]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/pexecute.c
cplus-dem.c (demangle_signature): Don't look for return types on constructors.
[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.
3 Copyright (C) 1996, 1997 Free Software Foundation, Inc.
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
19ddc834
JM
26#ifdef IN_GCC
27#include "config.h"
28#endif
29
6599da04
JM
30#include <stdio.h>
31#include <errno.h>
32
33#ifdef IN_GCC
6599da04
JM
34#include "gansidecl.h"
35/* ??? Need to find a suitable header file. */
36#define PEXECUTE_FIRST 1
37#define PEXECUTE_LAST 2
38#define PEXECUTE_ONE (PEXECUTE_FIRST + PEXECUTE_LAST)
39#define PEXECUTE_SEARCH 4
40#define PEXECUTE_VERBOSE 8
41#else
42#include "libiberty.h"
43#endif
44
45/* stdin file number. */
46#define STDIN_FILE_NO 0
47
48/* stdout file number. */
49#define STDOUT_FILE_NO 1
50
51/* value of `pipe': port index for reading. */
52#define READ_PORT 0
53
54/* value of `pipe': port index for writing. */
55#define WRITE_PORT 1
56
57static char *install_error_msg = "installation problem, cannot exec `%s'";
58
59/* pexecute: execute a program.
60
61 PROGRAM and ARGV are the arguments to execv/execvp.
62
63 THIS_PNAME is name of the calling program (i.e. argv[0]).
64
65 TEMP_BASE is the path name, sans suffix, of a temporary file to use
66 if needed. This is currently only needed for MSDOS ports that don't use
67 GO32 (do any still exist?). Ports that don't need it can pass NULL.
68
69 (FLAGS & PEXECUTE_SEARCH) is non-zero if $PATH should be searched
70 (??? It's not clear that GCC passes this flag correctly).
71 (FLAGS & PEXECUTE_FIRST) is nonzero for the first process in chain.
72 (FLAGS & PEXECUTE_FIRST) is nonzero for the last process in chain.
73 FIRST_LAST could be simplified to only mark the last of a chain of processes
74 but that requires the caller to always mark the last one (and not give up
75 early if some error occurs). It's more robust to require the caller to
76 mark both ends of the chain.
77
78 The result is the pid on systems like Unix where we fork/exec and on systems
79 like WIN32 and OS2 where we use spawn. It is up to the caller to wait for
80 the child.
81
82 The result is the WEXITSTATUS on systems like MSDOS where we spawn and wait
83 for the child here.
84
85 Upon failure, ERRMSG_FMT and ERRMSG_ARG are set to the text of the error
86 message with an optional argument (if not needed, ERRMSG_ARG is set to
87 NULL), and -1 is returned. `errno' is available to the caller to use.
88
89 pwait: cover function for wait.
90
91 PID is the process id of the task to wait for.
92 STATUS is the `status' argument to wait.
93 FLAGS is currently unused (allows future enhancement without breaking
94 upward compatibility). Pass 0 for now.
95
96 The result is the pid of the child reaped,
97 or -1 for failure (errno says why).
98
99 On systems that don't support waiting for a particular child, PID is
100 ignored. On systems like MSDOS that don't really multitask pwait
101 is just a mechanism to provide a consistent interface for the caller.
102
103 pfinish: finish generation of script
104
105 pfinish is necessary for systems like MPW where a script is generated that
106 runs the requested programs.
107*/
108
109#ifdef __MSDOS__
110
111/* MSDOS doesn't multitask, but for the sake of a consistent interface
112 the code behaves like it does. pexecute runs the program, tucks the
113 exit code away, and returns a "pid". pwait must be called to fetch the
114 exit code. */
115
116#include <process.h>
117
118/* For communicating information from pexecute to pwait. */
119static int last_pid = 0;
120static int last_status = 0;
121static int last_reaped = 0;
122
123int
124pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
125 const char *program;
126 char * const *argv;
127 const char *this_pname;
128 const char *temp_base;
129 char **errmsg_fmt, **errmsg_arg;
130 int flags;
131{
132 int rc;
133
134 last_pid++;
135 if (last_pid < 0)
136 last_pid = 1;
137
138 if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
139 abort ();
140
141#ifdef __GO32__
142 /* ??? What are the possible return values from spawnv? */
143 rc = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (1, program, argv);
144#else
145 char *scmd, *rf;
146 FILE *argfile;
147 int i, el = flags & PEXECUTE_SEARCH ? 4 : 0;
148
149 scmd = (char *) xmalloc (strlen (program) + strlen (temp_base) + 6 + el);
150 rf = scmd + strlen(program) + 2 + el;
151 sprintf (scmd, "%s%s @%s.gp", program,
152 (flags & PEXECUTE_SEARCH ? ".exe" : ""), temp_base);
153 argfile = fopen (rf, "w");
154 if (argfile == 0)
155 {
156 int errno_save = errno;
157 free (scmd);
158 errno = errno_save;
159 *errmsg_fmt = "cannot open `%s.gp'";
160 *errmsg_arg = temp_base;
161 return -1;
162 }
163
164 for (i=1; argv[i]; i++)
165 {
166 char *cp;
167 for (cp = argv[i]; *cp; cp++)
168 {
169 if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
170 fputc ('\\', argfile);
171 fputc (*cp, argfile);
172 }
173 fputc ('\n', argfile);
174 }
175 fclose (argfile);
176
177 rc = system (scmd);
178
179 {
180 int errno_save = errno;
181 remove (rf);
182 free (scmd);
183 errno = errno_save;
184 }
185#endif
186
187 if (rc == -1)
188 {
189 *errmsg_fmt = install_error_msg;
190 *errmsg_arg = program;
191 return -1;
192 }
193
194 /* Tuck the status away for pwait, and return a "pid". */
195 last_status = rc << 8;
196 return last_pid;
197}
198
199int
200pwait (pid, status, flags)
201 int pid;
202 int *status;
203 int flags;
204{
205 /* On MSDOS each pexecute must be followed by it's associated pwait. */
206 if (pid != last_pid
207 /* Called twice for the same child? */
208 || pid == last_reaped)
209 {
210 /* ??? ECHILD would be a better choice. Can we use it here? */
211 errno = EINVAL;
212 return -1;
213 }
214 /* ??? Here's an opportunity to canonicalize the values in STATUS.
215 Needed? */
216 *status = last_status;
217 last_reaped = last_pid;
218 return last_pid;
219}
220
221#endif /* MSDOS */
222
223#if defined (_WIN32)
224
225#include <process.h>
226extern int _spawnv ();
227extern int _spawnvp ();
228
19ddc834
JM
229#ifdef __CYGWIN32__
230
231#define fix_argv(argvec) (argvec)
232
233#else
234
235/* This is a kludge to get around the Microsoft C spawn functions' propensity
236 to remove the outermost set of double quotes from all arguments. */
237
238const char * const *
239fix_argv (argvec)
240 char **argvec;
241{
242 int i;
243
244 for (i = 1; argvec[i] != 0; i++)
245 {
246 int len, j;
247 char *temp, *newtemp;
248
249 temp = argvec[i];
250 len = strlen (temp);
251 for (j = 0; j < len; j++)
252 {
253 if (temp[j] == '"')
254 {
255 newtemp = xmalloc (len + 2);
256 strncpy (newtemp, temp, j);
257 newtemp [j] = '\\';
258 strncpy (&newtemp [j+1], &temp [j], len-j);
259 newtemp [len+1] = 0;
260 temp = newtemp;
261 len++;
262 j++;
263 }
264 }
265
266 argvec[i] = temp;
267 }
268
269 return (const char * const *) argvec;
270}
271
272#endif /* ! defined (__CYGWIN32__) */
273
6599da04
JM
274int
275pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
276 const char *program;
277 char * const *argv;
278 const char *this_pname;
279 const char *temp_base;
280 char **errmsg_fmt, **errmsg_arg;
281 int flags;
282{
283 int pid;
284
285 if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
286 abort ();
19ddc834
JM
287 pid = (flags & PEXECUTE_SEARCH ? _spawnvp : _spawnv)
288 (_P_NOWAIT, program, fix_argv(argv));
6599da04
JM
289 if (pid == -1)
290 {
291 *errmsg_fmt = install_error_msg;
292 *errmsg_arg = program;
293 return -1;
294 }
295 return pid;
296}
297
298int
299pwait (pid, status, flags)
300 int pid;
301 int *status;
302 int flags;
303{
304 /* ??? Here's an opportunity to canonicalize the values in STATUS.
305 Needed? */
19ddc834 306 return _cwait (status, pid, WAIT_CHILD);
6599da04
JM
307}
308
309#endif /* _WIN32 */
310
311#ifdef OS2
312
313/* ??? Does OS2 have process.h? */
314extern int spawnv ();
315extern int spawnvp ();
316
317int
318pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
319 const char *program;
320 char * const *argv;
321 const char *this_pname;
322 const char *temp_base;
323 char **errmsg_fmt, **errmsg_arg;
324 int flags;
325{
326 int pid;
327
328 if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
329 abort ();
330 /* ??? Presumably 1 == _P_NOWAIT. */
331 pid = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (1, program, argv);
332 if (pid == -1)
333 {
334 *errmsg_fmt = install_error_msg;
335 *errmsg_arg = program;
336 return -1;
337 }
338 return pid;
339}
340
341int
342pwait (pid, status, flags)
343 int pid;
344 int *status;
345 int flags;
346{
347 /* ??? Here's an opportunity to canonicalize the values in STATUS.
348 Needed? */
349 int pid = wait (status);
350 return pid;
351}
352
353#endif /* OS2 */
354
355#ifdef MPW
356
357/* MPW pexecute doesn't actually run anything; instead, it writes out
358 script commands that, when run, will do the actual executing.
359
360 For example, in GCC's case, GCC will write out several script commands:
361
362 cpp ...
363 cc1 ...
364 as ...
365 ld ...
366
367 and then exit. None of the above programs will have run yet. The task
368 that called GCC will then execute the script and cause cpp,etc. to run.
369 The caller must invoke pfinish before calling exit. This adds
370 the finishing touches to the generated script. */
371
372static int first_time = 1;
373
374int
375pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
376 const char *program;
377 char **argv;
378 const char *this_pname;
379 const char *temp_base;
380 char **errmsg_fmt, **errmsg_arg;
381 int flags;
382{
383 char tmpprogram[255];
384 char *cp, *tmpname;
385 int i;
386
387 mpwify_filename (program, tmpprogram);
388 if (first_time)
389 {
390 printf ("Set Failed 0\n");
391 first_time = 0;
392 }
393
394 fputs ("If {Failed} == 0\n", stdout);
395 /* If being verbose, output a copy of the command. It should be
396 accurate enough and escaped enough to be "clickable". */
397 if (flags & PEXECUTE_VERBOSE)
398 {
399 fputs ("\tEcho ", stdout);
400 fputc ('\'', stdout);
401 fputs (tmpprogram, stdout);
402 fputc ('\'', stdout);
403 fputc (' ', stdout);
404 for (i=1; argv[i]; i++)
405 {
406 /* We have to quote every arg, so that when the echo is
407 executed, the quotes are stripped and the original arg
408 is left. */
409 fputc ('\'', stdout);
410 for (cp = argv[i]; *cp; cp++)
411 {
412 /* Write an Option-d esc char in front of special chars. */
413 if (strchr ("\"'+", *cp))
414 fputc ('\266', stdout);
415 fputc (*cp, stdout);
416 }
417 fputc ('\'', stdout);
418 fputc (' ', stdout);
419 }
420 fputs ("\n", stdout);
421 }
422 fputs ("\t", stdout);
423 fputs (tmpprogram, stdout);
424 fputc (' ', stdout);
425
426 for (i=1; argv[i]; i++)
427 {
428 if (strchr (argv[i], ' '))
429 fputc ('\'', stdout);
430 for (cp = argv[i]; *cp; cp++)
431 {
432 /* Write an Option-d esc char in front of special chars. */
433 if (strchr ("\"'+", *cp))
434 {
435 fputc ('\266', stdout);
436 }
437 fputc (*cp, stdout);
438 }
439 if (strchr (argv[i], ' '))
440 fputc ('\'', stdout);
441 fputc (' ', stdout);
442 }
443
444 fputs ("\n", stdout);
445
446 /* Output commands that arrange to clean up and exit if a failure occurs.
447 We have to be careful to collect the status from the program that was
448 run, rather than some other script command. Also, we don't exit
449 immediately, since necessary cleanups are at the end of the script. */
450 fputs ("\tSet TmpStatus {Status}\n", stdout);
451 fputs ("\tIf {TmpStatus} != 0\n", stdout);
452 fputs ("\t\tSet Failed {TmpStatus}\n", stdout);
453 fputs ("\tEnd\n", stdout);
454 fputs ("End\n", stdout);
455
456 /* We're just composing a script, can't fail here. */
457 return 0;
458}
459
460int
461pwait (pid, status, flags)
462 int pid;
463 int *status;
464 int flags;
465{
466 *status = 0;
467 return 0;
468}
469
470/* Write out commands that will exit with the correct error code
471 if something in the script failed. */
472
473void
474pfinish ()
475{
476 printf ("\tExit \"{Failed}\"\n");
477}
478
479#endif /* MPW */
480
481/* include for Unix-like environments but not for Dos-like environments */
482#if ! defined (__MSDOS__) && ! defined (OS2) && ! defined (MPW) \
483 && ! defined (_WIN32)
484
485#ifdef VMS
486#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
487 lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
488#else
489#ifdef USG
490#define vfork fork
491#endif
492#endif
493
494extern int execv ();
495extern int execvp ();
496
497int
498pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
499 const char *program;
500 char * const *argv;
501 const char *this_pname;
502 const char *temp_base;
503 char **errmsg_fmt, **errmsg_arg;
504 int flags;
505{
506 int (*func)() = (flags & PEXECUTE_SEARCH ? execvp : execv);
507 int pid;
508 int pdes[2];
509 int input_desc, output_desc;
510 int retries, sleep_interval;
511 /* Pipe waiting from last process, to be used as input for the next one.
512 Value is STDIN_FILE_NO if no pipe is waiting
513 (i.e. the next command is the first of a group). */
514 static int last_pipe_input;
515
516 /* If this is the first process, initialize. */
517 if (flags & PEXECUTE_FIRST)
518 last_pipe_input = STDIN_FILE_NO;
519
520 input_desc = last_pipe_input;
521
522 /* If this isn't the last process, make a pipe for its output,
523 and record it as waiting to be the input to the next process. */
524 if (! (flags & PEXECUTE_LAST))
525 {
526 if (pipe (pdes) < 0)
527 {
528 *errmsg_fmt = "pipe";
529 *errmsg_arg = NULL;
530 return -1;
531 }
532 output_desc = pdes[WRITE_PORT];
533 last_pipe_input = pdes[READ_PORT];
534 }
535 else
536 {
537 /* Last process. */
538 output_desc = STDOUT_FILE_NO;
539 last_pipe_input = STDIN_FILE_NO;
540 }
541
542 /* Fork a subprocess; wait and retry if it fails. */
543 sleep_interval = 1;
544 for (retries = 0; retries < 4; retries++)
545 {
546 pid = vfork ();
547 if (pid >= 0)
548 break;
549 sleep (sleep_interval);
550 sleep_interval *= 2;
551 }
552
553 switch (pid)
554 {
555 case -1:
556 {
557#ifdef vfork
558 *errmsg_fmt = "fork";
559#else
560 *errmsg_fmt = "vfork";
561#endif
562 *errmsg_arg = NULL;
563 return -1;
564 }
565
566 case 0: /* child */
567 /* Move the input and output pipes into place, if necessary. */
568 if (input_desc != STDIN_FILE_NO)
569 {
570 close (STDIN_FILE_NO);
571 dup (input_desc);
572 close (input_desc);
573 }
574 if (output_desc != STDOUT_FILE_NO)
575 {
576 close (STDOUT_FILE_NO);
577 dup (output_desc);
578 close (output_desc);
579 }
580
581 /* Close the parent's descs that aren't wanted here. */
582 if (last_pipe_input != STDIN_FILE_NO)
583 close (last_pipe_input);
584
585 /* Exec the program. */
586 (*func) (program, argv);
587
588 /* Note: Calling fprintf and exit here doesn't seem right for vfork. */
589 fprintf (stderr, "%s: ", this_pname);
590 fprintf (stderr, install_error_msg, program);
591#ifdef IN_GCC
592 fprintf (stderr, ": %s\n", my_strerror (errno));
593#else
594 fprintf (stderr, ": %s\n", xstrerror (errno));
595#endif
596 exit (-1);
597 /* NOTREACHED */
598 return 0;
599
600 default:
601 /* In the parent, after forking.
602 Close the descriptors that we made for this child. */
603 if (input_desc != STDIN_FILE_NO)
604 close (input_desc);
605 if (output_desc != STDOUT_FILE_NO)
606 close (output_desc);
607
608 /* Return child's process number. */
609 return pid;
610 }
611}
612
613int
614pwait (pid, status, flags)
615 int pid;
616 int *status;
617 int flags;
618{
619 /* ??? Here's an opportunity to canonicalize the values in STATUS.
620 Needed? */
621#ifdef VMS
622 pid = waitpid (-1, status, 0);
623#else
624 pid = wait (status);
625#endif
626 return pid;
627}
628
629#endif /* ! __MSDOS__ && ! OS2 && ! MPW && ! _WIN32 */