0cc6fb182536858e26bd3cbaf1d8c1a8c18bef35
[platform/upstream/groff.git] / src / libs / libgroff / spawnvp.c
1 /* Copyright (C) 2004-2014  Free Software Foundation, Inc.
2      Written by: Keith Marshall (keith.d.marshall@ntlworld.com)
3
4 This file is part of groff.
5
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.
10
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
14 for more details.
15
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/>. */
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #ifdef HAVE_PROCESS_H
27 # include <process.h>
28 #endif
29
30 #if defined(__MSDOS__) \
31     || (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN__)) \
32     || defined(__EMX__)
33
34 #define SPAWN_FUNCTION_WRAPPERS 1
35
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  */
41
42 #include "nonposix.h"
43
44 #ifndef  REPORT_ERROR
45 # define REPORT_ERROR(WHY)  fprintf(stderr, "%s:%s\n", program_name, WHY)
46 #endif
47 #ifndef  ARGV_MALLOC_ERROR
48 # define ARGV_MALLOC_ERROR    "malloc: Allocation for 'argv' failed"
49 #endif
50
51 extern char *program_name;
52
53 extern char *quote_arg(char *string);
54 extern void purge_quoted_args(char **argv);
55
56 int
57 spawnvp_wrapper(int mode, char *path, char **argv)
58 {
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. */
63
64   char **quoted_argv;   /* used to build a quoted local copy of `argv' */
65
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  */
69
70   /* First count the number of arguments
71    * which are actually present in the passed `argv'. */
72
73   if (argv)
74     for (quoted_argv = argv; *quoted_argv; ++argc, ++quoted_argv)
75       ;
76
77   /* If we do not now have an argument count,
78    * then we must fall through and fail. */
79   
80   if (argc) {
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. */
84
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. */
88
89       REPORT_ERROR(ARGV_MALLOC_ERROR);
90       exit(1);
91     }
92
93     /* Now copy the passed `argv' into our new vector,
94      * quoting its contents as required. */
95     
96     for (i = 0; i < argc; i++)
97       quoted_argv[i] = quote_arg(argv[i]);
98
99     /* Invoke the MSVC `spawnvp' service
100      * passing our now appropriately quoted copy of `argv'. */
101
102     status = spawnvp(mode, path, quoted_argv);
103
104     /* Clean up our memory allocations
105      * for the quoted copy of `argv', which is no longer required. */
106
107     purge_quoted_args(quoted_argv);
108     free(quoted_argv);
109   }
110
111   /* Finally,
112    * return the status code returned by `spawnvp',
113    * or a failure code if we fell through. */
114
115   return status;
116 }
117
118 #endif  /* __MSDOS__ || _WIN32 */
119
120 /* spawnvp.c: end of file */