arun/src/arun-launchers-unix.adb

165 lines
5.5 KiB
Ada

------------------------------------------------------------------------------
--
-- Copyright (C) 2017 R. Tyler Croy <tyler@linux.com>
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- as published by the Free Software Foundation; either version 2
-- of the License, or (at your option) any later version.
--
-- 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, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-- 02110-1301, USA.
------------------------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Environment_Variables;
with GNAT.Directory_Operations;
with GNAT.OS_Lib;
with Interfaces.C;
with Interfaces.C.Strings;
package body Arun.Launchers.Unix is
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";
overriding
function Discover_Executables (L : in UnixLauncher)
return Arun.String_Vectors.Vector
is
use GNAT.Directory_Operations;
use GNAT.OS_Lib;
use GNAT.String_Split;
use Ada.Strings.Unbounded;
Dir : Dir_Type;
File_Name : String (1 .. MAX_FILENAME_LENGTH);
File_Index : Natural := 0;
Executables : Arun.String_Vectors.Vector;
begin
for Index in 1 .. Slice_Count (L.Path_Components) loop
declare
Path_Dir : constant String := Slice (L.Path_Components, Index);
begin
if Is_Directory (Path_Dir) then
Open (Dir, Path_Dir);
loop
Read (Dir, File_Name, File_Index);
exit when File_Index = 0;
declare
Name : constant String := File_Name (1 .. File_Index);
Full_Path : constant String := Path_Dir & "/" & Name;
begin
if Is_Executable_File (Full_Path) then
Executables.Append (To_Unbounded_String (Name));
end if;
end;
end loop;
Close (Dir);
end if;
end;
end loop;
return Executables;
end Discover_Executables;
overriding
procedure Execute (L : in UnixLauncher;
Executable_Path : in String;
Argv : in GNAT.String_Split.Slice_Set) is
pragma Unreferenced (L);
use GNAT.String_Split;
use Interfaces.C;
use Interfaces.C.Strings;
Status : Integer;
Argc : constant size_t := size_t (Slice_Count (Argv));
Arguments : chars_ptr_array (1 .. (Argc + 1)) := (others => Null_Ptr);
begin
-- 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;
Put_Line ("Spawning " & Executable_Path);
Status :=
Exec_And_Replace (Filename => To_C (Item => Executable_Path,
Append_Nul => True),
Arguments => Arguments);
-- If the Exec_And_Replace function returns then something has
-- gone wrong
if Status /= 0 then
Print_Errno ("Something went wrong");
end if;
end Execute;
overriding
function Find_Full_Path (L : in UnixLauncher;
Path_Snippet : in String) return String is
use GNAT.String_Split;
begin
if not L.Initialized then
Put_Line ("Uninitialized UnixLauncher!");
return "";
end if;
for Index in 1 .. Slice_Count (L.Path_Components) loop
Put_Line ("Looking for an executable in " &
Slice (S => L.Path_Components,
Index => Index));
declare
Path_Component : constant String :=
Slice (S => L.Path_Components,
Index => Index);
Computed_Location : constant String :=
Path_Component & "/" & Path_Snippet;
begin
if GNAT.OS_Lib.Is_Executable_File (Computed_Location) then
Put_Line ("Found executable at " & Computed_Location);
return Computed_Location;
end if;
end;
end loop;
return "";
end Find_Full_Path;
procedure Initialize (L : in out UnixLauncher) is
use GNAT.String_Split;
PATH : constant String := Ada.Environment_Variables.Value ("PATH");
Separator : constant String := ":";
begin
Create (L.Path_Components, PATH, Separator, Single);
L.Initialized := True;
end Initialize;
end Arun.Launchers.Unix;