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.