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