I have used pipes in C/C++ before but I'm working on setting up a pipe in some legacy Ada code...however I am still in the "learning" phase with Ada and there's a lot I still don't yet know.
That being said, I've been trying to figure out how pipes in Ada are setup & how to go about using them. I've only found these articles thus far:
- A Thick Ada 95 Binding for Unix Child Processes and Pipes
- Package: Util.Pipes
- Pipes - ada-util.
Don't get me wrong they have a lot of good knowledge in them, but 1 is geared towards Ada95 (I have the ability to compile up to Ada05), 2 just lists the functions, & 3 offers little in the way of explanation.
Does anyone know of a tutorial for Ada pipes? Or better yet, could someone give a quick example of how to implement a simple pipe in Ada?
I realize that this is not the most ideal question to ask, but I'm running out of "Google Combinations"...
You might be more interested in Streams -- http://en.wikibooks.org/wiki/Ada_Programming/Input_Output/Stream_Tutorial
Especially since, if you make a package that binds a stream to a pipe you get free access with Type_Name'Read( stream, object ) & Type_Name'Write( stream, object ).
Code
Compiled on Windows 10 with GNAT GPL 2015
with Ada.Text_IO;
with System;
with Interfaces.C;
procedure Main is
package Pipes is
type Pipe is private;
type Get_Result is private;
function Open_Read (Command : String) return Pipe;
procedure Close (Stream : Pipe);
function Get (Stream : Pipe) return Get_Result;
function End_Of_File (Item : Get_Result) return Boolean;
function To_Ada (Item : Get_Result) return Character;
private
use System;
use Interfaces.C;
type Pipe is new Address;
type Get_Result is new int;
end;
package body Pipes is
function popen (command : char_array; mode : char_array) return Address with Import, Convention => C, External_Name => "popen";
function pclose (stream : Address) return int with Import, Convention => C, External_Name => "pclose";
function fgetc (stream : Address) return int with Import, Convention => C, External_Name => "fgetc";
function Open_Read (Command : String) return Pipe is
Mode : constant char_array := "r" & nul;
Result : Address;
begin
Result := popen (To_C (Command), Mode);
if Result = Null_Address then
raise Program_Error with "popen error";
end if;
return Pipe (Result);
end;
procedure Close (Stream : Pipe) is
Result : int;
begin
Result := pclose (Address (Stream));
if Result = -1 then
raise Program_Error with "pclose error";
end if;
end;
function Get (Stream : Pipe) return Get_Result is
begin
return Get_Result (fgetc (Address (Stream)));
end;
function End_Of_File (Item : Get_Result) return Boolean is (Item = -1);
function To_Ada (Item : Get_Result) return Character is (Character'Val (Get_Result'Pos (Item)));
end;
procedure Test is
use Ada.Text_IO;
use Pipes;
P : Pipe;
C : Get_Result;
begin
P := Open_Read ("netstat");
loop
C := Get (P);
exit when End_Of_File (C);
Put (To_Ada (C));
end loop;
Close (P);
end;
begin
Test;
end;
Output
The output will differ from user to user .
Active Connections
Proto Local Address Foreign Address State
TCP 192.168.1.140:49698 stackoverflow:https ESTABLISHED
TCP 192.168.1.140:49874 stackoverflow:https ESTABLISHED
TCP 192.168.1.140:49915 stackoverflow:https TIME_WAIT
TCP 192.168.1.140:49916 stackoverflow:https TIME_WAIT
Ada the language has nothing to say on the subject of pipes; they don't form part of the standard library. I suspect the same is true of C++ and the Boost library (not that I'm a user); pipes are an operating system facility.
Your article 1 contains source which compiles and works with Ada 2005 and Ada 2012 as well as (I expect) Ada 95 - at any rate on Unix systems. Won't that do?
Your article 2 - rather, the Util
package found by poking around a bit - says it works on Windows and Unix.
The software available at your article 3 has the great advantage of being maintained!
As for a tutorial - since pipes aren't in the standard you have to use what the people who wrote the particular library you choose have provided. Articles 1 and 3 both contain demonstration programs (I haven't checked article 2). I suspect that's it!
This may be overengineering a little, but there is gnat.sockets if you are allowed to use gnat libraries.
After all a pipe is a simpler version of a socket (or a socket being an expanded version of a pipe), both allow you to transfer data between tasks/processes.
If you want to use Unix pipes in an Ada application, you should consider the POSIX Ada API, as it is a formal standard. One implementation of this is the "FLORIST" library.
The Crimeville language server is an example of how you can use pipes to handle communication between an Ada application and a legacy application with a pipe-friendly interface.