Mercurial > projects > ldc
comparison lphobos/std/process.d @ 473:373489eeaf90
Applied downs' lphobos update
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Mon, 04 Aug 2008 19:28:49 +0200 |
parents | |
children | 88e23f8c2354 |
comparison
equal
deleted
inserted
replaced
472:15c804b6ce77 | 473:373489eeaf90 |
---|---|
1 | |
2 /* | |
3 * Copyright (C) 2003-2004 by Digital Mars, www.digitalmars.com | |
4 * Written by Matthew Wilson and Walter Bright | |
5 * | |
6 * Incorporating idea (for execvpe() on Linux) from Russ Lewis | |
7 * | |
8 * Updated: 21st August 2004 | |
9 * | |
10 * This software is provided 'as-is', without any express or implied | |
11 * warranty. In no event will the authors be held liable for any damages | |
12 * arising from the use of this software. | |
13 * | |
14 * Permission is granted to anyone to use this software for any purpose, | |
15 * including commercial applications, and to alter it and redistribute it | |
16 * freely, subject to the following restrictions: | |
17 * | |
18 * o The origin of this software must not be misrepresented; you must not | |
19 * claim that you wrote the original software. If you use this software | |
20 * in a product, an acknowledgment in the product documentation would be | |
21 * appreciated but is not required. | |
22 * o Altered source versions must be plainly marked as such, and must not | |
23 * be misrepresented as being the original software. | |
24 * o This notice may not be removed or altered from any source | |
25 * distribution. | |
26 */ | |
27 /* NOTE: This file has been patched from the original DMD distribution to | |
28 work with the GDC compiler. | |
29 | |
30 Modified by David Friedman, October 2004 | |
31 */ | |
32 | |
33 /** | |
34 * Macros: | |
35 * WIKI=Phobos/StdProcess | |
36 */ | |
37 | |
38 | |
39 module std.process; | |
40 | |
41 private import std.c.stdlib; | |
42 private import std.c.string; | |
43 private import std.string; | |
44 private import std.c.process; | |
45 | |
46 /** | |
47 * Execute command in a _command shell. | |
48 * | |
49 * Returns: exit status of command | |
50 */ | |
51 | |
52 int system(char[] command) | |
53 { | |
54 return std.c.process.system(toStringz(command)); | |
55 } | |
56 | |
57 private void toAStringz(char[][] a, char**az) | |
58 { | |
59 foreach(char[] s; a) | |
60 { | |
61 *az++ = toStringz(s); | |
62 } | |
63 *az = null; | |
64 } | |
65 | |
66 | |
67 /* ========================================================== */ | |
68 | |
69 //version (Windows) | |
70 //{ | |
71 // int spawnvp(int mode, char[] pathname, char[][] argv) | |
72 // { | |
73 // char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length)); | |
74 // | |
75 // toAStringz(argv, argv_); | |
76 // | |
77 // return std.c.process.spawnvp(mode, toStringz(pathname), argv_); | |
78 // } | |
79 //} | |
80 | |
81 // Incorporating idea (for spawnvp() on linux) from Dave Fladebo | |
82 | |
83 alias std.c.process._P_WAIT P_WAIT; | |
84 alias std.c.process._P_NOWAIT P_NOWAIT; | |
85 | |
86 int spawnvp(int mode, char[] pathname, char[][] argv) | |
87 { | |
88 char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length)); | |
89 | |
90 toAStringz(argv, argv_); | |
91 | |
92 version(Unix) | |
93 { | |
94 return _spawnvp(mode, toStringz(pathname), argv_); | |
95 } | |
96 else | |
97 { | |
98 return std.c.process.spawnvp(mode, toStringz(pathname), argv_); | |
99 } | |
100 } | |
101 | |
102 version(Unix) | |
103 { | |
104 version(linux) import std.c.linux.linux; | |
105 else import std.c.unix.unix; | |
106 int _spawnvp(int mode, char *pathname, char **argv) | |
107 { | |
108 int retval = 0; | |
109 pid_t pid = fork(); | |
110 | |
111 if(!pid) | |
112 { // child | |
113 std.c.process.execvp(pathname, argv); | |
114 goto Lerror; | |
115 } | |
116 else if(pid > 0) | |
117 { // parent | |
118 if(mode == _P_NOWAIT) | |
119 { | |
120 retval = pid; // caller waits | |
121 } | |
122 else | |
123 { | |
124 while(1) | |
125 { | |
126 int status; | |
127 pid_t wpid = waitpid(pid, &status, 0); | |
128 if(exited(status)) | |
129 { | |
130 retval = exitstatus(status); | |
131 break; | |
132 } | |
133 else if(signaled(status)) | |
134 { | |
135 retval = -termsig(status); | |
136 break; | |
137 } | |
138 else if(stopped(status)) // ptrace support | |
139 continue; | |
140 else | |
141 goto Lerror; | |
142 } | |
143 } | |
144 | |
145 return retval; | |
146 } | |
147 | |
148 Lerror: | |
149 retval = getErrno; | |
150 throw new Exception( | |
151 "Cannot spawn " ~ toString(pathname) ~ "; " | |
152 ~ toString(strerror(retval)) | |
153 ~ " [errno " ~ toString(retval) ~ "]"); | |
154 } // _spawnvp | |
155 private | |
156 { | |
157 bool stopped(int status) { return cast(bool)((status & 0xff) == 0x7f); } | |
158 bool signaled(int status) { return cast(bool)((cast(char)((status & 0x7f) + 1) >> 1) > 0); } | |
159 int termsig(int status) { return status & 0x7f; } | |
160 bool exited(int status) { return cast(bool)((status & 0x7f) == 0); } | |
161 int exitstatus(int status) { return (status & 0xff00) >> 8; } | |
162 } // private | |
163 } // version(linux) | |
164 | |
165 /* ========================================================== */ | |
166 | |
167 /** | |
168 * Execute program specified by pathname, passing it the arguments (argv) | |
169 * and the environment (envp), returning the exit status. | |
170 * The 'p' versions of exec search the PATH environment variable | |
171 * setting for the program. | |
172 */ | |
173 | |
174 int execv(char[] pathname, char[][] argv) | |
175 { | |
176 char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length)); | |
177 | |
178 toAStringz(argv, argv_); | |
179 | |
180 return std.c.process.execv(toStringz(pathname), argv_); | |
181 } | |
182 | |
183 /** ditto */ | |
184 int execve(char[] pathname, char[][] argv, char[][] envp) | |
185 { | |
186 char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length)); | |
187 char** envp_ = cast(char**)alloca((char*).sizeof * (1 + envp.length)); | |
188 | |
189 toAStringz(argv, argv_); | |
190 toAStringz(envp, envp_); | |
191 | |
192 return std.c.process.execve(toStringz(pathname), argv_, envp_); | |
193 } | |
194 | |
195 /** ditto */ | |
196 int execvp(char[] pathname, char[][] argv) | |
197 { | |
198 char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length)); | |
199 | |
200 toAStringz(argv, argv_); | |
201 | |
202 return std.c.process.execvp(toStringz(pathname), argv_); | |
203 } | |
204 | |
205 /** ditto */ | |
206 int execvpe(char[] pathname, char[][] argv, char[][] envp) | |
207 { | |
208 version (GNU_Need_execvpe) | |
209 { | |
210 // Is pathname rooted? | |
211 if(pathname[0] == '/') | |
212 { | |
213 // Yes, so just call execve() | |
214 return execve(pathname, argv, envp); | |
215 } | |
216 else | |
217 { | |
218 // No, so must traverse PATHs, looking for first match | |
219 char[][] envPaths = std.string.split(std.string.toString(std.c.stdlib.getenv("PATH")), ":"); | |
220 int iRet = 0; | |
221 | |
222 // Note: if any call to execve() succeeds, this process will cease | |
223 // execution, so there's no need to check the execve() result through | |
224 // the loop. | |
225 | |
226 foreach(char[] pathDir; envPaths) | |
227 { | |
228 char[] composite = pathDir ~ "/" ~ pathname; | |
229 | |
230 iRet = execve(composite, argv, envp); | |
231 } | |
232 if(0 != iRet) | |
233 { | |
234 iRet = execve(pathname, argv, envp); | |
235 } | |
236 | |
237 return iRet; | |
238 } | |
239 } | |
240 else version(Windows) | |
241 { | |
242 char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length)); | |
243 char** envp_ = cast(char**)alloca((char*).sizeof * (1 + envp.length)); | |
244 | |
245 toAStringz(argv, argv_); | |
246 toAStringz(envp, envp_); | |
247 | |
248 return std.c.process.execvpe(toStringz(pathname), argv_, envp_); | |
249 } | |
250 else | |
251 { | |
252 throw new Exception("Not supported on this platform."); | |
253 } // version | |
254 } | |
255 | |
256 /* ////////////////////////////////////////////////////////////////////////// */ | |
257 | |
258 version(MainTest) | |
259 { | |
260 int main(char[][] args) | |
261 { | |
262 if(args.length < 2) | |
263 { | |
264 printf("Must supply executable (and optional arguments)\n"); | |
265 | |
266 return 1; | |
267 } | |
268 else | |
269 { | |
270 char[][] dummy_env; | |
271 | |
272 dummy_env ~= "VAL0=value"; | |
273 dummy_env ~= "VAL1=value"; | |
274 | |
275 /+ | |
276 foreach(char[] arg; args) | |
277 { | |
278 printf("%.*s\n", arg); | |
279 } | |
280 +/ | |
281 | |
282 // int i = execv(args[1], args[1 .. args.length]); | |
283 // int i = execvp(args[1], args[1 .. args.length]); | |
284 int i = execvpe(args[1], args[1 .. args.length], dummy_env); | |
285 | |
286 printf("exec??() has returned! Error code: %d; errno: %d\n", i, /* std.c.stdlib.getErrno() */-1); | |
287 | |
288 return 0; | |
289 } | |
290 } | |
291 } | |
292 | |
293 /* ////////////////////////////////////////////////////////////////////////// */ |