!standard A.18 04-04-02 AI95-00370/02 !class amendment 03-12-20 !status work item 03-12-20 !status received 03-12-20 !priority Medium !difficulty Medium !subject Environment variables !summary Add a new standard package, Ada.Environment, to access environment variables. !problem A vast number of operating systems support environment variables, including the various Unixes, GNU/Linux, MS-DOS, Windows, and Mac OS X. It's possible to create the interfaces to the C libraries, but a standard interface would improve portability and usability of the language. !proposal (See wording.) !discussion This proposal provides a minimum set of capabilities that should be straightforward to implement on modern operating systems, most of the time by a simple skin on top of the C library. We do not provide subprograms equivalent to all of the functions provided by C, we use a building block approach instead. For instance there is not equivalent to clearenv(), but there is a way to clear one particular environment variable. This package can potentially result in race conditions, because the environment variables are really shared resources. For instance, calling Count, then Name with a Number less than Count, might well raise Constraint_Error if some environment variables have been undefined in the meantime. Users who want to do these things will need to call Environment from within a protected object. Also, concurrent calls to operations of Environment are a dicey proposition, because the operating system interfaces for accessing environment variables may or may not be thread-safe. We don't want to force implementations to use a protected object to implement this package, as it is expected that most of its uses will not involve concurrent access. So we are making it erroneous to perform concurrent calls on the operations declared here. Based on the normative description of Environment, this package might well be implemented as a mere string-to-string map. We try to nail down the semantics of environment variables a bit more precisely in an Implementation Advice, where we can talk about subprocesses and the like. If the operating system has a notion of environment variable then it must implement this package with the proper semantics. If however there is no such notion in the operating system (or if there is no operating system) we give a permission to provide a "dummy" implementation of Environment. !wording Add after A.15: A.16 The Package Environment The package Environment allows a program to read or modify the environment variables. Environment variables are name-value pairs, where both the name and value are strings, and where a variable is uniquely identified by its name. The definition of what constitutes an "environment variable", and the meaning of the name and value, are implementation defined. Static Semantics The library package Ada.Environment has the following declaration: package Ada.Environment is pragma Pure (Environment); function Count return Natural; function Name (Number : in Positive) return String; function Value (Name : in String) return String; function Value (Number : in Positive) return String; function Exists (Name : in String) return Boolean; procedure Set (Name : in String; Value : in String); procedure Clear (Name : in String); procedure Clear (Number : in Positive); end Ada.Environment; Dynamic Semantics function Count return Natural; If the external execution environment supports environment variables, Count returns the number of environment variables currently defined. Otherwise it returns 0. function Name (Number : in Positive) return String; If the external execution environment supports environment variables, then Name returns the name of the environment variable at position Number. If Number is outside the range 1..Count, then Constraint_Error is propagated. function Value (Name : in String) return String; If the external execution environment supports environment variables, then Value returns the value of the environment variable with name Name. If Name is not the name of an environment variable, then Constraint_Error is propagated. function Value (Number : in Positive) return String; Equivalent to Value (Name (Number)). function Exists (Name : in String) return Boolean; If the external execution environment supports environment variables, then Exists returns True if an environment variable with name Name is currently defined. Otherwise it returns False. procedure Set (Name : in String; Value : in String); If the external execution environment supports environment variables, then Set defines an environment variable with name Name and value Value, possibly overwriting a preexisting environment variable with the same name. Otherwise Constraint_Error is propagated. In the implementation defined circumstances where the external execution environment does not allow the definition of an environment variable with the given name and value, Constraint_Error is propagated. It is implementation defined whether there exist values for which the call Set(Name, Value) has the same effect as Clear (Name). Calling Set changes in an unspecified manner the association between names and numbers exposed by function Name. procedure Clear (Name : in String); If the external execution environment supports environment variables, then Clear deletes the environment variable with name Name, if one existed. Otherwise Constraint_Error is propagated. Immediately after this procedure returns, the expression Exists(Name) is False. Calling Clear changes in an unspecified manner the association between names and numbers exposed by function Name. procedure Clear (Number : in Positive); Equivalent to Clear (Name (Number)). Implementation Permissions An implementation running on a system which has no concept corresponding to environment variables is permitted to define the operations of package Environment with the semantics corresponding to the case where "the external execution environment does not support environment variables". An alternative declaration is allowed for package Environment if different functionality is appropriate for the external execution environment. Implementation Advice If it chooses not to take advantage of the first permission above, an implementation should provide a mechanism to initialize a non-empty set of environment variables at the beginning of the execution of a partition. Also, if the execution environment has a concept of subprocess, the currently defined environment variables should be used to initialize the environment variables of the subprocess. Erroneous Execution Making concurrent calls to operations of package Environment results in erroneous execution. <> <> <> !example The following program prints out the environment, clears it, and defines a new environment variable: for V in 1 .. Ada.Environment.Count loop Ada.Text_Io.Put_Line (Ada.Environment.Name (V) & "=" & Ada.Environment.Value (V)); Ada.Environment.Clear (V); end loop; Ada.Environment.Set (Name => "ADA", Value => "05"); --!corrigendum !ACATS test Create ACATS C-Tests for this facility. !appendix From: Pascal Orby Sent: Sunday, December 21, 2003 2:12 AM > !subject Add standard interface for environment variables Did you check the AI database, I seem to remember that a proposal in this direction has already been made, no ? **************************************************************** [Editor's note: AI-371 contains a different proposal for such a package. For the sake of making it easier to evaluate the two proposals, it is copied here.] 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. ****************************************************************