Reputation: 3
I have a psuedo terminal running on linux C, opened as shown:
else
{
struct termios slave_orig_term_settings; // Saved terminal settings
struct termios new_term_settings; // Current terminal settings
// CHILD
close(fdm);
rc = tcgetattr(fds, &slave_orig_term_settings);
new_term_settings = slave_orig_term_settings;
new_term_settings.c_cc[VEOF] = '|';
new_term_settings.c_oflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG | ICRNL);
cfmakeraw (&new_term_settings);
tcsetattr (fds, TCSANOW, &new_term_settings);
}
When reading from the pipe, I can make a non blocking read() which will return after, for example, 5 seconds. The problem is that if I execute a command like "ls", which returns in several ms, it will wait the full 5 seconds before returning.
I understand using a physical GUI terminal, and not a psuedo terminal like this, the user can press CTRL^D and have EOF sent at the end of each output.
I want this effect, so my program can say "OK, I have received this certain byte, which means the terminal is done outputting, and I can now return this output back to the caller, and I know there is no more output to read".
I understand this is done with termios() function (or it's wrapper stty), but I can't get it working. I want the terminal to send me the '|' char instead of ctrl^d (\x04) upon completion of output, but it isn't working.
For clarity, upon completion of output (via read()), I want to receive the '|' byte. So if I send 'pwd' command, I get this output:
$ pwd
/home/user/dir
$|
Could someone please tell me how to edit this code to acheive that effect?
Thanks for your help.
EDIT - select() code
while ( (bytes = select(pipe + 1, &fd_in, NULL, NULL, &tv)) )
{
if (FD_ISSET(pipe, &fd_in))
{
read (pipe...)
The behaviour of the above code is as I've described, to wait for the full value of tv, even if there is nothing on the pipe, before returning.
Upvotes: 0
Views: 634
Reputation: 20797
The value of c_cc[VEOF]
will never be sent to you. For example, the default value of c_cc[VEOF]
is CTRL-D
but you'll not see the CTRL-D
on the end of file when the user presses CTRL-D
. Instead you are notified (e.g. by read()
returning 0
) that you're reaching the end of the file.
Usually when the child is done with its work it'll explicitly close()
the pty slave side so the pty master side will get EOF
.
Regarding
I can make a non blocking read() which will return after, for example, 5 seconds. The problem is that if I execute a command like "ls", which returns in several ms, it will wait the full 5 seconds before returning.
Not sure how you write the code but you can use select()
or poll()
which can notify you immediately when there's data available for reading.
According to select()
's man page:
select()
andpselect()
allow a program to monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" for some class of I/O operation (e.g., input possible). A file descriptor is considered ready if it is possible to perform a corresponding I/O operation (e.g.,read(2)
without blocking, or a sufficiently smallwrite(2)
).
Upvotes: 1