----------------------------------------------------------------------- -- util-streams-pipes -- Pipe stream to or from a process -- Copyright (C) 2011, 2013, 2016, 2017, 2018, 2021 Stephane Carrez -- Written by Stephane Carrez (Stephane.Carrez@gmail.com) -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. ----------------------------------------------------------------------- with Ada.IO_Exceptions; package body Util.Streams.Pipes is -- ----------------------- -- Set the shell executable path to use to launch a command. The default on Unix is -- the /bin/sh command. Argument splitting is done by the /bin/sh -c command. -- When setting an empty shell command, the argument splitting is done by the -- Spawn procedure. -- ----------------------- procedure Set_Shell (Stream : in out Pipe_Stream; Shell : in String) is begin Util.Processes.Set_Shell (Stream.Proc, Shell); end Set_Shell; -- ----------------------- -- Before launching the process, redirect the input stream of the process -- to the specified file. -- Raises Invalid_State if the process is running. -- ----------------------- procedure Set_Input_Stream (Stream : in out Pipe_Stream; File : in String) is begin Util.Processes.Set_Input_Stream (Stream.Proc, File); end Set_Input_Stream; -- ----------------------- -- Set the output stream of the process. -- Raises Invalid_State if the process is running. -- ----------------------- procedure Set_Output_Stream (Stream : in out Pipe_Stream; File : in String; Append : in Boolean := False) is begin Util.Processes.Set_Output_Stream (Stream.Proc, File, Append); end Set_Output_Stream; -- ----------------------- -- Set the error stream of the process. -- Raises Invalid_State if the process is running. -- ----------------------- procedure Set_Error_Stream (Stream : in out Pipe_Stream; File : in String; Append : in Boolean := False) is begin Util.Processes.Set_Error_Stream (Stream.Proc, File, Append); end Set_Error_Stream; -- ----------------------- -- Closes the given file descriptor in the child process before executing the command. -- ----------------------- procedure Add_Close (Stream : in out Pipe_Stream; Fd : in Util.Processes.File_Type) is begin Util.Processes.Add_Close (Stream.Proc, Fd); end Add_Close; -- ----------------------- -- Set the working directory that the process will use once it is created. -- The directory must exist or the Invalid_Directory exception will be raised. -- ----------------------- procedure Set_Working_Directory (Stream : in out Pipe_Stream; Path : in String) is begin Util.Processes.Set_Working_Directory (Stream.Proc, Path); end Set_Working_Directory; -- ----------------------- -- Open a pipe to read or write to an external process. The pipe is created and the -- command is executed with the input and output streams redirected through the pipe. -- ----------------------- procedure Open (Stream : in out Pipe_Stream; Command : in String; Mode : in Pipe_Mode := READ) is begin Util.Processes.Spawn (Stream.Proc, Command, Mode); end Open; -- ----------------------- -- Close the pipe and wait for the external process to terminate. -- ----------------------- overriding procedure Close (Stream : in out Pipe_Stream) is begin Util.Processes.Wait (Stream.Proc); end Close; -- ----------------------- -- Get the process exit status. -- ----------------------- function Get_Exit_Status (Stream : in Pipe_Stream) return Integer is begin return Util.Processes.Get_Exit_Status (Stream.Proc); end Get_Exit_Status; -- ----------------------- -- Returns True if the process is running. -- ----------------------- function Is_Running (Stream : in Pipe_Stream) return Boolean is begin return Util.Processes.Is_Running (Stream.Proc); end Is_Running; -- ----------------------- -- Write the buffer array to the output stream. -- ----------------------- overriding procedure Write (Stream : in out Pipe_Stream; Buffer : in Ada.Streams.Stream_Element_Array) is Output : constant Streams.Output_Stream_Access := Processes.Get_Input_Stream (Stream.Proc); begin if Output = null then raise Ada.IO_Exceptions.Status_Error with "Process is not launched"; end if; Output.Write (Buffer); end Write; -- ----------------------- -- Read into the buffer as many bytes as possible and return in -- last the position of the last byte read. -- ----------------------- overriding procedure Read (Stream : in out Pipe_Stream; Into : out Ada.Streams.Stream_Element_Array; Last : out Ada.Streams.Stream_Element_Offset) is Input : Streams.Input_Stream_Access := Processes.Get_Output_Stream (Stream.Proc); begin if Input = null then Input := Processes.Get_Error_Stream (Stream.Proc); if Input = null then raise Ada.IO_Exceptions.Status_Error with "Process is not launched"; end if; end if; Input.Read (Into, Last); end Read; -- ----------------------- -- Terminate the process by sending a signal on Unix and exiting the process on Windows. -- This operation is not portable and has a different behavior between Unix and Windows. -- Its intent is to stop the process. -- ----------------------- procedure Stop (Stream : in out Pipe_Stream; Signal : in Positive := 15) is begin Util.Processes.Stop (Stream.Proc, Signal); end Stop; end Util.Streams.Pipes;