with Ada.Command_Line, Ada.Text_IO, Interfaces.C.Strings;
with POSIX.IO, POSIX.Process_Primitives;
with Creat, Fork, Wait;

procedure Pipe is
   procedure Exec (Program : in String) is
      procedure Exec_No_Arguments
        (Command : in Interfaces.C.Strings.chars_ptr;
         Name    : in Interfaces.C.Strings.chars_ptr;
         The_End : in Interfaces.C.Strings.chars_ptr);
      pragma Import (C, Exec_No_Arguments, "execlp");
      Command : Interfaces.C.Strings.chars_ptr :=
        Interfaces.C.Strings.New_String (Program);
   begin
      Exec_No_Arguments (Command, Command, Interfaces.C.Strings.Null_Ptr);
   end Exec;

   use type Interfaces.C.int;

   Input, Output : POSIX.IO.File_Descriptor;
   Process_ID    : Interfaces.C.int;
   New_File      : POSIX.IO.File_Descriptor;
begin
   if Ada.Command_Line.Argument_Count = 2 then
      POSIX.IO.Create_Pipe (Read_End  => Input,
                            Write_End => Output);
      Process_ID := Fork;
      if Process_ID = -1 then
         Ada.Text_IO.Put_Line (File => Ada.Text_IO.Standard_Error,
                               Item => "Calling fork() failed.");
         POSIX.Process_Primitives.Exit_Process (Status => 2);
      elsif Process_ID > 0 then
         --  Parent
         POSIX.IO.Close (File => Output);
         New_File :=
           POSIX.IO.Duplicate_And_Close (Input, POSIX.IO.Standard_Input);
         POSIX.IO.Close (File => Input);
         Exec (Ada.Command_Line.Argument (2));
      else
         --  Child
         POSIX.IO.Close (File => Input);
         New_File :=
           POSIX.IO.Duplicate_And_Close (Output, POSIX.IO.Standard_Output);
         POSIX.IO.Close (File => Output);
         Exec (Ada.Command_Line.Argument (1));
      end if;
   else
      Ada.Text_IO.Put_Line
        (File => Ada.Text_IO.Standard_Error,
         Item => "Usage: " & Ada.Command_Line.Command_Name & " cmd1 cmd2");
      POSIX.Process_Primitives.Exit_Process (Status => 1);
   end if;
end Pipe;

