Home | History | Annotate | Line # | Download | only in libgroff
      1 /*	$NetBSD: spawnvp.c,v 1.1.1.1 2016/01/13 18:41:48 christos Exp $	*/
      2 
      3 /* Copyright (C) 2004
      4    Free Software Foundation, Inc.
      5      Written by: Keith Marshall (keith.d.marshall (at) ntlworld.com)
      6 
      7 This file is part of groff.
      8 
      9 groff is free software; you can redistribute it and/or modify it under
     10 the terms of the GNU General Public License as published by the Free
     11 Software Foundation; either version 2, or (at your option) any later
     12 version.
     13 
     14 groff is distributed in the hope that it will be useful, but WITHOUT ANY
     15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
     16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     17 for more details.
     18 
     19 You should have received a copy of the GNU General Public License along
     20 with groff; see the file COPYING.  If not, write to the Free Software
     21 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
     22 
     23 #ifdef HAVE_CONFIG_H
     24 # include "config.h"
     25 #endif
     26 
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 
     30 #ifdef HAVE_PROCESS_H
     31 # include <process.h>
     32 #endif
     33 
     34 #if defined(__MSDOS__) \
     35     || (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN__)) \
     36     || defined(__EMX__)
     37 
     38 #define SPAWN_FUNCTION_WRAPPERS 1
     39 
     40 /* Define the default mechanism, and messages, for error reporting
     41  * (user may substitute a preferred alternative, by defining his own
     42  *  implementation of the macros REPORT_ERROR and ARGV_MALLOC_ERROR,
     43  *  in the header file `nonposix.h').
     44  */
     45 
     46 #include "nonposix.h"
     47 
     48 #ifndef  REPORT_ERROR
     49 # define REPORT_ERROR(WHY)  fprintf(stderr, "%s:%s\n", program_name, WHY)
     50 #endif
     51 #ifndef  ARGV_MALLOC_ERROR
     52 # define ARGV_MALLOC_ERROR    "malloc: Allocation for 'argv' failed"
     53 #endif
     54 
     55 extern char *program_name;
     56 
     57 extern char *quote_arg(char *string);
     58 extern void purge_quoted_args(char **argv);
     59 
     60 int
     61 spawnvp_wrapper(int mode, char *path, char **argv)
     62 {
     63   /* Invoke the system `spawnvp' service
     64    * enclosing the passed arguments in double quotes, as required,
     65    * so that the (broken) default parsing in the MSVC runtime doesn't
     66    * split them at whitespace. */
     67 
     68   char **quoted_argv;	/* used to build a quoted local copy of `argv' */
     69 
     70   int i;		/* used as an index into `argv' or `quoted_argv' */
     71   int status = -1;	/* initialise return code, in case we fail */
     72   int argc = 0;		/* initialise argument count; may be none  */
     73 
     74   /* First count the number of arguments
     75    * which are actually present in the passed `argv'. */
     76 
     77   if (argv)
     78     for (quoted_argv = argv; *quoted_argv; ++argc, ++quoted_argv)
     79       ;
     80 
     81   /* If we do not now have an argument count,
     82    * then we must fall through and fail. */
     83 
     84   if (argc) {
     85     /* We do have at least one argument:
     86      * We will use a copy of the `argv', in which to do the quoting,
     87      * so we must allocate space for it. */
     88 
     89     if ((quoted_argv = (char **)malloc(++argc * sizeof(char **))) == NULL) {
     90       /* If we didn't get enough space,
     91        * then complain, and bail out gracefully. */
     92 
     93       REPORT_ERROR(ARGV_MALLOC_ERROR);
     94       exit(1);
     95     }
     96 
     97     /* Now copy the passed `argv' into our new vector,
     98      * quoting its contents as required. */
     99 
    100     for (i = 0; i < argc; i++)
    101       quoted_argv[i] = quote_arg(argv[i]);
    102 
    103     /* Invoke the MSVC `spawnvp' service
    104      * passing our now appropriately quoted copy of `argv'. */
    105 
    106     status = spawnvp(mode, path, quoted_argv);
    107 
    108     /* Clean up our memory allocations
    109      * for the quoted copy of `argv', which is no longer required. */
    110 
    111     purge_quoted_args(quoted_argv);
    112     free(quoted_argv);
    113   }
    114 
    115   /* Finally,
    116    * return the status code returned by `spawnvp',
    117    * or a failure code if we fell through. */
    118 
    119   return status;
    120 }
    121 
    122 #endif  /* __MSDOS__ || _WIN32 */
    123 
    124 /* spawnvp.c: end of file */
    125