Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / contrib / gcc / 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 /* $FreeBSD: src/contrib/gcc/pexecute.c,v 1.3 1999/11/04 10:26:31 obrien Exp $ */
27 /* $DragonFly: src/contrib/gcc/Attic/pexecute.c,v 1.2 2003/06/17 04:24:01 dillon Exp $ */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <stdio.h>
34 #include <errno.h>
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38 #define ISSPACE (x) isspace(x)
39 #ifdef HAVE_SYS_WAIT_H
40 #include <sys/wait.h>
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) && ! defined (_UWIN)
237
238 #include <process.h>
239
240 #ifdef __CYGWIN__
241
242 #define fix_argv(argvec) (argvec)
243
244 extern int _spawnv ();
245 extern int _spawnvp ();
246
247 #else /* ! __CYGWIN__ */
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
252 const char * const *
253 fix_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 }
285 #endif /* __CYGWIN__ */
286
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
303
304 /* Win32 supports pipes */
305 int
306 pexecute (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;
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     }
363
364   pid = (flags & PEXECUTE_SEARCH ? _spawnvp : _spawnv)
365     (_P_NOWAIT, program, fix_argv(argv));
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
379   if (pid == -1)
380     {
381       *errmsg_fmt = install_error_msg;
382       *errmsg_arg = program;
383       return -1;
384     }
385
386   return pid;
387 }
388
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
396 int
397 pwait (pid, status, flags)
398      int pid;
399      int *status;
400      int flags;
401 {
402 #ifdef __CYGWIN__
403   return wait (status);
404 #else
405   int termstat;
406
407   pid = _cwait (&termstat, pid, WAIT_CHILD);
408
409   /* ??? Here's an opportunity to canonicalize the values in STATUS.
410      Needed?  */
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;
422 #endif /* __CYGWIN__ */
423 }
424
425 #endif /* _WIN32 && ! _UWIN */
426
427 #ifdef OS2
428
429 /* ??? Does OS2 have process.h?  */
430 extern int spawnv ();
431 extern int spawnvp ();
432
433 int
434 pexecute (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
457 int
458 pwait (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
488 static int first_time = 1;
489
490 int
491 pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
492      const char *program;
493      char * const *argv;
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         {
522           fputc ('\'', stdout);
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             }
530           for (cp = argv[i]; *cp; cp++)
531             {
532               /* Write an Option-d escape char in front of special chars.  */
533               if (strchr("'+", *cp))
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     {
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         }
555       if (strchr (argv[i], ' '))
556         fputc ('\'', stdout);
557       for (cp = argv[i]; *cp; cp++)
558         {
559           /* Write an Option-d escape char in front of special chars.  */
560           if (strchr("'+", *cp))
561             fputc ('\266', stdout);
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
585 int
586 pwait (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
598 void
599 pfinish ()
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) && ! defined (_UWIN))
609
610 extern int execv ();
611 extern int execvp ();
612
613 int
614 pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
615      const char *program;
616      char * const *argv;
617      const char *this_pname;
618      const char *temp_base;
619      char **errmsg_fmt, **errmsg_arg;
620      int flags;
621 {
622   int (*func)() = (flags & PEXECUTE_SEARCH ? execvp : execv);
623   int pid;
624   int pdes[2];
625   int input_desc, output_desc;
626   int retries, sleep_interval;
627   /* Pipe waiting from last process, to be used as input for the next one.
628      Value is STDIN_FILE_NO if no pipe is waiting
629      (i.e. the next command is the first of a group).  */
630   static int last_pipe_input;
631
632   /* If this is the first process, initialize.  */
633   if (flags & PEXECUTE_FIRST)
634     last_pipe_input = STDIN_FILE_NO;
635
636   input_desc = last_pipe_input;
637
638   /* If this isn't the last process, make a pipe for its output,
639      and record it as waiting to be the input to the next process.  */
640   if (! (flags & PEXECUTE_LAST))
641     {
642       if (pipe (pdes) < 0)
643         {
644           *errmsg_fmt = "pipe";
645           *errmsg_arg = NULL;
646           return -1;
647         }
648       output_desc = pdes[WRITE_PORT];
649       last_pipe_input = pdes[READ_PORT];
650     }
651   else
652     {
653       /* Last process.  */
654       output_desc = STDOUT_FILE_NO;
655       last_pipe_input = STDIN_FILE_NO;
656     }
657
658   /* Fork a subprocess; wait and retry if it fails.  */
659   sleep_interval = 1;
660   for (retries = 0; retries < 4; retries++)
661     {
662       pid = vfork ();
663       if (pid >= 0)
664         break;
665       sleep (sleep_interval);
666       sleep_interval *= 2;
667     }
668
669   switch (pid)
670     {
671     case -1:
672       {
673         *errmsg_fmt = VFORK_STRING;
674         *errmsg_arg = NULL;
675         return -1;
676       }
677
678     case 0: /* child */
679       /* Move the input and output pipes into place, if necessary.  */
680       if (input_desc != STDIN_FILE_NO)
681         {
682           close (STDIN_FILE_NO);
683           dup (input_desc);
684           close (input_desc);
685         }
686       if (output_desc != STDOUT_FILE_NO)
687         {
688           close (STDOUT_FILE_NO);
689           dup (output_desc);
690           close (output_desc);
691         }
692
693       /* Close the parent's descs that aren't wanted here.  */
694       if (last_pipe_input != STDIN_FILE_NO)
695         close (last_pipe_input);
696
697       /* Exec the program.  */
698       (*func) (program, argv);
699
700       /* Note: Calling fprintf and exit here doesn't seem right for vfork.  */
701       fprintf (stderr, "%s: ", this_pname);
702       fprintf (stderr, install_error_msg, program);
703       fprintf (stderr, ": %s\n", xstrerror (errno));
704       _exit (1);
705       /* NOTREACHED */
706       return 0;
707
708     default:
709       /* In the parent, after forking.
710          Close the descriptors that we made for this child.  */
711       if (input_desc != STDIN_FILE_NO)
712         close (input_desc);
713       if (output_desc != STDOUT_FILE_NO)
714         close (output_desc);
715
716       /* Return child's process number.  */
717       return pid;
718     }
719 }
720
721 int
722 pwait (pid, status, flags)
723      int pid;
724      int *status;
725      int flags;
726 {
727   /* ??? Here's an opportunity to canonicalize the values in STATUS.
728      Needed?  */
729 #ifdef VMS
730   pid = waitpid (-1, status, 0);
731 #else
732   pid = wait (status);
733 #endif
734   return pid;
735 }
736
737 #endif /* ! __MSDOS__ && ! OS2 && ! MPW && ! (_WIN32 && ! _UWIN) */