X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libiberty%2Fpex-djgpp.c;h=0721139954ff993a0c872a5697b4d9c8bdba9eeb;hb=9dab78b8626157fec12a16727e729bd61a6969ef;hp=fe5b80b37dc227adf343954b231d5f7441f953b6;hpb=f8d9d6a03d24c6a42a1a813a25e63ac308062869;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libiberty/pex-djgpp.c b/libiberty/pex-djgpp.c index fe5b80b37dc..0721139954f 100644 --- a/libiberty/pex-djgpp.c +++ b/libiberty/pex-djgpp.c @@ -1,6 +1,6 @@ /* Utilities to execute a program in a subprocess (possibly linked by pipes with other subprocesses), and wait for it. DJGPP specialization. - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003 + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc. This file is part of the libiberty library. @@ -16,8 +16,8 @@ Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with libiberty; see the file COPYING.LIB. If not, -write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +Boston, MA 02110-1301, USA. */ #include "pex-common.h" @@ -29,6 +29,10 @@ extern int errno; #ifdef HAVE_STDLIB_H #include #endif +#include +#include +#include +#include #include /* Use ECHILD if available, otherwise use EINVAL. */ @@ -38,59 +42,253 @@ extern int errno; #define PWAIT_ERROR EINVAL #endif -/* MSDOS doesn't multitask, but for the sake of a consistent interface - the code behaves like it does. pexecute runs the program, tucks the - exit code away, and returns a "pid". pwait must be called to fetch the - exit code. */ +static int pex_djgpp_open_read (struct pex_obj *, const char *, int); +static int pex_djgpp_open_write (struct pex_obj *, const char *, int); +static pid_t pex_djgpp_exec_child (struct pex_obj *, int, const char *, + char * const *, char * const *, + int, int, int, int, + const char **, int *); +static int pex_djgpp_close (struct pex_obj *, int); +static pid_t pex_djgpp_wait (struct pex_obj *, pid_t, int *, struct pex_time *, + int, const char **, int *); -/* For communicating information from pexecute to pwait. */ -static int last_pid = 0; -static int last_status = 0; -static int last_reaped = 0; +/* The list of functions we pass to the common routines. */ -int -pexecute (const char *program, char * const *argv, const char *this_pname, - const char *temp_base, char **errmsg_fmt, - char **errmsg_arg, int flags) +const struct pex_funcs funcs = { - int rc; + pex_djgpp_open_read, + pex_djgpp_open_write, + pex_djgpp_exec_child, + pex_djgpp_close, + pex_djgpp_wait, + NULL, /* pipe */ + NULL, /* fdopenr */ + NULL, /* fdopenw */ + NULL /* cleanup */ +}; - last_pid++; - if (last_pid < 0) - last_pid = 1; +/* Return a newly initialized pex_obj structure. */ - if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE) - abort (); +struct pex_obj * +pex_init (int flags, const char *pname, const char *tempbase) +{ + /* DJGPP does not support pipes. */ + flags &= ~ PEX_USE_PIPES; + return pex_init_common (flags, pname, tempbase, &funcs); +} - /* ??? What are the possible return values from spawnv? */ - rc = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (P_WAIT, program, argv); +/* Open a file for reading. */ - if (rc == -1) - { - *errmsg_fmt = install_error_msg; - *errmsg_arg = (char *)program; - return -1; - } +static int +pex_djgpp_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, + const char *name, int binary) +{ + return open (name, O_RDONLY | (binary ? O_BINARY : O_TEXT)); +} + +/* Open a file for writing. */ + +static int +pex_djgpp_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, + const char *name, int binary) +{ + /* Note that we can't use O_EXCL here because gcc may have already + created the temporary file via make_temp_file. */ + return open (name, + (O_WRONLY | O_CREAT | O_TRUNC + | (binary ? O_BINARY : O_TEXT)), + S_IRUSR | S_IWUSR); +} + +/* Close a file. */ - /* Tuck the status away for pwait, and return a "pid". */ - last_status = rc << 8; - return last_pid; +static int +pex_djgpp_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd) +{ + return close (fd); } -int -pwait (int pid, int *status, int flags) +/* Execute a child. */ + +static pid_t +pex_djgpp_exec_child (struct pex_obj *obj, int flags, const char *executable, + char * const * argv, char * const * env, + int in, int out, int errdes, + int toclose ATTRIBUTE_UNUSED, const char **errmsg, + int *err) { - /* On MSDOS each pexecute must be followed by its associated pwait. */ - if (pid != last_pid - /* Called twice for the same child? */ - || pid == last_reaped) + int org_in, org_out, org_errdes; + int status; + int *statuses; + + org_in = -1; + org_out = -1; + org_errdes = -1; + + if (in != STDIN_FILE_NO) { - errno = PWAIT_ERROR; - return -1; + org_in = dup (STDIN_FILE_NO); + if (org_in < 0) + { + *err = errno; + *errmsg = "dup"; + return (pid_t) -1; + } + if (dup2 (in, STDIN_FILE_NO) < 0) + { + *err = errno; + *errmsg = "dup2"; + return (pid_t) -1; + } + if (close (in) < 0) + { + *err = errno; + *errmsg = "close"; + return (pid_t) -1; + } } - /* ??? Here's an opportunity to canonicalize the values in STATUS. - Needed? */ - *status = (last_status >> 8); - last_reaped = last_pid; - return last_pid; + + if (out != STDOUT_FILE_NO) + { + org_out = dup (STDOUT_FILE_NO); + if (org_out < 0) + { + *err = errno; + *errmsg = "dup"; + return (pid_t) -1; + } + if (dup2 (out, STDOUT_FILE_NO) < 0) + { + *err = errno; + *errmsg = "dup2"; + return (pid_t) -1; + } + if (close (out) < 0) + { + *err = errno; + *errmsg = "close"; + return (pid_t) -1; + } + } + + if (errdes != STDERR_FILE_NO + || (flags & PEX_STDERR_TO_STDOUT) != 0) + { + org_errdes = dup (STDERR_FILE_NO); + if (org_errdes < 0) + { + *err = errno; + *errmsg = "dup"; + return (pid_t) -1; + } + if (dup2 ((flags & PEX_STDERR_TO_STDOUT) != 0 ? STDOUT_FILE_NO : errdes, + STDERR_FILE_NO) < 0) + { + *err = errno; + *errmsg = "dup2"; + return (pid_t) -1; + } + if (errdes != STDERR_FILE_NO) + { + if (close (errdes) < 0) + { + *err = errno; + *errmsg = "close"; + return (pid_t) -1; + } + } + } + + if (env) + status = (((flags & PEX_SEARCH) != 0 ? spawnvpe : spawnve) + (P_WAIT, executable, argv, env)); + else + status = (((flags & PEX_SEARCH) != 0 ? spawnvp : spawnv) + (P_WAIT, executable, argv)); + + if (status == -1) + { + *err = errno; + *errmsg = ((flags & PEX_SEARCH) != 0) ? "spawnvp" : "spawnv"; + } + + if (in != STDIN_FILE_NO) + { + if (dup2 (org_in, STDIN_FILE_NO) < 0) + { + *err = errno; + *errmsg = "dup2"; + return (pid_t) -1; + } + if (close (org_in) < 0) + { + *err = errno; + *errmsg = "close"; + return (pid_t) -1; + } + } + + if (out != STDOUT_FILE_NO) + { + if (dup2 (org_out, STDOUT_FILE_NO) < 0) + { + *err = errno; + *errmsg = "dup2"; + return (pid_t) -1; + } + if (close (org_out) < 0) + { + *err = errno; + *errmsg = "close"; + return (pid_t) -1; + } + } + + if (errdes != STDERR_FILE_NO + || (flags & PEX_STDERR_TO_STDOUT) != 0) + { + if (dup2 (org_errdes, STDERR_FILE_NO) < 0) + { + *err = errno; + *errmsg = "dup2"; + return (pid_t) -1; + } + if (close (org_errdes) < 0) + { + *err = errno; + *errmsg = "close"; + return (pid_t) -1; + } + } + + /* Save the exit status for later. When we are called, obj->count + is the number of children which have executed before this + one. */ + statuses = (int *) obj->sysdep; + statuses = XRESIZEVEC (int, statuses, obj->count + 1); + statuses[obj->count] = status; + obj->sysdep = (void *) statuses; + + return (pid_t) obj->count; +} + +/* Wait for a child process to complete. Actually the child process + has already completed, and we just need to return the exit + status. */ + +static pid_t +pex_djgpp_wait (struct pex_obj *obj, pid_t pid, int *status, + struct pex_time *time, int done ATTRIBUTE_UNUSED, + const char **errmsg ATTRIBUTE_UNUSED, + int *err ATTRIBUTE_UNUSED) +{ + int *statuses; + + if (time != NULL) + memset (time, 0, sizeof *time); + + statuses = (int *) obj->sysdep; + *status = statuses[pid]; + + return 0; }