!standard A.18 04-02-05 AI95-00371/01 !class amendment 03-12-30 !status work item 03-12-30 !status received 03-12-30 !priority Medium !difficulty Medium !subject New hierarchy for OS-dependent services !summary A new root package for language defined units is added to the language. It contains information about the underlying operating system, and its descendents are assumed to provide operating-system dependent operations. !problem Currently, children of Ada are units whose definition does not depend on the target system, and children of System are units whose definition has dependencies on the hardware. There is no hierachy for units that depend on the host operating system. There was only one of these (Command_Line) in Ada95, but more such units are bound to appear in Ada05 (Directories, possibly others). !proposal Add a new package named "OS" to serve as the root of OS-dependent services. It is understood that part of the semantics of the units rooted at OS can have variations according to the underlying operating system. Packages that fall under this definition (Command_Line, Directories) are made children of OS. Moreover, packages providing access to commonly found services of operating systems, like environment variables and process execution, are proposed. !wording The following package exists: package OS is function OS_Name return String; function OS_Version return String; Unsupported : exception; end OS; Both OS_Name and OS_Version return implementation-defined strings, with lower bound of 1. The string returned by OS_Name should not change when the underlying operating system changes version. The string returned by OS_Version should change when the underlying operating system changes version. The exception Unsupported is raised by subprograms in this package or its children whenever an operation cannot be provided by the operating system. Packages Command_Line and Directories are children of OS, i.e. they are named OS.Command_Line and OS.Directories. The following renaming exists: with OS.Command_Line; package Ada.Command_Line renames OS.Command_Line; The following package exists: package Environment is procedure Set_Variable (Name : String; To : String); function Get_Variable (Name : String) return String; function Path return String; function Locate_Executable (Name : String) return String; function Locate_Regular_File (Name : String; Path : String := "") return String; end Environment; This package provides access to environment variables. An environment variable is a value external to the program, which has a name. If the operating system does not support the notion of environment variables, calls to Get_Variable will always return the null string, and calls to Set_Variable will raise Unsupported. The function Path returns an implementation defined string which defines the location of executable files. If the operating system does not support the notion of path, the null string is returned. The function Locate_Executable returns a string corresponding to the full name of the specified executable name, following the operating system's conventions for locating executables. The exception Ada.IO_Exceptions.Name_Error is raised if no executable with the given name can be identified. The function Locate_Regular_File returns a string corresponding to the full name of the specified file name, following the operating system's conventions for locating data files. The exception Ada.IO_Exceptions.Name_Error is raised if no file with the given name can be identified. The following package exists: with OS.Command_Line; package Processes is type Process_ID is private; Null_Process_ID : constant Process_ID; procedure Spawn (Command : in String; Parameters : in String := ""; Result : out OS.Command_Line.Exit_Status); function Non_Blocking_Spawn (Command : in String; Parameters : in String = "") return Process_ID; procedure Execute(Command_Line : in String; Result : out OS.Command_Line.Exit_Status); function Non_Blocking_Execute (Command_Line : in String; Result : out OS.Command_Line.Exit_Status) return Process_ID; procedure Wait_Process (Pid : in Process_Id; Result : out OS.Command_Line.Exit_Status); procedure Wait_Any_Process (Pid : out Process_Id; Result : out OS.Command_Line.Exit_Status); No_Such_Pid : exception; private -- Not specified by the language end Processes; A value of the type Process_ID identifies a subprocess, as started by the Spawn, Non_Blocking_Spawn, Execute and Non_Blocking_Execute subprograms in this package. The constant Null_Process_ID does not identify any process. Each object of the type Process_ID is default initialized to the value Null_Process_ID. The procedure Spawn starts a new process, executing the executable whose name is given as Command, with a parameter string given by Parameters. It blocks until the process terminates. The exit status of the process is returned in Result. It is implementation defined if the name given in Command is subject to the rules for finding executables. If the process could not be started (for example because Command does not identify an executable, of for OS dependent reasons), Failure is returned in Result. The procedure Non_Blocking Spawn starts a new process, executing the executable whose name is given as Command, with a parameter string given by Parameters. It blocks until the process has started, and returns the Process_IO of the child process. If the process could not be started (for example because Command does not identify an executable, of for OS dependent reasons), Null_Task_ID is returned. The subprograms Execute and Non_Blocking_Execute behave like Spawn and Non_Blocking_Spawn respectively, except that the process is started by a string given as the Command_Line parameter, with the syntax of Shell commands appropriate to the operating system. The syntax of the Command_Line parameter is implementation defined. On operating systems where it makes sense, it is expected that the process is started as a shell command. The procedure Wait_Process blocks until the process specified by Pid has terminated. The exit status of the process is returned in Result. If Pid is Null_Pid, or identifies a process for which Wait_Process has already been called, or which has been already returned by Wait_Any_Process, the exception No_Such_Pid is raised. The procedure Wait_Any_Process blocks until one of the processes previously started by one of the Non_Blocking_Spawn or Non_Blocking_Execute procedures has terminated. The exit status of the process is returned in Result. If Pid is Null_Pid, or there is no more process to wait for, the exception No_Such_Pid is raised. Implementation requirement The implementation of Wait_Process must be task safe in the following sense: if two tasks call Wait_Process simultaneously on the same Pid, one of them receives No_Such_Pid, and the other one behaves as specified. Which task receives the exception is implementation defined. The implementation of Wait_Any_Process must be task safe in the following sense: if two tasks call Wait_Any_Process simultaneously, they will never receive the same Pid. !discussion OS_Version is often referred to as one or two numbers, like major version number and minor version number. But all operating systems do not necessarily follow this convention, and there are sometimes variants, like in 3.2a. Providing a string that can be parsed if necessary seemed the most general solution. !example --!corrigendum !ACATS test !appendix From: Randy Brukardt Sent: Thursday, February 5, 2004 10:12 PM A couple of comments on this proposal (now AI-371). ... > Currently, children of Ada are units whose definition does not depend on > the target system, and children of System are units whose definition has > dependencies on the hardware. I don't see where you get this statement from. The existence of Command_Line certainly says it's not true, but even ignoring Command_Line, claiming that any of the IO packages "do not depend on the target system" requires an amazing stretch of imagination. > There is no hierachy for units that depend on the host operating system. > There was only one of these (Command_Line) in Ada95, but more such units > are bound to appear in Ada05 (Directories, possibly others). Certainly Directories belongs with the other IO packages! It's all about manipulating file names - it's pretty useless without being able to do something with the names afterwards. > !proposal > > Add a new package named "OS" to serve as the root of OS-dependent > services. It is understood that part of the semantics of the units > rooted at OS can have variations according to the underlying operating > system. Creating new top-level packages is exactly what the Ada root was intended to avoid. With this proposal, any program that has a package named OS is instantantly unable to use Ada 200Y. Children of Ada are essentially reserved for the Standard (and to a lesser extent, implementers) to use, so adding new packages there is much less to cause harm. (And we can fairly quickly find out about any conflicts.) Moreover, the proposed name implies that an operating system is present, but certainly at least some of the facilities can make useful sense without one (on a bare-machine implementation of Ada). Finally, there doesn't seem to be enough contents in this hierarchy to justify a new root. Just put the additional packages into Ada. --- The Environment package was also proposed by David Wheeler via SIGAda (see AI-370), so I expect that we'll end up discussing it in the context of that AI. I don't much like either proposal, for different reasons, but if I had to choose one, I'd prefer this one. But, in any case, the functionality is useful (this was the third of the three "packages to standardize" that I identified when we started the amendment process - I never had enough energy to propose one. Spawn functionality makes sense. I'm not sure I'd go as far as this package does (we just provide Spawn, with a non-blocking flag, and a Wait for the non-blocking version; Execute is interesting, but very hard to implement portably on Windows). ****************************************************************