/* Utilities to execute a program in a subprocess (possibly linked by pipes
   with other subprocesses), and wait for it.  Shared logic.
   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
   Free Software Foundation, Inc.

This file is part of the libiberty library.
Libiberty is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

Libiberty 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
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with libiberty; see the file COPYING.LIB.  If not,
write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
Boston, MA 02110-1301, USA.  */

#ifndef PEX_COMMON_H
#define PEX_COMMON_H

#include "config.h"
#include "libiberty.h"
#include <stdio.h>

/* pid_t is may defined by config.h or sys/types.h needs to be
   included.  */
#if !defined(pid_t) && defined(HAVE_SYS_TYPES_H)
#include <sys/types.h>
#endif

#define install_error_msg "installation problem, cannot exec `%s'"

/* stdin file number.  */
#define STDIN_FILE_NO 0

/* stdout file number.  */
#define STDOUT_FILE_NO 1

/* stderr file number.  */
#define STDERR_FILE_NO 2

/* value of `pipe': port index for reading.  */
#define READ_PORT 0

/* value of `pipe': port index for writing.  */
#define WRITE_PORT 1

/* The structure used by pex_init and friends.  */

struct pex_obj
{
  /* Flags.  */
  int flags;
  /* Name of calling program, for error messages.  */
  const char *pname;
  /* Base name to use for temporary files.  */
  const char *tempbase;
  /* Pipe to use as stdin for next process.  */
  int next_input;
  /* File name to use as stdin for next process.  */
  char *next_input_name;
  /* Whether next_input_name was allocated using malloc.  */
  int next_input_name_allocated;
  /* If not -1, stderr pipe from the last process.  */
  int stderr_pipe;
  /* Number of child processes.  */
  int count;
  /* PIDs of child processes; array allocated using malloc.  */
  pid_t *children;
  /* Exit statuses of child processes; array allocated using malloc.  */
  int *status;
  /* Time used by child processes; array allocated using malloc.  */
  struct pex_time *time;
  /* Number of children we have already waited for.  */
  int number_waited;
  /* FILE created by pex_input_file.  */
  FILE *input_file;
  /* FILE created by pex_read_output.  */
  FILE *read_output;
  /* FILE created by pex_read_err.  */
  FILE *read_err;
  /* Number of temporary files to remove.  */
  int remove_count;
  /* List of temporary files to remove; array allocated using malloc
     of strings allocated using malloc.  */
  char **remove;
  /* Pointers to system dependent functions.  */
  const struct pex_funcs *funcs;
  /* For use by system dependent code.  */
  void *sysdep;
};

/* Functions passed to pex_run_common.  */

struct pex_funcs
{
  /* Open file NAME for reading.  If BINARY is non-zero, open in
     binary mode.  Return >= 0 on success, -1 on error.  */
  int (*open_read) (struct pex_obj *, const char */* name */, int /* binary */);
  /* Open file NAME for writing.  If BINARY is non-zero, open in
     binary mode.  Return >= 0 on success, -1 on error.  */
  int (*open_write) (struct pex_obj *, const char */* name */,
                     int /* binary */, int /* append */);
  /* Execute a child process.  FLAGS, EXECUTABLE, ARGV, ERR are from
     pex_run.  IN, OUT, ERRDES, TOCLOSE are all descriptors, from
     open_read, open_write, or pipe, or they are one of STDIN_FILE_NO,
     STDOUT_FILE_NO or STDERR_FILE_NO; if IN, OUT, and ERRDES are not
     STD*_FILE_NO, they should be closed.  If the descriptor TOCLOSE
     is not -1, and the system supports pipes, TOCLOSE should be
     closed in the child process.  The function should handle the
     PEX_STDERR_TO_STDOUT flag.  Return >= 0 on success, or -1 on
     error and set *ERRMSG and *ERR.  */
  pid_t (*exec_child) (struct pex_obj *, int /* flags */,
                      const char */* executable */, char * const * /* argv */,
                      char * const * /* env */,
                      int /* in */, int /* out */, int /* errdes */,
		      int /* toclose */, const char **/* errmsg */,
		      int */* err */);
  /* Close a descriptor.  Return 0 on success, -1 on error.  */
  int (*close) (struct pex_obj *, int);
  /* Wait for a child to complete, returning exit status in *STATUS
     and time in *TIME (if it is not null).  CHILD is from fork.  DONE
     is 1 if this is called via pex_free.  ERRMSG and ERR are as in
     fork.  Return 0 on success, -1 on error.  */
  pid_t (*wait) (struct pex_obj *, pid_t /* child */, int * /* status */,
               struct pex_time * /* time */, int /* done */,
               const char ** /* errmsg */, int * /* err */);
  /* Create a pipe (only called if PEX_USE_PIPES is set) storing two
     descriptors in P[0] and P[1].  If BINARY is non-zero, open in
     binary mode.  Return 0 on success, -1 on error.  */
  int (*pipe) (struct pex_obj *, int * /* p */, int /* binary */);
  /* Get a FILE pointer to read from a file descriptor (only called if
     PEX_USE_PIPES is set).  If BINARY is non-zero, open in binary
     mode.  Return pointer on success, NULL on error.  */
  FILE * (*fdopenr) (struct pex_obj *, int /* fd */, int /* binary */);
  /* Get a FILE pointer to write to the file descriptor FD (only
     called if PEX_USE_PIPES is set).  If BINARY is non-zero, open in
     binary mode.  Arrange for FD not to be inherited by the child
     processes.  Return pointer on success, NULL on error.  */
  FILE * (*fdopenw) (struct pex_obj *, int /* fd */, int /* binary */);
  /* Free any system dependent data associated with OBJ.  May be
     NULL if there is nothing to do.  */
  void (*cleanup) (struct pex_obj *);
};

extern struct pex_obj *pex_init_common (int, const char *, const char *,
					const struct pex_funcs *);

#endif
