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