1 /* Copyright (C) 2004-2018 Free Software Foundation, Inc.
2 Written by: Keith Marshall (keith.d.marshall@ntlworld.com)
4 This file is part of groff.
6 groff is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 groff is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
30 #if defined(__MSDOS__) \
31 || (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN__)) \
34 #define SPAWN_FUNCTION_WRAPPERS 1
36 /* Define the default mechanism, and messages, for error reporting
37 * (user may substitute a preferred alternative, by defining his own
38 * implementation of the macros REPORT_ERROR and ARGV_MALLOC_ERROR,
39 * in the header file 'nonposix.h').
45 # define REPORT_ERROR(WHY) fprintf(stderr, "%s:%s\n", program_name, WHY)
47 #ifndef ARGV_MALLOC_ERROR
48 # define ARGV_MALLOC_ERROR "malloc: Allocation for 'argv' failed"
51 extern char *program_name;
53 extern char *quote_arg(char *string);
54 extern void purge_quoted_args(char **argv);
57 spawnvp_wrapper(int mode, char *path, char **argv)
59 /* Invoke the system 'spawnvp' service
60 * enclosing the passed arguments in double quotes, as required,
61 * so that the (broken) default parsing in the MSVC runtime doesn't
62 * split them at whitespace. */
64 char **quoted_argv; /* used to build a quoted local copy of 'argv' */
66 int i; /* used as an index into 'argv' or 'quoted_argv' */
67 int status = -1; /* initialise return code, in case we fail */
68 int argc = 0; /* initialise argument count; may be none */
70 /* First count the number of arguments
71 * which are actually present in the passed 'argv'. */
74 for (quoted_argv = argv; *quoted_argv; ++argc, ++quoted_argv)
77 /* If we do not now have an argument count,
78 * then we must fall through and fail. */
81 /* We do have at least one argument:
82 * We will use a copy of the 'argv', in which to do the quoting,
83 * so we must allocate space for it. */
85 if ((quoted_argv = (char **)malloc(++argc * sizeof(char **))) == NULL) {
86 /* If we didn't get enough space,
87 * then complain, and bail out gracefully. */
89 REPORT_ERROR(ARGV_MALLOC_ERROR);
93 /* Now copy the passed 'argv' into our new vector,
94 * quoting its contents as required. */
96 for (i = 0; i < argc; i++)
97 quoted_argv[i] = quote_arg(argv[i]);
99 /* Invoke the MSVC 'spawnvp' service
100 * passing our now appropriately quoted copy of 'argv'. */
102 status = spawnvp(mode, path, quoted_argv);
104 /* Clean up our memory allocations
105 * for the quoted copy of 'argv', which is no longer required. */
107 purge_quoted_args(quoted_argv);
112 * return the status code returned by 'spawnvp',
113 * or a failure code if we fell through. */
118 #endif /* __MSDOS__ || _WIN32 */
120 /* spawnvp.c: end of file */