]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/pex-unix.c
Daily bump.
[thirdparty/gcc.git] / libiberty / pex-unix.c
CommitLineData
55d0e5e0
ZW
1/* Utilities to execute a program in a subprocess (possibly linked by pipes
2 with other subprocesses), and wait for it. Generic Unix version
3 (also used for UWIN and VMS).
b303ef51 4 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2009
55d0e5e0
ZW
5 Free Software Foundation, Inc.
6
7This file is part of the libiberty library.
8Libiberty is free software; you can redistribute it and/or
9modify it under the terms of the GNU Library General Public
10License as published by the Free Software Foundation; either
11version 2 of the License, or (at your option) any later version.
12
13Libiberty is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16Library General Public License for more details.
17
18You should have received a copy of the GNU Library General Public
19License along with libiberty; see the file COPYING.LIB. If not,
ee58dffd
NC
20write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
21Boston, MA 02110-1301, USA. */
55d0e5e0 22
a584cf65
ILT
23#include "config.h"
24#include "libiberty.h"
55d0e5e0
ZW
25#include "pex-common.h"
26
27#include <stdio.h>
a584cf65 28#include <signal.h>
55d0e5e0
ZW
29#include <errno.h>
30#ifdef NEED_DECLARATION_ERRNO
31extern int errno;
32#endif
a584cf65
ILT
33#ifdef HAVE_STDLIB_H
34#include <stdlib.h>
35#endif
55d0e5e0
ZW
36#ifdef HAVE_STRING_H
37#include <string.h>
38#endif
39#ifdef HAVE_UNISTD_H
40#include <unistd.h>
41#endif
a584cf65
ILT
42
43#include <sys/types.h>
44
45#ifdef HAVE_FCNTL_H
46#include <fcntl.h>
55d0e5e0
ZW
47#endif
48#ifdef HAVE_SYS_WAIT_H
49#include <sys/wait.h>
50#endif
a584cf65
ILT
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>
55d0e5e0
ZW
57#endif
58
a584cf65 59
fed8129b
ILT
60#ifdef vfork /* Autoconf may define this to fork for us. */
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
b303ef51
DR
68#if defined(VMS) && defined (__LONG_POINTERS)
69#ifndef __CHAR_PTR32
70typedef char * __char_ptr32
71__attribute__ ((mode (SI)));
72#endif
73
74typedef __char_ptr32 *__char_ptr_char_ptr32
75__attribute__ ((mode (SI)));
76
77/* Return a 32 bit pointer to an array of 32 bit pointers
78 given a 64 bit pointer to an array of 64 bit pointers. */
79
80static __char_ptr_char_ptr32
81to_ptr32 (char **ptr64)
82{
83 int argc;
84 __char_ptr_char_ptr32 short_argv;
85
86 for (argc=0; ptr64[argc]; argc++);
fed8129b 87
b303ef51
DR
88 /* Reallocate argv with 32 bit pointers. */
89 short_argv = (__char_ptr_char_ptr32) decc$malloc
90 (sizeof (__char_ptr32) * (argc + 1));
91
92 for (argc=0; ptr64[argc]; argc++)
93 short_argv[argc] = (__char_ptr32) decc$strdup (ptr64[argc]);
94
95 short_argv[argc] = (__char_ptr32) 0;
96 return short_argv;
97
98}
99#else
100#define to_ptr32(argv) argv
101#endif
55d0e5e0 102
a584cf65
ILT
103/* File mode to use for private and world-readable files. */
104
105#if defined (S_IRUSR) && defined (S_IWUSR) && defined (S_IRGRP) && defined (S_IWGRP) && defined (S_IROTH) && defined (S_IWOTH)
106#define PUBLIC_MODE \
107 (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
108#else
109#define PUBLIC_MODE 0666
110#endif
111
112/* Get the exit status of a particular process, and optionally get the
113 time that it took. This is simple if we have wait4, slightly
114 harder if we have waitpid, and is a pain if we only have wait. */
115
116static pid_t pex_wait (struct pex_obj *, pid_t, int *, struct pex_time *);
117
118#ifdef HAVE_WAIT4
119
120static pid_t
121pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status,
122 struct pex_time *time)
123{
124 pid_t ret;
125 struct rusage r;
126
127#ifdef HAVE_WAITPID
128 if (time == NULL)
129 return waitpid (pid, status, 0);
130#endif
131
132 ret = wait4 (pid, status, 0, &r);
133
134 if (time != NULL)
135 {
136 time->user_seconds = r.ru_utime.tv_sec;
137 time->user_microseconds= r.ru_utime.tv_usec;
138 time->system_seconds = r.ru_stime.tv_sec;
139 time->system_microseconds= r.ru_stime.tv_usec;
140 }
141
142 return ret;
143}
144
145#else /* ! defined (HAVE_WAIT4) */
146
147#ifdef HAVE_WAITPID
148
149#ifndef HAVE_GETRUSAGE
150
151static pid_t
152pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status,
153 struct pex_time *time)
154{
155 if (time != NULL)
156 memset (time, 0, sizeof (struct pex_time));
157 return waitpid (pid, status, 0);
158}
159
160#else /* defined (HAVE_GETRUSAGE) */
161
162static pid_t
163pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status,
164 struct pex_time *time)
165{
166 struct rusage r1, r2;
167 pid_t ret;
168
169 if (time == NULL)
170 return waitpid (pid, status, 0);
171
172 getrusage (RUSAGE_CHILDREN, &r1);
173
174 ret = waitpid (pid, status, 0);
175 if (ret < 0)
176 return ret;
177
178 getrusage (RUSAGE_CHILDREN, &r2);
179
180 time->user_seconds = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec;
181 time->user_microseconds = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec;
182 if (r2.ru_utime.tv_usec < r1.ru_utime.tv_usec)
183 {
184 --time->user_seconds;
185 time->user_microseconds += 1000000;
186 }
187
188 time->system_seconds = r2.ru_stime.tv_sec - r1.ru_stime.tv_sec;
189 time->system_microseconds = r2.ru_stime.tv_usec - r1.ru_stime.tv_usec;
190 if (r2.ru_stime.tv_usec < r1.ru_stime.tv_usec)
191 {
192 --time->system_seconds;
193 time->system_microseconds += 1000000;
194 }
fed8129b 195
a584cf65
ILT
196 return ret;
197}
55d0e5e0 198
a584cf65 199#endif /* defined (HAVE_GETRUSAGE) */
55d0e5e0 200
a584cf65
ILT
201#else /* ! defined (HAVE_WAITPID) */
202
203struct status_list
204{
205 struct status_list *next;
206 pid_t pid;
207 int status;
208 struct pex_time time;
209};
210
211static pid_t
212pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time)
213{
214 struct status_list **pp;
215
216 for (pp = (struct status_list **) &obj->sysdep;
217 *pp != NULL;
218 pp = &(*pp)->next)
55d0e5e0 219 {
a584cf65 220 if ((*pp)->pid == pid)
55d0e5e0 221 {
a584cf65
ILT
222 struct status_list *p;
223
224 p = *pp;
225 *status = p->status;
226 if (time != NULL)
227 *time = p->time;
228 *pp = p->next;
229 free (p);
230 return pid;
55d0e5e0 231 }
55d0e5e0 232 }
a584cf65
ILT
233
234 while (1)
55d0e5e0 235 {
a584cf65
ILT
236 pid_t cpid;
237 struct status_list *psl;
238 struct pex_time pt;
239#ifdef HAVE_GETRUSAGE
240 struct rusage r1, r2;
241#endif
242
243 if (time != NULL)
244 {
245#ifdef HAVE_GETRUSAGE
246 getrusage (RUSAGE_CHILDREN, &r1);
247#else
248 memset (&pt, 0, sizeof (struct pex_time));
249#endif
250 }
251
252 cpid = wait (status);
253
254#ifdef HAVE_GETRUSAGE
255 if (time != NULL && cpid >= 0)
256 {
257 getrusage (RUSAGE_CHILDREN, &r2);
258
259 pt.user_seconds = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec;
260 pt.user_microseconds = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec;
261 if (pt.user_microseconds < 0)
262 {
263 --pt.user_seconds;
264 pt.user_microseconds += 1000000;
265 }
266
267 pt.system_seconds = r2.ru_stime.tv_sec - r1.ru_stime.tv_sec;
268 pt.system_microseconds = r2.ru_stime.tv_usec - r1.ru_stime.tv_usec;
269 if (pt.system_microseconds < 0)
270 {
271 --pt.system_seconds;
272 pt.system_microseconds += 1000000;
273 }
274 }
275#endif
276
277 if (cpid < 0 || cpid == pid)
278 {
279 if (time != NULL)
280 *time = pt;
281 return cpid;
282 }
283
d7cf8390 284 psl = XNEW (struct status_list);
a584cf65
ILT
285 psl->pid = cpid;
286 psl->status = *status;
287 if (time != NULL)
288 psl->time = pt;
289 psl->next = (struct status_list *) obj->sysdep;
290 obj->sysdep = (void *) psl;
55d0e5e0 291 }
a584cf65
ILT
292}
293
294#endif /* ! defined (HAVE_WAITPID) */
295#endif /* ! defined (HAVE_WAIT4) */
296
297static void pex_child_error (struct pex_obj *, const char *, const char *, int)
298 ATTRIBUTE_NORETURN;
299static int pex_unix_open_read (struct pex_obj *, const char *, int);
300static int pex_unix_open_write (struct pex_obj *, const char *, int);
1651030c 301static pid_t pex_unix_exec_child (struct pex_obj *, int, const char *,
ea60341e 302 char * const *, char * const *,
5317e1c7
ILT
303 int, int, int, int,
304 const char **, int *);
a584cf65 305static int pex_unix_close (struct pex_obj *, int);
1651030c 306static int pex_unix_wait (struct pex_obj *, pid_t, int *, struct pex_time *,
a584cf65
ILT
307 int, const char **, int *);
308static int pex_unix_pipe (struct pex_obj *, int *, int);
309static FILE *pex_unix_fdopenr (struct pex_obj *, int, int);
8eff378c 310static FILE *pex_unix_fdopenw (struct pex_obj *, int, int);
a584cf65
ILT
311static void pex_unix_cleanup (struct pex_obj *);
312
313/* The list of functions we pass to the common routines. */
314
315const struct pex_funcs funcs =
316{
317 pex_unix_open_read,
318 pex_unix_open_write,
319 pex_unix_exec_child,
320 pex_unix_close,
321 pex_unix_wait,
322 pex_unix_pipe,
323 pex_unix_fdopenr,
8eff378c 324 pex_unix_fdopenw,
a584cf65
ILT
325 pex_unix_cleanup
326};
327
328/* Return a newly initialized pex_obj structure. */
329
330struct pex_obj *
331pex_init (int flags, const char *pname, const char *tempbase)
332{
333 return pex_init_common (flags, pname, tempbase, &funcs);
334}
335
336/* Open a file for reading. */
337
338static int
339pex_unix_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
340 int binary ATTRIBUTE_UNUSED)
341{
342 return open (name, O_RDONLY);
343}
344
345/* Open a file for writing. */
346
347static int
348pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
349 int binary ATTRIBUTE_UNUSED)
350{
351 /* Note that we can't use O_EXCL here because gcc may have already
352 created the temporary file via make_temp_file. */
353 return open (name, O_WRONLY | O_CREAT | O_TRUNC, PUBLIC_MODE);
354}
55d0e5e0 355
a584cf65
ILT
356/* Close a file. */
357
358static int
359pex_unix_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
360{
361 return close (fd);
362}
363
364/* Report an error from a child process. We don't use stdio routines,
365 because we might be here due to a vfork call. */
366
367static void
368pex_child_error (struct pex_obj *obj, const char *executable,
369 const char *errmsg, int err)
370{
5120dc38
BE
371 int retval = 0;
372#define writeerr(s) retval |= (write (STDERR_FILE_NO, s, strlen (s)) < 0)
a584cf65
ILT
373 writeerr (obj->pname);
374 writeerr (": error trying to exec '");
375 writeerr (executable);
376 writeerr ("': ");
377 writeerr (errmsg);
378 writeerr (": ");
379 writeerr (xstrerror (err));
380 writeerr ("\n");
c22c44ba 381#undef writeerr
5120dc38
BE
382 /* Exit with -2 if the error output failed, too. */
383 _exit (retval == 0 ? -1 : -2);
a584cf65
ILT
384}
385
386/* Execute a child. */
387
ea60341e
MS
388extern char **environ;
389
1651030c 390static pid_t
a584cf65 391pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
ea60341e
MS
392 char * const * argv, char * const * env,
393 int in, int out, int errdes,
5317e1c7 394 int toclose, const char **errmsg, int *err)
a584cf65
ILT
395{
396 pid_t pid;
ea60341e 397
a584cf65
ILT
398 /* We declare these to be volatile to avoid warnings from gcc about
399 them being clobbered by vfork. */
400 volatile int sleep_interval;
401 volatile int retries;
fed8129b 402
698861dc
DE
403 /* We vfork and then set environ in the child before calling execvp.
404 This clobbers the parent's environ so we need to restore it.
405 It would be nice to use one of the exec* functions that takes an
406 environment as a parameter, but that may have portability issues. */
407 char **save_environ = environ;
408
55d0e5e0
ZW
409 sleep_interval = 1;
410 pid = -1;
a584cf65 411 for (retries = 0; retries < 4; ++retries)
55d0e5e0 412 {
fed8129b 413 pid = vfork ();
55d0e5e0
ZW
414 if (pid >= 0)
415 break;
416 sleep (sleep_interval);
417 sleep_interval *= 2;
418 }
419
420 switch (pid)
421 {
422 case -1:
a584cf65
ILT
423 *err = errno;
424 *errmsg = VFORK_STRING;
1651030c 425 return (pid_t) -1;
55d0e5e0 426
a584cf65
ILT
427 case 0:
428 /* Child process. */
429 if (in != STDIN_FILE_NO)
55d0e5e0 430 {
a584cf65
ILT
431 if (dup2 (in, STDIN_FILE_NO) < 0)
432 pex_child_error (obj, executable, "dup2", errno);
433 if (close (in) < 0)
434 pex_child_error (obj, executable, "close", errno);
55d0e5e0 435 }
a584cf65 436 if (out != STDOUT_FILE_NO)
55d0e5e0 437 {
a584cf65
ILT
438 if (dup2 (out, STDOUT_FILE_NO) < 0)
439 pex_child_error (obj, executable, "dup2", errno);
440 if (close (out) < 0)
441 pex_child_error (obj, executable, "close", errno);
442 }
443 if (errdes != STDERR_FILE_NO)
444 {
445 if (dup2 (errdes, STDERR_FILE_NO) < 0)
446 pex_child_error (obj, executable, "dup2", errno);
447 if (close (errdes) < 0)
448 pex_child_error (obj, executable, "close", errno);
449 }
5317e1c7
ILT
450 if (toclose >= 0)
451 {
452 if (close (toclose) < 0)
453 pex_child_error (obj, executable, "close", errno);
454 }
a584cf65
ILT
455 if ((flags & PEX_STDERR_TO_STDOUT) != 0)
456 {
457 if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
458 pex_child_error (obj, executable, "dup2", errno);
459 }
ea60341e
MS
460
461 if (env)
698861dc
DE
462 {
463 /* NOTE: In a standard vfork implementation this clobbers the
464 parent's copy of environ "too" (in reality there's only one copy).
465 This is ok as we restore it below. */
466 environ = (char**) env;
467 }
ea60341e 468
a584cf65
ILT
469 if ((flags & PEX_SEARCH) != 0)
470 {
b303ef51 471 execvp (executable, to_ptr32 (argv));
a584cf65 472 pex_child_error (obj, executable, "execvp", errno);
55d0e5e0 473 }
fed8129b 474 else
a584cf65 475 {
b303ef51 476 execv (executable, to_ptr32 (argv));
a584cf65
ILT
477 pex_child_error (obj, executable, "execv", errno);
478 }
fed8129b 479
55d0e5e0 480 /* NOTREACHED */
1651030c 481 return (pid_t) -1;
55d0e5e0
ZW
482
483 default:
a584cf65 484 /* Parent process. */
698861dc
DE
485
486 /* Restore environ.
487 Note that the parent either doesn't run until the child execs/exits
488 (standard vfork behaviour), or if it does run then vfork is behaving
489 more like fork. In either case we needn't worry about clobbering
490 the child's copy of environ. */
491 environ = save_environ;
492
a584cf65
ILT
493 if (in != STDIN_FILE_NO)
494 {
495 if (close (in) < 0)
496 {
497 *err = errno;
498 *errmsg = "close";
1651030c 499 return (pid_t) -1;
a584cf65
ILT
500 }
501 }
502 if (out != STDOUT_FILE_NO)
503 {
504 if (close (out) < 0)
505 {
506 *err = errno;
507 *errmsg = "close";
1651030c 508 return (pid_t) -1;
a584cf65
ILT
509 }
510 }
511 if (errdes != STDERR_FILE_NO)
512 {
513 if (close (errdes) < 0)
514 {
515 *err = errno;
516 *errmsg = "close";
1651030c 517 return (pid_t) -1;
a584cf65
ILT
518 }
519 }
520
1651030c 521 return pid;
55d0e5e0
ZW
522 }
523}
524
a584cf65
ILT
525/* Wait for a child process to complete. */
526
527static int
1651030c 528pex_unix_wait (struct pex_obj *obj, pid_t pid, int *status,
a584cf65
ILT
529 struct pex_time *time, int done, const char **errmsg,
530 int *err)
55d0e5e0 531{
a584cf65
ILT
532 /* If we are cleaning up when the caller didn't retrieve process
533 status for some reason, encourage the process to go away. */
534 if (done)
535 kill (pid, SIGTERM);
536
537 if (pex_wait (obj, pid, status, time) < 0)
538 {
539 *err = errno;
540 *errmsg = "wait";
541 return -1;
542 }
543
544 return 0;
545}
546
547/* Create a pipe. */
548
549static int
550pex_unix_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
551 int binary ATTRIBUTE_UNUSED)
552{
553 return pipe (p);
554}
555
556/* Get a FILE pointer to read from a file descriptor. */
557
558static FILE *
559pex_unix_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
560 int binary ATTRIBUTE_UNUSED)
561{
562 return fdopen (fd, "r");
563}
564
8eff378c
JB
565static FILE *
566pex_unix_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
567 int binary ATTRIBUTE_UNUSED)
568{
569 if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0)
570 return NULL;
571 return fdopen (fd, "w");
572}
573
a584cf65
ILT
574static void
575pex_unix_cleanup (struct pex_obj *obj ATTRIBUTE_UNUSED)
576{
577#if !defined (HAVE_WAIT4) && !defined (HAVE_WAITPID)
578 while (obj->sysdep != NULL)
579 {
580 struct status_list *this;
581 struct status_list *next;
582
583 this = (struct status_list *) obj->sysdep;
584 next = this->next;
585 free (this);
586 obj->sysdep = (void *) next;
587 }
588#endif
55d0e5e0 589}