/contrib/groff/src/libs/libgroff/spawnvp.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 122 lines · 46 code · 29 blank · 47 comment · 10 complexity · 8e16a132635e5255d522edd7c41984d0 MD5 · raw file

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