-- Topal: GPG/GnuPG and Alpine/Pine integration
-- Copyright (C) 2001--2022  Phillip J. Brooke
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License version 3 as
-- published by the Free Software Foundation.
--
-- This program 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
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.

with Globals;               use Globals;

package Externals is

   -- Get our process ID.
   function C_Get_Process_ID return Integer;
   pragma Import (C, C_Get_Process_ID, "getpid");

   -- Glob on a filename pattern.
   function Glob (Pattern : in String) return UBS_Array;

   -- Exceptions for external calls.
   System_Abort_By_User : exception;
   Exec_Failed          : exception;
   Pipe_Failed          : exception;
   Fork_Failed          : exception;
   Dup2_Failed          : exception;
   CClose_Failed        : exception;
   Waitpid_Failed       : exception;
   Open_Append_Failed   : exception;
   Open_Out_Failed      : exception;
   Open_In_Failed       : exception;

private

   -- Execute (via execvp) File with argument list Argv.
   procedure Execvp (File : in String;
                     Argv : in UBS);

   -- In this next variant, Argv had better be a UBS_Array with
   -- elements 0, 1, ...
   procedure Execvp (File : in String;
                     Argv : in UBS_Array);

   -- Pipe binding.
   procedure Pipe (Reading : out Integer;
                   Writing : out Integer);

   -- Fork binding.  Returns 0 to child; child_pid to parent.
   function Fork return Integer;

   -- Dup2 binding
   procedure Dup2 (Oldfd, Newfd : in Integer);

   -- Binding for C Close.  We'll need this to tidy up nicely.
   procedure CClose (FD : in Integer);

   -- Binding for waitpid.  We return the subprocess exit code.
   function Waitpid (PID : Integer) return Integer;
   
   -- Wrappers to open a file and get a file descriptor (e.g., for dup2).
   function Open_Append (S : String) return Integer;
   function Open_Out    (S : String) return Integer;
   function Open_In     (S : String) return Integer;
   
   -- ForkExec: a replacement for System.
   function ForkExec (File : in String;
                      Argv : in UBS_Array) return Integer;

   function ForkExec (File : in String;
                      Argv : in UBS) return Integer;

   -- ForkExec: a replacement for System + append stdout to target.
   function ForkExec_Append (File   : in String;
                             Argv   : in UBS_Array;
                             Target : in String) return Integer;
   
   -- ForkExec: System with stdin.
   function ForkExec_In (File   : in String;
			 Argv   : in UBS_Array;
			 Source : in String) return Integer;
   
   -- ForkExec: a replacement for System + output stdout to target.
   function ForkExec_Out (File   : in String;
                          Argv   : in UBS_Array;
                          Target : in String) return Integer;

   function ForkExec_Out (File   : in String;
                          Argv   : in UBS;
                          Target : in String) return Integer;

   -- ForkExec: a replacement for System + output stdout to target + input
   -- from source.
   function ForkExec_InOut (File   : in String;
                            Argv   : in UBS_Array;
                            Source : in String;
                            Target : in String) return Integer;

   function ForkExec_InOut (File   : in String;
                            Argv   : in UBS;
                            Source : in String;
                            Target : in String) return Integer;

   -- More ForkExec variants: the number indicates how many processes are
   -- piped together.  `In' means that a file is sent to the first process
   -- on stdin; `Out' means that the last process sends stdout to a file;
   -- `Append' is predictable!  MergeStdErr => True is the bash-ism 2>&1.
   procedure ForkExec2 (File1         : in  String;
                        Argv1         : in  UBS_Array;
                        Exit1         : out Integer;
                        File2         : in  String;
                        Argv2         : in  UBS_Array;
                        Exit2         : out Integer;
                        Merge_StdErr1 : in  Boolean := False;
                        Report        : in  Boolean := False);

   procedure ForkExec2 (File1         : in  String;
                        Argv1         : in  UBS;
                        Exit1         : out Integer;
                        File2         : in  String;
                        Argv2         : in  UBS;
                        Exit2         : out Integer;
                        Merge_StdErr1 : in  Boolean := False;
                        Report        : in  Boolean := False);

   procedure ForkExec2_Out (File1  : in  String;
                            Argv1  : in  UBS_Array;
                            Exit1  : out Integer;
                            File2  : in  String;
                            Argv2  : in  UBS_Array;
                            Exit2  : out Integer;
                            Target : in  String);

   procedure ForkExec2_Out (File1  : in  String;
                            Argv1  : in  UBS;
                            Exit1  : out Integer;
                            File2  : in  String;
                            Argv2  : in  UBS_Array;
                            Exit2  : out Integer;
                            Target : in  String);

   procedure ForkExec2_InOut (File1  : in  String;
                              Argv1  : in  UBS_Array;
                              Exit1  : out Integer;
                              File2  : in  String;
                              Argv2  : in  UBS_Array;
                              Exit2  : out Integer;
                              Source : in  String;
                              Target : in  String);

   procedure ForkExec3_Out (File1  : in  String;
                            Argv1  : in  UBS;
                            Exit1  : out Integer;
                            File2  : in  String;
                            Argv2  : in  UBS_Array;
                            Exit2  : out Integer;
                            File3  : in  String;
                            Argv3  : in  UBS_Array;
                            Exit3  : out Integer;
                            Target : in  String);

end Externals;
