158198Selan //    This is part of the iostream library, providing input/output for C++.
258198Selan //    Copyright (C) 1992 Per Bothner.
358198Selan //
458198Selan //    This library is free software; you can redistribute it and/or
558198Selan //    modify it under the terms of the GNU Library General Public
658198Selan //    License as published by the Free Software Foundation; either
758198Selan //    version 2 of the License, or (at your option) any later version.
858198Selan //
958198Selan //    This library is distributed in the hope that it will be useful,
1058198Selan //    but WITHOUT ANY WARRANTY; without even the implied warranty of
1158198Selan //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1258198Selan //    Library General Public License for more details.
1358198Selan //
1458198Selan //    You should have received a copy of the GNU Library General Public
1558198Selan //    License along with this library; if not, write to the Free
1658198Selan //    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1758198Selan 
18*60386Selan #ifdef notdef
1958198Selan #define _POSIX_SOURCE
20*60386Selan #endif
2158198Selan #include "ioprivate.h"
2258198Selan #include "procbuf.h"
2358198Selan #include <signal.h>
2458198Selan #include <unistd.h>
2558198Selan #include <sys/wait.h>
2658198Selan 
2758198Selan 
2858198Selan #ifndef FORK
2958198Selan #define FORK vfork
3058198Selan #endif
3158198Selan 
procbuf(const char * command,int mode)3258198Selan procbuf::procbuf(const char *command, int mode) : filebuf()
3358198Selan {
3458198Selan     open(command, mode);
3558198Selan }
3658198Selan 
open(const char * command,int mode)3758198Selan procbuf *procbuf::open(const char *command, int mode)
3858198Selan {
3958198Selan     int read_or_write;
4058198Selan     if (is_open())
4158198Selan 	return NULL;
4258198Selan     int pipe_fds[2];
4358198Selan     int parent_end, child_end;
4458198Selan     if (::pipe(pipe_fds) < 0)
4558198Selan 	return NULL;
4658198Selan     if (mode == ios::in) {
4758198Selan 	parent_end = pipe_fds[0];
4858198Selan 	child_end = pipe_fds[1];
4958198Selan 	read_or_write = _S_NO_WRITES;
5058198Selan     }
5158198Selan     else {
5258198Selan 	parent_end = pipe_fds[1];
5358198Selan 	child_end = pipe_fds[0];
5458198Selan 	read_or_write = _S_NO_READS;
5558198Selan     }
5658198Selan     _pid = FORK();
5758198Selan     if (_pid == 0) {
5858198Selan 	::close(parent_end);
5958198Selan 	int child_std_end = mode == ios::in ? 1 : 0;
6058198Selan 	if (child_end != child_std_end) {
6158198Selan 	    ::dup2(child_end, child_std_end);
6258198Selan 	    ::close(child_end);
6358198Selan 	}
6458198Selan 	::execl("/bin/sh", "sh", "-c", command, NULL);
6558198Selan 	::_exit(127);
6658198Selan     }
6758198Selan     ::close(child_end);
6858198Selan     if (_pid < 0) {
6958198Selan 	::close(parent_end);
7058198Selan 	return NULL;
7158198Selan     }
7258198Selan     _fb._fileno = parent_end;
7358198Selan     xsetflags(read_or_write, _S_NO_READS|_S_NO_WRITES);
7458198Selan     return this;
7558198Selan }
7658198Selan 
7758198Selan /* #define USE_SIGMASK */
7858198Selan 
sys_close()7958198Selan int procbuf::sys_close()
8058198Selan {
8158198Selan     _G_pid_t wait_pid;
8258198Selan     int status = filebuf::sys_close();
8358198Selan     if (status < 0)
8458198Selan 	return status;
8558198Selan     int wstatus;
8658198Selan #if defined(SIG_BLOCK) && defined(SIG_SETMASK)
8758198Selan     sigset_t set, oset;
8858198Selan     sigemptyset (&set);
8958198Selan     sigaddset (&set, SIGINT);
9058198Selan     sigaddset (&set, SIGQUIT);
9158198Selan     sigaddset (&set, SIGHUP);
9258198Selan     sigprocmask (SIG_BLOCK, &set, &oset);
9358198Selan #else
9458198Selan #ifdef USE_SIGMASK
9558198Selan     int mask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGHUP));
9658198Selan #else
9758198Selan     typedef void (*void_func)(int);
9858198Selan     void_func intsave = (void_func)signal(SIGINT, SIG_IGN);
9958198Selan     void_func quitsave = (void_func)signal(SIGQUIT, SIG_IGN);
10058198Selan     void_func hupsave = (void_func)signal(SIGHUP, SIG_IGN);
10158198Selan #endif
10258198Selan #endif
10358198Selan     while ((wait_pid = wait(&wstatus)) != _pid && wait_pid != -1) { }
10458198Selan #if defined(SIG_BLOCK) && defined(SIG_SETMASK)
10558198Selan     sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
10658198Selan #else
10758198Selan #ifdef USE_SIGMASK
10858198Selan     (void) sigsetmask(mask);
10958198Selan #else
11058198Selan     signal(SIGINT, intsave);
11158198Selan     signal(SIGQUIT, quitsave);
11258198Selan     signal(SIGHUP, hupsave);
11358198Selan #endif
11458198Selan #endif
11558198Selan     if (wait_pid == -1)
11658198Selan 	return -1;
11758198Selan     return 0;
11858198Selan }
11958198Selan 
~procbuf()12058198Selan procbuf::~procbuf()
12158198Selan {
12258198Selan     close();
12358198Selan }
124