[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [MiNT] STDIN and STDOUT are on a boat...
On Mon, Mar 13, 2000 at 06:26:36PM +0100, Remi Villatel wrote:
> ...And the boat is sinking with me on board. ;-) Any way...
>
> Hello everybody,
>
> Could someone explain to me (and to everyone interested around here) the
> mysteries of STDIN and STDOUT?
>
> What I'd like to know is how a program could catch the STDOUT output of another
> program... and how a program can satisfy the STDIN needs of another program.
>
> The project behind the questions is to do something like...
>
> $ program1 | my_program | program2
>
> ...as it could be done with 'bash' or any shell. So 'my_program' catches the
> STDOUT output of 'program1', does some computations and send the results to
> 'program2' as STDIN for further computations.
That's usually called IPC (interprocess communication).
Solution #1:
FILE* mypipe = popen ("otherprg.tos", "w");
fprintf (mypipe, "This is your stdin, otherprg.tos\n");
pclose (mypipe);
The above example would search for "otherprg.tos" in $PATH, start it and
connect stdin of that prg with the stream MYPIPE. The program's stdout is
the same as yours. You can also use popen with a mode argument of "r", in
that case the stream would be read-only instead of write-only and you
could read the program's stdout from MYPIPE. Since pipes are
uni-directional you cannot connect to the program's stdin and stdout at
once. Unless ...
Solution #2:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <stdlib.h>
char buf[] = "Message to cat.";
char buf2[sizeof buf];
int
main (int argc, char* argv[])
{
int mypipes[2];
pid_t childpid;
int status;
/* Create a pipe, the reading end is in mypipes[0], the
writing end in mypipes[1]. */
if (pipe (mypipes) != 0) {
perror ("pipe");
return 1;
}
childpid = fork ();
if (childpid == 0) {
/* This is the child process. Close standard streams
and connect them to the pipe but in reverse order.
In other words: The pipe's reading end is the child's
stdout/stderr; the pipe's writing end is the child's
stdin. */
char* childargv[] = { "cat", NULL };
dup2 (mypipes[1], 0);
dup2 (mypipes[0], 1);
dup2 (mypipes[0], 2);
execvp ("cat", childargv);
/* If execvp returns, there is an error. */
perror ("can't execvp cat");
exit (EXIT_FAILURE);
} else if (childpid < 0) {
perror ("fork");
return EXIT_FAILURE;;
}
/* Since childpid is >= zero, that means parent side. Say something
to the child and get an answer. */
write (mypipes[1], buf, sizeof buf - 1);
buf2[sizeof buf2 - 1] = '\0';
read (mypipes[0], buf2, sizeof buf2 - 1);
if (strcmp (buf, buf2)) {
fflush (stdout);
fprintf (stderr,
"Transmission error. Expected `%s', got `%s'\n",
buf, buf2);
fflush (stderr);
status = EXIT_FAILURE;
} else
printf ("child sent: `%s'\n", buf2);
/* Wait for child to terminate. */
if (close (mypipes[1]) != 0) {
perror ("close error");
return EXIT_FAILURE;
}
/* Wait for child to terminate. */
{
int childstatus;
int pid = waitpid (childpid, &childstatus, 0);
if (childpid != pid) {
perror ("waitpid");
return EXIT_FAILURE;
}
if (WIFEXITED (childstatus)) {
printf ("child terminated with exit code %d\n",
WEXITSTATUS (childstatus));
} else if (WIFSIGNALED (childstatus)) {
printf ("child got killed by signal %d\n",
WTERMSIG (childstatus));
} else {
fflush (stdout);
fprintf (stderr, "Ooops\n");
return EXIT_FAILURE;
}
}
(void) close (mypipes[0]);
return status;
}
That's it basically. Hope it compiles and runs.
If this is not enough try to get the manpages popen(2), pipe(2),
waitpid(2) from a Unix system.
Ciao
Guido
--
http://stud.uni-sb.de/~gufl0000/
mailto:guido@freemint.de