|
Packit |
eba2e2 |
.\" Copyright (C) 2010-2017 Colin Watson.
|
|
Packit |
eba2e2 |
.\"
|
|
Packit |
eba2e2 |
.\" This file is part of libpipeline.
|
|
Packit |
eba2e2 |
.\"
|
|
Packit |
eba2e2 |
.\" libpipeline is free software; you can redistribute it and/or modify
|
|
Packit |
eba2e2 |
.\" it under the terms of the GNU General Public License as published by
|
|
Packit |
eba2e2 |
.\" the Free Software Foundation; either version 3 of the License, or (at
|
|
Packit |
eba2e2 |
.\" your option) any later version.
|
|
Packit |
eba2e2 |
.\"
|
|
Packit |
eba2e2 |
.\" libpipeline is distributed in the hope that it will be useful, but
|
|
Packit |
eba2e2 |
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
eba2e2 |
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
eba2e2 |
.\" General Public License for more details.
|
|
Packit |
eba2e2 |
.\"
|
|
Packit |
eba2e2 |
.\" You should have received a copy of the GNU General Public License
|
|
Packit |
eba2e2 |
.\" along with libpipeline; if not, write to the Free Software
|
|
Packit |
eba2e2 |
.\" Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
|
Packit |
eba2e2 |
.\" USA.
|
|
Packit |
eba2e2 |
.Dd October 11, 2010
|
|
Packit |
eba2e2 |
.Os GNU
|
|
Packit |
eba2e2 |
.ds volume-operating-system GNU
|
|
Packit |
eba2e2 |
.Dt LIBPIPELINE 3
|
|
Packit |
eba2e2 |
.Sh NAME
|
|
Packit |
eba2e2 |
.Nm libpipeline
|
|
Packit |
eba2e2 |
.Nd pipeline manipulation library
|
|
Packit |
eba2e2 |
.Sh SYNOPSIS
|
|
Packit |
eba2e2 |
.In pipeline.h
|
|
Packit |
eba2e2 |
.Sh DESCRIPTION
|
|
Packit |
eba2e2 |
.Nm
|
|
Packit |
eba2e2 |
is a C library for setting up and running pipelines of processes, without
|
|
Packit |
eba2e2 |
needing to involve shell command-line parsing which is often error-prone and
|
|
Packit |
eba2e2 |
insecure.
|
|
Packit |
eba2e2 |
This relieves programmers of the need to laboriously construct pipelines
|
|
Packit |
eba2e2 |
using lower-level primitives such as
|
|
Packit |
eba2e2 |
.Ic fork
|
|
Packit |
eba2e2 |
and
|
|
Packit |
eba2e2 |
.Ic execve .
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
The general way to use
|
|
Packit |
eba2e2 |
.Nm
|
|
Packit |
eba2e2 |
involves constructing a
|
|
Packit |
eba2e2 |
.Vt pipeline
|
|
Packit |
eba2e2 |
structure and adding one or more
|
|
Packit |
eba2e2 |
.Vt pipecmd
|
|
Packit |
eba2e2 |
structures to it.
|
|
Packit |
eba2e2 |
A
|
|
Packit |
eba2e2 |
.Vt pipecmd
|
|
Packit |
eba2e2 |
represents a subprocess (or
|
|
Packit |
eba2e2 |
.Dq command ) ,
|
|
Packit |
eba2e2 |
while a
|
|
Packit |
eba2e2 |
.Vt pipeline
|
|
Packit |
eba2e2 |
represents a sequence of subprocesses each of whose outputs is connected to
|
|
Packit |
eba2e2 |
the next one's input, as in the example
|
|
Packit |
eba2e2 |
.Ic ls | grep pattern | less .
|
|
Packit |
eba2e2 |
The calling program may adjust certain properties of each command
|
|
Packit |
eba2e2 |
independently, such as its environment and
|
|
Packit |
eba2e2 |
.Xr nice 3
|
|
Packit |
eba2e2 |
priority, as well as properties of the entire pipeline such as its input and
|
|
Packit |
eba2e2 |
output and the way signals are handled while executing it.
|
|
Packit |
eba2e2 |
The calling program may then start the pipeline, read output from it, wait
|
|
Packit |
eba2e2 |
for it to complete, and gather its exit status.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Strings passed as
|
|
Packit |
eba2e2 |
.Vt const char *
|
|
Packit |
eba2e2 |
function arguments will be copied by the library.
|
|
Packit |
eba2e2 |
.Ss Functions to build individual commands
|
|
Packit |
eba2e2 |
.Bl -tag -width 4n -compact
|
|
Packit |
eba2e2 |
.It Ft "pipecmd *" Ns Fn pipecmd_new "const char *name"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Construct a new command representing execution of a program called
|
|
Packit |
eba2e2 |
.Va name .
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft "pipecmd *" Ns Fn pipecmd_new_argv "const char *name" "va_list argv"
|
|
Packit |
eba2e2 |
.It Ft "pipecmd *" Ns Fn pipecmd_new_args "const char *name" ...
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Convenience constructors wrapping
|
|
Packit |
eba2e2 |
.Fn pipecmd_new
|
|
Packit |
eba2e2 |
and
|
|
Packit |
eba2e2 |
.Fn pipecmd_arg .
|
|
Packit |
eba2e2 |
Construct a new command representing execution of a program called
|
|
Packit |
eba2e2 |
.Va name
|
|
Packit |
eba2e2 |
with arguments.
|
|
Packit |
eba2e2 |
Terminate arguments with
|
|
Packit |
eba2e2 |
.Li NULL .
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft "pipecmd *" Ns Fn pipecmd_new_argstr "const char *argstr"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Split
|
|
Packit |
eba2e2 |
.Va argstr
|
|
Packit |
eba2e2 |
on whitespace to construct a command and arguments, honouring shell-style
|
|
Packit |
eba2e2 |
single-quoting, double-quoting, and backslashes, but not other shell
|
|
Packit |
eba2e2 |
evilness like wildcards, semicolons, or backquotes.
|
|
Packit |
eba2e2 |
This is included only to support situations where command arguments are
|
|
Packit |
eba2e2 |
encoded into configuration files and the like.
|
|
Packit |
eba2e2 |
While it is safer than
|
|
Packit |
eba2e2 |
.Xr system 3 ,
|
|
Packit |
eba2e2 |
it still involves significant string parsing which is inherently riskier
|
|
Packit |
eba2e2 |
than avoiding it altogether.
|
|
Packit |
eba2e2 |
Please try to avoid using it in new code.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Vt typedef void pipecmd_function_type (void *) ;
|
|
Packit |
eba2e2 |
.It Vt typedef void pipecmd_function_free_type (void *) ;
|
|
Packit |
eba2e2 |
.It Xo Ft "pipecmd *" Ns
|
|
Packit |
eba2e2 |
.Fo pipecmd_new_function
|
|
Packit |
eba2e2 |
.Fa "const char *name"
|
|
Packit |
eba2e2 |
.Fa "pipecmd_function_type *func"
|
|
Packit |
eba2e2 |
.Fa "pipecmd_function_free_type *free_func"
|
|
Packit |
eba2e2 |
.Fa "void *data"
|
|
Packit |
eba2e2 |
.Fc
|
|
Packit |
eba2e2 |
.Xc
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Construct a new command that calls a given function rather than executing a
|
|
Packit |
eba2e2 |
process.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
The data argument is passed as the function's only argument, and will be
|
|
Packit |
eba2e2 |
freed before returning using free_func (if
|
|
Packit |
eba2e2 |
.No non- Ns Va NULL Ns ).
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.Li pipecmd_*
|
|
Packit |
eba2e2 |
functions that deal with arguments cannot be used with the command returned
|
|
Packit |
eba2e2 |
by this function.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Xo Ft "pipecmd *" Ns
|
|
Packit |
eba2e2 |
.Fn pipecmd_new_sequencev "const char *name" "va_list cmdv"
|
|
Packit |
eba2e2 |
.Xc
|
|
Packit |
eba2e2 |
.It Ft "pipecmd *" Ns Fn pipecmd_new_sequence "const char *name" ...
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Construct a new command that itself runs a sequence of commands, supplied as
|
|
Packit |
eba2e2 |
.Vt "command *"
|
|
Packit |
eba2e2 |
arguments following
|
|
Packit |
eba2e2 |
.Va name
|
|
Packit |
eba2e2 |
and terminated by
|
|
Packit |
eba2e2 |
.Li NULL .
|
|
Packit |
eba2e2 |
The commands will be executed in forked children; if any exits non-zero then
|
|
Packit |
eba2e2 |
it will terminate the sequence, as with "&&" in shell.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.Li pipecmd_*
|
|
Packit |
eba2e2 |
functions that deal with arguments cannot be used with the command returned
|
|
Packit |
eba2e2 |
by this function.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft "pipecmd *" Ns Fn pipecmd_new_passthrough void
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Return a new command that just passes data from its input to its output.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft "pipecmd *" Ns Fn pipecmd_dup "pipecmd *cmd"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Return a duplicate of a command.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_arg "pipecmd *cmd" "const char *arg"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Add an argument to a command.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_argf "pipecmd *cmd" "const char *format" ...
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Convenience function to add an argument with printf substitutions.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_argv "pipecmd *cmd" "va_list argv"
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_args "pipecmd *cmd" ...
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Convenience functions wrapping
|
|
Packit |
eba2e2 |
.Fn pipecmd_arg
|
|
Packit |
eba2e2 |
to add multiple arguments at once.
|
|
Packit |
eba2e2 |
Terminate arguments with
|
|
Packit |
eba2e2 |
.Li NULL .
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_argstr "pipecmd *cmd" "const char *argstr"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Split
|
|
Packit |
eba2e2 |
.Va argstr
|
|
Packit |
eba2e2 |
on whitespace to add a list of arguments, honouring shell-style
|
|
Packit |
eba2e2 |
single-quoting, double-quoting, and backslashes, but not other shell
|
|
Packit |
eba2e2 |
evilness like wildcards, semicolons, or backquotes.
|
|
Packit |
eba2e2 |
This is included only to support situations where command arguments are
|
|
Packit |
eba2e2 |
encoded into configuration files and the like.
|
|
Packit |
eba2e2 |
While it is safer than
|
|
Packit |
eba2e2 |
.Xr system 3 ,
|
|
Packit |
eba2e2 |
it still involves significant string parsing which is inherently riskier
|
|
Packit |
eba2e2 |
than avoiding it altogether.
|
|
Packit |
eba2e2 |
Please try to avoid using it in new code.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_get_nargs "pipecmd *cmd"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Return the number of arguments to this command.
|
|
Packit |
eba2e2 |
Note that this includes the command name as the first argument, so the
|
|
Packit |
eba2e2 |
command
|
|
Packit |
eba2e2 |
.Sq echo foo bar
|
|
Packit |
eba2e2 |
is counted as having three arguments.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_nice "pipecmd *cmd" "int value"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Set the
|
|
Packit |
eba2e2 |
.Xr nice 3
|
|
Packit |
eba2e2 |
value for this command.
|
|
Packit |
eba2e2 |
Defaults to 0.
|
|
Packit |
eba2e2 |
Errors while attempting to set the nice value are ignored, aside from
|
|
Packit |
eba2e2 |
emitting a debug message.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_discard_err "pipecmd *cmd" "int discard_err"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
If
|
|
Packit |
eba2e2 |
.Va discard_err
|
|
Packit |
eba2e2 |
is non-zero, redirect this command's standard error to
|
|
Packit |
eba2e2 |
.Pa /dev/null .
|
|
Packit |
eba2e2 |
Otherwise, and by default, pass it through.
|
|
Packit |
eba2e2 |
This is usually a bad idea.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_chdir "pipecmd *cmd" "const char *directory"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Change the working directory to
|
|
Packit |
eba2e2 |
.Va directory
|
|
Packit |
eba2e2 |
while running this command.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_fchdir "pipecmd *cmd" "int directory_fd"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Change the working directory to the directory given by the open file
|
|
Packit |
eba2e2 |
descriptor
|
|
Packit |
eba2e2 |
.Va directory_fd
|
|
Packit |
eba2e2 |
while running this command.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Xo Ft void
|
|
Packit |
eba2e2 |
.Fn pipecmd_setenv "pipecmd *cmd" "const char *name" "const char *value"
|
|
Packit |
eba2e2 |
.Xc
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Set environment variable
|
|
Packit |
eba2e2 |
.Va name
|
|
Packit |
eba2e2 |
to
|
|
Packit |
eba2e2 |
.Va value
|
|
Packit |
eba2e2 |
while running this command.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_unsetenv "pipecmd *cmd" "const char *name"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Unset environment variable
|
|
Packit |
eba2e2 |
.Va name
|
|
Packit |
eba2e2 |
while running this command.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_clearenv "pipecmd *cmd"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Clear the environment while running this command.
|
|
Packit |
eba2e2 |
(Note that environment operations work in sequence; pipecmd_clearenv
|
|
Packit |
eba2e2 |
followed by pipecmd_setenv causes the command to have just a single
|
|
Packit |
eba2e2 |
environment variable set.)
|
|
Packit |
eba2e2 |
Beware that this may cause unexpected failures, for example if some of the
|
|
Packit |
eba2e2 |
contents of the environment are necessary to execute programs at all (say,
|
|
Packit |
eba2e2 |
.Li PATH ) .
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Xo Ft void
|
|
Packit |
eba2e2 |
.Fo pipecmd_pre_exec
|
|
Packit |
eba2e2 |
.Fa "pipecmd *cmd"
|
|
Packit |
eba2e2 |
.Fa "pipecmd_function_type *func"
|
|
Packit |
eba2e2 |
.Fa "pipecmd_function_free_type *free_func"
|
|
Packit |
eba2e2 |
.Fa "void *data"
|
|
Packit |
eba2e2 |
.Fc
|
|
Packit |
eba2e2 |
.Xc
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Install a pre-exec handler.
|
|
Packit |
eba2e2 |
This will be run immediately before executing the command's payload (process
|
|
Packit |
eba2e2 |
or function).
|
|
Packit |
eba2e2 |
Pass NULL to clear any existing pre-exec handler.
|
|
Packit |
eba2e2 |
The data argument is passed as the function's only argument, and will be
|
|
Packit |
eba2e2 |
freed before returning using free_func (if non-NULL).
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
This is similar to pipeline_install_post_fork, except that is specific to a
|
|
Packit |
eba2e2 |
single command rather than installing a global handler, and it runs slightly
|
|
Packit |
eba2e2 |
later (immediately before exec rather than immediately after fork).
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_sequence_command "pipecmd *cmd" "pipecmd *child"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Add a command to a sequence created using
|
|
Packit |
eba2e2 |
.Fn pipecmd_new_sequence .
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_dump "pipecmd *cmd" "FILE *stream"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Dump a string representation of a command to stream.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft "char *" Ns Fn pipecmd_tostring "pipecmd *cmd"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Return a string representation of a command.
|
|
Packit |
eba2e2 |
The caller should free the result.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_exec "pipecmd *cmd"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Execute a single command, replacing the current process.
|
|
Packit |
eba2e2 |
Never returns, instead exiting non-zero on failure.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipecmd_free "pipecmd *cmd"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Destroy a command.
|
|
Packit |
eba2e2 |
Safely does nothing if
|
|
Packit |
eba2e2 |
.Va cmd
|
|
Packit |
eba2e2 |
is
|
|
Packit |
eba2e2 |
.Li NULL .
|
|
Packit |
eba2e2 |
.El
|
|
Packit |
eba2e2 |
.Ss Functions to build pipelines
|
|
Packit |
eba2e2 |
.Bl -tag -width 4n -compact
|
|
Packit |
eba2e2 |
.It Ft "pipeline *" Ns Fn pipeline_new void
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Construct a new pipeline.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft "pipeline *" Ns Fn pipeline_new_commandv "pipecmd *cmd1" "va_list cmdv"
|
|
Packit |
eba2e2 |
.It Ft "pipeline *" Ns Fn pipeline_new_commands "pipecmd *cmd1" ...
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Convenience constructors wrapping
|
|
Packit |
eba2e2 |
.Fn pipeline_new
|
|
Packit |
eba2e2 |
and
|
|
Packit |
eba2e2 |
.Fn pipeline_command .
|
|
Packit |
eba2e2 |
Construct a new pipeline consisting of the given list of commands.
|
|
Packit |
eba2e2 |
Terminate commands with
|
|
Packit |
eba2e2 |
.Li NULL .
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Xo Ft "pipeline *" Ns
|
|
Packit |
eba2e2 |
.Fn pipeline_new_command_argv "const char *name" "va_list argv"
|
|
Packit |
eba2e2 |
.Xc
|
|
Packit |
eba2e2 |
.It Ft "pipeline *" Ns Fn pipeline_new_command_args "const char *name" ...
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Construct a new pipeline and add a single command to it.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft "pipeline *" Ns Fn pipeline_join "pipeline *p1" "pipeline *p2"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Joins two pipelines, neither of which are allowed to be started.
|
|
Packit |
eba2e2 |
Discards
|
|
Packit |
eba2e2 |
.Fa want_out ,
|
|
Packit |
eba2e2 |
.Fa want_outfile ,
|
|
Packit |
eba2e2 |
and
|
|
Packit |
eba2e2 |
.Fa outfd
|
|
Packit |
eba2e2 |
from
|
|
Packit |
eba2e2 |
.Va p1 ,
|
|
Packit |
eba2e2 |
and
|
|
Packit |
eba2e2 |
.Fa want_in ,
|
|
Packit |
eba2e2 |
.Fa want_infile ,
|
|
Packit |
eba2e2 |
and
|
|
Packit |
eba2e2 |
.Fa infd
|
|
Packit |
eba2e2 |
from
|
|
Packit |
eba2e2 |
.Va p2 .
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_connect "pipeline *source" "pipeline *sink" ...
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Connect the input of one or more sink pipelines to the output of a source
|
|
Packit |
eba2e2 |
pipeline.
|
|
Packit |
eba2e2 |
The source pipeline may be started, but in that case
|
|
Packit |
eba2e2 |
.Fn pipeline_want_out
|
|
Packit |
eba2e2 |
must have been called with a negative
|
|
Packit |
eba2e2 |
.Fa fd ;
|
|
Packit |
eba2e2 |
otherwise, calls
|
|
Packit |
eba2e2 |
.Fn pipeline_want_out source -1 .
|
|
Packit |
eba2e2 |
In any event, calls
|
|
Packit |
eba2e2 |
.Fn pipeline_want_in sink -1
|
|
Packit |
eba2e2 |
on all sinks, none of which are allowed to be started.
|
|
Packit |
eba2e2 |
Terminate arguments with
|
|
Packit |
eba2e2 |
.Li NULL .
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
This is an application-level connection; data may be intercepted between the
|
|
Packit |
eba2e2 |
pipelines by the program before calling
|
|
Packit |
eba2e2 |
.Fn pipeline_pump ,
|
|
Packit |
eba2e2 |
which sets data flowing from the source to the sinks.
|
|
Packit |
eba2e2 |
It is primarily useful when more than one sink pipeline is involved, in
|
|
Packit |
eba2e2 |
which case the pipelines cannot simply be concatenated into one.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
The result is similar to
|
|
Packit |
eba2e2 |
.Xr tee 1 ,
|
|
Packit |
eba2e2 |
except that output can be sent to more than two places and can easily be
|
|
Packit |
eba2e2 |
sent to multiple processes.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_command "pipeline *p" "pipecmd *cmd"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Add a command to a pipeline.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Xo Ft void
|
|
Packit |
eba2e2 |
.Fn pipeline_command_argv "pipeline *p" "const char *name" "va_list argv"
|
|
Packit |
eba2e2 |
.Xc
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_command_args "pipeline *p" "const char *name" ...
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Construct a new command and add it to a pipeline in one go.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_command_argstr "pipeline *p" "const char *argstr"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Construct a new command from a shell-quoted string and add it to a pipeline
|
|
Packit |
eba2e2 |
in one go.
|
|
Packit |
eba2e2 |
See the comment against
|
|
Packit |
eba2e2 |
.Fn pipecmd_new_argstr
|
|
Packit |
eba2e2 |
above if you're tempted to use this function.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_commandv "pipeline *p" "va_list cmdv"
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_commands "pipeline *p" ...
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Convenience functions wrapping
|
|
Packit |
eba2e2 |
.Fn pipeline_command
|
|
Packit |
eba2e2 |
to add multiple commands at once.
|
|
Packit |
eba2e2 |
Terminate arguments with
|
|
Packit |
eba2e2 |
.Li NULL .
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_want_in "pipeline *p" "int fd"
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_want_out "pipeline *p" "int fd"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Set file descriptors to use as the input and output of the whole pipeline.
|
|
Packit |
eba2e2 |
If non-negative,
|
|
Packit |
eba2e2 |
.Va fd
|
|
Packit |
eba2e2 |
is used directly as a file descriptor.
|
|
Packit |
eba2e2 |
If negative,
|
|
Packit |
eba2e2 |
.Fn pipeline_start
|
|
Packit |
eba2e2 |
will create pipes and store the input writing half and the output reading
|
|
Packit |
eba2e2 |
half in the pipeline's
|
|
Packit |
eba2e2 |
.Fa infd
|
|
Packit |
eba2e2 |
or
|
|
Packit |
eba2e2 |
.Fa outfd
|
|
Packit |
eba2e2 |
field as appropriate.
|
|
Packit |
eba2e2 |
The default is to leave input and output as stdin and stdout unless
|
|
Packit |
eba2e2 |
.Fn pipeline_want_infile
|
|
Packit |
eba2e2 |
or
|
|
Packit |
eba2e2 |
.Fn pipeline_want_outfile
|
|
Packit |
eba2e2 |
respectively has been called.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Calling these functions supersedes any previous call to
|
|
Packit |
eba2e2 |
.Fn pipeline_want_infile
|
|
Packit |
eba2e2 |
or
|
|
Packit |
eba2e2 |
.Fn pipeline_want_outfile
|
|
Packit |
eba2e2 |
respectively.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_want_infile "pipeline *p" "const char *file"
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_want_outfile "pipeline *p" "const char *file"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Set file names to open and use as the input and output of the whole
|
|
Packit |
eba2e2 |
pipeline.
|
|
Packit |
eba2e2 |
This may be more convenient than supplying file descriptors, and guarantees
|
|
Packit |
eba2e2 |
that the files are opened with the same privileges under which the pipeline
|
|
Packit |
eba2e2 |
is run.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Calling these functions (even with
|
|
Packit |
eba2e2 |
.Li NULL ,
|
|
Packit |
eba2e2 |
which returns to the default of leaving input and output as stdin and
|
|
Packit |
eba2e2 |
stdout) supersedes any previous call to
|
|
Packit |
eba2e2 |
.Fn pipeline_want_in
|
|
Packit |
eba2e2 |
or
|
|
Packit |
eba2e2 |
.Fn pipeline_want_outfile
|
|
Packit |
eba2e2 |
respectively.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
The given files will be opened when the pipeline is started.
|
|
Packit |
eba2e2 |
If an output file does not already exist, it is created (with mode 0666
|
|
Packit |
eba2e2 |
modified in the usual way by umask); if it does exist, then it is truncated.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_ignore_signals "pipeline *p" "int ignore_signals"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
If
|
|
Packit |
eba2e2 |
.Va ignore_signals
|
|
Packit |
eba2e2 |
is non-zero, ignore
|
|
Packit |
eba2e2 |
.Li SIGINT
|
|
Packit |
eba2e2 |
and
|
|
Packit |
eba2e2 |
.Li SIGQUIT
|
|
Packit |
eba2e2 |
in the calling process while the pipeline is running, like
|
|
Packit |
eba2e2 |
.Xr system 3 .
|
|
Packit |
eba2e2 |
Otherwise, and by default, leave their dispositions unchanged.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft int Fn pipeline_get_ncommands "pipeline *p"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Return the number of commands in this pipeline.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft "pipecmd *" Ns Fn pipeline_get_command "pipeline *p" "int n"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Return command number
|
|
Packit |
eba2e2 |
.Va n
|
|
Packit |
eba2e2 |
from this pipeline, counting from zero, or
|
|
Packit |
eba2e2 |
.Li NULL
|
|
Packit |
eba2e2 |
if
|
|
Packit |
eba2e2 |
.Va n
|
|
Packit |
eba2e2 |
is out of range.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Xo Ft "pipecmd *" Ns
|
|
Packit |
eba2e2 |
.Fn pipeline_set_command "pipeline *p" "int n" "pipecmd *cmd"
|
|
Packit |
eba2e2 |
.Xc
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Set command number
|
|
Packit |
eba2e2 |
.Va n
|
|
Packit |
eba2e2 |
in this pipeline, counting from zero, to
|
|
Packit |
eba2e2 |
.Va cmd ,
|
|
Packit |
eba2e2 |
and return the previous command in that position.
|
|
Packit |
eba2e2 |
Do nothing and return
|
|
Packit |
eba2e2 |
.Li NULL
|
|
Packit |
eba2e2 |
if
|
|
Packit |
eba2e2 |
.Va n
|
|
Packit |
eba2e2 |
is out of range.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft pid_t Fn pipeline_get_pid "pipeline *p" "int n"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Return the process ID of command number
|
|
Packit |
eba2e2 |
.Va n
|
|
Packit |
eba2e2 |
from this pipeline, counting from zero.
|
|
Packit |
eba2e2 |
The pipeline must be started.
|
|
Packit |
eba2e2 |
Return
|
|
Packit |
eba2e2 |
.Li \-1
|
|
Packit |
eba2e2 |
if
|
|
Packit |
eba2e2 |
.Va n
|
|
Packit |
eba2e2 |
is out of range or if the command has already exited and been reaped.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft "FILE *" Ns Fn pipeline_get_infile "pipeline *p"
|
|
Packit |
eba2e2 |
.It Ft "FILE *" Ns Fn pipeline_get_outfile "pipeline *p"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Get streams corresponding to
|
|
Packit |
eba2e2 |
.Fa infd
|
|
Packit |
eba2e2 |
and
|
|
Packit |
eba2e2 |
.Fa outfd
|
|
Packit |
eba2e2 |
respectively.
|
|
Packit |
eba2e2 |
The pipeline must be started.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_dump "pipeline *p" "FILE *stream"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Dump a string representation of
|
|
Packit |
eba2e2 |
.Va p
|
|
Packit |
eba2e2 |
to stream.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft "char *" Ns Fn pipeline_tostring "pipeline *p"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Return a string representation of
|
|
Packit |
eba2e2 |
.Va p .
|
|
Packit |
eba2e2 |
The caller should free the result.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_free "pipeline *p"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Destroy a pipeline and all its commands.
|
|
Packit |
eba2e2 |
Safely does nothing if
|
|
Packit |
eba2e2 |
.Va p
|
|
Packit |
eba2e2 |
is
|
|
Packit |
eba2e2 |
.Li NULL .
|
|
Packit |
eba2e2 |
May wait for the pipeline to complete if it has not already done so.
|
|
Packit |
eba2e2 |
.El
|
|
Packit |
eba2e2 |
.Ss Functions to run pipelines and handle signals
|
|
Packit |
eba2e2 |
.Bl -tag -width 4n -compact
|
|
Packit |
eba2e2 |
.It Vt typedef void pipeline_post_fork_fn (void) ;
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_install_post_fork "pipeline_post_fork_fn *fn"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Install a post-fork handler.
|
|
Packit |
eba2e2 |
This will be run in any child process immediately after it is forked.
|
|
Packit |
eba2e2 |
For instance, this may be used for cleaning up application-specific signal
|
|
Packit |
eba2e2 |
handlers.
|
|
Packit |
eba2e2 |
Pass
|
|
Packit |
eba2e2 |
.Li NULL
|
|
Packit |
eba2e2 |
to clear any existing post-fork handler.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
See pipecmd_pre_exec for a similar facility limited to a single command
|
|
Packit |
eba2e2 |
rather than global to the calling process.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_start "pipeline *p"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Start the processes in a pipeline.
|
|
Packit |
eba2e2 |
Installs this library's
|
|
Packit |
eba2e2 |
.Li SIGCHLD
|
|
Packit |
eba2e2 |
handler if not already installed.
|
|
Packit |
eba2e2 |
Calls
|
|
Packit |
eba2e2 |
.Li error (FATAL)
|
|
Packit |
eba2e2 |
on error.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Xo
|
|
Packit |
eba2e2 |
.Ft int Fn pipeline_wait_all "pipeline *p" "int **statuses" "int *n_statuses"
|
|
Packit |
eba2e2 |
.Xc
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Wait for a pipeline to complete.
|
|
Packit |
eba2e2 |
Set
|
|
Packit |
eba2e2 |
.No * Ns Va statuses
|
|
Packit |
eba2e2 |
to a newly-allocated array of wait statuses, as returned by
|
|
Packit |
eba2e2 |
.Xr waitpid 2 ,
|
|
Packit |
eba2e2 |
and
|
|
Packit |
eba2e2 |
.No * Ns Va n_statuses
|
|
Packit |
eba2e2 |
to the length of that array.
|
|
Packit |
eba2e2 |
The return value is similar to the exit status that a shell would return,
|
|
Packit |
eba2e2 |
with some modifications.
|
|
Packit |
eba2e2 |
If the last command exits with a signal (other than
|
|
Packit |
eba2e2 |
.Li SIGPIPE ,
|
|
Packit |
eba2e2 |
which is considered equivalent to exiting zero), then the return value is
|
|
Packit |
eba2e2 |
128 plus the signal number; if the last command exits normally but non-zero,
|
|
Packit |
eba2e2 |
then the return value is its exit status; if any other command exits
|
|
Packit |
eba2e2 |
non-zero, then the return value is 127; otherwise, the return value is 0.
|
|
Packit |
eba2e2 |
This means that the return value is only 0 if all commands in the pipeline
|
|
Packit |
eba2e2 |
exit successfully.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft int Fn pipeline_wait "pipeline *p"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Wait for a pipeline to complete and return its combined exit status,
|
|
Packit |
eba2e2 |
calculated as for
|
|
Packit |
eba2e2 |
.Fn pipeline_wait_all .
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft int Fn pipeline_run "pipeline *p"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Start a pipeline, wait for it to complete, and free it, all in one go.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_pump "pipeline *p" ...
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Pump data among one or more pipelines connected using
|
|
Packit |
eba2e2 |
.Fn pipeline_connect
|
|
Packit |
eba2e2 |
until all source pipelines have reached end-of-file and all data has been
|
|
Packit |
eba2e2 |
written to all sinks (or failed).
|
|
Packit |
eba2e2 |
All relevant pipelines must be supplied: that is, no pipeline that has been
|
|
Packit |
eba2e2 |
connected to a source pipeline may be supplied unless that source pipeline
|
|
Packit |
eba2e2 |
is also supplied.
|
|
Packit |
eba2e2 |
Automatically starts all pipelines if they are not already started, but does
|
|
Packit |
eba2e2 |
not wait for them.
|
|
Packit |
eba2e2 |
Terminate arguments with
|
|
Packit |
eba2e2 |
.Li NULL .
|
|
Packit |
eba2e2 |
.El
|
|
Packit |
eba2e2 |
.Ss Functions to read output from pipelines
|
|
Packit |
eba2e2 |
In general, output is returned as a pointer into a buffer owned by the
|
|
Packit |
eba2e2 |
pipeline, which is automatically freed when
|
|
Packit |
eba2e2 |
.Fn pipeline_free
|
|
Packit |
eba2e2 |
is called.
|
|
Packit |
eba2e2 |
This saves the caller from having to explicitly free individual blocks of
|
|
Packit |
eba2e2 |
output data.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.Bl -tag -width 4n -compact
|
|
Packit |
eba2e2 |
.It Ft "const char *" Ns Fn pipeline_read "pipeline *p" "size_t *len"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Read
|
|
Packit |
eba2e2 |
.Va len
|
|
Packit |
eba2e2 |
bytes of data from the pipeline, returning the data block.
|
|
Packit |
eba2e2 |
.Va len
|
|
Packit |
eba2e2 |
is updated with the number of bytes read.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft "const char *" Ns Fn pipeline_peek "pipeline *p" "size_t *len"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Look ahead in the pipeline's output for
|
|
Packit |
eba2e2 |
.Va len
|
|
Packit |
eba2e2 |
bytes of data, returning the data block.
|
|
Packit |
eba2e2 |
.Va len
|
|
Packit |
eba2e2 |
is updated with the number of bytes read.
|
|
Packit |
eba2e2 |
The starting position of the next read or peek is not affected by this call.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft size_t Fn pipeline_peek_size "pipeline *p"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Return the number of bytes of data that can be read using
|
|
Packit |
eba2e2 |
.Fn pipeline_read
|
|
Packit |
eba2e2 |
or
|
|
Packit |
eba2e2 |
.Fn pipeline_peek
|
|
Packit |
eba2e2 |
solely from the peek cache, without having to read from the pipeline itself
|
|
Packit |
eba2e2 |
(and thus potentially block).
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft void Fn pipeline_peek_skip "pipeline *p" "size_t len"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Skip over and discard
|
|
Packit |
eba2e2 |
.Va len
|
|
Packit |
eba2e2 |
bytes of data from the peek cache.
|
|
Packit |
eba2e2 |
Asserts that enough data is available to skip, so you may want to check
|
|
Packit |
eba2e2 |
using
|
|
Packit |
eba2e2 |
.Fn pipeline_peek_size
|
|
Packit |
eba2e2 |
first.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft "const char *" Ns Fn pipeline_readline "pipeline *p"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Read a line of data from the pipeline, returning it.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.It Ft "const char *" Ns Fn pipeline_peekline "pipeline *p"
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Look ahead in the pipeline's output for a line of data, returning it.
|
|
Packit |
eba2e2 |
The starting position of the next read or peek is not affected by this call.
|
|
Packit |
eba2e2 |
.El
|
|
Packit |
eba2e2 |
.Ss Signal handling
|
|
Packit |
eba2e2 |
.Nm
|
|
Packit |
eba2e2 |
installs a signal handler for
|
|
Packit |
eba2e2 |
.Li SIGCHLD ,
|
|
Packit |
eba2e2 |
and collects the exit status of child processes in
|
|
Packit |
eba2e2 |
.Fn pipeline_wait .
|
|
Packit |
eba2e2 |
Applications using this library must either refrain from changing the
|
|
Packit |
eba2e2 |
disposition of
|
|
Packit |
eba2e2 |
.Li SIGCHLD
|
|
Packit |
eba2e2 |
(in other words, must rely on
|
|
Packit |
eba2e2 |
.Nm
|
|
Packit |
eba2e2 |
for all child process handling) or else must make sure to restore
|
|
Packit |
eba2e2 |
.Nm Ns 's
|
|
Packit |
eba2e2 |
.Li SIGCHLD
|
|
Packit |
eba2e2 |
handler before calling any of its functions.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
If the
|
|
Packit |
eba2e2 |
.Fa ignore_signals
|
|
Packit |
eba2e2 |
flag is set in a pipeline (which is the default), then the
|
|
Packit |
eba2e2 |
.Li SIGINT
|
|
Packit |
eba2e2 |
and
|
|
Packit |
eba2e2 |
.Li SIGQUIT
|
|
Packit |
eba2e2 |
signals will be ignored in the parent process while child processes are
|
|
Packit |
eba2e2 |
running.
|
|
Packit |
eba2e2 |
This mirrors the behaviour of
|
|
Packit |
eba2e2 |
.Xr system 3 .
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.Nm
|
|
Packit |
eba2e2 |
leaves child processes with the default disposition of
|
|
Packit |
eba2e2 |
.Li SIGPIPE ,
|
|
Packit |
eba2e2 |
namely to terminate the process.
|
|
Packit |
eba2e2 |
It ignores
|
|
Packit |
eba2e2 |
.Li SIGPIPE
|
|
Packit |
eba2e2 |
in the parent process while running
|
|
Packit |
eba2e2 |
.Fn pipeline_pump .
|
|
Packit |
eba2e2 |
.Ss Reaping of child processes
|
|
Packit |
eba2e2 |
.Nm
|
|
Packit |
eba2e2 |
installs a
|
|
Packit |
eba2e2 |
.Li SIGCHLD
|
|
Packit |
eba2e2 |
handler that will attempt to reap child processes which have exited.
|
|
Packit |
eba2e2 |
This calls
|
|
Packit |
eba2e2 |
.Xr waitpid 2
|
|
Packit |
eba2e2 |
with
|
|
Packit |
eba2e2 |
.Li \-1 ,
|
|
Packit |
eba2e2 |
so it will reap any child process, not merely those created by way of this
|
|
Packit |
eba2e2 |
library.
|
|
Packit |
eba2e2 |
At present, this means that if the calling program forks other child
|
|
Packit |
eba2e2 |
processes which may exit while a pipeline is running, the program is not
|
|
Packit |
eba2e2 |
guaranteed to be able to collect exit statuses of those processes.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
You should not rely on this behaviour, and in future it may be modified
|
|
Packit |
eba2e2 |
either to reap only child processes created by this library or to provide a
|
|
Packit |
eba2e2 |
way to return foreign statuses to the application.
|
|
Packit |
eba2e2 |
Please contact the author if you have an example application and would like
|
|
Packit |
eba2e2 |
to help design such an interface.
|
|
Packit |
eba2e2 |
.Sh ENVIRONMENT
|
|
Packit |
eba2e2 |
If the
|
|
Packit |
eba2e2 |
.Ev PIPELINE_DEBUG
|
|
Packit |
eba2e2 |
environment variable is set to
|
|
Packit |
eba2e2 |
.Dq 1 ,
|
|
Packit |
eba2e2 |
then
|
|
Packit |
eba2e2 |
.Nm
|
|
Packit |
eba2e2 |
will emit debugging messages on standard error.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
If the
|
|
Packit |
eba2e2 |
.Ev PIPELINE_QUIET
|
|
Packit |
eba2e2 |
environment variable is set to any value, then
|
|
Packit |
eba2e2 |
.Nm
|
|
Packit |
eba2e2 |
will refrain from printing an error message when a subprocess is terminated
|
|
Packit |
eba2e2 |
by a signal.
|
|
Packit |
eba2e2 |
.Sh EXAMPLES
|
|
Packit |
eba2e2 |
In the following examples, function names starting with
|
|
Packit |
eba2e2 |
.Li pipecmd_
|
|
Packit |
eba2e2 |
or
|
|
Packit |
eba2e2 |
.Li pipeline_
|
|
Packit |
eba2e2 |
are real
|
|
Packit |
eba2e2 |
.Nm
|
|
Packit |
eba2e2 |
functions, while any other function names are pseudocode.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
The simplest case is simple.
|
|
Packit |
eba2e2 |
To run a single command, such as
|
|
Packit |
eba2e2 |
.Ic mv
|
|
Packit |
eba2e2 |
.Pa source
|
|
Packit |
eba2e2 |
.Pa dest :
|
|
Packit |
eba2e2 |
.Bd -literal -offset indent
|
|
Packit |
eba2e2 |
pipeline *p = pipeline_new_command_args ("mv", source, dest, NULL);
|
|
Packit |
eba2e2 |
int status = pipeline_run (p);
|
|
Packit |
eba2e2 |
.Ed
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.Nm
|
|
Packit |
eba2e2 |
is often used to mimic shell pipelines, such as the following example:
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.Dl zsoelim < input-file | tbl | nroff -mandoc -Tutf8
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
The code to construct this would be:
|
|
Packit |
eba2e2 |
.Bd -literal -offset indent
|
|
Packit |
eba2e2 |
pipeline *p;
|
|
Packit |
eba2e2 |
int status;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
p = pipeline_new ();
|
|
Packit |
eba2e2 |
pipeline_want_infile (p, "input-file");
|
|
Packit |
eba2e2 |
pipeline_command_args (p, "zsoelim", NULL);
|
|
Packit |
eba2e2 |
pipeline_command_args (p, "tbl", NULL);
|
|
Packit |
eba2e2 |
pipeline_command_args (p, "nroff", "-mandoc", "-Tutf8", NULL);
|
|
Packit |
eba2e2 |
status = pipeline_run (p);
|
|
Packit |
eba2e2 |
.Ed
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
You might want to construct a command more dynamically:
|
|
Packit |
eba2e2 |
.Bd -literal -offset indent
|
|
Packit |
eba2e2 |
pipecmd *manconv = pipecmd_new_args ("manconv", "-f", from_code,
|
|
Packit |
eba2e2 |
"-t", "UTF-8", NULL);
|
|
Packit |
eba2e2 |
if (quiet)
|
|
Packit |
eba2e2 |
pipecmd_arg (manconv, "-q");
|
|
Packit |
eba2e2 |
pipeline_command (p, manconv);
|
|
Packit |
eba2e2 |
.Ed
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Perhaps you want an environment variable set only while running a certain
|
|
Packit |
eba2e2 |
command:
|
|
Packit |
eba2e2 |
.Bd -literal -offset indent
|
|
Packit |
eba2e2 |
pipecmd *less = pipecmd_new ("less");
|
|
Packit |
eba2e2 |
pipecmd_setenv (less, "LESSCHARSET", lesscharset);
|
|
Packit |
eba2e2 |
.Ed
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
You might find yourself needing to pass the output of one pipeline to
|
|
Packit |
eba2e2 |
several other pipelines, in a
|
|
Packit |
eba2e2 |
.Dq tee
|
|
Packit |
eba2e2 |
arrangement:
|
|
Packit |
eba2e2 |
.Bd -literal -offset indent
|
|
Packit |
eba2e2 |
pipeline *source, *sink1, *sink2;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
source = make_source ();
|
|
Packit |
eba2e2 |
sink1 = make_sink1 ();
|
|
Packit |
eba2e2 |
sink2 = make_sink2 ();
|
|
Packit |
eba2e2 |
pipeline_connect (source, sink1, sink2, NULL);
|
|
Packit |
eba2e2 |
/* Pump data among these pipelines until there's nothing left. */
|
|
Packit |
eba2e2 |
pipeline_pump (source, sink1, sink2, NULL);
|
|
Packit |
eba2e2 |
pipeline_free (sink2);
|
|
Packit |
eba2e2 |
pipeline_free (sink1);
|
|
Packit |
eba2e2 |
pipeline_free (source);
|
|
Packit |
eba2e2 |
.Ed
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Maybe one of your commands is actually an in-process function, rather than
|
|
Packit |
eba2e2 |
an external program:
|
|
Packit |
eba2e2 |
.Bd -literal -offset indent
|
|
Packit |
eba2e2 |
pipecmd *inproc = pipecmd_new_function ("in-process", &func,
|
|
Packit |
eba2e2 |
NULL, NULL);
|
|
Packit |
eba2e2 |
pipeline_command (p, inproc);
|
|
Packit |
eba2e2 |
.Ed
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
Sometimes your program needs to consume the output of a pipeline, rather
|
|
Packit |
eba2e2 |
than sending it all to some other subprocess:
|
|
Packit |
eba2e2 |
.Bd -literal -offset indent
|
|
Packit |
eba2e2 |
pipeline *p = make_pipeline ();
|
|
Packit |
eba2e2 |
const char *line;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
pipeline_want_out (p, -1);
|
|
Packit |
eba2e2 |
pipeline_start (p);
|
|
Packit |
eba2e2 |
line = pipeline_peekline (p);
|
|
Packit |
eba2e2 |
if (!strstr (line, "coding: UTF-8"))
|
|
Packit |
eba2e2 |
printf ("Unicode text follows:\n");
|
|
Packit |
eba2e2 |
while (line = pipeline_readline (p))
|
|
Packit |
eba2e2 |
printf (" %s", line);
|
|
Packit |
eba2e2 |
pipeline_free (p);
|
|
Packit |
eba2e2 |
.Ed
|
|
Packit |
eba2e2 |
.Sh SEE ALSO
|
|
Packit |
eba2e2 |
.Xr fork 2 ,
|
|
Packit |
eba2e2 |
.Xr execve 2 ,
|
|
Packit |
eba2e2 |
.Xr system 3 ,
|
|
Packit |
eba2e2 |
.Xr popen 3 .
|
|
Packit |
eba2e2 |
.Sh AUTHORS
|
|
Packit |
eba2e2 |
.An -nosplit
|
|
Packit |
eba2e2 |
Most of
|
|
Packit |
eba2e2 |
.Nm
|
|
Packit |
eba2e2 |
was written by
|
|
Packit |
eba2e2 |
.An Colin Watson Aq cjwatson@debian.org ,
|
|
Packit |
eba2e2 |
originally for use in man\-db.
|
|
Packit |
eba2e2 |
The initial version was based very loosely on the
|
|
Packit |
eba2e2 |
.Fn run_pipeline
|
|
Packit |
eba2e2 |
function in GNU groff, written by
|
|
Packit |
eba2e2 |
.An James Clark Aq jjc@jclark.com .
|
|
Packit |
eba2e2 |
It also contains library code by
|
|
Packit |
eba2e2 |
.An Markus Armbruster ,
|
|
Packit |
eba2e2 |
and by various contributors to Gnulib.
|
|
Packit |
eba2e2 |
.Pp
|
|
Packit |
eba2e2 |
.Nm
|
|
Packit |
eba2e2 |
is licensed under the GNU General Public License, version 3 or later.
|
|
Packit |
eba2e2 |
See the README file for full details.
|
|
Packit |
eba2e2 |
.Sh BUGS
|
|
Packit |
eba2e2 |
Using this library in a program which runs any other child processes and/or
|
|
Packit |
eba2e2 |
installs its own
|
|
Packit |
eba2e2 |
.Li SIGCHLD
|
|
Packit |
eba2e2 |
handler is unlikely to work.
|