]> gcc.gnu.org Git - gcc.git/blob - libiberty/pexecute.c
choose-temp.c: Always include libiberty.h.
[gcc.git] / libiberty / pexecute.c
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, 1998 Free Software Foundation, Inc.
4
5 This file is part of the libiberty library.
6 Libiberty is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 Libiberty is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public
17 License along with libiberty; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, 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
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 #ifdef IN_GCC
30 #include "system.h"
31 #else
32 #include <stdio.h>
33 #include <errno.h>
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37 #define ISSPACE (x) isspace(x)
38 #ifdef HAVE_SYS_WAIT_H
39 #include <sys/wait.h>
40 #endif
41 #endif
42
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
56 #include "libiberty.h"
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
70 static 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. */
132 static int last_pid = 0;
133 static int last_status = 0;
134 static int last_reaped = 0;
135
136 int
137 pexecute (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 {
182 if (*cp == '"' || *cp == '\'' || *cp == '\\' || ISSPACE (*cp))
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
212 int
213 pwait (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>
239
240 #ifdef __CYGWIN32__
241
242 #define fix_argv(argvec) (argvec)
243
244 extern int _spawnv ();
245 extern int _spawnvp ();
246
247 int
248 pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
249 const char *program;
250 char * const *argv;
251 const char *this_pname;
252 const char *temp_base;
253 char **errmsg_fmt, **errmsg_arg;
254 int flags;
255 {
256 int pid;
257
258 if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
259 abort ();
260 pid = (flags & PEXECUTE_SEARCH ? _spawnvp : _spawnv)
261 (_P_NOWAIT, program, fix_argv(argv));
262 if (pid == -1)
263 {
264 *errmsg_fmt = install_error_msg;
265 *errmsg_arg = program;
266 return -1;
267 }
268 return pid;
269 }
270
271 int
272 pwait (pid, status, flags)
273 int pid;
274 int *status;
275 int flags;
276 {
277 /* ??? Here's an opportunity to canonicalize the values in STATUS.
278 Needed? */
279 return cwait (status, pid, WAIT_CHILD);
280 }
281
282 #else /* ! __CYGWIN32__ */
283
284 /* This is a kludge to get around the Microsoft C spawn functions' propensity
285 to remove the outermost set of double quotes from all arguments. */
286
287 const char * const *
288 fix_argv (argvec)
289 char **argvec;
290 {
291 int i;
292
293 for (i = 1; argvec[i] != 0; i++)
294 {
295 int len, j;
296 char *temp, *newtemp;
297
298 temp = argvec[i];
299 len = strlen (temp);
300 for (j = 0; j < len; j++)
301 {
302 if (temp[j] == '"')
303 {
304 newtemp = xmalloc (len + 2);
305 strncpy (newtemp, temp, j);
306 newtemp [j] = '\\';
307 strncpy (&newtemp [j+1], &temp [j], len-j);
308 newtemp [len+1] = 0;
309 temp = newtemp;
310 len++;
311 j++;
312 }
313 }
314
315 argvec[i] = temp;
316 }
317
318 return (const char * const *) argvec;
319 }
320
321 #include <io.h>
322 #include <fcntl.h>
323 #include <signal.h>
324
325 /* mingw32 headers may not define the following. */
326
327 #ifndef _P_WAIT
328 # define _P_WAIT 0
329 # define _P_NOWAIT 1
330 # define _P_OVERLAY 2
331 # define _P_NOWAITO 3
332 # define _P_DETACH 4
333
334 # define WAIT_CHILD 0
335 # define WAIT_GRANDCHILD 1
336 #endif
337
338 /* Win32 supports pipes */
339 int
340 pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
341 const char *program;
342 char * const *argv;
343 const char *this_pname;
344 const char *temp_base;
345 char **errmsg_fmt, **errmsg_arg;
346 int flags;
347 {
348 int pid;
349 int pdes[2], org_stdin, org_stdout;
350 int input_desc, output_desc;
351 int retries, sleep_interval;
352
353 /* Pipe waiting from last process, to be used as input for the next one.
354 Value is STDIN_FILE_NO if no pipe is waiting
355 (i.e. the next command is the first of a group). */
356 static int last_pipe_input;
357
358 /* If this is the first process, initialize. */
359 if (flags & PEXECUTE_FIRST)
360 last_pipe_input = STDIN_FILE_NO;
361
362 input_desc = last_pipe_input;
363
364 /* If this isn't the last process, make a pipe for its output,
365 and record it as waiting to be the input to the next process. */
366 if (! (flags & PEXECUTE_LAST))
367 {
368 if (_pipe (pdes, 256, O_BINARY) < 0)
369 {
370 *errmsg_fmt = "pipe";
371 *errmsg_arg = NULL;
372 return -1;
373 }
374 output_desc = pdes[WRITE_PORT];
375 last_pipe_input = pdes[READ_PORT];
376 }
377 else
378 {
379 /* Last process. */
380 output_desc = STDOUT_FILE_NO;
381 last_pipe_input = STDIN_FILE_NO;
382 }
383
384 if (input_desc != STDIN_FILE_NO)
385 {
386 org_stdin = dup (STDIN_FILE_NO);
387 dup2 (input_desc, STDIN_FILE_NO);
388 close (input_desc);
389 }
390
391 if (output_desc != STDOUT_FILE_NO)
392 {
393 org_stdout = dup (STDOUT_FILE_NO);
394 dup2 (output_desc, STDOUT_FILE_NO);
395 close (output_desc);
396 }
397
398 pid = (flags & PEXECUTE_SEARCH ? _spawnvp : _spawnv)
399 (_P_NOWAIT, program, fix_argv(argv));
400
401 if (input_desc != STDIN_FILE_NO)
402 {
403 dup2 (org_stdin, STDIN_FILE_NO);
404 close (org_stdin);
405 }
406
407 if (output_desc != STDOUT_FILE_NO)
408 {
409 dup2 (org_stdout, STDOUT_FILE_NO);
410 close (org_stdout);
411 }
412
413 if (pid == -1)
414 {
415 *errmsg_fmt = install_error_msg;
416 *errmsg_arg = program;
417 return -1;
418 }
419
420 return pid;
421 }
422
423 /* MS CRTDLL doesn't return enough information in status to decide if the
424 child exited due to a signal or not, rather it simply returns an
425 integer with the exit code of the child; eg., if the child exited with
426 an abort() call and didn't have a handler for SIGABRT, it simply returns
427 with status = 3. We fix the status code to conform to the usual WIF*
428 macros. Note that WIFSIGNALED will never be true under CRTDLL. */
429
430 int
431 pwait (pid, status, flags)
432 int pid;
433 int *status;
434 int flags;
435 {
436 int termstat;
437
438 pid = _cwait (&termstat, pid, WAIT_CHILD);
439
440 /* ??? Here's an opportunity to canonicalize the values in STATUS.
441 Needed? */
442
443 /* cwait returns the child process exit code in termstat.
444 A value of 3 indicates that the child caught a signal, but not
445 which one. Since only SIGABRT, SIGFPE and SIGINT do anything, we
446 report SIGABRT. */
447 if (termstat == 3)
448 *status = SIGABRT;
449 else
450 *status = (((termstat) & 0xff) << 8);
451
452 return pid;
453 }
454
455 #endif /* ! defined (__CYGWIN32__) */
456
457 #endif /* _WIN32 */
458
459 #ifdef OS2
460
461 /* ??? Does OS2 have process.h? */
462 extern int spawnv ();
463 extern int spawnvp ();
464
465 int
466 pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
467 const char *program;
468 char * const *argv;
469 const char *this_pname;
470 const char *temp_base;
471 char **errmsg_fmt, **errmsg_arg;
472 int flags;
473 {
474 int pid;
475
476 if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
477 abort ();
478 /* ??? Presumably 1 == _P_NOWAIT. */
479 pid = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (1, program, argv);
480 if (pid == -1)
481 {
482 *errmsg_fmt = install_error_msg;
483 *errmsg_arg = program;
484 return -1;
485 }
486 return pid;
487 }
488
489 int
490 pwait (pid, status, flags)
491 int pid;
492 int *status;
493 int flags;
494 {
495 /* ??? Here's an opportunity to canonicalize the values in STATUS.
496 Needed? */
497 int pid = wait (status);
498 return pid;
499 }
500
501 #endif /* OS2 */
502
503 #ifdef MPW
504
505 /* MPW pexecute doesn't actually run anything; instead, it writes out
506 script commands that, when run, will do the actual executing.
507
508 For example, in GCC's case, GCC will write out several script commands:
509
510 cpp ...
511 cc1 ...
512 as ...
513 ld ...
514
515 and then exit. None of the above programs will have run yet. The task
516 that called GCC will then execute the script and cause cpp,etc. to run.
517 The caller must invoke pfinish before calling exit. This adds
518 the finishing touches to the generated script. */
519
520 static int first_time = 1;
521
522 int
523 pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
524 const char *program;
525 char * const *argv;
526 const char *this_pname;
527 const char *temp_base;
528 char **errmsg_fmt, **errmsg_arg;
529 int flags;
530 {
531 char tmpprogram[255];
532 char *cp, *tmpname;
533 int i;
534
535 mpwify_filename (program, tmpprogram);
536 if (first_time)
537 {
538 printf ("Set Failed 0\n");
539 first_time = 0;
540 }
541
542 fputs ("If {Failed} == 0\n", stdout);
543 /* If being verbose, output a copy of the command. It should be
544 accurate enough and escaped enough to be "clickable". */
545 if (flags & PEXECUTE_VERBOSE)
546 {
547 fputs ("\tEcho ", stdout);
548 fputc ('\'', stdout);
549 fputs (tmpprogram, stdout);
550 fputc ('\'', stdout);
551 fputc (' ', stdout);
552 for (i=1; argv[i]; i++)
553 {
554 fputc ('\'', stdout);
555 /* See if we have an argument that needs fixing. */
556 if (strchr(argv[i], '/'))
557 {
558 tmpname = (char *) xmalloc (256);
559 mpwify_filename (argv[i], tmpname);
560 argv[i] = tmpname;
561 }
562 for (cp = argv[i]; *cp; cp++)
563 {
564 /* Write an Option-d escape char in front of special chars. */
565 if (strchr("'+", *cp))
566 fputc ('\266', stdout);
567 fputc (*cp, stdout);
568 }
569 fputc ('\'', stdout);
570 fputc (' ', stdout);
571 }
572 fputs ("\n", stdout);
573 }
574 fputs ("\t", stdout);
575 fputs (tmpprogram, stdout);
576 fputc (' ', stdout);
577
578 for (i=1; argv[i]; i++)
579 {
580 /* See if we have an argument that needs fixing. */
581 if (strchr(argv[i], '/'))
582 {
583 tmpname = (char *) xmalloc (256);
584 mpwify_filename (argv[i], tmpname);
585 argv[i] = tmpname;
586 }
587 if (strchr (argv[i], ' '))
588 fputc ('\'', stdout);
589 for (cp = argv[i]; *cp; cp++)
590 {
591 /* Write an Option-d escape char in front of special chars. */
592 if (strchr("'+", *cp))
593 fputc ('\266', stdout);
594 fputc (*cp, stdout);
595 }
596 if (strchr (argv[i], ' '))
597 fputc ('\'', stdout);
598 fputc (' ', stdout);
599 }
600
601 fputs ("\n", stdout);
602
603 /* Output commands that arrange to clean up and exit if a failure occurs.
604 We have to be careful to collect the status from the program that was
605 run, rather than some other script command. Also, we don't exit
606 immediately, since necessary cleanups are at the end of the script. */
607 fputs ("\tSet TmpStatus {Status}\n", stdout);
608 fputs ("\tIf {TmpStatus} != 0\n", stdout);
609 fputs ("\t\tSet Failed {TmpStatus}\n", stdout);
610 fputs ("\tEnd\n", stdout);
611 fputs ("End\n", stdout);
612
613 /* We're just composing a script, can't fail here. */
614 return 0;
615 }
616
617 int
618 pwait (pid, status, flags)
619 int pid;
620 int *status;
621 int flags;
622 {
623 *status = 0;
624 return 0;
625 }
626
627 /* Write out commands that will exit with the correct error code
628 if something in the script failed. */
629
630 void
631 pfinish ()
632 {
633 printf ("\tExit \"{Failed}\"\n");
634 }
635
636 #endif /* MPW */
637
638 /* include for Unix-like environments but not for Dos-like environments */
639 #if ! defined (__MSDOS__) && ! defined (OS2) && ! defined (MPW) \
640 && ! defined (_WIN32)
641
642 extern int execv ();
643 extern int execvp ();
644 #ifdef IN_GCC
645 extern char * my_strerror PROTO ((int));
646 #endif
647
648 int
649 pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
650 const char *program;
651 char * const *argv;
652 const char *this_pname;
653 const char *temp_base;
654 char **errmsg_fmt, **errmsg_arg;
655 int flags;
656 {
657 int (*func)() = (flags & PEXECUTE_SEARCH ? execvp : execv);
658 int pid;
659 int pdes[2];
660 int input_desc, output_desc;
661 int retries, sleep_interval;
662 /* Pipe waiting from last process, to be used as input for the next one.
663 Value is STDIN_FILE_NO if no pipe is waiting
664 (i.e. the next command is the first of a group). */
665 static int last_pipe_input;
666
667 /* If this is the first process, initialize. */
668 if (flags & PEXECUTE_FIRST)
669 last_pipe_input = STDIN_FILE_NO;
670
671 input_desc = last_pipe_input;
672
673 /* If this isn't the last process, make a pipe for its output,
674 and record it as waiting to be the input to the next process. */
675 if (! (flags & PEXECUTE_LAST))
676 {
677 if (pipe (pdes) < 0)
678 {
679 *errmsg_fmt = "pipe";
680 *errmsg_arg = NULL;
681 return -1;
682 }
683 output_desc = pdes[WRITE_PORT];
684 last_pipe_input = pdes[READ_PORT];
685 }
686 else
687 {
688 /* Last process. */
689 output_desc = STDOUT_FILE_NO;
690 last_pipe_input = STDIN_FILE_NO;
691 }
692
693 /* Fork a subprocess; wait and retry if it fails. */
694 sleep_interval = 1;
695 for (retries = 0; retries < 4; retries++)
696 {
697 pid = vfork ();
698 if (pid >= 0)
699 break;
700 sleep (sleep_interval);
701 sleep_interval *= 2;
702 }
703
704 switch (pid)
705 {
706 case -1:
707 {
708 *errmsg_fmt = VFORK_STRING;
709 *errmsg_arg = NULL;
710 return -1;
711 }
712
713 case 0: /* child */
714 /* Move the input and output pipes into place, if necessary. */
715 if (input_desc != STDIN_FILE_NO)
716 {
717 close (STDIN_FILE_NO);
718 dup (input_desc);
719 close (input_desc);
720 }
721 if (output_desc != STDOUT_FILE_NO)
722 {
723 close (STDOUT_FILE_NO);
724 dup (output_desc);
725 close (output_desc);
726 }
727
728 /* Close the parent's descs that aren't wanted here. */
729 if (last_pipe_input != STDIN_FILE_NO)
730 close (last_pipe_input);
731
732 /* Exec the program. */
733 (*func) (program, argv);
734
735 /* Note: Calling fprintf and exit here doesn't seem right for vfork. */
736 fprintf (stderr, "%s: ", this_pname);
737 fprintf (stderr, install_error_msg, program);
738 #ifdef IN_GCC
739 fprintf (stderr, ": %s\n", my_strerror (errno));
740 #else
741 fprintf (stderr, ": %s\n", xstrerror (errno));
742 #endif
743 exit (-1);
744 /* NOTREACHED */
745 return 0;
746
747 default:
748 /* In the parent, after forking.
749 Close the descriptors that we made for this child. */
750 if (input_desc != STDIN_FILE_NO)
751 close (input_desc);
752 if (output_desc != STDOUT_FILE_NO)
753 close (output_desc);
754
755 /* Return child's process number. */
756 return pid;
757 }
758 }
759
760 int
761 pwait (pid, status, flags)
762 int pid;
763 int *status;
764 int flags;
765 {
766 /* ??? Here's an opportunity to canonicalize the values in STATUS.
767 Needed? */
768 #ifdef VMS
769 pid = waitpid (-1, status, 0);
770 #else
771 pid = wait (status);
772 #endif
773 return pid;
774 }
775
776 #endif /* ! __MSDOS__ && ! OS2 && ! MPW && ! _WIN32 */
This page took 2.604146 seconds and 6 git commands to generate.