2005-07-04 Thomas Quinot <quinot@adacore.com>
* g-expect-vms.adb, g-expect.ads, g-expect.adb (Get_Command_Output): New subprogram to launch a process and get its standard output as a string. From-SVN: r101571
This commit is contained in:
parent
fc64d83c6f
commit
1a79be3c00
|
@ -761,6 +761,89 @@ package body GNAT.Expect is
|
||||||
|
|
||||||
end Flush;
|
end Flush;
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
-- Get_Command_Output --
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
function Get_Command_Output
|
||||||
|
(Command : String;
|
||||||
|
Arguments : GNAT.OS_Lib.Argument_List;
|
||||||
|
Input : String;
|
||||||
|
Status : access Integer;
|
||||||
|
Err_To_Out : Boolean := False) return String
|
||||||
|
is
|
||||||
|
use GNAT.Expect;
|
||||||
|
|
||||||
|
Process : Process_Descriptor;
|
||||||
|
|
||||||
|
Output : String_Access := new String (1 .. 1024);
|
||||||
|
-- Buffer used to accumulate standard output from the launched
|
||||||
|
-- command, expanded as necessary during execution.
|
||||||
|
|
||||||
|
Last : Integer := 0;
|
||||||
|
-- Index of the last used character within Output
|
||||||
|
|
||||||
|
begin
|
||||||
|
Non_Blocking_Spawn
|
||||||
|
(Process, Command, Arguments, Err_To_Out => Err_To_Out);
|
||||||
|
|
||||||
|
if Input'Length > 0 then
|
||||||
|
Send (Process, Input);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
GNAT.OS_Lib.Close (Get_Input_Fd (Process));
|
||||||
|
|
||||||
|
declare
|
||||||
|
Result : Expect_Match;
|
||||||
|
|
||||||
|
begin
|
||||||
|
-- This loop runs until the call to Expect raises Process_Died
|
||||||
|
|
||||||
|
loop
|
||||||
|
Expect (Process, Result, ".+");
|
||||||
|
|
||||||
|
declare
|
||||||
|
NOutput : String_Access;
|
||||||
|
S : constant String := Expect_Out (Process);
|
||||||
|
pragma Assert (S'Length > 0);
|
||||||
|
|
||||||
|
begin
|
||||||
|
-- Expand buffer if we need more space
|
||||||
|
|
||||||
|
if Last + S'Length > Output'Last then
|
||||||
|
NOutput := new String (1 .. 2 * Output'Last);
|
||||||
|
NOutput (Output'Range) := Output.all;
|
||||||
|
Free (Output);
|
||||||
|
|
||||||
|
-- Here if current buffer size is OK
|
||||||
|
|
||||||
|
else
|
||||||
|
NOutput := Output;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
NOutput (Last + 1 .. Last + S'Length) := S;
|
||||||
|
Last := Last + S'Length;
|
||||||
|
Output := NOutput;
|
||||||
|
end;
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
exception
|
||||||
|
when Process_Died =>
|
||||||
|
Close (Process, Status.all);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if Last = 0 then
|
||||||
|
return "";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
declare
|
||||||
|
S : constant String := Output (1 .. Last);
|
||||||
|
begin
|
||||||
|
Free (Output);
|
||||||
|
return S;
|
||||||
|
end;
|
||||||
|
end Get_Command_Output;
|
||||||
|
|
||||||
------------------
|
------------------
|
||||||
-- Get_Error_Fd --
|
-- Get_Error_Fd --
|
||||||
------------------
|
------------------
|
||||||
|
|
|
@ -108,7 +108,7 @@ package body GNAT.Expect is
|
||||||
|
|
||||||
function Waitpid (Pid : Process_Id) return Integer;
|
function Waitpid (Pid : Process_Id) return Integer;
|
||||||
pragma Import (C, Waitpid, "__gnat_waitpid");
|
pragma Import (C, Waitpid, "__gnat_waitpid");
|
||||||
-- Wait for a specific process id, and return its exit code.
|
-- Wait for a specific process id, and return its exit code
|
||||||
|
|
||||||
---------
|
---------
|
||||||
-- "+" --
|
-- "+" --
|
||||||
|
@ -656,7 +656,7 @@ package body GNAT.Expect is
|
||||||
Descriptors (J).Buffer_Size - N;
|
Descriptors (J).Buffer_Size - N;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- Keep what we read in the buffer.
|
-- Keep what we read in the buffer
|
||||||
|
|
||||||
Descriptors (J).Buffer
|
Descriptors (J).Buffer
|
||||||
(Descriptors (J).Buffer_Index + 1 ..
|
(Descriptors (J).Buffer_Index + 1 ..
|
||||||
|
@ -754,9 +754,91 @@ package body GNAT.Expect is
|
||||||
end if;
|
end if;
|
||||||
end case;
|
end case;
|
||||||
end loop;
|
end loop;
|
||||||
|
|
||||||
end Flush;
|
end Flush;
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
-- Get_Command_Output --
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
function Get_Command_Output
|
||||||
|
(Command : String;
|
||||||
|
Arguments : GNAT.OS_Lib.Argument_List;
|
||||||
|
Input : String;
|
||||||
|
Status : access Integer;
|
||||||
|
Err_To_Out : Boolean := False) return String
|
||||||
|
is
|
||||||
|
use GNAT.Expect;
|
||||||
|
|
||||||
|
Process : Process_Descriptor;
|
||||||
|
|
||||||
|
Output : String_Access := new String (1 .. 1024);
|
||||||
|
-- Buffer used to accumulate standard output from the launched
|
||||||
|
-- command, expanded as necessary during execution.
|
||||||
|
|
||||||
|
Last : Integer := 0;
|
||||||
|
-- Index of the last used character within Output
|
||||||
|
|
||||||
|
begin
|
||||||
|
Non_Blocking_Spawn
|
||||||
|
(Process, Command, Arguments, Err_To_Out => Err_To_Out);
|
||||||
|
|
||||||
|
if Input'Length > 0 then
|
||||||
|
Send (Process, Input);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
GNAT.OS_Lib.Close (Get_Input_Fd (Process));
|
||||||
|
|
||||||
|
declare
|
||||||
|
Result : Expect_Match;
|
||||||
|
|
||||||
|
begin
|
||||||
|
-- This loop runs until the call to Expect raises Process_Died
|
||||||
|
|
||||||
|
loop
|
||||||
|
Expect (Process, Result, ".+");
|
||||||
|
|
||||||
|
declare
|
||||||
|
NOutput : String_Access;
|
||||||
|
S : constant String := Expect_Out (Process);
|
||||||
|
pragma Assert (S'Length > 0);
|
||||||
|
|
||||||
|
begin
|
||||||
|
-- Expand buffer if we need more space
|
||||||
|
|
||||||
|
if Last + S'Length > Output'Last then
|
||||||
|
NOutput := new String (1 .. 2 * Output'Last);
|
||||||
|
NOutput (Output'Range) := Output.all;
|
||||||
|
Free (Output);
|
||||||
|
|
||||||
|
-- Here if current buffer size is OK
|
||||||
|
|
||||||
|
else
|
||||||
|
NOutput := Output;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
NOutput (Last + 1 .. Last + S'Length) := S;
|
||||||
|
Last := Last + S'Length;
|
||||||
|
Output := NOutput;
|
||||||
|
end;
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
exception
|
||||||
|
when Process_Died =>
|
||||||
|
Close (Process, Status.all);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if Last = 0 then
|
||||||
|
return "";
|
||||||
|
end if;
|
||||||
|
|
||||||
|
declare
|
||||||
|
S : constant String := Output (1 .. Last);
|
||||||
|
begin
|
||||||
|
Free (Output);
|
||||||
|
return S;
|
||||||
|
end;
|
||||||
|
end Get_Command_Output;
|
||||||
|
|
||||||
------------------
|
------------------
|
||||||
-- Get_Error_Fd --
|
-- Get_Error_Fd --
|
||||||
------------------
|
------------------
|
||||||
|
@ -1012,7 +1094,7 @@ package body GNAT.Expect is
|
||||||
begin
|
begin
|
||||||
if Empty_Buffer then
|
if Empty_Buffer then
|
||||||
|
|
||||||
-- Force a read on the process if there is anything waiting.
|
-- Force a read on the process if there is anything waiting
|
||||||
|
|
||||||
Expect_Internal (Descriptors, Result,
|
Expect_Internal (Descriptors, Result,
|
||||||
Timeout => 0, Full_Buffer => False);
|
Timeout => 0, Full_Buffer => False);
|
||||||
|
@ -1047,7 +1129,7 @@ package body GNAT.Expect is
|
||||||
is
|
is
|
||||||
begin
|
begin
|
||||||
Kill (Descriptor.Pid, Signal);
|
Kill (Descriptor.Pid, Signal);
|
||||||
-- ??? Need to check process status here.
|
-- ??? Need to check process status here
|
||||||
end Send_Signal;
|
end Send_Signal;
|
||||||
|
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
-- --
|
-- --
|
||||||
-- S p e c --
|
-- S p e c --
|
||||||
-- --
|
-- --
|
||||||
-- Copyright (C) 2000-2004 Ada Core Technologies, Inc. --
|
-- Copyright (C) 2000-2005 Ada Core Technologies, Inc. --
|
||||||
-- --
|
-- --
|
||||||
-- GNAT is free software; you can redistribute it and/or modify it under --
|
-- GNAT is free software; you can redistribute it and/or modify it under --
|
||||||
-- terms of the GNU General Public License as published by the Free Soft- --
|
-- terms of the GNU General Public License as published by the Free Soft- --
|
||||||
|
@ -35,8 +35,9 @@
|
||||||
-- for VMS. It is not yet implemented for any of the cross-ports (e.g. it
|
-- for VMS. It is not yet implemented for any of the cross-ports (e.g. it
|
||||||
-- is not available for VxWorks or LynxOS).
|
-- is not available for VxWorks or LynxOS).
|
||||||
|
|
||||||
-- Usage
|
-- -----------
|
||||||
-- =====
|
-- -- Usage --
|
||||||
|
-- -----------
|
||||||
|
|
||||||
-- This package provides a set of subprograms similar to what is available
|
-- This package provides a set of subprograms similar to what is available
|
||||||
-- with the standard Tcl Expect tool.
|
-- with the standard Tcl Expect tool.
|
||||||
|
@ -111,11 +112,14 @@
|
||||||
-- Send (Fd, "command");
|
-- Send (Fd, "command");
|
||||||
-- Expect (Fd, Result, ".."); -- match only on the output of command
|
-- Expect (Fd, Result, ".."); -- match only on the output of command
|
||||||
|
|
||||||
-- Task Safety
|
-- -----------------
|
||||||
-- ===========
|
-- -- Task Safety --
|
||||||
|
-- -----------------
|
||||||
|
|
||||||
-- This package is not task-safe: there should be not concurrent calls to
|
-- This package is not task-safe: there should be not concurrent calls to
|
||||||
-- the functions defined in this package.
|
-- the functions defined in this package. In other words, separate tasks
|
||||||
|
-- may not access the facilities of this package without synchronization
|
||||||
|
-- that serializes access.
|
||||||
|
|
||||||
with System;
|
with System;
|
||||||
with GNAT.OS_Lib;
|
with GNAT.OS_Lib;
|
||||||
|
@ -195,7 +199,7 @@ package GNAT.Expect is
|
||||||
procedure Send_Signal
|
procedure Send_Signal
|
||||||
(Descriptor : Process_Descriptor;
|
(Descriptor : Process_Descriptor;
|
||||||
Signal : Integer);
|
Signal : Integer);
|
||||||
-- Send a given signal to the process.
|
-- Send a given signal to the process
|
||||||
|
|
||||||
procedure Interrupt (Descriptor : in out Process_Descriptor);
|
procedure Interrupt (Descriptor : in out Process_Descriptor);
|
||||||
-- Interrupt the process (the equivalent of Ctrl-C on unix and windows)
|
-- Interrupt the process (the equivalent of Ctrl-C on unix and windows)
|
||||||
|
@ -204,22 +208,33 @@ package GNAT.Expect is
|
||||||
function Get_Input_Fd
|
function Get_Input_Fd
|
||||||
(Descriptor : Process_Descriptor)
|
(Descriptor : Process_Descriptor)
|
||||||
return GNAT.OS_Lib.File_Descriptor;
|
return GNAT.OS_Lib.File_Descriptor;
|
||||||
-- Return the input file descriptor associated with Descriptor.
|
-- Return the input file descriptor associated with Descriptor
|
||||||
|
|
||||||
function Get_Output_Fd
|
function Get_Output_Fd
|
||||||
(Descriptor : Process_Descriptor)
|
(Descriptor : Process_Descriptor)
|
||||||
return GNAT.OS_Lib.File_Descriptor;
|
return GNAT.OS_Lib.File_Descriptor;
|
||||||
-- Return the output file descriptor associated with Descriptor.
|
-- Return the output file descriptor associated with Descriptor
|
||||||
|
|
||||||
function Get_Error_Fd
|
function Get_Error_Fd
|
||||||
(Descriptor : Process_Descriptor)
|
(Descriptor : Process_Descriptor)
|
||||||
return GNAT.OS_Lib.File_Descriptor;
|
return GNAT.OS_Lib.File_Descriptor;
|
||||||
-- Return the error output file descriptor associated with Descriptor.
|
-- Return the error output file descriptor associated with Descriptor
|
||||||
|
|
||||||
function Get_Pid
|
function Get_Pid
|
||||||
(Descriptor : Process_Descriptor)
|
(Descriptor : Process_Descriptor)
|
||||||
return Process_Id;
|
return Process_Id;
|
||||||
-- Return the process id assocated with a given process descriptor.
|
-- Return the process id assocated with a given process descriptor
|
||||||
|
|
||||||
|
function Get_Command_Output
|
||||||
|
(Command : String;
|
||||||
|
Arguments : GNAT.OS_Lib.Argument_List;
|
||||||
|
Input : String;
|
||||||
|
Status : access Integer;
|
||||||
|
Err_To_Out : Boolean := False) return String;
|
||||||
|
-- Execute Command with the specified Arguments and Input, and return the
|
||||||
|
-- generated standard output data as a single string. If Err_To_Out is
|
||||||
|
-- True, generated standard error output is included as well. On return,
|
||||||
|
-- Status is set to the command's exit status.
|
||||||
|
|
||||||
--------------------
|
--------------------
|
||||||
-- Adding filters --
|
-- Adding filters --
|
||||||
|
@ -302,10 +317,10 @@ package GNAT.Expect is
|
||||||
|
|
||||||
type Expect_Match is new Integer;
|
type Expect_Match is new Integer;
|
||||||
Expect_Full_Buffer : constant Expect_Match := -1;
|
Expect_Full_Buffer : constant Expect_Match := -1;
|
||||||
-- If the buffer was full and some characters were discarded.
|
-- If the buffer was full and some characters were discarded
|
||||||
|
|
||||||
Expect_Timeout : constant Expect_Match := -2;
|
Expect_Timeout : constant Expect_Match := -2;
|
||||||
-- If not output matching the regexps was found before the timeout.
|
-- If not output matching the regexps was found before the timeout
|
||||||
|
|
||||||
function "+" (S : String) return GNAT.OS_Lib.String_Access;
|
function "+" (S : String) return GNAT.OS_Lib.String_Access;
|
||||||
-- Allocate some memory for the string. This is merely a convenience
|
-- Allocate some memory for the string. This is merely a convenience
|
||||||
|
@ -380,7 +395,7 @@ package GNAT.Expect is
|
||||||
Matched : out GNAT.Regpat.Match_Array;
|
Matched : out GNAT.Regpat.Match_Array;
|
||||||
Timeout : Integer := 10000;
|
Timeout : Integer := 10000;
|
||||||
Full_Buffer : Boolean := False);
|
Full_Buffer : Boolean := False);
|
||||||
-- Same as above, but with a precompiled regular expression.
|
-- Same as above, but with a precompiled regular expression
|
||||||
|
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
-- Working on the output (single process, multiple regexp) --
|
-- Working on the output (single process, multiple regexp) --
|
||||||
|
@ -461,7 +476,7 @@ package GNAT.Expect is
|
||||||
Matched : out GNAT.Regpat.Match_Array;
|
Matched : out GNAT.Regpat.Match_Array;
|
||||||
Timeout : Integer := 10000;
|
Timeout : Integer := 10000;
|
||||||
Full_Buffer : Boolean := False);
|
Full_Buffer : Boolean := False);
|
||||||
-- Same as above, but for multi processes.
|
-- Same as above, but for multi processes
|
||||||
|
|
||||||
procedure Expect
|
procedure Expect
|
||||||
(Result : out Expect_Match;
|
(Result : out Expect_Match;
|
||||||
|
@ -535,7 +550,7 @@ private
|
||||||
type Pipe_Type is record
|
type Pipe_Type is record
|
||||||
Input, Output : GNAT.OS_Lib.File_Descriptor;
|
Input, Output : GNAT.OS_Lib.File_Descriptor;
|
||||||
end record;
|
end record;
|
||||||
-- This type represents a pipe, used to communicate between two processes.
|
-- This type represents a pipe, used to communicate between two processes
|
||||||
|
|
||||||
procedure Set_Up_Communications
|
procedure Set_Up_Communications
|
||||||
(Pid : in out Process_Descriptor;
|
(Pid : in out Process_Descriptor;
|
||||||
|
|
Loading…
Reference in New Issue