Unix Programming - Piping a terminal file descriptor

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > February 2004 > Piping a terminal file descriptor





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Piping a terminal file descriptor
Ar Fai Ve

2004-02-28, 9:33 pm


Is there a mechanism similar to pipe() which can transparently
pipe terminal file descriptors? Since any file descriptors
established by pipe() are stream file descriptors, they will
not support term-relevant ioctl commands such as TCGETA. I
would like to create a pipe in which I can catch termios
commands such as tcgetattr() and pass them to the other end
of the pipe where the controlling terminal is connected.

Basically I am interested in a pipe mechanism which allows
me to filter the data going to the output end of the
terminal, while still allowing for control commands to
pass transparently. Shown below is a small code which
illustrates the problem. It's easy to filter the data,
but I have no idea how to catch certain control commands
and pass them along the pipe. For instance, if the child
process were to exec() to ``top'' instead of simply dumping
a string, then top would assume that the new STDOUT (now
one end of a pipe) is a not a terminal because its
checks for terminal smartness (via requests through
tcgetattr or ioctl) would fail.

Thanks.

% g++ main.C
% ./a.out
tcgettattr() on real STDOUT returns 0
tcgettattr() on pipe returns -1
THIS WAS LOWERCASE

//////// main.C ////////
#include <sys/types.h>
#include <unistd.h>
#include <termios.h>
#include <iostream.h>

int main()
{
int outPipe[2];
pipe(outPipe);

pid_t child = fork();

if (child != 0) {
struct termios settings;
cerr << "tcgettattr() on real STDOUT returns "
<< tcgetattr(STDOUT_FILENO, &settings) << endl;

close(STDIN_FILENO);
close(outPipe[1]);

//
// Trivial filter which converts data arriving through pipe
// from lower case to upper
//
while (1) {
static char buf[1024];
int inCount = read(outPipe[0], buf, 1024);

if (inCount < 0)
break;
else if (inCount > 0) {
for (int i=0; i<inCount; i++) {
if (buf[i] >= 'a' && buf[i] <= 'z')
buf[i] -= 32;
}
write(STDOUT_FILENO, buf, inCount);
break;
}
}
}
else {
sleep(1);

//
// Replace stdout with one end of the pipe
//
dup2(outPipe[1], STDOUT_FILENO);
close(outPipe[0]);
close(outPipe[1]);

char *msg = "this was lowercase\n";
write(STDOUT_FILENO, msg, strlen(msg));

//
// Even though the data are connected through the pipe in the
// parent process, terminal related control commands cannot
// be handled and return an error value.
//
struct termios settings;
cerr << "tcgettattr() on pipe returns "
<< tcgetattr(outPipe[1], &settings) << endl;
}

return 0;
}
those who know me have no need of my name

2004-02-28, 11:33 pm

in comp.unix.programmer i read:

>Is there a mechanism similar to pipe() which can transparently
>pipe terminal file descriptors?


you need a pty. libexcept provides a nice api.

--
a signature
Ar Fai Ve

2004-02-29, 1:33 am

<not-a-real-address@usa.net> wrote:
> you need a pty. libexcept provides a nice api.


Thanks. I will look into that. But won't the pty
absorb the control calls itself?
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com