OSDN Git Service

ebe8c437590ed36816832377d17c394b0a3291be
[pf3gnuchains/gcc-fork.git] / libiberty / pex-common.c
1 /* Common code for executing a program in a sub-process.
2    Copyright (C) 2005 Free Software Foundation, Inc.
3    Written by Ian Lance Taylor <ian@airs.com>.
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., 51 Franklin Street - Fifth Floor,
19 Boston, MA 02110-1301, USA.  */
20
21 #include "config.h"
22 #include "libiberty.h"
23 #include "pex-common.h"
24
25 #include <stdio.h>
26 #include <errno.h>
27 #ifdef NEED_DECLARATION_ERRNO
28 extern int errno;
29 #endif
30 #ifdef HAVE_STDLIB_H
31 #include <stdlib.h>
32 #endif
33 #ifdef HAVE_STRING_H
34 #include <string.h>
35 #endif
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39
40 extern int mkstemps (char *, int);
41
42 /* This file contains subroutines for the program execution routines
43    (pex_init, pex_run, etc.).  This file is compiled on all
44    systems.  */
45
46 static void pex_add_remove (struct pex_obj *, const char *, int);
47 static int pex_get_status_and_time (struct pex_obj *, int, const char **,
48                                     int *);
49
50 /* Initialize a pex_obj structure.  */
51
52 struct pex_obj *
53 pex_init_common (int flags, const char *pname, const char *tempbase,
54                  const struct pex_funcs *funcs)
55 {
56   struct pex_obj *obj;
57
58   obj = XNEW (struct pex_obj);
59   obj->flags = flags;
60   obj->pname = pname;
61   obj->tempbase = tempbase;
62   obj->next_input = STDIN_FILE_NO;
63   obj->next_input_name = NULL;
64   obj->next_input_name_allocated = 0;
65   obj->count = 0;
66   obj->children = NULL;
67   obj->status = NULL;
68   obj->time = NULL;
69   obj->number_waited = 0;
70   obj->input_file = NULL;
71   obj->read_output = NULL;
72   obj->remove_count = 0;
73   obj->remove = NULL;
74   obj->funcs = funcs;
75   obj->sysdep = NULL;
76   return obj;
77 }
78
79 /* Add a file to be removed when we are done.  */
80
81 static void
82 pex_add_remove (struct pex_obj *obj, const char *name, int allocated)
83 {
84   char *add;
85
86   ++obj->remove_count;
87   obj->remove = XRESIZEVEC (char *, obj->remove, obj->remove_count);
88   if (allocated)
89     add = (char *) name;
90   else
91     add = xstrdup (name);
92   obj->remove[obj->remove_count - 1] = add;
93 }
94
95 /* Generate a temporary file name based on OBJ, FLAGS, and NAME.
96    Return NULL if we were unable to reserve a temporary filename.
97
98    If non-NULL, the result is either allocated with malloc, or the
99    same pointer as NAME.  */
100 static char *
101 temp_file (struct pex_obj *obj, int flags, char *name)
102 {
103   if (name == NULL)
104     {
105       if (obj->tempbase == NULL)
106         {
107           name = make_temp_file (NULL);
108         }
109       else
110         {
111           int len = strlen (obj->tempbase);
112           int out;
113
114           if (len >= 6
115               && strcmp (obj->tempbase + len - 6, "XXXXXX") == 0)
116             name = xstrdup (obj->tempbase);
117           else
118             name = concat (obj->tempbase, "XXXXXX", NULL);
119
120           out = mkstemps (name, 0);
121           if (out < 0)
122             {
123               free (name);
124               return NULL;
125             }
126
127           /* This isn't obj->funcs->close because we got the
128              descriptor from mkstemps, not from a function in
129              obj->funcs.  Calling close here is just like what
130              make_temp_file does.  */
131           close (out);
132         }
133     }
134   else if ((flags & PEX_SUFFIX) != 0)
135     {
136       if (obj->tempbase == NULL)
137         name = make_temp_file (name);
138       else
139         name = concat (obj->tempbase, name, NULL);
140     }
141
142   return name;
143 }
144
145 /* Run a program.  */
146
147 const char *
148 pex_run (struct pex_obj *obj, int flags, const char *executable,
149          char * const * argv, const char *orig_outname, const char *errname,
150          int *err)
151 {
152   const char *errmsg;
153   int in, out, errdes;
154   char *outname;
155   int outname_allocated;
156   int p[2];
157   long pid;
158
159   in = -1;
160   out = -1;
161   errdes = -1;
162   outname = (char *) orig_outname;
163   outname_allocated = 0;
164
165   /* If the user called pex_input_file, close the file now.  */
166   if (obj->input_file)
167     {
168       if (fclose (obj->input_file) == EOF)
169         {
170           errmsg = "closing pipeline input file";
171           goto error_exit;
172         }
173       obj->input_file = NULL;
174     }
175
176   /* Set IN.  */
177
178   if (obj->next_input_name != NULL)
179     {
180       /* We have to make sure that the previous process has completed
181          before we try to read the file.  */
182       if (!pex_get_status_and_time (obj, 0, &errmsg, err))
183         goto error_exit;
184
185       in = obj->funcs->open_read (obj, obj->next_input_name,
186                                   (flags & PEX_BINARY_INPUT) != 0);
187       if (in < 0)
188         {
189           *err = errno;
190           errmsg = "open temporary file";
191           goto error_exit;
192         }
193       if (obj->next_input_name_allocated)
194         {
195           free (obj->next_input_name);
196           obj->next_input_name_allocated = 0;
197         }
198       obj->next_input_name = NULL;
199     }
200   else
201     {
202       in = obj->next_input;
203       if (in < 0)
204         {
205           *err = 0;
206           errmsg = "pipeline already complete";
207           goto error_exit;
208         }
209     }
210
211   /* Set OUT and OBJ->NEXT_INPUT/OBJ->NEXT_INPUT_NAME.  */
212
213   if ((flags & PEX_LAST) != 0)
214     {
215       if (outname == NULL)
216         out = STDOUT_FILE_NO;
217       else if ((flags & PEX_SUFFIX) != 0)
218         {
219           outname = concat (obj->tempbase, outname, NULL);
220           outname_allocated = 1;
221         }
222       obj->next_input = -1;
223     }
224   else if ((obj->flags & PEX_USE_PIPES) == 0)
225     {
226       outname = temp_file (obj, flags, outname);
227       if (! outname)
228         {
229           *err = 0;
230           errmsg = "could not create temporary file";
231           goto error_exit;
232         }
233
234       if (outname != orig_outname)
235         outname_allocated = 1;
236
237       if ((obj->flags & PEX_SAVE_TEMPS) == 0)
238         {
239           pex_add_remove (obj, outname, outname_allocated);
240           outname_allocated = 0;
241         }
242
243       /* Hand off ownership of outname to the next stage.  */
244       obj->next_input_name = outname;
245       obj->next_input_name_allocated = outname_allocated;
246       outname_allocated = 0;
247     }
248   else
249     {
250       if (obj->funcs->pipe (obj, p, (flags & PEX_BINARY_OUTPUT) != 0) < 0)
251         {
252           *err = errno;
253           errmsg = "pipe";
254           goto error_exit;
255         }
256
257       out = p[WRITE_PORT];
258       obj->next_input = p[READ_PORT];
259     }
260
261   if (out < 0)
262     {
263       out = obj->funcs->open_write (obj, outname,
264                                     (flags & PEX_BINARY_OUTPUT) != 0);
265       if (out < 0)
266         {
267           *err = errno;
268           errmsg = "open temporary output file";
269           goto error_exit;
270         }
271     }
272
273   if (outname_allocated)
274     {
275       free (outname);
276       outname_allocated = 0;
277     }
278
279   /* Set ERRDES.  */
280
281   if (errname == NULL)
282     errdes = STDERR_FILE_NO;
283   else
284     {
285       /* We assume that stderr is in text mode--it certainly shouldn't
286          be controlled by PEX_BINARY_OUTPUT.  If necessary, we can add
287          a PEX_BINARY_STDERR flag.  */
288       errdes = obj->funcs->open_write (obj, errname, 0);
289       if (errdes < 0)
290         {
291           *err = errno;
292           errmsg = "open error file";
293           goto error_exit;
294         }
295     }
296
297   /* Run the program.  */
298
299   pid = obj->funcs->exec_child (obj, flags, executable, argv, in, out, errdes,
300                                 &errmsg, err);
301   if (pid < 0)
302     goto error_exit;
303
304   ++obj->count;
305   obj->children = XRESIZEVEC (long, obj->children, obj->count);
306   obj->children[obj->count - 1] = pid;
307
308   return NULL;
309
310  error_exit:
311   if (in >= 0 && in != STDIN_FILE_NO)
312     obj->funcs->close (obj, in);
313   if (out >= 0 && out != STDOUT_FILE_NO)
314     obj->funcs->close (obj, out);
315   if (errdes >= 0 && errdes != STDERR_FILE_NO)
316     obj->funcs->close (obj, errdes);
317   if (outname_allocated)
318     free (outname);
319   return errmsg;
320 }
321
322 /* Return a FILE pointer for a temporary file to fill with input for
323    the pipeline.  */
324 FILE *
325 pex_input_file (struct pex_obj *obj, int flags, const char *in_name)
326 {
327   char *name = (char *) in_name;
328   FILE *f;
329
330   /* This must be called before the first pipeline stage is run, and
331      there must not have been any other input selected.  */
332   if (obj->count != 0
333       || (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
334       || obj->next_input_name)
335     {
336       errno = EINVAL;
337       return NULL;
338     }
339
340   name = temp_file (obj, flags, name);
341   if (! name)
342     return NULL;
343
344   f = fopen (name, (flags & PEX_BINARY_OUTPUT) ? "wb" : "w");
345   if (! f)
346     {
347       free (name);
348       return NULL;
349     }
350
351   obj->input_file = f;
352   obj->next_input_name = name;
353   obj->next_input_name_allocated = (name != in_name);
354
355   return f;
356 }
357
358 /* Return a stream for a pipe connected to the standard input of the
359    first stage of the pipeline.  */
360 FILE *
361 pex_input_pipe (struct pex_obj *obj, int binary)
362 {
363   int p[2];
364   FILE *f;
365
366   /* You must call pex_input_pipe before the first pex_run or pex_one.  */
367   if (obj->count > 0)
368     goto usage_error;
369
370   /* You must be using pipes.  Implementations that don't support
371      pipes clear this flag before calling pex_init_common.  */
372   if (! (obj->flags & PEX_USE_PIPES))
373     goto usage_error;
374
375   /* If we have somehow already selected other input, that's a
376      mistake.  */
377   if ((obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
378       || obj->next_input_name)
379     goto usage_error;
380
381   if (obj->funcs->pipe (obj, p, binary != 0) < 0)
382     return NULL;
383
384   f = obj->funcs->fdopenw (obj, p[WRITE_PORT], binary != 0);
385   if (! f)
386     {
387       int saved_errno = errno;
388       obj->funcs->close (obj, p[READ_PORT]);
389       obj->funcs->close (obj, p[WRITE_PORT]);
390       errno = saved_errno;
391       return NULL;
392     }
393
394   obj->next_input = p[READ_PORT];
395
396   return f;
397
398  usage_error:
399   errno = EINVAL;
400   return NULL;
401 }
402
403 /* Return a FILE pointer for the output of the last program
404    executed.  */
405
406 FILE *
407 pex_read_output (struct pex_obj *obj, int binary)
408 {
409   if (obj->next_input_name != NULL)
410     {
411       const char *errmsg;
412       int err;
413
414       /* We have to make sure that the process has completed before we
415          try to read the file.  */
416       if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
417         {
418           errno = err;
419           return NULL;
420         }
421
422       obj->read_output = fopen (obj->next_input_name, binary ? "rb" : "r");
423
424       if (obj->next_input_name_allocated)
425         {
426           free (obj->next_input_name);
427           obj->next_input_name_allocated = 0;
428         }
429       obj->next_input_name = NULL;
430     }
431   else
432     {
433       int o;
434
435       o = obj->next_input;
436       if (o < 0 || o == STDIN_FILE_NO)
437         return NULL;
438       obj->read_output = obj->funcs->fdopenr (obj, o, binary);
439       obj->next_input = -1;
440     }
441
442   return obj->read_output;
443 }
444
445 /* Get the exit status and, if requested, the resource time for all
446    the child processes.  Return 0 on failure, 1 on success.  */
447
448 static int
449 pex_get_status_and_time (struct pex_obj *obj, int done, const char **errmsg,
450                          int *err)
451 {
452   int ret;
453   int i;
454
455   if (obj->number_waited == obj->count)
456     return 1;
457
458   obj->status = XRESIZEVEC (int, obj->status, obj->count);
459   if ((obj->flags & PEX_RECORD_TIMES) != 0)
460     obj->time = XRESIZEVEC (struct pex_time, obj->time, obj->count);
461
462   ret = 1;
463   for (i = obj->number_waited; i < obj->count; ++i)
464     {
465       if (obj->funcs->wait (obj, obj->children[i], &obj->status[i],
466                             obj->time == NULL ? NULL : &obj->time[i],
467                             done, errmsg, err) < 0)
468         ret = 0;
469     }
470   obj->number_waited = i;
471
472   return ret;
473 }
474
475 /* Get exit status of executed programs.  */
476
477 int
478 pex_get_status (struct pex_obj *obj, int count, int *vector)
479 {
480   if (obj->status == NULL)
481     {
482       const char *errmsg;
483       int err;
484
485       if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
486         return 0;
487     }
488
489   if (count > obj->count)
490     {
491       memset (vector + obj->count, 0, (count - obj->count) * sizeof (int));
492       count = obj->count;
493     }
494
495   memcpy (vector, obj->status, count * sizeof (int));
496
497   return 1;
498 }
499
500 /* Get process times of executed programs.  */
501
502 int
503 pex_get_times (struct pex_obj *obj, int count, struct pex_time *vector)
504 {
505   if (obj->status == NULL)
506     {
507       const char *errmsg;
508       int err;
509
510       if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
511         return 0;
512     }
513
514   if (obj->time == NULL)
515     return 0;
516
517   if (count > obj->count)
518     {
519       memset (vector + obj->count, 0,
520               (count - obj->count) * sizeof (struct pex_time));
521       count = obj->count;
522     }
523
524   memcpy (vector, obj->time, count * sizeof (struct pex_time));
525
526   return 1;
527 }
528
529 /* Free a pex_obj structure.  */
530
531 void
532 pex_free (struct pex_obj *obj)
533 {
534   if (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
535     obj->funcs->close (obj, obj->next_input);
536
537   /* If the caller forgot to wait for the children, we do it here, to
538      avoid zombies.  */
539   if (obj->status == NULL)
540     {
541       const char *errmsg;
542       int err;
543
544       obj->flags &= ~ PEX_RECORD_TIMES;
545       pex_get_status_and_time (obj, 1, &errmsg, &err);
546     }
547
548   if (obj->next_input_name_allocated)
549     free (obj->next_input_name);
550   if (obj->children != NULL)
551     free (obj->children);
552   if (obj->status != NULL)
553     free (obj->status);
554   if (obj->time != NULL)
555     free (obj->time);
556   if (obj->read_output != NULL)
557     fclose (obj->read_output);
558
559   if (obj->remove_count > 0)
560     {
561       int i;
562
563       for (i = 0; i < obj->remove_count; ++i)
564         {
565           remove (obj->remove[i]);
566           free (obj->remove[i]);
567         }
568       free (obj->remove);
569     }
570
571   if (obj->funcs->cleanup != NULL)
572     obj->funcs->cleanup (obj);
573
574   free (obj);
575 }