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 /* ////////////////////////////////////////////////////////////////////////// */