aboutsummaryrefslogtreecommitdiff
path: root/gnu/libexec/uucp/libunix/iswait.c
diff options
context:
space:
mode:
authorsvn2git <svn2git@FreeBSD.org>1994-05-01 08:00:00 +0000
committersvn2git <svn2git@FreeBSD.org>1994-05-01 08:00:00 +0000
commita16f65c7d117419bd266c28a1901ef129a337569 (patch)
tree2626602f66dc3551e7a7c7bc9ad763c3bc7ab40a /gnu/libexec/uucp/libunix/iswait.c
parent8503f4f13f77abf7adc8f7e329c6f9c1d52b6a20 (diff)
Diffstat (limited to 'gnu/libexec/uucp/libunix/iswait.c')
-rw-r--r--gnu/libexec/uucp/libunix/iswait.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/gnu/libexec/uucp/libunix/iswait.c b/gnu/libexec/uucp/libunix/iswait.c
new file mode 100644
index 000000000000..d2610aa1f8bd
--- /dev/null
+++ b/gnu/libexec/uucp/libunix/iswait.c
@@ -0,0 +1,159 @@
+/* iswait.c
+ Wait for a process to finish.
+
+ Copyright (C) 1992 Ian Lance Taylor
+
+ This file is part of the Taylor UUCP package.
+
+ 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 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author of the program may be contacted at ian@airs.com or
+ c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ */
+
+#include "uucp.h"
+
+#include "uudefs.h"
+#include "sysdep.h"
+
+#include <errno.h>
+
+#if HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+/* We use a typedef wait_status for wait (waitpid, wait4) to put
+ results into. We define the POSIX examination functions we need if
+ they are not already defined (if they aren't defined, I assume that
+ we have a standard wait status). */
+
+#if HAVE_UNION_WAIT
+typedef union wait wait_status;
+#ifndef WIFEXITED
+#define WIFEXITED(u) ((u).w_termsig == 0)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(u) ((u).w_retcode)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(u) ((u).w_termsig)
+#endif
+#else /* ! HAVE_UNION_WAIT */
+typedef int wait_status;
+#ifndef WIFEXITED
+#define WIFEXITED(i) (((i) & 0xff) == 0)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(i) (((i) >> 8) & 0xff)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(i) ((i) & 0x7f)
+#endif
+#endif /* ! HAVE_UNION_WAIT */
+
+/* Wait for a particular process to finish. The ipid argument should
+ be pid_t, but then we couldn't have a prototype. If the zreport
+ argument is not NULL, then a wait error will be logged, and if the
+ exit status is non-zero it will be logged with zreport as the
+ header of the log message. If the zreport argument is NULL, no
+ errors will be logged. This function returns the exit status if
+ the process exited normally, or -1 on error or if the process was
+ killed by a signal (I don't just always return the exit status
+ because then the calling code would have to prepared to handle
+ union wait status vs. int status, and none of the callers care
+ which signal killed the program anyhow).
+
+ This functions keeps waiting until the process finished, even if it
+ is interrupted by a signal. I think this is right for all uses.
+ The controversial one would be when called from uuxqt to wait for a
+ requested process. Hitting uuxqt with SIGKILL will approximate the
+ actions taken if we return from here with an error anyhow. If we
+ do get a signal, we call ulog with a NULL argument to get it in the
+ log file at about the right time. */
+
+int
+ixswait (ipid, zreport)
+ unsigned long ipid;
+ const char *zreport;
+{
+ wait_status istat;
+
+#if HAVE_WAITPID
+ while (waitpid ((pid_t) ipid, (pointer) &istat, 0) < 0)
+ {
+ if (errno != EINTR)
+ {
+ if (zreport != NULL)
+ ulog (LOG_ERROR, "waitpid: %s", strerror (errno));
+ return -1;
+ }
+ ulog (LOG_ERROR, (const char *) NULL);
+ }
+#else /* ! HAVE_WAITPID */
+#if HAVE_WAIT4
+ while (wait4 ((pid_t) ipid, (pointer) &istat, 0,
+ (struct rusage *) NULL) < 0)
+ {
+ if (errno != EINTR)
+ {
+ if (zreport != NULL)
+ ulog (LOG_ERROR, "wait4: %s", strerror (errno));
+ return -1;
+ }
+ ulog (LOG_ERROR, (const char *) NULL);
+ }
+#else /* ! HAVE_WAIT4 */
+ pid_t igot;
+
+ /* We could theoretically get the wrong child here if we're in some
+ kind of weird pipeline, so we don't give any error messages for
+ it. */
+ while ((igot = wait ((pointer) &istat)) != (pid_t) ipid)
+ {
+ if (igot < 0)
+ {
+ if (errno != EINTR)
+ {
+ if (zreport != NULL)
+ ulog (LOG_ERROR, "wait: %s", strerror (errno));
+ return -1;
+ }
+ ulog (LOG_ERROR, (const char *) NULL);
+ }
+ }
+#endif /* ! HAVE_WAIT4 */
+#endif /* ! HAVE_WAITPID */
+
+ DEBUG_MESSAGE2 (DEBUG_EXECUTE, "%s %d",
+ WIFEXITED (istat) ? "Exit status" : "Signal",
+ WIFEXITED (istat) ? WEXITSTATUS (istat) : WTERMSIG (istat));
+
+ if (WIFEXITED (istat) && WEXITSTATUS (istat) == 0)
+ return 0;
+
+ if (zreport != NULL)
+ {
+ if (! WIFEXITED (istat))
+ ulog (LOG_ERROR, "%s: Got signal %d", zreport, WTERMSIG (istat));
+ else
+ ulog (LOG_ERROR, "%s: Exit status %d", zreport,
+ WEXITSTATUS (istat));
+ }
+
+ if (WIFEXITED (istat))
+ return WEXITSTATUS (istat);
+ else
+ return -1;
+}