home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / adav313.zip / gnat-3_13p-os2-bin-20010916.zip / emx / gnatlib / g-os_lib.adb < prev    next >
Text File  |  2000-07-19  |  21KB  |  750 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                          G N A T . O S _ L I B                           --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.53 $
  10. --                                                                          --
  11. --           Copyright (C) 1995-2000 Ada Core Technologies, Inc.            --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
  22. -- MA 02111-1307, USA.                                                      --
  23. --                                                                          --
  24. -- As a special exception,  if other files  instantiate  generics from this --
  25. -- unit, or you link  this unit with other files  to produce an executable, --
  26. -- this  unit  does not  by itself cause  the resulting  executable  to  be --
  27. -- covered  by the  GNU  General  Public  License.  This exception does not --
  28. -- however invalidate  any other reasons why  the executable file  might be --
  29. -- covered by the  GNU Public License.                                      --
  30. --                                                                          --
  31. -- GNAT is maintained by Ada Core Technologies Inc (http://www.gnat.com).   --
  32. --                                                                          --
  33. ------------------------------------------------------------------------------
  34.  
  35. with System.Soft_Links;
  36. with Unchecked_Conversion;
  37. with System; use System;
  38.  
  39. package body GNAT.OS_Lib is
  40.  
  41.    package SSL renames System.Soft_Links;
  42.  
  43.    -----------------------
  44.    -- Local Subprograms --
  45.    -----------------------
  46.  
  47.    function C_String_Length (S : Address) return Integer;
  48.    --  Returns the length of a C string. Does check for null address
  49.    --  (returns 0).
  50.  
  51.    procedure Spawn_Internal
  52.      (Program_Name : String;
  53.       Args         : Argument_List;
  54.       Success      : out Boolean;
  55.       Pid          : out Process_Id;
  56.       Blocking     : Boolean);
  57.    --  Internal routine to implement the to Spawn (blocking and non blocking)
  58.    --  routines. If Blocking is set to True then the spawn is blocking
  59.    --  otherwise it is non blocking. In this latter case the Pid contains
  60.    --  the process id number. The first three parameters are as in Spawn.
  61.  
  62.    function To_Path_String_Access
  63.      (Path_Addr : Address;
  64.       Path_Len  : Integer)
  65.       return String_Access;
  66.    --  Converts a C String to an Ada String.  Are we doing this to avoid
  67.    --  withing Interfaces.C.Strings ???
  68.  
  69.    -----------------------------
  70.    -- Argument_String_To_List --
  71.    -----------------------------
  72.  
  73.    function Argument_String_To_List
  74.      (Arg_String : String)
  75.       return Argument_List_Access
  76.    is
  77.       Max_Args : Integer := Arg_String'Length;
  78.       New_Argv : Argument_List (1 .. Max_Args);
  79.       New_Argc : Natural := 0;
  80.       Idx      : Integer;
  81.  
  82.    begin
  83.       Idx := Arg_String'First;
  84.  
  85.       loop
  86.          declare
  87.             Quoted   : Boolean := False;
  88.             Backqd   : Boolean := False;
  89.             Old_Idx  : Integer;
  90.  
  91.          begin
  92.             Old_Idx := Idx;
  93.  
  94.             loop
  95.                --  A vanilla space is the end of an argument
  96.  
  97.                if not Backqd and then not Quoted
  98.                  and then Arg_String (Idx) = ' '
  99.                then
  100.                   exit;
  101.  
  102.                --  Start of a quoted string
  103.  
  104.                elsif not Backqd and then not Quoted
  105.                  and then Arg_String (Idx) = '"'
  106.                then
  107.                   Quoted := True;
  108.  
  109.                --  End of a quoted string and end of an argument
  110.  
  111.                elsif not Backqd and then Quoted
  112.                  and then Arg_String (Idx) = '"'
  113.                then
  114.                   Idx := Idx + 1;
  115.                   exit;
  116.  
  117.                --  Following character is backquoted
  118.  
  119.                elsif Arg_String (Idx) = '\' then
  120.                   Backqd := True;
  121.  
  122.                --  Turn off backquoting after advancing one character
  123.  
  124.                elsif Backqd then
  125.                   Backqd := False;
  126.  
  127.                end if;
  128.  
  129.                Idx := Idx + 1;
  130.                exit when Idx > Arg_String'Last;
  131.             end loop;
  132.  
  133.             --  Found an argument
  134.  
  135.             New_Argc := New_Argc + 1;
  136.             New_Argv (New_Argc) :=
  137.               new String'(Arg_String (Old_Idx .. Idx - 1));
  138.  
  139.             --  Skip extraneous spaces
  140.  
  141.             while Idx <= Arg_String'Last and then Arg_String (Idx) = ' ' loop
  142.                Idx := Idx + 1;
  143.             end loop;
  144.          end;
  145.  
  146.          exit when Idx > Arg_String'Last;
  147.       end loop;
  148.  
  149.       return new Argument_List'(New_Argv (1 .. New_Argc));
  150.    end Argument_String_To_List;
  151.  
  152.    ---------------------
  153.    -- C_String_Length --
  154.    ---------------------
  155.  
  156.    function C_String_Length (S : Address) return Integer is
  157.       function Strlen (S : Address) return Integer;
  158.       pragma Import (C, Strlen, "strlen");
  159.  
  160.    begin
  161.       if S = Null_Address then
  162.          return 0;
  163.       else
  164.          return Strlen (S);
  165.       end if;
  166.    end C_String_Length;
  167.  
  168.    ----------------------
  169.    -- Create_Temp_File --
  170.    ----------------------
  171.  
  172.    procedure Create_Temp_File
  173.      (FD   : out File_Descriptor;
  174.       Name : out Temp_File_Name)
  175.    is
  176.       function Get_Temp_Name (T : Address) return Address;
  177.       pragma Import (C, Get_Temp_Name, "mktemp");
  178.  
  179.       function Open_New_Temp
  180.         (Name  : System.Address;
  181.          Fmode : Mode)
  182.          return  File_Descriptor;
  183.       pragma Import (C, Open_New_Temp, "open_new_temp");
  184.  
  185.    begin
  186.       Name := "GNAT-XXXXXX" & ASCII.NUL;
  187.  
  188.       --  Check for NULL pointer returned by C
  189.  
  190.       if Get_Temp_Name (Name'Address) = Null_Address then
  191.          FD := -1;
  192.       else
  193.          FD := Open_New_Temp (Name'Address, Binary);
  194.       end if;
  195.    end Create_Temp_File;
  196.  
  197.    -----------------
  198.    -- Delete_File --
  199.    -----------------
  200.  
  201.    procedure Delete_File (Name : Address; Success : out Boolean) is
  202.       R : Integer;
  203.  
  204.       function unlink (A : Address) return Integer;
  205.       pragma Import (C, unlink, "unlink");
  206.  
  207.    begin
  208.       R := unlink (Name);
  209.       Success := (R = 0);
  210.    end Delete_File;
  211.  
  212.    ----------------------
  213.    -- File_Time_Stamp  --
  214.    ----------------------
  215.  
  216.    function File_Time_Stamp (FD : File_Descriptor) return OS_Time is
  217.       function File_Time (FD    : File_Descriptor) return OS_Time;
  218.       pragma Import (C, File_Time, "file_time_fd");
  219.  
  220.    begin
  221.       return File_Time (FD);
  222.    end File_Time_Stamp;
  223.  
  224.    ----------------------
  225.    -- File_Time_Stamp  --
  226.    ----------------------
  227.  
  228.    function File_Time_Stamp (Name : String) return OS_Time is
  229.  
  230.       function File_Time (Name : Address) return OS_Time;
  231.       pragma Import (C, File_Time, "file_time_name");
  232.  
  233.       F_Name : String (1 .. Name'Length + 1);
  234.  
  235.    begin
  236.       F_Name (1 .. Name'Length) := Name;
  237.       F_Name (Name'Length + 1)  := ASCII.NUL;
  238.       return File_Time (F_Name'Address);
  239.    end File_Time_Stamp;
  240.  
  241.    ----------------------------
  242.    -- Get_Debuggable_Suffix  --
  243.    ----------------------------
  244.  
  245.    function Get_Debuggable_Suffix return String_Access is
  246.  
  247.       procedure Get_Suffix_Ptr (Length, Ptr : Address);
  248.       pragma Import (C, Get_Suffix_Ptr, "get_debuggable_suffix_ptr");
  249.  
  250.       procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
  251.       pragma Import (C, Strncpy, "strncpy");
  252.  
  253.       Suffix_Ptr    : Address;
  254.       Suffix_Length : Integer;
  255.       Result        : String_Access;
  256.  
  257.    begin
  258.  
  259.       Get_Suffix_Ptr (Suffix_Length'Address, Suffix_Ptr'Address);
  260.  
  261.       Result := new String (1 .. Suffix_Length);
  262.  
  263.       if Suffix_Length > 0 then
  264.          Strncpy (Result.all'Address, Suffix_Ptr, Suffix_Length);
  265.       end if;
  266.  
  267.       return Result;
  268.    end Get_Debuggable_Suffix;
  269.  
  270.    ----------------------------
  271.    -- Get_Executable_Suffix  --
  272.    ----------------------------
  273.  
  274.    function Get_Executable_Suffix return String_Access is
  275.  
  276.       procedure Get_Suffix_Ptr (Length, Ptr : Address);
  277.       pragma Import (C, Get_Suffix_Ptr, "get_executable_suffix_ptr");
  278.  
  279.       procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
  280.       pragma Import (C, Strncpy, "strncpy");
  281.  
  282.       Suffix_Ptr    : Address;
  283.       Suffix_Length : Integer;
  284.       Result        : String_Access;
  285.  
  286.    begin
  287.  
  288.       Get_Suffix_Ptr (Suffix_Length'Address, Suffix_Ptr'Address);
  289.  
  290.       Result := new String (1 .. Suffix_Length);
  291.  
  292.       if Suffix_Length > 0 then
  293.          Strncpy (Result.all'Address, Suffix_Ptr, Suffix_Length);
  294.       end if;
  295.  
  296.       return Result;
  297.    end Get_Executable_Suffix;
  298.  
  299.    ------------------------
  300.    -- Get_Object_Suffix  --
  301.    ------------------------
  302.  
  303.    function Get_Object_Suffix return String_Access is
  304.  
  305.       procedure Get_Suffix_Ptr (Length, Ptr : Address);
  306.       pragma Import (C, Get_Suffix_Ptr, "get_object_suffix_ptr");
  307.  
  308.       procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
  309.       pragma Import (C, Strncpy, "strncpy");
  310.  
  311.       Suffix_Ptr    : Address;
  312.       Suffix_Length : Integer;
  313.       Result        : String_Access;
  314.  
  315.    begin
  316.  
  317.       Get_Suffix_Ptr (Suffix_Length'Address, Suffix_Ptr'Address);
  318.  
  319.       Result := new String (1 .. Suffix_Length);
  320.  
  321.       if Suffix_Length > 0 then
  322.          Strncpy (Result.all'Address, Suffix_Ptr, Suffix_Length);
  323.       end if;
  324.  
  325.       return Result;
  326.    end Get_Object_Suffix;
  327.  
  328.    ------------
  329.    -- Getenv --
  330.    ------------
  331.  
  332.    function Getenv (Name : String) return String_Access is
  333.  
  334.       procedure Get_Env_Value_Ptr (Name, Length, Ptr : Address);
  335.       pragma Import (C, Get_Env_Value_Ptr, "get_env_value_ptr");
  336.  
  337.       procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
  338.       pragma Import (C, Strncpy, "strncpy");
  339.  
  340.       Env_Value_Ptr    : Address;
  341.       Env_Value_Length : Integer;
  342.       F_Name           : String (1 .. Name'Length + 1);
  343.       Result           : String_Access;
  344.  
  345.    begin
  346.       F_Name (1 .. Name'Length) := Name;
  347.       F_Name (Name'Length + 1)  := ASCII.NUL;
  348.  
  349.       Get_Env_Value_Ptr
  350.         (F_Name'Address, Env_Value_Length'Address, Env_Value_Ptr'Address);
  351.  
  352.       Result := new String (1 .. Env_Value_Length);
  353.  
  354.       if Env_Value_Length > 0 then
  355.          Strncpy (Result.all'Address, Env_Value_Ptr, Env_Value_Length);
  356.       end if;
  357.  
  358.       return Result;
  359.    end Getenv;
  360.  
  361.    ------------
  362.    -- GM_Day --
  363.    ------------
  364.  
  365.    function GM_Day (Date : OS_Time) return Day_Type is
  366.       Y  : Year_Type;
  367.       Mo : Month_Type;
  368.       D  : Day_Type;
  369.       H  : Hour_Type;
  370.       Mn : Minute_Type;
  371.       S  : Second_Type;
  372.  
  373.    begin
  374.       GM_Split (Date, Y, Mo, D, H, Mn, S);
  375.       return D;
  376.    end GM_Day;
  377.  
  378.    -------------
  379.    -- GM_Hour --
  380.    -------------
  381.  
  382.    function GM_Hour (Date : OS_Time) return Hour_Type is
  383.       Y  : Year_Type;
  384.       Mo : Month_Type;
  385.       D  : Day_Type;
  386.       H  : Hour_Type;
  387.       Mn : Minute_Type;
  388.       S  : Second_Type;
  389.  
  390.    begin
  391.       GM_Split (Date, Y, Mo, D, H, Mn, S);
  392.       return H;
  393.    end GM_Hour;
  394.  
  395.    ---------------
  396.    -- GM_Minute --
  397.    ---------------
  398.  
  399.    function GM_Minute (Date : OS_Time) return Minute_Type is
  400.       Y  : Year_Type;
  401.       Mo : Month_Type;
  402.       D  : Day_Type;
  403.       H  : Hour_Type;
  404.       Mn : Minute_Type;
  405.       S  : Second_Type;
  406.  
  407.    begin
  408.       GM_Split (Date, Y, Mo, D, H, Mn, S);
  409.       return Mn;
  410.    end GM_Minute;
  411.  
  412.    --------------
  413.    -- GM_Month --
  414.    --------------
  415.  
  416.    function GM_Month (Date : OS_Time) return Month_Type is
  417.       Y  : Year_Type;
  418.       Mo : Month_Type;
  419.       D  : Day_Type;
  420.       H  : Hour_Type;
  421.       Mn : Minute_Type;
  422.       S  : Second_Type;
  423.  
  424.    begin
  425.       GM_Split (Date, Y, Mo, D, H, Mn, S);
  426.       return Mo;
  427.    end GM_Month;
  428.  
  429.    ---------------
  430.    -- GM_Second --
  431.    ---------------
  432.  
  433.    function GM_Second (Date : OS_Time) return Second_Type is
  434.       Y  : Year_Type;
  435.       Mo : Month_Type;
  436.       D  : Day_Type;
  437.       H  : Hour_Type;
  438.       Mn : Minute_Type;
  439.       S  : Second_Type;
  440.  
  441.    begin
  442.       GM_Split (Date, Y, Mo, D, H, Mn, S);
  443.       return S;
  444.    end GM_Second;
  445.  
  446.    --------------
  447.    -- GM_Split --
  448.    --------------
  449.  
  450.    procedure GM_Split
  451.      (Date   : OS_Time;
  452.       Year   : out Year_Type;
  453.       Month  : out Month_Type;
  454.       Day    : out Day_Type;
  455.       Hour   : out Hour_Type;
  456.       Minute : out Minute_Type;
  457.       Second : out Second_Type)
  458.    is
  459.       procedure To_GM_Time
  460.         (P_Time_T, P_Year, P_Month, P_Day, P_Hours, P_Mins, P_Secs : Address);
  461.       pragma Import (C, To_GM_Time, "to_gm_time");
  462.  
  463.       T  : OS_Time := Date;
  464.       Y  : Integer;
  465.       Mo : Integer;
  466.       D  : Integer;
  467.       H  : Integer;
  468.       Mn : Integer;
  469.       S  : Integer;
  470.  
  471.    begin
  472.       --  Use the global lock because To_GM_Time is not thread safe.
  473.  
  474.       Locked_Processing : begin
  475.          SSL.Lock_Task.all;
  476.          To_GM_Time
  477.            (T'Address, Y'Address, Mo'Address, D'Address,
  478.             H'Address, Mn'Address, S'Address);
  479.          SSL.Unlock_Task.all;
  480.  
  481.       exception
  482.          when others =>
  483.             SSL.Unlock_Task.all;
  484.             raise;
  485.       end Locked_Processing;
  486.  
  487.       Year   := Y + 1900;
  488.       Month  := Mo + 1;
  489.       Day    := D;
  490.       Hour   := H;
  491.       Minute := Mn;
  492.       Second := S;
  493.    end GM_Split;
  494.  
  495.    -------------
  496.    -- GM_Year --
  497.    -------------
  498.  
  499.    function GM_Year (Date : OS_Time) return Year_Type is
  500.       Y  : Year_Type;
  501.       Mo : Month_Type;
  502.       D  : Day_Type;
  503.       H  : Hour_Type;
  504.       Mn : Minute_Type;
  505.       S  : Second_Type;
  506.  
  507.    begin
  508.       GM_Split (Date, Y, Mo, D, H, Mn, S);
  509.       return Y;
  510.    end GM_Year;
  511.  
  512.    ------------------
  513.    -- Is_Directory --
  514.    ------------------
  515.  
  516.    function Is_Directory (Name : String) return Boolean is
  517.  
  518.       function Is_Directory (Name : Address) return Integer;
  519.       pragma Import (C, Is_Directory, "is_directory");
  520.  
  521.       F_Name : String (1 .. Name'Length + 1);
  522.  
  523.    begin
  524.       F_Name (1 .. Name'Length) := Name;
  525.       F_Name (Name'Length + 1)  := ASCII.NUL;
  526.       return Is_Directory (F_Name'Address) /= 0;
  527.    end Is_Directory;
  528.  
  529.    ---------------------
  530.    -- Is_Regular_File --
  531.    ---------------------
  532.  
  533.    function Is_Regular_File (Name : String) return Boolean is
  534.  
  535.       function Is_Regular_File (Name : Address) return Integer;
  536.       pragma Import (C, Is_Regular_File, "is_regular_file");
  537.  
  538.       F_Name : String (1 .. Name'Length + 1);
  539.  
  540.    begin
  541.       F_Name (1 .. Name'Length) := Name;
  542.       F_Name (Name'Length + 1)  := ASCII.NUL;
  543.       return Is_Regular_File (F_Name'Address) /= 0;
  544.    end Is_Regular_File;
  545.  
  546.    ----------------------
  547.    -- Is_Writable_File --
  548.    ----------------------
  549.  
  550.    function Is_Writable_File (Name : String) return Boolean is
  551.  
  552.       function Is_Writable_File (Name : Address) return Integer;
  553.       pragma Import (C, Is_Writable_File, "is_writable_file");
  554.  
  555.       F_Name : String (1 .. Name'Length + 1);
  556.  
  557.    begin
  558.       F_Name (1 .. Name'Length) := Name;
  559.       F_Name (Name'Length + 1) := ASCII.NUL;
  560.       return Is_Writable_File (F_Name'Address) /= 0;
  561.    end Is_Writable_File;
  562.  
  563.    -------------------------
  564.    -- Locate_Exec_On_Path --
  565.    -------------------------
  566.  
  567.    function Locate_Exec_On_Path
  568.      (Exec_Name : String)
  569.       return      String_Access
  570.    is
  571.       function Locate_Exec_On_Path (C_Exec_Name : Address) return Address;
  572.       pragma Import (C, Locate_Exec_On_Path, "locate_exec_on_path");
  573.  
  574.       C_Exec_Name  : String (1 .. Exec_Name'Length + 1);
  575.       Path_Addr    : Address;
  576.       Path_Len     : Integer;
  577.  
  578.    begin
  579.       C_Exec_Name (1 .. Exec_Name'Length)   := Exec_Name;
  580.       C_Exec_Name (C_Exec_Name'Last)        := ASCII.NUL;
  581.  
  582.       Path_Addr := Locate_Exec_On_Path (C_Exec_Name'Address);
  583.       Path_Len  := C_String_Length (Path_Addr);
  584.  
  585.       if Path_Len = 0 then
  586.          return null;
  587.       else
  588.          return To_Path_String_Access (Path_Addr, Path_Len);
  589.       end if;
  590.    end Locate_Exec_On_Path;
  591.  
  592.    -------------------------
  593.    -- Locate_Regular_File --
  594.    -------------------------
  595.  
  596.    function Locate_Regular_File
  597.      (File_Name : String;
  598.       Path      : String)
  599.       return      String_Access
  600.    is
  601.       function Locate_Regular_File
  602.         (C_File_Name, Path_Val : Address) return Address;
  603.       pragma Import (C, Locate_Regular_File, "locate_regular_file");
  604.  
  605.       C_File_Name  : String (1 .. File_Name'Length + 1);
  606.       Path_Val     : String (1 .. Path'Length + 1);
  607.       Path_Addr    : Address;
  608.       Path_Len     : Integer;
  609.  
  610.    begin
  611.       C_File_Name (1 .. File_Name'Length)   := File_Name;
  612.       C_File_Name (C_File_Name'Last)        := ASCII.NUL;
  613.       Path_Val  (1 .. Path'Length)          := Path;
  614.       Path_Val  (Path_Val'Last)             := ASCII.NUL;
  615.  
  616.       Path_Addr := Locate_Regular_File (C_File_Name'Address, Path_Val'Address);
  617.       Path_Len  := C_String_Length (Path_Addr);
  618.  
  619.       if Path_Len = 0 then
  620.          return null;
  621.       else
  622.          return To_Path_String_Access (Path_Addr, Path_Len);
  623.       end if;
  624.    end Locate_Regular_File;
  625.  
  626.    ------------------------
  627.    -- Non_Blocking_Spawn --
  628.    ------------------------
  629.  
  630.    function Non_Blocking_Spawn
  631.      (Program_Name : String;
  632.       Args         : Argument_List)
  633.       return         Process_Id
  634.    is
  635.       Junk : Boolean;
  636.       Pid  : Process_Id;
  637.  
  638.    begin
  639.       Spawn_Internal (Program_Name, Args, Junk, Pid, Blocking => False);
  640.       return Pid;
  641.    end Non_Blocking_Spawn;
  642.  
  643.    -----------
  644.    -- Spawn --
  645.    -----------
  646.  
  647.    procedure Spawn
  648.      (Program_Name : String;
  649.       Args         : Argument_List;
  650.       Success      : out Boolean)
  651.    is
  652.       Junk : Process_Id;
  653.  
  654.    begin
  655.       Spawn_Internal (Program_Name, Args, Success, Junk, Blocking => True);
  656.    end Spawn;
  657.  
  658.    --------------------
  659.    -- Spawn_Internal --
  660.    --------------------
  661.  
  662.    procedure Spawn_Internal
  663.      (Program_Name : String;
  664.       Args         : Argument_List;
  665.       Success      : out Boolean;
  666.       Pid          : out Process_Id;
  667.       Blocking     : Boolean)
  668.    is
  669.       Arg_List : array (1 .. Args'Length + 2) of Address;
  670.  
  671.       Arg : String_Access;
  672.  
  673.       function Portable_Spawn (Args : Address) return Integer;
  674.       pragma Import (C, Portable_Spawn, "portable_spawn");
  675.  
  676.       function Portable_No_Block_Spawn (Args : Address) return Process_Id;
  677.       pragma Import (C, Portable_No_Block_Spawn, "portable_no_block_spawn");
  678.  
  679.    begin
  680.       Arg := new String (1 .. Program_Name'Length + 1);
  681.       Arg (1 .. Program_Name'Length) := Program_Name;
  682.       Arg (Arg'Last)                 := ASCII.NUL;
  683.       Arg_List (1)                   := Arg.all'Address;
  684.  
  685.       for J in 1 .. Args'Length loop
  686.          Arg := new String (1 .. Args (J + Args'First - 1)'Length + 1);
  687.          Arg (1 .. Arg'Last - 1) := Args (J + Args'First - 1).all;
  688.          Arg (Arg'Last) := ASCII.NUL;
  689.          Arg_List (J + 1) := Arg.all'Address;
  690.       end loop;
  691.  
  692.       Arg_List (Arg_List'Last) := Null_Address;
  693.  
  694.       if Blocking then
  695.          Pid     := Invalid_Pid;
  696.          Success := (Portable_Spawn (Arg_List'Address) = 0);
  697.       else
  698.          Pid     := Portable_No_Block_Spawn (Arg_List'Address);
  699.          Success := (Pid /= Invalid_Pid);
  700.       end if;
  701.  
  702.    end Spawn_Internal;
  703.  
  704.    ---------------------------
  705.    -- To_Path_String_Access --
  706.    ---------------------------
  707.  
  708.    function To_Path_String_Access
  709.      (Path_Addr : Address;
  710.       Path_Len  : Integer)
  711.       return String_Access is
  712.  
  713.       subtype Path_String is String (1 .. Path_Len);
  714.       type    Path_String_Access is access Path_String;
  715.  
  716.       function Address_To_Access is new
  717.         Unchecked_Conversion (Source => Address,
  718.                               Target => Path_String_Access);
  719.  
  720.       Path_Access : Path_String_Access := Address_To_Access (Path_Addr);
  721.  
  722.       Return_Val  : String_Access;
  723.  
  724.    begin
  725.       Return_Val := new String (1 .. Path_Len);
  726.  
  727.       for J in 1 .. Path_Len loop
  728.          Return_Val (J) := Path_Access (J);
  729.       end loop;
  730.  
  731.       return Return_Val;
  732.    end To_Path_String_Access;
  733.  
  734.    ------------------
  735.    -- Wait_Process --
  736.    ------------------
  737.  
  738.    procedure Wait_Process (Pid : out Process_Id; Success : out Boolean) is
  739.       Status : Integer;
  740.  
  741.       function Portable_Wait (S : Address) return Process_Id;
  742.       pragma Import (C, Portable_Wait, "portable_wait");
  743.  
  744.    begin
  745.       Pid := Portable_Wait (Status'Address);
  746.       Success := (Status = 0);
  747.    end Wait_Process;
  748.  
  749. end GNAT.OS_Lib;
  750.