1151497Sru/* Copyright (C) 2004
2151497Sru   Free Software Foundation, Inc.
3151497Sru     Written by: Keith Marshall (keith.d.marshall@ntlworld.com)
4151497Sru
5151497SruThis file is part of groff.
6151497Sru
7151497Srugroff is free software; you can redistribute it and/or modify it under
8151497Sruthe terms of the GNU General Public License as published by the Free
9151497SruSoftware Foundation; either version 2, or (at your option) any later
10151497Sruversion.
11151497Sru
12151497Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY
13151497SruWARRANTY; without even the implied warranty of MERCHANTABILITY or
14151497SruFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15151497Srufor more details.
16151497Sru
17151497SruYou should have received a copy of the GNU General Public License along
18151497Sruwith groff; see the file COPYING.  If not, write to the Free Software
19151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
20151497Sru
21151497Sru#ifdef HAVE_CONFIG_H
22151497Sru# include "config.h"
23151497Sru#endif
24151497Sru
25151497Sru#include <stdio.h>
26151497Sru#include <stdlib.h>
27151497Sru
28151497Sru#ifdef HAVE_PROCESS_H
29151497Sru# include <process.h>
30151497Sru#endif
31151497Sru
32151497Sru#if defined(__MSDOS__) \
33151497Sru    || (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN__)) \
34151497Sru    || defined(__EMX__)
35151497Sru
36151497Sru#define SPAWN_FUNCTION_WRAPPERS 1
37151497Sru
38151497Sru/* Define the default mechanism, and messages, for error reporting
39151497Sru * (user may substitute a preferred alternative, by defining his own
40151497Sru *  implementation of the macros REPORT_ERROR and ARGV_MALLOC_ERROR,
41151497Sru *  in the header file `nonposix.h').
42151497Sru */
43151497Sru
44151497Sru#include "nonposix.h"
45151497Sru
46151497Sru#ifndef  REPORT_ERROR
47151497Sru# define REPORT_ERROR(WHY)  fprintf(stderr, "%s:%s\n", program_name, WHY)
48151497Sru#endif
49151497Sru#ifndef  ARGV_MALLOC_ERROR
50151497Sru# define ARGV_MALLOC_ERROR    "malloc: Allocation for 'argv' failed"
51151497Sru#endif
52151497Sru
53151497Sruextern char *program_name;
54151497Sru
55151497Sruextern char *quote_arg(char *string);
56151497Sruextern void purge_quoted_args(char **argv);
57151497Sru
58151497Sruint
59151497Sruspawnvp_wrapper(int mode, char *path, char **argv)
60151497Sru{
61151497Sru  /* Invoke the system `spawnvp' service
62151497Sru   * enclosing the passed arguments in double quotes, as required,
63151497Sru   * so that the (broken) default parsing in the MSVC runtime doesn't
64151497Sru   * split them at whitespace. */
65151497Sru
66151497Sru  char **quoted_argv;	/* used to build a quoted local copy of `argv' */
67151497Sru
68151497Sru  int i;		/* used as an index into `argv' or `quoted_argv' */
69151497Sru  int status = -1;	/* initialise return code, in case we fail */
70151497Sru  int argc = 0;		/* initialise argument count; may be none  */
71151497Sru
72151497Sru  /* First count the number of arguments
73151497Sru   * which are actually present in the passed `argv'. */
74151497Sru
75151497Sru  if (argv)
76151497Sru    for (quoted_argv = argv; *quoted_argv; ++argc, ++quoted_argv)
77151497Sru      ;
78151497Sru
79151497Sru  /* If we do not now have an argument count,
80151497Sru   * then we must fall through and fail. */
81151497Sru
82151497Sru  if (argc) {
83151497Sru    /* We do have at least one argument:
84151497Sru     * We will use a copy of the `argv', in which to do the quoting,
85151497Sru     * so we must allocate space for it. */
86151497Sru
87151497Sru    if ((quoted_argv = (char **)malloc(++argc * sizeof(char **))) == NULL) {
88151497Sru      /* If we didn't get enough space,
89151497Sru       * then complain, and bail out gracefully. */
90151497Sru
91151497Sru      REPORT_ERROR(ARGV_MALLOC_ERROR);
92151497Sru      exit(1);
93151497Sru    }
94151497Sru
95151497Sru    /* Now copy the passed `argv' into our new vector,
96151497Sru     * quoting its contents as required. */
97151497Sru
98151497Sru    for (i = 0; i < argc; i++)
99151497Sru      quoted_argv[i] = quote_arg(argv[i]);
100151497Sru
101151497Sru    /* Invoke the MSVC `spawnvp' service
102151497Sru     * passing our now appropriately quoted copy of `argv'. */
103151497Sru
104151497Sru    status = spawnvp(mode, path, quoted_argv);
105151497Sru
106151497Sru    /* Clean up our memory allocations
107151497Sru     * for the quoted copy of `argv', which is no longer required. */
108151497Sru
109151497Sru    purge_quoted_args(quoted_argv);
110151497Sru    free(quoted_argv);
111151497Sru  }
112151497Sru
113151497Sru  /* Finally,
114151497Sru   * return the status code returned by `spawnvp',
115151497Sru   * or a failure code if we fell through. */
116151497Sru
117151497Sru  return status;
118151497Sru}
119151497Sru
120151497Sru#endif  /* __MSDOS__ || _WIN32 */
121151497Sru
122151497Sru/* spawnvp.c: end of file */
123