1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23: #include "config.h"
24: #include "libiberty.h"
25: #include "pex-common.h"
26:
27: #include <stdio.h>
28: #include <signal.h>
29: #include <errno.h>
30: #ifdef NEED_DECLARATION_ERRNO
31: extern int errno;
32: #endif
33: #ifdef HAVE_STDLIB_H
34: #include <stdlib.h>
35: #endif
36: #ifdef HAVE_STRING_H
37: #include <string.h>
38: #endif
39: #ifdef HAVE_UNISTD_H
40: #include <unistd.h>
41: #endif
42:
43: #include <sys/types.h>
44:
45: #ifdef HAVE_FCNTL_H
46: #include <fcntl.h>
47: #endif
48: #ifdef HAVE_SYS_WAIT_H
49: #include <sys/wait.h>
50: #endif
51: #ifdef HAVE_GETRUSAGE
52: #include <sys/time.h>
53: #include <sys/resource.h>
54: #endif
55: #ifdef HAVE_SYS_STAT_H
56: #include <sys/stat.h>
57: #endif
58:
59:
60: #ifdef vfork
61: # define VFORK_STRING "fork"
62: #else
63: # define VFORK_STRING "vfork"
64: #endif
65: #ifdef HAVE_VFORK_H
66: #include <vfork.h>
67: #endif
68: #ifdef VMS
69: #define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
70: lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
71: #endif
72:
73:
74:
75:
76: #if defined (S_IRUSR) && defined (S_IWUSR) && defined (S_IRGRP) && defined (S_IWGRP) && defined (S_IROTH) && defined (S_IWOTH)
77: #define PUBLIC_MODE \
78: (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
79: #else
80: #define PUBLIC_MODE 0666
81: #endif
82:
83:
84:
85:
86:
87: static pid_t pex_wait (struct pex_obj *, pid_t, int *, struct pex_time *);
88:
89: #ifdef HAVE_WAIT4
90:
91: static pid_t
92: pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status,
93: struct pex_time *time)
94: {
95: pid_t ret;
96: struct rusage r;
97:
98: #ifdef HAVE_WAITPID
99: if (time == NULL)
100: return waitpid (pid, status, 0);
101: #endif
102:
103: ret = wait4 (pid, status, 0, &r);
104:
105: if (time != NULL)
106: {
107: time->user_seconds = r.ru_utime.tv_sec;
108: time->user_microseconds= r.ru_utime.tv_usec;
109: time->system_seconds = r.ru_stime.tv_sec;
110: time->system_microseconds= r.ru_stime.tv_usec;
111: }
112:
113: return ret;
114: }
115:
116: #else
117:
118: #ifdef HAVE_WAITPID
119:
120: #ifndef HAVE_GETRUSAGE
121:
122: static pid_t
123: pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status,
124: struct pex_time *time)
125: {
126: if (time != NULL)
127: memset (time, 0, sizeof (struct pex_time));
128: return waitpid (pid, status, 0);
129: }
130:
131: #else
132:
133: static pid_t
134: pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status,
135: struct pex_time *time)
136: {
137: struct rusage r1, r2;
138: pid_t ret;
139:
140: if (time == NULL)
141: return waitpid (pid, status, 0);
142:
143: getrusage (RUSAGE_CHILDREN, &r1);
144:
145: ret = waitpid (pid, status, 0);
146: if (ret < 0)
147: return ret;
148:
149: getrusage (RUSAGE_CHILDREN, &r2);
150:
151: time->user_seconds = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec;
152: time->user_microseconds = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec;
153: if (r2.ru_utime.tv_usec < r1.ru_utime.tv_usec)
154: {
155: --time->user_seconds;
156: time->user_microseconds += 1000000;
157: }
158:
159: time->system_seconds = r2.ru_stime.tv_sec - r1.ru_stime.tv_sec;
160: time->system_microseconds = r2.ru_stime.tv_usec - r1.ru_stime.tv_usec;
161: if (r2.ru_stime.tv_usec < r1.ru_stime.tv_usec)
162: {
163: --time->system_seconds;
164: time->system_microseconds += 1000000;
165: }
166:
167: return ret;
168: }
169:
170: #endif
171:
172: #else
173:
174: struct status_list
175: {
176: struct status_list *next;
177: pid_t pid;
178: int status;
179: struct pex_time time;
180: };
181:
182: static pid_t
183: pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time)
184: {
185: struct status_list **pp;
186:
187: for (pp = (struct status_list **) &obj->sysdep;
188: *pp != NULL;
189: pp = &(*pp)->next)
190: {
191: if ((*pp)->pid == pid)
192: {
193: struct status_list *p;
194:
195: p = *pp;
196: *status = p->status;
197: if (time != NULL)
198: *time = p->time;
199: *pp = p->next;
200: free (p);
201: return pid;
202: }
203: }
204:
205: while (1)
206: {
207: pid_t cpid;
208: struct status_list *psl;
209: struct pex_time pt;
210: #ifdef HAVE_GETRUSAGE
211: struct rusage r1, r2;
212: #endif
213:
214: if (time != NULL)
215: {
216: #ifdef HAVE_GETRUSAGE
217: getrusage (RUSAGE_CHILDREN, &r1);
218: #else
219: memset (&pt, 0, sizeof (struct pex_time));
220: #endif
221: }
222:
223: cpid = wait (status);
224:
225: #ifdef HAVE_GETRUSAGE
226: if (time != NULL && cpid >= 0)
227: {
228: getrusage (RUSAGE_CHILDREN, &r2);
229:
230: pt.user_seconds = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec;
231: pt.user_microseconds = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec;
232: if (pt.user_microseconds < 0)
233: {
234: --pt.user_seconds;
235: pt.user_microseconds += 1000000;
236: }
237:
238: pt.system_seconds = r2.ru_stime.tv_sec - r1.ru_stime.tv_sec;
239: pt.system_microseconds = r2.ru_stime.tv_usec - r1.ru_stime.tv_usec;
240: if (pt.system_microseconds < 0)
241: {
242: --pt.system_seconds;
243: pt.system_microseconds += 1000000;
244: }
245: }
246: #endif
247:
248: if (cpid < 0 || cpid == pid)
249: {
250: if (time != NULL)
251: *time = pt;
252: return cpid;
253: }
254:
255: psl = XNEW (struct status_list);
256: psl->pid = cpid;
257: psl->status = *status;
258: if (time != NULL)
259: psl->time = pt;
260: psl->next = (struct status_list *) obj->sysdep;
261: obj->sysdep = (void *) psl;
262: }
263: }
264:
265: #endif
266: #endif
267:
268: static void pex_child_error (struct pex_obj *, const char *, const char *, int)
269: ATTRIBUTE_NORETURN;
270: static int pex_unix_open_read (struct pex_obj *, const char *, int);
271: static int pex_unix_open_write (struct pex_obj *, const char *, int);
272: static long pex_unix_exec_child (struct pex_obj *, int, const char *,
273: char * const *, char * const *,
274: int, int, int, int,
275: const char **, int *);
276: static int pex_unix_close (struct pex_obj *, int);
277: static int pex_unix_wait (struct pex_obj *, long, int *, struct pex_time *,
278: int, const char **, int *);
279: static int pex_unix_pipe (struct pex_obj *, int *, int);
280: static FILE *pex_unix_fdopenr (struct pex_obj *, int, int);
281: static FILE *pex_unix_fdopenw (struct pex_obj *, int, int);
282: static void pex_unix_cleanup (struct pex_obj *);
283:
284:
285:
286: const struct pex_funcs funcs =
287: {
288: pex_unix_open_read,
289: pex_unix_open_write,
290: pex_unix_exec_child,
291: pex_unix_close,
292: pex_unix_wait,
293: pex_unix_pipe,
294: pex_unix_fdopenr,
295: pex_unix_fdopenw,
296: pex_unix_cleanup
297: };
298:
299:
300:
301: struct pex_obj *
302: pex_init (int flags, const char *pname, const char *tempbase)
303: {
304: return pex_init_common (flags, pname, tempbase, &funcs);
305: }
306:
307:
308:
309: static int
310: pex_unix_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
311: int binary ATTRIBUTE_UNUSED)
312: {
313: return open (name, O_RDONLY);
314: }
315:
316:
317:
318: static int
319: pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
320: int binary ATTRIBUTE_UNUSED)
321: {
322:
323:
324: return open (name, O_WRONLY | O_CREAT | O_TRUNC, PUBLIC_MODE);
325: }
326:
327:
328:
329: static int
330: pex_unix_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
331: {
332: return close (fd);
333: }
334:
335:
336:
337:
338: static void
339: pex_child_error (struct pex_obj *obj, const char *executable,
340: const char *errmsg, int err)
341: {
342: #define writeerr(s) (void) write (STDERR_FILE_NO, s, strlen (s))
343: writeerr (obj->pname);
344: writeerr (": error trying to exec '");
345: writeerr (executable);
346: writeerr ("': ");
347: writeerr (errmsg);
348: writeerr (": ");
349: writeerr (xstrerror (err));
350: writeerr ("\n");
351: _exit (-1);
352: }
353:
354:
355:
356: extern char **environ;
357:
358: static long
359: pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
360: char * const * argv, char * const * env,
361: int in, int out, int errdes,
362: int toclose, const char **errmsg, int *err)
363: {
364: pid_t pid;
365:
366:
367:
368: volatile int sleep_interval;
369: volatile int retries;
370:
371: sleep_interval = 1;
372: pid = -1;
373: for (retries = 0; retries < 4; ++retries)
374: {
375: pid = vfork ();
376: if (pid >= 0)
377: break;
378: sleep (sleep_interval);
379: sleep_interval *= 2;
380: }
381:
382: switch (pid)
383: {
384: case -1:
385: *err = errno;
386: *errmsg = VFORK_STRING;
387: return -1;
388:
389: case 0:
390:
391: if (in != STDIN_FILE_NO)
392: {
393: if (dup2 (in, STDIN_FILE_NO) < 0)
394: pex_child_error (obj, executable, "dup2", errno);
395: if (close (in) < 0)
396: pex_child_error (obj, executable, "close", errno);
397: }
398: if (out != STDOUT_FILE_NO)
399: {
400: if (dup2 (out, STDOUT_FILE_NO) < 0)
401: pex_child_error (obj, executable, "dup2", errno);
402: if (close (out) < 0)
403: pex_child_error (obj, executable, "close", errno);
404: }
405: if (errdes != STDERR_FILE_NO)
406: {
407: if (dup2 (errdes, STDERR_FILE_NO) < 0)
408: pex_child_error (obj, executable, "dup2", errno);
409: if (close (errdes) < 0)
410: pex_child_error (obj, executable, "close", errno);
411: }
412: if (toclose >= 0)
413: {
414: if (close (toclose) < 0)
415: pex_child_error (obj, executable, "close", errno);
416: }
417: if ((flags & PEX_STDERR_TO_STDOUT) != 0)
418: {
419: if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
420: pex_child_error (obj, executable, "dup2", errno);
421: }
422:
423: if (env)
424: environ = (char**) env;
425:
426: if ((flags & PEX_SEARCH) != 0)
427: {
428: execvp (executable, argv);
429: pex_child_error (obj, executable, "execvp", errno);
430: }
431: else
432: {
433: execv (executable, argv);
434: pex_child_error (obj, executable, "execv", errno);
435: }
436:
437:
438: return -1;
439:
440: default:
441:
442: if (in != STDIN_FILE_NO)
443: {
444: if (close (in) < 0)
445: {
446: *err = errno;
447: *errmsg = "close";
448: return -1;
449: }
450: }
451: if (out != STDOUT_FILE_NO)
452: {
453: if (close (out) < 0)
454: {
455: *err = errno;
456: *errmsg = "close";
457: return -1;
458: }
459: }
460: if (errdes != STDERR_FILE_NO)
461: {
462: if (close (errdes) < 0)
463: {
464: *err = errno;
465: *errmsg = "close";
466: return -1;
467: }
468: }
469:
470: return (long) pid;
471: }
472: }
473:
474:
475:
476: static int
477: pex_unix_wait (struct pex_obj *obj, long pid, int *status,
478: struct pex_time *time, int done, const char **errmsg,
479: int *err)
480: {
481:
482:
483: if (done)
484: kill (pid, SIGTERM);
485:
486: if (pex_wait (obj, pid, status, time) < 0)
487: {
488: *err = errno;
489: *errmsg = "wait";
490: return -1;
491: }
492:
493: return 0;
494: }
495:
496:
497:
498: static int
499: pex_unix_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
500: int binary ATTRIBUTE_UNUSED)
501: {
502: return pipe (p);
503: }
504:
505:
506:
507: static FILE *
508: pex_unix_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
509: int binary ATTRIBUTE_UNUSED)
510: {
511: return fdopen (fd, "r");
512: }
513:
514: static FILE *
515: pex_unix_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
516: int binary ATTRIBUTE_UNUSED)
517: {
518: if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0)
519: return NULL;
520: return fdopen (fd, "w");
521: }
522:
523: static void
524: pex_unix_cleanup (struct pex_obj *obj ATTRIBUTE_UNUSED)
525: {
526: #if !defined (HAVE_WAIT4) && !defined (HAVE_WAITPID)
527: while (obj->sysdep != NULL)
528: {
529: struct status_list *this;
530: struct status_list *next;
531:
532: this = (struct status_list *) obj->sysdep;
533: next = this->next;
534: free (this);
535: obj->sysdep = (void *) next;
536: }
537: #endif
538: }