OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [libiberty/] [pex-common.c] - Blame information for rev 167

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.