218 lines
9.0 KiB
HTML
218 lines
9.0 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
|
|
<!--Converted with LaTeX2HTML 96.1-c (Feb 29, 1996) by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds -->
|
|
<HTML>
|
|
<HEAD>
|
|
<TITLE>6.2.3 Pipes the Easy Way!</TITLE>
|
|
<META NAME="description" CONTENT="6.2.3 Pipes the Easy Way!">
|
|
<META NAME="keywords" CONTENT="lpg">
|
|
<META NAME="resource-type" CONTENT="document">
|
|
<META NAME="distribution" CONTENT="global">
|
|
<LINK REL=STYLESHEET HREF="lpg.css">
|
|
</HEAD>
|
|
<BODY LANG="EN">
|
|
<A NAME="tex2html479" HREF="node13.html"><IMG WIDTH=37 HEIGHT=24 ALIGN=BOTTOM ALT="next" SRC="next_motif.gif"></A> <A NAME="tex2html477" HREF="node9.html"><IMG WIDTH=26 HEIGHT=24 ALIGN=BOTTOM ALT="up" SRC="up_motif.gif"></A> <A NAME="tex2html471" HREF="node11.html"><IMG WIDTH=63 HEIGHT=24 ALIGN=BOTTOM ALT="previous" SRC="previous_motif.gif"></A> <A NAME="tex2html481" HREF="node1.html"><IMG WIDTH=65 HEIGHT=24 ALIGN=BOTTOM ALT="contents" SRC="contents_motif.gif"></A> <BR>
|
|
<B> Next:</B> <A NAME="tex2html480" HREF="node13.html">6.2.4 Atomic Operations with </A>
|
|
<B>Up:</B> <A NAME="tex2html478" HREF="node9.html">6.2 Half-duplex UNIX Pipes</A>
|
|
<B> Previous:</B> <A NAME="tex2html472" HREF="node11.html">6.2.2 Creating Pipes in </A>
|
|
<BR> <P>
|
|
<H2><A NAME="SECTION00723000000000000000">6.2.3 Pipes the Easy Way!</A></H2>
|
|
<P>
|
|
If all of the above ramblings seem like a very round-about way of creating
|
|
and utilizing pipes, there is an alternative.
|
|
<P>
|
|
<P>
|
|
<HR><PRE> LIBRARY FUNCTION: popen();
|
|
|
|
PROTOTYPE: FILE *popen ( char *command, char *type);
|
|
RETURNS: new file stream on success
|
|
NULL on unsuccessful fork() or pipe() call
|
|
|
|
NOTES: creates a pipe, and performs fork/exec operations using "command"</PRE>
|
|
<HR>This standard library function creates a half-duplex pipeline by calling
|
|
pipe() internally. It then forks a child process, execs the Bourne shell,
|
|
and executes the "command" argument within the shell. Direction of data
|
|
flow is determined by the second argument, "type". It can be "r" or "w", for
|
|
"read" or "write". It cannot be both! Under Linux, the pipe will be opened
|
|
up in the mode specified by the first character of the "type" argument. So,
|
|
if you try to pass "rw", it will only open it up in "read" mode.
|
|
<P>
|
|
While this library function performs quite a bit of the dirty work for you,
|
|
there is a substantial tradeoff. You lose the fine control you once had
|
|
by using the pipe() system call, and handling the fork/exec yourself. However,
|
|
since the Bourne shell is used directly, shell metacharacter expansion
|
|
(including wildcards) is permissible within the "command" argument.
|
|
<P>
|
|
Pipes which are created with popen() must be closed with pclose(). By now,
|
|
you have probably realized that popen/pclose share a striking resemblance
|
|
to the standard file stream I/O functions fopen() and fclose().
|
|
<P>
|
|
<P>
|
|
<HR><PRE> LIBRARY FUNCTION: pclose();
|
|
|
|
PROTOTYPE: int pclose( FILE *stream );
|
|
RETURNS: exit status of wait4() call
|
|
-1 if "stream" is not valid, or if wait4() fails
|
|
|
|
NOTES: waits on the pipe process to terminate, then closes the stream.</PRE>
|
|
<HR>The pclose() function performs a wait4() on the process forked by popen().
|
|
When it returns, it destroys the pipe and the file stream. Once again, it is
|
|
synonymous with the fclose() function for normal stream-based file I/O.
|
|
<P>
|
|
Consider this example, which opens up a pipe to the sort command, and proceeds
|
|
to sort an array of strings:
|
|
<P>
|
|
<PRE>/*****************************************************************************
|
|
Excerpt from "Linux Programmer's Guide - Chapter 6"
|
|
(C)opyright 1994-1995, Scott Burkett
|
|
*****************************************************************************
|
|
MODULE: popen1.c
|
|
*****************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
|
|
#define MAXSTRS 5
|
|
|
|
int main(void)
|
|
{
|
|
int cntr;
|
|
FILE *pipe_fp;
|
|
char *strings[MAXSTRS] = { "echo", "bravo", "alpha",
|
|
"charlie", "delta"};
|
|
|
|
/* Create one way pipe line with call to popen() */
|
|
if (( pipe_fp = popen("sort", "w")) == NULL)
|
|
{
|
|
perror("popen");
|
|
exit(1);
|
|
}
|
|
|
|
/* Processing loop */
|
|
for(cntr=0; cntr<MAXSTRS; cntr++) {
|
|
fputs(strings[cntr], pipe_fp);
|
|
fputc('\n', pipe_fp);
|
|
}
|
|
|
|
/* Close the pipe */
|
|
pclose(pipe_fp);
|
|
|
|
return(0);
|
|
}</PRE>
|
|
<P>
|
|
Since <TT>popen()</TT> uses the shell to do its bidding, all shell expansion
|
|
characters and metacharacters are available for use! In addition, more
|
|
advanced techniques such as redirection, and even output piping, can be utilized
|
|
with <TT>popen()</TT>. Consider the following sample calls:
|
|
<P>
|
|
<PRE> popen("ls ~scottb", "r");
|
|
popen("sort > /tmp/foo", "w");
|
|
popen("sort | uniq | more", "w");</PRE>
|
|
<P>
|
|
As another example of popen(), consider this small program, which opens
|
|
up two pipes (one to the ls command, the other to sort):
|
|
<P>
|
|
<PRE>/*****************************************************************************
|
|
Excerpt from "Linux Programmer's Guide - Chapter 6"
|
|
(C)opyright 1994-1995, Scott Burkett
|
|
*****************************************************************************
|
|
MODULE: popen2.c
|
|
*****************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
|
|
int main(void)
|
|
{
|
|
FILE *pipein_fp, *pipeout_fp;
|
|
char readbuf[80];
|
|
|
|
/* Create one way pipe line with call to popen() */
|
|
if (( pipein_fp = popen("ls", "r")) == NULL)
|
|
{
|
|
perror("popen");
|
|
exit(1);
|
|
}
|
|
|
|
/* Create one way pipe line with call to popen() */
|
|
if (( pipeout_fp = popen("sort", "w")) == NULL)
|
|
{
|
|
perror("popen");
|
|
exit(1);
|
|
}
|
|
|
|
/* Processing loop */
|
|
while(fgets(readbuf, 80, pipein_fp))
|
|
fputs(readbuf, pipeout_fp);
|
|
|
|
/* Close the pipes */
|
|
pclose(pipein_fp);
|
|
pclose(pipeout_fp);
|
|
|
|
return(0);
|
|
}</PRE>
|
|
<P>
|
|
For our final demonstration of popen(), let's create a generic program that
|
|
opens up a pipeline between a passed command and filename:
|
|
<P>
|
|
<PRE>/*****************************************************************************
|
|
Excerpt from "Linux Programmer's Guide - Chapter 6"
|
|
(C)opyright 1994-1995, Scott Burkett
|
|
*****************************************************************************
|
|
MODULE: popen3.c
|
|
*****************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
FILE *pipe_fp, *infile;
|
|
char readbuf[80];
|
|
|
|
if( argc != 3) {
|
|
fprintf(stderr, "USAGE: popen3 [command] [filename]\n");
|
|
exit(1);
|
|
}
|
|
|
|
/* Open up input file */
|
|
if (( infile = fopen(argv[2], "rt")) == NULL)
|
|
{
|
|
perror("fopen");
|
|
exit(1);
|
|
}
|
|
|
|
/* Create one way pipe line with call to popen() */
|
|
if (( pipe_fp = popen(argv[1], "w")) == NULL)
|
|
{
|
|
perror("popen");
|
|
exit(1);
|
|
}
|
|
|
|
/* Processing loop */
|
|
do {
|
|
fgets(readbuf, 80, infile);
|
|
if(feof(infile)) break;
|
|
|
|
fputs(readbuf, pipe_fp);
|
|
} while(!feof(infile));
|
|
|
|
fclose(infile);
|
|
pclose(pipe_fp);
|
|
|
|
return(0);
|
|
}</PRE>
|
|
<P>
|
|
Try this program out, with the following invocations:
|
|
<PRE> popen3 sort popen3.c
|
|
popen3 cat popen3.c
|
|
popen3 more popen3.c
|
|
popen3 cat popen3.c | grep main</PRE>
|
|
<P>
|
|
<HR><A NAME="tex2html479" HREF="node13.html"><IMG WIDTH=37 HEIGHT=24 ALIGN=BOTTOM ALT="next" SRC="next_motif.gif"></A> <A NAME="tex2html477" HREF="node9.html"><IMG WIDTH=26 HEIGHT=24 ALIGN=BOTTOM ALT="up" SRC="up_motif.gif"></A> <A NAME="tex2html471" HREF="node11.html"><IMG WIDTH=63 HEIGHT=24 ALIGN=BOTTOM ALT="previous" SRC="previous_motif.gif"></A> <A NAME="tex2html481" HREF="node1.html"><IMG WIDTH=65 HEIGHT=24 ALIGN=BOTTOM ALT="contents" SRC="contents_motif.gif"></A> <BR>
|
|
<B> Next:</B> <A NAME="tex2html480" HREF="node13.html">6.2.4 Atomic Operations with </A>
|
|
<B>Up:</B> <A NAME="tex2html478" HREF="node9.html">6.2 Half-duplex UNIX Pipes</A>
|
|
<B> Previous:</B> <A NAME="tex2html472" HREF="node11.html">6.2.2 Creating Pipes in </A>
|
|
<P><ADDRESS>
|
|
<I>Converted on: <BR>
|
|
Fri Mar 29 14:43:04 EST 1996</I>
|
|
</ADDRESS>
|
|
</BODY>
|
|
</HTML>
|