bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug-gnulib] addition: wait-process.h, wait-process.c


From: Bruno Haible
Subject: [Bug-gnulib] addition: wait-process.h, wait-process.c
Date: Wed, 23 Apr 2003 22:08:27 +0200 (CEST)

Continuing the series of modules for executing programs. Here is
'wait-process - Waiting for a subprocess to finish.' Its intended use
is to be applied to the PID of a subprocess created by execute
(fork/exec) or pipe.

The main points of this code are:
  - to provide reasonable error messages,
  - to handle the return code 127 correctly (a convention specified
    in POSIX).

The mingw32 part is not finished, I'm currently working on it.

Any objections?

Bruno


========================= wait-process.h =========================
/* Waiting for a subprocess to finish.
   Copyright (C) 2001-2002 Free Software Foundation, Inc.
   Written by Bruno Haible <address@hidden>, 2001.

   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 2, 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, write to the Free Software Foundation,
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

#ifndef _WAIT_PROCESS_H
#define _WAIT_PROCESS_H

/* Get pid_t.  */
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>

#include <stdbool.h>

/* Wait for a subprocess to finish.  Return its exit code.
   If it didn't terminate correctly, exit if exit_on_error is true, otherwise
   return 127.  */
extern int wait_subprocess (pid_t child, const char *progname,
                            bool exit_on_error);

#endif /* _WAIT_PROCESS_H */
========================= wait-process.c =========================
/* Waiting for a subprocess to finish.
   Copyright (C) 2001-2003 Free Software Foundation, Inc.
   Written by Bruno Haible <address@hidden>, 2001.

   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 2, 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, write to the Free Software Foundation,
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */


#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

/* Specification.  */
#include "wait-process.h"

#include <errno.h>
#include <stdlib.h>

#include <sys/types.h>

#if defined _MSC_VER || defined __MINGW32__

/* Native Woe32 API.  */
#include <process.h>
#define waitpid(pid,statusp,options) _cwait (statusp, pid, WAIT_CHILD)
#define WAIT_T int
#define WTERMSIG(x) ((x) & 0xff) /* or: SIGABRT ?? */
#define WCOREDUMP(x) 0
#define WEXITSTATUS(x) (((x) >> 8) & 0xff) /* or: (x) ?? */
#define WIFSIGNALED(x) (WTERMSIG (x) != 0) /* or: ((x) == 3) ?? */
#define WIFEXITED(x) (WTERMSIG (x) == 0) /* or: ((x) != 3) ?? */
#define WIFSTOPPED(x) 0

#else

/* Unix API.  */
#include <sys/wait.h>
/* On Linux, WEXITSTATUS are bits 15..8 and WTERMSIG are bits 7..0, while
   BeOS uses the contrary.  Therefore we use the abstract macros.  */
#if HAVE_UNION_WAIT
# define WAIT_T union wait
# ifndef WTERMSIG
#  define WTERMSIG(x) ((x).w_termsig)
# endif
# ifndef WCOREDUMP
#  define WCOREDUMP(x) ((x).w_coredump)
# endif
# ifndef WEXITSTATUS
#  define WEXITSTATUS(x) ((x).w_retcode)
# endif
#else
# define WAIT_T int
# ifndef WTERMSIG
#  define WTERMSIG(x) ((x) & 0x7f)
# endif
# ifndef WCOREDUMP
#  define WCOREDUMP(x) ((x) & 0x80)
# endif
# ifndef WEXITSTATUS
#  define WEXITSTATUS(x) (((x) >> 8) & 0xff)
# endif
#endif
/* For valid x, exactly one of WIFSIGNALED(x), WIFEXITED(x), WIFSTOPPED(x)
   is true.  */
#ifndef WIFSIGNALED
# define WIFSIGNALED(x) (WTERMSIG (x) != 0 && WTERMSIG(x) != 0x7f)
#endif
#ifndef WIFEXITED
# define WIFEXITED(x) (WTERMSIG (x) == 0)
#endif
#ifndef WIFSTOPPED
# define WIFSTOPPED(x) (WTERMSIG (x) == 0x7f)
#endif
/* Note that portable applications may access
   WTERMSIG(x) only if WIFSIGNALED(x) is true, and
   WEXITSTATUS(x) only if WIFEXITED(x) is true.  */

#endif

#include "error.h"
#include "exit.h"
#include "gettext.h"

#define _(str) gettext (str)


int
wait_subprocess (pid_t child, const char *progname, bool exit_on_error)
{
  /* waitpid() is just as portable as wait() nowadays.  */
  WAIT_T status;

  *(int *) &status = 0;
  for (;;)
    {
      int result = waitpid (child, &status, 0);

      if (result != child)
        {
#ifdef EINTR
          if (errno == EINTR)
            continue;
#endif
#if 0 /* defined ECHILD */
          if (errno == ECHILD)
            {
              /* Child process nonexistent?! Assume it terminated
                 successfully.  */
              *(int *) &status = 0;
              break;
            }
#endif
          if (exit_on_error)
            error (EXIT_FAILURE, errno, _("%s subprocess"), progname);
          else
            return 127;
        }

      /* One of WIFSIGNALED (status), WIFEXITED (status), WIFSTOPPED (status)
         must always be true.  Loop until the program terminates.  */
      if (!WIFSTOPPED (status))
        break;
    }

  if (WIFSIGNALED (status))
    {
      if (exit_on_error)
        error (EXIT_FAILURE, 0, _("%s subprocess got fatal signal %d"),
               progname, (int) WTERMSIG (status));
      else
        return 127;
    }
  if (WEXITSTATUS (status) == 127)
    {
      if (exit_on_error)
        error (EXIT_FAILURE, 0, _("%s subprocess failed"), progname);
      else
        return 127;
    }
  return WEXITSTATUS (status);
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]