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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [libiberty/] [pex-common.c] - Blame information for rev 867

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

Line No. Rev Author Line
1 38 julius
/* 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
}

powered by: WebSVN 2.1.0

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