You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
5.0 KiB

3 months ago
  1. /**
  2. @file
  3. @ingroup util
  4. @brief Forks a command and sets up pipes to and from.
  5. @author Rick L Spickelmier
  6. @author Richard Rudell
  7. @copyright@parblock
  8. Copyright (c) 1994-1998 The Regents of the Univ. of California.
  9. All rights reserved.
  10. Permission is hereby granted, without written agreement and without license
  11. or royalty fees, to use, copy, modify, and distribute this software and its
  12. documentation for any purpose, provided that the above copyright notice and
  13. the following two paragraphs appear in all copies of this software.
  14. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  15. DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  16. OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  17. CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  18. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  19. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  20. FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
  21. "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
  22. MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  23. @endparblock
  24. @copyright@parblock
  25. Copyright (c) 1999-2015, Regents of the University of Colorado
  26. All rights reserved.
  27. Redistribution and use in source and binary forms, with or without
  28. modification, are permitted provided that the following conditions
  29. are met:
  30. Redistributions of source code must retain the above copyright
  31. notice, this list of conditions and the following disclaimer.
  32. Redistributions in binary form must reproduce the above copyright
  33. notice, this list of conditions and the following disclaimer in the
  34. documentation and/or other materials provided with the distribution.
  35. Neither the name of the University of Colorado nor the names of its
  36. contributors may be used to endorse or promote products derived from
  37. this software without specific prior written permission.
  38. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  39. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  40. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  41. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  42. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  43. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  44. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  45. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  46. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  47. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  48. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  49. POSSIBILITY OF SUCH DAMAGE.
  50. @endparblock
  51. */
  52. #include "config.h"
  53. #if HAVE_UNISTD_H == 1
  54. #define _POSIX_SOURCE
  55. #include <unistd.h>
  56. #endif
  57. #include <stdio.h>
  58. #if HAVE_SYS_WAIT_H == 1
  59. #include <sys/wait.h>
  60. #endif
  61. /**
  62. * @def EXTERN
  63. * @brief Allows C linkage when compiling as C++.
  64. */
  65. #ifndef EXTERN
  66. # ifdef __cplusplus
  67. # define EXTERN extern "C"
  68. # else
  69. # define EXTERN extern
  70. # endif
  71. #endif
  72. /**
  73. * @brief Forks a command and sets up pipes to and from.
  74. *
  75. * @return 1 for success, with toCommand and fromCommand pointing to
  76. * the streams; 0 for failure
  77. */
  78. int
  79. util_pipefork(
  80. char * const *argv, /**< normal argv argument list */
  81. FILE **toCommand, /**< pointer to the sending stream */
  82. FILE **fromCommand, /**< pointer to the reading stream */
  83. int *pid /**< process ID */)
  84. {
  85. #if HAVE_SYS_WAIT_H == 1
  86. int forkpid, waitPid;
  87. int topipe[2], frompipe[2];
  88. char buffer[1024];
  89. int status;
  90. /* create the PIPES...
  91. * fildes[0] for reading from command
  92. * fildes[1] for writing to command
  93. */
  94. if (pipe(topipe)) return(0);
  95. if (pipe(frompipe)) return(0);
  96. if ((forkpid = fork()) == 0) {
  97. /* child here, connect the pipes */
  98. (void) dup2(topipe[0], fileno(stdin));
  99. (void) dup2(frompipe[1], fileno(stdout));
  100. (void) close(topipe[0]);
  101. (void) close(topipe[1]);
  102. (void) close(frompipe[0]);
  103. (void) close(frompipe[1]);
  104. (void) execvp(argv[0], argv);
  105. (void) sprintf(buffer, "util_pipefork: can not exec %s", argv[0]);
  106. perror(buffer);
  107. (void) _exit(1);
  108. }
  109. if (pid) {
  110. *pid = forkpid;
  111. }
  112. waitPid = waitpid(-1, &status, WNOHANG);
  113. /* parent here, use fork() semantics to get return status */
  114. if (waitPid == forkpid && WIFEXITED(status)) {
  115. return 0;
  116. }
  117. if ((*toCommand = fdopen(topipe[1], "w")) == NULL) {
  118. return 0;
  119. }
  120. if ((*fromCommand = fdopen(frompipe[0], "r")) == NULL) {
  121. return 0;
  122. }
  123. (void) close(topipe[0]);
  124. (void) close(frompipe[1]);
  125. return 1;
  126. #else
  127. (void) argv; /* to avoid warning */
  128. (void) toCommand; /* to avoid warning */
  129. (void) fromCommand; /* to avoid warning */
  130. (void) pid; /* to avoid warning */
  131. (void) fprintf(stderr,
  132. "util_pipefork: not implemented on your operating system\n");
  133. return 0;
  134. #endif
  135. }