From bfdce8bc381bc38b7621f1d2df7bdb3d6267d032 Mon Sep 17 00:00:00 2001 From: "R. Tyler Croy" Date: Sat, 14 Jan 2017 00:05:35 -0800 Subject: [PATCH] Update Arun.Launcher_Type.Execute to take a Slic_Set in order to support arguments With this commit Arun now supports executing commands which can be found on $PATH with arguments :fireworks: --- src/arun-handlers.adb | 30 ++++++++++++++++----- src/arun-launchers-unix.adb | 53 +++++++++++++++++++++---------------- src/arun-launchers-unix.ads | 10 ++++--- src/arun.ads | 7 +++-- 4 files changed, 66 insertions(+), 34 deletions(-) diff --git a/src/arun-handlers.adb b/src/arun-handlers.adb index 5340f24..f0d0615 100644 --- a/src/arun-handlers.adb +++ b/src/arun-handlers.adb @@ -29,6 +29,8 @@ with Gtk.Widget; with Gtk.Search_Entry; with Gtkada.Builder; use Gtkada.Builder; +with GNAT.String_Split; + with Arun; with Arun.Launchers.Unix; with Arun.View; use Arun.View; @@ -53,21 +55,37 @@ package body Arun.Handlers is end Search_Changed; + function Slice_Command (Text : in String) return GNAT.String_Split.Slice_Set is + use GNAT.String_Split; + + Separator : constant String := " "; + Slices : Slice_Set; + begin + + Create (Slices, Text, Separator, Single); + + return Slices; + end Slice_Command; + procedure Execute_Command (Object : access Gtkada_Builder_Record'Class) is use Ada.Text_IO; use Gtk.Search_Entry; use Gtkada.Builder; + use GNAT.String_Split; - Widget : Gtk_Search_Entry := Gtk_Search_Entry (Get_Object (Object, "commandEntry")); - Command : constant String := Widget.Get_Text; - B : Arun.View.Arun_Builder_Record renames Arun.View.Arun_Builder_Record (Object.all); - L : Arun.Launchers.Unix.UnixLauncher renames Arun.Launchers.Unix.UnixLauncher (B.Launcher); + Widget : Gtk_Search_Entry := Gtk_Search_Entry (Get_Object (Object, "commandEntry")); + Builder : Arun.View.Arun_Builder_Record renames Arun.View.Arun_Builder_Record (Object.all); + L : Arun.Launchers.Unix.UnixLauncher renames Arun.Launchers.Unix.UnixLauncher (Builder.Launcher); + + + Slices : constant Slice_Set := Slice_Command (Widget.Get_Text); + Command : constant String := Slice (S => Slices, Index => 1); Full_Path : aliased constant String := L.Find_Full_Path (Command); begin if Full_Path /= "" then - Put_Line ("Should Execute: " & Command); - L.Execute (Full_Path); + Put_Line ("Should Execute: " & Full_Path); + L.Execute (Full_Path, Slices); end if; Gtk.Main.Main_Quit; diff --git a/src/arun-launchers-unix.adb b/src/arun-launchers-unix.adb index be3378e..0b5ffe5 100644 --- a/src/arun-launchers-unix.adb +++ b/src/arun-launchers-unix.adb @@ -74,41 +74,48 @@ package body Arun.Launchers.Unix is end Find_Full_Path; - procedure Execute (L : in UnixLauncher; - Executable : in String) is - use GNAT.OS_Lib; + + function Exec_And_Replace (Filename : in Interfaces.C.Char_Array; + Arguments : in Interfaces.C.Strings.Chars_Ptr_Array) return Integer + with Import, + Convention => C, + Link_Name => "execv"; + + procedure Print_Errno (Message : in String) + with Import, + Convention => C, + Link_Name => "perror"; + + procedure Execute (L : in UnixLauncher; + Executable_Path : in String; + Argv : in GNAT.String_Split.Slice_Set) is + use GNAT.String_Split; use Interfaces.C; use Interfaces.C.Strings; - use Ada.Command_Line.Environment; - - function Exec_And_Replace (Filename : in Char_Array; - Arguments : in Chars_Ptr_Array) return Integer - with Import, - Convention => C, - Link_Name => "execv"; - - procedure Print_Errno (Message : in String) - with Import, - Convention => C, - Link_Name => "perror"; - - Default_Args : Chars_Ptr_Array (1 .. 2) := (1 => New_String (Executable), 2 => Null_Ptr); Status : Integer; + Argc : constant Size_T := Size_T (Slice_Count (Argv)); + Arguments : Chars_Ptr_Array (1 .. (Argc + 1)) := (others => Null_Ptr); begin - Put_Line ("Spawning " & Executable); + -- For the first argument, we must replace the executable name with + -- the full path, e.g. "xeyes" => "/usr/bin/xeyes" + Arguments (1) := New_String (Executable_Path); + for Index in 1 .. Argc loop + Arguments (Index) := New_String (Slice (S => Argv, + Index => Slice_Number (Index))); + end loop; - Status := Exec_And_Replace (Filename => To_C (Item => Executable, + Put_Line ("Spawning " & Executable_Path); + + Status := Exec_And_Replace (Filename => To_C (Item => Executable_Path, Append_Nul => True), - Arguments => Default_Args); + Arguments => Arguments); -- If the Exec_And_Replace function returns then something has gone wrong - Put_Line ("Spawned " & Executable & " with " & Status'Img); - if Status /= 0 then Print_Errno ("Something went wrong"); end if; - end Execute; + end Arun.Launchers.Unix; diff --git a/src/arun-launchers-unix.ads b/src/arun-launchers-unix.ads index a66f21a..b5546b2 100644 --- a/src/arun-launchers-unix.ads +++ b/src/arun-launchers-unix.ads @@ -19,7 +19,7 @@ with Arun; -private with GNAT.String_Split; +with GNAT.String_Split; package Arun.Launchers.Unix is type UnixLauncher is new Arun.Launcher_Type with private; @@ -34,8 +34,12 @@ package Arun.Launchers.Unix is -- Will return an empty string if a full path was not discoverable. - procedure Execute (L : in UnixLauncher; - Executable : in String); + procedure Execute (L : in UnixLauncher; + Executable_Path : in String; + Argv : in GNAT.String_Split.Slice_Set); + -- Execute a command using the given UnixLauncher with an "Argv" + -- Slice_Set assuming the first argument is the command and subsequent values + -- are arguments for that command. private type UnixLauncher is new Arun.Launcher_Type with record diff --git a/src/arun.ads b/src/arun.ads index 98db178..469d7af 100644 --- a/src/arun.ads +++ b/src/arun.ads @@ -17,6 +17,8 @@ -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ------------------------------------------------------------------------------ +with GNAT.String_Split; + package Arun is procedure Main; @@ -32,8 +34,9 @@ package Arun is -- -- Will return an empty string if a full path was not discoverable. - procedure Execute (L : in Launcher_Type; - Executable : in String) is abstract; + procedure Execute (L : in Launcher_Type; + Executable_Path : in String; + Argv : in GNAT.String_Split.Slice_Set) is abstract; -- Spawn the Executable in place of the current process end Arun;