|
|
1.1 root 1: /* iswait.c
2: Wait for a process to finish.
3:
4: Copyright (C) 1992 Ian Lance Taylor
5:
6: This file is part of the Taylor UUCP package.
7:
8: This program is free software; you can redistribute it and/or
9: modify it under the terms of the GNU General Public License as
10: published by the Free Software Foundation; either version 2 of the
11: License, or (at your option) any later version.
12:
13: This program is distributed in the hope that it will be useful, but
14: WITHOUT ANY WARRANTY; without even the implied warranty of
15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16: General Public License for more details.
17:
18: You should have received a copy of the GNU General Public License
19: along with this program; if not, write to the Free Software
20: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21:
22: The author of the program may be contacted at [email protected] or
23: c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
24: */
25:
26: #include "uucp.h"
27:
28: #include "uudefs.h"
29: #include "sysdep.h"
30:
31: #include <errno.h>
32:
33: #if HAVE_SYS_WAIT_H
34: #include <sys/wait.h>
35: #endif
36:
37: /* We use a typedef wait_status for wait (waitpid, wait4) to put
38: results into. We define the POSIX examination functions we need if
39: they are not already defined (if they aren't defined, I assume that
40: we have a standard wait status). */
41:
42: #if HAVE_UNION_WAIT
43: typedef union wait wait_status;
44: #ifndef WIFEXITED
45: #define WIFEXITED(u) ((u).w_termsig == 0)
46: #endif
47: #ifndef WEXITSTATUS
48: #define WEXITSTATUS(u) ((u).w_retcode)
49: #endif
50: #ifndef WTERMSIG
51: #define WTERMSIG(u) ((u).w_termsig)
52: #endif
53: #else /* ! HAVE_UNION_WAIT */
54: typedef int wait_status;
55: #ifndef WIFEXITED
56: #define WIFEXITED(i) (((i) & 0xff) == 0)
57: #endif
58: #ifndef WEXITSTATUS
59: #define WEXITSTATUS(i) (((i) >> 8) & 0xff)
60: #endif
61: #ifndef WTERMSIG
62: #define WTERMSIG(i) ((i) & 0x7f)
63: #endif
64: #endif /* ! HAVE_UNION_WAIT */
65:
66: /* Wait for a particular process to finish. The ipid argument should
67: be pid_t, but then we couldn't have a prototype. If the zreport
68: argument is not NULL, then a wait error will be logged, and if the
69: exit status is non-zero it will be logged with zreport as the
70: header of the log message. If the zreport argument is NULL, no
71: errors will be logged. This function returns the exit status if
72: the process exited normally, or -1 on error or if the process was
73: killed by a signal (I don't just always return the exit status
74: because then the calling code would have to prepared to handle
75: union wait status vs. int status, and none of the callers care
76: which signal killed the program anyhow).
77:
78: This functions keeps waiting until the process finished, even if it
79: is interrupted by a signal. I think this is right for all uses.
80: The controversial one would be when called from uuxqt to wait for a
81: requested process. Hitting uuxqt with SIGKILL will approximate the
82: actions taken if we return from here with an error anyhow. If we
83: do get a signal, we call ulog with a NULL argument to get it in the
84: log file at about the right time. */
85:
86: int
87: ixswait (ipid, zreport)
88: unsigned long ipid;
89: const char *zreport;
90: {
91: wait_status istat;
92:
93: #if HAVE_WAITPID
94: while (waitpid ((pid_t) ipid, (pointer) &istat, 0) < 0)
95: {
96: if (errno != EINTR)
97: {
98: if (zreport != NULL)
99: ulog (LOG_ERROR, "waitpid: %s", strerror (errno));
100: return -1;
101: }
102: ulog (LOG_ERROR, (const char *) NULL);
103: }
104: #else /* ! HAVE_WAITPID */
105: #if HAVE_WAIT4
106: while (wait4 ((pid_t) ipid, (pointer) &istat, 0,
107: (struct rusage *) NULL) < 0)
108: {
109: if (errno != EINTR)
110: {
111: if (zreport != NULL)
112: ulog (LOG_ERROR, "wait4: %s", strerror (errno));
113: return -1;
114: }
115: ulog (LOG_ERROR, (const char *) NULL);
116: }
117: #else /* ! HAVE_WAIT4 */
118: pid_t igot;
119:
120: /* We could theoretically get the wrong child here if we're in some
121: kind of weird pipeline, so we don't give any error messages for
122: it. */
123: while ((igot = wait ((pointer) &istat)) != (pid_t) ipid)
124: {
125: if (igot < 0)
126: {
127: if (errno != EINTR)
128: {
129: if (zreport != NULL)
130: ulog (LOG_ERROR, "wait: %s", strerror (errno));
131: return -1;
132: }
133: ulog (LOG_ERROR, (const char *) NULL);
134: }
135: }
136: #endif /* ! HAVE_WAIT4 */
137: #endif /* ! HAVE_WAITPID */
138:
139: DEBUG_MESSAGE2 (DEBUG_EXECUTE, "%s %d",
140: WIFEXITED (istat) ? "Exit status" : "Signal",
141: WIFEXITED (istat) ? WEXITSTATUS (istat) : WTERMSIG (istat));
142:
143: if (WIFEXITED (istat) && WEXITSTATUS (istat) == 0)
144: return 0;
145:
146: if (zreport != NULL)
147: {
148: if (! WIFEXITED (istat))
149: ulog (LOG_ERROR, "%s: Got signal %d", zreport, WTERMSIG (istat));
150: else
151: ulog (LOG_ERROR, "%s: Exit status %d", zreport,
152: WEXITSTATUS (istat));
153: }
154:
155: if (WIFEXITED (istat))
156: return WEXITSTATUS (istat);
157: else
158: return -1;
159: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.