(root)/
gcc-13.2.0/
libiberty/
pex-msdos.c
       1  /* Utilities to execute a program in a subprocess (possibly linked by pipes
       2     with other subprocesses), and wait for it.  Generic MSDOS 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_STRING_H
      29  #include <string.h>
      30  #endif
      31  #ifdef HAVE_STDLIB_H
      32  #include <stdlib.h>
      33  #endif
      34  
      35  #include "safe-ctype.h"
      36  #include <process.h>
      37  
      38  /* The structure we keep in obj->sysdep.  */
      39  
      40  #define PEX_MSDOS_FILE_COUNT 3
      41  
      42  #define PEX_MSDOS_FD_OFFSET 10
      43  
      44  struct pex_msdos
      45  {
      46    /* An array of file names.  We refer to these using file descriptors
      47       of 10 + array index.  */
      48    const char *files[PEX_MSDOS_FILE_COUNT];
      49    /* Exit statuses of programs which have been run.  */
      50    int *statuses;
      51  };
      52  
      53  static int pex_msdos_open (struct pex_obj *, const char *, int);
      54  static int pex_msdos_open (struct pex_obj *, const char *, int);
      55  static int pex_msdos_fdindex (struct pex_msdos *, int);
      56  static pid_t pex_msdos_exec_child (struct pex_obj *, int, const char *,
      57  				  char * const *, char * const *,
      58  				  int, int, int, int,
      59  				  int, const char **, int *);
      60  static int pex_msdos_close (struct pex_obj *, int);
      61  static pid_t pex_msdos_wait (struct pex_obj *, pid_t, int *, struct pex_time *,
      62  			   int, const char **, int *);
      63  static void pex_msdos_cleanup (struct pex_obj *);
      64  
      65  /* The list of functions we pass to the common routines.  */
      66  
      67  const struct pex_funcs funcs =
      68  {
      69    pex_msdos_open,
      70    pex_msdos_open,
      71    pex_msdos_exec_child,
      72    pex_msdos_close,
      73    pex_msdos_wait,
      74    NULL, /* pipe */
      75    NULL, /* fdopenr */
      76    NULL, /* fdopenw */
      77    pex_msdos_cleanup
      78  };
      79  
      80  /* Return a newly initialized pex_obj structure.  */
      81  
      82  struct pex_obj *
      83  pex_init (int flags, const char *pname, const char *tempbase)
      84  {
      85    struct pex_obj *ret;
      86    int i;
      87  
      88    /* MSDOS does not support pipes.  */
      89    flags &= ~ PEX_USE_PIPES;
      90  
      91    ret = pex_init_common (flags, pname, tempbase, funcs);
      92  
      93    ret->sysdep = XNEW (struct pex_msdos);
      94    for (i = 0; i < PEX_MSDOS_FILE_COUNT; ++i)
      95      ret->files[i] = NULL;
      96    ret->statuses = NULL;
      97  
      98    return ret;
      99  }
     100  
     101  /* Open a file.  FIXME: We ignore the binary argument, since we have
     102     no way to handle it.  */
     103  
     104  static int
     105  pex_msdos_open (struct pex_obj *obj, const char *name,
     106  		int binary ATTRIBUTE_UNUSED)
     107  {
     108    struct pex_msdos *ms;
     109    int i;
     110  
     111    ms = (struct pex_msdos *) obj->sysdep;
     112  
     113    for (i = 0; i < PEX_MSDOS_FILE_COUNT; ++i)
     114      {
     115        if (ms->files[i] == NULL)
     116  	{
     117  	  ms->files[i] = xstrdup (name);
     118  	  return i + PEX_MSDOS_FD_OFFSET;
     119  	}
     120      }
     121  
     122    abort ();
     123  }
     124  
     125  /* Get the index into msdos->files associated with an open file
     126     descriptor.  */
     127  
     128  static int
     129  pex_msdos_fdindex (struct pex_msdos *ms, int fd)
     130  {
     131    fd -= PEX_MSDOS_FD_OFFSET;
     132    if (fd < 0 || fd >= PEX_MSDOS_FILE_COUNT || ms->files[fd] == NULL)
     133      abort ();
     134    return fd;
     135  }
     136  
     137  
     138  /* Close a file.  */
     139  
     140  static int
     141  pex_msdos_close (struct pex_obj *obj, int fd)
     142  {
     143    struct pex_msdos *ms;
     144    int fdinex;
     145  
     146    ms = (struct pex_msdos *) obj->sysdep;
     147    fdindex = pe_msdos_fdindex (ms, fd);
     148    free (ms->files[fdindex]);
     149    ms->files[fdindex] = NULL;
     150  }
     151  
     152  /* Execute a child.  */
     153  
     154  static pid_t
     155  pex_msdos_exec_child (struct pex_obj *obj, int flags, const char *executable,
     156  		      char * const * argv, char * const * env, int in, int out,
     157  		      int toclose ATTRIBUTE_UNUSED,
     158  		      int errdes ATTRIBUTE_UNUSED, const char **errmsg,
     159  		      int *err)
     160  {
     161    struct pex_msdos *ms;
     162    char *temp_base;
     163    int temp_base_allocated;
     164    char *rf;
     165    int inindex;
     166    char *infile;
     167    int outindex;
     168    char *outfile;
     169    char *scmd;
     170    FILE *argfile;
     171    int i;
     172    int status;
     173  
     174    ms = (struct pex_msdos *) obj->sysdep;
     175  
     176    /* FIXME: I don't know how to redirect stderr, so we ignore ERRDES
     177       and PEX_STDERR_TO_STDOUT.  */
     178  
     179    temp_base = obj->temp_base;
     180    if (temp_base != NULL)
     181      temp_base_allocated = 0;
     182    else
     183      {
     184        temp_base = choose_temp_base ();
     185        temp_base_allocated = 1;
     186      }
     187  
     188    rf = concat (temp_base, ".gp", NULL);
     189  
     190    if (temp_base_allocated)
     191      free (temp_base);
     192  
     193    if (in == STDIN_FILE_NO)
     194      {
     195        inindex = -1;
     196        infile = "";
     197      }
     198    else
     199      {
     200        inindex = pex_msdos_fdindex (ms, in);
     201        infile = ms->files[inindex];
     202      }
     203  
     204    if (out == STDOUT_FILE_NO)
     205      {
     206        outindex = -1;
     207        outfile = "";
     208      }
     209    else
     210      {
     211        outindex = pex_msdos_fdindex (ms, out);
     212        outfile = ms->files[outindex];
     213      }
     214  
     215    scmd = XNEWVEC (char, strlen (program)
     216  		  + ((flags & PEXECUTE_SEARCH) != 0 ? 4 : 0)
     217  		  + strlen (rf)
     218  		  + strlen (infile)
     219  		  + strlen (outfile)
     220  		  + 10);
     221    sprintf (scmd, "%s%s @%s%s%s%s%s",
     222  	   program,
     223  	   (flags & PEXECUTE_SEARCH) != 0 ? ".exe" : "",
     224  	   rf,
     225  	   inindex != -1 ? " <" : "",
     226  	   infile,
     227  	   outindex != -1 ? " >" : "",
     228  	   outfile);
     229  
     230    argfile = fopen (rf, "w");
     231    if (argfile == NULL)
     232      {
     233        *err = errno;
     234        free (scmd);
     235        free (rf);
     236        *errmsg = "cannot open temporary command file";
     237        return (pid_t) -1;
     238      }
     239  
     240    for (i = 1; argv[i] != NULL; ++i)
     241      {
     242        char *p;
     243  
     244        for (p = argv[i]; *p != '\0'; ++p)
     245  	{
     246  	  if (*p == '"' || *p == '\'' || *p == '\\' || ISSPACE (*p))
     247  	    putc ('\\', argfile);
     248  	  putc (*p, argfile);
     249  	}
     250        putc ('\n', argfile);
     251      }
     252  
     253    fclose (argfile);
     254  
     255    status = system (scmd);
     256  
     257    if (status == -1)
     258      {
     259        *err = errno;
     260        remove (rf);
     261        free (scmd);
     262        free (rf);
     263        *errmsg = "system";
     264        return (pid_t) -1;
     265      }
     266  
     267    remove (rf);
     268    free (scmd);
     269    free (rf);
     270  
     271    /* Save the exit status for later.  When we are called, obj->count
     272       is the number of children which have executed before this
     273       one.  */
     274    ms->statuses = XRESIZEVEC(int, ms->statuses, obj->count + 1);
     275    ms->statuses[obj->count] = status;
     276  
     277    return (pid_t) obj->count;
     278  }
     279  
     280  /* Wait for a child process to complete.  Actually the child process
     281     has already completed, and we just need to return the exit
     282     status.  */
     283  
     284  static pid_t
     285  pex_msdos_wait (struct pex_obj *obj, pid_t pid, int *status,
     286  		struct pex_time *time, int done ATTRIBUTE_UNUSED,
     287  		const char **errmsg ATTRIBUTE_UNUSED,
     288  		int *err ATTRIBUTE_UNUSED)
     289  {
     290    struct pex_msdos *ms;
     291  
     292    ms = (struct pex_msdos *) obj->sysdep;
     293  
     294    if (time != NULL)
     295      memset (time, 0, sizeof *time);
     296  
     297    *status = ms->statuses[pid];
     298  
     299    return 0;
     300  }
     301  
     302  /* Clean up the pex_msdos structure.  */
     303  
     304  static void
     305  pex_msdos_cleanup (struct pex_obj  *obj)
     306  {
     307    struct pex_msdos *ms;
     308    int i;
     309  
     310    ms = (struct pex_msdos *) obj->sysdep;
     311    for (i = 0; i < PEX_MSDOS_FILE_COUNT; ++i)
     312      free (msdos->files[i]);
     313    free (msdos->statuses);
     314    free (msdos);
     315    obj->sysdep = NULL;
     316  }