1 |
/*******************************************************************\ |
2 |
|
3 |
Copyright (C) 2004 Joseph Coffland |
4 |
|
5 |
This program is free software; you can redistribute it and/or |
6 |
modify it under the terms of the GNU General Public License |
7 |
as published by the Free Software Foundation; either version 2 |
8 |
of the License, or (at your option) any later version. |
9 |
|
10 |
This program is distributed in the hope that it will be useful, |
11 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 |
GNU General Public License for more details. |
14 |
|
15 |
You should have received a copy of the GNU General Public License |
16 |
along with this program; if not, write to the Free Software |
17 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
18 |
02111-1307, USA. |
19 |
|
20 |
For information regarding this software email |
21 |
jcofflan@users.sourceforge.net |
22 |
|
23 |
\*******************************************************************/ |
24 |
|
25 |
#include "debug/Pipe.hpp" |
26 |
|
27 |
#include "utils/Exception.hpp" |
28 |
#include "utils/Zap.hpp" |
29 |
|
30 |
#include <stdio.h> |
31 |
#include <unistd.h> |
32 |
#include <ext/stdio_filebuf.h> // NOTE: This only works in GCC 3.2 and newer |
33 |
|
34 |
using namespace std; |
35 |
using namespace OpenMD; |
36 |
|
37 |
Pipe::Pipe() : |
38 |
outStream(0), inStream(0) { |
39 |
if (pipe(pipeFDs)) THROW("Error creating pipe!"); |
40 |
fdOpen[0] = fdOpen[1] = true; |
41 |
} |
42 |
|
43 |
Pipe::~Pipe() { |
44 |
if (fdOpen[0]) closeOut(); |
45 |
if (fdOpen[1]) closeIn(); |
46 |
|
47 |
zap(outStream); |
48 |
zap(inStream); |
49 |
} |
50 |
|
51 |
void Pipe::closeOut() { |
52 |
ASSERT_OR_THROW("Pipe output not open!", fdOpen[0]); |
53 |
close(pipeFDs[0]); |
54 |
fdOpen[0] = false; |
55 |
} |
56 |
|
57 |
void Pipe::closeIn() { |
58 |
ASSERT_OR_THROW("Pipe input not open!", fdOpen[1]); |
59 |
close(pipeFDs[1]); |
60 |
fdOpen[1] = false; |
61 |
} |
62 |
|
63 |
void Pipe::duplicateOutFD(int newFD) { |
64 |
if (dup2(pipeFDs[0], newFD) != newFD) |
65 |
THROW("Error duplicating file descriptor!"); |
66 |
} |
67 |
|
68 |
void Pipe::moveOutFD(int newFD) { |
69 |
duplicateOutFD(newFD); |
70 |
|
71 |
if (close(pipeFDs[0])) THROW("Error closing old file descriptor!"); |
72 |
|
73 |
pipeFDs[0] = newFD; |
74 |
} |
75 |
|
76 |
void Pipe::duplicateInFD(int newFD) { |
77 |
if (dup2(pipeFDs[1], newFD) != newFD) |
78 |
THROW("Error duplicating file descriptor!"); |
79 |
} |
80 |
|
81 |
void Pipe::moveInFD(int newFD) { |
82 |
duplicateInFD(newFD); |
83 |
|
84 |
if (close(pipeFDs[1])) THROW("Error closing old file descriptor!"); |
85 |
|
86 |
pipeFDs[1] = newFD; |
87 |
} |
88 |
|
89 |
istream *Pipe::getOutStream() { |
90 |
ASSERT_OR_THROW("Pipe output not open!", fdOpen[0]); |
91 |
|
92 |
if (!outStream) { |
93 |
// C file descriptor to C++ streams magic |
94 |
// NOTE: This only works in GCC 3.2 and newer |
95 |
// Hopefully they will leave the API alone now! |
96 |
__c_file *pipeFile = fdopen(pipeFDs[0], "r"); |
97 |
__gnu_cxx::stdio_filebuf<char> *pipeBuf = |
98 |
new __gnu_cxx::stdio_filebuf<char>(pipeFile, ios::in); |
99 |
|
100 |
// FIXME There are two leaks above. fdopen must be closed |
101 |
// and the stdio_filebuf must be freed. |
102 |
// Also in the getInStream() |
103 |
|
104 |
outStream = new istream(pipeBuf); |
105 |
} |
106 |
|
107 |
return outStream; |
108 |
} |
109 |
|
110 |
ostream *Pipe::getInStream() { |
111 |
ASSERT_OR_THROW("Pipe input not open!", fdOpen[1]); |
112 |
|
113 |
if (!inStream) { |
114 |
// C file descriptor to C++ streams magic |
115 |
// NOTE: This only works in GCC 3.2 and newer |
116 |
// Hopefully they will leave the API alone now! |
117 |
__c_file *pipeFile = fdopen(pipeFDs[1], "w"); |
118 |
__gnu_cxx::stdio_filebuf<char> *pipeBuf = |
119 |
new __gnu_cxx::stdio_filebuf<char>(pipeFile, ios::out); |
120 |
|
121 |
inStream = new ostream(pipeBuf); |
122 |
} |
123 |
|
124 |
return inStream; |
125 |
} |
126 |
|