note description: "The objects available from the environment at time of execution" library: "Free implementation of ELKS library" status: "See notice at end of class." legal: "See notice at end of class." date: "$Date: 2019-02-18 11:07:51 +0000 (Mon, 18 Feb 2019) $" revision: "$Revision: 102848 $" class EXECUTION_ENVIRONMENT inherit NATIVE_STRING_HANDLER create default_create feature -- Access Arguments: ARGUMENTS_32 -- Arguments that were used to start current execution. once create Result ensure instance_free: class end Command_line: ARGUMENTS obsolete "Use `arguments' instead for handling Unicode command lines. [2017-05-31]" -- Command line that was used to start current execution once create Result ensure instance_free: class end current_working_path: PATH -- Directory of current execution. local l_count, l_nbytes: INTEGER_32 l_managed: MANAGED_POINTER do l_count := 50 create l_managed.make (l_count) l_nbytes := eif_dir_current (l_managed.item, l_count) if l_nbytes = -1 then create Result.make_from_string (".") else if l_nbytes > l_count then l_count := l_nbytes; l_managed.resize (l_count) l_nbytes := eif_dir_current (l_managed.item, l_count) end if l_nbytes > 0 and l_nbytes <= l_count then create Result.make_from_pointer (l_managed.item) else create Result.make_from_string (".") end end ensure instance_free: class result_not_void: Result /= Void end current_working_directory: STRING_8 obsolete "Use `current_working_path' instead to support Unicode path. [2017-05-31]" -- Directory of current execution. -- Execution of this query on concurrent threads will result in -- an unspecified behavior. local l_count, l_nbytes: INTEGER_32 l_managed: MANAGED_POINTER do l_count := 50 create l_managed.make (l_count) l_nbytes := eif_dir_current (l_managed.item, l_count) if l_nbytes = -1 then Result := "." else if l_nbytes > l_count then l_count := l_nbytes; l_managed.resize (l_count) l_nbytes := eif_dir_current (l_managed.item, l_count) end if l_nbytes > 0 and l_nbytes <= l_count then Result := File_info.pointer_to_file_name_8 (l_managed.item) else Result := "." check False end end end ensure instance_free: class result_not_void: Result /= Void end Default_shell: STRING_32 -- Default shell once if attached item ("SHELL") as l_shell then Result := l_shell else create Result.make_empty end ensure instance_free: class end get (s: STRING_8): detachable STRING_8 obsolete "Use `item' instead to retrieve Unicode environment variables. [2017-05-31]" -- Value of s if it is an environment variable and has been set; -- void otherwise. require s_exists: s /= Void not_has_null_character: not s.has ('%U') do if attached item (s) as l_val then Result := l_val.as_string_8 end ensure instance_free: class end item (s: READABLE_STRING_GENERAL): detachable STRING_32 -- Value of s if it is an environment variable and has been set; -- void otherwise. require s_exists: s /= Void not_has_null_character: not s.has ('%U'.to_character_32) local l_key: NATIVE_STRING c_string: POINTER do create l_key.make (s) c_string := eif_getenv (l_key.item) if not c_string.is_default_pointer then Result := (create {NATIVE_STRING}.make_from_pointer (c_string)).string end ensure instance_free: class end Home_directory_path: detachable PATH -- Directory name corresponding to the home directory. require home_directory_supported: Operating_environment.home_directory_supported local l_count, l_nbytes: INTEGER_32 l_managed: MANAGED_POINTER once l_count := 50 create l_managed.make (l_count) l_nbytes := eif_home_directory_name_ptr (l_managed.item, l_count) if l_nbytes > l_count then l_count := l_nbytes; l_managed.resize (l_count) l_nbytes := eif_home_directory_name_ptr (l_managed.item, l_count) end if l_nbytes > 0 and l_nbytes <= l_count then create Result.make_from_pointer (l_managed.item) end ensure instance_free: class end User_directory_path: detachable PATH -- Directory name corresponding to the user directory -- On Windows: C:\Users\manus\Documents -- On Unix & Mac: $HOME -- Otherwise Void local l_count, l_nbytes: INTEGER_32 l_managed: MANAGED_POINTER once l_count := 50 create l_managed.make (50) l_nbytes := eif_user_directory_name_ptr (l_managed.item, l_count) if l_nbytes > l_count then l_count := l_nbytes; l_managed.resize (l_count) l_nbytes := eif_user_directory_name_ptr (l_managed.item, l_count) end if l_nbytes > 0 and l_nbytes <= l_count then create Result.make_from_pointer (l_managed.item) end if Result /= Void and then not Result.is_empty then elseif Operating_environment.home_directory_supported and then attached Home_directory_path as l_home then Result := l_home else Result := Void end ensure instance_free: class end Temporary_directory_path: detachable PATH -- Temporary directory name. -- On Windows: %SystemDrive%\Users\%USERNAME%\AppData\Local\Temp (%USERPROFILE%\AppData\Local\Temp). -- On Unix: /tmp and /var/tmp. -- On VMS: /sys$scratch -- Otherwise Void local l_count, l_nbytes: INTEGER_32 ns: NATIVE_STRING once l_count := 10 create ns.make_empty (l_count) l_nbytes := eif_temporary_directory_name_ptr (ns.item, l_count) if l_nbytes > l_count then l_count := l_nbytes create ns.make_empty (l_count) l_nbytes := eif_temporary_directory_name_ptr (ns.item, l_count) end if l_nbytes > 0 and l_nbytes <= l_count then create Result.make_from_string (ns.string) end ensure instance_free: class end Home_directory_name: detachable STRING_8 obsolete "Use `home_directory_path' instead to support Unicode path. [2017-05-31]" -- Directory name corresponding to the home directory. require home_directory_supported: Operating_environment.home_directory_supported local l_count, l_nbytes: INTEGER_32 l_managed: MANAGED_POINTER once l_count := 50 create l_managed.make (l_count) l_nbytes := eif_home_directory_name_ptr (l_managed.item, l_count) if l_nbytes > l_count then l_count := l_nbytes; l_managed.resize (l_count) l_nbytes := eif_home_directory_name_ptr (l_managed.item, l_count) end if l_nbytes > 0 and l_nbytes <= l_count then Result := File_info.pointer_to_file_name_8 (l_managed.item) end ensure instance_free: class end User_directory_name: detachable STRING_8 obsolete "Use `user_directory_path' instead to support Unicode paths. [2017-05-31]" -- Directory name corresponding to the user directory -- On Windows: C:\Users\manus\Documents -- On Unix & Mac: $HOME -- Otherwise Void local l_count, l_nbytes: INTEGER_32 l_managed: MANAGED_POINTER once l_count := 50 create l_managed.make (50) l_nbytes := eif_user_directory_name_ptr (l_managed.item, l_count) if l_nbytes > l_count then l_count := l_nbytes; l_managed.resize (l_count) l_nbytes := eif_user_directory_name_ptr (l_managed.item, l_count) end if l_nbytes > 0 and l_nbytes <= l_count then Result := File_info.pointer_to_file_name_8 (l_managed.item) end if Result /= Void and then not Result.is_empty then elseif Operating_environment.home_directory_supported and then attached Home_directory_name as l_home then Result := l_home else Result := Void end ensure instance_free: class end Root_directory_name: STRING_8 -- Directory name corresponding to the root directory. require root_directory_supported: Operating_environment.root_directory_supported once if {PLATFORM}.is_windows then Result := "\" elseif {PLATFORM}.is_vms then Result := "[000000]" else Result := "/" end ensure instance_free: class result_not_void: Result /= Void end starting_environment_variables: HASH_TABLE [STRING_8, STRING_8] obsolete "Use starting_environment which support unicode. [2017-05-31]" -- Table of environment variables when current process starts, -- indexed by variable name local l_ptr: POINTER i: INTEGER_32 ns: NATIVE_STRING do create Result.make (40) from i := 0 l_ptr := i_th_environ (i) create ns.make_empty (0) until l_ptr.is_default_pointer loop ns.set_shared_from_pointer (l_ptr) if attached separated_variables (ns.string) as l_curr_var then Result.force (l_curr_var.value.as_string_8, l_curr_var.key.as_string_8) end i := i + 1 l_ptr := i_th_environ (i) end ensure instance_free: class result_attached: Result /= Void end starting_environment: HASH_TABLE [STRING_32, STRING_32] -- Table of environment variables when current process starts, -- indexed by variable name local l_ptr: POINTER i: INTEGER_32 ns: NATIVE_STRING do create Result.make (40) from i := 0 l_ptr := i_th_environ (i) create ns.make_empty (0) until l_ptr.is_default_pointer loop ns.set_shared_from_pointer (l_ptr) if attached separated_variables (ns.string) as l_curr_var then Result.force (l_curr_var.value, l_curr_var.key) end i := i + 1 l_ptr := i_th_environ (i) end ensure instance_free: class result_attached: Result /= Void end available_cpu_count: NATURAL_32 -- Number of available CPUs. external "C inline use <eif_system.h>" alias "[ #ifdef EIF_WINDOWS SYSTEM_INFO SysInfo; ZeroMemory (&SysInfo, sizeof (SYSTEM_INFO)); GetSystemInfo (&SysInfo); return (EIF_NATURAL_32) SysInfo.dwNumberOfProcessors; #elif defined(EIF_MACOSX) /* MacOS X < 10.4 */ int nm [2]; size_t len = 4; uint32_t count; nm [0] = CTL_HW; nm [1] = HW_AVAILCPU; sysctl (nm, 2, &count, &len, NULL, 0); if(count < 1) { nm[1] = HW_NCPU; sysctl(nm, 2, &count, &len, NULL, 0); if (count < 1) {count = 1;} } return (EIF_NATURAL_32) count; #else /* Linux, Solaris, AIX, Mac OS X >=10.4 (i.e. Tiger onwards), ... */ return (EIF_NATURAL_32) sysconf(_SC_NPROCESSORS_ONLN); #endif ]" ensure instance_free: class end feature -- Status return_code: INTEGER_32 -- Status code set by last call to system or put feature -- Status setting change_working_directory (path: READABLE_STRING_GENERAL) obsolete "Use `change_working_path' instead to support Unicode path. [2017-05-31]" -- Set the current directory to path local l_ptr: MANAGED_POINTER do l_ptr := File_info.file_name_to_pointer (path, Void) return_code := eif_chdir (l_ptr.item) end change_working_path (path: PATH) -- Set the current directory to path local l_ptr: MANAGED_POINTER do l_ptr := path.to_pointer return_code := eif_chdir (l_ptr.item) end put (value, key: READABLE_STRING_GENERAL) -- Set the environment variable key to value treating both -- value and key as Unicode characters. require key_exists: key /= Void key_meaningful: not key.is_empty not_key_has_null_character: not key.has ('%U'.to_character_32) value_exists: value /= Void not_value_has_null_character: not value.has ('%U'.to_character_32) local l_env: STRING_32 l_c_env: NATIVE_STRING do create l_env.make (value.count + key.count + 1); l_env.append_string_general (key); l_env.append_character ('='.to_character_32); l_env.append_string_general (value) create l_c_env.make (l_env); Environ.force (l_c_env, create {IMMUTABLE_STRING_32}.make_from_string_general (key)) return_code := eif_putenv (l_c_env.item) ensure variable_set: return_code = 0 implies ((value.is_empty and then item (key) = Void) or else not value.is_empty and then attached item (key) as k and then k.same_string_general (value)) end system (s: READABLE_STRING_GENERAL) -- Pass to the operating system a request to execute s interpreted as a Unicode string. -- If s is empty, use the default shell as command. require s_exists: s /= Void local l_cstr: NATIVE_STRING do if s.is_empty then create l_cstr.make (Default_shell) else create l_cstr.make (s) end return_code := system_call (l_cstr.item) end launch (s: READABLE_STRING_GENERAL) -- Pass to the operating system an asynchronous request to -- execute s interpreted as a Unicode string. -- If s is empty, use the default shell as command. require s_not_void: s /= Void local l_cstr: NATIVE_STRING do if s.is_empty then create l_cstr.make (Default_shell) else create l_cstr.make (s) end asynchronous_system_call (l_cstr.item) ensure instance_free: class end sleep (nanoseconds: INTEGER_64) -- Suspend thread execution for interval specified in -- nanoseconds (1 nanosecond = 10^(-9) second). require non_negative_nanoseconds: nanoseconds >= 0 do eif_sleep (nanoseconds) ensure instance_free: class end feature {NONE} -- Implementation Environ: HASH_TABLE [NATIVE_STRING, IMMUTABLE_STRING_32] -- Environment variable memory set by current execution, -- indexed by environment variable name. Needed otherwise -- we would corrupt memory after freeing memory used by -- NATIVE_STRING instance since not referenced anywhere else. once create Result.make (10) end i_th_environ (i: INTEGER_32): POINTER -- Environment variable at i-th position of eif_environ. require i_valid: i >= 0 external "C inline use <string.h>" alias "[ if (eif_environ) { #ifdef EIF_WINDOWS EIF_NATIVE_CHAR *vars = (EIF_NATIVE_CHAR *) eif_environ; int cnt = 0; for (; *vars; vars++) { if ($i==cnt) return vars; while (*vars) { vars++; } cnt++; } return NULL; #else return ((EIF_NATIVE_CHAR **)eif_environ)[$i]; #endif } else { return NULL; } ]" ensure instance_free: class end separated_variables (a_var: STRING_32): detachable TUPLE [value: STRING_32; key: STRING_32] -- Given an environment variable a_var in form of "key=value", -- return separated key and value. -- Return Void if a_var is in incorrect format. require a_var_attached: a_var /= Void local i, j: INTEGER_32 done: BOOLEAN do j := a_var.count from i := 1 until i > j or done loop if a_var.item (i) = '='.to_character_32 then done := True else i := i + 1 end end if i > 1 and then i < j then Result := [a_var.substring (i + 1, j), a_var.substring (1, i - 1)] end ensure instance_free: class end File_info: FILE_INFO obsolete "Remove when all obsolete routines using it will be removed. [2017-05-31]" -- Platform specific helper of filenames. once create Result.make ensure instance_free: class end feature {NONE} -- External eif_dir_current (a_ptr: POINTER; a_count: INTEGER_32): INTEGER_32 -- Store platform specific path of current working directory in a_ptr with a_count bytes. If -- there is a need for more bytes than a_count, or if a_ptr is the default_pointer, nothing is done with a_ptr. -- We always return the number of bytes required including the null-terminating character, or -1 on error. external "C signature (EIF_FILENAME, EIF_INTEGER): EIF_INTEGER use %"eif_dir.h%"" end eif_getenv (s: POINTER): POINTER -- Value of environment variable s external "C inline use <stdlib.h>" alias "[ #ifdef EIF_WINDOWS return _wgetenv ((EIF_NATIVE_CHAR *) $s); #else return getenv ((EIF_NATIVE_CHAR *) $s); #endif ]" end eif_putenv (v: POINTER): INTEGER_32 -- Set v in environment. external "C inline use <stdlib.h>" alias "[ #ifdef EIF_WINDOWS return _wputenv ((EIF_NATIVE_CHAR *) $v); #else return putenv ((EIF_NATIVE_CHAR *) $v); #endif ]" end eif_chdir (path: POINTER): INTEGER_32 -- Set the current directory to path external "C signature (EIF_FILENAME): EIF_INTEGER use %"eif_dir.h%"" end system_call (s: POINTER): INTEGER_32 -- Pass to the operating system a request to execute s. external "C blocking use %"eif_misc.h%"" alias "eif_system" end asynchronous_system_call (s: POINTER) -- Pass to the operating system an asynchronous request to execute s. external "C blocking use %"eif_misc.h%"" alias "eif_system_asynchronous" end eif_home_directory_name_ptr (a_ptr: POINTER; a_count: INTEGER_32): INTEGER_32 -- Stored directory name corresponding to the home directory in a_ptr with a_count bytes. If -- there is a need for more bytes than a_count, or if a_ptr is the default_pointer, nothing is done with a_ptr. -- We always return the number of bytes required including the null-terminating character. external "C signature (EIF_FILENAME, EIF_INTEGER): EIF_INTEGER use %"eif_path_name.h%"" end eif_user_directory_name_ptr (a_buffer: POINTER; a_count: INTEGER_32): INTEGER_32 -- Directory name corresponding to the user directory that will be stored in buffer a_buffer -- of size a_count bytes. Returns the number of bytes necessary in a_buffer to get the full copy. external "C signature (EIF_FILENAME, EIF_INTEGER): EIF_INTEGER use %"eif_path_name.h%"" end eif_temporary_directory_name_ptr (a_ptr: POINTER; a_count: INTEGER_32): INTEGER_32 -- Stored directory name corresponding to the temporary directory in a_ptr with a_count bytes. -- If there is a need for more bytes than a_count, or if a_ptr is the default_pointer, -- nothing is done with a_ptr. -- We always return the number of bytes required including the null-terminating character. external "C signature (EIF_FILENAME, EIF_INTEGER): EIF_INTEGER use %"eif_path_name.h%"" end eif_sleep (nanoseconds: INTEGER_64) -- Suspend thread execution for interval specified in -- nanoseconds (1 nanosecond = 10^(-9) second). require non_negative_nanoseconds: nanoseconds >= 0 external "C blocking use %"eif_misc.h%"" ensure instance_free: class end note copyright: "Copyright (c) 1984-2019, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end -- class EXECUTION_ENVIRONMENT
Generated by ISE EiffelStudio