home *** CD-ROM | disk | FTP | other *** search
- // This may look like C code, but it is really -*- C++ -*-
-
- // pipestream.C -*- C++ -*- socket library
- // Copyright (C) 1992,1993 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: 31Jan93 1.3
-
-
- #include <pipestream.h>
- #include <builtin.h>
-
- // child closes s2 and uses s1
- // parent closes s1 and uses s2
-
- extern "C" {
- int socketpair (int af, int type, int proto, int* sp);
-
- extern char** environ;
- }
-
- 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 ) {
- (*lib_error_handler) ("pipestream", "fork");
- return 0;
- }
-
- int pid = fork ();
- if (pid == -1) {
- (*lib_error_handler) ("pipestream", "vfork");
- return 0;
- }
-
- if (pid == 0) {
- // child process
- if (::close (sockets[1]) == -1)
- (*lib_error_handler) ("pipestream", "child close 1");
- if ((mode & ios::in) && ::dup2 (sockets[0], 1) == -1) {
- (*lib_error_handler) ("pipestream", "child dup2 1");
- _exit (0x70);
- }
- if ((mode & ios::out) && ::dup2 (sockets[0], 0) == -1) {
- (*lib_error_handler) ("pipestream", "child dup2 0");
- _exit (0x71);
- }
- if (::close (sockets[0]) == -1)
- (*lib_error_handler) ("pipestream", "child close 0");
- const char* argv[4];
- argv[0] = "/bin/sh";
- argv[1] = "-c";
- argv[2] = cmd;
- argv[3] = 0;
- execve ("/bin/sh", argv, environ);
- (*lib_error_handler) ("pipestream", "execve");
- _exit (0x7f);
- }
- // parent process
- sockbuf* s = new sockbuf (sockets[1]);
- if (::close (sockets[0]) == -1)
- (*lib_error_handler) ("pipestream", "parent close 0");
- 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, ostream* tied)
- : ios (0, tied)
- {
- init (createpipestream (cmd, ios::in));
- }
-
- opipestream::opipestream (const char* cmd, ostream* tied)
- : ios (0, tied)
- {
- init (createpipestream (cmd, ios::out));
- }
-
- iopipestream::iopipestream (const char* cmd, ostream* tied)
- : ios (0, tied), cpid (-1)
- {
- init (createpipestream (cmd, ios::in|ios::out));
- }
-
- iopipestream::iopipestream(sockbuf::type ty, int proto)
- : ios (0, 0), next (head), cpid (-1)
- {
- if ( ::socketpair(af_unix, ty, proto, sp) == -1 ) {
- error ("iopipestream-socketpair ");
- return;
- }
-
- head = this;
- }
-
- int iopipestream::fork()
- {
- int pid = ::fork();
- if ( pid == -1 ) {
- (*lib_error_handler) ("iopipestream", "fork");
- return pid;
- } else if (pid > 0) {
- // parent process
- while (head) {
- head->cpid = pid;
- head->init (new sockbuf (head->sp[0]));
- if (::close (head->sp[1]) == -1)
- (*lib_error_handler) ("iopipestream", "parent close 0");
- head = head->next;
- }
-
- } else {
- // child process
- while (head) {
- head->cpid = 0;
- head->init (new sockbuf (head->sp[1]));
- if (::close (head->sp[0]) == -1)
- (*lib_error_handler) ("iopipestream", "child close 0");
- head = head->next;
- }
- }
- return pid;
- }
-