(root)/
binutils-2.41/
libiberty/
pex-djgpp.c
       1  /* Utilities to execute a program in a subprocess (possibly linked by pipes
       2     with other subprocesses), and wait for it.  DJGPP specialization.
       3     Copyright (C) 1996-2023 Free Software Foundation, Inc.
       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 "pex-common.h"
      22  
      23  #include <stdio.h>
      24  #include <errno.h>
      25  #ifdef NEED_DECLARATION_ERRNO
      26  extern int errno;
      27  #endif
      28  #ifdef HAVE_STDLIB_H
      29  #include <stdlib.h>
      30  #endif
      31  #include <string.h>
      32  #include <fcntl.h>
      33  #include <unistd.h>
      34  #include <sys/stat.h>
      35  #include <process.h>
      36  
      37  /* Use ECHILD if available, otherwise use EINVAL.  */
      38  #ifdef ECHILD
      39  #define PWAIT_ERROR ECHILD
      40  #else
      41  #define PWAIT_ERROR EINVAL
      42  #endif
      43  
      44  static int pex_djgpp_open_read (struct pex_obj *, const char *, int);
      45  static int pex_djgpp_open_write (struct pex_obj *, const char *, int, int);
      46  static pid_t pex_djgpp_exec_child (struct pex_obj *, int, const char *,
      47  				  char * const *, char * const *,
      48  				  int, int, int, int,
      49  				  const char **, int *);
      50  static int pex_djgpp_close (struct pex_obj *, int);
      51  static pid_t pex_djgpp_wait (struct pex_obj *, pid_t, int *, struct pex_time *,
      52  			   int, const char **, int *);
      53  
      54  /* The list of functions we pass to the common routines.  */
      55  
      56  const struct pex_funcs funcs =
      57  {
      58    pex_djgpp_open_read,
      59    pex_djgpp_open_write,
      60    pex_djgpp_exec_child,
      61    pex_djgpp_close,
      62    pex_djgpp_wait,
      63    NULL, /* pipe */
      64    NULL, /* fdopenr */
      65    NULL, /* fdopenw */
      66    NULL  /* cleanup */
      67  };
      68  
      69  /* Return a newly initialized pex_obj structure.  */
      70  
      71  struct pex_obj *
      72  pex_init (int flags, const char *pname, const char *tempbase)
      73  {
      74    /* DJGPP does not support pipes.  */
      75    flags &= ~ PEX_USE_PIPES;
      76    return pex_init_common (flags, pname, tempbase, &funcs);
      77  }
      78  
      79  /* Open a file for reading.  */
      80  
      81  static int
      82  pex_djgpp_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED,
      83  		     const char *name, int binary)
      84  {
      85    return open (name, O_RDONLY | (binary ? O_BINARY : O_TEXT));
      86  }
      87  
      88  /* Open a file for writing.  */
      89  
      90  static int
      91  pex_djgpp_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED,
      92  		      const char *name, int binary, int append)
      93  {
      94    /* Note that we can't use O_EXCL here because gcc may have already
      95       created the temporary file via make_temp_file.  */
      96    if (append)
      97      return -1;
      98    return open (name,
      99  	       (O_WRONLY | O_CREAT | O_TRUNC
     100  		| (binary ? O_BINARY : O_TEXT)),
     101  	       S_IRUSR | S_IWUSR);
     102  }
     103  
     104  /* Close a file.  */
     105  
     106  static int
     107  pex_djgpp_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
     108  {
     109    return close (fd);
     110  }
     111  
     112  /* Execute a child.  */
     113  
     114  static pid_t
     115  pex_djgpp_exec_child (struct pex_obj *obj, int flags, const char *executable,
     116  		      char * const * argv, char * const * env,
     117                        int in, int out, int errdes,
     118  		      int toclose ATTRIBUTE_UNUSED, const char **errmsg,
     119  		      int *err)
     120  {
     121    int org_in, org_out, org_errdes;
     122    int status;
     123    int *statuses;
     124  
     125    org_in = -1;
     126    org_out = -1;
     127    org_errdes = -1;
     128  
     129    if (in != STDIN_FILE_NO)
     130      {
     131        org_in = dup (STDIN_FILE_NO);
     132        if (org_in < 0)
     133  	{
     134  	  *err = errno;
     135  	  *errmsg = "dup";
     136  	  return (pid_t) -1;
     137  	}
     138        if (dup2 (in, STDIN_FILE_NO) < 0)
     139  	{
     140  	  *err = errno;
     141  	  *errmsg = "dup2";
     142  	  return (pid_t) -1;
     143  	}
     144        if (close (in) < 0)
     145  	{
     146  	  *err = errno;
     147  	  *errmsg = "close";
     148  	  return (pid_t) -1;
     149  	}
     150      }
     151  
     152    if (out != STDOUT_FILE_NO)
     153      {
     154        org_out = dup (STDOUT_FILE_NO);
     155        if (org_out < 0)
     156  	{
     157  	  *err = errno;
     158  	  *errmsg = "dup";
     159  	  return (pid_t) -1;
     160  	}
     161        if (dup2 (out, STDOUT_FILE_NO) < 0)
     162  	{
     163  	  *err = errno;
     164  	  *errmsg = "dup2";
     165  	  return (pid_t) -1;
     166  	}
     167        if (close (out) < 0)
     168  	{
     169  	  *err = errno;
     170  	  *errmsg = "close";
     171  	  return (pid_t) -1;
     172  	}
     173      }
     174  
     175    if (errdes != STDERR_FILE_NO
     176        || (flags & PEX_STDERR_TO_STDOUT) != 0)
     177      {
     178        org_errdes = dup (STDERR_FILE_NO);
     179        if (org_errdes < 0)
     180  	{
     181  	  *err = errno;
     182  	  *errmsg = "dup";
     183  	  return (pid_t) -1;
     184  	}
     185        if (dup2 ((flags & PEX_STDERR_TO_STDOUT) != 0 ? STDOUT_FILE_NO : errdes,
     186  		 STDERR_FILE_NO) < 0)
     187  	{
     188  	  *err = errno;
     189  	  *errmsg = "dup2";
     190  	  return (pid_t) -1;
     191  	}
     192        if (errdes != STDERR_FILE_NO)
     193  	{
     194  	  if (close (errdes) < 0)
     195  	    {
     196  	      *err = errno;
     197  	      *errmsg = "close";
     198  	      return (pid_t) -1;
     199  	    }
     200  	}
     201      }
     202  
     203    if (env)
     204      status = (((flags & PEX_SEARCH) != 0 ? spawnvpe : spawnve)
     205  	      (P_WAIT, executable, argv, env));
     206    else
     207      status = (((flags & PEX_SEARCH) != 0 ? spawnvp : spawnv)
     208    	      (P_WAIT, executable, argv));
     209  
     210    if (status == -1)
     211      {
     212        *err = errno;
     213        *errmsg = ((flags & PEX_SEARCH) != 0) ? "spawnvp" : "spawnv";
     214      }
     215  
     216    if (in != STDIN_FILE_NO)
     217      {
     218        if (dup2 (org_in, STDIN_FILE_NO) < 0)
     219  	{
     220  	  *err = errno;
     221  	  *errmsg = "dup2";
     222  	  return (pid_t) -1;
     223  	}
     224        if (close (org_in) < 0)
     225  	{
     226  	  *err = errno;
     227  	  *errmsg = "close";
     228  	  return (pid_t) -1;
     229  	}
     230      }
     231  
     232    if (out != STDOUT_FILE_NO)
     233      {
     234        if (dup2 (org_out, STDOUT_FILE_NO) < 0)
     235  	{
     236  	  *err = errno;
     237  	  *errmsg = "dup2";
     238  	  return (pid_t) -1;
     239  	}
     240        if (close (org_out) < 0)
     241  	{
     242  	  *err = errno;
     243  	  *errmsg = "close";
     244  	  return (pid_t) -1;
     245  	}
     246      }
     247  
     248    if (errdes != STDERR_FILE_NO
     249        || (flags & PEX_STDERR_TO_STDOUT) != 0)
     250      {
     251        if (dup2 (org_errdes, STDERR_FILE_NO) < 0)
     252  	{
     253  	  *err = errno;
     254  	  *errmsg = "dup2";
     255  	  return (pid_t) -1;
     256  	}
     257        if (close (org_errdes) < 0)
     258  	{
     259  	  *err = errno;
     260  	  *errmsg = "close";
     261  	  return (pid_t) -1;
     262  	}
     263      }
     264  
     265    /* Save the exit status for later.  When we are called, obj->count
     266       is the number of children which have executed before this
     267       one.  */
     268    statuses = (int *) obj->sysdep;
     269    statuses = XRESIZEVEC (int, statuses, obj->count + 1);
     270    statuses[obj->count] = status;
     271    obj->sysdep = (void *) statuses;
     272  
     273    return (pid_t) obj->count;
     274  }
     275  
     276  /* Wait for a child process to complete.  Actually the child process
     277     has already completed, and we just need to return the exit
     278     status.  */
     279  
     280  static pid_t
     281  pex_djgpp_wait (struct pex_obj *obj, pid_t pid, int *status,
     282  		struct pex_time *time, int done ATTRIBUTE_UNUSED,
     283  		const char **errmsg ATTRIBUTE_UNUSED,
     284  		int *err ATTRIBUTE_UNUSED)
     285  {
     286    int *statuses;
     287  
     288    if (time != NULL)
     289      memset (time, 0, sizeof *time);
     290  
     291    statuses = (int *) obj->sysdep;
     292    *status = statuses[pid];
     293  
     294    return 0;
     295  }