]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/gcclibs/libiberty/pex-common.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / gcclibs / 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
146 /* As for pex_run (), but permits the environment for the child process
147    to be specified. */
148
149 const char *
150 pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable,
151                         char * const * argv, char * const * env,
152                         const char *orig_outname, const char *errname,
153                         int *err)
154 {
155   const char *errmsg;
156   int in, out, errdes;
157   char *outname;
158   int outname_allocated;
159   int p[2];
160   int toclose;
161   long pid;
162
163   in = -1;
164   out = -1;
165   errdes = -1;
166   outname = (char *) orig_outname;
167   outname_allocated = 0;
168
169   /* If the user called pex_input_file, close the file now.  */
170   if (obj->input_file)
171     {
172       if (fclose (obj->input_file) == EOF)
173         {
174           errmsg = "closing pipeline input file";
175           goto error_exit;
176         }
177       obj->input_file = NULL;
178     }
179
180   /* Set IN.  */
181
182   if (obj->next_input_name != NULL)
183     {
184       /* We have to make sure that the previous process has completed
185          before we try to read the file.  */
186       if (!pex_get_status_and_time (obj, 0, &errmsg, err))
187         goto error_exit;
188
189       in = obj->funcs->open_read (obj, obj->next_input_name,
190                                   (flags & PEX_BINARY_INPUT) != 0);
191       if (in < 0)
192         {
193           *err = errno;
194           errmsg = "open temporary file";
195           goto error_exit;
196         }
197       if (obj->next_input_name_allocated)
198         {
199           free (obj->next_input_name);
200           obj->next_input_name_allocated = 0;
201         }
202       obj->next_input_name = NULL;
203     }
204   else
205     {
206       in = obj->next_input;
207       if (in < 0)
208         {
209           *err = 0;
210           errmsg = "pipeline already complete";
211           goto error_exit;
212         }
213     }
214
215   /* Set OUT and OBJ->NEXT_INPUT/OBJ->NEXT_INPUT_NAME.  */
216
217   if ((flags & PEX_LAST) != 0)
218     {
219       if (outname == NULL)
220         out = STDOUT_FILE_NO;
221       else if ((flags & PEX_SUFFIX) != 0)
222         {
223           outname = concat (obj->tempbase, outname, NULL);
224           outname_allocated = 1;
225         }
226       obj->next_input = -1;
227     }
228   else if ((obj->flags & PEX_USE_PIPES) == 0)
229     {
230       outname = temp_file (obj, flags, outname);
231       if (! outname)
232         {
233           *err = 0;
234           errmsg = "could not create temporary file";
235           goto error_exit;
236         }
237
238       if (outname != orig_outname)
239         outname_allocated = 1;
240
241       if ((obj->flags & PEX_SAVE_TEMPS) == 0)
242         {
243           pex_add_remove (obj, outname, outname_allocated);
244           outname_allocated = 0;
245         }
246
247       /* Hand off ownership of outname to the next stage.  */
248       obj->next_input_name = outname;
249       obj->next_input_name_allocated = outname_allocated;
250       outname_allocated = 0;
251     }
252   else
253     {
254       if (obj->funcs->pipe (obj, p, (flags & PEX_BINARY_OUTPUT) != 0) < 0)
255         {
256           *err = errno;
257           errmsg = "pipe";
258           goto error_exit;
259         }
260
261       out = p[WRITE_PORT];
262       obj->next_input = p[READ_PORT];
263     }
264
265   if (out < 0)
266     {
267       out = obj->funcs->open_write (obj, outname,
268                                     (flags & PEX_BINARY_OUTPUT) != 0);
269       if (out < 0)
270         {
271           *err = errno;
272           errmsg = "open temporary output file";
273           goto error_exit;
274         }
275     }
276
277   if (outname_allocated)
278     {
279       free (outname);
280       outname_allocated = 0;
281     }
282
283   /* Set ERRDES.  */
284
285   if (errname == NULL)
286     errdes = STDERR_FILE_NO;
287   else
288     {
289       /* We assume that stderr is in text mode--it certainly shouldn't
290          be controlled by PEX_BINARY_OUTPUT.  If necessary, we can add
291          a PEX_BINARY_STDERR flag.  */
292       errdes = obj->funcs->open_write (obj, errname, 0);
293       if (errdes < 0)
294         {
295           *err = errno;
296           errmsg = "open error file";
297           goto error_exit;
298         }
299     }
300
301   /* If we are using pipes, the child process has to close the next
302      input pipe.  */
303
304   if ((obj->flags & PEX_USE_PIPES) == 0)
305     toclose = -1;
306   else
307     toclose = obj->next_input;
308
309   /* Run the program.  */
310
311   pid = obj->funcs->exec_child (obj, flags, executable, argv, env,
312                                 in, out, errdes, toclose, &errmsg, err);
313   if (pid < 0)
314     goto error_exit;
315
316   ++obj->count;
317   obj->children = XRESIZEVEC (long, obj->children, obj->count);
318   obj->children[obj->count - 1] = pid;
319
320   return NULL;
321
322  error_exit:
323   if (in >= 0 && in != STDIN_FILE_NO)
324     obj->funcs->close (obj, in);
325   if (out >= 0 && out != STDOUT_FILE_NO)
326     obj->funcs->close (obj, out);
327   if (errdes >= 0 && errdes != STDERR_FILE_NO)
328     obj->funcs->close (obj, errdes);
329   if (outname_allocated)
330     free (outname);
331   return errmsg;
332 }
333
334 /* Run a program.  */
335
336 const char *
337 pex_run (struct pex_obj *obj, int flags, const char *executable,
338          char * const * argv, const char *orig_outname, const char *errname,
339          int *err)
340 {
341   return pex_run_in_environment (obj, flags, executable, argv, NULL,
342                                  orig_outname, errname, err);
343 }
344
345 /* Return a FILE pointer for a temporary file to fill with input for
346    the pipeline.  */
347 FILE *
348 pex_input_file (struct pex_obj *obj, int flags, const char *in_name)
349 {
350   char *name = (char *) in_name;
351   FILE *f;
352
353   /* This must be called before the first pipeline stage is run, and
354      there must not have been any other input selected.  */
355   if (obj->count != 0
356       || (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
357       || obj->next_input_name)
358     {
359       errno = EINVAL;
360       return NULL;
361     }
362
363   name = temp_file (obj, flags, name);
364   if (! name)
365     return NULL;
366
367   f = fopen (name, (flags & PEX_BINARY_OUTPUT) ? "wb" : "w");
368   if (! f)
369     {
370       free (name);
371       return NULL;
372     }
373
374   obj->input_file = f;
375   obj->next_input_name = name;
376   obj->next_input_name_allocated = (name != in_name);
377
378   return f;
379 }
380
381 /* Return a stream for a pipe connected to the standard input of the
382    first stage of the pipeline.  */
383 FILE *
384 pex_input_pipe (struct pex_obj *obj, int binary)
385 {
386   int p[2];
387   FILE *f;
388
389   /* You must call pex_input_pipe before the first pex_run or pex_one.  */
390   if (obj->count > 0)
391     goto usage_error;
392
393   /* You must be using pipes.  Implementations that don't support
394      pipes clear this flag before calling pex_init_common.  */
395   if (! (obj->flags & PEX_USE_PIPES))
396     goto usage_error;
397
398   /* If we have somehow already selected other input, that's a
399      mistake.  */
400   if ((obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
401       || obj->next_input_name)
402     goto usage_error;
403
404   if (obj->funcs->pipe (obj, p, binary != 0) < 0)
405     return NULL;
406
407   f = obj->funcs->fdopenw (obj, p[WRITE_PORT], binary != 0);
408   if (! f)
409     {
410       int saved_errno = errno;
411       obj->funcs->close (obj, p[READ_PORT]);
412       obj->funcs->close (obj, p[WRITE_PORT]);
413       errno = saved_errno;
414       return NULL;
415     }
416
417   obj->next_input = p[READ_PORT];
418
419   return f;
420
421  usage_error:
422   errno = EINVAL;
423   return NULL;
424 }
425
426 /* Return a FILE pointer for the output of the last program
427    executed.  */
428
429 FILE *
430 pex_read_output (struct pex_obj *obj, int binary)
431 {
432   if (obj->next_input_name != NULL)
433     {
434       const char *errmsg;
435       int err;
436
437       /* We have to make sure that the process has completed before we
438          try to read the file.  */
439       if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
440         {
441           errno = err;
442           return NULL;
443         }
444
445       obj->read_output = fopen (obj->next_input_name, binary ? "rb" : "r");
446
447       if (obj->next_input_name_allocated)
448         {
449           free (obj->next_input_name);
450           obj->next_input_name_allocated = 0;
451         }
452       obj->next_input_name = NULL;
453     }
454   else
455     {
456       int o;
457
458       o = obj->next_input;
459       if (o < 0 || o == STDIN_FILE_NO)
460         return NULL;
461       obj->read_output = obj->funcs->fdopenr (obj, o, binary);
462       obj->next_input = -1;
463     }
464
465   return obj->read_output;
466 }
467
468 /* Get the exit status and, if requested, the resource time for all
469    the child processes.  Return 0 on failure, 1 on success.  */
470
471 static int
472 pex_get_status_and_time (struct pex_obj *obj, int done, const char **errmsg,
473                          int *err)
474 {
475   int ret;
476   int i;
477
478   if (obj->number_waited == obj->count)
479     return 1;
480
481   obj->status = XRESIZEVEC (int, obj->status, obj->count);
482   if ((obj->flags & PEX_RECORD_TIMES) != 0)
483     obj->time = XRESIZEVEC (struct pex_time, obj->time, obj->count);
484
485   ret = 1;
486   for (i = obj->number_waited; i < obj->count; ++i)
487     {
488       if (obj->funcs->wait (obj, obj->children[i], &obj->status[i],
489                             obj->time == NULL ? NULL : &obj->time[i],
490                             done, errmsg, err) < 0)
491         ret = 0;
492     }
493   obj->number_waited = i;
494
495   return ret;
496 }
497
498 /* Get exit status of executed programs.  */
499
500 int
501 pex_get_status (struct pex_obj *obj, int count, int *vector)
502 {
503   if (obj->status == NULL)
504     {
505       const char *errmsg;
506       int err;
507
508       if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
509         return 0;
510     }
511
512   if (count > obj->count)
513     {
514       memset (vector + obj->count, 0, (count - obj->count) * sizeof (int));
515       count = obj->count;
516     }
517
518   memcpy (vector, obj->status, count * sizeof (int));
519
520   return 1;
521 }
522
523 /* Get process times of executed programs.  */
524
525 int
526 pex_get_times (struct pex_obj *obj, int count, struct pex_time *vector)
527 {
528   if (obj->status == NULL)
529     {
530       const char *errmsg;
531       int err;
532
533       if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
534         return 0;
535     }
536
537   if (obj->time == NULL)
538     return 0;
539
540   if (count > obj->count)
541     {
542       memset (vector + obj->count, 0,
543               (count - obj->count) * sizeof (struct pex_time));
544       count = obj->count;
545     }
546
547   memcpy (vector, obj->time, count * sizeof (struct pex_time));
548
549   return 1;
550 }
551
552 /* Free a pex_obj structure.  */
553
554 void
555 pex_free (struct pex_obj *obj)
556 {
557   if (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
558     obj->funcs->close (obj, obj->next_input);
559
560   /* If the caller forgot to wait for the children, we do it here, to
561      avoid zombies.  */
562   if (obj->status == NULL)
563     {
564       const char *errmsg;
565       int err;
566
567       obj->flags &= ~ PEX_RECORD_TIMES;
568       pex_get_status_and_time (obj, 1, &errmsg, &err);
569     }
570
571   if (obj->next_input_name_allocated)
572     free (obj->next_input_name);
573   if (obj->children != NULL)
574     free (obj->children);
575   if (obj->status != NULL)
576     free (obj->status);
577   if (obj->time != NULL)
578     free (obj->time);
579   if (obj->read_output != NULL)
580     fclose (obj->read_output);
581
582   if (obj->remove_count > 0)
583     {
584       int i;
585
586       for (i = 0; i < obj->remove_count; ++i)
587         {
588           remove (obj->remove[i]);
589           free (obj->remove[i]);
590         }
591       free (obj->remove);
592     }
593
594   if (obj->funcs->cleanup != NULL)
595     obj->funcs->cleanup (obj);
596
597   free (obj);
598 }