/* Filtering of data through a subprocess.
Copyright (C) 2009 Free Software Foundation, Inc.
Written by Bruno Haible
, 2009.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#ifndef _PIPE_FILTER_H
#define _PIPE_FILTER_H
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/* Piping data through a subprocess in the naïve way - write data to the
subprocess and read from the subprocess when you expect it to have
produced results - is subject to two kinds of deadlocks:
1) If you write more than PIPE_MAX bytes or, more generally, if you write
more bytes than the subprocess can handle at once, the subprocess
may write its data and wait on you to read it, but you are currently
busy writing.
2) When you don't know ahead of time how many bytes the subprocess
will produce, the usual technique of calling read (fd, buf, BUFSIZ)
with a fixed BUFSIZ will, on Linux 2.2.17 and on BSD systems, cause
the read() call to block until *all* of the buffer has been filled.
But the subprocess cannot produce more data until you gave it more
input. But you are currently busy reading from it.
This module provides a function that pipes data to a subprocess and
gets its output back via a callback, without risking these deadlocks. */
typedef void (*done_read_fn) (char *read_buf, size_t num_bytes_read,
void *private_data);
struct filter;
/* Create a subprocess and pipe some data through it.
progname is the program name used in error messages.
prog_path is the file name of the program to invoke.
prog_argv is a NULL terminated argument list, starting with
prog_path as first element.
If null_stderr is true, the subprocess' stderr will be redirected
to /dev/null, and the usual error message to stderr will be
omitted. This is suitable when the subprocess does not fulfill an
important task.
If exit_on_error is true, any error will cause the main process to
exit with an error status.
If the subprocess does not start correctly, exit if exit_on_error is
true, otherwise return NULL and set errno.
The caller will write to the subprocess through filter_write; during
calls to filter_write, the done_read function may be called to
process any data that the subprocess has written. done_read will
receive at most read_bufsize bytes stored into buf, as well as a
copy of private_data. */
extern struct filter * filter_create (const char *progname,
const char *prog_path,
const char **prog_argv,
bool null_stderr, bool exit_on_error,
char *read_buf, size_t read_bufsize,
done_read_fn done_read,
void *private_data);
/* Write size bytes starting at buf into the pipe and in the meanwhile
possibly call the done_read function specified in create_filter.
The done_read function may be called in a different thread than
the current thread, depending on the platform. However, it will
always be called before filter_write has returned (or else will be
delayed to the next call to filter_write or filter_close). Return
only after all the entire buffer has been written to the pipe or
the subprocess has exited.
If there is a problem reading or writing, return -1 and set errno.
If the subprocess exits early with nonzero status, return the status.
(In either case, filter_write will instead exit if exit_on_error was
passed as true).
If the subprocess exits early with zero status, subsequent writes
will becomes no-ops and zero is returned.
Otherwise return 0. */
extern int filter_write (struct filter *f,
const char *buf, size_t size);
/* Finish reading the output via the done_read function specified in
create_filter. The done_read function may be called in a different
thread than. However, it will always be called before filter_close
has returned. The write side of the pipe is closed as soon as
filter_close starts, while the read side will be closed just before
it finishes. If there is a problem reading or closing the pipe,
return -1 and set errno. If the subprocess exits early with nonzero
status, return the status. (In either case, filter_close will
instead exit if exit_on_error was passed as true).
Otherwise return 0. */
extern int filter_close (struct filter *f);
#ifdef __cplusplus
}
#endif
#endif /* _PIPE_FILTER_H */