Mercurial > hg > CbC > CbC_gcc
comparison libiberty/pex-unix.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | f6334be47118 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
1 /* Utilities to execute a program in a subprocess (possibly linked by pipes | 1 /* Utilities to execute a program in a subprocess (possibly linked by pipes |
2 with other subprocesses), and wait for it. Generic Unix version | 2 with other subprocesses), and wait for it. Generic Unix version |
3 (also used for UWIN and VMS). | 3 (also used for UWIN and VMS). |
4 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 | 4 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2009 |
5 Free Software Foundation, Inc. | 5 Free Software Foundation, Inc. |
6 | 6 |
7 This file is part of the libiberty library. | 7 This file is part of the libiberty library. |
8 Libiberty is free software; you can redistribute it and/or | 8 Libiberty is free software; you can redistribute it and/or |
9 modify it under the terms of the GNU Library General Public | 9 modify it under the terms of the GNU Library General Public |
63 # define VFORK_STRING "vfork" | 63 # define VFORK_STRING "vfork" |
64 #endif | 64 #endif |
65 #ifdef HAVE_VFORK_H | 65 #ifdef HAVE_VFORK_H |
66 #include <vfork.h> | 66 #include <vfork.h> |
67 #endif | 67 #endif |
68 #ifdef VMS | 68 #if defined(VMS) && defined (__LONG_POINTERS) |
69 #define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \ | 69 #ifndef __CHAR_PTR32 |
70 lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1) | 70 typedef char * __char_ptr32 |
71 #endif /* VMS */ | 71 __attribute__ ((mode (SI))); |
72 | 72 #endif |
73 | |
74 typedef __char_ptr32 *__char_ptr_char_ptr32 | |
75 __attribute__ ((mode (SI))); | |
76 | |
77 /* Return a 32 bit pointer to an array of 32 bit pointers | |
78 given a 64 bit pointer to an array of 64 bit pointers. */ | |
79 | |
80 static __char_ptr_char_ptr32 | |
81 to_ptr32 (char **ptr64) | |
82 { | |
83 int argc; | |
84 __char_ptr_char_ptr32 short_argv; | |
85 | |
86 for (argc=0; ptr64[argc]; argc++); | |
87 | |
88 /* Reallocate argv with 32 bit pointers. */ | |
89 short_argv = (__char_ptr_char_ptr32) decc$malloc | |
90 (sizeof (__char_ptr32) * (argc + 1)); | |
91 | |
92 for (argc=0; ptr64[argc]; argc++) | |
93 short_argv[argc] = (__char_ptr32) decc$strdup (ptr64[argc]); | |
94 | |
95 short_argv[argc] = (__char_ptr32) 0; | |
96 return short_argv; | |
97 | |
98 } | |
99 #else | |
100 #define to_ptr32(argv) argv | |
101 #endif | |
73 | 102 |
74 /* File mode to use for private and world-readable files. */ | 103 /* File mode to use for private and world-readable files. */ |
75 | 104 |
76 #if defined (S_IRUSR) && defined (S_IWUSR) && defined (S_IRGRP) && defined (S_IWGRP) && defined (S_IROTH) && defined (S_IWOTH) | 105 #if defined (S_IRUSR) && defined (S_IWUSR) && defined (S_IRGRP) && defined (S_IWGRP) && defined (S_IROTH) && defined (S_IWOTH) |
77 #define PUBLIC_MODE \ | 106 #define PUBLIC_MODE \ |
337 | 366 |
338 static void | 367 static void |
339 pex_child_error (struct pex_obj *obj, const char *executable, | 368 pex_child_error (struct pex_obj *obj, const char *executable, |
340 const char *errmsg, int err) | 369 const char *errmsg, int err) |
341 { | 370 { |
342 #define writeerr(s) (void) write (STDERR_FILE_NO, s, strlen (s)) | 371 int retval = 0; |
372 #define writeerr(s) retval |= (write (STDERR_FILE_NO, s, strlen (s)) < 0) | |
343 writeerr (obj->pname); | 373 writeerr (obj->pname); |
344 writeerr (": error trying to exec '"); | 374 writeerr (": error trying to exec '"); |
345 writeerr (executable); | 375 writeerr (executable); |
346 writeerr ("': "); | 376 writeerr ("': "); |
347 writeerr (errmsg); | 377 writeerr (errmsg); |
348 writeerr (": "); | 378 writeerr (": "); |
349 writeerr (xstrerror (err)); | 379 writeerr (xstrerror (err)); |
350 writeerr ("\n"); | 380 writeerr ("\n"); |
351 _exit (-1); | 381 #undef writeerr |
382 /* Exit with -2 if the error output failed, too. */ | |
383 _exit (retval == 0 ? -1 : -2); | |
352 } | 384 } |
353 | 385 |
354 /* Execute a child. */ | 386 /* Execute a child. */ |
355 | 387 |
356 extern char **environ; | 388 extern char **environ; |
366 /* We declare these to be volatile to avoid warnings from gcc about | 398 /* We declare these to be volatile to avoid warnings from gcc about |
367 them being clobbered by vfork. */ | 399 them being clobbered by vfork. */ |
368 volatile int sleep_interval; | 400 volatile int sleep_interval; |
369 volatile int retries; | 401 volatile int retries; |
370 | 402 |
403 /* We vfork and then set environ in the child before calling execvp. | |
404 This clobbers the parent's environ so we need to restore it. | |
405 It would be nice to use one of the exec* functions that takes an | |
406 environment as a parameter, but that may have portability issues. */ | |
407 char **save_environ = environ; | |
408 | |
371 sleep_interval = 1; | 409 sleep_interval = 1; |
372 pid = -1; | 410 pid = -1; |
373 for (retries = 0; retries < 4; ++retries) | 411 for (retries = 0; retries < 4; ++retries) |
374 { | 412 { |
375 pid = vfork (); | 413 pid = vfork (); |
419 if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0) | 457 if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0) |
420 pex_child_error (obj, executable, "dup2", errno); | 458 pex_child_error (obj, executable, "dup2", errno); |
421 } | 459 } |
422 | 460 |
423 if (env) | 461 if (env) |
424 environ = (char**) env; | 462 { |
463 /* NOTE: In a standard vfork implementation this clobbers the | |
464 parent's copy of environ "too" (in reality there's only one copy). | |
465 This is ok as we restore it below. */ | |
466 environ = (char**) env; | |
467 } | |
425 | 468 |
426 if ((flags & PEX_SEARCH) != 0) | 469 if ((flags & PEX_SEARCH) != 0) |
427 { | 470 { |
428 execvp (executable, argv); | 471 execvp (executable, to_ptr32 (argv)); |
429 pex_child_error (obj, executable, "execvp", errno); | 472 pex_child_error (obj, executable, "execvp", errno); |
430 } | 473 } |
431 else | 474 else |
432 { | 475 { |
433 execv (executable, argv); | 476 execv (executable, to_ptr32 (argv)); |
434 pex_child_error (obj, executable, "execv", errno); | 477 pex_child_error (obj, executable, "execv", errno); |
435 } | 478 } |
436 | 479 |
437 /* NOTREACHED */ | 480 /* NOTREACHED */ |
438 return (pid_t) -1; | 481 return (pid_t) -1; |
439 | 482 |
440 default: | 483 default: |
441 /* Parent process. */ | 484 /* Parent process. */ |
485 | |
486 /* Restore environ. | |
487 Note that the parent either doesn't run until the child execs/exits | |
488 (standard vfork behaviour), or if it does run then vfork is behaving | |
489 more like fork. In either case we needn't worry about clobbering | |
490 the child's copy of environ. */ | |
491 environ = save_environ; | |
492 | |
442 if (in != STDIN_FILE_NO) | 493 if (in != STDIN_FILE_NO) |
443 { | 494 { |
444 if (close (in) < 0) | 495 if (close (in) < 0) |
445 { | 496 { |
446 *err = errno; | 497 *err = errno; |