Characters not making it from a master to a slave pseudo-terminal
0x04 is ^D, which is the end-of-file keypress. Has the pty been set in raw mode? Maybe the driver is eating it.
If you make it:
os.write(child_fd, b"'\x04hmm\x16\x04'\n")
you can see that indeed the driver is doing translation. \x16
is the same as ^V, which is how you quote things. It makes sense the translation would only be happening from the master (the pretend physical terminal) and the slave. The pretend physical terminal is where (on a normal terminal device) the person would be typing
I'm not sure how to get the driver to stop doing that. If the child sets its terminal to raw mode then that will likely do it.
Does terminal control function setting baud rate really effective for pseudo terminals?
The baud rate setting for a pseudo-terminal doesn't control anything, but advises the terminal driver (when it matters) how to synchronize with a physical device, as well as advising applications if they should send padding characters.
A pseudo-terminal might be connected to a physical device, but there's no way for an application to tell the difference. Physical devices are still used (perhaps not by you).
For example, xterm has an option, used for testing ncurses:
Patch #327 - 2016/10/07
add-baudrate
option, for testing ncurses.
but you would not find it useful.
Why is ruby's PTY library failing to capture input when the shell has subprocesses?
The tty input mode defaults to line input, so you won't see anything until you output
a newline.
I suggest using strace to debug this kind of behaviour. This way you can see the system call, and for example see if you are blocked on a read waiting for more input and so on.
When you do not use '< /dev/tty0', it does work, right ?
Basically, what you want is echoing of character. If you do the following :
shell = PTY.spawn 'env TERM=ansi COLUMNS=63 LINES=21 sh -i'
shell[1].puts("cat\nasdf")
s = shell[0].read(16)
puts s
And you strace the process using :
strace -ff -o test.log -e trace=read,write ./testr.rb
In the output you will see asdf twice.
But if you look at the strace code, you see that the cat subprocess only writes asdf once, and it's parent process, ie the shell, never writes asdf.
So why is there two 'asdf' output ? Because the tty layer is doing local echo. So that when you type something in shell it goes to the pty, and the pty driver :
- Write it to the slave side of the pseudo tty
- Echoes it to the master side.
So what happens when you do sh -i </dev/tty0
? The character coming from the keyboard are echoed to /dev/tty0, not to the output of the shell.
The shell is not doing any echo, the tty layer is, so what you want to do is the folowing (take it as pseudo code, I am not competent in ruby) :
# Emulate terminal behavior with pty
shell = PTY.spawn 'env TERM=ansi COLUMNS=63 LINES=21 sh -i'
keyboard = open(/dev/tty0)
input = keyboard.read()
shell[1].write(input)
puts shell[0].read(...)
Now, if you want something interactive, you will need to configure /dev/tty0 in raw mode, and use select to know when you can read without blocking, and when there is data available for output.
To configure tty in raw mode, you can try to use
stty -F /dev/tty0 -cooked
Is stdout line buffered, unbuffered or indeterminate by default?
The C99 standard does not specify if the three standard streams are unbuffered or line buffered: It is up to the implementation. All UNIX implementations I know have a line buffered stdin
. On Linux, stdout
in line buffered and stderr
unbuffered.
As far as I know, POSIX does not impose additional restrictions. POSIX's fflush page does note in the EXAMPLES section:
[...] The fflush() function is used because standard output is usually buffered and the prompt may not immediately be printed on the output or terminal.
So the remark that you add fflush(stdout);
is correct.
An alternative could be to make stdout
unbuffered:
setbuf(stdout, NULL);
/* or */
setvbuf(stdout, NULL, _IONBF, 0);
But as R. notes you can only do this once, and it must be before you write to stdout
or perform any other operantion on it. (C99 7.19.5.5 2)
I just read a recent thread on comp.lang.c
about the same thing. One of the remarks:
Unix convention is that
stdin
andstdout
are line-buffered when associated with a terminal, and fully-buffered (aka block-buffered) otherwise.stderr
is always unbuffered.
Serial driver in userspace
Yes, you can do this using a pty. The user mode driver opens the master end of the pty and the application that wants to use the serial port opens the slave end. Search for Linux pty.
Related Topics
Fatal: Bad Config File Line 1 in /Home/Trx/.Gitconfig
How to Find the Particular Text Stored in the File "Data.Txt" and It Occurs Only Once
How Do Programs Communicate with Each Other
Why Does This Movq Instruction Work on Linux and Not Osx
Linux /Bin/Sh Check If String Contains X
How to Install Visual Studio 2015 in Ubuntu
How to Find List of Odbc Drivers Installed on Linux
Dlopen Failed: Cannot Open Shared Object File: No Such File or Directory
Converting a Pcap Trace to Netflow Format
How to Break an Arbitrary Tcp/Ip Connection on Linux
Addresses of Thread Local Storage Variables
How to Redirect the Telnet Console Logs to a File Linux
Bash: No Such File or Directory
How to Tell If Running in a Linux Console Versus an Ssh Session
Looping Through Lines in a File in Bash, Without Using Stdin
How to Display the Output of a Linux Command on Stdout and Also Pipe It to Another Command
Combine Results of Column One Then Sum Column 2 to List Total for Each Entry in Column One