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