// -*- c++ -*- //------------------------------------------------------------------------------ // $Id: Pipe.cpp,v 1.5 2006/07/20 02:30:54 vlg Exp $ //------------------------------------------------------------------------------ // Pipe.cpp //------------------------------------------------------------------------------ // Copyright (c) 1997-2002,2005 by Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------------ // // Pipe class is based on ./unixsysdevel-734/homework3/src/bin/pipe/pipe.c // code I wrote for UNIX system development class of JohnsHopking // part time engineering school in November 1997. // The class implementation is a rip off of Stevens' popen ()/ pclose() // function, p. 438. // //------------------------------------------------------------------------------ #include #include // kill (2) #include // kill (2) #include // pipe (2) #include "assa/Pipe.h" #include "assa/Fork.h" using namespace ASSA; Pipe:: Pipe () : m_fp (NULL), m_child_pid (0) { trace_with_mask("Pipe::Pipe", PIPE); /* no-op */ } Pipe:: ~Pipe () { trace_with_mask("Pipe::~Pipe", PIPE); close (); } FILE* Pipe:: open (const string& cmd_, const string& type_) { trace_with_mask("Pipe::open", PIPE); #if !defined(WIN32) // not yet implemented if (type_ != "r" && type_ != "w") { EL((ASSAERR,"Wrong type \"%s\"\n", type_.c_str ())); errno = EINVAL; return NULL; } int fd [2]; if (pipe (fd) < 0) { EL((ASSAERR,"failed: pipe(2)\n")); return NULL; } Fork f (Fork::KILL_ON_EXIT, Fork::IGNORE_STATUS); if (f.isChild ()) { if (type_ == "r") { ::close (fd [0]); if (fd [1] != STDOUT_FILENO) { dup2 (fd [1], STDOUT_FILENO); ::close (fd [1]); } } else { // 'w' ::close (fd [1]); if (fd [0] != STDIN_FILENO) { dup2 (fd [0], STDIN_FILENO); ::close (fd [0]); } } DL((PIPE,"Executing cmd: \"%s\"\n", cmd_.c_str ())); execl ("/bin/sh", "sh", "-c", cmd_.c_str (), (char* ) 0); EL((ASSAERR,"failed: execl(2)\n")); _exit (127); } /* parent */ if (type_ == "r") { ::close (fd [1]); if ((m_fp = fdopen (fd [0], type_.c_str ())) == NULL) { EL((ASSAERR,"failed: fdopen ()\n")); return NULL; } } else { // 'w' ::close (fd [0]); if ((m_fp = fdopen (fd [1], type_.c_str ())) == NULL) { EL((ASSAERR,"failed: fdopen ()\n")); return NULL; } } m_child_pid = f.getChildPID (); DL((PIPE,"m_child_pid = %d\n",m_child_pid)); return m_fp; #else DL((ASSAERR|PIPE,"Not implemented for win32!\n")); return NULL; #endif } int Pipe:: kill () { trace_with_mask("Pipe::kill", PIPE); #if !defined(WIN32) if (m_child_pid == 0) return -1; int ret = ::kill (m_child_pid, SIGTERM); close (); return ret; #else DL((ASSAERR|PIPE,"Not implemented for win32!\n")); return -1; #endif } int Pipe:: close () { trace_with_mask("Pipe::close", PIPE); int ret = 0; if (m_child_pid == 0) { ret = EOF; } if (m_fp) { ret = fclose (m_fp); } m_fp = NULL; m_child_pid = 0; return ret == EOF ? -1 : 0; }