libassa  3.5.1
Pipe.cpp
Go to the documentation of this file.
1 // -*- c++ -*-
2 //------------------------------------------------------------------------------
3 // $Id: Pipe.cpp,v 1.5 2006/07/20 02:30:54 vlg Exp $
4 //------------------------------------------------------------------------------
5 // Pipe.cpp
6 //------------------------------------------------------------------------------
7 // Copyright (c) 1997-2002,2005 by Vladislav Grinchenko
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Library General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
13 //------------------------------------------------------------------------------
14 //
15 // Pipe class is based on ./unixsysdevel-734/homework3/src/bin/pipe/pipe.c
16 // code I wrote for UNIX system development class of JohnsHopking
17 // part time engineering school in November 1997.
18 // The class implementation is a rip off of Stevens' popen ()/ pclose()
19 // function, p. 438.
20 //
21 //------------------------------------------------------------------------------
22 
23 #include <errno.h>
24 #include <sys/types.h> // kill (2)
25 #include <signal.h> // kill (2)
26 #include <unistd.h> // pipe (2)
27 
28 #include "assa/Pipe.h"
29 #include "assa/Fork.h"
30 
31 using namespace ASSA;
32 
34 Pipe ()
35  : m_fp (NULL),
36  m_child_pid (0)
37  {
38  trace_with_mask("Pipe::Pipe", PIPE);
39  /* no-op */
40 }
41 
43 ~Pipe ()
44 {
45  trace_with_mask("Pipe::~Pipe", PIPE);
46  close ();
47 }
48 
49 FILE*
51 open (const string& cmd_, const string& type_)
52 {
53  trace_with_mask("Pipe::open", PIPE);
54 
55 #if !defined(WIN32) // not yet implemented
56 
57  if (type_ != "r" && type_ != "w") {
58  EL((ASSAERR,"Wrong type \"%s\"\n", type_.c_str ()));
59  errno = EINVAL;
60  return NULL;
61  }
62 
63  int fd [2];
64  if (pipe (fd) < 0) {
65  EL((ASSAERR,"failed: pipe(2)\n"));
66  return NULL;
67  }
69 
70  if (f.isChild ()) {
71  if (type_ == "r") {
72  ::close (fd [0]);
73  if (fd [1] != STDOUT_FILENO) {
74  dup2 (fd [1], STDOUT_FILENO);
75  ::close (fd [1]);
76  }
77  }
78  else { // 'w'
79  ::close (fd [1]);
80  if (fd [0] != STDIN_FILENO) {
81  dup2 (fd [0], STDIN_FILENO);
82  ::close (fd [0]);
83  }
84  }
85 
86  DL((PIPE,"Executing cmd: \"%s\"\n", cmd_.c_str ()));
87  execl ("/bin/sh", "sh", "-c", cmd_.c_str (), (char* ) 0);
88  EL((ASSAERR,"failed: execl(2)\n"));
89  _exit (127);
90  }
91  /* parent */
92  if (type_ == "r") {
93  ::close (fd [1]);
94  if ((m_fp = fdopen (fd [0], type_.c_str ())) == NULL) {
95  EL((ASSAERR,"failed: fdopen ()\n"));
96  return NULL;
97  }
98  }
99  else { // 'w'
100  ::close (fd [0]);
101  if ((m_fp = fdopen (fd [1], type_.c_str ())) == NULL) {
102  EL((ASSAERR,"failed: fdopen ()\n"));
103  return NULL;
104  }
105  }
106  m_child_pid = f.getChildPID ();
107  DL((PIPE,"m_child_pid = %d\n",m_child_pid));
108  return m_fp;
109 
110 #else
111  DL((ASSAERR|PIPE,"Not implemented for win32!\n"));
112  return NULL;
113 #endif
114 }
115 
116 int
118 kill ()
119 {
120  trace_with_mask("Pipe::kill", PIPE);
121 
122 #if !defined(WIN32)
123  if (m_child_pid == 0) return -1;
124 
125  int ret = ::kill (m_child_pid, SIGTERM);
126  close ();
127  return ret;
128 #else
129  DL((ASSAERR|PIPE,"Not implemented for win32!\n"));
130  return -1;
131 #endif
132 }
133 
134 int
136 close ()
137 {
138  trace_with_mask("Pipe::close", PIPE);
139 
140  int ret = 0;
141  if (m_child_pid == 0) {
142  ret = EOF;
143  }
144 
145  if (m_fp) {
146  ret = fclose (m_fp);
147  }
148  m_fp = NULL;
149  m_child_pid = 0;
150  return ret == EOF ? -1 : 0;
151 }
152 
153 
154 
A simple wrapper around fork() library function call.
#define EL(X)
A macro for writing error message to the Logger.
Definition: Logger.h:285
#define DL(X)
A macro for writing debug message to the Logger.
Definition: Logger.h:273
#define trace_with_mask(s, m)
trace_with_mask() is used to trace function call chain in C++ program.
Definition: Logger.h:437
A wrapper around UNIX popen()/pclose() standard library calls.
Fork class is a simple wrapper around C library function fork().
Definition: Fork.h:86
@ KILL_ON_EXIT
Kill all childer on exit.
Definition: Fork.h:92
bool isChild() const
Test whether we are in child section of the code.
Definition: Fork.h:136
@ IGNORE_STATUS
Don't wait for child to complete.
Definition: Fork.h:100
pid_t getChildPID() const
Retrieve child process id.
Definition: Fork.h:142
pid_t m_child_pid
Supbrocess' PID.
Definition: Pipe.h:98
int fd() const
Get pipe's file descriptor.
Definition: Pipe.h:105
Pipe()
A no-op constructor.
Definition: Pipe.cpp:34
FILE * open(const string &cmd_, const string &type_)
Starts a subshell and feed it the string cmd_ to be executed.
Definition: Pipe.cpp:51
FILE * m_fp
A standard I/O stream descriptor.
Definition: Pipe.h:93
int kill()
Kill subprocess with SIGTERM.
Definition: Pipe.cpp:118
~Pipe()
Destructor calls close () first in an attempt to close opened pipe.
Definition: Pipe.cpp:43
int close()
Close the pipe.
Definition: Pipe.cpp:136
Definition: Acceptor.h:40
@ PIPE
Class Pipe messages
Definition: LogMask.h:49
@ ASSAERR
ASSA and system errors
Definition: LogMask.h:34