|
Packit |
eba2e2 |
/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2002
|
|
Packit |
eba2e2 |
* Free Software Foundation, Inc.
|
|
Packit |
eba2e2 |
* Copyright (C) 2003-2017 Colin Watson.
|
|
Packit |
eba2e2 |
* Written for groff by James Clark (jjc@jclark.com)
|
|
Packit |
eba2e2 |
* Adapted for man-db by 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 2 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 |
*/
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
#ifndef PIPELINE_H
|
|
Packit |
eba2e2 |
#define PIPELINE_H
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
#ifdef __cplusplus
|
|
Packit |
eba2e2 |
extern "C" {
|
|
Packit |
eba2e2 |
#endif
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
#include <stdio.h>
|
|
Packit |
eba2e2 |
#include <stdarg.h>
|
|
Packit |
eba2e2 |
#include <sys/types.h>
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* GCC version checking borrowed from glibc. */
|
|
Packit |
eba2e2 |
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
|
Packit |
eba2e2 |
# define PIPELINE_GNUC_PREREQ(maj,min) \
|
|
Packit |
eba2e2 |
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
|
Packit |
eba2e2 |
#else
|
|
Packit |
eba2e2 |
# define PIPELINE_GNUC_PREREQ(maj,min) 0
|
|
Packit |
eba2e2 |
#endif
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Does this compiler support format string checking? */
|
|
Packit |
eba2e2 |
#if PIPELINE_GNUC_PREREQ(2,0)
|
|
Packit |
eba2e2 |
# define PIPELINE_ATTR_FORMAT_PRINTF(a,b) \
|
|
Packit |
eba2e2 |
__attribute__ ((__format__ (__printf__, a, b)))
|
|
Packit |
eba2e2 |
#else
|
|
Packit |
eba2e2 |
# define PIPELINE_ATTR_FORMAT_PRINTF(a,b)
|
|
Packit |
eba2e2 |
#endif
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Does this compiler support marking variables as unused? */
|
|
Packit |
eba2e2 |
#if PIPELINE_GNUC_PREREQ(2,4)
|
|
Packit |
eba2e2 |
# define PIPELINE_ATTR_UNUSED __attribute__ ((__unused__))
|
|
Packit |
eba2e2 |
#else
|
|
Packit |
eba2e2 |
# define PIPELINE_ATTR_UNUSED
|
|
Packit |
eba2e2 |
#endif
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Does this compiler support marking functions as non-returning? */
|
|
Packit |
eba2e2 |
#if PIPELINE_GNUC_PREREQ(2,5)
|
|
Packit |
eba2e2 |
# define PIPELINE_ATTR_NORETURN __attribute__ ((__noreturn__))
|
|
Packit |
eba2e2 |
#else
|
|
Packit |
eba2e2 |
# define PIPELINE_ATTR_NORETURN
|
|
Packit |
eba2e2 |
#endif
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Does this compiler support unused result checking? */
|
|
Packit |
eba2e2 |
#if PIPELINE_GNUC_PREREQ(3,4)
|
|
Packit |
eba2e2 |
# define PIPELINE_ATTR_WARN_UNUSED_RESULT \
|
|
Packit |
eba2e2 |
__attribute__ ((__warn_unused_result__))
|
|
Packit |
eba2e2 |
#else
|
|
Packit |
eba2e2 |
# define PIPELINE_ATTR_WARN_UNUSED_RESULT
|
|
Packit |
eba2e2 |
#endif
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Does this compiler support sentinel checking? */
|
|
Packit |
eba2e2 |
#if PIPELINE_GNUC_PREREQ(4,0)
|
|
Packit |
eba2e2 |
# define PIPELINE_ATTR_SENTINEL __attribute__ ((__sentinel__))
|
|
Packit |
eba2e2 |
#else
|
|
Packit |
eba2e2 |
# define PIPELINE_ATTR_SENTINEL
|
|
Packit |
eba2e2 |
#endif
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
typedef void pipecmd_function_type (void *);
|
|
Packit |
eba2e2 |
typedef void pipecmd_function_free_type (void *);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
struct pipecmd;
|
|
Packit |
eba2e2 |
typedef struct pipecmd pipecmd;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
struct pipeline;
|
|
Packit |
eba2e2 |
typedef struct pipeline pipeline;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* ---------------------------------------------------------------------- */
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Functions to build individual commands. */
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Construct a new command. */
|
|
Packit |
eba2e2 |
pipecmd *pipecmd_new (const char *name);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Convenience constructors wrapping pipecmd_new() and pipecmd_arg().
|
|
Packit |
eba2e2 |
* Terminate arguments with NULL.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
pipecmd *pipecmd_new_argv (const char *name, va_list argv);
|
|
Packit |
eba2e2 |
pipecmd *pipecmd_new_args (const char *name, ...) PIPELINE_ATTR_SENTINEL;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Split argstr on whitespace to construct a command and arguments,
|
|
Packit |
eba2e2 |
* honouring shell-style single-quoting, double-quoting, and backslashes,
|
|
Packit |
eba2e2 |
* but not other shell evil like wildcards, semicolons, or backquotes. This
|
|
Packit |
eba2e2 |
* is a backward-compatibility hack to support old configuration file
|
|
Packit |
eba2e2 |
* directives; please try to avoid using it in new code.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
pipecmd *pipecmd_new_argstr (const char *argstr);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Construct a new command that calls a given function rather than executing
|
|
Packit |
eba2e2 |
* a process. The data argument is passed as the function's only argument,
|
|
Packit |
eba2e2 |
* and will be freed before returning using free_func (if non-NULL).
|
|
Packit |
eba2e2 |
*
|
|
Packit |
eba2e2 |
* pipecmd_* functions that deal with arguments cannot be used with the
|
|
Packit |
eba2e2 |
* command returned by this function.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
pipecmd *pipecmd_new_function (const char *name,
|
|
Packit |
eba2e2 |
pipecmd_function_type *func,
|
|
Packit |
eba2e2 |
pipecmd_function_free_type *free_func,
|
|
Packit |
eba2e2 |
void *data);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Construct a new command that runs a sequence of commands. The commands
|
|
Packit |
eba2e2 |
* will be executed in forked children; if any exits non-zero then it will
|
|
Packit |
eba2e2 |
* terminate the sequence, as with "&&" in shell.
|
|
Packit |
eba2e2 |
*
|
|
Packit |
eba2e2 |
* pipecmd_* functions that deal with arguments cannot be used with the
|
|
Packit |
eba2e2 |
* command returned by this function.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
pipecmd *pipecmd_new_sequencev (const char *name, va_list cmdv);
|
|
Packit |
eba2e2 |
pipecmd *pipecmd_new_sequence (const char *name, ...) PIPELINE_ATTR_SENTINEL;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Return a new command that just passes data from its input to its output. */
|
|
Packit |
eba2e2 |
pipecmd *pipecmd_new_passthrough (void);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Return a duplicate of a command. */
|
|
Packit |
eba2e2 |
pipecmd *pipecmd_dup (pipecmd *cmd);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Add an argument to a command. */
|
|
Packit |
eba2e2 |
void pipecmd_arg (pipecmd *cmd, const char *arg);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Convenience function to add an argument with printf substitutions. */
|
|
Packit |
eba2e2 |
void pipecmd_argf (pipecmd *cmd, const char *format, ...)
|
|
Packit |
eba2e2 |
PIPELINE_ATTR_FORMAT_PRINTF(2, 3);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Convenience functions wrapping pipecmd_arg().
|
|
Packit |
eba2e2 |
* Terminate arguments with NULL.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipecmd_argv (pipecmd *cmd, va_list argv);
|
|
Packit |
eba2e2 |
void pipecmd_args (pipecmd *cmd, ...) PIPELINE_ATTR_SENTINEL;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Split argstr on whitespace to add a list of arguments, honouring
|
|
Packit |
eba2e2 |
* shell-style single-quoting, double-quoting, and backslashes, but not
|
|
Packit |
eba2e2 |
* other shell evil like wildcards, semicolons, or backquotes. This is a
|
|
Packit |
eba2e2 |
* backward-compatibility hack to support old configuration file directives;
|
|
Packit |
eba2e2 |
* please try to avoid using it in new code.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipecmd_argstr (pipecmd *cmd, const char *argstr);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Return the number of arguments to this command. Note that this includes
|
|
Packit |
eba2e2 |
* the command name as the first argument, so the command 'echo foo bar' is
|
|
Packit |
eba2e2 |
* counted as having three arguments.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
int pipecmd_get_nargs (pipecmd *cmd);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Set the nice(3) value for this command. Defaults to 0. Errors while
|
|
Packit |
eba2e2 |
* attempting to set the nice value are ignored, aside from emitting a debug
|
|
Packit |
eba2e2 |
* message.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipecmd_nice (pipecmd *cmd, int nice);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* If discard_err is non-zero, redirect this command's standard error to
|
|
Packit |
eba2e2 |
* /dev/null. Otherwise, and by default, pass it through.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipecmd_discard_err (pipecmd *cmd, int discard_err);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Change to this directory while running this command. */
|
|
Packit |
eba2e2 |
void pipecmd_chdir (pipecmd *cmd, const char *directory);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Change to the directory given by this open file descriptor while running
|
|
Packit |
eba2e2 |
* this command. */
|
|
Packit |
eba2e2 |
void pipecmd_fchdir (pipecmd *cmd, int directory_fd);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Set an environment variable while running this command. */
|
|
Packit |
eba2e2 |
void pipecmd_setenv (pipecmd *cmd, const char *name, const char *value);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Unset an environment variable while running this command. */
|
|
Packit |
eba2e2 |
void pipecmd_unsetenv (pipecmd *cmd, const char *name);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Clear the environment while running this command. (Note that environment
|
|
Packit |
eba2e2 |
* operations work in sequence; pipecmd_clearenv followed by pipecmd_setenv
|
|
Packit |
eba2e2 |
* causes the command to have just a single environment variable set.)
|
|
Packit |
eba2e2 |
* Beware that this may cause unexpected failures, for example if some of
|
|
Packit |
eba2e2 |
* the contents of the environment are necessary to execute programs at all
|
|
Packit |
eba2e2 |
* (say, PATH).
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipecmd_clearenv (pipecmd *cmd);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Install a pre-exec handler. This will be run immediately before
|
|
Packit |
eba2e2 |
* executing the command's payload (process or function). Pass NULL to
|
|
Packit |
eba2e2 |
* clear any existing pre-exec handler. The data argument is passed as the
|
|
Packit |
eba2e2 |
* function's only argument, and will be freed before returning using
|
|
Packit |
eba2e2 |
* free_func (if non-NULL).
|
|
Packit |
eba2e2 |
*
|
|
Packit |
eba2e2 |
* This is similar to pipeline_install_post_fork, except that is specific to
|
|
Packit |
eba2e2 |
* a single command rather than installing a global handler, and it runs
|
|
Packit |
eba2e2 |
* slightly later (immediately before exec rather than immediately after
|
|
Packit |
eba2e2 |
* fork).
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipecmd_pre_exec (pipecmd *cmd,
|
|
Packit |
eba2e2 |
pipecmd_function_type *func,
|
|
Packit |
eba2e2 |
pipecmd_function_free_type *free_func,
|
|
Packit |
eba2e2 |
void *data);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Add a command to a sequence. */
|
|
Packit |
eba2e2 |
void pipecmd_sequence_command (pipecmd *cmd, pipecmd *child);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Dump a string representation of a command to stream. */
|
|
Packit |
eba2e2 |
void pipecmd_dump (pipecmd *cmd, FILE *stream);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Return a string representation of a command. The caller should free the
|
|
Packit |
eba2e2 |
* result.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
char *pipecmd_tostring (pipecmd *cmd);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Execute a single command, replacing the current process. Never returns,
|
|
Packit |
eba2e2 |
* instead exiting non-zero on failure.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipecmd_exec (pipecmd *cmd) PIPELINE_ATTR_NORETURN;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Destroy a command. Safely does nothing on NULL. */
|
|
Packit |
eba2e2 |
void pipecmd_free (pipecmd *cmd);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* ---------------------------------------------------------------------- */
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Functions to build pipelines. */
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Construct a new pipeline. */
|
|
Packit |
eba2e2 |
pipeline *pipeline_new (void);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Convenience constructors wrapping pipeline_new() and pipeline_command().
|
|
Packit |
eba2e2 |
* Terminate commands with NULL.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
pipeline *pipeline_new_commandv (pipecmd *cmd1, va_list cmdv);
|
|
Packit |
eba2e2 |
pipeline *pipeline_new_commands (pipecmd *cmd1, ...) PIPELINE_ATTR_SENTINEL;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Construct a new pipeline and add a single command to it. */
|
|
Packit |
eba2e2 |
pipeline *pipeline_new_command_argv (const char *name, va_list argv);
|
|
Packit |
eba2e2 |
pipeline *pipeline_new_command_args (const char *name, ...)
|
|
Packit |
eba2e2 |
PIPELINE_ATTR_SENTINEL;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Joins two pipelines, neither of which are allowed to be started. Discards
|
|
Packit |
eba2e2 |
* want_out, want_outfile, and outfd from p1, and want_in, want_infile, and
|
|
Packit |
eba2e2 |
* infd from p2.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
pipeline *pipeline_join (pipeline *p1, pipeline *p2);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Connect the input of one or more sink pipelines to the output of a source
|
|
Packit |
eba2e2 |
* pipeline. The source pipeline may be started, but in that case want_out
|
|
Packit |
eba2e2 |
* must be negative; otherwise, discards want_out from source. In any event,
|
|
Packit |
eba2e2 |
* discards want_in from all sinks, none of which are allowed to be started.
|
|
Packit |
eba2e2 |
* Terminate arguments with NULL.
|
|
Packit |
eba2e2 |
*
|
|
Packit |
eba2e2 |
* This is an application-level connection; data may be intercepted between
|
|
Packit |
eba2e2 |
* the pipelines by the program before calling pipeline_pump(), which sets
|
|
Packit |
eba2e2 |
* data flowing from the source to the sinks. It is primarily useful when
|
|
Packit |
eba2e2 |
* more than one sink pipeline is involved, in which case the pipelines
|
|
Packit |
eba2e2 |
* cannot simply be concatenated into one.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipeline_connect (pipeline *source, pipeline *sink, ...)
|
|
Packit |
eba2e2 |
PIPELINE_ATTR_SENTINEL;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Add a command to a pipeline. */
|
|
Packit |
eba2e2 |
void pipeline_command (pipeline *p, pipecmd *cmd);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Construct a new command and add it to a pipeline in one go. */
|
|
Packit |
eba2e2 |
void pipeline_command_argv (pipeline *p, const char *name, va_list argv);
|
|
Packit |
eba2e2 |
void pipeline_command_args (pipeline *p, const char *name, ...)
|
|
Packit |
eba2e2 |
PIPELINE_ATTR_SENTINEL;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Construct a new command from a shell-quoted string and add it to a
|
|
Packit |
eba2e2 |
* pipeline in one go. See the comment against pipecmd_new_argstr() above if
|
|
Packit |
eba2e2 |
* you're tempted to use this function.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipeline_command_argstr (pipeline *p, const char *argstr);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Convenience functions wrapping pipeline_command().
|
|
Packit |
eba2e2 |
* Terminate commands with NULL.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipeline_commandv (pipeline *p, va_list cmdv);
|
|
Packit |
eba2e2 |
void pipeline_commands (pipeline *p, ...) PIPELINE_ATTR_SENTINEL;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Return the number of commands in this pipeline. */
|
|
Packit |
eba2e2 |
int pipeline_get_ncommands (pipeline *p);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Return command number n from this pipeline, counting from zero, or NULL
|
|
Packit |
eba2e2 |
* if n is out of range.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
pipecmd *pipeline_get_command (pipeline *p, int n);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Set command number n in this pipeline, counting from zero, to cmd, and
|
|
Packit |
eba2e2 |
* return the previous command in that position. Do nothing and return NULL
|
|
Packit |
eba2e2 |
* if n is out of range.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
pipecmd *pipeline_set_command (pipeline *p, int n, pipecmd *cmd);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Return the process ID of command number n from this pipeline, counting
|
|
Packit |
eba2e2 |
* from zero. The pipeline must be started. Return -1 if n is out of range
|
|
Packit |
eba2e2 |
* or if the command has already exited and been reaped.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
pid_t pipeline_get_pid (pipeline *p, int n);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Set file descriptors to use as the input and output of the whole
|
|
Packit |
eba2e2 |
* pipeline. If non-negative, fd is used directly as a file descriptor. If
|
|
Packit |
eba2e2 |
* negative, pipeline_start will create pipes and store the input writing
|
|
Packit |
eba2e2 |
* half and the output reading half in the pipeline's infd or outfd field as
|
|
Packit |
eba2e2 |
* appropriate. The default is to leave input and output as stdin and
|
|
Packit |
eba2e2 |
* stdout unless pipeline_want_infile or pipeline_want_outfile respectively
|
|
Packit |
eba2e2 |
* has been called.
|
|
Packit |
eba2e2 |
*
|
|
Packit |
eba2e2 |
* Calling these functions supersedes any previous call to
|
|
Packit |
eba2e2 |
* pipeline_want_infile or pipeline_want_outfile respectively.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipeline_want_in (pipeline *p, int fd);
|
|
Packit |
eba2e2 |
void pipeline_want_out (pipeline *p, int fd);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Set file names to open and use as the input and output of the whole
|
|
Packit |
eba2e2 |
* pipeline. This may be more convenient than supplying file descriptors,
|
|
Packit |
eba2e2 |
* and guarantees that the files are opened with the same privileges under
|
|
Packit |
eba2e2 |
* which the pipeline is run.
|
|
Packit |
eba2e2 |
*
|
|
Packit |
eba2e2 |
* Calling these functions (even with NULL, which returns to the default of
|
|
Packit |
eba2e2 |
* leaving input and output as stdin and stdout) supersedes any previous
|
|
Packit |
eba2e2 |
* call to pipeline_want_in or pipeline_want_outfile respectively.
|
|
Packit |
eba2e2 |
*
|
|
Packit |
eba2e2 |
* The given files will be opened when the pipeline is started. If an
|
|
Packit |
eba2e2 |
* 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
|
|
Packit |
eba2e2 |
* truncated.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipeline_want_infile (pipeline *p, const char *file);
|
|
Packit |
eba2e2 |
void pipeline_want_outfile (pipeline *p, const char *file);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* If ignore_signals is non-zero (which is the default), ignore SIGINT and
|
|
Packit |
eba2e2 |
* SIGQUIT while the pipeline is running, like system(). Otherwise, leave
|
|
Packit |
eba2e2 |
* their dispositions unchanged.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipeline_ignore_signals (pipeline *p, int ignore_signals);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Get streams corresponding to infd and outfd respectively. The pipeline
|
|
Packit |
eba2e2 |
* must be started.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
FILE *pipeline_get_infile (pipeline *p);
|
|
Packit |
eba2e2 |
FILE *pipeline_get_outfile (pipeline *p);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Dump a string representation of p to stream. */
|
|
Packit |
eba2e2 |
void pipeline_dump (pipeline *p, FILE *stream);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Return a string representation of p. The caller should free the result. */
|
|
Packit |
eba2e2 |
char *pipeline_tostring (pipeline *p);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Destroy a pipeline and all its commands. Safely does nothing on NULL.
|
|
Packit |
eba2e2 |
* May wait for the pipeline to complete if it has not already done so.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipeline_free (pipeline *p);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* ---------------------------------------------------------------------- */
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Functions to run pipelines and handle signals. */
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
typedef void pipeline_post_fork_fn (void);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Install a post-fork handler. This will be run in any child process
|
|
Packit |
eba2e2 |
* immediately after it is forked. For instance, this may be used for
|
|
Packit |
eba2e2 |
* cleaning up application-specific signal handlers. Pass NULL to clear any
|
|
Packit |
eba2e2 |
* existing post-fork handler.
|
|
Packit |
eba2e2 |
*
|
|
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 |
*/
|
|
Packit |
eba2e2 |
void pipeline_install_post_fork (pipeline_post_fork_fn *fn);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Start the processes in a pipeline. Installs this library's SIGCHLD
|
|
Packit |
eba2e2 |
* handler if not already installed. Calls error(FATAL) on error. */
|
|
Packit |
eba2e2 |
void pipeline_start (pipeline *p);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Wait for a pipeline to complete. Set *statuses to a newly-allocated
|
|
Packit |
eba2e2 |
* array of wait statuses, as returned by waitpid, and *n_statuses to the
|
|
Packit |
eba2e2 |
* length of that array. The return value is similar to the exit status
|
|
Packit |
eba2e2 |
* that a shell would return, with some modifications. If the last command
|
|
Packit |
eba2e2 |
* exits with a signal (other than SIGPIPE, which is considered equivalent
|
|
Packit |
eba2e2 |
* to exiting zero), then the return value is 128 plus the signal number; if
|
|
Packit |
eba2e2 |
* the last command exits normally but non-zero, then the return value is
|
|
Packit |
eba2e2 |
* its exit status; if any other command exits non-zero, then the return
|
|
Packit |
eba2e2 |
* value is 127; otherwise, the return value is 0. This means that the
|
|
Packit |
eba2e2 |
* return value is only 0 if all commands in the pipeline exit successfully.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
int pipeline_wait_all (pipeline *p, int **statuses, int *n_statuses);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Wait for a pipeline to complete and return its combined exit status,
|
|
Packit |
eba2e2 |
* calculated as for pipeline_wait_all().
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
int pipeline_wait (pipeline *p);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Start a pipeline, wait for it to complete, and free it, all in one go. */
|
|
Packit |
eba2e2 |
int pipeline_run (pipeline *p);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Pump data among one or more pipelines connected using 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). All relevant pipelines must be
|
|
Packit |
eba2e2 |
* supplied: that is, no pipeline that has been connected to a source
|
|
Packit |
eba2e2 |
* pipeline may be supplied unless that source pipeline is also supplied.
|
|
Packit |
eba2e2 |
* Automatically starts all pipelines if they are not already started, but
|
|
Packit |
eba2e2 |
* does not wait for them. Terminate arguments with NULL.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipeline_pump (pipeline *p, ...) PIPELINE_ATTR_SENTINEL;
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* ---------------------------------------------------------------------- */
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Functions to read output from pipelines. */
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Read len bytes of data from the pipeline, returning the data block. len
|
|
Packit |
eba2e2 |
* is updated with the number of bytes read.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
const char *pipeline_read (pipeline *p, size_t *len);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Look ahead in the pipeline's output for len bytes of data, returning the
|
|
Packit |
eba2e2 |
* data block. len is updated with the number of bytes read. The starting
|
|
Packit |
eba2e2 |
* position of the next read or peek is not affected by this call.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
const char *pipeline_peek (pipeline *p, size_t *len);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Return the number of bytes of data that can be read using pipeline_read
|
|
Packit |
eba2e2 |
* or pipeline_peek solely from the peek cache, without having to read from
|
|
Packit |
eba2e2 |
* the pipeline itself (and thus potentially block).
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
size_t pipeline_peek_size (pipeline *p);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Skip over and discard len bytes of data from the peek cache. Asserts that
|
|
Packit |
eba2e2 |
* enough data is available to skip, so you may want to check using
|
|
Packit |
eba2e2 |
* pipeline_peek_size first.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
void pipeline_peek_skip (pipeline *p, size_t len);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Read a line of data from the pipeline, returning it. */
|
|
Packit |
eba2e2 |
const char *pipeline_readline (pipeline *p);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
/* Look ahead in the pipeline's output for a line of data, returning it. The
|
|
Packit |
eba2e2 |
* starting position of the next read or peek is not affected by this call.
|
|
Packit |
eba2e2 |
*/
|
|
Packit |
eba2e2 |
const char *pipeline_peekline (pipeline *p);
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
#ifdef __cplusplus
|
|
Packit |
eba2e2 |
}
|
|
Packit |
eba2e2 |
#endif
|
|
Packit |
eba2e2 |
|
|
Packit |
eba2e2 |
#endif /* PIPELINE_H */
|