Mark compat code with attribute_compat_text_section.
[kopensolaris-gnu/glibc.git] / libio / oldiopopen.c
1 /* Copyright (C) 1998-2002, 2004 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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.
19
20    As a special exception, if you link the code in this file with
21    files compiled with a GNU compiler to produce an executable,
22    that does not cause the resulting executable to be covered by
23    the GNU Lesser General Public License.  This exception does not
24    however invalidate any other reasons why the executable file
25    might be covered by the GNU Lesser General Public License.
26    This exception applies to code released by its copyright holders
27    in files containing the exception.  */
28
29 #define _IO_USE_OLD_IO_FILE
30 #ifndef _POSIX_SOURCE
31 # define _POSIX_SOURCE
32 #endif
33 #include "libioP.h"
34 #if _IO_HAVE_SYS_WAIT
35 #include <signal.h>
36 #include <unistd.h>
37 #ifdef __STDC__
38 #include <stdlib.h>
39 #endif
40 #ifdef _LIBC
41 # include <unistd.h>
42 #endif
43 #include <sys/types.h>
44 #include <sys/wait.h>
45
46 #ifndef _IO_fork
47 #ifdef _LIBC
48 #define _IO_fork __fork
49 #else
50 #define _IO_fork fork /* defined in libiberty, if needed */
51 #endif
52 extern _IO_pid_t _IO_fork __P ((void));
53 #endif
54
55 #endif /* _IO_HAVE_SYS_WAIT */
56
57 #include <shlib-compat.h>
58 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
59
60 #ifndef _IO_pipe
61 #ifdef _LIBC
62 #define _IO_pipe __pipe
63 #else
64 #define _IO_pipe pipe
65 #endif
66 extern int _IO_pipe __P ((int des[2]));
67 #endif
68
69 #ifndef _IO_dup2
70 #ifdef _LIBC
71 #define _IO_dup2 __dup2
72 #else
73 #define _IO_dup2 dup2
74 #endif
75 extern int _IO_dup2 __P ((int fd, int fd2));
76 #endif
77
78 #ifndef _IO_waitpid
79 #ifdef _LIBC
80 #define _IO_waitpid __waitpid
81 #else
82 #define _IO_waitpid waitpid
83 #endif
84 #endif
85
86 #ifndef _IO_execl
87 #define _IO_execl execl
88 #endif
89 #ifndef _IO__exit
90 #define _IO__exit _exit
91 #endif
92
93 #ifndef _IO_close
94 #ifdef _LIBC
95 #define _IO_close __close
96 #else
97 #define _IO_close close
98 #endif
99 #endif
100
101 struct _IO_proc_file
102 {
103   struct _IO_FILE_complete_plus file;
104   /* Following fields must match those in class procbuf (procbuf.h) */
105   _IO_pid_t pid;
106   struct _IO_proc_file *next;
107 };
108 typedef struct _IO_proc_file _IO_proc_file;
109
110 static struct _IO_proc_file *old_proc_file_chain;
111
112 #ifdef _IO_MTSAFE_IO
113 static _IO_lock_t proc_file_chain_lock = _IO_lock_initializer;
114
115 static void
116 unlock (void *not_used)
117 {
118   _IO_lock_unlock (proc_file_chain_lock);
119 }
120 #endif
121
122 _IO_FILE *
123 attribute_compat_text_section
124 _IO_old_proc_open (fp, command, mode)
125      _IO_FILE *fp;
126      const char *command;
127      const char *mode;
128 {
129 #if _IO_HAVE_SYS_WAIT
130   volatile int read_or_write;
131   volatile int parent_end, child_end;
132   int pipe_fds[2];
133   _IO_pid_t child_pid;
134   if (_IO_file_is_open (fp))
135     return NULL;
136   if (_IO_pipe (pipe_fds) < 0)
137     return NULL;
138   if (mode[0] == 'r' && mode[1] == '\0')
139     {
140       parent_end = pipe_fds[0];
141       child_end = pipe_fds[1];
142       read_or_write = _IO_NO_WRITES;
143     }
144   else if (mode[0] == 'w' && mode[1] == '\0')
145     {
146       parent_end = pipe_fds[1];
147       child_end = pipe_fds[0];
148       read_or_write = _IO_NO_READS;
149     }
150   else
151     {
152       _IO_close (pipe_fds[0]);
153       _IO_close (pipe_fds[1]);
154       __set_errno (EINVAL);
155       return NULL;
156     }
157   ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
158   if (child_pid == 0)
159     {
160       int child_std_end = mode[0] == 'r' ? 1 : 0;
161       struct _IO_proc_file *p;
162
163       _IO_close (parent_end);
164       if (child_end != child_std_end)
165         {
166           _IO_dup2 (child_end, child_std_end);
167           _IO_close (child_end);
168         }
169       /* POSIX.2:  "popen() shall ensure that any streams from previous
170          popen() calls that remain open in the parent process are closed
171          in the new child process." */
172       for (p = old_proc_file_chain; p; p = p->next)
173         _IO_close (_IO_fileno ((_IO_FILE *) p));
174
175       _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
176       _IO__exit (127);
177     }
178   _IO_close (child_end);
179   if (child_pid < 0)
180     {
181       _IO_close (parent_end);
182       return NULL;
183     }
184   _IO_fileno (fp) = parent_end;
185
186   /* Link into old_proc_file_chain. */
187 #ifdef _IO_MTSAFE_IO
188   _IO_cleanup_region_start_noarg (unlock);
189   _IO_lock_lock (proc_file_chain_lock);
190 #endif
191   ((_IO_proc_file *) fp)->next = old_proc_file_chain;
192   old_proc_file_chain = (_IO_proc_file *) fp;
193 #ifdef _IO_MTSAFE_IO
194   _IO_lock_unlock (proc_file_chain_lock);
195   _IO_cleanup_region_end (0);
196 #endif
197
198   _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
199   return fp;
200 #else /* !_IO_HAVE_SYS_WAIT */
201   return NULL;
202 #endif
203 }
204
205 _IO_FILE *
206 attribute_compat_text_section
207 _IO_old_popen (command, mode)
208      const char *command;
209      const char *mode;
210 {
211   struct locked_FILE
212   {
213     struct _IO_proc_file fpx;
214 #ifdef _IO_MTSAFE_IO
215     _IO_lock_t lock;
216 #endif
217   } *new_f;
218   _IO_FILE *fp;
219
220   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
221   if (new_f == NULL)
222     return NULL;
223 #ifdef _IO_MTSAFE_IO
224   new_f->fpx.file.file._file._lock = &new_f->lock;
225 #endif
226   fp = &new_f->fpx.file.file._file;
227   _IO_old_init (fp, 0);
228   _IO_JUMPS ((struct _IO_FILE_plus *) &new_f->fpx.file) = &_IO_old_proc_jumps;
229   _IO_old_file_init ((struct _IO_FILE_plus *) &new_f->fpx.file);
230 #if  !_IO_UNIFIED_JUMPTABLES
231   new_f->fpx.file.vtable = NULL;
232 #endif
233   if (_IO_old_proc_open (fp, command, mode) != NULL)
234     return fp;
235   INTUSE(_IO_un_link) ((struct _IO_FILE_plus *) &new_f->fpx.file);
236   free (new_f);
237   return NULL;
238 }
239
240 int
241 attribute_compat_text_section
242 _IO_old_proc_close (fp)
243      _IO_FILE *fp;
244 {
245   /* This is not name-space clean. FIXME! */
246 #if _IO_HAVE_SYS_WAIT
247   int wstatus;
248   _IO_proc_file **ptr = &old_proc_file_chain;
249   _IO_pid_t wait_pid;
250   int status = -1;
251
252   /* Unlink from old_proc_file_chain. */
253 #ifdef _IO_MTSAFE_IO
254   _IO_cleanup_region_start_noarg (unlock);
255   _IO_lock_lock (proc_file_chain_lock);
256 #endif
257   for ( ; *ptr != NULL; ptr = &(*ptr)->next)
258     {
259       if (*ptr == (_IO_proc_file *) fp)
260         {
261           *ptr = (*ptr)->next;
262           status = 0;
263           break;
264         }
265     }
266 #ifdef _IO_MTSAFE_IO
267   _IO_lock_unlock (proc_file_chain_lock);
268   _IO_cleanup_region_end (0);
269 #endif
270
271   if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
272     return -1;
273   /* POSIX.2 Rationale:  "Some historical implementations either block
274      or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
275      for the child process to terminate.  Since this behavior is not
276      described in POSIX.2, such implementations are not conforming." */
277   do
278     {
279       wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
280     }
281   while (wait_pid == -1 && errno == EINTR);
282   if (wait_pid == -1)
283     return -1;
284   return wstatus;
285 #else /* !_IO_HAVE_SYS_WAIT */
286   return -1;
287 #endif
288 }
289
290 const struct _IO_jump_t _IO_old_proc_jumps = {
291   JUMP_INIT_DUMMY,
292   JUMP_INIT(finish, _IO_old_file_finish),
293   JUMP_INIT(overflow, _IO_old_file_overflow),
294   JUMP_INIT(underflow, _IO_old_file_underflow),
295   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
296   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
297   JUMP_INIT(xsputn, _IO_old_file_xsputn),
298   JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
299   JUMP_INIT(seekoff, _IO_old_file_seekoff),
300   JUMP_INIT(seekpos, _IO_default_seekpos),
301   JUMP_INIT(setbuf, _IO_old_file_setbuf),
302   JUMP_INIT(sync, _IO_old_file_sync),
303   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
304   JUMP_INIT(read, INTUSE(_IO_file_read)),
305   JUMP_INIT(write, _IO_old_file_write),
306   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
307   JUMP_INIT(close, _IO_old_proc_close),
308   JUMP_INIT(stat, INTUSE(_IO_file_stat)),
309   JUMP_INIT(showmanyc, _IO_default_showmanyc),
310   JUMP_INIT(imbue, _IO_default_imbue)
311 };
312
313 strong_alias (_IO_old_popen, __old_popen)
314 compat_symbol (libc, _IO_old_popen, _IO_popen, GLIBC_2_0);
315 compat_symbol (libc, __old_popen, popen, GLIBC_2_0);
316 compat_symbol (libc, _IO_old_proc_open, _IO_proc_open, GLIBC_2_0);
317 compat_symbol (libc, _IO_old_proc_close, _IO_proc_close, GLIBC_2_0);
318
319 #endif