OSDN Git Service

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