052b4c383a8983822bc8b2589ddad177d73a0bdd
[reactos.git] / reactos / tools / sysreg / namedpipe_reader.cpp
1 /* $Id: pipe_reader.cpp 24643 2006-10-24 11:45:21Z janderwald $
2 *
3 * PROJECT: System regression tool for ReactOS
4 * LICENSE: GPL - See COPYING in the top level directory
5 * FILE: tools/sysreg/namedpipe_reader.cpp
6 * PURPOSE: pipe reader support
7 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
8 * Christoph von Wittich (Christoph_vW@ReactOS.org)
9 */
10
11 #include "namedpipe_reader.h"
12
13 #include <iostream>
14 #include <cassert>
15 #include <cstring>
16
17 namespace System_
18 {
19 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
20
21 #ifdef __LINUX__
22 const char * NamedPipeReader::s_LineBreak = "\x0A\0";
23 #else
24 const char * NamedPipeReader::s_LineBreak = "\x0D\x0A\0";
25 #endif
26 using std::vector;
27 //---------------------------------------------------------------------------------------
28 NamedPipeReader::NamedPipeReader() : DataSource(), h_Pipe(NULLVAL), m_Buffer(0)
29 {
30 }
31
32 //---------------------------------------------------------------------------------------
33 NamedPipeReader::~NamedPipeReader()
34 {
35 if (m_Buffer)
36 free(m_Buffer);
37 }
38
39 bool NamedPipeReader::isSourceOpen()
40 {
41 return true;
42 }
43
44 //---------------------------------------------------------------------------------------
45
46 bool NamedPipeReader::openSource(const string & PipeCmd)
47 {
48 if (h_Pipe != NULLVAL)
49 {
50 cerr << "NamedPipeReader::openPipe> pipe already open" << endl;
51 return false;
52 }
53 #ifndef __LINUX__
54 h_Pipe = CreateFile(PipeCmd.c_str(),
55 GENERIC_WRITE | GENERIC_READ,
56 0,
57 NULL,
58 OPEN_EXISTING,
59 FILE_ATTRIBUTE_NORMAL,
60 (HANDLE)
61 NULL);
62
63 if(INVALID_HANDLE_VALUE == h_Pipe) {
64 cerr << "NamedPipeReader::openPipe> failed to open pipe " << PipeCmd << " Error:" << GetLastError() << endl;
65 h_Pipe = NULLVAL;
66 return false;
67 }
68 else
69 {
70 cout << "NamedPipeReader::openPipe> successfully opened pipe" << endl;
71
72 if (!m_Buffer)
73 {
74 m_BufferLength = 100;
75 m_Buffer = (char*)malloc(sizeof(char) * m_BufferLength);
76 }
77 ConnectNamedPipe(h_Pipe,
78 0);
79 return true;
80 }
81 #else
82 h_Pipe = open(PipeCmd.c_str(), O_RDONLY);
83
84 if(INVALID_HANDLE_VALUE == h_Pipe) {
85 cerr << "NamedPipeReader::openPipe> failed to open pipe " << PipeCmd << endl;
86 h_Pipe = NULLVAL;
87 return false;
88 }
89 else
90 {
91 cout << "NamedPipeReader::openPipe> successfully opened pipe handle: "<< h_Pipe << endl << "Src: " << PipeCmd << endl;
92 if (!m_Buffer)
93 {
94 m_BufferLength = 100;
95 m_Buffer = (char*)malloc(sizeof(char) * m_BufferLength);
96 }
97 return true;
98 }
99 #endif
100 }
101
102 //---------------------------------------------------------------------------------------
103
104 bool NamedPipeReader::closeSource()
105 {
106 cerr << "NamedPipeReader::closePipe> entered" << endl;
107 if (h_Pipe == NULLVAL)
108 {
109 cerr << "NamedPipeReader::closePipe> pipe is not open" << endl;
110 return false;
111 }
112 #ifdef __LINUX__
113 close(h_Pipe);
114 #else
115 DisconnectNamedPipe(h_Pipe);
116 CloseHandle(h_Pipe);
117 #endif
118 h_Pipe = NULLVAL;
119 return true;
120 }
121 //---------------------------------------------------------------------------------------
122 void NamedPipeReader::insertLine(std::vector<string> & vect, string line, bool append_line)
123 {
124 if (append_line && vect.size ())
125 {
126 string prev = vect[vect.size () - 1];
127 prev += line;
128 vect[vect.size () - 1] = prev;
129 }
130 else
131 {
132 vect.push_back (line);
133 }
134
135 }
136 //---------------------------------------------------------------------------------------
137 void NamedPipeReader::extractLines(char * buffer, std::vector<string> & vect, bool & append_line, unsigned long cbRead)
138 {
139 #if 0
140 long offset = 0;
141 size_t start_size = vect.size ();
142 char * start = buffer;
143 buffer[cbRead] = '\0';
144 char * end = strstr(buffer, s_LineBreak);
145
146 //cout << "extractLines entered with append_line: " << append_line << " cbRead: " << cbRead << "buffer: " << buffer << endl;
147
148 do
149 {
150 if (end)
151 {
152 end[0] = '\0';
153 string line = start;
154 end += (sizeof(s_LineBreak) / sizeof(char));
155 start = end;
156 offset += line.length() + (sizeof(s_LineBreak) / sizeof(char));
157
158 // cout << "Offset: "<< offset << "cbRead: " << cbRead << "line: " << line << endl;
159 insertLine(vect, line, append_line);
160 if (append_line)
161 {
162 append_line = false;
163 }
164 }
165 else
166 {
167 string line = start;
168 // cout << "inserting line start_size: " << start_size << "current: " << vect.size () << "line length: "<< line.length () << endl;
169 if (!line.length ())
170 {
171 if (start_size == vect.size ())
172 append_line = true;
173 break;
174 }
175 if (start_size == vect.size ())
176 {
177 insertLine(vect, line, true);
178 }
179 else
180 {
181 insertLine(vect, line, false);
182 }
183 append_line = true;
184 break;
185 }
186
187 end = strstr(end, s_LineBreak);
188
189 }while(append_line);
190
191 #else
192 DWORD buf_offset = 0;
193 char * offset = strchr(buffer, '\x0D');
194 while(offset)
195 {
196 ///
197 /// HACKHACK
198 /// due to some mysterious reason, strchr / strstr sometimes returns
199 /// not always the offset to the CR character but to the next LF
200 /// in MSVC 2005 (Debug Modus)
201
202 if (offset[0] == '\x0A')
203 {
204 if (buf_offset)
205 {
206 offset--;
207 }
208 else
209 {
210 //TODO
211 // implement me special case
212 }
213 }
214
215 if (offset[0] == '\x0D')
216 {
217 buf_offset += 2;
218 offset[0] = '\0';
219 offset +=2;
220 }
221 else
222 {
223 ///
224 /// BUG detected in parsing code
225 ///
226 abort();
227 }
228
229 string line = buffer;
230 if (append_line)
231 {
232 assert(vect.empty () == false);
233 string prev_line = vect[vect.size () -1];
234 prev_line += line;
235 vect.pop_back ();
236 vect.push_back (prev_line);
237 append_line = false;
238 }
239 else
240 {
241 vect.push_back (line);
242 }
243
244 buf_offset += line.length();
245 if (buf_offset >= cbRead)
246 {
247 break;
248 }
249 buffer = offset;
250
251 offset = strstr(buffer, "\n");
252 }
253 if (buf_offset < cbRead)
254 {
255 buffer[cbRead - buf_offset] = '\0';
256 string line = buffer;
257 if (append_line)
258 {
259 assert(vect.empty () == false);
260 string prev_line = vect[vect.size () -1];
261 vect.pop_back ();
262 prev_line += line;
263 vect.push_back (prev_line);
264 }
265 else
266 {
267 vect.push_back (line);
268 append_line = true;
269 }
270 }
271 else
272 {
273 append_line = false;
274 }
275 #endif
276 }
277 //---------------------------------------------------------------------------------------
278 bool NamedPipeReader::readPipe(char * buffer, int bufferlength, long & bytesread)
279 {
280
281 #ifdef __LINUX__
282 long cbRead = read(h_Pipe,
283 buffer,
284 (bufferlength-1) * sizeof(char));
285 #else
286 DWORD cbRead = 0;
287 BOOL fSuccess = ReadFile(h_Pipe,
288 buffer,
289 (bufferlength-1) * sizeof(char),
290 &cbRead,
291 NULL);
292
293 if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
294 return false;
295 #endif
296
297 bytesread = cbRead;
298 return true;
299 }
300 //---------------------------------------------------------------------------------------
301
302 bool NamedPipeReader::readSource(vector<string> & vect)
303 {
304 size_t lines = vect.size ();
305
306 if (h_Pipe == NULLVAL)
307 {
308 cerr << "Error: pipe is not open" << endl;
309 return false;
310 }
311
312 if (!m_Buffer)
313 {
314 cerr << "Error: no memory" << endl;
315 return false;
316 }
317
318 bool append_line = false;
319 do
320 {
321 memset(m_Buffer, 0x0, m_BufferLength * sizeof(char));
322 long cbRead = 0;
323
324 if (!readPipe(m_Buffer, m_BufferLength-1, cbRead))
325 break;
326
327 extractLines(m_Buffer, vect, append_line, cbRead);
328 }while (append_line);
329
330 return (vect.size () - lines);
331 }
332
333
334 } // end of namespace System_