An example of using pipe and fork in C

This is an example C program which illustrates use of the pipe and vfork system calls to run an external command.

#include <stdio.h>
#include <errno.h>
/* For strerrno. */
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
/* For "pipe". */
#include <unistd.h>
/* For "exit". */
#include <stdlib.h>

/* Close a file descriptor, and exit if there was an error. */

static void
close_or_die (int fd)
{
    int status;
    status = close (fd);
    if (status != 0) {
	fprintf (stderr, "close %d failed: %s\n", fd, strerror (errno));
	exit (EXIT_FAILURE);
    }
}

/* Run the command and print it to the pipe's write descriptor
   "outfd". */

static void
run_command (int outfd)
{
    int status;
    char * command;
    char * argv[4] = {
	"sh",
	"-c",
	0,
	0,
    };
    if (outfd != STDOUT_FILENO) {
	status = dup2 (outfd, STDOUT_FILENO);
	if (status == -1) {
	    fprintf (stderr, "dup2 %d failed: %s\n", outfd, strerror (errno));
	    exit (EXIT_FAILURE);
	}
    }
    close_or_die (outfd);
    command = "ls -l";
    argv[2] = command;
    execve ("/bin/sh", argv, 0);
    fprintf (stderr, "execve %s returned.\n", command);
    exit (EXIT_FAILURE);
}

#define SIZE 0x100

static void
read_print_pipe (FILE * p)
{
    char buf[SIZE];
    while (! feof (p)) {
	int bytes;
	bytes = fread (buf, sizeof (char), SIZE, p);
	printf ("%.*s", bytes, buf);
    }
}

int main ()
{
    pid_t pid;
    int status;
    int pfd[2];
    FILE * p;
    status = pipe (pfd);
    if (status != 0) {
	fprintf (stderr, "Error with pipe: %s\n", strerror (errno));
	exit (EXIT_FAILURE);
    }
    pid = vfork ();
    if (pid < 0) {
	fprintf (stderr, "Error with fork: %s\n", strerror (errno));
	exit (EXIT_FAILURE);
    }
    if (pid == 0) {
	close_or_die (pfd[0]);
	run_command (pfd[1]);
	exit (EXIT_SUCCESS);
    }
    close_or_die (pfd[1]);
    p = fdopen (pfd[0], "r");
    read_print_pipe (p);
    fclose (p);
    wait4 (pid, & status, 0, 0);
    if (status != 0) {
	fprintf (stderr, "Bad status %d from child.\n", status);
	exit (EXIT_FAILURE);
    }
    return 0;
}

(download)

The output of the example looks like this:

total 88
-rw-r--r--  1 ben  ben    500 Dec 18 12:58 index.html
-rw-r--r--  1 ben  ben    332 Dec 18 13:08 links-table
-rw-r--r--  1 ben  ben    134 Dec 18 12:55 makefile
-rwxr-xr-x  1 ben  ben  11612 Dec 18 13:08 pfc
-rw-r--r--  1 ben  ben   1948 Dec 18 12:54 pfc.c
-rw-r--r--  1 ben  ben      0 Dec 18 13:08 pfc.txt
-rw-r--r--  1 ben  ben   8912 Dec 18 13:08 pfc_c.html
-rw-r--r--  1 ben  ben     55 Dec 18 11:42 tags

Acknowledgements

I wrote the above example looking at the code of W. Richard Stevens' book "Advanced Programming in the Unix Environment" and then modified it by comparing it to the FreeBSD popen source code.

Web links


Copyright © Ben Bullock 2009-2017. All rights reserved. For comments, questions, and corrections, please email Ben Bullock (benkasminbullock@gmail.com) or use the discussion group at Google Groups. / Privacy / Disclaimer