ftp.nice.ch/pub/next/unix/developer/pcn.2.0.s.tar.gz#/src/pipe/pipe.c

This is pipe.c in view mode; [Download] [Up]

/*
 * PCN System
 * Author:      Steve Tuecke
 *              Argonne National Laboratory
 *
 * Please see the DISCLAIMER file in the top level directory of the
 * distribution regarding the provisions under which this software
 * is distributed.
 *
 * pipe.c
 *
 * C code to setup and run a pipe.
 */

/*
 * Pipe input for PCN compiler to implement compilation directives --
 * CAL  Jan. 91
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/file.h>
#include <sys/wait.h>
#include <errno.h>

#ifdef PCN_SYSV
#include <sys/fcntl.h>
#endif

#include "pcn_pipe.h"
#include "pcn_types.h"

static char sh_path[] = "/bin/sh";
static char sh_arg1[] = "-c";
static char *exec_args[4] = {sh_path, sh_arg1, (char *) NULL, (char *) NULL};

#define PIPE_READ  0
#define PIPE_WRITE 1

/*
#define DEBUG 1
*/


/*
 * _p_pipe_setup_pipe()
 *
 * Use '/bin/sh -c command' to fork off a child with optional
 * stdin, stdout, and stderr.  /bin/sh is used in order to get
 * reasonable argument handling.  (For example, of quoted strings,
 * wildcards, etc.)
 */
_p_pipe_setup_pipe(command, stdin_action, fp_in, stdout_action, fp_out,
		   stderr_action, fp_err, pid)
char *command;
int_t *stdin_action;
FILE **fp_in;
int_t *stdout_action;
FILE **fp_out;
int_t *stderr_action;
FILE **fp_err;
int_t *pid;
{
    int pipe_in[2];  /* 0=reading, 1=writing */
    int pipe_out[2];
    int pipe_err[2];
    int dev_null_fd = -1;
    int status;
    
    exec_args[2] = command;

    /* Setup stdin */
    if (*stdin_action == STDIN_CREATE && pipe( pipe_out ) )
    {
	perror("stdio_pipe");
	*pid = -1;
	return;
    }
    
    /* Setup stdout */
    if (*stdout_action == STDOUT_CREATE && pipe( pipe_out ) )
    {
	perror("stdio_pipe");
	*pid = -1;
	return;
    }
    
    /* Setup stderr */
    if (*stderr_action == STDERR_CREATE && pipe( pipe_err ) )
    {
	perror("stdio_pipe");
	*pid = -1;
	return;
    }

    /* Fork */
    *pid = (int_t) fork();
    if  ( *pid < 0 )		/* error */
    {
	perror("stdio_pipe");
	return;
    }
    
    if  ( *pid > 0 )		/* parent */
    {
	if (*stdin_action == STDIN_CREATE)
	{
	    close( pipe_in[PIPE_READ] );
	    *fp_in = (FILE *) fdopen( pipe_in[PIPE_WRITE], "w" );
	}
	if (*stdout_action == STDOUT_CREATE)
	{
	    close( pipe_out[PIPE_WRITE] );
	    *fp_out = (FILE *) fdopen( pipe_out[PIPE_READ], "r" );
	}
	if (*stderr_action == STDERR_CREATE)
	{
	    close( pipe_err[PIPE_WRITE] );
	    *fp_err = (FILE *) fdopen( pipe_err[PIPE_READ], "r" );
	}
	return;
    }
    else			/* child  */
    {
#if DEBUG > 0
	char **argp;
	fprintf(stderr,"Child execing: ");
	argp = exec_args;
	while ( *argp != NULL ) fprintf(stderr," %s", *argp++);
	fprintf(stderr,"\n"); fflush(stderr);
#endif
	if (   *stdin_action == STDIN_FROM_DEV_NULL
	    || *stdout_action == STDOUT_TO_DEV_NULL
	    || *stderr_action == STDERR_TO_DEV_NULL)
	{
	    dev_null_fd = open("/dev/null", O_RDWR, 0);
	}
	else
	{
	    dev_null_fd = -1;
	}
	
	/* Setup stdin */
	if (*stdin_action == STDIN_FROM_DEV_NULL)
	{
	    status = dup2( dev_null_fd, 0 );
	}
	else if (*stdin_action == STDIN_CREATE)
	{
	    close( pipe_in[PIPE_WRITE] );
	    status = dup2( pipe_in[PIPE_READ], 0 );
	    close( pipe_in[PIPE_READ] );
	}
	else if(*stdin_action == STDIN_USE_ARGUMENT)
	{
	    /* Feeding the fp argument to stdin */
	    status = dup2( fileno(*fp_in), 0 );
	    fclose(*fp_in);
	}

	/* Setup stdout */
	if (*stdout_action == STDOUT_TO_DEV_NULL)
	{
	    status = dup2( dev_null_fd, 1 );
	}
	else if (*stdout_action == STDOUT_CREATE)
	{
	    close( pipe_out[PIPE_READ] );
	    status = dup2( pipe_out[PIPE_WRITE], 1 );
	    close( pipe_out[PIPE_WRITE] );
	}
	else if (*stdout_action == STDOUT_USE_ARGUMENT)
	{
	    /* Feeding the fp argument to stdout */
	    status = dup2( fileno(*fp_out), 1 );
	    fclose(*fp_out);
	}

	/* Setup stderr */
	if (*stderr_action == STDERR_TO_DEV_NULL)
	{
	    status = dup2( dev_null_fd, 2 );
	}
	else if (*stderr_action == STDERR_CREATE)
	{
	    close( pipe_err[PIPE_READ] );
	    status = dup2( pipe_err[PIPE_WRITE], 2 );
	    close( pipe_err[PIPE_WRITE] );
	}
	else if (*stderr_action == STDERR_USE_ARGUMENT)
	{
	    /* Feeding the fp argument to stderr */
	    status = dup2( fileno(*fp_err), 2 );
	    fclose(*fp_err);
	}

	if (dev_null_fd >= 0)
	    close( dev_null_fd );
	
	status = execv( sh_path, exec_args );
	perror("stdio_pipe");
	exit(0);
    }
} /* _p_pipe_setup_pipe() */


#if defined(next040)
typedef union wait my_wait_t;
#else
typedef int my_wait_t;
#endif


/*
 * _p_pipe_wait()
 *
 * Wrapper around wait(), to wait for a child process to signal this process.
 * Fill in pid, exit_status, and signal with the appropriate values.
 * If block==1, then make it a blocking wait, otherwise make it a nonblocking
 * wait.
 */
_p_pipe_wait(pid, exit_status, signal, block)
int_t *pid, *exit_status, *signal, *block;
{
#if defined(next040) || defined(iris)
    union wait status;
#else
    int status;
#endif    
    int options;
    int status_int;
    int status_byte;

    if (*block)
	options = 0;
    else
	options = WNOHANG;

    *pid = (int_t) wait3(&status, options, (struct rusage *) 0);

    if (*pid <= 0)
    {
	*exit_status = -1;
	*signal = -1;
    }
    else
    {
	status_int = *((int *) &status);
	status_byte = status_int & 0xFF;
	if (status_byte == 0)
	{
	    /* child process exited due to exit call -- get the exit status */
	    *exit_status = (int_t) ((status_int & 0xFF00) >> 8);
	    *signal = -1;
	}
	else if (status_byte == 0177)
	{
	    /* child process has stopped */
	    *exit_status = -1;
	    *signal = -1;
	}
	else
	{
	    /* child process terminated due to a signal -- get the signal */
	    *exit_status = -1;
	    *signal = (int_t) (status_int & 0x7F);
	}
    }
} /* _p_pipe_wait() */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.