Back to index

cell-binutils  2.17cvs20070401
pex-djgpp.c
Go to the documentation of this file.
00001 /* Utilities to execute a program in a subprocess (possibly linked by pipes
00002    with other subprocesses), and wait for it.  DJGPP specialization.
00003    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005
00004    Free Software Foundation, Inc.
00005 
00006 This file is part of the libiberty library.
00007 Libiberty is free software; you can redistribute it and/or
00008 modify it under the terms of the GNU Library General Public
00009 License as published by the Free Software Foundation; either
00010 version 2 of the License, or (at your option) any later version.
00011 
00012 Libiberty is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 Library General Public License for more details.
00016 
00017 You should have received a copy of the GNU Library General Public
00018 License along with libiberty; see the file COPYING.LIB.  If not,
00019 write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00020 Boston, MA 02110-1301, USA.  */
00021 
00022 #include "pex-common.h"
00023 
00024 #include <stdio.h>
00025 #include <errno.h>
00026 #ifdef NEED_DECLARATION_ERRNO
00027 extern int errno;
00028 #endif
00029 #ifdef HAVE_STDLIB_H
00030 #include <stdlib.h>
00031 #endif
00032 #include <string.h>
00033 #include <fcntl.h>
00034 #include <unistd.h>
00035 #include <sys/stat.h>
00036 #include <process.h>
00037 
00038 /* Use ECHILD if available, otherwise use EINVAL.  */
00039 #ifdef ECHILD
00040 #define PWAIT_ERROR ECHILD
00041 #else
00042 #define PWAIT_ERROR EINVAL
00043 #endif
00044 
00045 static int pex_djgpp_open_read (struct pex_obj *, const char *, int);
00046 static int pex_djgpp_open_write (struct pex_obj *, const char *, int);
00047 static long pex_djgpp_exec_child (struct pex_obj *, int, const char *,
00048                               char * const *, char * const *,
00049                               int, int, int, int,
00050                               const char **, int *);
00051 static int pex_djgpp_close (struct pex_obj *, int);
00052 static int pex_djgpp_wait (struct pex_obj *, long, int *, struct pex_time *,
00053                         int, const char **, int *);
00054 
00055 /* The list of functions we pass to the common routines.  */
00056 
00057 const struct pex_funcs funcs =
00058 {
00059   pex_djgpp_open_read,
00060   pex_djgpp_open_write,
00061   pex_djgpp_exec_child,
00062   pex_djgpp_close,
00063   pex_djgpp_wait,
00064   NULL, /* pipe */
00065   NULL, /* fdopenr */
00066   NULL, /* fdopenw */
00067   NULL  /* cleanup */
00068 };
00069 
00070 /* Return a newly initialized pex_obj structure.  */
00071 
00072 struct pex_obj *
00073 pex_init (int flags, const char *pname, const char *tempbase)
00074 {
00075   /* DJGPP does not support pipes.  */
00076   flags &= ~ PEX_USE_PIPES;
00077   return pex_init_common (flags, pname, tempbase, &funcs);
00078 }
00079 
00080 /* Open a file for reading.  */
00081 
00082 static int
00083 pex_djgpp_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED,
00084                    const char *name, int binary)
00085 {
00086   return open (name, O_RDONLY | (binary ? O_BINARY : O_TEXT));
00087 }
00088 
00089 /* Open a file for writing.  */
00090 
00091 static int
00092 pex_djgpp_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED,
00093                     const char *name, int binary)
00094 {
00095   /* Note that we can't use O_EXCL here because gcc may have already
00096      created the temporary file via make_temp_file.  */
00097   return open (name,
00098               (O_WRONLY | O_CREAT | O_TRUNC
00099               | (binary ? O_BINARY : O_TEXT)),
00100               S_IRUSR | S_IWUSR);
00101 }
00102 
00103 /* Close a file.  */
00104 
00105 static int
00106 pex_djgpp_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
00107 {
00108   return close (fd);
00109 }
00110 
00111 /* Execute a child.  */
00112 
00113 static long
00114 pex_djgpp_exec_child (struct pex_obj *obj, int flags, const char *executable,
00115                     char * const * argv, char * const * env,
00116                       int in, int out, int errdes,
00117                     int toclose ATTRIBUTE_UNUSED, const char **errmsg,
00118                     int *err)
00119 {
00120   int org_in, org_out, org_errdes;
00121   int status;
00122   int *statuses;
00123 
00124   org_in = -1;
00125   org_out = -1;
00126   org_errdes = -1;
00127 
00128   if (in != STDIN_FILE_NO)
00129     {
00130       org_in = dup (STDIN_FILE_NO);
00131       if (org_in < 0)
00132        {
00133          *err = errno;
00134          *errmsg = "dup";
00135          return -1;
00136        }
00137       if (dup2 (in, STDIN_FILE_NO) < 0)
00138        {
00139          *err = errno;
00140          *errmsg = "dup2";
00141          return -1;
00142        }
00143       if (close (in) < 0)
00144        {
00145          *err = errno;
00146          *errmsg = "close";
00147          return -1;
00148        }
00149     }
00150 
00151   if (out != STDOUT_FILE_NO)
00152     {
00153       org_out = dup (STDOUT_FILE_NO);
00154       if (org_out < 0)
00155        {
00156          *err = errno;
00157          *errmsg = "dup";
00158          return -1;
00159        }
00160       if (dup2 (out, STDOUT_FILE_NO) < 0)
00161        {
00162          *err = errno;
00163          *errmsg = "dup2";
00164          return -1;
00165        }
00166       if (close (out) < 0)
00167        {
00168          *err = errno;
00169          *errmsg = "close";
00170          return -1;
00171        }
00172     }
00173 
00174   if (errdes != STDERR_FILE_NO
00175       || (flags & PEX_STDERR_TO_STDOUT) != 0)
00176     {
00177       org_errdes = dup (STDERR_FILE_NO);
00178       if (org_errdes < 0)
00179        {
00180          *err = errno;
00181          *errmsg = "dup";
00182          return -1;
00183        }
00184       if (dup2 ((flags & PEX_STDERR_TO_STDOUT) != 0 ? STDOUT_FILE_NO : errdes,
00185                STDERR_FILE_NO) < 0)
00186        {
00187          *err = errno;
00188          *errmsg = "dup2";
00189          return -1;
00190        }
00191       if (errdes != STDERR_FILE_NO)
00192        {
00193          if (close (errdes) < 0)
00194            {
00195              *err = errno;
00196              *errmsg = "close";
00197              return -1;
00198            }
00199        }
00200     }
00201 
00202   if (env)
00203     status = (((flags & PEX_SEARCH) != 0 ? spawnvpe : spawnve)
00204              (P_WAIT, executable, argv, env));
00205   else
00206     status = (((flags & PEX_SEARCH) != 0 ? spawnvp : spawnv)
00207              (P_WAIT, executable, argv));
00208 
00209   if (status == -1)
00210     {
00211       *err = errno;
00212       *errmsg = ((flags & PEX_SEARCH) != 0) ? "spawnvp" : "spawnv";
00213     }
00214 
00215   if (in != STDIN_FILE_NO)
00216     {
00217       if (dup2 (org_in, STDIN_FILE_NO) < 0)
00218        {
00219          *err = errno;
00220          *errmsg = "dup2";
00221          return -1;
00222        }
00223       if (close (org_in) < 0)
00224        {
00225          *err = errno;
00226          *errmsg = "close";
00227          return -1;
00228        }
00229     }
00230 
00231   if (out != STDOUT_FILE_NO)
00232     {
00233       if (dup2 (org_out, STDOUT_FILE_NO) < 0)
00234        {
00235          *err = errno;
00236          *errmsg = "dup2";
00237          return -1;
00238        }
00239       if (close (org_out) < 0)
00240        {
00241          *err = errno;
00242          *errmsg = "close";
00243          return -1;
00244        }
00245     }
00246 
00247   if (errdes != STDERR_FILE_NO
00248       || (flags & PEX_STDERR_TO_STDOUT) != 0)
00249     {
00250       if (dup2 (org_errdes, STDERR_FILE_NO) < 0)
00251        {
00252          *err = errno;
00253          *errmsg = "dup2";
00254          return -1;
00255        }
00256       if (close (org_errdes) < 0)
00257        {
00258          *err = errno;
00259          *errmsg = "close";
00260          return -1;
00261        }
00262     }
00263 
00264   /* Save the exit status for later.  When we are called, obj->count
00265      is the number of children which have executed before this
00266      one.  */
00267   statuses = (int *) obj->sysdep;
00268   statuses = XRESIZEVEC (int, statuses, obj->count + 1);
00269   statuses[obj->count] = status;
00270   obj->sysdep = (void *) statuses;
00271 
00272   return obj->count;
00273 }
00274 
00275 /* Wait for a child process to complete.  Actually the child process
00276    has already completed, and we just need to return the exit
00277    status.  */
00278 
00279 static int
00280 pex_djgpp_wait (struct pex_obj *obj, long pid, int *status,
00281               struct pex_time *time, int done ATTRIBUTE_UNUSED,
00282               const char **errmsg ATTRIBUTE_UNUSED,
00283               int *err ATTRIBUTE_UNUSED)
00284 {
00285   int *statuses;
00286 
00287   if (time != NULL)
00288     memset (time, 0, sizeof *time);
00289 
00290   statuses = (int *) obj->sysdep;
00291   *status = statuses[pid];
00292 
00293   return 0;
00294 }