pconnect -- create a pipeline to a given command
#include <afblib/pconnect.h>
enum {PIPE_READ = 0, PIPE_WRITE = 1};
typedef struct pipe_end { int fd; pid_t pid; int wstat; } pipe_end;
int pconnect(const char* path, char* const* argv, int mode, pipe_end* pipe_con); int pconnect2(const char* path, char* const* argv, int mode, int fd, pipe_end* pipe_con); int phangup(pipe_end* pipe_end);
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.
All functions return 1 on success and 0 otherwise.
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; int 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);
The close-on-exec flag is set for all pipe file descriptors
left for the invoking process. However, the file descriptors
are unfortunately not closed automatically if a forked-off
process does not exec()
to another image.
Andreas F. Borchert