OSDN Git Service

* config/xtensa/lib1funcs.asm (__udivsi3, __divsi3): Rearrange special
[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 = xmalloc (sizeof (*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->read_output = NULL;
71   obj->remove_count = 0;
72   obj->remove = NULL;
73   obj->funcs = funcs;
74   obj->sysdep = NULL;
75   return obj;
76 }
77
78 /* Add a file to be removed when we are done.  */
79
80 static void
81 pex_add_remove (struct pex_obj *obj, const char *name, int allocated)
82 {
83   char *add;
84
85   ++obj->remove_count;
86   obj->remove = xrealloc (obj->remove, obj->remove_count * sizeof (char *));
87   if (allocated)
88     add = (char *) name;
89   else
90     add = xstrdup (name);
91   obj->remove[obj->remove_count - 1] = add;
92 }
93
94 /* Run a program.  */
95
96 const char *
97 pex_run (struct pex_obj *obj, int flags, const char *executable,
98          char * const * argv, const char *orig_outname, const char *errname,
99          int *err)
100 {
101   const char *errmsg;
102   int in, out, errdes;
103   char *outname;
104   int outname_allocated;
105   int p[2];
106   long pid;
107
108   in = -1;
109   out = -1;
110   errdes = -1;
111   outname = (char *) orig_outname;
112   outname_allocated = 0;
113
114   /* Set IN.  */
115
116   if (obj->next_input_name != NULL)
117     {
118       /* We have to make sure that the previous process has completed
119          before we try to read the file.  */
120       if (!pex_get_status_and_time (obj, 0, &errmsg, err))
121         goto error_exit;
122
123       in = obj->funcs->open_read (obj, obj->next_input_name,
124                                   (flags & PEX_BINARY_INPUT) != 0);
125       if (in < 0)
126         {
127           *err = errno;
128           errmsg = "open temporary file";
129           goto error_exit;
130         }
131       if (obj->next_input_name_allocated)
132         {
133           free (obj->next_input_name);
134           obj->next_input_name_allocated = 0;
135         }
136       obj->next_input_name = NULL;
137     }
138   else
139     {
140       in = obj->next_input;
141       if (in < 0)
142         {
143           *err = 0;
144           errmsg = "pipeline already complete";
145           goto error_exit;
146         }
147     }
148
149   /* Set OUT and OBJ->NEXT_INPUT/OBJ->NEXT_INPUT_NAME.  */
150
151   if ((flags & PEX_LAST) != 0)
152     {
153       if (outname == NULL)
154         out = STDOUT_FILE_NO;
155       else if ((flags & PEX_SUFFIX) != 0)
156         {
157           outname = concat (obj->tempbase, outname, NULL);
158           outname_allocated = 1;
159         }
160       obj->next_input = -1;
161     }
162   else if ((obj->flags & PEX_USE_PIPES) == 0)
163     {
164       if (outname == NULL)
165         {
166           if (obj->tempbase == NULL)
167             {
168               outname = make_temp_file (NULL);
169               outname_allocated = 1;
170             }
171           else
172             {
173               int len = strlen (obj->tempbase);
174
175               if (len >= 6
176                   && strcmp (obj->tempbase + len - 6, "XXXXXX") == 0)
177                 outname = xstrdup (obj->tempbase);
178               else
179                 outname = concat (obj->tempbase, "XXXXXX", NULL);
180
181               outname_allocated = 1;
182
183               out = mkstemps (outname, 0);
184               if (out < 0)
185                 {
186                   *err = 0;
187                   errmsg = "could not create temporary output file";
188                   goto error_exit;
189                 }
190
191               /* This isn't obj->funcs->close because we got the
192                  descriptor from mkstemps, not from a function in
193                  obj->funcs.  Calling close here is just like what
194                  make_temp_file does.  */
195               close (out);
196               out = -1;
197             }
198         }
199       else if ((flags & PEX_SUFFIX) != 0)
200         {
201           if (obj->tempbase == NULL)
202             outname = make_temp_file (outname);
203           else
204             outname = concat (obj->tempbase, outname, NULL);
205           outname_allocated = 1;
206         }
207
208       if ((obj->flags & PEX_SAVE_TEMPS) == 0)
209         {
210           pex_add_remove (obj, outname, outname_allocated);
211           outname_allocated = 0;
212         }
213
214       if (!outname_allocated)
215         {
216           obj->next_input_name = outname;
217           obj->next_input_name_allocated = 0;
218         }
219       else
220         {
221           obj->next_input_name = outname;
222           outname_allocated = 0;
223           obj->next_input_name_allocated = 1;
224         }
225     }
226   else
227     {
228       if (obj->funcs->pipe (obj, p, (flags & PEX_BINARY_OUTPUT) != 0) < 0)
229         {
230           *err = errno;
231           errmsg = "pipe";
232           goto error_exit;
233         }
234
235       out = p[WRITE_PORT];
236       obj->next_input = p[READ_PORT];
237     }
238
239   if (out < 0)
240     {
241       out = obj->funcs->open_write (obj, outname,
242                                     (flags & PEX_BINARY_OUTPUT) != 0);
243       if (out < 0)
244         {
245           *err = errno;
246           errmsg = "open temporary output file";
247           goto error_exit;
248         }
249     }
250
251   if (outname_allocated)
252     {
253       free (outname);
254       outname_allocated = 0;
255     }
256
257   /* Set ERRDES.  */
258
259   if (errname == NULL)
260     errdes = STDERR_FILE_NO;
261   else
262     {
263       /* We assume that stderr is in text mode--it certainly shouldn't
264          be controlled by PEX_BINARY_OUTPUT.  If necessary, we can add
265          a PEX_BINARY_STDERR flag.  */
266       errdes = obj->funcs->open_write (obj, errname, 0);
267       if (errdes < 0)
268         {
269           *err = errno;
270           errmsg = "open error file";
271           goto error_exit;
272         }
273     }
274
275   /* Run the program.  */
276
277   pid = obj->funcs->exec_child (obj, flags, executable, argv, in, out, errdes,
278                                 &errmsg, err);
279   if (pid < 0)
280     goto error_exit;
281
282   ++obj->count;
283   obj->children = xrealloc (obj->children, obj->count * sizeof (long));
284   obj->children[obj->count - 1] = pid;
285
286   return NULL;
287
288  error_exit:
289   if (in >= 0 && in != STDIN_FILE_NO)
290     obj->funcs->close (obj, in);
291   if (out >= 0 && out != STDOUT_FILE_NO)
292     obj->funcs->close (obj, out);
293   if (errdes >= 0 && errdes != STDERR_FILE_NO)
294     obj->funcs->close (obj, errdes);
295   if (outname_allocated)
296     free (outname);
297   return errmsg;
298 }
299
300 /* Return a FILE pointer for the output of the last program
301    executed.  */
302
303 FILE *
304 pex_read_output (struct pex_obj *obj, int binary)
305 {
306   if (obj->next_input_name != NULL)
307     {
308       const char *errmsg;
309       int err;
310
311       /* We have to make sure that the process has completed before we
312          try to read the file.  */
313       if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
314         {
315           errno = err;
316           return NULL;
317         }
318
319       obj->read_output = fopen (obj->next_input_name, binary ? "rb" : "r");
320
321       if (obj->next_input_name_allocated)
322         {
323           free (obj->next_input_name);
324           obj->next_input_name_allocated = 0;
325         }
326       obj->next_input_name = NULL;
327     }
328   else
329     {
330       int o;
331
332       o = obj->next_input;
333       if (o < 0 || o == STDIN_FILE_NO)
334         return NULL;
335       obj->read_output = obj->funcs->fdopenr (obj, o, binary);
336       obj->next_input = -1;
337     }
338
339   return obj->read_output;
340 }
341
342 /* Get the exit status and, if requested, the resource time for all
343    the child processes.  Return 0 on failure, 1 on success.  */
344
345 static int
346 pex_get_status_and_time (struct pex_obj *obj, int done, const char **errmsg,
347                          int *err)
348 {
349   int ret;
350   int i;
351
352   if (obj->number_waited == obj->count)
353     return 1;
354
355   obj->status = xrealloc (obj->status, obj->count * sizeof (int));
356   if ((obj->flags & PEX_RECORD_TIMES) != 0)
357     obj->time = xrealloc (obj->time, obj->count * sizeof (struct pex_time));
358
359   ret = 1;
360   for (i = obj->number_waited; i < obj->count; ++i)
361     {
362       if (obj->funcs->wait (obj, obj->children[i], &obj->status[i],
363                             obj->time == NULL ? NULL : &obj->time[i],
364                             done, errmsg, err) < 0)
365         ret = 0;
366     }
367   obj->number_waited = i;
368
369   return ret;
370 }
371
372 /* Get exit status of executed programs.  */
373
374 int
375 pex_get_status (struct pex_obj *obj, int count, int *vector)
376 {
377   if (obj->status == NULL)
378     {
379       const char *errmsg;
380       int err;
381
382       if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
383         return 0;
384     }
385
386   if (count > obj->count)
387     {
388       memset (vector + obj->count, 0, (count - obj->count) * sizeof (int));
389       count = obj->count;
390     }
391
392   memcpy (vector, obj->status, count * sizeof (int));
393
394   return 1;
395 }
396
397 /* Get process times of executed programs.  */
398
399 int
400 pex_get_times (struct pex_obj *obj, int count, struct pex_time *vector)
401 {
402   if (obj->status == NULL)
403     {
404       const char *errmsg;
405       int err;
406
407       if (!pex_get_status_and_time (obj, 0, &errmsg, &err))
408         return 0;
409     }
410
411   if (obj->time == NULL)
412     return 0;
413
414   if (count > obj->count)
415     {
416       memset (vector + obj->count, 0,
417               (count - obj->count) * sizeof (struct pex_time));
418       count = obj->count;
419     }
420
421   memcpy (vector, obj->time, count * sizeof (struct pex_time));
422
423   return 1;
424 }
425
426 /* Free a pex_obj structure.  */
427
428 void
429 pex_free (struct pex_obj *obj)
430 {
431   if (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
432     obj->funcs->close (obj, obj->next_input);
433
434   /* If the caller forgot to wait for the children, we do it here, to
435      avoid zombies.  */
436   if (obj->status == NULL)
437     {
438       const char *errmsg;
439       int err;
440
441       obj->flags &= ~ PEX_RECORD_TIMES;
442       pex_get_status_and_time (obj, 1, &errmsg, &err);
443     }
444
445   if (obj->next_input_name_allocated)
446     free (obj->next_input_name);
447   if (obj->children != NULL)
448     free (obj->children);
449   if (obj->status != NULL)
450     free (obj->status);
451   if (obj->time != NULL)
452     free (obj->time);
453   if (obj->read_output != NULL)
454     fclose (obj->read_output);
455
456   if (obj->remove_count > 0)
457     {
458       int i;
459
460       for (i = 0; i < obj->remove_count; ++i)
461         {
462           remove (obj->remove[i]);
463           free (obj->remove[i]);
464         }
465       free (obj->remove);
466     }
467
468   if (obj->funcs->cleanup != NULL)
469     obj->funcs->cleanup (obj);
470
471   free (obj);
472 }