NAME

pconnect -- create a pipeline to a given command

SYNOPSIS

   #include <afblib/pconnect.h>

   enum {PIPE_READ = 0, PIPE_WRITE = 1};

   typedef struct pipe_end {
      int fd;
      pid_t pid;
      int wstat;
   } pipe_end;

   bool pconnect(const char* path, char* const* argv,
         int mode, pipe_end* pipe_con);
   bool pconnect2(const char* path, char* const* argv,
         int mode, int fd, pipe_end* pipe_con);
   bool phangup(pipe_end* pipe_con);
   bool pshare(pipe_end* pipe_con);
   bool pcut(pipe_end* pipe_con);
   bool pwait(pipe_end* pipe_con);

DESCRIPTION

pconnect provides a safe alternative to popen by avoiding the invocation of a shell to interpret a command line. Instead of a command string, a path for the command and an argument list is passed to pconnect that are passed directly to execvp(2) in the forked-off process. The mode which has to be either PIPE_READ or PIPE_WRITE selects the end of the pipe that is left to the invoking process. Pipelines created by pconnect are to be closed by phangup which waits for the forked-off process to terminate and returns its status in the wstat field.

pconnect2 works similar to pconnect but connects in the spawned off process fd to the remaining standard input or output file descriptor not connected to the pipeline. This allows pipelines to be chained. However, fd needs to be shared using pshare (see below) if this file descriptor belong to another pipe end returned by pconnect or pconnect2.

All pipe ends returned by pconnect and pconnect2 are protected against being inherited through fork or exec. This protection can be lifted using pshare. This is necessary if a pipe end is to be passed on to a child. In case of a shared pipe end pcut and pwait can be used instead of phangup. pcut closes the file descriptor associated with the pipe end while pwait waits for the associated process to terminate. This separation allows pcut to be invoked immediately after the fork on the parent side.

DIAGNOSTICS

All functions return true on success and false otherwise.

EXAMPLE

The following example retrieves the output of ``ps -fu login'' where login is some given login name:

   char ps_path[] = "/usr/bin/ps";
   strlist argv = {0};
   strlist_push(&argv, ps_path);
   strlist_push(&argv, "-fu");
   strlist_push(&argv, login);
   strlist_push0(&argv);
   pipe_end pipe;
   bool ok = pconnect(ps_path, argv.list, PIPE_READ, &pipe);
   strlist_free(&argv);
   if (!ok) return 0;

   stralloc ps_output = {0};
   ssize_t nbytes;
   char buf[512];
   while ((nbytes = read(pipe.fd, buf, sizeof buf)) > 0) {
      stralloc_catb(&ps_output, buf, nbytes);
   }
   phangup(&pipe);

AUTHOR

Andreas F. Borchert