1 /******************************************************************************* 2 3 Copyright: 4 Copyright (c) 2007 Tango contributors. 5 Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH. 6 All rights reserved. 7 8 License: 9 Tango Dual License: 3-Clause BSD License / Academic Free License v3.0. 10 See LICENSE_TANGO.txt for details. 11 12 Version: Feb 2007: Initial release 13 14 Authors: Deewiant, Maxter, Gregor, Kris 15 16 *******************************************************************************/ 17 18 module ocean.sys.Environment; 19 20 import ocean.core.ExceptionDefinitions; 21 import ocean.io.model.IFile; 22 import ocean.io.Path; 23 import ocean.io.FilePath; 24 import ocean.sys.Common; 25 import Text = ocean.text.Util; 26 import ocean.transition; 27 28 import core.stdc.string; 29 import core.sys.posix.stdlib; 30 31 private 32 { 33 __gshared extern (C) extern char** environ; 34 } 35 36 37 /******************************************************************************* 38 39 Exposes the system Environment settings, along with some handy 40 utilities 41 42 *******************************************************************************/ 43 44 struct Environment 45 { 46 public alias cwd directory; 47 48 /*********************************************************************** 49 50 Throw an exception 51 52 ***********************************************************************/ 53 54 private static void exception (istring msg) 55 { 56 throw new PlatformException (msg); 57 } 58 59 /*********************************************************************** 60 61 Returns an absolute version of the provided path, where cwd is used 62 as the prefix. 63 64 The provided path is returned as is if already absolute. 65 66 ***********************************************************************/ 67 68 static istring toAbsolute(mstring path) 69 { 70 scope fp = new FilePath(path); 71 if (fp.isAbsolute) 72 return idup(path); 73 74 fp.absolute(cwd); 75 return fp.toString; 76 } 77 78 /*********************************************************************** 79 80 Returns the full path location of the provided executable 81 file, rifling through the PATH as necessary. 82 83 Returns null if the provided filename was not found 84 85 ***********************************************************************/ 86 87 static FilePath exePath (cstring file) 88 { 89 auto bin = new FilePath (file); 90 91 // is this a directory? Potentially make it absolute 92 if (bin.isChild && !bin.isAbsolute) 93 return bin.absolute (cwd); 94 95 // rifle through the path (after converting to standard format) 96 foreach (_pe; Text.patterns (standard(get("PATH").dup), FileConst.SystemPathString)) 97 { 98 auto pe = assumeUnique(_pe); // only acessible via foreach args 99 100 if (bin.path(pe).exists) 101 { 102 stat_t stats; 103 stat(bin.cString.ptr, &stats); 104 if (stats.st_mode & Octal!("100")) 105 return bin; 106 } 107 } 108 return null; 109 } 110 111 /*************************************************************************** 112 113 Returns: 114 the provided 'def' value if the variable does not exist 115 116 ***************************************************************************/ 117 118 static istring get (cstring variable, istring def = null) 119 { 120 char* ptr = getenv ((variable ~ '\0').ptr); 121 122 if (ptr is null) 123 return def; 124 125 return idup(ptr[0 .. strlen(ptr)]); 126 } 127 128 /*************************************************************************** 129 130 Clears the variable, if value is null or empty 131 132 ***************************************************************************/ 133 134 static void set (cstring variable, cstring value = null) 135 { 136 int result; 137 138 if (value.length is 0) 139 unsetenv ((variable ~ '\0').ptr); 140 else 141 result = setenv ((variable ~ '\0').ptr, (value ~ '\0').ptr, 1); 142 143 if (result != 0) 144 exception (SysError.lastMsg); 145 } 146 147 /*************************************************************************** 148 149 Get all set environment variables as an associative array. 150 151 ***************************************************************************/ 152 153 static istring[istring] get () 154 { 155 istring[istring] arr; 156 157 for (char** p = environ; *p; ++p) 158 { 159 size_t k = 0; 160 char* str = *p; 161 162 while (*str++ != '=') 163 ++k; 164 istring key = idup((*p)[0..k]); 165 166 k = 0; 167 char* val = str; 168 while (*str++) 169 ++k; 170 arr[key] = idup(val[0 .. k]); 171 } 172 173 return arr; 174 } 175 176 /*************************************************************************** 177 178 Set the current working directory 179 180 ***************************************************************************/ 181 182 static void cwd (cstring path) 183 { 184 char[512] tmp = void; 185 tmp [path.length] = 0; 186 tmp[0..path.length] = path; 187 188 if (core.sys.posix.unistd.chdir (tmp.ptr)) 189 exception ("Failed to set current directory"); 190 } 191 192 /*************************************************************************** 193 194 Get the current working directory 195 196 ***************************************************************************/ 197 198 static istring cwd () 199 { 200 char[512] tmp = void; 201 202 char *s = core.sys.posix.unistd.getcwd (tmp.ptr, tmp.length); 203 if (s is null) 204 exception ("Failed to get current directory"); 205 206 auto path = s[0 .. strlen(s)+1].dup; 207 if (path[$-2] is '/') // root path has the slash 208 path.length = path.length-1; 209 else 210 path[$-1] = '/'; 211 return assumeUnique(path); 212 } 213 }