oldiopopen.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /* Copyright (C) 1998-2026 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <https://www.gnu.org/licenses/>.
  14. As a special exception, if you link the code in this file with
  15. files compiled with a GNU compiler to produce an executable,
  16. that does not cause the resulting executable to be covered by
  17. the GNU Lesser General Public License. This exception does not
  18. however invalidate any other reasons why the executable file
  19. might be covered by the GNU Lesser General Public License.
  20. This exception applies to code released by its copyright holders
  21. in files containing the exception. */
  22. #define _IO_USE_OLD_IO_FILE
  23. #include "libioP.h"
  24. #include <signal.h>
  25. #include <unistd.h>
  26. #include <stdlib.h>
  27. #include <unistd.h>
  28. #include <sys/types.h>
  29. #include <sys/wait.h>
  30. #include <shlib-compat.h>
  31. #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
  32. struct _IO_proc_file
  33. {
  34. struct _IO_FILE_complete_plus file;
  35. /* Following fields must match those in class procbuf (procbuf.h) */
  36. pid_t pid;
  37. struct _IO_proc_file *next;
  38. };
  39. typedef struct _IO_proc_file _IO_proc_file;
  40. static struct _IO_proc_file *old_proc_file_chain;
  41. #ifdef _IO_MTSAFE_IO
  42. static _IO_lock_t proc_file_chain_lock = _IO_lock_initializer;
  43. static void
  44. unlock (void *not_used)
  45. {
  46. _IO_lock_unlock (proc_file_chain_lock);
  47. }
  48. #endif
  49. FILE *
  50. attribute_compat_text_section
  51. _IO_old_proc_open (FILE *fp, const char *command, const char *mode)
  52. {
  53. volatile int read_or_write;
  54. volatile int parent_end, child_end;
  55. int pipe_fds[2];
  56. pid_t child_pid;
  57. if (_IO_file_is_open (fp))
  58. return NULL;
  59. if (__pipe (pipe_fds) < 0)
  60. return NULL;
  61. if (mode[0] == 'r' && mode[1] == '\0')
  62. {
  63. parent_end = pipe_fds[0];
  64. child_end = pipe_fds[1];
  65. read_or_write = _IO_NO_WRITES;
  66. }
  67. else if (mode[0] == 'w' && mode[1] == '\0')
  68. {
  69. parent_end = pipe_fds[1];
  70. child_end = pipe_fds[0];
  71. read_or_write = _IO_NO_READS;
  72. }
  73. else
  74. {
  75. __close (pipe_fds[0]);
  76. __close (pipe_fds[1]);
  77. __set_errno (EINVAL);
  78. return NULL;
  79. }
  80. ((_IO_proc_file *) fp)->pid = child_pid = __fork ();
  81. if (child_pid == 0)
  82. {
  83. int child_std_end = mode[0] == 'r' ? 1 : 0;
  84. struct _IO_proc_file *p;
  85. __close (parent_end);
  86. if (child_end != child_std_end)
  87. {
  88. __dup2 (child_end, child_std_end);
  89. __close (child_end);
  90. }
  91. /* POSIX.2: "popen() shall ensure that any streams from previous
  92. popen() calls that remain open in the parent process are closed
  93. in the new child process." */
  94. for (p = old_proc_file_chain; p; p = p->next)
  95. __close (_IO_fileno ((FILE *) p));
  96. execl ("/bin/sh", "sh", "-c", command, (char *) 0);
  97. _exit (127);
  98. }
  99. __close (child_end);
  100. if (child_pid < 0)
  101. {
  102. __close (parent_end);
  103. return NULL;
  104. }
  105. _IO_fileno (fp) = parent_end;
  106. /* Link into old_proc_file_chain. */
  107. #ifdef _IO_MTSAFE_IO
  108. _IO_cleanup_region_start_noarg (unlock);
  109. _IO_lock_lock (proc_file_chain_lock);
  110. #endif
  111. ((_IO_proc_file *) fp)->next = old_proc_file_chain;
  112. old_proc_file_chain = (_IO_proc_file *) fp;
  113. #ifdef _IO_MTSAFE_IO
  114. _IO_lock_unlock (proc_file_chain_lock);
  115. _IO_cleanup_region_end (0);
  116. #endif
  117. _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
  118. return fp;
  119. }
  120. FILE *
  121. attribute_compat_text_section
  122. _IO_old_popen (const char *command, const char *mode)
  123. {
  124. struct locked_FILE
  125. {
  126. struct _IO_proc_file fpx;
  127. #ifdef _IO_MTSAFE_IO
  128. _IO_lock_t lock;
  129. #endif
  130. } *new_f;
  131. FILE *fp;
  132. new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
  133. if (new_f == NULL)
  134. return NULL;
  135. #ifdef _IO_MTSAFE_IO
  136. new_f->fpx.file.file._file._lock = &new_f->lock;
  137. #endif
  138. fp = &new_f->fpx.file.file._file;
  139. _IO_old_init (fp, 0);
  140. _IO_JUMPS_FILE_plus (&new_f->fpx.file) = &_IO_old_proc_jumps;
  141. _IO_old_file_init_internal ((struct _IO_FILE_plus *) &new_f->fpx.file);
  142. if (_IO_old_proc_open (fp, command, mode) != NULL)
  143. return fp;
  144. _IO_un_link ((struct _IO_FILE_plus *) &new_f->fpx.file);
  145. free (new_f);
  146. return NULL;
  147. }
  148. int
  149. attribute_compat_text_section
  150. _IO_old_proc_close (FILE *fp)
  151. {
  152. /* This is not name-space clean. FIXME! */
  153. int wstatus;
  154. _IO_proc_file **ptr = &old_proc_file_chain;
  155. pid_t wait_pid;
  156. int status = -1;
  157. /* Unlink from old_proc_file_chain. */
  158. #ifdef _IO_MTSAFE_IO
  159. _IO_cleanup_region_start_noarg (unlock);
  160. _IO_lock_lock (proc_file_chain_lock);
  161. #endif
  162. for ( ; *ptr != NULL; ptr = &(*ptr)->next)
  163. {
  164. if (*ptr == (_IO_proc_file *) fp)
  165. {
  166. *ptr = (*ptr)->next;
  167. status = 0;
  168. break;
  169. }
  170. }
  171. #ifdef _IO_MTSAFE_IO
  172. _IO_lock_unlock (proc_file_chain_lock);
  173. _IO_cleanup_region_end (0);
  174. #endif
  175. if (status < 0 || __close (_IO_fileno(fp)) < 0)
  176. return -1;
  177. /* POSIX.2 Rationale: "Some historical implementations either block
  178. or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
  179. for the child process to terminate. Since this behavior is not
  180. described in POSIX.2, such implementations are not conforming." */
  181. do
  182. {
  183. wait_pid = __waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
  184. }
  185. while (wait_pid == -1 && errno == EINTR);
  186. if (wait_pid == -1)
  187. return -1;
  188. return wstatus;
  189. }
  190. strong_alias (_IO_old_popen, __old_popen)
  191. compat_symbol (libc, _IO_old_popen, _IO_popen, GLIBC_2_0);
  192. compat_symbol (libc, __old_popen, popen, GLIBC_2_0);
  193. compat_symbol (libc, _IO_old_proc_open, _IO_proc_open, GLIBC_2_0);
  194. compat_symbol (libc, _IO_old_proc_close, _IO_proc_close, GLIBC_2_0);
  195. #endif