1cca88dd6Selan //    This is part of the iostream library, providing input/output for C++.
2cca88dd6Selan //    Copyright (C) 1992 Per Bothner.
3cca88dd6Selan //
4cca88dd6Selan //    This library is free software; you can redistribute it and/or
5cca88dd6Selan //    modify it under the terms of the GNU Library General Public
6cca88dd6Selan //    License as published by the Free Software Foundation; either
7cca88dd6Selan //    version 2 of the License, or (at your option) any later version.
8cca88dd6Selan //
9cca88dd6Selan //    This library is distributed in the hope that it will be useful,
10cca88dd6Selan //    but WITHOUT ANY WARRANTY; without even the implied warranty of
11cca88dd6Selan //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12cca88dd6Selan //    Library General Public License for more details.
13cca88dd6Selan //
14cca88dd6Selan //    You should have received a copy of the GNU Library General Public
15cca88dd6Selan //    License along with this library; if not, write to the Free
16cca88dd6Selan //    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17cca88dd6Selan 
18*6767d717Selan #ifdef notdef
19cca88dd6Selan #define _POSIX_SOURCE
20*6767d717Selan #endif
21cca88dd6Selan #include "ioprivate.h"
22cca88dd6Selan #include "procbuf.h"
23cca88dd6Selan #include <signal.h>
24cca88dd6Selan #include <unistd.h>
25cca88dd6Selan #include <sys/wait.h>
26cca88dd6Selan 
27cca88dd6Selan 
28cca88dd6Selan #ifndef FORK
29cca88dd6Selan #define FORK vfork
30cca88dd6Selan #endif
31cca88dd6Selan 
procbuf(const char * command,int mode)32cca88dd6Selan procbuf::procbuf(const char *command, int mode) : filebuf()
33cca88dd6Selan {
34cca88dd6Selan     open(command, mode);
35cca88dd6Selan }
36cca88dd6Selan 
open(const char * command,int mode)37cca88dd6Selan procbuf *procbuf::open(const char *command, int mode)
38cca88dd6Selan {
39cca88dd6Selan     int read_or_write;
40cca88dd6Selan     if (is_open())
41cca88dd6Selan 	return NULL;
42cca88dd6Selan     int pipe_fds[2];
43cca88dd6Selan     int parent_end, child_end;
44cca88dd6Selan     if (::pipe(pipe_fds) < 0)
45cca88dd6Selan 	return NULL;
46cca88dd6Selan     if (mode == ios::in) {
47cca88dd6Selan 	parent_end = pipe_fds[0];
48cca88dd6Selan 	child_end = pipe_fds[1];
49cca88dd6Selan 	read_or_write = _S_NO_WRITES;
50cca88dd6Selan     }
51cca88dd6Selan     else {
52cca88dd6Selan 	parent_end = pipe_fds[1];
53cca88dd6Selan 	child_end = pipe_fds[0];
54cca88dd6Selan 	read_or_write = _S_NO_READS;
55cca88dd6Selan     }
56cca88dd6Selan     _pid = FORK();
57cca88dd6Selan     if (_pid == 0) {
58cca88dd6Selan 	::close(parent_end);
59cca88dd6Selan 	int child_std_end = mode == ios::in ? 1 : 0;
60cca88dd6Selan 	if (child_end != child_std_end) {
61cca88dd6Selan 	    ::dup2(child_end, child_std_end);
62cca88dd6Selan 	    ::close(child_end);
63cca88dd6Selan 	}
64cca88dd6Selan 	::execl("/bin/sh", "sh", "-c", command, NULL);
65cca88dd6Selan 	::_exit(127);
66cca88dd6Selan     }
67cca88dd6Selan     ::close(child_end);
68cca88dd6Selan     if (_pid < 0) {
69cca88dd6Selan 	::close(parent_end);
70cca88dd6Selan 	return NULL;
71cca88dd6Selan     }
72cca88dd6Selan     _fb._fileno = parent_end;
73cca88dd6Selan     xsetflags(read_or_write, _S_NO_READS|_S_NO_WRITES);
74cca88dd6Selan     return this;
75cca88dd6Selan }
76cca88dd6Selan 
77cca88dd6Selan /* #define USE_SIGMASK */
78cca88dd6Selan 
sys_close()79cca88dd6Selan int procbuf::sys_close()
80cca88dd6Selan {
81cca88dd6Selan     _G_pid_t wait_pid;
82cca88dd6Selan     int status = filebuf::sys_close();
83cca88dd6Selan     if (status < 0)
84cca88dd6Selan 	return status;
85cca88dd6Selan     int wstatus;
86cca88dd6Selan #if defined(SIG_BLOCK) && defined(SIG_SETMASK)
87cca88dd6Selan     sigset_t set, oset;
88cca88dd6Selan     sigemptyset (&set);
89cca88dd6Selan     sigaddset (&set, SIGINT);
90cca88dd6Selan     sigaddset (&set, SIGQUIT);
91cca88dd6Selan     sigaddset (&set, SIGHUP);
92cca88dd6Selan     sigprocmask (SIG_BLOCK, &set, &oset);
93cca88dd6Selan #else
94cca88dd6Selan #ifdef USE_SIGMASK
95cca88dd6Selan     int mask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGHUP));
96cca88dd6Selan #else
97cca88dd6Selan     typedef void (*void_func)(int);
98cca88dd6Selan     void_func intsave = (void_func)signal(SIGINT, SIG_IGN);
99cca88dd6Selan     void_func quitsave = (void_func)signal(SIGQUIT, SIG_IGN);
100cca88dd6Selan     void_func hupsave = (void_func)signal(SIGHUP, SIG_IGN);
101cca88dd6Selan #endif
102cca88dd6Selan #endif
103cca88dd6Selan     while ((wait_pid = wait(&wstatus)) != _pid && wait_pid != -1) { }
104cca88dd6Selan #if defined(SIG_BLOCK) && defined(SIG_SETMASK)
105cca88dd6Selan     sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
106cca88dd6Selan #else
107cca88dd6Selan #ifdef USE_SIGMASK
108cca88dd6Selan     (void) sigsetmask(mask);
109cca88dd6Selan #else
110cca88dd6Selan     signal(SIGINT, intsave);
111cca88dd6Selan     signal(SIGQUIT, quitsave);
112cca88dd6Selan     signal(SIGHUP, hupsave);
113cca88dd6Selan #endif
114cca88dd6Selan #endif
115cca88dd6Selan     if (wait_pid == -1)
116cca88dd6Selan 	return -1;
117cca88dd6Selan     return 0;
118cca88dd6Selan }
119cca88dd6Selan 
~procbuf()120cca88dd6Selan procbuf::~procbuf()
121cca88dd6Selan {
122cca88dd6Selan     close();
123cca88dd6Selan }
124