2
* Copyright (c) 1998 - 2001, 2004 Kungliga Tekniska Högskolan
3
* (Royal Institute of Technology, Stockholm, Sweden).
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
17
* 3. Neither the name of the Institute nor the names of its contributors
18
* may be used to endorse or promote products derived from this software
19
* without specific prior written permission.
21
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41
#ifdef HAVE_SYS_TYPES_H
42
#include <sys/types.h>
44
#ifdef HAVE_SYS_WAIT_H
54
#if !HAVE_DECL_ENVIRON
55
extern char **environ;
59
#define EX_NOTFOUND 127
62
-1 on `unspecified' system errors
66
0- is return value from subprocess
67
126 if the program couldn't be executed
68
127 if the program couldn't be found
69
128- is 128 + signal that killed subprocess
71
possible values `func' can return:
72
((time_t)-2) exit loop w/o killing child and return
73
`exec timeout'/-4 from simple_exec
74
((time_t)-1) kill child with SIGTERM and wait for child to exit
76
n seconds to next timeout
88
int ROKEN_LIB_FUNCTION
89
wait_for_process_timed(pid_t pid, time_t (*func)(void *),
90
void *ptr, time_t timeout)
92
RETSIGTYPE (*old_func)(int sig) = NULL;
93
unsigned int oldtime = 0;
99
old_func = signal(SIGALRM, sigtimeout);
100
oldtime = alarm(timeout);
106
while(waitpid(pid, &status, 0) < 0) {
107
if (errno != EINTR) {
115
timeout = (*func)(ptr);
116
if (timeout == (time_t)-1) {
119
} else if (timeout == (time_t)-2) {
125
if(WIFSTOPPED(status))
127
if(WIFEXITED(status)) {
128
ret = WEXITSTATUS(status);
131
if(WIFSIGNALED(status)) {
132
ret = WTERMSIG(status) + 128;
138
signal(SIGALRM, old_func);
144
int ROKEN_LIB_FUNCTION
145
wait_for_process(pid_t pid)
147
return wait_for_process_timed(pid, NULL, NULL, 0);
150
int ROKEN_LIB_FUNCTION
151
pipe_execv(FILE **stdin_fd, FILE **stdout_fd, FILE **stderr_fd,
152
const char *file, ...)
154
int in_fd[2], out_fd[2], err_fd[2];
161
if(stdout_fd != NULL)
163
if(stderr_fd != NULL)
169
argv = vstrcollect(&ap);
174
/* close pipes we're not interested in */
177
if(stdout_fd != NULL)
179
if(stderr_fd != NULL)
182
/* pipe everything caller doesn't care about to /dev/null */
184
in_fd[0] = open(_PATH_DEVNULL, O_RDONLY);
185
if(stdout_fd == NULL)
186
out_fd[1] = open(_PATH_DEVNULL, O_WRONLY);
187
if(stderr_fd == NULL)
188
err_fd[1] = open(_PATH_DEVNULL, O_WRONLY);
190
/* move to proper descriptors */
191
if(in_fd[0] != STDIN_FILENO) {
192
dup2(in_fd[0], STDIN_FILENO);
195
if(out_fd[1] != STDOUT_FILENO) {
196
dup2(out_fd[1], STDOUT_FILENO);
199
if(err_fd[1] != STDERR_FILENO) {
200
dup2(err_fd[1], STDERR_FILENO);
207
exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
209
if(stdin_fd != NULL) {
213
if(stdout_fd != NULL) {
217
if(stderr_fd != NULL) {
223
if(stdin_fd != NULL) {
225
*stdin_fd = fdopen(in_fd[1], "w");
227
if(stdout_fd != NULL) {
229
*stdout_fd = fdopen(out_fd[0], "r");
231
if(stderr_fd != NULL) {
233
*stderr_fd = fdopen(err_fd[0], "r");
239
int ROKEN_LIB_FUNCTION
240
simple_execvp_timed(const char *file, char *const args[],
241
time_t (*func)(void *), void *ptr, time_t timeout)
249
exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
251
return wait_for_process_timed(pid, func, ptr, timeout);
255
int ROKEN_LIB_FUNCTION
256
simple_execvp(const char *file, char *const args[])
258
return simple_execvp_timed(file, args, NULL, NULL, 0);
261
/* gee, I'd like a execvpe */
262
int ROKEN_LIB_FUNCTION
263
simple_execve_timed(const char *file, char *const args[], char *const envp[],
264
time_t (*func)(void *), void *ptr, time_t timeout)
271
execve(file, args, envp);
272
exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
274
return wait_for_process_timed(pid, func, ptr, timeout);
278
int ROKEN_LIB_FUNCTION
279
simple_execve(const char *file, char *const args[], char *const envp[])
281
return simple_execve_timed(file, args, envp, NULL, NULL, 0);
284
int ROKEN_LIB_FUNCTION
285
simple_execlp(const char *file, ...)
292
argv = vstrcollect(&ap);
296
ret = simple_execvp(file, argv);
301
int ROKEN_LIB_FUNCTION
302
simple_execle(const char *file, ... /* ,char *const envp[] */)
310
argv = vstrcollect(&ap);
311
envp = va_arg(ap, char **);
315
ret = simple_execve(file, argv, envp);
320
int ROKEN_LIB_FUNCTION
321
simple_execl(const char *file, ...)
328
argv = vstrcollect(&ap);
332
ret = simple_execve(file, argv, environ);