Matthew Heaney's solution works if the environment variable exists, but raises an exception if it does not. I offer this refinement of Matthew's solution, where the exception is raised, but with information supplied which quickly pinpoints the cause of the exception. If Matthew's solution were incorporated in a large program, it might take some time for the user to etermine what is wrong. ---- begin source code ---- with Ada.Exceptions; with Interfaces.C.Strings; function Getenv (Name : String) return String is use Interfaces.C; use Interfaces.C.Strings; C_Name_Buf : aliased Char_Array := To_C (Name); C_Name : constant Chars_Ptr := To_Chars_Ptr (C_Name_Buf'Unchecked_Access); function C_Getenv (Name : Chars_Ptr) return Chars_Ptr; pragma Import (C, C_Getenv, "getenv"); C_Val : constant Chars_Ptr := C_Getenv (C_Name); begin if C_Val = Null_Ptr then Ada.Exceptions.Raise_Exception (E => Dereference_Error'identity, Message => "Environment variable """ & Name & """ does not exist"); end if; return To_Ada (Value (C_Val)); end Getenv; --- end source code --- Actually, there are two other solutions worthy of mention, viz.: 1. There is a package Gnat.OS_Lib in GNAT which provides a compiler-specific solution which does not raise the exception, but does not distinguish between the case of the environment variable being defined but empty, and the case where it's undefined. Furthermore, the GNAT solution is an allocator function which means that the memory deallocation is the responsibility of the caller. 2. This third solution is my preference -- the POSIX binding provided by florist -- available at ftp://ftp.cs.fsu.edu/pub/PART/FLORIST/ This binding has the Boolean function POSIX.Process_Environment.Is_Environment_Variable which permits testing for existence before getting the value with a call to POSIX.Process_Environment.Environment_Value_Of. Not only does this binding provide the process environment functionality, it has clean interfaces to many OS-related runtime library functions. One final comment -- The use of verbs as the names of functions is not considered good style by many authorities. The POSIX bindings adhere to the following subprogram naming conventions: Procedure names -- verb_phrase -- e.g. Set_Environment_Variable Boolean functions -- predicate phrase -- e.g Is_Environment_Variable Non-Boolean functions -- Noun_Phrase -- e.g. Environment_Value_Of These naming conventions -- along with the naming conventions for types, objects and tasks go a long way toward making code more readily comprehensible -- either to the author some time after writing it -- or to the unfortunate maintainer who has never seen the code before he has to fix or enhance it.