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@ntlworld.com) 6 7This file is part of groff. 8 9groff is free software; you can redistribute it and/or modify it under 10the terms of the GNU General Public License as published by the Free 11Software Foundation; either version 2, or (at your option) any later 12version. 13 14groff is distributed in the hope that it will be useful, but WITHOUT ANY 15WARRANTY; without even the implied warranty of MERCHANTABILITY or 16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17for more details. 18 19You should have received a copy of the GNU General Public License along 20with groff; see the file COPYING. If not, write to the Free Software 21Foundation, 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 55extern char *program_name; 56 57extern char *quote_arg(char *string); 58extern void purge_quoted_args(char **argv); 59 60int 61spawnvp_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