4 * Sub-process with communications using pipe I/O channel class.
6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
30 * Revision 1.22 2003/09/17 05:41:59 csoutheren
31 * Removed recursive includes
33 * Revision 1.21 2003/09/17 01:18:02 csoutheren
34 * Removed recursive include file system and removed all references
35 * to deprecated coooperative threading support
37 * Revision 1.20 2002/09/16 01:08:59 robertj
38 * Added #define so can select if #pragma interface/implementation is used on
39 * platform basis (eg MacOS) rather than compiler, thanks Robert Monaghan.
41 * Revision 1.19 2001/05/22 12:49:32 robertj
42 * Did some seriously wierd rewrite of platform headers to eliminate the
43 * stupid GNU compiler warning about braces not matching.
45 * Revision 1.18 1999/03/09 02:59:50 robertj
46 * Changed comments to doc++ compatible documentation.
48 * Revision 1.17 1999/02/16 08:11:09 robertj
49 * MSVC 6.0 compatibility changes.
51 * Revision 1.16 1998/11/02 10:06:39 robertj
52 * Added capability of pip output to go to stdout/stderr.
54 * Revision 1.15 1998/10/30 10:42:29 robertj
55 * Better function arrangement for multi platforming.
57 * Revision 1.14 1998/10/29 11:29:17 robertj
58 * Added ability to set environment in sub-process.
60 * Revision 1.13 1998/10/26 09:11:05 robertj
61 * Added ability to separate out stdout from stderr on pipe channels.
63 * Revision 1.12 1998/09/23 06:21:08 robertj
64 * Added open source copyright license.
66 * Revision 1.11 1997/01/03 05:25:05 robertj
67 * Added Wait and Kill functions.
69 * Revision 1.10 1996/03/31 08:50:51 robertj
70 * Changed string list to array.
71 * Added function to idicate if sub-process is running.
73 * Revision 1.9 1995/07/31 12:15:45 robertj
74 * Removed PContainer from PChannel ancestor.
76 * Revision 1.8 1995/06/17 11:12:53 robertj
77 * Documentation update.
79 * Revision 1.7 1995/03/14 12:42:02 robertj
80 * Updated documentation to use HTML codes.
82 * Revision 1.6 1995/01/09 12:39:01 robertj
85 * Revision 1.5 1994/10/23 04:50:55 robertj
86 * Further refinement of semantics after implementation.
88 * Revision 1.4 1994/09/25 10:43:19 robertj
89 * Added more implementation.
91 * Revision 1.3 1994/08/23 11:32:52 robertj
94 * Revision 1.2 1994/08/22 00:46:48 robertj
95 * Added pragma fro GNU C++ compiler.
97 * Revision 1.1 1994/04/20 12:17:44 robertj
102 #ifndef _PPIPECHANNEL
103 #define _PPIPECHANNEL
110 /**A channel that uses a operating system pipe between the current process and
111 a sub-process. On platforms that support {\it multi-processing}, the
112 sub-program is executed concurrently with the calling process.
114 Where full multi-processing is not supported then the sub-program is run
115 with its input supplied from, or output captured to, a disk file. The
116 current process is then suspended during the execution of the sub-program.
117 In the latter case the semantics of the #Execute()# and #Close()#
118 functions change from the usual for channels.
120 Note that for platforms that do not support multi-processing, the current
121 process is suspended until the sub-program terminates. The input and output
122 of the sub-program is transferred via a temporary file. The exact moment of
123 execution of the sub-program depends on the mode. If mode is
124 #ReadOnly# then it is executed immediately and its output
125 captured. In #WriteOnly# mode the sub-program is run when the
126 #Close()# function is called, or when the pipe channel is destroyed.
127 In #ReadWrite# mode the sub-program is run when the
128 #Execute()# function is called indicating that the output from the
129 current process to the sub-program has completed and input is now desired.
131 The #CanReadAndWrite()# function effectively determines whether full
132 multi-processing is supported by the platform. Note that this is different
133 to whether {\it multi-threading} is supported.
135 class PPipeChannel
: public PChannel
137 PCLASSINFO(PPipeChannel
, PChannel
);
140 /**@name Construction */
142 /// Channel mode for the pipe to the sub-process.
144 /// Pipe is only from the sub-process to the current process.
146 /// Pipe is only from the current process to the sub-process.
148 /// Pipe is bidirectional between current and sub-processes.
150 /**Pipe is bidirectional between current and sub-processes but the write
151 side goes to stdout and stderr */
155 /**Create a new pipe channel.
158 /**Create a new pipe channel.
159 This executes the subProgram and transfers data from its stdin/stdout/stderr.
161 See the #Open()# function for details of various parameters.
164 const PString
& subProgram
, /// Sub program name or command line.
165 OpenMode mode
= ReadWrite
, /// Mode for the pipe channel.
166 BOOL searchPath
= TRUE
, /// Flag for system PATH to be searched.
167 BOOL stderrSeparate
= FALSE
/// Standard error is on separate pipe
169 /**Create a new pipe channel.
170 This executes the subProgram and transfers data from its stdin/stdout/stderr.
172 See the #Open()# function for details of various parameters.
175 const PString
& subProgram
, /// Sub program name or command line.
176 const PStringArray
& argumentList
, /// Array of arguments to sub-program.
177 OpenMode mode
= ReadWrite
, /// Mode for the pipe channel.
178 BOOL searchPath
= TRUE
, /// Flag for system PATH to be searched.
179 BOOL stderrSeparate
= FALSE
/// Standard error is on separate pipe
181 /**Create a new pipe channel.
182 This executes the subProgram and transfers data from its stdin/stdout/stderr.
184 See the #Open()# function for details of various parameters.
187 const PString
& subProgram
, /// Sub program name or command line.
188 const PStringToString
& environment
, /// Array of arguments to sub-program.
189 OpenMode mode
= ReadWrite
, /// Mode for the pipe channel.
190 BOOL searchPath
= TRUE
, /// Flag for system PATH to be searched.
191 BOOL stderrSeparate
= FALSE
/// Standard error is on separate pipe
193 /**Create a new pipe channel.
194 This executes the subProgram and transfers data from its stdin/stdout/stderr.
196 See the #Open()# function for details of various parameters.
199 const PString
& subProgram
, /// Sub program name or command line.
200 const PStringArray
& argumentList
, /// Array of arguments to sub-program.
201 const PStringToString
& environment
, /// Array of arguments to sub-program.
202 OpenMode mode
= ReadWrite
, /// Mode for the pipe channel.
203 BOOL searchPath
= TRUE
, /// Flag for system PATH to be searched.
204 BOOL stderrSeparate
= FALSE
/// Standard error is on separate pipe
207 /// Close the pipe channel, killing the sub-process.
211 /**@name Overrides from class PObject */
213 /**Determine if the two objects refer to the same pipe channel. This
214 actually compares the sub-program names that are passed into the
218 Comparison value of the sub-program strings.
221 const PObject
& obj
/// Another pipe channel to compare against.
226 /**@name Overrides from class PChannel */
228 /**Get the name of the channel.
231 string for the sub-program that is run.
233 virtual PString
GetName() const;
235 /**Low level read from the channel. This function may block until the
236 requested number of characters were read or the read timeout was
237 reached. The GetLastReadCount() function returns the actual number
240 If there are no more characters available as the sub-program has
241 stopped then the number of characters available is returned. This is
242 similar to end of file for the PFile channel.
244 The GetErrorCode() function should be consulted after Read() returns
245 FALSE to determine what caused the failure.
248 TRUE indicates that at least one character was read from the channel.
249 FALSE means no bytes were read due to timeout or some other I/O error.
252 void * buf
, /// Pointer to a block of memory to receive the read bytes.
253 PINDEX len
/// Maximum number of bytes to read into the buffer.
256 /**Low level write to the channel. This function will block until the
257 requested number of characters are written or the write timeout is
258 reached. The GetLastWriteCount() function returns the actual number
261 If the sub-program has completed its run then this function will fail
264 The GetErrorCode() function should be consulted after Write() returns
265 FALSE to determine what caused the failure.
268 TRUE if at least len bytes were written to the channel.
271 const void * buf
, /// Pointer to a block of memory to write.
272 PINDEX len
/// Number of bytes to write.
275 /**Close the channel. This will kill the sub-program's process (on
276 platforms where that is relevent).
278 For #WriteOnly# or #ReadWrite# mode pipe channels
279 on platforms that do no support concurrent multi-processing and have
280 not yet called the #Execute()# function this will run the
283 virtual BOOL
Close();
286 /**@name New member functions */
288 /** Open a channel. */
290 const PString
& subProgram
, /// Sub program name or command line.
291 OpenMode mode
= ReadWrite
, /// Mode for the pipe channel.
292 BOOL searchPath
= TRUE
, /// Flag for system PATH to be searched.
293 BOOL stderrSeparate
= FALSE
/// Standard error is on separate pipe
295 /** Open a channel. */
297 const PString
& subProgram
, /// Sub program name or command line.
298 const PStringArray
& argumentList
, /// Array of arguments to sub-program.
299 OpenMode mode
= ReadWrite
, /// Mode for the pipe channel.
300 BOOL searchPath
= TRUE
, /// Flag for system PATH to be searched.
301 BOOL stderrSeparate
= FALSE
/// Standard error is on separate pipe
303 /** Open a channel. */
305 const PString
& subProgram
, /// Sub program name or command line.
306 const PStringToString
& environment
, /// Array of arguments to sub-program.
307 OpenMode mode
= ReadWrite
, /// Mode for the pipe channel.
308 BOOL searchPath
= TRUE
, /// Flag for system PATH to be searched.
309 BOOL stderrSeparate
= FALSE
/// Standard error is on separate pipe
311 /**Open a new pipe channel allowing the subProgram to be executed and
312 data transferred from its stdin/stdout/stderr.
314 If the mode is #ReadOnly# then the #stdout# of the
315 sub-program is supplied via the #Read()# calls of the PPipeChannel.
316 The sub-programs input is set to the platforms null device (eg
319 If mode is #WriteOnly# then #Write()# calls of the
320 PPipeChannel are suppied to the sub-programs #stdin# and its
321 #stdout# is sent to the null device.
323 If mode is #ReadWrite# then both read and write actions can
326 The #subProgram# parameter may contain just the path of the
327 program to be run or a program name and space separated arguments,
328 similar to that provided to the platforms command processing shell.
329 Which use of this parameter is determiend by whether arguments are
330 passed via the #argumentPointers# or
331 #argumentList# parameters.
333 The #searchPath# parameter indicates that the system PATH
334 for executables should be searched for the sub-program. If FALSE then
335 only the explicit or implicit path contained in the
336 #subProgram# parameter is searched for the executable.
338 The #stderrSeparate# parameter indicates that the standard
339 error stream is not included in line with the standard output stream.
340 In this case, data in this stream must be read using the
341 #ReadStandardError()# function.
343 The #environment# parameter is a null terminated sequence
344 of null terminated strings of the form name=value. If NULL is passed
345 then the same invironment as calling process uses is passed to the
349 const PString
& subProgram
, /// Sub program name or command line.
350 const PStringArray
& argumentList
, /// Array of arguments to sub-program.
351 const PStringToString
& environment
, /// Array of arguments to sub-program.
352 OpenMode mode
= ReadWrite
, /// Mode for the pipe channel.
353 BOOL searchPath
= TRUE
, /// Flag for system PATH to be searched.
354 BOOL stderrSeparate
= FALSE
/// Standard error is on separate pipe
357 /**Get the full file path for the sub-programs executable file.
360 file path name for sub-program.
362 const PFilePath
& GetSubProgram() const;
364 /**Start execution of sub-program for platforms that do not support
365 multi-processing, this will actually run the sub-program passing all
366 data written to the PPipeChannel.
368 For platforms that do support concurrent multi-processing this will
369 close the pipe from the current process to the sub-process.
371 As the sub-program is run immediately and concurrently, this will just
372 give an end of file to the stdin of the remote process. This is often
375 @return TRUE if execute was successful.
379 /**Determine if the program associated with the PPipeChannel is still
380 executing. This is useful for determining the status of PPipeChannels
381 which take a long time to execute on operating systems which support
382 concurrent multi-processing.
385 TRUE if the program associated with the PPipeChannel is still running
387 BOOL
IsRunning() const;
389 /**Get the return code from the most recent Close;
392 Return code from the closing process
394 int GetReturnCode() const;
396 /**This function will block and wait for the sub-program to terminate.
399 Return code from the closing process
401 int WaitForTermination();
403 /**This function will block and wait for the sub-program to terminate.
404 It will wait only for the specified amount of time.
407 Return code from the closing process, -1 if timed out.
409 int WaitForTermination(
410 const PTimeInterval
& timeout
/// Amount of time to wait for process.
413 /**This function will terminate the sub-program using the signal code
417 TRUE if the process received the signal. Note that this does not mean
418 that the process has actually terminated.
421 int signal
= 9 /// Signal code to be sent to process.
424 /**Read all available data on the standard error stream of the
425 sub-process. If the #wait# parameter is FALSE then only
426 the text currently available is returned. If TRUE then the function
427 blocks as long as necessary to get some number of bytes.
430 TRUE indicates that at least one character was read from stderr.
431 FALSE means no bytes were read due to timeout or some other I/O error.
433 BOOL
ReadStandardError(
434 PString
& errors
, /// String to receive standard error text.
435 BOOL wait
= FALSE
/// Flag to indicate if function should block
438 /**Determine if the platform can support simultaneous read and writes from
439 the PPipeChannel (eg MSDOS returns FALSE, Unix returns TRUE).
442 TRUE if platform supports concurrent multi-processing.
444 static BOOL
CanReadAndWrite();
450 /// The fully qualified path name for the sub-program executable.
451 PFilePath subProgName
;
455 BOOL
PlatformOpen(const PString
& subProgram
,
456 const PStringArray
& arguments
,
460 const PStringToString
* environment
);
463 // Include platform dependent part of class
465 #include "msos/ptlib/pipechan.h"
467 #include "unix/ptlib/pipechan.h"
473 // End Of File ///////////////////////////////////////////////////////////////