// pipestream.cpp -*- C++ -*- socket library
// Copyright (C) 2002 Herbert Straub
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// pipestream.C -*- C++ -*- socket library
// Copyright (C) 1992-1996 Gnanasekaran Swaminathan <gs4t@virginia.edu>
//
// Permission is granted to use at your own risk and distribute this software
// in source and binary forms provided the above copyright notice and this
// paragraph are preserved on all copies. This software is provided "as is"
// with no express or implied warranty.
//
// Version: 12Jan97 1.11
// 2002-07-28 Version 1.2 (C) Herbert Straub
// Eliminating sorry_about_global_temp inititialisation. This don't work
// in combination with NewsCache. My idea is: initializing the classes with (0)
// and in the second step call ios::init (sockbuf *) and iosockstream::init ...
// The constructors of ipipestream, opipestream and iopipestream are changed.
using namespace std;
#include <config.h>
#include <pipestream.h>
#include <unistd.h>
#include <sys/socket.h>
// environ is not given a declaration in sun's <unistd.h>
extern char** environ;
// child closes s2 and uses s1
// parent closes s1 and uses s2
enum domain { af_unix = 1 };
iopipestream* iopipestream::head = 0;
static sockbuf* createpipestream (const char* cmd, int mode)
{
int sockets[2];
if (::socketpair (af_unix, sockbuf::sock_stream, 0, sockets) == -1)
throw sockerr (errno);
pid_t pid = ::vfork ();
if (pid == -1) throw sockerr (errno);
if (pid == 0) {
// child process
if (::close (sockets[1]) == -1) throw sockerr (errno);
if ((mode & ios::in) && ::dup2 (sockets[0], 1) == -1)
throw sockerr (errno);
if ((mode & ios::out) && ::dup2 (sockets[0], 0) == -1)
throw sockerr (errno);
if (::close (sockets[0]) == -1) throw sockerr (errno);
const char* argv[4];
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = cmd;
argv[3] = 0;
execve ("/bin/sh", (char**) argv, environ);
throw sockerr (errno);
}
// parent process
if (::close (sockets[0]) == -1) throw sockerr (errno);
sockbuf* s = new sockbuf (sockbuf::sockdesc(sockets[1]));
if (!(mode & ios::out)) s->shutdown (sockbuf::shut_write);
if (!(mode & ios::in)) s->shutdown (sockbuf::shut_read);
return s;
}
ipipestream::ipipestream (const char* cmd)
: ios (0), isockstream(0)
{
sockbuf *t = createpipestream (cmd, ios::in);
ios::init (t);
isockstream::init (t);
}
opipestream::opipestream (const char* cmd)
: ios (0), osockstream(0)
{
sockbuf *t = createpipestream (cmd, ios::out);
ios::init (t);
osockstream::init (t);
}
iopipestream::iopipestream (const char* cmd)
: ios (0), iosockstream(0),
cpid (-1), next (0)
{
sockbuf *t = createpipestream (cmd, ios::in|ios::out);
ios::init (t);
iosockstream::init (t);
}
iopipestream::iopipestream(sockbuf::type ty, int proto)
: ios (0), iosockstream(NULL), cpid (-1), next (head) // probably NULL is not a good idea //LN
{
if (::socketpair(af_unix, ty, proto, sp) == -1)
throw sockerr (errno);
head = this;
}
pid_t iopipestream::fork ()
{
pid_t pid = ::fork (); // donot use vfork here
if (pid == -1) throw sockerr (errno);
if (pid > 0) {
// parent process
while (head) {
if (::close (head->sp[1]) == -1) throw sockerr (errno);
head->cpid = pid;
head->init (new sockbuf (sockbuf::sockdesc(head->sp[0])));
head = head->next;
}
} else {
// child process
while (head) {
if (::close (head->sp[0]) == -1) throw sockerr (errno);
head->cpid = 0;
head->init (new sockbuf (sockbuf::sockdesc(head->sp[1])));
head = head->next;
}
}
return pid;
}
syntax highlighted by Code2HTML, v. 0.9.1