(root)/
gettext-0.22.4/
gettext-tools/
gnulib-lib/
pipe-filter.h
       1  /* Filtering of data through a subprocess.  -*- coding: utf-8 -*-
       2     Copyright (C) 2009-2023 Free Software Foundation, Inc.
       3     Written by Bruno Haible <haible@clisp.cons.org>, 2009,
       4     and Paolo Bonzini <bonzini@gnu.org>, 2009.
       5  
       6     This program is free software: you can redistribute it and/or modify
       7     it under the terms of the GNU General Public License as published by
       8     the Free Software Foundation, either version 3 of the License, or
       9     (at your option) any later version.
      10  
      11     This program is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14     GNU General Public License for more details.
      15  
      16     You should have received a copy of the GNU General Public License
      17     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef _PIPE_FILTER_H
      20  #define _PIPE_FILTER_H
      21  
      22  /* This file uses _GL_ATTRIBUTE_DEALLOC.  */
      23  #if !_GL_CONFIG_H_INCLUDED
      24   #error "Please include config.h first."
      25  #endif
      26  
      27  #include <stddef.h>
      28  
      29  #ifdef __cplusplus
      30  extern "C" {
      31  #endif
      32  
      33  
      34  /* Piping data through a subprocess in the naïve way - write data to the
      35     subprocess and read from the subprocess when you expect it to have
      36     produced results - is subject to two kinds of deadlocks:
      37     1) If you write more than PIPE_MAX bytes or, more generally, if you write
      38        more bytes than the subprocess can handle at once, the subprocess
      39        may write its data and wait on you to read it, but you are currently
      40        busy writing.
      41     2) When you don't know ahead of time how many bytes the subprocess
      42        will produce, the usual technique of calling read (fd, buf, BUFSIZ)
      43        with a fixed BUFSIZ will, on Linux 2.2.17 and on BSD systems, cause
      44        the read() call to block until *all* of the buffer has been filled.
      45        But the subprocess cannot produce more data until you gave it more
      46        input.  But you are currently busy reading from it.
      47  
      48     This header file declares four set of functions that pipes data through
      49     the subprocess, without risking these deadlocks.
      50  
      51     The side that writes data to the subprocess can be seen as a "generator",
      52     that is, as a subroutine that produces and writes a piece of data here and
      53     there, see <https://en.wikipedia.org/wiki/Generator_(computer_science)>.
      54     But often, it can be written in the form of an "iterator", that is, as a
      55     function that, each time it is invoked, produces and writes one more piece
      56     of data.
      57  
      58     Similarly, the side that reads data from the subprocess can be seen as
      59     a "generator", that is, as a subroutine that consumes a piece of data here
      60     and there.  Often, it can be written in the form of an "iterator", that
      61     is, as a function that, each time it is invoked, consumes one more piece
      62     of data.
      63  
      64     This header file declares four set of functions:
      65  
      66                         |   writer   |   reader   |
      67         ----------------+------------+------------+
      68         pipe_filter_ii  |  iterator  |  iterator  |
      69         pipe_filter_ig  |  iterator  |  generator |
      70         pipe_filter_gi  |  generator |  iterator  |
      71         pipe_filter_gg  |  generator |  generator |
      72         ----------------+------------+------------+
      73  
      74     The last one uses threads in order to implement two generators running at
      75     the same time.  (For the relation between generators, coroutines, and
      76     threads, see <https://en.wikipedia.org/wiki/Generator_(computer_science)>
      77     and <https://en.wikipedia.org/wiki/Coroutine>.)  It is therefore only
      78     portable to platforms with kernel-based POSIX threads.  */
      79  
      80  /* These two functions together describe the side that writes data to the
      81     subprocess when it has the form of an iterator.
      82     - prepare_write (&num_bytes, p) must either return a pointer to data that
      83       is ready to be written and set num_bytes to the number of bytes ready to
      84       be written, or return NULL when no more bytes are to be written.
      85     - done_write (data_written, num_bytes_written) is called after
      86       num_bytes_written bytes were written.  It is guaranteed that
      87       num_bytes_written > 0.
      88     Here p is always the private_data argument passed to the main function.  */
      89  typedef const void * (*prepare_write_fn) (size_t *num_bytes_p,
      90                                            void *private_data);
      91  typedef void (*done_write_fn) (void *data_written, size_t num_bytes_written,
      92                                 void *private_data);
      93  
      94  /* These two functions together describe the side that reads data from the
      95     subprocess when it has the form of an iterator.
      96     - prepare_read (&num_bytes, p) must return a pointer to a buffer for data
      97       that can be read and set num_bytes to the size of that buffer
      98       (must be > 0).
      99     - done_read (data_read, num_bytes_read, p) is called after num_bytes_read
     100       bytes were read into the buffer.
     101     Here p is always the private_data argument passed to the main function.  */
     102  typedef void * (*prepare_read_fn) (size_t *num_bytes_p,
     103                                     void *private_data);
     104  typedef void (*done_read_fn) (void *data_read, size_t num_bytes_read,
     105                                void *private_data);
     106  
     107  
     108  /* ============================ pipe_filter_ii ============================ */
     109  
     110  /* Create a subprocess and pipe some data through it.
     111     Arguments:
     112     - progname is the program name used in error messages.
     113     - prog_path is the file name of the program to invoke.
     114     - prog_argv is a NULL terminated argument list, starting with prog_path as
     115       first element.
     116     - If null_stderr is true, the subprocess' stderr will be redirected to
     117       /dev/null, and the usual error message to stderr will be omitted.
     118       This is suitable when the subprocess does not fulfill an important task.
     119     - If exit_on_error is true, any error will cause the main process to exit
     120       with an error status.
     121     If the subprocess does not terminate correctly, exit if exit_on_error is
     122     true, otherwise return 127.
     123     Callback arguments are as described above.
     124  
     125     Data is alternately written to the subprocess, through the functions
     126     prepare_write and done_write, and read from the subprocess, through the
     127     functions prepare_read and done_read.
     128  
     129     Note that the prepare_write/done_write functions and the
     130     prepare_read/done_read functions may be called in different threads than
     131     the current thread (depending on the platform).  But they will not be
     132     called after the pipe_filter_ii_execute function has returned.
     133  
     134     Return 0 upon success, or (only if exit_on_error is false):
     135     - -1 with errno set upon failure,
     136     - the positive exit code of the subprocess if that failed.  */
     137  extern int
     138         pipe_filter_ii_execute (const char *progname,
     139                                 const char *prog_path,
     140                                 const char * const *prog_argv,
     141                                 bool null_stderr, bool exit_on_error,
     142                                 prepare_write_fn prepare_write,
     143                                 done_write_fn done_write,
     144                                 prepare_read_fn prepare_read,
     145                                 done_read_fn done_read,
     146                                 void *private_data);
     147  
     148  
     149  /* ============================ pipe_filter_ig ============================ */
     150  
     151  struct pipe_filter_ig;
     152  
     153  
     154  /* ============================ pipe_filter_gi ============================ */
     155  
     156  struct pipe_filter_gi;
     157  
     158  /* Finish reading the output via the prepare_read/done_read functions
     159     specified to pipe_filter_gi_create.
     160  
     161     Note that the prepare_read/done_read functions may be called in a
     162     different thread than the current thread (depending on the platform).
     163     However, they will always be called before pipe_filter_gi_close has
     164     returned.
     165  
     166     The write side of the pipe is closed as soon as pipe_filter_gi_close
     167     starts, while the read side will be closed just before it finishes.
     168  
     169     Return 0 upon success, or (only if exit_on_error is false):
     170     - -1 with errno set upon failure,
     171     - the positive exit code of the subprocess if that failed.  */
     172  extern int
     173         pipe_filter_gi_close (struct pipe_filter_gi *filter);
     174  
     175  /* Create a subprocess and pipe some data through it.
     176     Arguments:
     177     - progname is the program name used in error messages.
     178     - prog_path is the file name of the program to invoke.
     179     - prog_argv is a NULL terminated argument list, starting with
     180       prog_path as first element.
     181     - If null_stderr is true, the subprocess' stderr will be redirected
     182       to /dev/null, and the usual error message to stderr will be
     183       omitted.  This is suitable when the subprocess does not fulfill an
     184       important task.
     185     - If exit_on_error is true, any error will cause the main process to
     186       exit with an error status.
     187     If the subprocess does not start correctly, exit if exit_on_error is
     188     true, otherwise return NULL and set errno.
     189  
     190     The caller will write to the subprocess through pipe_filter_gi_write
     191     and finally call pipe_filter_gi_close.  During such calls, the
     192     prepare_read and done_read function may be called to process any data
     193     that the subprocess has written.
     194  
     195     Note that the prepare_read/done_read functions may be called in a
     196     different thread than the current thread (depending on the platform).
     197     But they will not be called after the pipe_filter_gi_close function has
     198     returned.
     199  
     200     Return the freshly created 'struct pipe_filter_gi'.  */
     201  extern struct pipe_filter_gi *
     202         pipe_filter_gi_create (const char *progname,
     203                                const char *prog_path,
     204                                const char * const *prog_argv,
     205                                bool null_stderr, bool exit_on_error,
     206                                prepare_read_fn prepare_read,
     207                                done_read_fn done_read,
     208                                void *private_data)
     209    _GL_ATTRIBUTE_DEALLOC (pipe_filter_gi_close, 1);
     210  
     211  /* Write size bytes starting at buf into the pipe and in the meanwhile
     212     possibly call the prepare_read and done_read functions specified to
     213     pipe_filter_gi_create.
     214  
     215     Note that the prepare_read/done_read functions may be called in a
     216     different thread than the current thread (depending on the platform).
     217     However, they will always be called before pipe_filter_gi_write has
     218     returned, or otherwise not sooner than the next call to
     219     pipe_filter_gi_write or pipe_filter_gi_close.
     220  
     221     Return only after all the entire buffer has been written to the pipe or
     222     the subprocess has exited.
     223  
     224     Return 0 upon success, or (only if exit_on_error is false):
     225     - -1 with errno set upon failure,
     226     - the positive exit code of the subprocess if that failed.  */
     227  extern int
     228         pipe_filter_gi_write (struct pipe_filter_gi *filter,
     229                               const void *buf, size_t size);
     230  
     231  
     232  /* ============================ pipe_filter_gg ============================ */
     233  
     234  
     235  /* ======================================================================== */
     236  
     237  
     238  #ifdef __cplusplus
     239  }
     240  #endif
     241  
     242  
     243  #endif /* _PIPE_FILTER_H */