Copyright 2017
[s-roff.git] / src / lib-roff / spawnvp.c
blobf67a0f3e6279189329251177f1845a17247afb63
1 /*@
2 * Copyright (c) 2014 - 2017 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
4 * Copyright (C) 2004
5 * Free Software Foundation, Inc.
6 * Written by: Keith Marshall (keith.d.marshall@ntlworld.com)
8 * This is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2, or (at your option) any later
11 * version.
13 * This is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with groff; see the file COPYING. If not, write to the Free Software
20 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "config.h"
25 #include <stdio.h>
26 #include <stdlib.h>
28 #ifdef HAVE_PROCESS_H
29 # include <process.h>
30 #endif
32 #if defined(__MSDOS__) \
33 || (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN__)) \
34 || defined(__EMX__)
35 # 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').
40 # include "nonposix.h"
42 # ifndef REPORT_ERROR
43 # define REPORT_ERROR(WHY) fprintf(stderr, "%s:%s\n", program_name, WHY)
44 # endif
45 # ifndef ARGV_MALLOC_ERROR
46 # define ARGV_MALLOC_ERROR "malloc: Allocation for 'argv' failed"
47 # endif
49 extern char *program_name; // FIXME
51 extern char *quote_arg(char *string); // FIXME
52 extern void purge_quoted_args(char **argv);
54 int
55 spawnvp_wrapper(int mode, char *path, char **argv)
57 /* Invoke the system `spawnvp' service
58 * enclosing the passed arguments in double quotes, as required,
59 * so that the (broken) default parsing in the MSVC runtime doesn't
60 * split them at whitespace. */
62 char **quoted_argv; /* used to build a quoted local copy of `argv' */
64 int i; /* used as an index into `argv' or `quoted_argv' */
65 int status = -1; /* initialise return code, in case we fail */
66 int argc = 0; /* initialise argument count; may be none */
68 /* First count the number of arguments
69 * which are actually present in the passed `argv'. */
71 if (argv)
72 for (quoted_argv = argv; *quoted_argv; ++argc, ++quoted_argv)
75 /* If we do not now have an argument count,
76 * then we must fall through and fail. */
78 if (argc) {
79 /* We do have at least one argument:
80 * We will use a copy of the `argv', in which to do the quoting,
81 * so we must allocate space for it. */
83 if ((quoted_argv = (char **)malloc(++argc * sizeof(char **))) == NULL) {
84 /* If we didn't get enough space,
85 * then complain, and bail out gracefully. */
87 REPORT_ERROR(ARGV_MALLOC_ERROR);
88 exit(1);
91 /* Now copy the passed `argv' into our new vector,
92 * quoting its contents as required. */
94 for (i = 0; i < argc; i++)
95 quoted_argv[i] = quote_arg(argv[i]);
97 /* Invoke the MSVC `spawnvp' service
98 * passing our now appropriately quoted copy of `argv'. */
100 status = spawnvp(mode, path, quoted_argv);
102 /* Clean up our memory allocations
103 * for the quoted copy of `argv', which is no longer required. */
105 purge_quoted_args(quoted_argv);
106 free(quoted_argv);
109 /* Finally,
110 * return the status code returned by `spawnvp',
111 * or a failure code if we fell through. */
113 return status;
116 #endif /* __MSDOS__ || _WIN32 */
117 // s-it2-mode