]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/pexecute.c
demangle.h: Don't check IN_GCC anymore.
[thirdparty/gcc.git] / libiberty / pexecute.c
CommitLineData
6599da04
JM
1/* Utilities to execute a program in a subprocess (possibly linked by pipes
2 with other subprocesses), and wait for it.
3f3726a3 3 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
6599da04
JM
4
5This file is part of the libiberty library.
6Libiberty is free software; you can redistribute it and/or
7modify it under the terms of the GNU Library General Public
8License as published by the Free Software Foundation; either
9version 2 of the License, or (at your option) any later version.
10
11Libiberty is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14Library General Public License for more details.
15
16You should have received a copy of the GNU Library General Public
17License along with libiberty; see the file COPYING.LIB. If not,
18write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21/* This file exports two functions: pexecute and pwait. */
22
23/* This file lives in at least two places: libiberty and gcc.
24 Don't change one without the other. */
25
c5f7c445 26#ifdef HAVE_CONFIG_H
19ddc834 27#include "config.h"
c5f7c445
KG
28#endif
29#ifdef IN_GCC
3f3726a3
JL
30#include "system.h"
31#else
6599da04
JM
32#include <stdio.h>
33#include <errno.h>
c5f7c445
KG
34#ifdef HAVE_UNISTD_H
35#include <unistd.h>
36#endif
3f3726a3 37#define ISSPACE (x) isspace(x)
a6458d1d
KG
38#ifdef HAVE_SYS_WAIT_H
39#include <sys/wait.h>
40#endif
3f3726a3 41#endif
6599da04 42
c5f7c445
KG
43#ifdef vfork /* Autoconf may define this to fork for us. */
44# define VFORK_STRING "fork"
45#else
46# define VFORK_STRING "vfork"
47#endif
48#ifdef HAVE_VFORK_H
49#include <vfork.h>
50#endif
51#ifdef VMS
52#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
53 lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
54#endif /* VMS */
55
6599da04 56#include "libiberty.h"
6599da04
JM
57
58/* stdin file number. */
59#define STDIN_FILE_NO 0
60
61/* stdout file number. */
62#define STDOUT_FILE_NO 1
63
64/* value of `pipe': port index for reading. */
65#define READ_PORT 0
66
67/* value of `pipe': port index for writing. */
68#define WRITE_PORT 1
69
70static char *install_error_msg = "installation problem, cannot exec `%s'";
71
72/* pexecute: execute a program.
73
74 PROGRAM and ARGV are the arguments to execv/execvp.
75
76 THIS_PNAME is name of the calling program (i.e. argv[0]).
77
78 TEMP_BASE is the path name, sans suffix, of a temporary file to use
79 if needed. This is currently only needed for MSDOS ports that don't use
80 GO32 (do any still exist?). Ports that don't need it can pass NULL.
81
82 (FLAGS & PEXECUTE_SEARCH) is non-zero if $PATH should be searched
83 (??? It's not clear that GCC passes this flag correctly).
84 (FLAGS & PEXECUTE_FIRST) is nonzero for the first process in chain.
85 (FLAGS & PEXECUTE_FIRST) is nonzero for the last process in chain.
86 FIRST_LAST could be simplified to only mark the last of a chain of processes
87 but that requires the caller to always mark the last one (and not give up
88 early if some error occurs). It's more robust to require the caller to
89 mark both ends of the chain.
90
91 The result is the pid on systems like Unix where we fork/exec and on systems
92 like WIN32 and OS2 where we use spawn. It is up to the caller to wait for
93 the child.
94
95 The result is the WEXITSTATUS on systems like MSDOS where we spawn and wait
96 for the child here.
97
98 Upon failure, ERRMSG_FMT and ERRMSG_ARG are set to the text of the error
99 message with an optional argument (if not needed, ERRMSG_ARG is set to
100 NULL), and -1 is returned. `errno' is available to the caller to use.
101
102 pwait: cover function for wait.
103
104 PID is the process id of the task to wait for.
105 STATUS is the `status' argument to wait.
106 FLAGS is currently unused (allows future enhancement without breaking
107 upward compatibility). Pass 0 for now.
108
109 The result is the pid of the child reaped,
110 or -1 for failure (errno says why).
111
112 On systems that don't support waiting for a particular child, PID is
113 ignored. On systems like MSDOS that don't really multitask pwait
114 is just a mechanism to provide a consistent interface for the caller.
115
116 pfinish: finish generation of script
117
118 pfinish is necessary for systems like MPW where a script is generated that
119 runs the requested programs.
120*/
121
122#ifdef __MSDOS__
123
124/* MSDOS doesn't multitask, but for the sake of a consistent interface
125 the code behaves like it does. pexecute runs the program, tucks the
126 exit code away, and returns a "pid". pwait must be called to fetch the
127 exit code. */
128
129#include <process.h>
130
131/* For communicating information from pexecute to pwait. */
132static int last_pid = 0;
133static int last_status = 0;
134static int last_reaped = 0;
135
136int
137pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
138 const char *program;
139 char * const *argv;
140 const char *this_pname;
141 const char *temp_base;
142 char **errmsg_fmt, **errmsg_arg;
143 int flags;
144{
145 int rc;
146
147 last_pid++;
148 if (last_pid < 0)
149 last_pid = 1;
150
151 if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
152 abort ();
153
154#ifdef __GO32__
155 /* ??? What are the possible return values from spawnv? */
156 rc = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (1, program, argv);
157#else
158 char *scmd, *rf;
159 FILE *argfile;
160 int i, el = flags & PEXECUTE_SEARCH ? 4 : 0;
161
162 scmd = (char *) xmalloc (strlen (program) + strlen (temp_base) + 6 + el);
163 rf = scmd + strlen(program) + 2 + el;
164 sprintf (scmd, "%s%s @%s.gp", program,
165 (flags & PEXECUTE_SEARCH ? ".exe" : ""), temp_base);
166 argfile = fopen (rf, "w");
167 if (argfile == 0)
168 {
169 int errno_save = errno;
170 free (scmd);
171 errno = errno_save;
172 *errmsg_fmt = "cannot open `%s.gp'";
173 *errmsg_arg = temp_base;
174 return -1;
175 }
176
177 for (i=1; argv[i]; i++)
178 {
179 char *cp;
180 for (cp = argv[i]; *cp; cp++)
181 {
3f3726a3 182 if (*cp == '"' || *cp == '\'' || *cp == '\\' || ISSPACE (*cp))
6599da04
JM
183 fputc ('\\', argfile);
184 fputc (*cp, argfile);
185 }
186 fputc ('\n', argfile);
187 }
188 fclose (argfile);
189
190 rc = system (scmd);
191
192 {
193 int errno_save = errno;
194 remove (rf);
195 free (scmd);
196 errno = errno_save;
197 }
198#endif
199
200 if (rc == -1)
201 {
202 *errmsg_fmt = install_error_msg;
203 *errmsg_arg = program;
204 return -1;
205 }
206
207 /* Tuck the status away for pwait, and return a "pid". */
208 last_status = rc << 8;
209 return last_pid;
210}
211
212int
213pwait (pid, status, flags)
214 int pid;
215 int *status;
216 int flags;
217{
218 /* On MSDOS each pexecute must be followed by it's associated pwait. */
219 if (pid != last_pid
220 /* Called twice for the same child? */
221 || pid == last_reaped)
222 {
223 /* ??? ECHILD would be a better choice. Can we use it here? */
224 errno = EINVAL;
225 return -1;
226 }
227 /* ??? Here's an opportunity to canonicalize the values in STATUS.
228 Needed? */
229 *status = last_status;
230 last_reaped = last_pid;
231 return last_pid;
232}
233
234#endif /* MSDOS */
235
236#if defined (_WIN32)
237
238#include <process.h>
6599da04 239
19ddc834
JM
240#ifdef __CYGWIN32__
241
242#define fix_argv(argvec) (argvec)
243
77aff459
MK
244extern int _spawnv ();
245extern int _spawnvp ();
246
77aff459 247#else /* ! __CYGWIN32__ */
19ddc834
JM
248
249/* This is a kludge to get around the Microsoft C spawn functions' propensity
250 to remove the outermost set of double quotes from all arguments. */
251
252const char * const *
253fix_argv (argvec)
254 char **argvec;
255{
256 int i;
257
258 for (i = 1; argvec[i] != 0; i++)
259 {
260 int len, j;
261 char *temp, *newtemp;
262
263 temp = argvec[i];
264 len = strlen (temp);
265 for (j = 0; j < len; j++)
266 {
267 if (temp[j] == '"')
268 {
269 newtemp = xmalloc (len + 2);
270 strncpy (newtemp, temp, j);
271 newtemp [j] = '\\';
272 strncpy (&newtemp [j+1], &temp [j], len-j);
273 newtemp [len+1] = 0;
274 temp = newtemp;
275 len++;
276 j++;
277 }
278 }
279
280 argvec[i] = temp;
281 }
282
283 return (const char * const *) argvec;
284}
8d525fa8 285#endif /* __CYGWIN32__ */
19ddc834 286
77aff459
MK
287#include <io.h>
288#include <fcntl.h>
289#include <signal.h>
290
291/* mingw32 headers may not define the following. */
292
293#ifndef _P_WAIT
294# define _P_WAIT 0
295# define _P_NOWAIT 1
296# define _P_OVERLAY 2
297# define _P_NOWAITO 3
298# define _P_DETACH 4
299
300# define WAIT_CHILD 0
301# define WAIT_GRANDCHILD 1
302#endif
19ddc834 303
77aff459 304/* Win32 supports pipes */
6599da04
JM
305int
306pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
307 const char *program;
308 char * const *argv;
309 const char *this_pname;
310 const char *temp_base;
311 char **errmsg_fmt, **errmsg_arg;
312 int flags;
313{
314 int pid;
77aff459
MK
315 int pdes[2], org_stdin, org_stdout;
316 int input_desc, output_desc;
317 int retries, sleep_interval;
318
319 /* Pipe waiting from last process, to be used as input for the next one.
320 Value is STDIN_FILE_NO if no pipe is waiting
321 (i.e. the next command is the first of a group). */
322 static int last_pipe_input;
323
324 /* If this is the first process, initialize. */
325 if (flags & PEXECUTE_FIRST)
326 last_pipe_input = STDIN_FILE_NO;
327
328 input_desc = last_pipe_input;
329
330 /* If this isn't the last process, make a pipe for its output,
331 and record it as waiting to be the input to the next process. */
332 if (! (flags & PEXECUTE_LAST))
333 {
334 if (_pipe (pdes, 256, O_BINARY) < 0)
335 {
336 *errmsg_fmt = "pipe";
337 *errmsg_arg = NULL;
338 return -1;
339 }
340 output_desc = pdes[WRITE_PORT];
341 last_pipe_input = pdes[READ_PORT];
342 }
343 else
344 {
345 /* Last process. */
346 output_desc = STDOUT_FILE_NO;
347 last_pipe_input = STDIN_FILE_NO;
348 }
349
350 if (input_desc != STDIN_FILE_NO)
351 {
352 org_stdin = dup (STDIN_FILE_NO);
353 dup2 (input_desc, STDIN_FILE_NO);
354 close (input_desc);
355 }
356
357 if (output_desc != STDOUT_FILE_NO)
358 {
359 org_stdout = dup (STDOUT_FILE_NO);
360 dup2 (output_desc, STDOUT_FILE_NO);
361 close (output_desc);
362 }
6599da04 363
19ddc834
JM
364 pid = (flags & PEXECUTE_SEARCH ? _spawnvp : _spawnv)
365 (_P_NOWAIT, program, fix_argv(argv));
77aff459
MK
366
367 if (input_desc != STDIN_FILE_NO)
368 {
369 dup2 (org_stdin, STDIN_FILE_NO);
370 close (org_stdin);
371 }
372
373 if (output_desc != STDOUT_FILE_NO)
374 {
375 dup2 (org_stdout, STDOUT_FILE_NO);
376 close (org_stdout);
377 }
378
6599da04
JM
379 if (pid == -1)
380 {
381 *errmsg_fmt = install_error_msg;
382 *errmsg_arg = program;
383 return -1;
384 }
77aff459 385
6599da04
JM
386 return pid;
387}
388
77aff459
MK
389/* MS CRTDLL doesn't return enough information in status to decide if the
390 child exited due to a signal or not, rather it simply returns an
391 integer with the exit code of the child; eg., if the child exited with
392 an abort() call and didn't have a handler for SIGABRT, it simply returns
393 with status = 3. We fix the status code to conform to the usual WIF*
394 macros. Note that WIFSIGNALED will never be true under CRTDLL. */
395
6599da04
JM
396int
397pwait (pid, status, flags)
398 int pid;
399 int *status;
400 int flags;
401{
8d525fa8
CF
402#ifdef __CYGWIN32__
403 return wait (status);
404#else
77aff459
MK
405 int termstat;
406
407 pid = _cwait (&termstat, pid, WAIT_CHILD);
408
6599da04
JM
409 /* ??? Here's an opportunity to canonicalize the values in STATUS.
410 Needed? */
77aff459
MK
411
412 /* cwait returns the child process exit code in termstat.
413 A value of 3 indicates that the child caught a signal, but not
414 which one. Since only SIGABRT, SIGFPE and SIGINT do anything, we
415 report SIGABRT. */
416 if (termstat == 3)
417 *status = SIGABRT;
418 else
419 *status = (((termstat) & 0xff) << 8);
420
421 return pid;
8d525fa8 422#endif /* __CYGWIN32__ */
6599da04
JM
423}
424
425#endif /* _WIN32 */
426
427#ifdef OS2
428
429/* ??? Does OS2 have process.h? */
430extern int spawnv ();
431extern int spawnvp ();
432
433int
434pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
435 const char *program;
436 char * const *argv;
437 const char *this_pname;
438 const char *temp_base;
439 char **errmsg_fmt, **errmsg_arg;
440 int flags;
441{
442 int pid;
443
444 if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
445 abort ();
446 /* ??? Presumably 1 == _P_NOWAIT. */
447 pid = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (1, program, argv);
448 if (pid == -1)
449 {
450 *errmsg_fmt = install_error_msg;
451 *errmsg_arg = program;
452 return -1;
453 }
454 return pid;
455}
456
457int
458pwait (pid, status, flags)
459 int pid;
460 int *status;
461 int flags;
462{
463 /* ??? Here's an opportunity to canonicalize the values in STATUS.
464 Needed? */
465 int pid = wait (status);
466 return pid;
467}
468
469#endif /* OS2 */
470
471#ifdef MPW
472
473/* MPW pexecute doesn't actually run anything; instead, it writes out
474 script commands that, when run, will do the actual executing.
475
476 For example, in GCC's case, GCC will write out several script commands:
477
478 cpp ...
479 cc1 ...
480 as ...
481 ld ...
482
483 and then exit. None of the above programs will have run yet. The task
484 that called GCC will then execute the script and cause cpp,etc. to run.
485 The caller must invoke pfinish before calling exit. This adds
486 the finishing touches to the generated script. */
487
488static int first_time = 1;
489
490int
491pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
492 const char *program;
3f3726a3 493 char * const *argv;
6599da04
JM
494 const char *this_pname;
495 const char *temp_base;
496 char **errmsg_fmt, **errmsg_arg;
497 int flags;
498{
499 char tmpprogram[255];
500 char *cp, *tmpname;
501 int i;
502
503 mpwify_filename (program, tmpprogram);
504 if (first_time)
505 {
506 printf ("Set Failed 0\n");
507 first_time = 0;
508 }
509
510 fputs ("If {Failed} == 0\n", stdout);
511 /* If being verbose, output a copy of the command. It should be
512 accurate enough and escaped enough to be "clickable". */
513 if (flags & PEXECUTE_VERBOSE)
514 {
515 fputs ("\tEcho ", stdout);
516 fputc ('\'', stdout);
517 fputs (tmpprogram, stdout);
518 fputc ('\'', stdout);
519 fputc (' ', stdout);
520 for (i=1; argv[i]; i++)
521 {
6599da04 522 fputc ('\'', stdout);
3f3726a3
JL
523 /* See if we have an argument that needs fixing. */
524 if (strchr(argv[i], '/'))
525 {
526 tmpname = (char *) xmalloc (256);
527 mpwify_filename (argv[i], tmpname);
528 argv[i] = tmpname;
529 }
6599da04
JM
530 for (cp = argv[i]; *cp; cp++)
531 {
3f3726a3
JL
532 /* Write an Option-d escape char in front of special chars. */
533 if (strchr("'+", *cp))
6599da04
JM
534 fputc ('\266', stdout);
535 fputc (*cp, stdout);
536 }
537 fputc ('\'', stdout);
538 fputc (' ', stdout);
539 }
540 fputs ("\n", stdout);
541 }
542 fputs ("\t", stdout);
543 fputs (tmpprogram, stdout);
544 fputc (' ', stdout);
545
546 for (i=1; argv[i]; i++)
547 {
3f3726a3
JL
548 /* See if we have an argument that needs fixing. */
549 if (strchr(argv[i], '/'))
550 {
551 tmpname = (char *) xmalloc (256);
552 mpwify_filename (argv[i], tmpname);
553 argv[i] = tmpname;
554 }
6599da04
JM
555 if (strchr (argv[i], ' '))
556 fputc ('\'', stdout);
557 for (cp = argv[i]; *cp; cp++)
558 {
3f3726a3
JL
559 /* Write an Option-d escape char in front of special chars. */
560 if (strchr("'+", *cp))
561 fputc ('\266', stdout);
6599da04
JM
562 fputc (*cp, stdout);
563 }
564 if (strchr (argv[i], ' '))
565 fputc ('\'', stdout);
566 fputc (' ', stdout);
567 }
568
569 fputs ("\n", stdout);
570
571 /* Output commands that arrange to clean up and exit if a failure occurs.
572 We have to be careful to collect the status from the program that was
573 run, rather than some other script command. Also, we don't exit
574 immediately, since necessary cleanups are at the end of the script. */
575 fputs ("\tSet TmpStatus {Status}\n", stdout);
576 fputs ("\tIf {TmpStatus} != 0\n", stdout);
577 fputs ("\t\tSet Failed {TmpStatus}\n", stdout);
578 fputs ("\tEnd\n", stdout);
579 fputs ("End\n", stdout);
580
581 /* We're just composing a script, can't fail here. */
582 return 0;
583}
584
585int
586pwait (pid, status, flags)
587 int pid;
588 int *status;
589 int flags;
590{
591 *status = 0;
592 return 0;
593}
594
595/* Write out commands that will exit with the correct error code
596 if something in the script failed. */
597
598void
599pfinish ()
600{
601 printf ("\tExit \"{Failed}\"\n");
602}
603
604#endif /* MPW */
605
606/* include for Unix-like environments but not for Dos-like environments */
607#if ! defined (__MSDOS__) && ! defined (OS2) && ! defined (MPW) \
608 && ! defined (_WIN32)
609
6599da04
JM
610extern int execv ();
611extern int execvp ();
3f3726a3
JL
612#ifdef IN_GCC
613extern char * my_strerror PROTO ((int));
614#endif
6599da04
JM
615
616int
617pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
618 const char *program;
619 char * const *argv;
620 const char *this_pname;
621 const char *temp_base;
622 char **errmsg_fmt, **errmsg_arg;
623 int flags;
624{
625 int (*func)() = (flags & PEXECUTE_SEARCH ? execvp : execv);
626 int pid;
627 int pdes[2];
628 int input_desc, output_desc;
629 int retries, sleep_interval;
630 /* Pipe waiting from last process, to be used as input for the next one.
631 Value is STDIN_FILE_NO if no pipe is waiting
632 (i.e. the next command is the first of a group). */
633 static int last_pipe_input;
634
635 /* If this is the first process, initialize. */
636 if (flags & PEXECUTE_FIRST)
637 last_pipe_input = STDIN_FILE_NO;
638
639 input_desc = last_pipe_input;
640
641 /* If this isn't the last process, make a pipe for its output,
642 and record it as waiting to be the input to the next process. */
643 if (! (flags & PEXECUTE_LAST))
644 {
645 if (pipe (pdes) < 0)
646 {
647 *errmsg_fmt = "pipe";
648 *errmsg_arg = NULL;
649 return -1;
650 }
651 output_desc = pdes[WRITE_PORT];
652 last_pipe_input = pdes[READ_PORT];
653 }
654 else
655 {
656 /* Last process. */
657 output_desc = STDOUT_FILE_NO;
658 last_pipe_input = STDIN_FILE_NO;
659 }
660
661 /* Fork a subprocess; wait and retry if it fails. */
662 sleep_interval = 1;
663 for (retries = 0; retries < 4; retries++)
664 {
665 pid = vfork ();
666 if (pid >= 0)
667 break;
668 sleep (sleep_interval);
669 sleep_interval *= 2;
670 }
671
672 switch (pid)
673 {
674 case -1:
675 {
c5f7c445 676 *errmsg_fmt = VFORK_STRING;
6599da04
JM
677 *errmsg_arg = NULL;
678 return -1;
679 }
680
681 case 0: /* child */
682 /* Move the input and output pipes into place, if necessary. */
683 if (input_desc != STDIN_FILE_NO)
684 {
685 close (STDIN_FILE_NO);
686 dup (input_desc);
687 close (input_desc);
688 }
689 if (output_desc != STDOUT_FILE_NO)
690 {
691 close (STDOUT_FILE_NO);
692 dup (output_desc);
693 close (output_desc);
694 }
695
696 /* Close the parent's descs that aren't wanted here. */
697 if (last_pipe_input != STDIN_FILE_NO)
698 close (last_pipe_input);
699
700 /* Exec the program. */
701 (*func) (program, argv);
702
703 /* Note: Calling fprintf and exit here doesn't seem right for vfork. */
704 fprintf (stderr, "%s: ", this_pname);
705 fprintf (stderr, install_error_msg, program);
706#ifdef IN_GCC
707 fprintf (stderr, ": %s\n", my_strerror (errno));
708#else
709 fprintf (stderr, ": %s\n", xstrerror (errno));
710#endif
711 exit (-1);
712 /* NOTREACHED */
713 return 0;
714
715 default:
716 /* In the parent, after forking.
717 Close the descriptors that we made for this child. */
718 if (input_desc != STDIN_FILE_NO)
719 close (input_desc);
720 if (output_desc != STDOUT_FILE_NO)
721 close (output_desc);
722
723 /* Return child's process number. */
724 return pid;
725 }
726}
727
728int
729pwait (pid, status, flags)
730 int pid;
731 int *status;
732 int flags;
733{
734 /* ??? Here's an opportunity to canonicalize the values in STATUS.
735 Needed? */
736#ifdef VMS
737 pid = waitpid (-1, status, 0);
738#else
739 pid = wait (status);
740#endif
741 return pid;
742}
743
744#endif /* ! __MSDOS__ && ! OS2 && ! MPW && ! _WIN32 */