New module 'pipe-filter-ii'.
[gnulib.git] / lib / pipe-filter.h
diff --git a/lib/pipe-filter.h b/lib/pipe-filter.h
new file mode 100644 (file)
index 0000000..0918235
--- /dev/null
@@ -0,0 +1,237 @@
+/* Filtering of data through a subprocess.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+   Written by Bruno Haible <haible@clisp.cons.org>, 2009,
+   and Paolo Bonzini <bonzini@gnu.org>, 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 <http://www.gnu.org/licenses/>.  */
+
+#ifndef _PIPE_FILTER_H
+#define _PIPE_FILTER_H
+
+#include <stdbool.h>
+#include <stddef.h>
+
+
+#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 header file declares four set of functions that pipes data through
+   the subprocess, without risking these deadlocks.
+
+   The side that writes data to the subprocess can be seen as a "generator",
+   that is, as a subroutine that produces and writes a piece of data here and
+   there, see <http://en.wikipedia.org/wiki/Generator_(computer_science)>.
+   But often, it can be written in the form of an "iterator", that is, as a
+   function that, each time it is invoked, produces and writes one more piece
+   of data.
+
+   Similarly, the side that reads data from the subprocess can be seen as
+   a "generator", that is, as a subroutine that consumes a piece of data here
+   and there.  Often, it can be written in the form of an "iterator", that
+   is, as a function that, each time it is invoked, consumes one more piece
+   of data.
+
+   This header file declares four set of functions:
+
+                       |   writer   |   reader   |
+       ----------------+------------+------------+
+       pipe_filter_ii  |  iterator  |  iterator  |
+       pipe_filter_ig  |  iterator  |  generator |
+       pipe_filter_gi  |  generator |  iterator  |
+       pipe_filter_gg  |  generator |  generator |
+       ----------------+------------+------------+
+
+   The last one uses threads in order to implement two generators running at
+   the same time.  (For the relation between generators, coroutines, and
+   threads, see <http://en.wikipedia.org/wiki/Generator_(computer_science)>
+   and <http://en.wikipedia.org/wiki/Coroutine>.)  It is therefore only
+   portable to platforms with kernel-based POSIX threads.  */
+
+/* These two functions together describe the side that writes data to the
+   subprocess when it has the form of an iterator.
+   - prepare_write (&num_bytes, p) must either return a pointer to data that
+     is ready to be written and set num_bytes to the number of bytes ready to
+     be written, or return NULL when no more bytes are to be written.
+   - done_write (data_written, num_bytes_written) is called after
+     num_bytes_written bytes were written.  It is guaranteed that
+     num_bytes_written > 0.
+   Here p is always the private_data argument passed to the main function.  */
+typedef const void * (*prepare_write_fn) (size_t *num_bytes_p,
+                                         void *private_data);
+typedef void (*done_write_fn) (void *data_written, size_t num_bytes_written,
+                              void *private_data);
+
+/* These two functions together describe the side that reads data from the
+   subprocess when it has the form of an iterator.
+   - prepare_read (&num_bytes, p) must return a pointer to a buffer for data
+     that can be read and set num_bytes to the size of that buffer
+     (must be > 0).
+   - done_read (data_read, num_bytes_read, p) is called after num_bytes_read
+     bytes were read into the buffer.
+   Here p is always the private_data argument passed to the main function.  */
+typedef void * (*prepare_read_fn) (size_t *num_bytes_p,
+                                  void *private_data);
+typedef void (*done_read_fn) (void *data_read, size_t num_bytes_read,
+                             void *private_data);
+
+
+/* ============================ pipe_filter_ii ============================ */
+
+/* Create a subprocess and pipe some data through it.
+   Arguments:
+   - 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 terminate correctly, exit if exit_on_error is
+   true, otherwise return 127.
+   Callback arguments are as described above.
+
+   Data is alternatingly written to the subprocess, through the functions
+   prepare_write and done_write, and read from the subprocess, through the
+   functions prepare_read and done_read.
+
+   Note that the prepare_write/done_write functions and the
+   prepare_read/done_read functions may be called in different threads than
+   the current thread (depending on the platform).  But they will not be
+   called after the pipe_filter_ii_execute function has returned.
+
+   Return 0 upon success, or (only if exit_on_error is false):
+   - -1 with errno set upon failure,
+   - the positive exit code of the subprocess if that failed.  */
+extern int
+       pipe_filter_ii_execute (const char *progname,
+                              const char *prog_path, const char **prog_argv,
+                              bool null_stderr, bool exit_on_error,
+                              prepare_write_fn prepare_write,
+                              done_write_fn done_write,
+                              prepare_read_fn prepare_read,
+                              done_read_fn done_read,
+                              void *private_data);
+
+
+/* ============================ pipe_filter_ig ============================ */
+
+struct pipe_filter_ig;
+
+
+/* ============================ pipe_filter_gi ============================ */
+
+struct pipe_filter_gi;
+
+/* Create a subprocess and pipe some data through it.
+   Arguments:
+   - 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 pipe_filter_gi_write
+   and finally call pipe_filter_gi_write.  During such calls, the
+   prepare_read and done_read function may be called to process any data
+   that the subprocess has written.
+
+   Note that the prepare_read/done_read functions may be called in a
+   different thread than the current thread (depending on the platform).
+   But they will not be called after the pipe_filter_gi_close function has
+   returned.
+
+   Return the freshly created 'struct pipe_filter_gi'.  */
+extern struct pipe_filter_gi *
+       pipe_filter_gi_create (const char *progname,
+                             const char *prog_path, const char **prog_argv,
+                             bool null_stderr, bool exit_on_error,
+                             prepare_read_fn prepare_read,
+                             done_read_fn done_read,
+                             void *private_data);
+
+/* Write size bytes starting at buf into the pipe and in the meanwhile
+   possibly call the prepare_read and done_read functions specified to
+   pipe_filter_gi_create.
+
+   Note that the prepare_read/done_read functions may be called in a
+   different thread than the current thread (depending on the platform).
+   However, they will always be called before pipe_filter_gi_write has
+   returned, or otherwise not sooner than the next call to
+   pipe_filter_gi_write or pipe_filter_gi_close.
+
+   Return only after all the entire buffer has been written to the pipe or
+   the subprocess has exited.
+
+   Return 0 upon success, or (only if exit_on_error is false):
+   - -1 with errno set upon failure,
+   - the positive exit code of the subprocess if that failed.  */
+extern int
+       pipe_filter_gi_write (struct pipe_filter_gi *filter,
+                            const void *buf, size_t size);
+
+/* Finish reading the output via the prepare_read/done_read functions
+   specified to pipe_filter_gi_create.
+
+   Note that the prepare_read/done_read functions may be called in a
+   different thread than the current thread (depending on the platform).
+   However, they will always be called before pipe_filter_gi_close has
+   returned.
+
+   The write side of the pipe is closed as soon as pipe_filter_gi_close
+   starts, while the read side will be closed just before it finishes.
+
+   Return 0 upon success, or (only if exit_on_error is false):
+   - -1 with errno set upon failure,
+   - the positive exit code of the subprocess if that failed.  */
+extern int
+       pipe_filter_gi_close (struct pipe_filter_gi *filter);
+
+
+/* ============================ pipe_filter_gg ============================ */
+
+
+/* ======================================================================== */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _PIPE_FILTER_H */