1
-------------------------------------------------------------------------------
3
-- <STRONG>Copyright © 2001, 2002 by Thomas Wolf.</STRONG>
5
-- This piece of software is free software; you can redistribute it and/or
6
-- modify it under the terms of the GNU General Public License as published
7
-- by the Free Software Foundation; either version 2, or (at your option)
8
-- any later version. This software is distributed in the hope that it will
9
-- be useful, but <EM>without any warranty</EM>; without even the implied
10
-- warranty of <EM>merchantability or fitness for a particular purpose.</EM>
11
-- See the GNU General Public License for more details. You should have
12
-- received a copy of the GNU General Public License with this distribution,
13
-- see file "<A HREF="GPL.txt">GPL.txt</A>". If not, write to the Free
14
-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18
-- As a special exception from the GPL, if other files instantiate generics
19
-- from this unit, or you link this unit with other files to produce an
20
-- executable, this unit does not by itself cause the resulting executable
21
-- to be covered by the GPL. This exception does not however invalidate any
22
-- other reasons why the executable file might be covered by the GPL.
26
-- Thomas Wolf (TW) <E_MAIL>
30
-- This is a thick binding to the @popen@ and @pclose@ routines available
31
-- on both Unix and Win32. It gives a convenient way to execute an external
32
-- program and pass it some input, or read its output.
36
-- Neither task- not abortion-safe. All operations here should be
37
-- considered <EM>potentially blocking</EM>.
43
-- 26-APR-2002 TW Initial version.
44
-- 29-APR-2002 TW Added auto-close feature.
46
-------------------------------------------------------------------------------
48
pragma License (Modified_GPL);
50
with Ada.Finalization;
51
with Ada.IO_Exceptions;
54
with Interfaces.C.Strings;
58
type Stream_Mode is (In_Stream, Out_Stream);
59
-- Used in @Open@ to specify the type of the stream.
61
type Pipe_Stream is new Ada.Streams.Root_Stream_Type with private;
62
-- I have found no indication whatsoever about the type of the underlying
63
-- C stream (binary or text mode?). Although you <EM>can</EM> write and
64
-- read binary data to and from a @Pipe_Stream@, it's probably prudent to
65
-- consider these streams as <EM>text-only</EM>, because they set up pipes
66
-- to or from an external processes stdin or stdout handles, which are
67
-- defined by the ISO C standard as text streams.
69
Name_Error : exception renames Ada.IO_Exceptions.Name_Error;
70
-- Raised by @Open@ if the command cannot be executed.
72
Use_Error : exception renames Ada.IO_Exceptions.Use_Error;
73
-- Raised by any stream operation if the stream is not open (and by @Open@,
74
-- if it already is open).
76
Mode_Error : exception renames Ada.IO_Exceptions.Mode_Error;
77
-- Stream operations on the returned stream may raise @Mode_Error@ if
78
-- writing on an @In_Stream@ or reading from an @Out_Stream@ is attempted.
80
End_Error : exception renames Ada.IO_Exceptions.End_Error;
81
-- Stream operations on an @In_Stream@ will raise @End_Error@ if EOF is
84
Device_Error : exception renames Ada.IO_Exceptions.Device_Error;
85
-- Raised by the @Put@ or @Get@ operations (and also by @Write@ and
86
-- @Read@) if the underlying system operations indicate any reading or
90
(Stream : in out Pipe_Stream;
92
Mode : in Stream_Mode;
93
Close : in Boolean := True;
94
Std_In : in String := "");
95
-- Executes @Command@, which may contain arguments, setting it up such that
96
-- the executed command's stdin comes from the returned stream if @Mode@
97
-- is @Out_Stream@, or the command's stdout can be read from that stream
98
-- if @Mode@ is @In_Stream@. Note that "in" and "out" are from the caller's
101
-- If <CODE>Close = True</CODE>, the stream is closed automatically when
102
-- the stream object disappears. Note that this may involve waiting until
103
-- the external command terminates. @Out_Stream@s always are closed
106
-- Raises @Name_Error@ if the @Command@ cannot be executed, or @Use_Error@
107
-- if the stream is already open.
109
-- Note that an <EM>output filter</EM> is created using a stream of mode
110
-- @Out_Stream@. The external process will share its stdout with the
111
-- calling application, so you should carefully flush your stdout before
112
-- opening such a pipe, otherwise, output may become garbled and mixed up.
113
-- The same applies to an <EM>input filter</EM>: it shares its stdin with
114
-- the calling application! Unfortunately, one cannot flush an input stream
115
-- (that would be a meaningless operation anyway), so be careful!
117
-- One way to avoid such problems is using the @Std_In@ parameter. If it
118
-- is not the empty string, the command's stdin is redirected to come
119
-- from the given filename (which had better be valid). In other words,
120
-- the command actually executed is <CODE>Command & " <" & Std_In</CODE>.
121
-- If this feature is used, the caller is responsible for removing the
122
-- file, if that is desired.
125
(Stream : in out Pipe_Stream;
126
Exit_Code : out Integer);
127
-- Closes a stream obtained through @Open@. Raises @Use_Error@ if the
128
-- stream has not been opened.
130
-- An @Out_Stream@ <EM>must</EM> be closed, otherwise your program might
131
-- not terminate. therefore, @Pipe_Stream@s are controlled, and any
132
-- @Out_Stream@ is closed automatically when the stream object disappears.
134
-- An @In_Stream@ is only closed automatically if it has been opened with
135
-- <CODE>Close = True</CODE>, because closing such a stream may involve
136
-- waiting until the external command has terminated.
138
-- Note: this is a blocking call: it waits until the executed command
139
-- has terminated, and then returns that commands exit code.
142
(Stream : in Pipe_Stream)
144
-- Returns @True@ if the @Stream@ is open, and @False@ otherwise.
146
function End_Of_Stream
147
(Stream : in Pipe_Stream)
149
-- Raises @Mode_Error@ if the @Stream@ is an @Out_Stream@. Otherwise,
150
-- returns @True@ if the @In_Stream@s end has been reached and @False@
154
(Stream : in Pipe_Stream;
156
-- Same semantics as @Ada.Text_IO.Put@.
159
(Stream : in Pipe_Stream;
161
-- Same semantics as @Put@ for a string.
164
(Stream : in Pipe_Stream;
166
-- Same semantics as @Ada.Text_IO.Put_Line@.
169
(Stream : in Pipe_Stream;
171
-- Same semantics as @Ada.Text_IO.Get@.
174
(Stream : in Pipe_Stream;
175
Buffer : out String);
176
-- Same semantics as @Ada.Text_IO.Get@.
179
(Stream : in Pipe_Stream;
182
-- Same semantics as @Ada.Text_IO.Get_Line@.
185
(Stream : in Pipe_Stream)
187
-- As @Ada.Text_IO.Get_Line@, but always returns a full line.
191
type C_File_Ptr is new Interfaces.C.Strings.chars_ptr;
193
Null_Ptr : constant C_File_Ptr :=
194
C_File_Ptr (Interfaces.C.Strings.Null_Ptr);
196
type Closer (Stream : access Pipe_Stream) is
197
new Ada.Finalization.Limited_Controlled with null record;
199
procedure Finalize (C : in out Closer);
201
type Pipe_Stream is new Ada.Streams.Root_Stream_Type with
203
F : C_File_Ptr := Null_Ptr;
205
Close_It : Boolean := True;
206
Clean_Up : Closer (Pipe_Stream'Access);
210
(Stream : in out Pipe_Stream;
211
Item : out Ada.Streams.Stream_Element_Array;
212
Last : out Ada.Streams.Stream_Element_Offset);
215
(Stream : in out Pipe_Stream;
216
Item : in Ada.Streams.Stream_Element_Array);