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