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