Unix questions - Trouble with UNIX pipes

This is Interesting: Free IT Magazines  
Home > Archive > Unix questions > March 2004 > Trouble with UNIX pipes





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 Trouble with UNIX pipes
Gergely Korodi

2004-03-30, 4:35 pm


Hi,

I'm trying to write a front-end for programs that read their standard
input and write the result to standard output. I'd do this by forking a
process and exec'ing the program; communication would be done by
anonymous pipes (my first try). Yet nothing seems to work, as if the
pipes would stall indefinitely (exact error seems to depend on what
program I actually call. Sometimes one cycle of reading-writing works,
but nothing more).

The following code should take messages one per line, and filter all
occurrences of the symbol 'e' by calling the "tr" utility. In this
case, nothing works--I can type in messages but there's no answer from
"tr". This happens under several different platforms, such as Linux and
Solaris.

If anyone could point out what's wrong and how to resolve it, please do.

Thanks,

Gergo

Code begins here:

#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>


char * getline (char * str, int size, int fd) {
int n, s = 0;
do {
n = read (fd, str + s++, 1);
} while (n && s < size && str [s - 1] != '\n');
return n ? str : NULL;
}

int putline (char * str, int size, int fd) {
int n, s = 0;
do {
n = write (fd, str + s++, 1);
} while (n && s < size && str [s - 1] != '\n');
return n;
}

char command [102400];
char result [102400];

int main(void) {

int forward[2], backward[2];

pipe(forward);
pipe(backward);

if (fork() == 0) {
dup2(forward[0], 0);
close(forward[0]);
close(forward[1]);
dup2(backward[1], 1);
close(backward[0]);
close(backward[1]);
execlp("tr", "tr", "-d", "e", 0);
}

close(forward[0]);
close(backward[1]);

while (getline (command, sizeof(command), 0)) {
putline (command, sizeof(command), forward [1]);
getline (result, sizeof(result), backward [0]);
putline (result, sizeof(result), 1);
}

wait(0);

return 0;
}

Barry Margolin

2004-03-31, 1:38 am

In article <c4cp97$n3d$1@news.cc.tut.fi>,
Gergely Korodi <gergely.korodi@tut.fi> wrote:

> Hi,
>
> I'm trying to write a front-end for programs that read their standard
> input and write the result to standard output. I'd do this by forking a
> process and exec'ing the program; communication would be done by
> anonymous pipes (my first try). Yet nothing seems to work, as if the
> pipes would stall indefinitely (exact error seems to depend on what
> program I actually call. Sometimes one cycle of reading-writing works,
> but nothing more).


The program you're running probably uses stdio, and by default stdout is
fully buffered. This means that it doesn't send anything to the pipe
until the stdio buffer is filled, and the buffer size is typically
something like 4K bytes.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Marc Rochkind

2004-03-31, 3:40 pm


"Gergely Korodi" <gergely.korodi@tut.fi> wrote in message
news:c4cp97$n3d$1@news.cc.tut.fi...
>
> Hi,
>
> I'm trying to write a front-end for programs that read their standard
> input and write the result to standard output. I'd do this by forking a
> process and exec'ing the program; communication would be done by
> anonymous pipes (my first try). Yet nothing seems to work, as if the
> pipes would stall indefinitely (exact error seems to depend on what
> program I actually call. Sometimes one cycle of reading-writing works,
> but nothing more).
>
> The following code should take messages one per line, and filter all
> occurrences of the symbol 'e' by calling the "tr" utility. In this
> case, nothing works--I can type in messages but there's no answer from
> "tr". This happens under several different platforms, such as Linux and
> Solaris.
>
> If anyone could point out what's wrong and how to resolve it, please do.
>
> Thanks,
>
> Gergo
>

[snip]

The other replies in this thread (the ones about buffering) explain the
problem very well.

The only entirely general solution to capturing output from a command and
feeding input to it is to use pseudo-terminals (ptys), but setting them up
is very complicated compared to using pipes.

Here's a link to an example which captures the output of any command (even,
say, vi) to record it so it can be played back:

http://basepath.com/aup/ex/record_8c.html


--
Marc Rochkind
"Advanced UNIX Programming" (publishing April 2004)
www.basepath.com/aup


Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com