remove gcc34
[dragonfly.git] / crypto / heimdal-0.6.3 / lib / roken / simple_exec.c
1 /*
2  * Copyright (c) 1998 - 2001 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden). 
4  * All rights reserved. 
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met: 
9  *
10  * 1. Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer. 
12  *
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. 
16  *
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. 
20  *
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 
31  * SUCH DAMAGE. 
32  */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 RCSID("$Id: simple_exec.c,v 1.10 2001/06/21 03:38:03 assar Exp $");
37 #endif
38
39 #include <stdarg.h>
40 #include <stdlib.h>
41 #ifdef HAVE_SYS_TYPES_H
42 #include <sys/types.h>
43 #endif
44 #ifdef HAVE_SYS_WAIT_H
45 #include <sys/wait.h>
46 #endif
47 #ifdef HAVE_UNISTD_H
48 #include <unistd.h>
49 #endif
50 #include <errno.h>
51
52 #include <roken.h>
53
54 #define EX_NOEXEC       126
55 #define EX_NOTFOUND     127
56
57 /* return values:
58    -1   on `unspecified' system errors
59    -2   on fork failures
60    -3   on waitpid errors
61    0-   is return value from subprocess
62    126  if the program couldn't be executed
63    127  if the program couldn't be found
64    128- is 128 + signal that killed subprocess
65    */
66
67 int
68 wait_for_process(pid_t pid)
69 {
70     while(1) {
71         int status;
72
73         while(waitpid(pid, &status, 0) < 0)
74             if (errno != EINTR)
75                 return -3;
76         if(WIFSTOPPED(status))
77             continue;
78         if(WIFEXITED(status))
79             return WEXITSTATUS(status);
80         if(WIFSIGNALED(status))
81             return WTERMSIG(status) + 128;
82     }
83 }
84
85 int
86 pipe_execv(FILE **stdin_fd, FILE **stdout_fd, FILE **stderr_fd, 
87            const char *file, ...)
88 {
89     int in_fd[2], out_fd[2], err_fd[2];
90     pid_t pid;
91     va_list ap;
92     char **argv;
93
94     if(stdin_fd != NULL)
95         pipe(in_fd);
96     if(stdout_fd != NULL)
97         pipe(out_fd);
98     if(stderr_fd != NULL)
99         pipe(err_fd);
100     pid = fork();
101     switch(pid) {
102     case 0:
103         va_start(ap, file);
104         argv = vstrcollect(&ap);
105         va_end(ap);
106         if(argv == NULL)
107             exit(-1);
108
109         /* close pipes we're not interested in */
110         if(stdin_fd != NULL)
111             close(in_fd[1]);
112         if(stdout_fd != NULL)
113             close(out_fd[0]);
114         if(stderr_fd != NULL)
115             close(err_fd[0]);
116
117         /* pipe everything caller doesn't care about to /dev/null */
118         if(stdin_fd == NULL)
119             in_fd[0] = open(_PATH_DEVNULL, O_RDONLY);
120         if(stdout_fd == NULL)
121             out_fd[1] = open(_PATH_DEVNULL, O_WRONLY);
122         if(stderr_fd == NULL)
123             err_fd[1] = open(_PATH_DEVNULL, O_WRONLY);
124
125         /* move to proper descriptors */
126         if(in_fd[0] != STDIN_FILENO) {
127             dup2(in_fd[0], STDIN_FILENO);
128             close(in_fd[0]);
129         }
130         if(out_fd[1] != STDOUT_FILENO) {
131             dup2(out_fd[1], STDOUT_FILENO);
132             close(out_fd[1]);
133         }
134         if(err_fd[1] != STDERR_FILENO) {
135             dup2(err_fd[1], STDERR_FILENO);
136             close(err_fd[1]);
137         }
138
139         execv(file, argv);
140         exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
141     case -1:
142         if(stdin_fd != NULL) {
143             close(in_fd[0]);
144             close(in_fd[1]);
145         }
146         if(stdout_fd != NULL) {
147             close(out_fd[0]);
148             close(out_fd[1]);
149         }
150         if(stderr_fd != NULL) {
151             close(err_fd[0]);
152             close(err_fd[1]);
153         }
154         return -2;
155     default:
156         if(stdin_fd != NULL) {
157             close(in_fd[0]);
158             *stdin_fd = fdopen(in_fd[1], "w");
159         }
160         if(stdout_fd != NULL) {
161             close(out_fd[1]);
162             *stdout_fd = fdopen(out_fd[0], "r");
163         }
164         if(stderr_fd != NULL) {
165             close(err_fd[1]);
166             *stderr_fd = fdopen(err_fd[0], "r");
167         }
168     }
169     return pid;
170 }
171
172 int
173 simple_execvp(const char *file, char *const args[])
174 {
175     pid_t pid = fork();
176     switch(pid){
177     case -1:
178         return -2;
179     case 0:
180         execvp(file, args);
181         exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
182     default: 
183         return wait_for_process(pid);
184     }
185 }
186
187 /* gee, I'd like a execvpe */
188 int
189 simple_execve(const char *file, char *const args[], char *const envp[])
190 {
191     pid_t pid = fork();
192     switch(pid){
193     case -1:
194         return -2;
195     case 0:
196         execve(file, args, envp);
197         exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
198     default: 
199         return wait_for_process(pid);
200     }
201 }
202
203 int
204 simple_execlp(const char *file, ...)
205 {
206     va_list ap;
207     char **argv;
208     int ret;
209
210     va_start(ap, file);
211     argv = vstrcollect(&ap);
212     va_end(ap);
213     if(argv == NULL)
214         return -1;
215     ret = simple_execvp(file, argv);
216     free(argv);
217     return ret;
218 }
219
220 int
221 simple_execle(const char *file, ... /* ,char *const envp[] */)
222 {
223     va_list ap;
224     char **argv;
225     char *const* envp;
226     int ret;
227
228     va_start(ap, file);
229     argv = vstrcollect(&ap);
230     envp = va_arg(ap, char **);
231     va_end(ap);
232     if(argv == NULL)
233         return -1;
234     ret = simple_execve(file, argv, envp);
235     free(argv);
236     return ret;
237 }
238
239 int
240 simple_execl(const char *file, ...) 
241 {
242     va_list ap;
243     char **argv;
244     int ret;
245
246     va_start(ap, file);
247     argv = vstrcollect(&ap);
248     va_end(ap);
249     if(argv == NULL)
250         return -1;
251     ret = simple_execve(file, argv, environ);
252     free(argv);
253     return ret;
254 }