home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 400_01 / socketpp-1.5 / pipestream.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-06  |  3.3 KB  |  133 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2.  
  3. // pipestream.C -*- C++ -*- socket library
  4. // Copyright (C) 1992,1993 Gnanasekaran Swaminathan <gs4t@virginia.edu>
  5. // 
  6. // Permission is granted to use at your own risk and distribute this software
  7. // in source and binary forms provided the above copyright
  8. // notice and this paragraph are preserved on all copies.
  9. // This software is provided "as is" with no express or implied warranty.
  10. //
  11. // Version: 31Jan93 1.3
  12.  
  13.  
  14. #include <pipestream.h>
  15. #include <builtin.h>
  16.  
  17. // child closes s2 and uses s1
  18. // parent closes s1 and uses s2
  19.  
  20. extern "C" {
  21.     int    socketpair    (int af, int type, int proto, int* sp);
  22.  
  23.     extern char** environ;
  24. }    
  25.  
  26. enum domain { af_unix = 1 };
  27.  
  28. iopipestream* iopipestream::head = 0;
  29.  
  30. static sockbuf* createpipestream (const char* cmd, int mode)
  31. {
  32.     int sockets[2];
  33.     if ( ::socketpair (af_unix, sockbuf::sock_stream, 0, sockets) == -1 ) {
  34.     (*lib_error_handler) ("pipestream", "fork");
  35.     return 0;
  36.     }
  37.  
  38.     int pid = fork ();
  39.     if (pid == -1) {
  40.     (*lib_error_handler) ("pipestream", "vfork");
  41.     return 0;
  42.     }
  43.  
  44.     if (pid == 0) {
  45.     // child process
  46.     if (::close (sockets[1]) == -1)
  47.         (*lib_error_handler) ("pipestream", "child close 1");
  48.     if ((mode & ios::in) && ::dup2 (sockets[0], 1) == -1) {
  49.         (*lib_error_handler) ("pipestream", "child dup2 1");
  50.         _exit (0x70);
  51.     }
  52.     if ((mode & ios::out) && ::dup2 (sockets[0], 0) == -1) {
  53.         (*lib_error_handler) ("pipestream", "child dup2 0");
  54.         _exit (0x71);
  55.     }
  56.     if (::close (sockets[0]) == -1)
  57.         (*lib_error_handler) ("pipestream", "child close 0");
  58.     const char*    argv[4];
  59.     argv[0] = "/bin/sh";
  60.     argv[1] = "-c";
  61.     argv[2] = cmd;
  62.     argv[3] = 0;
  63.     execve ("/bin/sh", argv, environ);
  64.     (*lib_error_handler) ("pipestream", "execve");
  65.     _exit (0x7f);
  66.     }
  67.     // parent process
  68.     sockbuf* s = new sockbuf (sockets[1]);
  69.     if (::close (sockets[0]) == -1)
  70.     (*lib_error_handler) ("pipestream", "parent close 0");
  71.     if ( !(mode & ios::out) ) s->shutdown (sockbuf::shut_write);
  72.     if ( !(mode & ios::in) ) s->shutdown (sockbuf::shut_read);
  73.     return s;
  74. }
  75.  
  76. ipipestream::ipipestream (const char* cmd, ostream* tied)
  77. : ios (0, tied)
  78. {
  79.     init (createpipestream (cmd, ios::in));
  80. }
  81.  
  82. opipestream::opipestream (const char* cmd, ostream* tied)
  83. : ios (0, tied)
  84. {
  85.     init (createpipestream (cmd, ios::out));
  86. }
  87.  
  88. iopipestream::iopipestream (const char* cmd, ostream* tied)
  89. : ios (0, tied), cpid (-1)
  90. {
  91.     init (createpipestream (cmd, ios::in|ios::out));
  92. }
  93.  
  94. iopipestream::iopipestream(sockbuf::type ty, int proto)
  95. : ios (0, 0), next (head), cpid (-1)
  96. {
  97.     if ( ::socketpair(af_unix, ty, proto, sp) == -1 ) {
  98.     error ("iopipestream-socketpair ");
  99.     return;
  100.     }
  101.  
  102.     head = this;    
  103. }
  104.  
  105. int    iopipestream::fork()
  106. {
  107.     int pid = ::fork();
  108.     if ( pid == -1 ) {
  109.     (*lib_error_handler) ("iopipestream", "fork");
  110.     return pid;
  111.     } else if (pid > 0) {
  112.     // parent process
  113.     while (head) {
  114.         head->cpid = pid;
  115.         head->init (new sockbuf (head->sp[0]));
  116.         if (::close (head->sp[1]) == -1)
  117.         (*lib_error_handler) ("iopipestream", "parent close 0");
  118.         head = head->next;
  119.     }
  120.     
  121.     } else {
  122.     // child process
  123.     while (head) {
  124.         head->cpid = 0;
  125.         head->init (new sockbuf (head->sp[1]));
  126.         if (::close (head->sp[0]) == -1)
  127.         (*lib_error_handler) ("iopipestream", "child close 0");
  128.         head = head->next;
  129.     }
  130.     }
  131.     return pid;
  132. }    
  133.