| Commit | Line | Data |
|---|---|---|
| 4d3e9548 | 1 | /* Copyright (C) 2004, 2009 |
| 92d0a6a6 JR |
2 | Free Software Foundation, Inc. |
| 3 | Written by: Keith Marshall (keith.d.marshall@ntlworld.com) | |
| 4 | ||
| 5 | This file is part of groff. | |
| 6 | ||
| 7 | groff is free software; you can redistribute it and/or modify it under | |
| 8 | the terms of the GNU General Public License as published by the Free | |
| 4d3e9548 JL |
9 | Software Foundation, either version 3 of the License, or |
| 10 | (at your option) any later version. | |
| 92d0a6a6 JR |
11 | |
| 12 | groff is distributed in the hope that it will be useful, but WITHOUT ANY | |
| 13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 15 | for more details. | |
| 16 | ||
| 4d3e9548 JL |
17 | You should have received a copy of the GNU General Public License |
| 18 | along 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 | ||
| 52 | extern char *program_name; | |
| 53 | ||
| 54 | extern char *quote_arg(char *string); | |
| 55 | extern void purge_quoted_args(char **argv); | |
| 56 | ||
| 57 | int | |
| 58 | spawnvp_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 */ |