Package: Util.Pipes

Dependencies

with Ada.Finalization;
with Ada.IO_Exceptions;
with Ada.Streams;

with Interfaces.C.Strings;

Description

Copyright © 2001, 2002 by Thomas Wolf.
This piece of software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This software is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License with this distribution, see file "GPL.txt". If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
As a special exception from the GPL, if other files instantiate generics from this unit, or you link this unit with other files to produce an executable, this unit does not by itself cause the resulting executable to be covered by the GPL. This exception does not however invalidate any other reasons why the executable file might be covered by the GPL.

Version: 1.1

Author:
Thomas Wolf (TW) <twolf AT acm DOT org>
Purpose:
This is a thick binding to the popen and pclose routines available on both Unix and Win32. It gives a convenient way to execute an external program and pass it some input, or read its output.
Tasking Semantics
Neither task- not abortion-safe. All operations here should be considered potentially blocking.
Storage Semantics
No dynamic storage allocation.

Header

package Util.Pipes is
 

Exceptions

Device_Error renames Ada.IO_Exceptions.Device_Error
Raised by the Put or Get operations (and also by Write and Read) if the underlying system operations indicate any reading or writing error.
End_Error renames Ada.IO_Exceptions.End_Error
Stream operations on an In_Stream will raise End_Error if EOF is encountered.
Mode_Error renames Ada.IO_Exceptions.Mode_Error
Stream operations on the returned stream may raise Mode_Error if writing on an In_Stream or reading from an Out_Stream is attempted.
Name_Error renames Ada.IO_Exceptions.Name_Error
Raised by Open if the command cannot be executed.
Use_Error renames Ada.IO_Exceptions.Use_Error
Raised by any stream operation if the stream is not open (and by Open, if it already is open).

Type Summary

Pipe_Stream derived from Root_Stream_Type
New Operations:  Close, End_Of_Stream, Get, Get, Get_Line, Get_Line, Is_Open, Open, Put, Put, Put_Line
Inherited Operations:  Read, Write
Stream_Mode

Other Items:

type Stream_Mode is (In_Stream, Out_Stream);
Used in Open to specify the type of the stream.

type Pipe_Stream is new Ada.Streams.Root_Stream_Type with private;
I have found no indication whatsoever about the type of the underlying C stream (binary or text mode?). Although you can write and read binary data to and from a Pipe_Stream, it's probably prudent to consider these streams as text-only, because they set up pipes to or from an external processes stdin or stdout handles, which are defined by the ISO C standard as text streams.

procedure Open
  (Stream  : in out Pipe_Stream;
   Command : in     String;
   Mode    : in     Stream_Mode;
   Close   : in     Boolean := True;
   Std_In  : in     String  := "");
Executes Command, which may contain arguments, setting it up such that the executed command's stdin comes from the returned stream if Mode is Out_Stream, or the command's stdout can be read from that stream if Mode is In_Stream. Note that "in" and "out" are from the caller's perspective.

If Close = True, the stream is closed automatically when the stream object disappears. Note that this may involve waiting until the external command terminates. Out_Streams always are closed automatically.

Raises Name_Error if the Command cannot be executed, or Use_Error if the stream is already open.

Note that an output filter is created using a stream of mode Out_Stream. The external process will share its stdout with the calling application, so you should carefully flush your stdout before opening such a pipe, otherwise, output may become garbled and mixed up. The same applies to an input filter: it shares its stdin with the calling application! Unfortunately, one cannot flush an input stream (that would be a meaningless operation anyway), so be careful!

One way to avoid such problems is using the Std_In parameter. If it is not the empty string, the command's stdin is redirected to come from the given filename (which had better be valid). In other words, the command actually executed is Command & " <" & Std_In. If this feature is used, the caller is responsible for removing the file, if that is desired.


procedure Close
  (Stream    : in out Pipe_Stream;
   Exit_Code :    out Integer);
Closes a stream obtained through Open. Raises Use_Error if the stream has not been opened.

An Out_Stream must be closed, otherwise your program might not terminate. therefore, Pipe_Streams are controlled, and any Out_Stream is closed automatically when the stream object disappears.

An In_Stream is only closed automatically if it has been opened with Close = True, because closing such a stream may involve waiting until the external command has terminated.

Note: this is a blocking call: it waits until the executed command has terminated, and then returns that commands exit code.


function Is_Open
  (Stream : in Pipe_Stream)
  return Boolean;
Returns True if the Stream is open, and False otherwise.

function End_Of_Stream
  (Stream : in Pipe_Stream)
  return Boolean;
Raises Mode_Error if the Stream is an Out_Stream. Otherwise, returns True if the In_Streams end has been reached and False otherwise.

procedure Put
  (Stream : in Pipe_Stream;
   Text   : in String);
Same semantics as Ada.Text_IO.Put.

procedure Put
  (Stream : in Pipe_Stream;
   Ch     : in Character);
Same semantics as Put for a string.

procedure Put_Line
  (Stream : in Pipe_Stream;
   Text   : in String);
Same semantics as Ada.Text_IO.Put_Line.

procedure Get
  (Stream : in     Pipe_Stream;
   Ch     :    out Character);
Same semantics as Ada.Text_IO.Get.

procedure Get
  (Stream : in     Pipe_Stream;
   Buffer :    out String);
Same semantics as Ada.Text_IO.Get.

procedure Get_Line
  (Stream : in     Pipe_Stream;
   Buffer :    out String;
   Last   :    out Natural);
Same semantics as Ada.Text_IO.Get_Line.

function Get_Line
  (Stream : in Pipe_Stream)
  return String;
As Ada.Text_IO.Get_Line, but always returns a full line.

private

   --  Implementation-defined ...
end Util.Pipes;