/* 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 */