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