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