with Ada.Text_IO, Interfaces.C, POSIX.IO, POSIX.Process_Primitives;

with Fork;

procedure Pipe_Demonstration_2 is
   use type Interfaces.C.int;
   use type POSIX.POSIX_String;

   Child_Says  : constant POSIX.POSIX_String := "I want a cookie" & POSIX.LF;
   Parent_Says : constant POSIX.POSIX_String := "testing ..." & POSIX.LF;

   procedure Oops (Message : in     String;
                   Error   : in     POSIX.Process_Primitives.Exit_Status) is
   begin
      Ada.Text_IO.Put_Line (File => Ada.Text_IO.Standard_Error,
                            Item => "Error: " & Message);
      POSIX.Process_Primitives.Exit_Process (Status => Error);
   end Oops;

   Input, Output : POSIX.IO.File_Descriptor;
begin
   POSIX.IO.Create_Pipe (Read_End  => Input,
                         Write_End => Output);

   case Fork is
      when -1 =>
         Oops (Message => "Cannot fork.",
               Error   => 2);
      when 0 =>
         declare
            Written : Natural;
         begin
            loop
               POSIX.IO.NONSTANDARD_Write (File   => Output,
                                           Buffer => Child_Says,
                                           Last   => Written);
               if Written /= Child_Says'Last then
                  Oops (Message => "Child cannot write to pipe.",
                        Error   => 3);
               end if;
               delay 5.0;
            end loop;
         end;
      when others =>
         declare
            Written, Read : Natural;
            Buffer        : POSIX.IO.IO_Buffer (1 .. 512);
         begin
            loop
               POSIX.IO.NONSTANDARD_Write (File   => Output,
                                           Buffer => Parent_Says,
                                           Last   => Written);
               if Written /= Parent_Says'Last then
                  Oops (Message => "Parent cannot write to pipe.",
                        Error   => 4);
               end if;
               delay 1.0;
               POSIX.IO.NONSTANDARD_Read (File   => Input,
                                          Buffer => Buffer,
                                          Last   => Read);
               exit when Read <= 0;
               POSIX.IO.NONSTANDARD_Write
                 (File   => POSIX.IO.Standard_Output,
                  Buffer => Buffer (Buffer'First .. Read),
                  Last   => Written);
            end loop;
         end;
   end case;
end Pipe_Demonstration_2;

