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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libiberty/] [pex-common.c] - Blame information for rev 20

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

Line No. Rev Author Line
1 14 jlechner
/* 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->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 = XRESIZEVEC (char *, obj->remove, obj->remove_count);
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 = XRESIZEVEC (long, obj->children, obj->count);
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 = XRESIZEVEC (int, obj->status, obj->count);
356
  if ((obj->flags & PEX_RECORD_TIMES) != 0)
357
    obj->time = XRESIZEVEC (struct pex_time, obj->time, obj->count);
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
}

powered by: WebSVN 2.1.0

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