1 // Written in the D programming language.
2 
3 /**
4 Functions for starting and interacting with other processes, and for
5 working with the current process' execution environment.
6 
7 Process_handling:
8 $(UL $(LI
9     $(LREF spawnProcess) spawns a new process, optionally assigning it an
10     arbitrary set of standard input, output, and error streams.
11     The function returns immediately, leaving the child process to execute
12     in parallel with its parent.  All other functions in this module that
13     spawn processes are built around `spawnProcess`.)
14 $(LI
15     $(LREF wait) makes the parent process wait for a child process to
16     terminate.  In general one should always do this, to avoid
17     child processes becoming "zombies" when the parent process exits.
18     Scope guards are perfect for this – see the $(LREF spawnProcess)
19     documentation for examples.  $(LREF tryWait) is similar to `wait`,
20     but does not block if the process has not yet terminated.)
21 $(LI
22     $(LREF pipeProcess) also spawns a child process which runs
23     in parallel with its parent.  However, instead of taking
24     arbitrary streams, it automatically creates a set of
25     pipes that allow the parent to communicate with the child
26     through the child's standard input, output, and/or error streams.
27     This function corresponds roughly to C's `popen` function.)
28 $(LI
29     $(LREF execute) starts a new process and waits for it
30     to complete before returning.  Additionally, it captures
31     the process' standard output and error streams and returns
32     the output of these as a string.)
33 $(LI
34     $(LREF spawnShell), $(LREF pipeShell) and $(LREF executeShell) work like
35     `spawnProcess`, `pipeProcess` and `execute`, respectively,
36     except that they take a single command string and run it through
37     the current user's default command interpreter.
38     `executeShell` corresponds roughly to C's `system` function.)
39 $(LI
40     $(LREF kill) attempts to terminate a running process.)
41 )
42 
43 The following table compactly summarises the different process creation
44 functions and how they relate to each other:
45 $(BOOKTABLE,
46     $(TR $(TH )
47          $(TH Runs program directly)
48          $(TH Runs shell command))
49     $(TR $(TD Low-level process creation)
50          $(TD $(LREF spawnProcess))
51          $(TD $(LREF spawnShell)))
52     $(TR $(TD Automatic input/output redirection using pipes)
53          $(TD $(LREF pipeProcess))
54          $(TD $(LREF pipeShell)))
55     $(TR $(TD Execute and wait for completion, collect output)
56          $(TD $(LREF execute))
57          $(TD $(LREF executeShell)))
58 )
59 
60 Other_functionality:
61 $(UL
62 $(LI
63     $(LREF pipe) is used to create unidirectional pipes.)
64 $(LI
65     $(LREF environment) is an interface through which the current process'
66     environment variables can be read and manipulated.)
67 $(LI
68     $(LREF escapeShellCommand) and $(LREF escapeShellFileName) are useful
69     for constructing shell command lines in a portable way.)
70 )
71 
72 Authors:
73     $(LINK2 https://github.com/kyllingstad, Lars Tandle Kyllingstad),
74     $(LINK2 https://github.com/schveiguy, Steven Schveighoffer),
75     $(HTTP thecybershadow.net, Vladimir Panteleev)
76 Copyright:
77     Copyright (c) 2013, the authors. All rights reserved.
78 License:
79    $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
80 Source:
81     $(PHOBOSSRC std/process.d)
82 Macros:
83     OBJECTREF=$(REF1 $0, object)
84 
85 Note:
86 Most of the functionality in this module is not available on iOS, tvOS
87 and watchOS. The only functions available on those platforms are:
88 $(LREF environment), $(LREF thisProcessID) and $(LREF thisThreadID).
89 */
90 module std.process;
91 
92 import core.thread : ThreadID;
93 
94 version (Posix)
95 {
96     import core.sys.posix.sys.wait;
97     import core.sys.posix.unistd;
98 }
99 version (Windows)
100 {
101     import core.stdc.stdio;
102     import core.sys.windows.winbase;
103     import core.sys.windows.winnt;
104     import std.utf;
105     import std.windows.syserror;
106 }
107 
108 import std.internal.cstring;
109 import std.range;
110 import std.stdio;
111 
112 version (OSX)
113     version = Darwin;
114 else version (iOS)
115 {
116     version = Darwin;
117     version = iOSDerived;
118 }
119 else version (TVOS)
120 {
121     version = Darwin;
122     version = iOSDerived;
123 }
124 else version (WatchOS)
125 {
126     version = Darwin;
127     version = iOSDerived;
128 }
129 
130 
131 // Some of the following should be moved to druntime.
132 private
133 {
134     // Microsoft Visual C Runtime (MSVCRT) declarations.
135     version (CRuntime_Microsoft)
136     {
137         import core.stdc.stdint;
138         enum
139         {
140             STDIN_FILENO  = 0,
141             STDOUT_FILENO = 1,
142             STDERR_FILENO = 2,
143         }
144     }
145 
146     // POSIX API declarations.
147     version (Posix)
148     {
149         import core.sys.posix.unistd : getEnvironPtr = environ;
150 
151         @system unittest
152         {
153             import core.thread : Thread;
154             new Thread({assert(getEnvironPtr !is null);}).start();
155         }
156     }
157 } // private
158 
159 // =============================================================================
160 // Environment variable manipulation.
161 // =============================================================================
162 
163 /**
164 Manipulates _environment variables using an associative-array-like
165 interface.
166 
167 This class contains only static methods, and cannot be instantiated.
168 See below for examples of use.
169 */
170 abstract final class environment
171 {
172     static import core.sys.posix.stdlib;
173     import core.stdc.errno : errno, EINVAL;
174 
175 static:
176     /**
177     Retrieves the value of the environment variable with the given `name`.
178     ---
179     auto path = environment["PATH"];
180     ---
181 
182     Throws:
183     $(OBJECTREF Exception) if the environment variable does not exist,
184     or $(REF UTFException, std,utf) if the variable contains invalid UTF-16
185     characters (Windows only).
186 
187     See_also:
188     $(LREF environment.get), which doesn't throw on failure.
189     */
190     string opIndex(scope const(char)[] name) @safe
191     {
192         import std.exception : enforce;
193         return get(name, null).enforce("Environment variable not found: "~name);
194     }
195 
196     /**
197     Retrieves the value of the environment variable with the given `name`,
198     or a default value if the variable doesn't exist.
199 
200     Unlike $(LREF environment.opIndex), this function never throws on Posix.
201     ---
202     auto sh = environment.get("SHELL", "/bin/sh");
203     ---
204     This function is also useful in checking for the existence of an
205     environment variable.
206     ---
207     auto myVar = environment.get("MYVAR");
208     if (myVar is null)
209     {
210         // Environment variable doesn't exist.
211         // Note that we have to use 'is' for the comparison, since
212         // myVar == null is also true if the variable exists but is
213         // empty.
214     }
215     ---
216     Params:
217         name = name of the environment variable to retrieve
218         defaultValue = default value to return if the environment variable doesn't exist.
219 
220     Returns:
221         the value of the environment variable if found, otherwise
222         `null` if the environment doesn't exist.
223 
224     Throws:
225     $(REF UTFException, std,utf) if the variable contains invalid UTF-16
226     characters (Windows only).
227     */
228     string get(scope const(char)[] name, string defaultValue = null) @safe
229     {
230         string value;
231         getImpl(name, (result) { value = result ? cachedToString(result) : defaultValue; });
232         return value;
233     }
234 
235     /**
236     Assigns the given `value` to the environment variable with the given
237     `name`.
238     If `value` is null the variable is removed from environment.
239 
240     If the variable does not exist, it will be created. If it already exists,
241     it will be overwritten.
242     ---
243     environment["foo"] = "bar";
244     ---
245 
246     Throws:
247     $(OBJECTREF Exception) if the environment variable could not be added
248         (e.g. if the name is invalid).
249 
250     Note:
251     On some platforms, modifying environment variables may not be allowed in
252     multi-threaded programs. See e.g.
253     $(LINK2 https://www.gnu.org/software/libc/manual/html_node/Environment-Access.html#Environment-Access, glibc).
254     */
255     inout(char)[] opIndexAssign(return scope inout char[] value, scope const(char)[] name) @trusted
256     {
257         version (Posix)
258         {
259             import std.exception : enforce, errnoEnforce;
260             if (value is null)
261             {
262                 remove(name);
263                 return value;
264             }
265             if (core.sys.posix.stdlib.setenv(name.tempCString(), value.tempCString(), 1) != -1)
266             {
267                 return value;
268             }
269             // The default errno error message is very uninformative
270             // in the most common case, so we handle it manually.
271             enforce(errno != EINVAL,
272                 "Invalid environment variable name: '"~name~"'");
273             errnoEnforce(false,
274                 "Failed to add environment variable");
275             assert(0);
276         }
277         else version (Windows)
278         {
279             import std.windows.syserror : wenforce;
280             wenforce(
281                 SetEnvironmentVariableW(name.tempCStringW(), value.tempCStringW()),
282             );
283             return value;
284         }
285         else static assert(0);
286     }
287 
288     /**
289     Removes the environment variable with the given `name`.
290 
291     If the variable isn't in the environment, this function returns
292     successfully without doing anything.
293 
294     Note:
295     On some platforms, modifying environment variables may not be allowed in
296     multi-threaded programs. See e.g.
297     $(LINK2 https://www.gnu.org/software/libc/manual/html_node/Environment-Access.html#Environment-Access, glibc).
298     */
299     void remove(scope const(char)[] name) @trusted nothrow @nogc
300     {
301         version (Windows)    SetEnvironmentVariableW(name.tempCStringW(), null);
302         else version (Posix) core.sys.posix.stdlib.unsetenv(name.tempCString());
303         else static assert(0);
304     }
305 
306     /**
307     Identify whether a variable is defined in the environment.
308 
309     Because it doesn't return the value, this function is cheaper than `get`.
310     However, if you do need the value as well, you should just check the
311     return of `get` for `null` instead of using this function first.
312 
313     Example:
314     -------------
315     // good usage
316     if ("MY_ENV_FLAG" in environment)
317         doSomething();
318 
319     // bad usage
320     if ("MY_ENV_VAR" in environment)
321         doSomething(environment["MY_ENV_VAR"]);
322 
323     // do this instead
324     if (auto var = environment.get("MY_ENV_VAR"))
325         doSomething(var);
326     -------------
327     */
328     bool opBinaryRight(string op : "in")(scope const(char)[] name) @trusted
329     {
330         if (name is null)
331             return false;
332         version (Posix)
333             return core.sys.posix.stdlib.getenv(name.tempCString()) !is null;
334         else version (Windows)
335         {
336             SetLastError(NO_ERROR);
337             if (GetEnvironmentVariableW(name.tempCStringW, null, 0) > 0)
338                 return true;
339             immutable err = GetLastError();
340             if (err == NO_ERROR)
341                 return true; // zero-length environment variable on Wine / XP
342             if (err == ERROR_ENVVAR_NOT_FOUND)
343                 return false;
344             // Some other Windows error, throw.
345             throw new WindowsException(err);
346         }
347         else static assert(0);
348     }
349 
350     /**
351     Copies all environment variables into an associative array.
352 
353     Windows_specific:
354     While Windows environment variable names are case insensitive, D's
355     built-in associative arrays are not.  This function will store all
356     variable names in uppercase (e.g. `PATH`).
357 
358     Throws:
359     $(OBJECTREF Exception) if the environment variables could not
360         be retrieved (Windows only).
361     */
362     string[string] toAA() @trusted
363     {
364         import std.conv : to;
365         string[string] aa;
366         version (Posix)
367         {
368             auto environ = getEnvironPtr;
369             for (int i=0; environ[i] != null; ++i)
370             {
371                 import std.string : indexOf;
372 
373                 immutable varDef = to!string(environ[i]);
374                 immutable eq = indexOf(varDef, '=');
375                 assert(eq >= 0);
376 
377                 immutable name = varDef[0 .. eq];
378                 immutable value = varDef[eq+1 .. $];
379 
380                 // In POSIX, environment variables may be defined more
381                 // than once.  This is a security issue, which we avoid
382                 // by checking whether the key already exists in the array.
383                 // For more info:
384                 // http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/environment-variables.html
385                 if (name !in aa)  aa[name] = value;
386             }
387         }
388         else version (Windows)
389         {
390             import std.exception : enforce;
391             import std.uni : toUpper;
392             auto envBlock = GetEnvironmentStringsW();
393             enforce(envBlock, "Failed to retrieve environment variables.");
394             scope(exit) FreeEnvironmentStringsW(envBlock);
395 
396             for (int i=0; envBlock[i] != '\0'; ++i)
397             {
398                 auto start = i;
399                 while (envBlock[i] != '=') ++i;
400                 immutable name = toUTF8(toUpper(envBlock[start .. i]));
401 
402                 start = i+1;
403                 while (envBlock[i] != '\0') ++i;
404 
405                 // Ignore variables with empty names. These are used internally
406                 // by Windows to keep track of each drive's individual current
407                 // directory.
408                 if (!name.length)
409                     continue;
410 
411                 // Just like in POSIX systems, environment variables may be
412                 // defined more than once in an environment block on Windows,
413                 // and it is just as much of a security issue there.  Moreso,
414                 // in fact, due to the case insensensitivity of variable names,
415                 // which is not handled correctly by all programs.
416                 auto val = toUTF8(envBlock[start .. i]);
417                 if (name !in aa) aa[name] = val is null ? "" : val;
418             }
419         }
420         else static assert(0);
421         return aa;
422     }
423 
424 private:
425     version (Windows) alias OSChar = WCHAR;
426     else version (Posix) alias OSChar = char;
427 
428     // Retrieves the environment variable. Calls `sink` with a
429     // temporary buffer of OS characters, or `null` if the variable
430     // doesn't exist.
431     void getImpl(scope const(char)[] name, scope void delegate(const(OSChar)[]) @safe sink) @trusted
432     {
433         // fix issue https://issues.dlang.org/show_bug.cgi?id=24549
434         if (name is null)
435             return sink(null);
436 
437         version (Windows)
438         {
439             // first we ask windows how long the environment variable is,
440             // then we try to read it in to a buffer of that length. Lots
441             // of error conditions because the windows API is nasty.
442 
443             import std.conv : to;
444             const namezTmp = name.tempCStringW();
445             WCHAR[] buf;
446 
447             // clear error because GetEnvironmentVariable only says it sets it
448             // if the environment variable is missing, not on other errors.
449             SetLastError(NO_ERROR);
450             // len includes terminating null
451             immutable len = GetEnvironmentVariableW(namezTmp, null, 0);
452             if (len == 0)
453             {
454                 immutable err = GetLastError();
455                 if (err == ERROR_ENVVAR_NOT_FOUND)
456                     return sink(null);
457                 if (err != NO_ERROR) // Some other Windows error, throw.
458                     throw new WindowsException(err);
459             }
460             if (len <= 1)
461                 return sink("");
462             buf.length = len;
463 
464             while (true)
465             {
466                 // lenRead is either the number of bytes read w/o null - if buf was long enough - or
467                 // the number of bytes necessary *including* null if buf wasn't long enough
468                 immutable lenRead = GetEnvironmentVariableW(namezTmp, buf.ptr, to!DWORD(buf.length));
469                 if (lenRead == 0)
470                 {
471                     immutable err = GetLastError();
472                     if (err == NO_ERROR) // sucessfully read a 0-length variable
473                         return sink("");
474                     if (err == ERROR_ENVVAR_NOT_FOUND) // variable didn't exist
475                         return sink(null);
476                     // some other windows error
477                     throw new WindowsException(err);
478                 }
479                 assert(lenRead != buf.length, "impossible according to msft docs");
480                 if (lenRead < buf.length) // the buffer was long enough
481                     return sink(buf[0 .. lenRead]);
482                 // resize and go around again, because the environment variable grew
483                 buf.length = lenRead;
484             }
485         }
486         else version (Posix)
487         {
488             import core.stdc.string : strlen;
489 
490             const vz = core.sys.posix.stdlib.getenv(name.tempCString());
491             if (vz == null) return sink(null);
492             return sink(vz[0 .. strlen(vz)]);
493        }
494         else static assert(0);
495     }
496 
497     string cachedToString(C)(scope const(C)[] v) @safe
498     {
499         import std.algorithm.comparison : equal;
500 
501         // Cache the last call's result.
502         static string lastResult;
503         if (v.empty)
504         {
505             // Return non-null array for blank result to distinguish from
506             // not-present result.
507             lastResult = "";
508         }
509         else if (!v.equal(lastResult))
510         {
511             import std.conv : to;
512             lastResult = v.to!string;
513         }
514         return lastResult;
515     }
516 }
517 
518 @safe unittest
519 {
520     import std.exception : assertThrown;
521     // New variable
522     environment["std_process"] = "foo";
523     assert(environment["std_process"] == "foo");
524     assert("std_process" in environment);
525 
526     // Set variable again (also tests length 1 case)
527     environment["std_process"] = "b";
528     assert(environment["std_process"] == "b");
529     assert("std_process" in environment);
530 
531     // Remove variable
532     environment.remove("std_process");
533     assert("std_process" !in environment);
534 
535     // Remove again, should succeed
536     environment.remove("std_process");
537     assert("std_process" !in environment);
538 
539     // Throw on not found.
540     assertThrown(environment["std_process"]);
541 
542     // get() without default value
543     assert(environment.get("std_process") is null);
544 
545     // get() with default value
546     assert(environment.get("std_process", "baz") == "baz");
547 
548     // get() on an empty (but present) value
549     environment["std_process"] = "";
550     auto res = environment.get("std_process");
551     assert(res !is null);
552     assert(res == "");
553     assert("std_process" in environment);
554 
555     // Important to do the following round-trip after the previous test
556     // because it tests toAA with an empty var
557 
558     // Convert to associative array
559     auto aa = environment.toAA();
560     assert(aa.length > 0);
561     foreach (n, v; aa)
562     {
563         // Wine has some bugs related to environment variables:
564         //  - Wine allows the existence of an env. variable with the name
565         //    "\0", but GetEnvironmentVariable refuses to retrieve it.
566         //    As of 2.067 we filter these out anyway (see comment in toAA).
567 
568         assert(v == environment[n]);
569     }
570 
571     // ... and back again.
572     foreach (n, v; aa)
573         environment[n] = v;
574 
575     // Complete the roundtrip
576     auto aa2 = environment.toAA();
577     import std.conv : text;
578     assert(aa == aa2, text(aa, " != ", aa2));
579     assert("std_process" in environment);
580 
581     // Setting null must have the same effect as remove
582     environment["std_process"] = null;
583     assert("std_process" !in environment);
584 }
585 
586 // https://issues.dlang.org/show_bug.cgi?id=24549
587 @safe unittest
588 {
589     import std.exception : assertThrown;
590     assert(environment.get(null) is null);
591     assertThrown(environment[null]);
592     assert(!(null in environment));
593 }
594 
595 // =============================================================================
596 // Functions and classes for process management.
597 // =============================================================================
598 
599 /**
600  * Returns the process ID of the current process,
601  * which is guaranteed to be unique on the system.
602  *
603  * Example:
604  * ---
605  * writefln("Current process ID: %d", thisProcessID);
606  * ---
607  */
608 @property int thisProcessID() @trusted nothrow @nogc //TODO: @safe
609 {
610     version (Windows)    return GetCurrentProcessId();
611     else version (Posix) return core.sys.posix.unistd.getpid();
612 }
613 
614 
615 /**
616  * Returns the process ID of the current thread,
617  * which is guaranteed to be unique within the current process.
618  *
619  * Returns:
620  * A $(REF ThreadID, core,thread) value for the calling thread.
621  *
622  * Example:
623  * ---
624  * writefln("Current thread ID: %s", thisThreadID);
625  * ---
626  */
627 @property ThreadID thisThreadID() @trusted nothrow @nogc //TODO: @safe
628 {
629     version (Windows)
630         return GetCurrentThreadId();
631     else
632     version (Posix)
633     {
634         import core.sys.posix.pthread : pthread_self;
635         return pthread_self();
636     }
637 }
638 
639 
640 @system unittest
641 {
642     int pidA, pidB;
643     ThreadID tidA, tidB;
644     pidA = thisProcessID;
645     tidA = thisThreadID;
646 
647     import core.thread;
648     auto t = new Thread({
649         pidB = thisProcessID;
650         tidB = thisThreadID;
651     });
652     t.start();
653     t.join();
654 
655     assert(pidA == pidB);
656     assert(tidA != tidB);
657 }
658 
659 
660 package(std) string uniqueTempPath() @safe
661 {
662     import std.file : tempDir;
663     import std.path : buildPath;
664     import std.uuid : randomUUID;
665     // Path should contain spaces to test escaping whitespace
666     return buildPath(tempDir(), "std.process temporary file " ~
667         randomUUID().toString());
668 }
669 
670 
671 version (iOSDerived) {}
672 else:
673 
674 /**
675 Spawns a new process, optionally assigning it an arbitrary set of standard
676 input, output, and error streams.
677 
678 The function returns immediately, leaving the child process to execute
679 in parallel with its parent.  It is recommended to always call $(LREF wait)
680 on the returned $(LREF Pid) unless the process was spawned with
681 `Config.detached` flag, as detailed in the documentation for `wait`.
682 
683 Command_line:
684 There are four overloads of this function.  The first two take an array
685 of strings, `args`, which should contain the program name as the
686 zeroth element and any command-line arguments in subsequent elements.
687 The third and fourth versions are included for convenience, and may be
688 used when there are no command-line arguments.  They take a single string,
689 `program`, which specifies the program name.
690 
691 Unless a directory is specified in `args[0]` or `program`,
692 `spawnProcess` will search for the program in a platform-dependent
693 manner.  On POSIX systems, it will look for the executable in the
694 directories listed in the PATH environment variable, in the order
695 they are listed.  On Windows, it will search for the executable in
696 the following sequence:
697 $(OL
698     $(LI The directory from which the application loaded.)
699     $(LI The current directory for the parent process.)
700     $(LI The 32-bit Windows system directory.)
701     $(LI The 16-bit Windows system directory.)
702     $(LI The Windows directory.)
703     $(LI The directories listed in the PATH environment variable.)
704 )
705 ---
706 // Run an executable called "prog" located in the current working
707 // directory:
708 auto pid = spawnProcess("./prog");
709 scope(exit) wait(pid);
710 // We can do something else while the program runs.  The scope guard
711 // ensures that the process is waited for at the end of the scope.
712 ...
713 
714 // Run DMD on the file "myprog.d", specifying a few compiler switches:
715 auto dmdPid = spawnProcess(["dmd", "-O", "-release", "-inline", "myprog.d" ]);
716 if (wait(dmdPid) != 0)
717     writeln("Compilation failed!");
718 ---
719 
720 Environment_variables:
721 By default, the child process inherits the environment of the parent
722 process, along with any additional variables specified in the `env`
723 parameter.  If the same variable exists in both the parent's environment
724 and in `env`, the latter takes precedence.
725 
726 If the $(LREF Config.newEnv) flag is set in `config`, the child
727 process will $(I not) inherit the parent's environment.  Its entire
728 environment will then be determined by `env`.
729 ---
730 wait(spawnProcess("myapp", ["foo" : "bar"], Config.newEnv));
731 ---
732 
733 Standard_streams:
734 The optional arguments `stdin`, `stdout` and `stderr` may
735 be used to assign arbitrary $(REF File, std,stdio) objects as the standard
736 input, output and error streams, respectively, of the child process.  The
737 former must be opened for reading, while the latter two must be opened for
738 writing.  The default is for the child process to inherit the standard
739 streams of its parent.
740 ---
741 // Run DMD on the file myprog.d, logging any error messages to a
742 // file named errors.log.
743 auto logFile = File("errors.log", "w");
744 auto pid = spawnProcess(["dmd", "myprog.d"],
745                         std.stdio.stdin,
746                         std.stdio.stdout,
747                         logFile);
748 if (wait(pid) != 0)
749     writeln("Compilation failed. See errors.log for details.");
750 ---
751 
752 Note that if you pass a `File` object that is $(I not)
753 one of the standard input/output/error streams of the parent process,
754 that stream will by default be $(I closed) in the parent process when
755 this function returns.  See the $(LREF Config) documentation below for
756 information about how to disable this behaviour.
757 
758 Beware of buffering issues when passing `File` objects to
759 `spawnProcess`.  The child process will inherit the low-level raw
760 read/write offset associated with the underlying file descriptor, but
761 it will not be aware of any buffered data.  In cases where this matters
762 (e.g. when a file should be aligned before being passed on to the
763 child process), it may be a good idea to use unbuffered streams, or at
764 least ensure all relevant buffers are flushed.
765 
766 Params:
767 args    = An array which contains the program name as the zeroth element
768           and any command-line arguments in the following elements.
769 stdin   = The standard input stream of the child process.
770           This can be any $(REF File, std,stdio) that is opened for reading.
771           By default the child process inherits the parent's input
772           stream.
773 stdout  = The standard output stream of the child process.
774           This can be any $(REF File, std,stdio) that is opened for writing.
775           By default the child process inherits the parent's output stream.
776 stderr  = The standard error stream of the child process.
777           This can be any $(REF File, std,stdio) that is opened for writing.
778           By default the child process inherits the parent's error stream.
779 env     = Additional environment variables for the child process.
780 config  = Flags that control process creation. See $(LREF Config)
781           for an overview of available flags.
782 workDir = The working directory for the new process.
783           By default the child process inherits the parent's working
784           directory.
785 
786 Returns:
787 A $(LREF Pid) object that corresponds to the spawned process.
788 
789 Throws:
790 $(LREF ProcessException) on failure to start the process.$(BR)
791 $(REF StdioException, std,stdio) on failure to pass one of the streams
792     to the child process (Windows only).$(BR)
793 $(REF RangeError, core,exception) if `args` is empty.
794 */
795 Pid spawnProcess(scope const(char[])[] args,
796                  File stdin = std.stdio.stdin,
797                  File stdout = std.stdio.stdout,
798                  File stderr = std.stdio.stderr,
799                  const string[string] env = null,
800                  Config config = Config.none,
801                  scope const char[] workDir = null)
802     @safe
803 {
804     version (Windows)
805     {
806         const commandLine = escapeShellArguments(args);
807         const program = args.length ? args[0] : null;
808         return spawnProcessWin(commandLine, program, stdin, stdout, stderr, env, config, workDir);
809     }
810     else version (Posix)
811     {
812         return spawnProcessPosix(args, stdin, stdout, stderr, env, config, workDir);
813     }
814     else
815         static assert(0);
816 }
817 
818 /// ditto
819 Pid spawnProcess(scope const(char[])[] args,
820                  const string[string] env,
821                  Config config = Config.none,
822                  scope const(char)[] workDir = null)
823     @trusted // TODO: Should be @safe
824 {
825     return spawnProcess(args,
826                         std.stdio.stdin,
827                         std.stdio.stdout,
828                         std.stdio.stderr,
829                         env,
830                         config,
831                         workDir);
832 }
833 
834 /// ditto
835 Pid spawnProcess(scope const(char)[] program,
836                  File stdin = std.stdio.stdin,
837                  File stdout = std.stdio.stdout,
838                  File stderr = std.stdio.stderr,
839                  const string[string] env = null,
840                  Config config = Config.none,
841                  scope const(char)[] workDir = null)
842     @trusted
843 {
844     return spawnProcess((&program)[0 .. 1],
845                         stdin, stdout, stderr, env, config, workDir);
846 }
847 
848 /// ditto
849 Pid spawnProcess(scope const(char)[] program,
850                  const string[string] env,
851                  Config config = Config.none,
852                  scope const(char)[] workDir = null)
853     @trusted
854 {
855     return spawnProcess((&program)[0 .. 1], env, config, workDir);
856 }
857 
858 version (Posix) private enum InternalError : ubyte
859 {
860     noerror,
861     exec,
862     chdir,
863     getrlimit,
864     doubleFork,
865     malloc,
866     preExec,
867     closefds_dup2,
868 }
869 
870 /*
871 Implementation of spawnProcess() for POSIX.
872 
873 envz should be a zero-terminated array of zero-terminated strings
874 on the form "var=value".
875 */
876 version (Posix)
877 private Pid spawnProcessPosix(scope const(char[])[] args,
878                               File stdin,
879                               File stdout,
880                               File stderr,
881                               scope const string[string] env,
882                               Config config,
883                               scope const(char)[] workDir)
884     @trusted // TODO: Should be @safe
885 {
886     import core.exception : RangeError;
887     import std.algorithm.searching : any;
888     import std.conv : text;
889     import std.path : isDirSeparator;
890     import std.string : toStringz;
891 
892     if (args.empty) throw new RangeError();
893     const(char)[] name = args[0];
894     if (!any!isDirSeparator(name))
895     {
896         name = searchPathFor(name);
897         if (name is null)
898             throw new ProcessException(text("Executable file not found: ", args[0]));
899     }
900 
901     // Convert program name and arguments to C-style strings.
902     auto argz = new const(char)*[args.length+1];
903     argz[0] = toStringz(name);
904     foreach (i; 1 .. args.length) argz[i] = toStringz(args[i]);
905     argz[$-1] = null;
906 
907     // Prepare environment.
908     auto envz = createEnv(env, !(config.flags & Config.Flags.newEnv));
909 
910     // Open the working directory.
911     // We use open in the parent and fchdir in the child
912     // so that most errors (directory doesn't exist, not a directory)
913     // can be propagated as exceptions before forking.
914     int workDirFD = -1;
915     scope(exit) if (workDirFD >= 0) close(workDirFD);
916     if (workDir.length)
917     {
918         import core.sys.posix.fcntl : open, O_RDONLY, stat_t, fstat, S_ISDIR;
919         workDirFD = open(workDir.tempCString(), O_RDONLY);
920         if (workDirFD < 0)
921             throw ProcessException.newFromErrno("Failed to open working directory");
922         stat_t s;
923         if (fstat(workDirFD, &s) < 0)
924             throw ProcessException.newFromErrno("Failed to stat working directory");
925         if (!S_ISDIR(s.st_mode))
926             throw new ProcessException("Not a directory: " ~ cast(string) workDir);
927     }
928 
929     static int getFD(ref File f) { return core.stdc.stdio.fileno(f.getFP()); }
930 
931     // Get the file descriptors of the streams.
932     // These could potentially be invalid, but that is OK.  If so, later calls
933     // to dup2() and close() will just silently fail without causing any harm.
934     auto stdinFD  = getFD(stdin);
935     auto stdoutFD = getFD(stdout);
936     auto stderrFD = getFD(stderr);
937 
938     // We don't have direct access to the errors that may happen in a child process.
939     // So we use this pipe to deliver them.
940     int[2] forkPipe;
941     if (core.sys.posix.unistd.pipe(forkPipe) == 0)
942         setCLOEXEC(forkPipe[1], true);
943     else
944         throw ProcessException.newFromErrno("Could not create pipe to check startup of child");
945     scope(exit) close(forkPipe[0]);
946 
947     /*
948     To create detached process, we use double fork technique
949     but we don't have a direct access to the second fork pid from the caller side thus use a pipe.
950     We also can't reuse forkPipe for that purpose
951     because we can't predict the order in which pid and possible error will be written
952     since the first and the second forks will run in parallel.
953     */
954     int[2] pidPipe;
955     if (config.flags & Config.Flags.detached)
956     {
957         if (core.sys.posix.unistd.pipe(pidPipe) != 0)
958             throw ProcessException.newFromErrno("Could not create pipe to get process pid");
959         setCLOEXEC(pidPipe[1], true);
960     }
961     scope(exit) if (config.flags & Config.Flags.detached) close(pidPipe[0]);
962 
963     static void abortOnError(int forkPipeOut, InternalError errorType, int error) nothrow
964     {
965         core.sys.posix.unistd.write(forkPipeOut, &errorType, errorType.sizeof);
966         core.sys.posix.unistd.write(forkPipeOut, &error, error.sizeof);
967         close(forkPipeOut);
968         core.sys.posix.unistd._exit(1);
969         assert(0);
970     }
971 
972     void closePipeWriteEnds()
973     {
974         close(forkPipe[1]);
975         if (config.flags & Config.Flags.detached)
976             close(pidPipe[1]);
977     }
978 
979     auto id = core.sys.posix.unistd.fork();
980     if (id < 0)
981     {
982         closePipeWriteEnds();
983         throw ProcessException.newFromErrno("Failed to spawn new process");
984     }
985 
986     void forkChild() nothrow @nogc
987     {
988         static import core.sys.posix.stdio;
989 
990         // Child process
991 
992         // no need for the read end of pipe on child side
993         if (config.flags & Config.Flags.detached)
994             close(pidPipe[0]);
995         close(forkPipe[0]);
996         auto forkPipeOut = forkPipe[1];
997         immutable pidPipeOut = pidPipe[1];
998 
999         // Set the working directory.
1000         if (workDirFD >= 0)
1001         {
1002             if (fchdir(workDirFD) < 0)
1003             {
1004                 // Fail. It is dangerous to run a program
1005                 // in an unexpected working directory.
1006                 abortOnError(forkPipeOut, InternalError.chdir, .errno);
1007             }
1008             close(workDirFD);
1009         }
1010 
1011         void execProcess()
1012         {
1013             // Redirect streams and close the old file descriptors.
1014             // In the case that stderr is redirected to stdout, we need
1015             // to backup the file descriptor since stdout may be redirected
1016             // as well.
1017             if (stderrFD == STDOUT_FILENO) stderrFD = dup(stderrFD);
1018             dup2(stdinFD,  STDIN_FILENO);
1019             dup2(stdoutFD, STDOUT_FILENO);
1020             dup2(stderrFD, STDERR_FILENO);
1021 
1022             // Ensure that the standard streams aren't closed on execute, and
1023             // optionally close all other file descriptors.
1024             setCLOEXEC(STDIN_FILENO, false);
1025             setCLOEXEC(STDOUT_FILENO, false);
1026             setCLOEXEC(STDERR_FILENO, false);
1027 
1028             if (!(config.flags & Config.Flags.inheritFDs))
1029             {
1030                 version (FreeBSD)
1031                     import core.sys.freebsd.unistd : closefrom;
1032                 else version (OpenBSD)
1033                     import core.sys.openbsd.unistd : closefrom;
1034 
1035                 static if (!__traits(compiles, closefrom))
1036                 {
1037                     void fallback (int lowfd)
1038                     {
1039                         import core.sys.posix.dirent : dirent, opendir, readdir, closedir, DIR;
1040                         import core.sys.posix.unistd : close;
1041                         import core.sys.posix.stdlib : atoi, malloc, free;
1042                         import core.sys.posix.sys.resource : rlimit, getrlimit, RLIMIT_NOFILE;
1043 
1044                         // Get the maximum number of file descriptors that could be open.
1045                         rlimit r;
1046                         if (getrlimit(RLIMIT_NOFILE, &r) != 0)
1047                             abortOnError(forkPipeOut, InternalError.getrlimit, .errno);
1048 
1049                         immutable maxDescriptors = cast(int) r.rlim_cur;
1050 
1051                         // Missing druntime declaration
1052                         pragma(mangle, "dirfd")
1053                         extern(C) nothrow @nogc int dirfd(DIR* dir);
1054 
1055                         DIR* dir = null;
1056 
1057                         // We read from /dev/fd or /proc/self/fd only if the limit is high enough
1058                         if (maxDescriptors > 128*1024)
1059                         {
1060                             // Try to open the directory /dev/fd or /proc/self/fd
1061                             dir = opendir("/dev/fd");
1062                             if (dir is null) dir = opendir("/proc/self/fd");
1063                         }
1064 
1065                         // If we have a directory, close all file descriptors except stdin, stdout, and stderr
1066                         if (dir)
1067                         {
1068                             scope(exit) closedir(dir);
1069 
1070                             int opendirfd = dirfd(dir);
1071 
1072                             // Iterate over all file descriptors
1073                             while (true)
1074                             {
1075                                 dirent* entry = readdir(dir);
1076 
1077                                 if (entry is null) break;
1078                                 if (entry.d_name[0] == '.') continue;
1079 
1080                                 int fd = atoi(cast(char*) entry.d_name);
1081 
1082                                 // Don't close stdin, stdout, stderr, or the directory file descriptor
1083                                 if (fd < lowfd || fd == opendirfd) continue;
1084 
1085                                 close(fd);
1086                             }
1087                         }
1088                         else
1089                         {
1090                             // This is going to allocate 8 bytes for each possible file descriptor from lowfd to r.rlim_cur
1091                             if (maxDescriptors <= 128*1024)
1092                             {
1093                                 // NOTE: malloc() and getrlimit() are not on the POSIX async
1094                                 // signal safe functions list, but practically this should
1095                                 // not be a problem. Java VM and CPython also use malloc()
1096                                 // in its own implementation via opendir().
1097                                 import core.stdc.stdlib : malloc;
1098                                 import core.sys.posix.poll : pollfd, poll, POLLNVAL;
1099 
1100                                 immutable maxToClose = maxDescriptors - lowfd;
1101 
1102                                 // Call poll() to see which ones are actually open:
1103                                 auto pfds = cast(pollfd*) malloc(pollfd.sizeof * maxToClose);
1104                                 if (pfds is null)
1105                                 {
1106                                     abortOnError(forkPipeOut, InternalError.malloc, .errno);
1107                                 }
1108 
1109                                 foreach (i; 0 .. maxToClose)
1110                                 {
1111                                     pfds[i].fd = i + lowfd;
1112                                     pfds[i].events = 0;
1113                                     pfds[i].revents = 0;
1114                                 }
1115 
1116                                 if (poll(pfds, maxToClose, 0) < 0)
1117                                     // couldn't use poll, use the slow path.
1118                                     goto LslowClose;
1119 
1120                                 foreach (i; 0 .. maxToClose)
1121                                 {
1122                                     // POLLNVAL will be set if the file descriptor is invalid.
1123                                     if (!(pfds[i].revents & POLLNVAL)) close(pfds[i].fd);
1124                                 }
1125                             }
1126                             else
1127                             {
1128                             LslowClose:
1129                                 // Fall back to closing everything.
1130                                 foreach (i; lowfd .. maxDescriptors)
1131                                 {
1132                                     close(i);
1133                                 }
1134                             }
1135                         }
1136                     }
1137 
1138                     // closefrom may not be available on the version of glibc we build against.
1139                     // Until we find a way to perform this check we will try to use dlsym to
1140                     // check for the function. See: https://github.com/dlang/phobos/pull/9048
1141                     version (CRuntime_Glibc)
1142                     {
1143                         void closefrom (int lowfd) {
1144                             static bool tryGlibcClosefrom (int lowfd) {
1145                                 import core.sys.posix.dlfcn : dlopen, dlclose, dlsym, dlerror, RTLD_LAZY;
1146 
1147                                 void *handle = dlopen("libc.so.6", RTLD_LAZY);
1148                                 if (!handle)
1149                                     return false;
1150                                 scope(exit) dlclose(handle);
1151 
1152                                 // Clear errors
1153                                 dlerror();
1154                                 alias closefromT = extern(C) void function(int) @nogc @system nothrow;
1155                                 auto closefrom = cast(closefromT) dlsym(handle, "closefrom");
1156                                 if (dlerror())
1157                                     return false;
1158 
1159                                 closefrom(lowfd);
1160                                 return true;
1161                             }
1162 
1163                             if (!tryGlibcClosefrom(lowfd))
1164                                 fallback(lowfd);
1165                         }
1166                     }
1167                     else
1168                         alias closefrom = fallback;
1169                 }
1170 
1171                 // We need to close all open file descriptors excluding std{in,out,err}
1172                 // and forkPipeOut because we still need it.
1173                 // Since the various libc's provide us with `closefrom` move forkPipeOut
1174                 // to position 3, right after STDERR_FILENO, and close all FDs following that.
1175                 if (dup2(forkPipeOut, 3) == -1)
1176                     abortOnError(forkPipeOut, InternalError.closefds_dup2, .errno);
1177                 forkPipeOut = 3;
1178                 // forkPipeOut needs to be closed after we call `exec`.
1179                 setCLOEXEC(forkPipeOut, true);
1180                 closefrom(forkPipeOut + 1);
1181             }
1182             else // This is already done if we don't inherit descriptors.
1183             {
1184                 // Close the old file descriptors, unless they are
1185                 // either of the standard streams.
1186                 if (stdinFD  > STDERR_FILENO)  close(stdinFD);
1187                 if (stdoutFD > STDERR_FILENO)  close(stdoutFD);
1188                 if (stderrFD > STDERR_FILENO)  close(stderrFD);
1189             }
1190 
1191             if (config.preExecFunction !is null)
1192             {
1193                 if (config.preExecFunction() != true)
1194                 {
1195                     abortOnError(forkPipeOut, InternalError.preExec, .errno);
1196                 }
1197             }
1198 
1199             if (config.preExecDelegate !is null)
1200             {
1201                 if (config.preExecDelegate() != true)
1202                 {
1203                     abortOnError(forkPipeOut, InternalError.preExec, .errno);
1204                 }
1205             }
1206 
1207             // Execute program.
1208             core.sys.posix.unistd.execve(argz[0], argz.ptr, envz is null ? getEnvironPtr : envz);
1209 
1210             // If execution fails, exit as quickly as possible.
1211             abortOnError(forkPipeOut, InternalError.exec, .errno);
1212         }
1213 
1214         if (config.flags & Config.Flags.detached)
1215         {
1216             auto secondFork = core.sys.posix.unistd.fork();
1217             if (secondFork == 0)
1218             {
1219                 close(pidPipeOut);
1220                 execProcess();
1221             }
1222             else if (secondFork == -1)
1223             {
1224                 auto secondForkErrno = .errno;
1225                 close(pidPipeOut);
1226                 abortOnError(forkPipeOut, InternalError.doubleFork, secondForkErrno);
1227             }
1228             else
1229             {
1230                 core.sys.posix.unistd.write(pidPipeOut, &secondFork, pid_t.sizeof);
1231                 close(pidPipeOut);
1232                 close(forkPipeOut);
1233                 _exit(0);
1234             }
1235         }
1236         else
1237         {
1238             execProcess();
1239         }
1240     }
1241 
1242     if (id == 0)
1243     {
1244         forkChild();
1245         assert(0);
1246     }
1247     else
1248     {
1249         closePipeWriteEnds();
1250         auto status = InternalError.noerror;
1251         auto readExecResult = core.sys.posix.unistd.read(forkPipe[0], &status, status.sizeof);
1252         // Save error number just in case if subsequent "waitpid" fails and overrides errno
1253         immutable lastError = .errno;
1254 
1255         if (config.flags & Config.Flags.detached)
1256         {
1257             // Forked child exits right after creating second fork. So it should be safe to wait here.
1258             import core.sys.posix.sys.wait : waitpid;
1259             int waitResult;
1260             waitpid(id, &waitResult, 0);
1261         }
1262 
1263         if (readExecResult == -1)
1264             throw ProcessException.newFromErrno(lastError, "Could not read from pipe to get child status");
1265 
1266         bool owned = true;
1267         if (status != InternalError.noerror)
1268         {
1269             int error;
1270             readExecResult = read(forkPipe[0], &error, error.sizeof);
1271             string errorMsg;
1272             final switch (status)
1273             {
1274                 case InternalError.chdir:
1275                     errorMsg = "Failed to set working directory";
1276                     break;
1277                 case InternalError.getrlimit:
1278                     errorMsg = "getrlimit failed";
1279                     break;
1280                 case InternalError.exec:
1281                     errorMsg = "Failed to execute '" ~ cast(string) name ~ "'";
1282                     break;
1283                 case InternalError.doubleFork:
1284                     // Can happen only when starting detached process
1285                     assert(config.flags & Config.Flags.detached);
1286                     errorMsg = "Failed to fork twice";
1287                     break;
1288                 case InternalError.malloc:
1289                     errorMsg = "Failed to allocate memory";
1290                     break;
1291                 case InternalError.preExec:
1292                     errorMsg = "Failed to execute preExecFunction or preExecDelegate";
1293                     break;
1294                 case InternalError.closefds_dup2:
1295                     assert(!(config.flags & Config.Flags.inheritFDs));
1296                     errorMsg = "Failed to close inherited file descriptors";
1297                     break;
1298                 case InternalError.noerror:
1299                     assert(false);
1300             }
1301             if (readExecResult == error.sizeof)
1302                 throw ProcessException.newFromErrno(error, errorMsg);
1303             throw new ProcessException(errorMsg);
1304         }
1305         else if (config.flags & Config.Flags.detached)
1306         {
1307             owned = false;
1308             if (read(pidPipe[0], &id, id.sizeof) != id.sizeof)
1309                 throw ProcessException.newFromErrno("Could not read from pipe to get detached process id");
1310         }
1311 
1312         // Parent process:  Close streams and return.
1313         if (!(config.flags & Config.Flags.retainStdin ) && stdinFD  > STDERR_FILENO
1314                                             && stdinFD  != getFD(std.stdio.stdin ))
1315             stdin.close();
1316         if (!(config.flags & Config.Flags.retainStdout) && stdoutFD > STDERR_FILENO
1317                                             && stdoutFD != getFD(std.stdio.stdout))
1318             stdout.close();
1319         if (!(config.flags & Config.Flags.retainStderr) && stderrFD > STDERR_FILENO
1320                                             && stderrFD != getFD(std.stdio.stderr))
1321             stderr.close();
1322         return new Pid(id, owned);
1323     }
1324 }
1325 
1326 version (Posix)
1327 @system unittest
1328 {
1329     import std.concurrency : ownerTid, receiveTimeout, send, spawn;
1330     import std.datetime : seconds;
1331 
1332     sigset_t ss;
1333     sigemptyset(&ss);
1334     sigaddset(&ss, SIGINT);
1335     pthread_sigmask(SIG_BLOCK, &ss, null);
1336 
1337     Config config = {
1338         preExecFunction: () @trusted @nogc nothrow {
1339             // Reset signal handlers
1340             sigset_t ss;
1341             if (sigfillset(&ss) != 0)
1342             {
1343                 return false;
1344             }
1345             if (sigprocmask(SIG_UNBLOCK, &ss, null) != 0)
1346             {
1347                 return false;
1348             }
1349             return true;
1350         },
1351     };
1352 
1353     auto pid = spawnProcess(["sleep", "10000"],
1354                             std.stdio.stdin,
1355                             std.stdio.stdout,
1356                             std.stdio.stderr,
1357                             null,
1358                             config,
1359                             null);
1360     scope(failure)
1361     {
1362         kill(pid, SIGKILL);
1363         wait(pid);
1364     }
1365 
1366     // kill the spawned process with SIGINT
1367     // and send its return code
1368     spawn((shared Pid pid) {
1369         auto p = cast() pid;
1370         kill(p, SIGINT);
1371         auto code = wait(p);
1372         assert(code < 0);
1373         send(ownerTid, code);
1374     }, cast(shared) pid);
1375 
1376     auto received = receiveTimeout(3.seconds, (int) {});
1377     assert(received);
1378 }
1379 
1380 version (Posix)
1381 @system unittest
1382 {
1383     __gshared int j;
1384     foreach (i; 0 .. 3)
1385     {
1386         auto config = Config(
1387             preExecFunction: function() @trusted {
1388                 j = 1;
1389                 return true;
1390             },
1391             preExecDelegate: delegate() @trusted {
1392                 // j should now be 1, as preExecFunction is called before
1393                 // preExecDelegate is.
1394                 _Exit(i + j);
1395                 return true;
1396             },
1397         );
1398         auto pid = spawnProcess(["false"], config: config);
1399         assert(wait(pid) == i + 1);
1400     }
1401 }
1402 
1403 /*
1404 Implementation of spawnProcess() for Windows.
1405 
1406 commandLine must contain the entire command line, properly
1407 quoted/escaped as required by CreateProcessW().
1408 
1409 envz must be a pointer to a block of UTF-16 characters on the form
1410 "var1=value1\0var2=value2\0...varN=valueN\0\0".
1411 */
1412 version (Windows)
1413 private Pid spawnProcessWin(scope const(char)[] commandLine,
1414                             scope const(char)[] program,
1415                             File stdin,
1416                             File stdout,
1417                             File stderr,
1418                             scope const string[string] env,
1419                             Config config,
1420                             scope const(char)[] workDir)
1421     @trusted
1422 {
1423     import core.exception : RangeError;
1424     import std.conv : text;
1425 
1426     if (commandLine.empty) throw new RangeError("Command line is empty");
1427 
1428     // Prepare environment.
1429     auto envz = createEnv(env, !(config.flags & Config.Flags.newEnv));
1430 
1431     // Startup info for CreateProcessW().
1432     STARTUPINFO_W startinfo;
1433     startinfo.cb = startinfo.sizeof;
1434     static int getFD(ref File f) { return f.isOpen ? f.fileno : -1; }
1435 
1436     // Extract file descriptors and HANDLEs from the streams and make the
1437     // handles inheritable.
1438     static void prepareStream(ref File file, DWORD stdHandle, string which,
1439                               out int fileDescriptor, out HANDLE handle)
1440     {
1441         enum _NO_CONSOLE_FILENO = cast(HANDLE)-2;
1442         fileDescriptor = getFD(file);
1443         handle = null;
1444         if (fileDescriptor >= 0)
1445             handle = file.windowsHandle;
1446         // Windows GUI applications have a fd but not a valid Windows HANDLE.
1447         if (handle is null || handle == INVALID_HANDLE_VALUE || handle == _NO_CONSOLE_FILENO)
1448             handle = GetStdHandle(stdHandle);
1449 
1450         DWORD dwFlags;
1451         if (GetHandleInformation(handle, &dwFlags))
1452         {
1453             if (!(dwFlags & HANDLE_FLAG_INHERIT))
1454             {
1455                 if (!SetHandleInformation(handle,
1456                                           HANDLE_FLAG_INHERIT,
1457                                           HANDLE_FLAG_INHERIT))
1458                 {
1459                     throw new StdioException(
1460                         "Failed to make "~which~" stream inheritable by child process ("
1461                         ~generateSysErrorMsg() ~ ')',
1462                         0);
1463                 }
1464             }
1465         }
1466     }
1467     int stdinFD = -1, stdoutFD = -1, stderrFD = -1;
1468     prepareStream(stdin,  STD_INPUT_HANDLE,  "stdin" , stdinFD,  startinfo.hStdInput );
1469     prepareStream(stdout, STD_OUTPUT_HANDLE, "stdout", stdoutFD, startinfo.hStdOutput);
1470     prepareStream(stderr, STD_ERROR_HANDLE,  "stderr", stderrFD, startinfo.hStdError );
1471 
1472     if ((startinfo.hStdInput  != null && startinfo.hStdInput  != INVALID_HANDLE_VALUE)
1473      || (startinfo.hStdOutput != null && startinfo.hStdOutput != INVALID_HANDLE_VALUE)
1474      || (startinfo.hStdError  != null && startinfo.hStdError  != INVALID_HANDLE_VALUE))
1475         startinfo.dwFlags = STARTF_USESTDHANDLES;
1476 
1477     // Create process.
1478     PROCESS_INFORMATION pi;
1479     DWORD dwCreationFlags =
1480         CREATE_UNICODE_ENVIRONMENT |
1481         ((config.flags & Config.Flags.suppressConsole) ? CREATE_NO_WINDOW : 0);
1482     // workaround until https://issues.dlang.org/show_bug.cgi?id=14696 is fixed
1483     auto pworkDir = workDir.tempCStringW();
1484     if (!CreateProcessW(null, commandLine.tempCStringW().buffPtr,
1485                         null, null, true, dwCreationFlags,
1486                         envz, workDir.length ? pworkDir : null, &startinfo, &pi))
1487         throw ProcessException.newFromLastError("Failed to spawn process \"" ~ cast(string) program ~ '"');
1488 
1489     // figure out if we should close any of the streams
1490     if (!(config.flags & Config.Flags.retainStdin ) && stdinFD  > STDERR_FILENO
1491                                         && stdinFD  != getFD(std.stdio.stdin ))
1492         stdin.close();
1493     if (!(config.flags & Config.Flags.retainStdout) && stdoutFD > STDERR_FILENO
1494                                         && stdoutFD != getFD(std.stdio.stdout))
1495         stdout.close();
1496     if (!(config.flags & Config.Flags.retainStderr) && stderrFD > STDERR_FILENO
1497                                         && stderrFD != getFD(std.stdio.stderr))
1498         stderr.close();
1499 
1500     // close the thread handle in the process info structure
1501     CloseHandle(pi.hThread);
1502     if (config.flags & Config.Flags.detached)
1503     {
1504         CloseHandle(pi.hProcess);
1505         return new Pid(pi.dwProcessId);
1506     }
1507     return new Pid(pi.dwProcessId, pi.hProcess);
1508 }
1509 
1510 // Converts childEnv to a zero-terminated array of zero-terminated strings
1511 // on the form "name=value", optionally adding those of the current process'
1512 // environment strings that are not present in childEnv.  If the parent's
1513 // environment should be inherited without modification, this function
1514 // returns null.
1515 version (Posix)
1516 private const(char*)* createEnv(const string[string] childEnv,
1517                                 bool mergeWithParentEnv)
1518 {
1519     // Determine the number of strings in the parent's environment.
1520     int parentEnvLength = 0;
1521     auto environ = getEnvironPtr;
1522     if (mergeWithParentEnv)
1523     {
1524         if (childEnv.length == 0) return null;
1525         while (environ[parentEnvLength] != null) ++parentEnvLength;
1526     }
1527 
1528     // Convert the "new" variables to C-style strings.
1529     auto envz = new const(char)*[parentEnvLength + childEnv.length + 1];
1530     int pos = 0;
1531     foreach (var, val; childEnv)
1532         envz[pos++] = (var~'='~val~'\0').ptr;
1533 
1534     // Add the parent's environment.
1535     foreach (environStr; environ[0 .. parentEnvLength])
1536     {
1537         int eqPos = 0;
1538         while (environStr[eqPos] != '=' && environStr[eqPos] != '\0') ++eqPos;
1539         if (environStr[eqPos] != '=') continue;
1540         auto var = environStr[0 .. eqPos];
1541         if (var in childEnv) continue;
1542         envz[pos++] = environStr;
1543     }
1544     envz[pos] = null;
1545     return envz.ptr;
1546 }
1547 
1548 version (Posix) @system unittest
1549 {
1550     auto e1 = createEnv(null, false);
1551     assert(e1 != null && *e1 == null);
1552 
1553     auto e2 = createEnv(null, true);
1554     assert(e2 == null);
1555 
1556     auto e3 = createEnv(["foo" : "bar", "hello" : "world"], false);
1557     assert(e3 != null && e3[0] != null && e3[1] != null && e3[2] == null);
1558     assert((e3[0][0 .. 8] == "foo=bar\0" && e3[1][0 .. 12] == "hello=world\0")
1559          || (e3[0][0 .. 12] == "hello=world\0" && e3[1][0 .. 8] == "foo=bar\0"));
1560 }
1561 
1562 
1563 // Converts childEnv to a Windows environment block, which is on the form
1564 // "name1=value1\0name2=value2\0...nameN=valueN\0\0", optionally adding
1565 // those of the current process' environment strings that are not present
1566 // in childEnv.  Returns null if the parent's environment should be
1567 // inherited without modification, as this is what is expected by
1568 // CreateProcess().
1569 version (Windows)
1570 private LPVOID createEnv(const string[string] childEnv,
1571                          bool mergeWithParentEnv)
1572 {
1573     if (mergeWithParentEnv && childEnv.length == 0) return null;
1574     import std.array : appender;
1575     import std.uni : toUpper;
1576     auto envz = appender!(wchar[])();
1577     void put(string var, string val)
1578     {
1579         envz.put(var);
1580         envz.put('=');
1581         envz.put(val);
1582         envz.put(cast(wchar) '\0');
1583     }
1584 
1585     // Add the variables in childEnv, removing them from parentEnv
1586     // if they exist there too.
1587     auto parentEnv = mergeWithParentEnv ? environment.toAA() : null;
1588     foreach (k, v; childEnv)
1589     {
1590         auto uk = toUpper(k);
1591         put(uk, v);
1592         if (uk in parentEnv) parentEnv.remove(uk);
1593     }
1594 
1595     // Add remaining parent environment variables.
1596     foreach (k, v; parentEnv) put(k, v);
1597 
1598     // Two final zeros are needed in case there aren't any environment vars,
1599     // and the last one does no harm when there are.
1600     envz.put("\0\0"w);
1601     return envz.data.ptr;
1602 }
1603 
1604 version (Windows) @system unittest
1605 {
1606     assert(createEnv(null, true) == null);
1607     assert((cast(wchar*) createEnv(null, false))[0 .. 2] == "\0\0"w);
1608     auto e1 = (cast(wchar*) createEnv(["foo":"bar", "ab":"c"], false))[0 .. 14];
1609     assert(e1 == "FOO=bar\0AB=c\0\0"w || e1 == "AB=c\0FOO=bar\0\0"w);
1610 }
1611 
1612 // Searches the PATH variable for the given executable file,
1613 // (checking that it is in fact executable).
1614 version (Posix)
1615 package(std) string searchPathFor(scope const(char)[] executable)
1616     @safe
1617 {
1618     import std.algorithm.iteration : splitter;
1619     import std.conv : to;
1620     import std.path : chainPath;
1621 
1622     typeof(return) result;
1623 
1624     environment.getImpl("PATH",
1625         (scope const(char)[] path)
1626         {
1627             if (!path)
1628                 return;
1629 
1630             foreach (dir; splitter(path, ":"))
1631             {
1632                 auto execPath = chainPath(dir, executable);
1633                 if (isExecutable(execPath))
1634                 {
1635                     result = execPath.to!(typeof(result));
1636                     return;
1637                 }
1638             }
1639         });
1640 
1641     return result;
1642 }
1643 
1644 // Checks whether the file exists and can be executed by the
1645 // current user.
1646 version (Posix)
1647 private bool isExecutable(R)(R path) @trusted nothrow @nogc
1648 if (isSomeFiniteCharInputRange!R)
1649 {
1650     return (access(path.tempCString(), X_OK) == 0);
1651 }
1652 
1653 version (Posix) @safe unittest
1654 {
1655     import std.algorithm;
1656     auto lsPath = searchPathFor("ls");
1657     assert(!lsPath.empty);
1658     assert(lsPath[0] == '/');
1659     assert(lsPath.endsWith("ls"));
1660     auto unlikely = searchPathFor("lkmqwpoialhggyaofijadsohufoiqezm");
1661     assert(unlikely is null, "Are you kidding me?");
1662 }
1663 
1664 // Sets or unsets the FD_CLOEXEC flag on the given file descriptor.
1665 version (Posix)
1666 private void setCLOEXEC(int fd, bool on) nothrow @nogc
1667 {
1668     import core.sys.posix.fcntl : fcntl, F_GETFD, FD_CLOEXEC, F_SETFD;
1669     auto flags = fcntl(fd, F_GETFD);
1670     if (flags >= 0)
1671     {
1672         if (on) flags |= FD_CLOEXEC;
1673         else    flags &= ~(cast(typeof(flags)) FD_CLOEXEC);
1674         flags = fcntl(fd, F_SETFD, flags);
1675     }
1676     assert(flags != -1 || .errno == EBADF);
1677 }
1678 
1679 @system unittest // Command line arguments in spawnProcess().
1680 {
1681     version (Windows) TestScript prog =
1682        "if not [%~1]==[foo] ( exit 1 )
1683         if not [%~2]==[bar] ( exit 2 )
1684         exit 0";
1685     else version (Posix) TestScript prog =
1686        `if test "$1" != "foo"; then exit 1; fi
1687         if test "$2" != "bar"; then exit 2; fi
1688         exit 0`;
1689     assert(wait(spawnProcess(prog.path)) == 1);
1690     assert(wait(spawnProcess([prog.path])) == 1);
1691     assert(wait(spawnProcess([prog.path, "foo"])) == 2);
1692     assert(wait(spawnProcess([prog.path, "foo", "baz"])) == 2);
1693     assert(wait(spawnProcess([prog.path, "foo", "bar"])) == 0);
1694 }
1695 
1696 // test that file descriptors are correctly closed / left open.
1697 // ideally this would be done by the child process making libc
1698 // calls, but we make do...
1699 version (Posix) @system unittest
1700 {
1701     import core.stdc.errno : errno;
1702     import core.sys.posix.fcntl : open, O_RDONLY;
1703     import core.sys.posix.unistd : close;
1704     import std.algorithm.searching : canFind, findSplitBefore;
1705     import std.array : split;
1706     import std.conv : to;
1707     static import std.file;
1708     import std.functional : reverseArgs;
1709     import std.path : buildPath;
1710 
1711     auto directory = uniqueTempPath();
1712     std.file.mkdir(directory);
1713     scope(exit) std.file.rmdirRecurse(directory);
1714     auto path = buildPath(directory, "tmp");
1715     std.file.write(path, null);
1716     errno = 0;
1717     auto fd = open(path.tempCString, O_RDONLY);
1718     if (fd == -1)
1719     {
1720         import core.stdc.string : strerror;
1721         import std.stdio : stderr;
1722         import std.string : fromStringz;
1723 
1724         // For the CI logs
1725         stderr.writefln("%s: could not open '%s': %s",
1726             __FUNCTION__, path, strerror(errno).fromStringz);
1727         // TODO: should we retry here instead?
1728         return;
1729     }
1730     scope(exit) close(fd);
1731 
1732     // command >&2 (or any other number) checks whethether that number
1733     // file descriptor is open.
1734     // Can't use this for arbitrary descriptors as many shells only support
1735     // single digit fds.
1736     TestScript testDefaults = `command >&0 && command >&1 && command >&2`;
1737     assert(execute(testDefaults.path).status == 0);
1738     assert(execute(testDefaults.path, null, Config.inheritFDs).status == 0);
1739 
1740     // Try a few different methods to check whether there are any
1741     // incorrectly-open files.
1742     void testFDs()
1743     {
1744         // try /proc/<pid>/fd/ on linux
1745         version (linux)
1746         {
1747             TestScript proc = "ls /proc/$$/fd";
1748             auto procRes = execute(proc.path, null);
1749             if (procRes.status == 0)
1750             {
1751                 auto fdStr = fd.to!string;
1752                 assert(!procRes.output.split.canFind(fdStr));
1753                 assert(execute(proc.path, null, Config.inheritFDs)
1754                         .output.split.canFind(fdStr));
1755                 return;
1756             }
1757         }
1758 
1759         // try fuser (might sometimes need permissions)
1760         TestScript fuser = "echo $$ && fuser -f " ~ path;
1761         auto fuserRes = execute(fuser.path, null);
1762         if (fuserRes.status == 0)
1763         {
1764             assert(!reverseArgs!canFind(fuserRes
1765                         .output.findSplitBefore("\n").expand));
1766             assert(reverseArgs!canFind(execute(fuser.path, null, Config.inheritFDs)
1767                         .output.findSplitBefore("\n").expand));
1768             return;
1769         }
1770 
1771         // last resort, try lsof (not available on all Posix)
1772         TestScript lsof = "lsof -p$$";
1773         auto lsofRes = execute(lsof.path, null);
1774         if (lsofRes.status == 0)
1775         {
1776             assert(!lsofRes.output.canFind(path));
1777             auto lsofOut = execute(lsof.path, null, Config.inheritFDs).output;
1778             if (!lsofOut.canFind(path))
1779             {
1780                 std.stdio.stderr.writeln(__FILE__, ':', __LINE__,
1781                     ": Warning: unexpected lsof output:", lsofOut);
1782             }
1783             return;
1784         }
1785 
1786         std.stdio.stderr.writeln(__FILE__, ':', __LINE__,
1787                 ": Warning: Couldn't find any way to check open files");
1788     }
1789     testFDs();
1790 }
1791 
1792 @system unittest // Environment variables in spawnProcess().
1793 {
1794     // We really should use set /a on Windows, but Wine doesn't support it.
1795     version (Windows) TestScript envProg =
1796        `if [%STD_PROCESS_UNITTEST1%] == [1] (
1797             if [%STD_PROCESS_UNITTEST2%] == [2] (exit 3)
1798             exit 1
1799         )
1800         if [%STD_PROCESS_UNITTEST1%] == [4] (
1801             if [%STD_PROCESS_UNITTEST2%] == [2] (exit 6)
1802             exit 4
1803         )
1804         if [%STD_PROCESS_UNITTEST2%] == [2] (exit 2)
1805         exit 0`;
1806     version (Posix) TestScript envProg =
1807        `if test "$std_process_unittest1" = ""; then
1808             std_process_unittest1=0
1809         fi
1810         if test "$std_process_unittest2" = ""; then
1811             std_process_unittest2=0
1812         fi
1813         exit $(($std_process_unittest1+$std_process_unittest2))`;
1814 
1815     environment.remove("std_process_unittest1"); // Just in case.
1816     environment.remove("std_process_unittest2");
1817     assert(wait(spawnProcess(envProg.path)) == 0);
1818     assert(wait(spawnProcess(envProg.path, null, Config.newEnv)) == 0);
1819 
1820     environment["std_process_unittest1"] = "1";
1821     assert(wait(spawnProcess(envProg.path)) == 1);
1822     assert(wait(spawnProcess(envProg.path, null, Config.newEnv)) == 0);
1823 
1824     auto env = ["std_process_unittest2" : "2"];
1825     assert(wait(spawnProcess(envProg.path, env)) == 3);
1826     assert(wait(spawnProcess(envProg.path, env, Config.newEnv)) == 2);
1827 
1828     env["std_process_unittest1"] = "4";
1829     assert(wait(spawnProcess(envProg.path, env)) == 6);
1830     assert(wait(spawnProcess(envProg.path, env, Config.newEnv)) == 6);
1831 
1832     environment.remove("std_process_unittest1");
1833     assert(wait(spawnProcess(envProg.path, env)) == 6);
1834     assert(wait(spawnProcess(envProg.path, env, Config.newEnv)) == 6);
1835 }
1836 
1837 @system unittest // Stream redirection in spawnProcess().
1838 {
1839     import std.path : buildPath;
1840     import std.string;
1841     version (Windows) TestScript prog =
1842        "set /p INPUT=
1843         echo %INPUT% output %~1
1844         echo %INPUT% error %~2 1>&2
1845         echo done > %3";
1846     else version (Posix) TestScript prog =
1847        "read INPUT
1848         echo $INPUT output $1
1849         echo $INPUT error $2 >&2
1850         echo done > \"$3\"";
1851 
1852     // Pipes
1853     void testPipes(Config config)
1854     {
1855         import std.file : tempDir, exists, remove;
1856         import std.uuid : randomUUID;
1857         import std.exception : collectException;
1858         auto pipei = pipe();
1859         auto pipeo = pipe();
1860         auto pipee = pipe();
1861         auto done = buildPath(tempDir(), randomUUID().toString());
1862         auto pid = spawnProcess([prog.path, "foo", "bar", done],
1863                                     pipei.readEnd, pipeo.writeEnd, pipee.writeEnd, null, config);
1864         pipei.writeEnd.writeln("input");
1865         pipei.writeEnd.flush();
1866         assert(pipeo.readEnd.readln().chomp() == "input output foo");
1867         assert(pipee.readEnd.readln().chomp().stripRight() == "input error bar");
1868         if (config.flags & Config.Flags.detached)
1869             while (!done.exists) Thread.sleep(10.msecs);
1870         else
1871             wait(pid);
1872         while (remove(done).collectException) Thread.sleep(10.msecs);
1873     }
1874 
1875     // Files
1876     void testFiles(Config config)
1877     {
1878         import std.ascii : newline;
1879         import std.file : tempDir, exists, remove, readText, write;
1880         import std.uuid : randomUUID;
1881         import std.exception : collectException;
1882         auto pathi = buildPath(tempDir(), randomUUID().toString());
1883         auto patho = buildPath(tempDir(), randomUUID().toString());
1884         auto pathe = buildPath(tempDir(), randomUUID().toString());
1885         write(pathi, "INPUT" ~ newline);
1886         auto filei = File(pathi, "r");
1887         auto fileo = File(patho, "w");
1888         auto filee = File(pathe, "w");
1889         auto done = buildPath(tempDir(), randomUUID().toString());
1890         auto pid = spawnProcess([prog.path, "bar", "baz", done], filei, fileo, filee, null, config);
1891         if (config.flags & Config.Flags.detached)
1892             while (!done.exists) Thread.sleep(10.msecs);
1893         else
1894             wait(pid);
1895         assert(readText(patho).chomp() == "INPUT output bar");
1896         assert(readText(pathe).chomp().stripRight() == "INPUT error baz");
1897         while (remove(pathi).collectException) Thread.sleep(10.msecs);
1898         while (remove(patho).collectException) Thread.sleep(10.msecs);
1899         while (remove(pathe).collectException) Thread.sleep(10.msecs);
1900         while (remove(done).collectException) Thread.sleep(10.msecs);
1901     }
1902 
1903     testPipes(Config.none);
1904     testFiles(Config.none);
1905     testPipes(Config.detached);
1906     testFiles(Config.detached);
1907 }
1908 
1909 @system unittest // Error handling in spawnProcess()
1910 {
1911     import std.algorithm.searching : canFind;
1912     import std.exception : assertThrown, collectExceptionMsg;
1913 
1914     static void testNotFoundException(string program)
1915     {
1916         assert(collectExceptionMsg!ProcessException(spawnProcess(program)).canFind(program));
1917         assert(collectExceptionMsg!ProcessException(spawnProcess(program, null, Config.detached)).canFind(program));
1918     }
1919     testNotFoundException("ewrgiuhrifuheiohnmnvqweoijwf");
1920     testNotFoundException("./rgiuhrifuheiohnmnvqweoijwf");
1921 
1922     // can't execute malformed file with executable permissions
1923     version (Posix)
1924     {
1925         import std.path : buildPath;
1926         import std.file : remove, write, setAttributes, tempDir;
1927         import core.sys.posix.sys.stat : S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IXGRP, S_IROTH, S_IXOTH;
1928         import std.conv : to;
1929         string deleteme = buildPath(tempDir(), "deleteme.std.process.unittest.pid") ~ to!string(thisProcessID);
1930         write(deleteme, "");
1931         scope(exit) remove(deleteme);
1932         setAttributes(deleteme, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
1933         assertThrown!ProcessException(spawnProcess(deleteme));
1934         assertThrown!ProcessException(spawnProcess(deleteme, null, Config.detached));
1935     }
1936 }
1937 
1938 @system unittest // Specifying a working directory.
1939 {
1940     import std.path;
1941     import std.file;
1942     TestScript prog = "echo foo>bar";
1943 
1944     auto directory = uniqueTempPath();
1945     mkdir(directory);
1946     scope(exit) rmdirRecurse(directory);
1947 
1948     auto pid = spawnProcess([prog.path], null, Config.none, directory);
1949     wait(pid);
1950     assert(exists(buildPath(directory, "bar")));
1951 }
1952 
1953 @system unittest // Specifying a bad working directory.
1954 {
1955     import std.exception : assertThrown;
1956     import std.file;
1957     TestScript prog = "echo";
1958 
1959     auto directory = uniqueTempPath();
1960     assertThrown!ProcessException(spawnProcess([prog.path], null, Config.none, directory));
1961     assertThrown!ProcessException(spawnProcess([prog.path], null, Config.detached, directory));
1962 
1963     std.file.write(directory, "foo");
1964     scope(exit) remove(directory);
1965     assertThrown!ProcessException(spawnProcess([prog.path], null, Config.none, directory));
1966     assertThrown!ProcessException(spawnProcess([prog.path], null, Config.detached, directory));
1967 
1968     // can't run in directory if user does not have search permission on this directory
1969     version (Posix)
1970     {
1971         if (core.sys.posix.unistd.getuid() != 0)
1972         {
1973             import core.sys.posix.sys.stat : S_IRUSR;
1974             auto directoryNoSearch = uniqueTempPath();
1975             mkdir(directoryNoSearch);
1976             scope(exit) rmdirRecurse(directoryNoSearch);
1977             setAttributes(directoryNoSearch, S_IRUSR);
1978             assertThrown!ProcessException(spawnProcess(prog.path, null, Config.none, directoryNoSearch));
1979             assertThrown!ProcessException(spawnProcess(prog.path, null, Config.detached, directoryNoSearch));
1980         }
1981     }
1982 }
1983 
1984 @system unittest // Specifying empty working directory.
1985 {
1986     TestScript prog = "";
1987 
1988     string directory = "";
1989     assert(directory.ptr && !directory.length);
1990     spawnProcess([prog.path], null, Config.none, directory).wait();
1991 }
1992 
1993 // Reopening the standard streams (https://issues.dlang.org/show_bug.cgi?id=13258)
1994 @system unittest
1995 {
1996     import std.string;
1997     import std.file;
1998     void fun()
1999     {
2000         spawnShell("echo foo").wait();
2001         spawnShell("echo bar").wait();
2002     }
2003 
2004     auto tmpFile = uniqueTempPath();
2005     scope(exit) if (exists(tmpFile)) remove(tmpFile);
2006 
2007     {
2008         auto oldOut = std.stdio.stdout;
2009         scope(exit) std.stdio.stdout = oldOut;
2010 
2011         std.stdio.stdout = File(tmpFile, "w");
2012         fun();
2013         std.stdio.stdout.close();
2014     }
2015 
2016     auto lines = readText(tmpFile).splitLines();
2017     assert(lines == ["foo", "bar"]);
2018 }
2019 
2020 // MSVCRT workaround (https://issues.dlang.org/show_bug.cgi?id=14422)
2021 version (Windows)
2022 @system unittest
2023 {
2024     auto fn = uniqueTempPath();
2025     scope(exit) if (exists(fn)) remove(fn);
2026     std.file.write(fn, "AAAAAAAAAA");
2027 
2028     auto f = File(fn, "a");
2029     spawnProcess(["cmd", "/c", "echo BBBBB"], std.stdio.stdin, f).wait();
2030 
2031     auto data = readText(fn);
2032     assert(data == "AAAAAAAAAABBBBB\r\n", data);
2033 }
2034 
2035 // https://issues.dlang.org/show_bug.cgi?id=20765
2036 // Test that running processes with relative path works in conjunction
2037 // with indicating a workDir.
2038 version (Posix) @system unittest
2039 {
2040     import std.file : mkdir, write, setAttributes, rmdirRecurse;
2041     import std.conv : octal;
2042 
2043     auto dir = uniqueTempPath();
2044     mkdir(dir);
2045     scope(exit) rmdirRecurse(dir);
2046     write(dir ~ "/program", "#!/bin/sh\necho Hello");
2047     setAttributes(dir ~ "/program", octal!700);
2048 
2049     assert(execute(["./program"], null, Config.none, size_t.max, dir).output == "Hello\n");
2050 }
2051 
2052 /**
2053 A variation on $(LREF spawnProcess) that runs the given _command through
2054 the current user's preferred _command interpreter (aka. shell).
2055 
2056 The string `command` is passed verbatim to the shell, and is therefore
2057 subject to its rules about _command structure, argument/filename quoting
2058 and escaping of special characters.
2059 The path to the shell executable defaults to $(LREF nativeShell).
2060 
2061 In all other respects this function works just like `spawnProcess`.
2062 Please refer to the $(LREF spawnProcess) documentation for descriptions
2063 of the other function parameters, the return value and any exceptions
2064 that may be thrown.
2065 ---
2066 // Run the command/program "foo" on the file named "my file.txt", and
2067 // redirect its output into foo.log.
2068 auto pid = spawnShell(`foo "my file.txt" > foo.log`);
2069 wait(pid);
2070 ---
2071 
2072 See_also:
2073 $(LREF escapeShellCommand), which may be helpful in constructing a
2074 properly quoted and escaped shell _command line for the current platform.
2075 */
2076 Pid spawnShell(scope const(char)[] command,
2077                File stdin = std.stdio.stdin,
2078                File stdout = std.stdio.stdout,
2079                File stderr = std.stdio.stderr,
2080                scope const string[string] env = null,
2081                Config config = Config.none,
2082                scope const(char)[] workDir = null,
2083                scope string shellPath = nativeShell)
2084     @trusted // See reason below
2085 {
2086     version (Windows)
2087     {
2088         // CMD does not parse its arguments like other programs.
2089         // It does not use CommandLineToArgvW.
2090         // Instead, it treats the first and last quote specially.
2091         // See CMD.EXE /? for details.
2092         const commandLine = escapeShellFileName(shellPath)
2093                             ~ ` ` ~ shellSwitch ~ ` "` ~ command ~ `"`;
2094         return spawnProcessWin(commandLine, shellPath, stdin, stdout, stderr, env, config, workDir);
2095     }
2096     else version (Posix)
2097     {
2098         const(char)[][3] args;
2099         args[0] = shellPath;
2100         args[1] = shellSwitch;
2101         args[2] = command;
2102         /* The passing of args converts the static array, which is initialized with `scope` pointers,
2103          * to a dynamic array, which is also a scope parameter. So, it is a scope pointer to a
2104          * scope pointer, which although is safely used here, D doesn't allow transitive scope.
2105          * See https://github.com/dlang/dmd/pull/10951
2106          */
2107         return spawnProcessPosix(args, stdin, stdout, stderr, env, config, workDir);
2108     }
2109     else
2110         static assert(0);
2111 }
2112 
2113 /// ditto
2114 Pid spawnShell(scope const(char)[] command,
2115                scope const string[string] env,
2116                Config config = Config.none,
2117                scope const(char)[] workDir = null,
2118                scope string shellPath = nativeShell)
2119     @trusted // TODO: Should be @safe
2120 {
2121     return spawnShell(command,
2122                       std.stdio.stdin,
2123                       std.stdio.stdout,
2124                       std.stdio.stderr,
2125                       env,
2126                       config,
2127                       workDir,
2128                       shellPath);
2129 }
2130 
2131 @system unittest
2132 {
2133     version (Windows)
2134         auto cmd = "echo %FOO%";
2135     else version (Posix)
2136         auto cmd = "echo $foo";
2137     import std.file;
2138     auto tmpFile = uniqueTempPath();
2139     scope(exit) if (exists(tmpFile)) remove(tmpFile);
2140     auto redir = "> \""~tmpFile~'"';
2141     auto env = ["foo" : "bar"];
2142     assert(wait(spawnShell(cmd~redir, env)) == 0);
2143     auto f = File(tmpFile, "a");
2144     version (CRuntime_Microsoft) f.seek(0, SEEK_END); // MSVCRT probably seeks to the end when writing, not before
2145     assert(wait(spawnShell(cmd, std.stdio.stdin, f, std.stdio.stderr, env)) == 0);
2146     f.close();
2147     auto output = std.file.readText(tmpFile);
2148     assert(output == "bar\nbar\n" || output == "bar\r\nbar\r\n");
2149 }
2150 
2151 version (Windows)
2152 @system unittest
2153 {
2154     import std.string;
2155     import std.conv : text;
2156     TestScript prog = "echo %0 %*";
2157     auto outputFn = uniqueTempPath();
2158     scope(exit) if (exists(outputFn)) remove(outputFn);
2159     auto args = [`a b c`, `a\b\c\`, `a"b"c"`];
2160     auto result = executeShell(
2161         escapeShellCommand([prog.path] ~ args)
2162         ~ " > " ~
2163         escapeShellFileName(outputFn));
2164     assert(result.status == 0);
2165     auto args2 = outputFn.readText().strip().parseCommandLine()[1..$];
2166     assert(args == args2, text(args2));
2167 }
2168 
2169 
2170 /**
2171 Options that control the behaviour of process creation functions in this
2172 module. Most options only apply to $(LREF spawnProcess) and
2173 $(LREF spawnShell).
2174 
2175 Example:
2176 ---
2177 auto logFile = File("myapp_error.log", "w");
2178 
2179 // Start program, suppressing the console window (Windows only),
2180 // redirect its error stream to logFile, and leave logFile open
2181 // in the parent process as well.
2182 auto pid = spawnProcess("myapp", stdin, stdout, logFile,
2183                         Config.retainStderr | Config.suppressConsole);
2184 scope(exit)
2185 {
2186     auto exitCode = wait(pid);
2187     logFile.writeln("myapp exited with code ", exitCode);
2188     logFile.close();
2189 }
2190 ---
2191 */
2192 struct Config
2193 {
2194     /**
2195        Flag options.
2196        Use bitwise OR to combine flags.
2197     **/
2198     enum Flags
2199     {
2200         none = 0,
2201 
2202         /**
2203         By default, the child process inherits the parent's environment,
2204         and any environment variables passed to $(LREF spawnProcess) will
2205         be added to it.  If this flag is set, the only variables in the
2206         child process' environment will be those given to spawnProcess.
2207         */
2208         newEnv = 1,
2209 
2210         /**
2211         Unless the child process inherits the standard input/output/error
2212         streams of its parent, one almost always wants the streams closed
2213         in the parent when $(LREF spawnProcess) returns.  Therefore, by
2214         default, this is done.  If this is not desirable, pass any of these
2215         options to spawnProcess.
2216         */
2217         retainStdin  = 2,
2218         retainStdout = 4,                                  /// ditto
2219         retainStderr = 8,                                  /// ditto
2220 
2221         /**
2222         On Windows, if the child process is a console application, this
2223         flag will prevent the creation of a console window.  Otherwise,
2224         it will be ignored. On POSIX, `suppressConsole` has no effect.
2225         */
2226         suppressConsole = 16,
2227 
2228         /**
2229         On POSIX, open $(LINK2 http://en.wikipedia.org/wiki/File_descriptor,file descriptors)
2230         are by default inherited by the child process.  As this may lead
2231         to subtle bugs when pipes or multiple threads are involved,
2232         $(LREF spawnProcess) ensures that all file descriptors except the
2233         ones that correspond to standard input/output/error are closed
2234         in the child process when it starts.  Use `inheritFDs` to prevent
2235         this.
2236 
2237         On Windows, this option has no effect, and any handles which have been
2238         explicitly marked as inheritable will always be inherited by the child
2239         process.
2240         */
2241         inheritFDs = 32,
2242 
2243         /**
2244         Spawn process in detached state. This removes the need in calling
2245         $(LREF wait) to clean up the process resources.
2246 
2247         Note:
2248         Calling $(LREF wait) or $(LREF kill) with the resulting `Pid` is invalid.
2249         */
2250         detached = 64,
2251 
2252         /**
2253         By default, the $(LREF execute) and $(LREF executeShell) functions
2254         will capture child processes' both stdout and stderr. This can be
2255         undesirable if the standard output is to be processed or otherwise
2256         used by the invoking program, as `execute`'s result would then
2257         contain a mix of output and warning/error messages.
2258 
2259         Specify this flag when calling `execute` or `executeShell` to
2260         cause invoked processes' stderr stream to be sent to $(REF stderr,
2261         std,stdio), and only capture and return standard output.
2262 
2263         This flag has no effect on $(LREF spawnProcess) or $(LREF spawnShell).
2264         */
2265         stderrPassThrough = 128,
2266     }
2267     Flags flags; /// ditto
2268 
2269     /**
2270        For backwards compatibility, and cases when only flags need to
2271        be specified in the `Config`, these allow building `Config`
2272        instances using flag names only.
2273     */
2274     enum Config none = Config.init;
2275     enum Config newEnv = Config(Flags.newEnv); /// ditto
2276     enum Config retainStdin = Config(Flags.retainStdin); /// ditto
2277     enum Config retainStdout = Config(Flags.retainStdout); /// ditto
2278     enum Config retainStderr = Config(Flags.retainStderr); /// ditto
2279     enum Config suppressConsole = Config(Flags.suppressConsole); /// ditto
2280     enum Config inheritFDs = Config(Flags.inheritFDs); /// ditto
2281     enum Config detached = Config(Flags.detached); /// ditto
2282     enum Config stderrPassThrough = Config(Flags.stderrPassThrough); /// ditto
2283     Config opUnary(string op)()
2284     if (is(typeof(mixin(op ~ q{flags}))))
2285     {
2286         return Config(mixin(op ~ q{flags}));
2287     } /// ditto
2288     Config opBinary(string op)(Config other)
2289     if (is(typeof(mixin(q{flags} ~ op ~ q{other.flags}))))
2290     {
2291         return Config(mixin(q{flags} ~ op ~ q{other.flags}));
2292     } /// ditto
2293     Config opOpAssign(string op)(Config other)
2294     if (is(typeof(mixin(q{flags} ~ op ~ q{=other.flags}))))
2295     {
2296         return Config(mixin(q{flags} ~ op ~ q{=other.flags}));
2297     } /// ditto
2298 
2299     version (StdDdoc)
2300     {
2301         /**
2302         A function that is called before `exec` in $(LREF spawnProcess).
2303         It returns `true` if succeeded and otherwise returns `false`.
2304 
2305         $(RED Warning:
2306             Please note that the code in this function must only use
2307             async-signal-safe functions.)
2308 
2309         If $(LREF preExecDelegate) is also set, it is called last.
2310 
2311         On Windows, this member is not available.
2312         */
2313         bool function() nothrow @nogc @safe preExecFunction;
2314 
2315         /**
2316         A delegate that is called before `exec` in $(LREF spawnProcess).
2317         It returns `true` if succeeded and otherwise returns `false`.
2318 
2319         $(RED Warning:
2320             Please note that the code in this function must only use
2321             async-signal-safe functions.)
2322 
2323         If $(LREF preExecFunction) is also set, it is called first.
2324 
2325         On Windows, this member is not available.
2326         */
2327         bool delegate() nothrow @nogc @safe preExecDelegate;
2328     }
2329     else version (Posix)
2330     {
2331         bool function() nothrow @nogc @safe preExecFunction;
2332         bool delegate() nothrow @nogc @safe preExecDelegate;
2333     }
2334 }
2335 
2336 // https://issues.dlang.org/show_bug.cgi?id=22125
2337 @safe unittest
2338 {
2339     Config c = Config.retainStdin;
2340     c |= Config.retainStdout;
2341     c |= Config.retainStderr;
2342     c &= ~Config.retainStderr;
2343     assert(c == (Config.retainStdin | Config.retainStdout));
2344 }
2345 
2346 /// A handle that corresponds to a spawned process.
2347 final class Pid
2348 {
2349     /**
2350     The process ID number.
2351 
2352     This is a number that uniquely identifies the process on the operating
2353     system, for at least as long as the process is running.  Once $(LREF wait)
2354     has been called on the $(LREF Pid), this method will return an
2355     invalid (negative) process ID.
2356     */
2357     @property int processID() const @safe pure nothrow
2358     {
2359         return _processID;
2360     }
2361 
2362     /**
2363     An operating system handle to the process.
2364 
2365     This handle is used to specify the process in OS-specific APIs.
2366     On POSIX, this function returns a `core.sys.posix.sys.types.pid_t`
2367     with the same value as $(LREF Pid.processID), while on Windows it returns
2368     a `core.sys.windows.windows.HANDLE`.
2369 
2370     Once $(LREF wait) has been called on the $(LREF Pid), this method
2371     will return an invalid handle.
2372     */
2373     // Note: Since HANDLE is a reference, this function cannot be const.
2374     version (Windows)
2375     @property HANDLE osHandle() @nogc @safe pure nothrow
2376     {
2377         return _handle;
2378     }
2379     else version (Posix)
2380     @property pid_t osHandle() @nogc @safe pure nothrow
2381     {
2382         return _processID;
2383     }
2384 
2385 private:
2386     /*
2387     Pid.performWait() does the dirty work for wait() and nonBlockingWait().
2388 
2389     If block == true, this function blocks until the process terminates,
2390     sets _processID to terminated, and returns the exit code or terminating
2391     signal as described in the wait() documentation.
2392 
2393     If block == false, this function returns immediately, regardless
2394     of the status of the process.  If the process has terminated, the
2395     function has the exact same effect as the blocking version.  If not,
2396     it returns 0 and does not modify _processID.
2397     */
2398     version (Posix)
2399     int performWait(bool block) @trusted
2400     {
2401         import std.exception : enforce;
2402         enforce!ProcessException(owned, "Can't wait on a detached process");
2403         if (_processID == terminated) return _exitCode;
2404         int exitCode;
2405         while (true)
2406         {
2407             int status;
2408             auto check = waitpid(_processID, &status, block ? 0 : WNOHANG);
2409             if (check == -1)
2410             {
2411                 if (errno == ECHILD)
2412                 {
2413                     throw new ProcessException(
2414                         "Process does not exist or is not a child process.");
2415                 }
2416                 else
2417                 {
2418                     // waitpid() was interrupted by a signal.  We simply
2419                     // restart it.
2420                     assert(errno == EINTR);
2421                     continue;
2422                 }
2423             }
2424             if (!block && check == 0) return 0;
2425             if (WIFEXITED(status))
2426             {
2427                 exitCode = WEXITSTATUS(status);
2428                 break;
2429             }
2430             else if (WIFSIGNALED(status))
2431             {
2432                 exitCode = -WTERMSIG(status);
2433                 break;
2434             }
2435             // We check again whether the call should be blocking,
2436             // since we don't care about other status changes besides
2437             // "exited" and "terminated by signal".
2438             if (!block) return 0;
2439 
2440             // Process has stopped, but not terminated, so we continue waiting.
2441         }
2442         // Mark Pid as terminated, and cache and return exit code.
2443         _processID = terminated;
2444         _exitCode = exitCode;
2445         return exitCode;
2446     }
2447     else version (Windows)
2448     {
2449         int performWait(const bool block, const DWORD timeout = INFINITE) @trusted
2450         {
2451             import std.exception : enforce;
2452             enforce!ProcessException(owned, "Can't wait on a detached process");
2453             if (_processID == terminated) return _exitCode;
2454             assert(_handle != INVALID_HANDLE_VALUE);
2455             if (block)
2456             {
2457                 auto result = WaitForSingleObject(_handle, timeout);
2458                 if (result != WAIT_OBJECT_0)
2459                 {
2460                     // Wait time exceeded `timeout` milliseconds?
2461                     if (result == WAIT_TIMEOUT && timeout != INFINITE)
2462                         return 0;
2463 
2464                     throw ProcessException.newFromLastError("Wait failed.");
2465                 }
2466             }
2467             if (!GetExitCodeProcess(_handle, cast(LPDWORD)&_exitCode))
2468                 throw ProcessException.newFromLastError();
2469             if (!block && _exitCode == STILL_ACTIVE) return 0;
2470             CloseHandle(_handle);
2471             _handle = INVALID_HANDLE_VALUE;
2472             _processID = terminated;
2473             return _exitCode;
2474         }
2475 
2476         int performWait(Duration timeout) @safe
2477         {
2478             import std.exception : enforce;
2479             const msecs = timeout.total!"msecs";
2480 
2481             // Limit this implementation the maximum wait time offered by
2482             // WaitForSingleObject. One could theoretically break up larger
2483             // durations into multiple waits but (DWORD.max - 1).msecs
2484             // (> 7 weeks, 17 hours) should be enough for the usual case.
2485             // DWORD.max is reserved for INFINITE
2486             enforce!ProcessException(msecs < DWORD.max, "Timeout exceeds maximum wait time!");
2487             return performWait(true, cast(DWORD) msecs);
2488         }
2489 
2490         ~this()
2491         {
2492             if (_handle != INVALID_HANDLE_VALUE)
2493             {
2494                 CloseHandle(_handle);
2495                 _handle = INVALID_HANDLE_VALUE;
2496             }
2497         }
2498     }
2499 
2500     // Special values for _processID.
2501     enum invalid = -1, terminated = -2;
2502 
2503     // OS process ID number.  Only nonnegative IDs correspond to
2504     // running processes.
2505     int _processID = invalid;
2506 
2507     // Exit code cached by wait().  This is only expected to hold a
2508     // sensible value if _processID == terminated.
2509     int _exitCode;
2510 
2511     // Whether the process can be waited for by wait() for or killed by kill().
2512     // False if process was started as detached. True otherwise.
2513     bool owned;
2514 
2515     // Pids are only meant to be constructed inside this module, so
2516     // we make the constructor private.
2517     version (Windows)
2518     {
2519         HANDLE _handle = INVALID_HANDLE_VALUE;
2520         this(int pid, HANDLE handle) @safe pure nothrow
2521         {
2522             _processID = pid;
2523             _handle = handle;
2524             this.owned = true;
2525         }
2526         this(int pid) @safe pure nothrow
2527         {
2528             _processID = pid;
2529             this.owned = false;
2530         }
2531     }
2532     else
2533     {
2534         this(int id, bool owned) @safe pure nothrow
2535         {
2536             _processID = id;
2537             this.owned = owned;
2538         }
2539     }
2540 }
2541 
2542 
2543 /**
2544 Waits for the process associated with `pid` to terminate, and returns
2545 its exit status.
2546 
2547 In general one should always _wait for child processes to terminate
2548 before exiting the parent process unless the process was spawned as detached
2549 (that was spawned with `Config.detached` flag).
2550 Otherwise, they may become "$(HTTP en.wikipedia.org/wiki/Zombie_process,zombies)"
2551 – processes that are defunct, yet still occupy a slot in the OS process table.
2552 You should not and must not wait for detached processes, since you don't own them.
2553 
2554 If the process has already terminated, this function returns directly.
2555 The exit code is cached, so that if wait() is called multiple times on
2556 the same $(LREF Pid) it will always return the same value.
2557 
2558 POSIX_specific:
2559 If the process is terminated by a signal, this function returns a
2560 negative number whose absolute value is the signal number.
2561 Since POSIX restricts normal exit codes to the range 0-255, a
2562 negative return value will always indicate termination by signal.
2563 Signal codes are defined in the `core.sys.posix.signal` module
2564 (which corresponds to the `signal.h` POSIX header).
2565 
2566 Throws:
2567 $(LREF ProcessException) on failure or on attempt to wait for detached process.
2568 
2569 Example:
2570 See the $(LREF spawnProcess) documentation.
2571 
2572 See_also:
2573 $(LREF tryWait), for a non-blocking function.
2574 */
2575 int wait(Pid pid) @safe
2576 {
2577     assert(pid !is null, "Called wait on a null Pid.");
2578     return pid.performWait(true);
2579 }
2580 
2581 
2582 @system unittest // Pid and wait()
2583 {
2584     version (Windows)    TestScript prog = "exit %~1";
2585     else version (Posix) TestScript prog = "exit $1";
2586     assert(wait(spawnProcess([prog.path, "0"])) == 0);
2587     assert(wait(spawnProcess([prog.path, "123"])) == 123);
2588     auto pid = spawnProcess([prog.path, "10"]);
2589     assert(pid.processID > 0);
2590     version (Windows)    assert(pid.osHandle != INVALID_HANDLE_VALUE);
2591     else version (Posix) assert(pid.osHandle == pid.processID);
2592     assert(wait(pid) == 10);
2593     assert(wait(pid) == 10); // cached exit code
2594     assert(pid.processID < 0);
2595     version (Windows)    assert(pid.osHandle == INVALID_HANDLE_VALUE);
2596     else version (Posix) assert(pid.osHandle < 0);
2597 }
2598 
2599 private import std.typecons : Tuple;
2600 
2601 /**
2602 Waits until either the process associated with `pid` terminates or the
2603 elapsed time exceeds the given timeout.
2604 
2605 If the process terminates within the given duration it behaves exactly like
2606 `wait`, except that it returns a tuple `(true, exit code)`.
2607 
2608 If the process does not terminate within the given duration it will stop
2609 waiting and return `(false, 0).`
2610 
2611 The timeout may not exceed `(uint.max - 1).msecs` (~ 7 weeks, 17 hours).
2612 
2613 $(BLUE This function is Windows-Only.)
2614 
2615 Returns:
2616 An $(D std.typecons.Tuple!(bool, "terminated", int, "status")).
2617 
2618 Throws:
2619 $(LREF ProcessException) on failure or on attempt to wait for detached process.
2620 
2621 Example:
2622 See the $(LREF spawnProcess) documentation.
2623 
2624 See_also:
2625 $(LREF wait), for a blocking function without timeout.
2626 $(LREF tryWait), for a non-blocking function without timeout.
2627 */
2628 version (StdDdoc)
2629 Tuple!(bool, "terminated", int, "status") waitTimeout(Pid pid, Duration timeout) @safe;
2630 
2631 else version (Windows)
2632 Tuple!(bool, "terminated", int, "status") waitTimeout(Pid pid, Duration timeout) @safe
2633 {
2634     assert(pid !is null, "Called wait on a null Pid.");
2635     auto code = pid.performWait(timeout);
2636     return typeof(return)(pid._processID == Pid.terminated, code);
2637 }
2638 
2639 version (Windows)
2640 @system unittest // Pid and waitTimeout()
2641 {
2642     import std.exception : collectException;
2643     import std.typecons : tuple;
2644 
2645     TestScript prog = ":Loop\r\n" ~ "goto Loop";
2646     auto pid = spawnProcess(prog.path);
2647 
2648     // Doesn't block longer than one second
2649     assert(waitTimeout(pid, 1.seconds) == tuple(false, 0));
2650 
2651     kill(pid);
2652     assert(waitTimeout(pid, 1.seconds) == tuple(true, 1)); // exit 1 because the process is killed
2653 
2654     // Rejects timeouts exceeding the Windows API capabilities
2655     const dur = DWORD.max.msecs;
2656     const ex = collectException!ProcessException(waitTimeout(pid, dur));
2657     assert(ex);
2658     assert(ex.msg == "Timeout exceeds maximum wait time!");
2659 }
2660 
2661 /**
2662 A non-blocking version of $(LREF wait).
2663 
2664 If the process associated with `pid` has already terminated,
2665 `tryWait` has the exact same effect as `wait`.
2666 In this case, it returns a tuple where the `terminated` field
2667 is set to `true` and the `status` field has the same
2668 interpretation as the return value of `wait`.
2669 
2670 If the process has $(I not) yet terminated, this function differs
2671 from `wait` in that does not wait for this to happen, but instead
2672 returns immediately.  The `terminated` field of the returned
2673 tuple will then be set to `false`, while the `status` field
2674 will always be 0 (zero).  `wait` or `tryWait` should then be
2675 called again on the same `Pid` at some later time; not only to
2676 get the exit code, but also to avoid the process becoming a "zombie"
2677 when it finally terminates.  (See $(LREF wait) for details).
2678 
2679 Returns:
2680 An $(D std.typecons.Tuple!(bool, "terminated", int, "status")).
2681 
2682 Throws:
2683 $(LREF ProcessException) on failure or on attempt to wait for detached process.
2684 
2685 Example:
2686 ---
2687 auto pid = spawnProcess("dmd myapp.d");
2688 scope(exit) wait(pid);
2689 ...
2690 auto dmd = tryWait(pid);
2691 if (dmd.terminated)
2692 {
2693     if (dmd.status == 0) writeln("Compilation succeeded!");
2694     else writeln("Compilation failed");
2695 }
2696 else writeln("Still compiling...");
2697 ...
2698 ---
2699 Note that in this example, the first `wait` call will have no
2700 effect if the process has already terminated by the time `tryWait`
2701 is called.  In the opposite case, however, the `scope` statement
2702 ensures that we always wait for the process if it hasn't terminated
2703 by the time we reach the end of the scope.
2704 */
2705 auto tryWait(Pid pid) @safe
2706 {
2707     import std.typecons : Tuple;
2708     assert(pid !is null, "Called tryWait on a null Pid.");
2709     auto code = pid.performWait(false);
2710     return Tuple!(bool, "terminated", int, "status")(pid._processID == Pid.terminated, code);
2711 }
2712 // unittest: This function is tested together with kill() below.
2713 
2714 
2715 /**
2716 Attempts to terminate the process associated with `pid`.
2717 
2718 The effect of this function, as well as the meaning of `codeOrSignal`,
2719 is highly platform dependent.  Details are given below.  Common to all
2720 platforms is that this function only $(I initiates) termination of the process,
2721 and returns immediately.  It does not wait for the process to end,
2722 nor does it guarantee that the process does in fact get terminated.
2723 
2724 Always call $(LREF wait) to wait for a process to complete, even if `kill`
2725 has been called on it.
2726 
2727 Windows_specific:
2728 The process will be
2729 $(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/ms686714%28v=vs.100%29.aspx,
2730 forcefully and abruptly terminated).  If `codeOrSignal` is specified, it
2731 must be a nonnegative number which will be used as the exit code of the process.
2732 If not, the process wil exit with code 1.  Do not use $(D codeOrSignal = 259),
2733 as this is a special value (aka. $(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/ms683189.aspx,STILL_ACTIVE))
2734 used by Windows to signal that a process has in fact $(I not) terminated yet.
2735 ---
2736 auto pid = spawnProcess("some_app");
2737 kill(pid, 10);
2738 assert(wait(pid) == 10);
2739 ---
2740 
2741 POSIX_specific:
2742 A $(LINK2 http://en.wikipedia.org/wiki/Unix_signal,signal) will be sent to
2743 the process, whose value is given by `codeOrSignal`.  Depending on the
2744 signal sent, this may or may not terminate the process.  Symbolic constants
2745 for various $(LINK2 http://en.wikipedia.org/wiki/Unix_signal#POSIX_signals,
2746 POSIX signals) are defined in `core.sys.posix.signal`, which corresponds to the
2747 $(LINK2 http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html,
2748 `signal.h` POSIX header).  If `codeOrSignal` is omitted, the
2749 `SIGTERM` signal will be sent.  (This matches the behaviour of the
2750 $(LINK2 http://pubs.opengroup.org/onlinepubs/9699919799/utilities/kill.html,
2751 `_kill`) shell command.)
2752 ---
2753 import core.sys.posix.signal : SIGKILL;
2754 auto pid = spawnProcess("some_app");
2755 kill(pid, SIGKILL);
2756 assert(wait(pid) == -SIGKILL); // Negative return value on POSIX!
2757 ---
2758 
2759 Throws:
2760 $(LREF ProcessException) on error (e.g. if codeOrSignal is invalid).
2761     or on attempt to kill detached process.
2762     Note that failure to terminate the process is considered a "normal"
2763     outcome, not an error.$(BR)
2764 */
2765 void kill(Pid pid)
2766 {
2767     version (Windows) kill(pid, 1);
2768     else version (Posix)
2769     {
2770         import core.sys.posix.signal : SIGTERM;
2771         kill(pid, SIGTERM);
2772     }
2773 }
2774 
2775 /// ditto
2776 void kill(Pid pid, int codeOrSignal)
2777 {
2778     import std.exception : enforce;
2779     enforce!ProcessException(pid.owned, "Can't kill detached process");
2780     version (Windows)
2781     {
2782         if (codeOrSignal < 0) throw new ProcessException("Invalid exit code");
2783         // On Windows, TerminateProcess() appears to terminate the
2784         // *current* process if it is passed an invalid handle...
2785         if (pid.osHandle == INVALID_HANDLE_VALUE)
2786             throw new ProcessException("Invalid process handle");
2787         if (!TerminateProcess(pid.osHandle, codeOrSignal))
2788             throw ProcessException.newFromLastError();
2789     }
2790     else version (Posix)
2791     {
2792         import core.sys.posix.signal : kill;
2793         if (pid.osHandle == Pid.invalid)
2794             throw new ProcessException("Pid is invalid");
2795         if (pid.osHandle == Pid.terminated)
2796             throw new ProcessException("Pid is already terminated");
2797         if (kill(pid.osHandle, codeOrSignal) == -1)
2798             throw ProcessException.newFromErrno();
2799     }
2800 }
2801 
2802 @system unittest // tryWait() and kill()
2803 {
2804     import core.thread;
2805     import std.exception : assertThrown;
2806     // The test script goes into an infinite loop.
2807     version (Windows)
2808     {
2809         TestScript prog = ":loop
2810                            goto loop";
2811     }
2812     else version (Posix)
2813     {
2814         import core.sys.posix.signal : SIGTERM, SIGKILL;
2815         TestScript prog = "while true; do sleep 1; done";
2816     }
2817     auto pid = spawnProcess(prog.path);
2818     // Android appears to automatically kill sleeping processes very quickly,
2819     // so shorten the wait before killing here.
2820     version (Android)
2821         Thread.sleep(dur!"msecs"(5));
2822     else
2823         Thread.sleep(dur!"msecs"(500));
2824     kill(pid);
2825     version (Windows)    assert(wait(pid) == 1);
2826     else version (Posix) assert(wait(pid) == -SIGTERM);
2827 
2828     pid = spawnProcess(prog.path);
2829     Thread.sleep(dur!"msecs"(500));
2830     auto s = tryWait(pid);
2831     assert(!s.terminated && s.status == 0);
2832     assertThrown!ProcessException(kill(pid, -123)); // Negative code not allowed.
2833     version (Windows)    kill(pid, 123);
2834     else version (Posix) kill(pid, SIGKILL);
2835     do { s = tryWait(pid); } while (!s.terminated);
2836     version (Windows)    assert(s.status == 123);
2837     else version (Posix) assert(s.status == -SIGKILL);
2838     assertThrown!ProcessException(kill(pid)); // Already terminated
2839 }
2840 
2841 @system unittest // wait() and kill() detached process
2842 {
2843     import core.thread;
2844     import std.exception : assertThrown;
2845     TestScript prog = "exit 0";
2846     auto pid = spawnProcess([prog.path], null, Config.detached);
2847     /*
2848     This sleep is needed because we can't wait() for detached process to end
2849     and therefore TestScript destructor may run at the same time as /bin/sh tries to start the script.
2850     This leads to the annoying message like "/bin/sh: 0: Can't open /tmp/std.process temporary file" to appear when running tests.
2851     It does not happen in unittests with non-detached processes because we always wait() for them to finish.
2852     */
2853     Thread.sleep(500.msecs);
2854     assert(!pid.owned);
2855     version (Windows) assert(pid.osHandle == INVALID_HANDLE_VALUE);
2856     assertThrown!ProcessException(wait(pid));
2857     assertThrown!ProcessException(kill(pid));
2858 }
2859 
2860 
2861 /**
2862 Creates a unidirectional _pipe.
2863 
2864 Data is written to one end of the _pipe and read from the other.
2865 ---
2866 auto p = pipe();
2867 p.writeEnd.writeln("Hello World");
2868 p.writeEnd.flush();
2869 assert(p.readEnd.readln().chomp() == "Hello World");
2870 ---
2871 Pipes can, for example, be used for interprocess communication
2872 by spawning a new process and passing one end of the _pipe to
2873 the child, while the parent uses the other end.
2874 (See also $(LREF pipeProcess) and $(LREF pipeShell) for an easier
2875 way of doing this.)
2876 ---
2877 // Use cURL to download the dlang.org front page, pipe its
2878 // output to grep to extract a list of links to ZIP files,
2879 // and write the list to the file "D downloads.txt":
2880 auto p = pipe();
2881 auto outFile = File("D downloads.txt", "w");
2882 auto cpid = spawnProcess(["curl", "http://dlang.org/download.html"],
2883                          std.stdio.stdin, p.writeEnd);
2884 scope(exit) wait(cpid);
2885 auto gpid = spawnProcess(["grep", "-o", `http://\S*\.zip`],
2886                          p.readEnd, outFile);
2887 scope(exit) wait(gpid);
2888 ---
2889 
2890 Returns:
2891 A $(LREF Pipe) object that corresponds to the created _pipe.
2892 
2893 Throws:
2894 $(REF StdioException, std,stdio) on failure.
2895 */
2896 version (Posix)
2897 Pipe pipe() @trusted //TODO: @safe
2898 {
2899     import core.sys.posix.stdio : fdopen;
2900     int[2] fds;
2901     if (core.sys.posix.unistd.pipe(fds) != 0)
2902         throw new StdioException("Unable to create pipe");
2903     Pipe p;
2904     auto readFP = fdopen(fds[0], "r");
2905     if (readFP == null)
2906         throw new StdioException("Cannot open read end of pipe");
2907     p._read = File(readFP, null);
2908     auto writeFP = fdopen(fds[1], "w");
2909     if (writeFP == null)
2910         throw new StdioException("Cannot open write end of pipe");
2911     p._write = File(writeFP, null);
2912     return p;
2913 }
2914 else version (Windows)
2915 Pipe pipe() @trusted //TODO: @safe
2916 {
2917     // use CreatePipe to create an anonymous pipe
2918     HANDLE readHandle;
2919     HANDLE writeHandle;
2920     if (!CreatePipe(&readHandle, &writeHandle, null, 0))
2921     {
2922         throw new StdioException(
2923             "Error creating pipe (" ~ generateSysErrorMsg() ~ ')',
2924             0);
2925     }
2926 
2927     scope(failure)
2928     {
2929         CloseHandle(readHandle);
2930         CloseHandle(writeHandle);
2931     }
2932 
2933     try
2934     {
2935         Pipe p;
2936         p._read .windowsHandleOpen(readHandle , "r");
2937         p._write.windowsHandleOpen(writeHandle, "a");
2938         return p;
2939     }
2940     catch (Exception e)
2941     {
2942         throw new StdioException("Error attaching pipe (" ~ e.msg ~ ")",
2943             0);
2944     }
2945 }
2946 
2947 
2948 /// An interface to a pipe created by the $(LREF pipe) function.
2949 struct Pipe
2950 {
2951     /// The read end of the pipe.
2952     @property File readEnd() @safe nothrow { return _read; }
2953 
2954 
2955     /// The write end of the pipe.
2956     @property File writeEnd() @safe nothrow { return _write; }
2957 
2958 
2959     /**
2960     Closes both ends of the pipe.
2961 
2962     Normally it is not necessary to do this manually, as $(REF File, std,stdio)
2963     objects are automatically closed when there are no more references
2964     to them.
2965 
2966     Note that if either end of the pipe has been passed to a child process,
2967     it will only be closed in the parent process.  (What happens in the
2968     child process is platform dependent.)
2969 
2970     Throws:
2971     $(REF ErrnoException, std,exception) if an error occurs.
2972     */
2973     void close() @safe
2974     {
2975         _read.close();
2976         _write.close();
2977     }
2978 
2979 private:
2980     File _read, _write;
2981 }
2982 
2983 @system unittest
2984 {
2985     import std.string;
2986     auto p = pipe();
2987     p.writeEnd.writeln("Hello World");
2988     p.writeEnd.flush();
2989     assert(p.readEnd.readln().chomp() == "Hello World");
2990     p.close();
2991     assert(!p.readEnd.isOpen);
2992     assert(!p.writeEnd.isOpen);
2993 }
2994 
2995 
2996 /**
2997 Starts a new process, creating pipes to redirect its standard
2998 input, output and/or error streams.
2999 
3000 `pipeProcess` and `pipeShell` are convenient wrappers around
3001 $(LREF spawnProcess) and $(LREF spawnShell), respectively, and
3002 automate the task of redirecting one or more of the child process'
3003 standard streams through pipes.  Like the functions they wrap,
3004 these functions return immediately, leaving the child process to
3005 execute in parallel with the invoking process.  It is recommended
3006 to always call $(LREF wait) on the returned $(LREF ProcessPipes.pid),
3007 as detailed in the documentation for `wait`.
3008 
3009 The `args`/`program`/`command`, `env` and `config`
3010 parameters are forwarded straight to the underlying spawn functions,
3011 and we refer to their documentation for details.
3012 
3013 Params:
3014 args      = An array which contains the program name as the zeroth element
3015             and any command-line arguments in the following elements.
3016             (See $(LREF spawnProcess) for details.)
3017 program   = The program name, $(I without) command-line arguments.
3018             (See $(LREF spawnProcess) for details.)
3019 command   = A shell command which is passed verbatim to the command
3020             interpreter.  (See $(LREF spawnShell) for details.)
3021 redirect  = Flags that determine which streams are redirected, and
3022             how.  See $(LREF Redirect) for an overview of available
3023             flags.
3024 env       = Additional environment variables for the child process.
3025             (See $(LREF spawnProcess) for details.)
3026 config    = Flags that control process creation. See $(LREF Config)
3027             for an overview of available flags, and note that the
3028             `retainStd...` flags have no effect in this function.
3029 workDir   = The working directory for the new process.
3030             By default the child process inherits the parent's working
3031             directory.
3032 shellPath = The path to the shell to use to run the specified program.
3033             By default this is $(LREF nativeShell).
3034 
3035 Returns:
3036 A $(LREF ProcessPipes) object which contains $(REF File, std,stdio)
3037 handles that communicate with the redirected streams of the child
3038 process, along with a $(LREF Pid) object that corresponds to the
3039 spawned process.
3040 
3041 Throws:
3042 $(LREF ProcessException) on failure to start the process.$(BR)
3043 $(REF StdioException, std,stdio) on failure to redirect any of the streams.$(BR)
3044 
3045 Example:
3046 ---
3047 // my_application writes to stdout and might write to stderr
3048 auto pipes = pipeProcess("my_application", Redirect.stdout | Redirect.stderr);
3049 scope(exit) wait(pipes.pid);
3050 
3051 // Store lines of output.
3052 string[] output;
3053 foreach (line; pipes.stdout.byLine) output ~= line.idup;
3054 
3055 // Store lines of errors.
3056 string[] errors;
3057 foreach (line; pipes.stderr.byLine) errors ~= line.idup;
3058 
3059 
3060 // sendmail expects to read from stdin
3061 pipes = pipeProcess(["/usr/bin/sendmail", "-t"], Redirect.stdin);
3062 pipes.stdin.writeln("To: you");
3063 pipes.stdin.writeln("From: me");
3064 pipes.stdin.writeln("Subject: dlang");
3065 pipes.stdin.writeln("");
3066 pipes.stdin.writeln(message);
3067 
3068 // a single period tells sendmail we are finished
3069 pipes.stdin.writeln(".");
3070 
3071 // but at this point sendmail might not see it, we need to flush
3072 pipes.stdin.flush();
3073 
3074 // sendmail happens to exit on ".", but some you have to close the file:
3075 pipes.stdin.close();
3076 
3077 // otherwise this wait will wait forever
3078 wait(pipes.pid);
3079 
3080 ---
3081 */
3082 ProcessPipes pipeProcess(scope const(char[])[] args,
3083                          Redirect redirect = Redirect.all,
3084                          const string[string] env = null,
3085                          Config config = Config.none,
3086                          scope const(char)[] workDir = null)
3087     @safe
3088 {
3089     return pipeProcessImpl!spawnProcess(args, redirect, env, config, workDir);
3090 }
3091 
3092 /// ditto
3093 ProcessPipes pipeProcess(scope const(char)[] program,
3094                          Redirect redirect = Redirect.all,
3095                          const string[string] env = null,
3096                          Config config = Config.none,
3097                          scope const(char)[] workDir = null)
3098     @safe
3099 {
3100     return pipeProcessImpl!spawnProcess(program, redirect, env, config, workDir);
3101 }
3102 
3103 /// ditto
3104 ProcessPipes pipeShell(scope const(char)[] command,
3105                        Redirect redirect = Redirect.all,
3106                        const string[string] env = null,
3107                        Config config = Config.none,
3108                        scope const(char)[] workDir = null,
3109                        string shellPath = nativeShell)
3110     @safe
3111 {
3112     return pipeProcessImpl!spawnShell(command,
3113                                       redirect,
3114                                       env,
3115                                       config,
3116                                       workDir,
3117                                       shellPath);
3118 }
3119 
3120 // Implementation of the pipeProcess() family of functions.
3121 private ProcessPipes pipeProcessImpl(alias spawnFunc, Cmd, ExtraSpawnFuncArgs...)
3122                                     (scope Cmd command,
3123                                      Redirect redirectFlags,
3124                                      const string[string] env = null,
3125                                      Config config = Config.none,
3126                                      scope const(char)[] workDir = null,
3127                                      ExtraSpawnFuncArgs extraArgs = ExtraSpawnFuncArgs.init)
3128     @trusted //TODO: @safe
3129 {
3130     File childStdin, childStdout, childStderr;
3131     ProcessPipes pipes;
3132     pipes._redirectFlags = redirectFlags;
3133 
3134     if (redirectFlags & Redirect.stdin)
3135     {
3136         auto p = pipe();
3137         childStdin = p.readEnd;
3138         pipes._stdin = p.writeEnd;
3139     }
3140     else
3141     {
3142         childStdin = std.stdio.stdin;
3143     }
3144 
3145     if (redirectFlags & Redirect.stdout)
3146     {
3147         if ((redirectFlags & Redirect.stdoutToStderr) != 0)
3148             throw new StdioException("Cannot create pipe for stdout AND "
3149                                      ~"redirect it to stderr", 0);
3150         auto p = pipe();
3151         childStdout = p.writeEnd;
3152         pipes._stdout = p.readEnd;
3153     }
3154     else
3155     {
3156         childStdout = std.stdio.stdout;
3157     }
3158 
3159     if (redirectFlags & Redirect.stderr)
3160     {
3161         if ((redirectFlags & Redirect.stderrToStdout) != 0)
3162             throw new StdioException("Cannot create pipe for stderr AND "
3163                                      ~"redirect it to stdout", 0);
3164         auto p = pipe();
3165         childStderr = p.writeEnd;
3166         pipes._stderr = p.readEnd;
3167     }
3168     else
3169     {
3170         childStderr = std.stdio.stderr;
3171     }
3172 
3173     if (redirectFlags & Redirect.stdoutToStderr)
3174     {
3175         if (redirectFlags & Redirect.stderrToStdout)
3176         {
3177             // We know that neither of the other options have been
3178             // set, so we assign the std.stdio.std* streams directly.
3179             childStdout = std.stdio.stderr;
3180             childStderr = std.stdio.stdout;
3181         }
3182         else
3183         {
3184             childStdout = childStderr;
3185         }
3186     }
3187     else if (redirectFlags & Redirect.stderrToStdout)
3188     {
3189         childStderr = childStdout;
3190     }
3191 
3192     config.flags &= ~(Config.Flags.retainStdin | Config.Flags.retainStdout | Config.Flags.retainStderr);
3193     pipes._pid = spawnFunc(command, childStdin, childStdout, childStderr,
3194                            env, config, workDir, extraArgs);
3195     return pipes;
3196 }
3197 
3198 
3199 /**
3200 Flags that can be passed to $(LREF pipeProcess) and $(LREF pipeShell)
3201 to specify which of the child process' standard streams are redirected.
3202 Use bitwise OR to combine flags.
3203 */
3204 enum Redirect
3205 {
3206     /// Redirect the standard input, output or error streams, respectively.
3207     stdin = 1,
3208     stdout = 2,                             /// ditto
3209     stderr = 4,                             /// ditto
3210 
3211     /**
3212     Redirect _all three streams.  This is equivalent to
3213     $(D Redirect.stdin | Redirect.stdout | Redirect.stderr).
3214     */
3215     all = stdin | stdout | stderr,
3216 
3217     /**
3218     Redirect the standard error stream into the standard output stream.
3219     This can not be combined with `Redirect.stderr`.
3220     */
3221     stderrToStdout = 8,
3222 
3223     /**
3224     Redirect the standard output stream into the standard error stream.
3225     This can not be combined with `Redirect.stdout`.
3226     */
3227     stdoutToStderr = 16,
3228 }
3229 
3230 @system unittest
3231 {
3232     import std.string;
3233     version (Windows) TestScript prog =
3234        "call :sub %~1 %~2 0
3235         call :sub %~1 %~2 1
3236         call :sub %~1 %~2 2
3237         call :sub %~1 %~2 3
3238         exit 3
3239 
3240         :sub
3241         set /p INPUT=
3242         if -%INPUT%-==-stop- ( exit %~3 )
3243         echo %INPUT% %~1
3244         echo %INPUT% %~2 1>&2";
3245     else version (Posix) TestScript prog =
3246        `for EXITCODE in 0 1 2 3; do
3247             read INPUT
3248             if test "$INPUT" = stop; then break; fi
3249             echo "$INPUT $1"
3250             echo "$INPUT $2" >&2
3251         done
3252         exit $EXITCODE`;
3253     auto pp = pipeProcess([prog.path, "bar", "baz"]);
3254     pp.stdin.writeln("foo");
3255     pp.stdin.flush();
3256     assert(pp.stdout.readln().chomp() == "foo bar");
3257     assert(pp.stderr.readln().chomp().stripRight() == "foo baz");
3258     pp.stdin.writeln("1234567890");
3259     pp.stdin.flush();
3260     assert(pp.stdout.readln().chomp() == "1234567890 bar");
3261     assert(pp.stderr.readln().chomp().stripRight() == "1234567890 baz");
3262     pp.stdin.writeln("stop");
3263     pp.stdin.flush();
3264     assert(wait(pp.pid) == 2);
3265 
3266     pp = pipeProcess([prog.path, "12345", "67890"],
3267                      Redirect.stdin | Redirect.stdout | Redirect.stderrToStdout);
3268     pp.stdin.writeln("xyz");
3269     pp.stdin.flush();
3270     assert(pp.stdout.readln().chomp() == "xyz 12345");
3271     assert(pp.stdout.readln().chomp().stripRight() == "xyz 67890");
3272     pp.stdin.writeln("stop");
3273     pp.stdin.flush();
3274     assert(wait(pp.pid) == 1);
3275 
3276     pp = pipeShell(escapeShellCommand(prog.path, "AAAAA", "BBB"),
3277                    Redirect.stdin | Redirect.stdoutToStderr | Redirect.stderr);
3278     pp.stdin.writeln("ab");
3279     pp.stdin.flush();
3280     assert(pp.stderr.readln().chomp() == "ab AAAAA");
3281     assert(pp.stderr.readln().chomp().stripRight() == "ab BBB");
3282     pp.stdin.writeln("stop");
3283     pp.stdin.flush();
3284     assert(wait(pp.pid) == 1);
3285 }
3286 
3287 @system unittest
3288 {
3289     import std.exception : assertThrown;
3290     TestScript prog = "exit 0";
3291     assertThrown!StdioException(pipeProcess(
3292         prog.path,
3293         Redirect.stdout | Redirect.stdoutToStderr));
3294     assertThrown!StdioException(pipeProcess(
3295         prog.path,
3296         Redirect.stderr | Redirect.stderrToStdout));
3297     auto p = pipeProcess(prog.path, Redirect.stdin);
3298     assertThrown!Error(p.stdout);
3299     assertThrown!Error(p.stderr);
3300     wait(p.pid);
3301     p = pipeProcess(prog.path, Redirect.stderr);
3302     assertThrown!Error(p.stdin);
3303     assertThrown!Error(p.stdout);
3304     wait(p.pid);
3305 }
3306 
3307 /**
3308 Object which contains $(REF File, std,stdio) handles that allow communication
3309 with a child process through its standard streams.
3310 */
3311 struct ProcessPipes
3312 {
3313     /// The $(LREF Pid) of the child process.
3314     @property Pid pid() @safe nothrow
3315     {
3316         return _pid;
3317     }
3318 
3319     /**
3320     An $(REF File, std,stdio) that allows writing to the child process'
3321     standard input stream.
3322 
3323     Throws:
3324     $(OBJECTREF Error) if the child process' standard input stream hasn't
3325     been redirected.
3326     */
3327     @property File stdin() @safe nothrow
3328     {
3329         if ((_redirectFlags & Redirect.stdin) == 0)
3330             throw new Error("Child process' standard input stream hasn't "
3331                             ~"been redirected.");
3332         return _stdin;
3333     }
3334 
3335     /**
3336     An $(REF File, std,stdio) that allows reading from the child process'
3337     standard output stream.
3338 
3339     Throws:
3340     $(OBJECTREF Error) if the child process' standard output stream hasn't
3341     been redirected.
3342     */
3343     @property File stdout() @safe nothrow
3344     {
3345         if ((_redirectFlags & Redirect.stdout) == 0)
3346             throw new Error("Child process' standard output stream hasn't "
3347                             ~"been redirected.");
3348         return _stdout;
3349     }
3350 
3351     /**
3352     An $(REF File, std,stdio) that allows reading from the child process'
3353     standard error stream.
3354 
3355     Throws:
3356     $(OBJECTREF Error) if the child process' standard error stream hasn't
3357     been redirected.
3358     */
3359     @property File stderr() @safe nothrow
3360     {
3361         if ((_redirectFlags & Redirect.stderr) == 0)
3362             throw new Error("Child process' standard error stream hasn't "
3363                             ~"been redirected.");
3364         return _stderr;
3365     }
3366 
3367 private:
3368     Redirect _redirectFlags;
3369     Pid _pid;
3370     File _stdin, _stdout, _stderr;
3371 }
3372 
3373 
3374 
3375 /**
3376 Executes the given program or shell command and returns its exit
3377 code and output.
3378 
3379 `execute` and `executeShell` start a new process using
3380 $(LREF spawnProcess) and $(LREF spawnShell), respectively, and wait
3381 for the process to complete before returning.  The functions capture
3382 what the child process prints to both its standard output and
3383 standard error streams, and return this together with its exit code.
3384 ---
3385 auto dmd = execute(["dmd", "myapp.d"]);
3386 if (dmd.status != 0) writeln("Compilation failed:\n", dmd.output);
3387 
3388 auto ls = executeShell("ls -l");
3389 if (ls.status != 0) writeln("Failed to retrieve file listing");
3390 else writeln(ls.output);
3391 ---
3392 
3393 The `args`/`program`/`command`, `env` and `config`
3394 parameters are forwarded straight to the underlying spawn functions,
3395 and we refer to their documentation for details.
3396 
3397 Params:
3398 args      = An array which contains the program name as the zeroth element
3399             and any command-line arguments in the following elements.
3400             (See $(LREF spawnProcess) for details.)
3401 program   = The program name, $(I without) command-line arguments.
3402             (See $(LREF spawnProcess) for details.)
3403 command   = A shell command which is passed verbatim to the command
3404             interpreter.  (See $(LREF spawnShell) for details.)
3405 env       = Additional environment variables for the child process.
3406             (See $(LREF spawnProcess) for details.)
3407 config    = Flags that control process creation. See $(LREF Config)
3408             for an overview of available flags, and note that the
3409             `retainStd...` flags have no effect in this function.
3410 maxOutput = The maximum number of bytes of output that should be
3411             captured.
3412 workDir   = The working directory for the new process.
3413             By default the child process inherits the parent's working
3414             directory.
3415 shellPath = The path to the shell to use to run the specified program.
3416             By default this is $(LREF nativeShell).
3417 
3418 
3419 Returns:
3420 An $(D std.typecons.Tuple!(int, "status", string, "output")).
3421 
3422 POSIX_specific:
3423 If the process is terminated by a signal, the `status` field of
3424 the return value will contain a negative number whose absolute
3425 value is the signal number.  (See $(LREF wait) for details.)
3426 
3427 Throws:
3428 $(LREF ProcessException) on failure to start the process.$(BR)
3429 $(REF StdioException, std,stdio) on failure to capture output.
3430 */
3431 auto execute(scope const(char[])[] args,
3432              const string[string] env = null,
3433              Config config = Config.none,
3434              size_t maxOutput = size_t.max,
3435              scope const(char)[] workDir = null)
3436     @safe
3437 {
3438     return executeImpl!pipeProcess(args, env, config, maxOutput, workDir);
3439 }
3440 
3441 /// ditto
3442 auto execute(scope const(char)[] program,
3443              const string[string] env = null,
3444              Config config = Config.none,
3445              size_t maxOutput = size_t.max,
3446              scope const(char)[] workDir = null)
3447     @safe
3448 {
3449     return executeImpl!pipeProcess(program, env, config, maxOutput, workDir);
3450 }
3451 
3452 /// ditto
3453 auto executeShell(scope const(char)[] command,
3454                   const string[string] env = null,
3455                   Config config = Config.none,
3456                   size_t maxOutput = size_t.max,
3457                   scope const(char)[] workDir = null,
3458                   string shellPath = nativeShell)
3459     @safe
3460 {
3461     return executeImpl!pipeShell(command,
3462                                  env,
3463                                  config,
3464                                  maxOutput,
3465                                  workDir,
3466                                  shellPath);
3467 }
3468 
3469 // Does the actual work for execute() and executeShell().
3470 private auto executeImpl(alias pipeFunc, Cmd, ExtraPipeFuncArgs...)(
3471     Cmd commandLine,
3472     const string[string] env = null,
3473     Config config = Config.none,
3474     size_t maxOutput = size_t.max,
3475     scope const(char)[] workDir = null,
3476     ExtraPipeFuncArgs extraArgs = ExtraPipeFuncArgs.init)
3477     @trusted //TODO: @safe
3478 {
3479     import std.algorithm.comparison : min;
3480     import std.array : appender;
3481     import std.typecons : Tuple;
3482 
3483     auto redirect = (config.flags & Config.Flags.stderrPassThrough)
3484         ? Redirect.stdout
3485         : Redirect.stdout | Redirect.stderrToStdout;
3486 
3487     auto p = pipeFunc(commandLine, redirect,
3488                       env, config, workDir, extraArgs);
3489 
3490     auto a = appender!string;
3491     enum size_t defaultChunkSize = 4096;
3492     immutable chunkSize = min(maxOutput, defaultChunkSize);
3493 
3494     // Store up to maxOutput bytes in a.
3495     foreach (ubyte[] chunk; p.stdout.byChunk(chunkSize))
3496     {
3497         immutable size_t remain = maxOutput - a.data.length;
3498 
3499         if (chunk.length < remain) a.put(chunk);
3500         else
3501         {
3502             a.put(chunk[0 .. remain]);
3503             break;
3504         }
3505     }
3506     // Exhaust the stream, if necessary.
3507     foreach (ubyte[] chunk; p.stdout.byChunk(defaultChunkSize)) { }
3508 
3509     return Tuple!(int, "status", string, "output")(wait(p.pid), a.data);
3510 }
3511 
3512 @system unittest
3513 {
3514     import std.string;
3515     // To avoid printing the newline characters, we use the echo|set trick on
3516     // Windows, and printf on POSIX (neither echo -n nor echo \c are portable).
3517     version (Windows) TestScript prog =
3518        "echo|set /p=%~1
3519         echo|set /p=%~2 1>&2
3520         exit 123";
3521     else version (Android) TestScript prog =
3522        `echo -n $1
3523         echo -n $2 >&2
3524         exit 123`;
3525     else version (Posix) TestScript prog =
3526        `printf '%s' $1
3527         printf '%s' $2 >&2
3528         exit 123`;
3529     auto r = execute([prog.path, "foo", "bar"]);
3530     assert(r.status == 123);
3531     assert(r.output.stripRight() == "foobar");
3532     auto s = execute([prog.path, "Hello", "World"]);
3533     assert(s.status == 123);
3534     assert(s.output.stripRight() == "HelloWorld");
3535 }
3536 
3537 @safe unittest
3538 {
3539     import std.string;
3540     auto r1 = executeShell("echo foo");
3541     assert(r1.status == 0);
3542     assert(r1.output.chomp() == "foo");
3543     auto r2 = executeShell("echo bar 1>&2");
3544     assert(r2.status == 0);
3545     assert(r2.output.chomp().stripRight() == "bar");
3546     auto r3 = executeShell("exit 123");
3547     assert(r3.status == 123);
3548     assert(r3.output.empty);
3549 }
3550 
3551 @system unittest
3552 {
3553     // Temporarily disable output to stderr so as to not spam the build log.
3554     import std.stdio : stderr;
3555     import std.typecons : Tuple;
3556     import std.file : readText, exists, remove;
3557     import std.traits : ReturnType;
3558 
3559     ReturnType!executeShell r;
3560     auto tmpname = uniqueTempPath;
3561     scope(exit) if (exists(tmpname)) remove(tmpname);
3562     auto t = stderr;
3563     // Open a new scope to minimize code ran with stderr redirected.
3564     {
3565         stderr.open(tmpname, "w");
3566         scope(exit) stderr = t;
3567         r = executeShell("echo D rox>&2", null, Config.stderrPassThrough);
3568     }
3569     assert(r.status == 0);
3570     assert(r.output.empty);
3571     auto witness = readText(tmpname);
3572     import std.ascii : newline;
3573     assert(witness == "D rox" ~ newline, "'" ~ witness ~ "'");
3574 }
3575 
3576 @safe unittest
3577 {
3578     import std.typecons : Tuple;
3579     void foo() //Just test the compilation
3580     {
3581         auto ret1 = execute(["dummy", "arg"]);
3582         auto ret2 = executeShell("dummy arg");
3583         static assert(is(typeof(ret1) == typeof(ret2)));
3584 
3585         Tuple!(int, string) ret3 = execute(["dummy", "arg"]);
3586     }
3587 }
3588 
3589 /// An exception that signals a problem with starting or waiting for a process.
3590 class ProcessException : Exception
3591 {
3592     import std.exception : basicExceptionCtors;
3593     mixin basicExceptionCtors;
3594 
3595     // Creates a new ProcessException based on errno.
3596     static ProcessException newFromErrno(string customMsg = null,
3597                                          string file = __FILE__,
3598                                          size_t line = __LINE__)
3599     {
3600         import core.stdc.errno : errno;
3601         return newFromErrno(errno, customMsg, file, line);
3602     }
3603 
3604     // ditto, but error number is provided by caller
3605     static ProcessException newFromErrno(int error,
3606                                          string customMsg = null,
3607                                          string file = __FILE__,
3608                                          size_t line = __LINE__)
3609     {
3610         import std.exception : errnoString;
3611         auto errnoMsg = errnoString(error);
3612         auto msg = customMsg.empty ? errnoMsg
3613                                    : customMsg ~ " (" ~ errnoMsg ~ ')';
3614         return new ProcessException(msg, file, line);
3615     }
3616 
3617     // Creates a new ProcessException based on GetLastError() (Windows only).
3618     version (Windows)
3619     static ProcessException newFromLastError(string customMsg = null,
3620                                              string file = __FILE__,
3621                                              size_t line = __LINE__)
3622     {
3623         auto lastMsg = generateSysErrorMsg();
3624         auto msg = customMsg.empty ? lastMsg
3625                                    : customMsg ~ " (" ~ lastMsg ~ ')';
3626         return new ProcessException(msg, file, line);
3627     }
3628 }
3629 
3630 
3631 /**
3632 Determines the path to the current user's preferred command interpreter.
3633 
3634 On Windows, this function returns the contents of the COMSPEC environment
3635 variable, if it exists.  Otherwise, it returns the result of $(LREF nativeShell).
3636 
3637 On POSIX, `userShell` returns the contents of the SHELL environment
3638 variable, if it exists and is non-empty.  Otherwise, it returns the result of
3639 $(LREF nativeShell).
3640 */
3641 @property string userShell() @safe
3642 {
3643     version (Windows)      return environment.get("COMSPEC", nativeShell);
3644     else version (Posix)   return environment.get("SHELL", nativeShell);
3645 }
3646 
3647 /**
3648 The platform-specific native shell path.
3649 
3650 This function returns `"cmd.exe"` on Windows, `"/bin/sh"` on POSIX, and
3651 `"/system/bin/sh"` on Android.
3652 */
3653 @property string nativeShell() @safe @nogc pure nothrow
3654 {
3655     version (Windows)      return "cmd.exe";
3656     else version (Android) return "/system/bin/sh";
3657     else version (Posix)   return "/bin/sh";
3658 }
3659 
3660 // A command-line switch that indicates to the shell that it should
3661 // interpret the following argument as a command to be executed.
3662 version (Posix)   private immutable string shellSwitch = "-c";
3663 version (Windows) private immutable string shellSwitch = "/C";
3664 
3665 // Unittest support code:  TestScript takes a string that contains a
3666 // shell script for the current platform, and writes it to a temporary
3667 // file. On Windows the file name gets a .cmd extension, while on
3668 // POSIX its executable permission bit is set.  The file is
3669 // automatically deleted when the object goes out of scope.
3670 version (StdUnittest)
3671 private struct TestScript
3672 {
3673     this(string code) @system
3674     {
3675         // @system due to chmod
3676         import std.ascii : newline;
3677         import std.file : write;
3678         version (Windows)
3679         {
3680             auto ext = ".cmd";
3681             auto firstLine = "@echo off";
3682         }
3683         else version (Posix)
3684         {
3685             auto ext = "";
3686             auto firstLine = "#!" ~ nativeShell;
3687         }
3688         path = uniqueTempPath()~ext;
3689         write(path, firstLine ~ newline ~ code ~ newline);
3690         version (Posix)
3691         {
3692             import core.sys.posix.sys.stat : chmod;
3693             import std.conv : octal;
3694             chmod(path.tempCString(), octal!777);
3695         }
3696     }
3697 
3698     ~this()
3699     {
3700         import std.file : remove, exists;
3701         if (!path.empty && exists(path))
3702         {
3703             try { remove(path); }
3704             catch (Exception e)
3705             {
3706                 debug std.stdio.stderr.writeln(e.msg);
3707             }
3708         }
3709     }
3710 
3711     string path;
3712 }
3713 
3714 
3715 // =============================================================================
3716 // Functions for shell command quoting/escaping.
3717 // =============================================================================
3718 
3719 
3720 /*
3721     Command line arguments exist in three forms:
3722     1) string or char* array, as received by main.
3723        Also used internally on POSIX systems.
3724     2) Command line string, as used in Windows'
3725        CreateProcess and CommandLineToArgvW functions.
3726        A specific quoting and escaping algorithm is used
3727        to distinguish individual arguments.
3728     3) Shell command string, as written at a shell prompt
3729        or passed to cmd /C - this one may contain shell
3730        control characters, e.g. > or | for redirection /
3731        piping - thus, yet another layer of escaping is
3732        used to distinguish them from program arguments.
3733 
3734     Except for escapeWindowsArgument, the intermediary
3735     format (2) is hidden away from the user in this module.
3736 */
3737 
3738 /**
3739 Escapes an argv-style argument array to be used with $(LREF spawnShell),
3740 $(LREF pipeShell) or $(LREF executeShell).
3741 ---
3742 string url = "http://dlang.org/";
3743 executeShell(escapeShellCommand("wget", url, "-O", "dlang-index.html"));
3744 ---
3745 
3746 Concatenate multiple `escapeShellCommand` and
3747 $(LREF escapeShellFileName) results to use shell redirection or
3748 piping operators.
3749 ---
3750 executeShell(
3751     escapeShellCommand("curl", "http://dlang.org/download.html") ~
3752     "|" ~
3753     escapeShellCommand("grep", "-o", `http://\S*\.zip`) ~
3754     ">" ~
3755     escapeShellFileName("D download links.txt"));
3756 ---
3757 
3758 Throws:
3759 $(OBJECTREF Exception) if any part of the command line contains unescapable
3760 characters (NUL on all platforms, as well as CR and LF on Windows).
3761 */
3762 string escapeShellCommand(scope const(char[])[] args...) @safe pure
3763 {
3764     if (args.empty)
3765         return null;
3766     version (Windows)
3767     {
3768         // Do not ^-escape the first argument (the program path),
3769         // as the shell parses it differently from parameters.
3770         // ^-escaping a program path that contains spaces will fail.
3771         string result = escapeShellFileName(args[0]);
3772         if (args.length > 1)
3773         {
3774             result ~= " " ~ escapeShellCommandString(
3775                 escapeShellArguments(args[1..$]));
3776         }
3777         return result;
3778     }
3779     version (Posix)
3780     {
3781         return escapeShellCommandString(escapeShellArguments(args));
3782     }
3783 }
3784 
3785 @safe unittest
3786 {
3787     // This is a simple unit test without any special requirements,
3788     // in addition to the unittest_burnin one below which requires
3789     // special preparation.
3790 
3791     struct TestVector { string[] args; string windows, posix; }
3792     TestVector[] tests =
3793     [
3794         {
3795             args    : ["foo bar"],
3796             windows : `"foo bar"`,
3797             posix   : `'foo bar'`
3798         },
3799         {
3800             args    : ["foo bar", "hello"],
3801             windows : `"foo bar" hello`,
3802             posix   : `'foo bar' hello`
3803         },
3804         {
3805             args    : ["foo bar", "hello world"],
3806             windows : `"foo bar" ^"hello world^"`,
3807             posix   : `'foo bar' 'hello world'`
3808         },
3809         {
3810             args    : ["foo bar", "hello", "world"],
3811             windows : `"foo bar" hello world`,
3812             posix   : `'foo bar' hello world`
3813         },
3814         {
3815             args    : ["foo bar", `'"^\`],
3816             windows : `"foo bar" ^"'\^"^^\\^"`,
3817             posix   : `'foo bar' ''\''"^\'`
3818         },
3819         {
3820             args    : ["foo bar", ""],
3821             windows : `"foo bar" ^"^"`,
3822             posix   : `'foo bar' ''`
3823         },
3824         {
3825             args    : ["foo bar", "2"],
3826             windows : `"foo bar" ^"2^"`,
3827             posix   : `'foo bar' '2'`
3828         },
3829     ];
3830 
3831     foreach (test; tests)
3832     {
3833         auto actual = escapeShellCommand(test.args);
3834         version (Windows)
3835             string expected = test.windows;
3836         else
3837             string expected = test.posix;
3838         assert(actual == expected, "\nExpected: " ~ expected ~ "\nGot: " ~ actual);
3839     }
3840 }
3841 
3842 private string escapeShellCommandString(return scope string command) @safe pure
3843 {
3844     version (Windows)
3845         return escapeWindowsShellCommand(command);
3846     else
3847         return command;
3848 }
3849 
3850 private string escapeWindowsShellCommand(scope const(char)[] command) @safe pure
3851 {
3852     import std.array : appender;
3853     auto result = appender!string();
3854     result.reserve(command.length);
3855 
3856     foreach (c; command)
3857         switch (c)
3858         {
3859             case '\0':
3860                 throw new Exception("Cannot put NUL in command line");
3861             case '\r':
3862             case '\n':
3863                 throw new Exception("CR/LF are not escapable");
3864             case '\x01': .. case '\x09':
3865             case '\x0B': .. case '\x0C':
3866             case '\x0E': .. case '\x1F':
3867             case '"':
3868             case '^':
3869             case '&':
3870             case '<':
3871             case '>':
3872             case '|':
3873                 result.put('^');
3874                 goto default;
3875             default:
3876                 result.put(c);
3877         }
3878     return result.data;
3879 }
3880 
3881 private string escapeShellArguments(scope const(char[])[] args...)
3882     @trusted pure nothrow
3883 {
3884     import std.exception : assumeUnique;
3885     char[] buf;
3886 
3887     @safe nothrow
3888     char[] allocator(size_t size)
3889     {
3890         if (buf.length == 0)
3891             return buf = new char[size];
3892         else
3893         {
3894             auto p = buf.length;
3895             buf.length = buf.length + 1 + size;
3896             buf[p++] = ' ';
3897             return buf[p .. p+size];
3898         }
3899     }
3900 
3901     foreach (arg; args)
3902         escapeShellArgument!allocator(arg);
3903     return assumeUnique(buf);
3904 }
3905 
3906 private auto escapeShellArgument(alias allocator)(scope const(char)[] arg) @safe nothrow
3907 {
3908     // The unittest for this function requires special
3909     // preparation - see below.
3910 
3911     version (Windows)
3912         return escapeWindowsArgumentImpl!allocator(arg);
3913     else
3914         return escapePosixArgumentImpl!allocator(arg);
3915 }
3916 
3917 /**
3918 Quotes a command-line argument in a manner conforming to the behavior of
3919 $(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx,
3920 CommandLineToArgvW).
3921 */
3922 string escapeWindowsArgument(scope const(char)[] arg) @trusted pure nothrow
3923 {
3924     // Rationale for leaving this function as public:
3925     // this algorithm of escaping paths is also used in other software,
3926     // e.g. DMD's response files.
3927     import std.exception : assumeUnique;
3928     auto buf = escapeWindowsArgumentImpl!charAllocator(arg);
3929     return assumeUnique(buf);
3930 }
3931 
3932 
3933 private char[] charAllocator(size_t size) @safe pure nothrow
3934 {
3935     return new char[size];
3936 }
3937 
3938 
3939 private char[] escapeWindowsArgumentImpl(alias allocator)(scope const(char)[] arg)
3940     @safe nothrow
3941 if (is(typeof(allocator(size_t.init)[0] = char.init)))
3942 {
3943     // References:
3944     // * http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx
3945     // * http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx
3946 
3947     // Check if the string needs to be escaped,
3948     // and calculate the total string size.
3949 
3950     // Trailing backslashes must be escaped
3951     bool escaping = true;
3952     bool needEscape = false;
3953     // Result size = input size + 2 for surrounding quotes + 1 for the
3954     // backslash for each escaped character.
3955     size_t size = 1 + arg.length + 1;
3956 
3957     foreach_reverse (char c; arg)
3958     {
3959         if (c == '"')
3960         {
3961             needEscape = true;
3962             escaping = true;
3963             size++;
3964         }
3965         else
3966         if (c == '\\')
3967         {
3968             if (escaping)
3969                 size++;
3970         }
3971         else
3972         {
3973             if (c == ' ' || c == '\t')
3974                 needEscape = true;
3975             escaping = false;
3976         }
3977     }
3978 
3979     import std.ascii : isDigit;
3980     // Empty arguments need to be specified as ""
3981     if (!arg.length)
3982         needEscape = true;
3983     else
3984     // Arguments ending with digits need to be escaped,
3985     // to disambiguate with 1>file redirection syntax
3986     if (isDigit(arg[$-1]))
3987         needEscape = true;
3988 
3989     if (!needEscape)
3990         return allocator(arg.length)[] = arg;
3991 
3992     // Construct result string.
3993 
3994     auto buf = allocator(size);
3995     size_t p = size;
3996     buf[--p] = '"';
3997     escaping = true;
3998     foreach_reverse (char c; arg)
3999     {
4000         if (c == '"')
4001             escaping = true;
4002         else
4003         if (c != '\\')
4004             escaping = false;
4005 
4006         buf[--p] = c;
4007         if (escaping)
4008             buf[--p] = '\\';
4009     }
4010     buf[--p] = '"';
4011     assert(p == 0);
4012 
4013     return buf;
4014 }
4015 
4016 version (Windows) version (StdUnittest)
4017 {
4018 private:
4019     import core.stdc.stddef;
4020     import core.stdc.wchar_ : wcslen;
4021     import core.sys.windows.shellapi : CommandLineToArgvW;
4022     import core.sys.windows.winbase;
4023     import core.sys.windows.winnt;
4024     import std.array;
4025 
4026     string[] parseCommandLine(string line)
4027     {
4028         import std.algorithm.iteration : map;
4029         import std.array : array;
4030         import std.conv : to;
4031         auto lpCommandLine = (to!(WCHAR[])(line) ~ '\0').ptr;
4032         int numArgs;
4033         auto args = CommandLineToArgvW(lpCommandLine, &numArgs);
4034         scope(exit) LocalFree(args);
4035         return args[0 .. numArgs]
4036             .map!(arg => to!string(arg[0 .. wcslen(arg)]))
4037             .array();
4038     }
4039 
4040     @system unittest
4041     {
4042         import std.conv : text;
4043         string[] testStrings = [
4044             `Hello`,
4045             `Hello, world`,
4046             `Hello, "world"`,
4047             `C:\`,
4048             `C:\dmd`,
4049             `C:\Program Files\`,
4050         ];
4051 
4052         enum CHARS = `_x\" *&^` ~ "\t"; // _ is placeholder for nothing
4053         foreach (c1; CHARS)
4054         foreach (c2; CHARS)
4055         foreach (c3; CHARS)
4056         foreach (c4; CHARS)
4057             testStrings ~= [c1, c2, c3, c4].replace("_", "");
4058 
4059         foreach (s; testStrings)
4060         {
4061             auto q = escapeWindowsArgument(s);
4062             auto args = parseCommandLine("Dummy.exe " ~ q);
4063             assert(args.length == 2, s ~ " => " ~ q ~ " #" ~ text(args.length-1));
4064             assert(args[1] == s, s ~ " => " ~ q ~ " => " ~ args[1]);
4065         }
4066     }
4067 }
4068 
4069 private string escapePosixArgument(scope const(char)[] arg) @trusted pure nothrow
4070 {
4071     import std.exception : assumeUnique;
4072     auto buf = escapePosixArgumentImpl!charAllocator(arg);
4073     return assumeUnique(buf);
4074 }
4075 
4076 private char[] escapePosixArgumentImpl(alias allocator)(scope const(char)[] arg)
4077     @safe nothrow
4078 if (is(typeof(allocator(size_t.init)[0] = char.init)))
4079 {
4080     bool needQuoting = {
4081         import std.ascii : isAlphaNum, isDigit;
4082         import std.algorithm.comparison : among;
4083 
4084         // Empty arguments need to be specified as ''
4085         if (arg.length == 0)
4086             return true;
4087         // Arguments ending with digits need to be escaped,
4088         // to disambiguate with 1>file redirection syntax
4089         if (isDigit(arg[$-1]))
4090             return true;
4091 
4092         // Obtained using:
4093         // for n in $(seq 1 255) ; do
4094         //     c=$(printf \\$(printf "%o" $n))
4095         //     q=$(/bin/printf '%q' "$c")
4096         //     if [[ "$q" == "$c" ]] ; then printf "%s, " "'$c'" ; fi
4097         // done
4098         // printf '\n'
4099         foreach (char c; arg)
4100             if (!isAlphaNum(c) && !c.among('%', '+', ',', '-', '.', '/', ':', '@', ']', '_'))
4101                 return true;
4102         return false;
4103     }();
4104     if (!needQuoting)
4105     {
4106         auto buf = allocator(arg.length);
4107         buf[] = arg;
4108         return buf;
4109     }
4110 
4111     // '\'' means: close quoted part of argument, append an escaped
4112     // single quote, and reopen quotes
4113 
4114     // Below code is equivalent to:
4115     // return `'` ~ std.array.replace(arg, `'`, `'\''`) ~ `'`;
4116 
4117     size_t size = 1 + arg.length + 1;
4118     foreach (char c; arg)
4119         if (c == '\'')
4120             size += 3;
4121 
4122     auto buf = allocator(size);
4123     size_t p = 0;
4124     buf[p++] = '\'';
4125     foreach (char c; arg)
4126         if (c == '\'')
4127         {
4128             buf[p .. p+4] = `'\''`;
4129             p += 4;
4130         }
4131         else
4132             buf[p++] = c;
4133     buf[p++] = '\'';
4134     assert(p == size);
4135 
4136     return buf;
4137 }
4138 
4139 /**
4140 Escapes a filename to be used for shell redirection with $(LREF spawnShell),
4141 $(LREF pipeShell) or $(LREF executeShell).
4142 */
4143 string escapeShellFileName(scope const(char)[] fileName) @trusted pure nothrow
4144 {
4145     // The unittest for this function requires special
4146     // preparation - see below.
4147 
4148     version (Windows)
4149     {
4150         // If a file starts with &, it can cause cmd.exe to misinterpret
4151         // the file name as the stream redirection syntax:
4152         //     command > "&foo.txt"
4153         // gets interpreted as
4154         //     command >&foo.txt
4155         // Prepend .\ to disambiguate.
4156 
4157         if (fileName.length && fileName[0] == '&')
4158             return cast(string)(`".\` ~ fileName ~ '"');
4159 
4160         return cast(string)('"' ~ fileName ~ '"');
4161     }
4162     else
4163         return escapePosixArgument(fileName);
4164 }
4165 
4166 // Loop generating strings with random characters
4167 //version = unittest_burnin;
4168 
4169 version (unittest_burnin)
4170 @system unittest
4171 {
4172     // There are no readily-available commands on all platforms suitable
4173     // for properly testing command escaping. The behavior of CMD's "echo"
4174     // built-in differs from the POSIX program, and Windows ports of POSIX
4175     // environments (Cygwin, msys, gnuwin32) may interfere with their own
4176     // "echo" ports.
4177 
4178     // To run this unit test, create std_process_unittest_helper.d with the
4179     // following content and compile it:
4180     // import std.stdio, std.array; void main(string[] args) { write(args.join("\0")); }
4181     // Then, test this module with:
4182     // rdmd --main -unittest -version=unittest_burnin process.d
4183 
4184     import std.file : readText, remove;
4185     import std.format : format;
4186     import std.path : absolutePath;
4187     import std.random : uniform;
4188 
4189     auto helper = absolutePath("std_process_unittest_helper");
4190     assert(executeShell(helper ~ " hello").output.split("\0")[1..$] == ["hello"], "Helper malfunction");
4191 
4192     void test(string[] s, string fn)
4193     {
4194         string e;
4195         string[] g;
4196 
4197         e = escapeShellCommand(helper ~ s);
4198         {
4199             scope(failure) writefln("executeShell() failed.\nExpected:\t%s\nEncoded:\t%s", s, [e]);
4200             auto result = executeShell(e);
4201             assert(result.status == 0, "std_process_unittest_helper failed");
4202             g = result.output.split("\0")[1..$];
4203         }
4204         assert(s == g, format("executeShell() test failed.\nExpected:\t%s\nGot:\t\t%s\nEncoded:\t%s", s, g, [e]));
4205 
4206         e = escapeShellCommand(helper ~ s) ~ ">" ~ escapeShellFileName(fn);
4207         {
4208             scope(failure) writefln(
4209                 "executeShell() with redirect failed.\nExpected:\t%s\nFilename:\t%s\nEncoded:\t%s", s, [fn], [e]);
4210             auto result = executeShell(e);
4211             assert(result.status == 0, "std_process_unittest_helper failed");
4212             assert(!result.output.length, "No output expected, got:\n" ~ result.output);
4213             g = readText(fn).split("\0")[1..$];
4214         }
4215         remove(fn);
4216         assert(s == g,
4217             format("executeShell() with redirect test failed.\nExpected:\t%s\nGot:\t\t%s\nEncoded:\t%s", s, g, [e]));
4218     }
4219 
4220     while (true)
4221     {
4222         string[] args;
4223         foreach (n; 0 .. uniform(1, 4))
4224         {
4225             string arg;
4226             foreach (l; 0 .. uniform(0, 10))
4227             {
4228                 dchar c;
4229                 while (true)
4230                 {
4231                     version (Windows)
4232                     {
4233                         // As long as DMD's system() uses CreateProcessA,
4234                         // we can't reliably pass Unicode
4235                         c = uniform(0, 128);
4236                     }
4237                     else
4238                         c = uniform!ubyte();
4239 
4240                     if (c == 0)
4241                         continue; // argv-strings are zero-terminated
4242                     version (Windows)
4243                         if (c == '\r' || c == '\n')
4244                             continue; // newlines are unescapable on Windows
4245                     break;
4246                 }
4247                 arg ~= c;
4248             }
4249             args ~= arg;
4250         }
4251 
4252         // generate filename
4253         string fn;
4254         foreach (l; 0 .. uniform(1, 10))
4255         {
4256             dchar c;
4257             while (true)
4258             {
4259                 version (Windows)
4260                     c = uniform(0, 128); // as above
4261                 else
4262                     c = uniform!ubyte();
4263 
4264                 if (c == 0 || c == '/')
4265                     continue; // NUL and / are the only characters
4266                               // forbidden in POSIX filenames
4267                 version (Windows)
4268                     if (c < '\x20' || c == '<' || c == '>' || c == ':' ||
4269                         c == '"' || c == '\\' || c == '|' || c == '?' || c == '*')
4270                         continue; // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx
4271                 break;
4272             }
4273 
4274             fn ~= c;
4275         }
4276         fn = fn[0..$/2] ~ "_testfile_" ~ fn[$/2..$];
4277 
4278         test(args, fn);
4279     }
4280 }
4281 
4282 // =============================================================================
4283 // Everything below this line was part of the old std.process, and most of
4284 // it will be deprecated and removed.
4285 // =============================================================================
4286 
4287 
4288 /*
4289 Copyright: Copyright The D Language Foundation 2007 - 2009.
4290 License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
4291 Authors:   $(HTTP digitalmars.com, Walter Bright),
4292            $(HTTP erdani.org, Andrei Alexandrescu),
4293            $(HTTP thecybershadow.net, Vladimir Panteleev)
4294 Source:    $(PHOBOSSRC std/_process.d)
4295 */
4296 /*
4297          Copyright The D Language Foundation 2007 - 2009.
4298 Distributed under the Boost Software License, Version 1.0.
4299    (See accompanying file LICENSE_1_0.txt or copy at
4300          http://www.boost.org/LICENSE_1_0.txt)
4301 */
4302 
4303 
4304 import core.stdc.errno;
4305 import core.stdc.stdlib;
4306 import core.stdc.string;
4307 import core.thread;
4308 
4309 version (Windows)
4310 {
4311     import std.file, std.format, std.random;
4312 }
4313 version (Posix)
4314 {
4315     import core.sys.posix.stdlib;
4316 }
4317 
4318 private void toAStringz(in string[] a, const(char)**az)
4319 {
4320     import std.string : toStringz;
4321     foreach (string s; a)
4322     {
4323         *az++ = toStringz(s);
4324     }
4325     *az = null;
4326 }
4327 
4328 
4329 /* ========================================================== */
4330 
4331 //version (Windows)
4332 //{
4333 //    int spawnvp(int mode, string pathname, string[] argv)
4334 //    {
4335 //      char** argv_ = cast(char**) core.stdc.stdlib.malloc((char*).sizeof * (1 + argv.length));
4336 //      scope(exit) core.stdc.stdlib.free(argv_);
4337 //
4338 //      toAStringz(argv, argv_);
4339 //
4340 //      return spawnvp(mode, pathname.tempCString(), argv_);
4341 //    }
4342 //}
4343 
4344 // Incorporating idea (for spawnvp() on Posix) from Dave Fladebo
4345 
4346 enum { _P_WAIT, _P_NOWAIT, _P_OVERLAY }
4347 version (Windows) extern(C) int spawnvp(int, scope const(char) *, scope const(char*)*);
4348 alias P_WAIT = _P_WAIT;
4349 alias P_NOWAIT = _P_NOWAIT;
4350 
4351 /* ========================================================== */
4352 
4353 version (StdDdoc)
4354 {
4355     /**
4356     Replaces the current process by executing a command, `pathname`, with
4357     the arguments in `argv`.
4358 
4359     $(BLUE This function is Posix-Only.)
4360 
4361     Typically, the first element of `argv` is
4362     the command being executed, i.e. $(D argv[0] == pathname). The 'p'
4363     versions of `exec` search the PATH environment variable for $(D
4364     pathname). The 'e' versions additionally take the new process'
4365     environment variables as an array of strings of the form key=value.
4366 
4367     Does not return on success (the current process will have been
4368     replaced). Returns -1 on failure with no indication of the
4369     underlying error.
4370 
4371     Windows_specific:
4372     These functions are only supported on POSIX platforms, as the Windows
4373     operating systems do not provide the ability to overwrite the current
4374     process image with another. In single-threaded programs it is possible
4375     to approximate the effect of `execv*` by using $(LREF spawnProcess)
4376     and terminating the current process once the child process has returned.
4377     For example:
4378     ---
4379     auto commandLine = [ "program", "arg1", "arg2" ];
4380     version (Posix)
4381     {
4382         execv(commandLine[0], commandLine);
4383         throw new Exception("Failed to execute program");
4384     }
4385     else version (Windows)
4386     {
4387         import core.stdc.stdlib : _Exit;
4388         _Exit(wait(spawnProcess(commandLine)));
4389     }
4390     ---
4391     This is, however, NOT equivalent to POSIX' `execv*`.  For one thing, the
4392     executed program is started as a separate process, with all this entails.
4393     Secondly, in a multithreaded program, other threads will continue to do
4394     work while the current thread is waiting for the child process to complete.
4395 
4396     A better option may sometimes be to terminate the current program immediately
4397     after spawning the child process.  This is the behaviour exhibited by the
4398     $(LINK2 http://msdn.microsoft.com/en-us/library/431x4c1w.aspx,`__exec`)
4399     functions in Microsoft's C runtime library, and it is how D's now-deprecated
4400     Windows `execv*` functions work. Example:
4401     ---
4402     auto commandLine = [ "program", "arg1", "arg2" ];
4403     version (Posix)
4404     {
4405         execv(commandLine[0], commandLine);
4406         throw new Exception("Failed to execute program");
4407     }
4408     else version (Windows)
4409     {
4410         spawnProcess(commandLine);
4411         import core.stdc.stdlib : _exit;
4412         _exit(0);
4413     }
4414     ---
4415     */
4416     int execv(in string pathname, in string[] argv);
4417     ///ditto
4418     int execve(in string pathname, in string[] argv, in string[] envp);
4419     /// ditto
4420     int execvp(in string pathname, in string[] argv);
4421     /// ditto
4422     int execvpe(in string pathname, in string[] argv, in string[] envp);
4423 }
4424 else version (Posix)
4425 {
4426     int execv(in string pathname, in string[] argv)
4427     {
4428         return execv_(pathname, argv);
4429     }
4430     int execve(in string pathname, in string[] argv, in string[] envp)
4431     {
4432         return execve_(pathname, argv, envp);
4433     }
4434     int execvp(in string pathname, in string[] argv)
4435     {
4436         return execvp_(pathname, argv);
4437     }
4438     int execvpe(in string pathname, in string[] argv, in string[] envp)
4439     {
4440         return execvpe_(pathname, argv, envp);
4441     }
4442 }
4443 
4444 // Move these C declarations to druntime if we decide to keep the D wrappers
4445 extern(C)
4446 {
4447     int execv(scope const(char) *, scope const(char *)*);
4448     int execve(scope const(char)*, scope const(char*)*, scope const(char*)*);
4449     int execvp(scope const(char)*, scope const(char*)*);
4450     version (Windows) int execvpe(scope const(char)*, scope const(char*)*, scope const(char*)*);
4451 }
4452 
4453 private int execv_(in string pathname, in string[] argv)
4454 {
4455     import core.exception : OutOfMemoryError;
4456     import std.exception : enforce;
4457     auto argv_ = cast(const(char)**)core.stdc.stdlib.malloc((char*).sizeof * (1 + argv.length));
4458     enforce!OutOfMemoryError(argv_ !is null, "Out of memory in std.process.");
4459     scope(exit) core.stdc.stdlib.free(argv_);
4460 
4461     toAStringz(argv, argv_);
4462 
4463     return execv(pathname.tempCString(), argv_);
4464 }
4465 
4466 private int execve_(in string pathname, in string[] argv, in string[] envp)
4467 {
4468     import core.exception : OutOfMemoryError;
4469     import std.exception : enforce;
4470     auto argv_ = cast(const(char)**)core.stdc.stdlib.malloc((char*).sizeof * (1 + argv.length));
4471     enforce!OutOfMemoryError(argv_ !is null, "Out of memory in std.process.");
4472     scope(exit) core.stdc.stdlib.free(argv_);
4473     auto envp_ = cast(const(char)**)core.stdc.stdlib.malloc((char*).sizeof * (1 + envp.length));
4474     enforce!OutOfMemoryError(envp_ !is null, "Out of memory in std.process.");
4475     scope(exit) core.stdc.stdlib.free(envp_);
4476 
4477     toAStringz(argv, argv_);
4478     toAStringz(envp, envp_);
4479 
4480     return execve(pathname.tempCString(), argv_, envp_);
4481 }
4482 
4483 private int execvp_(in string pathname, in string[] argv)
4484 {
4485     import core.exception : OutOfMemoryError;
4486     import std.exception : enforce;
4487     auto argv_ = cast(const(char)**)core.stdc.stdlib.malloc((char*).sizeof * (1 + argv.length));
4488     enforce!OutOfMemoryError(argv_ !is null, "Out of memory in std.process.");
4489     scope(exit) core.stdc.stdlib.free(argv_);
4490 
4491     toAStringz(argv, argv_);
4492 
4493     return execvp(pathname.tempCString(), argv_);
4494 }
4495 
4496 private int execvpe_(in string pathname, in string[] argv, in string[] envp)
4497 {
4498 version (Posix)
4499 {
4500     import std.array : split;
4501     import std.conv : to;
4502     // Is pathname rooted?
4503     if (pathname[0] == '/')
4504     {
4505         // Yes, so just call execve()
4506         return execve(pathname, argv, envp);
4507     }
4508     else
4509     {
4510         // No, so must traverse PATHs, looking for first match
4511         string[]    envPaths    =   split(
4512             to!string(core.stdc.stdlib.getenv("PATH")), ":");
4513         int         iRet        =   0;
4514 
4515         // Note: if any call to execve() succeeds, this process will cease
4516         // execution, so there's no need to check the execve() result through
4517         // the loop.
4518 
4519         foreach (string pathDir; envPaths)
4520         {
4521             string  composite   =  cast(string) (pathDir ~ "/" ~ pathname);
4522 
4523             iRet = execve(composite, argv, envp);
4524         }
4525         if (0 != iRet)
4526         {
4527             iRet = execve(pathname, argv, envp);
4528         }
4529 
4530         return iRet;
4531     }
4532 }
4533 else version (Windows)
4534 {
4535     import core.exception : OutOfMemoryError;
4536     import std.exception : enforce;
4537     auto argv_ = cast(const(char)**)core.stdc.stdlib.malloc((char*).sizeof * (1 + argv.length));
4538     enforce!OutOfMemoryError(argv_ !is null, "Out of memory in std.process.");
4539     scope(exit) core.stdc.stdlib.free(argv_);
4540     auto envp_ = cast(const(char)**)core.stdc.stdlib.malloc((char*).sizeof * (1 + envp.length));
4541     enforce!OutOfMemoryError(envp_ !is null, "Out of memory in std.process.");
4542     scope(exit) core.stdc.stdlib.free(envp_);
4543 
4544     toAStringz(argv, argv_);
4545     toAStringz(envp, envp_);
4546 
4547     return execvpe(pathname.tempCString(), argv_, envp_);
4548 }
4549 else
4550 {
4551     static assert(0);
4552 } // version
4553 }
4554 
4555 version (StdDdoc)
4556 {
4557     /****************************************
4558      * Start up the browser and set it to viewing the page at url.
4559      */
4560     void browse(scope const(char)[] url);
4561 }
4562 else
4563 version (Windows)
4564 {
4565     import core.sys.windows.shellapi, core.sys.windows.winuser;
4566 
4567     pragma(lib,"shell32.lib");
4568 
4569     void browse(scope const(char)[] url) nothrow @nogc @trusted
4570     {
4571         ShellExecuteW(null, "open", url.tempCStringW(), null, null, SW_SHOWNORMAL);
4572     }
4573 }
4574 else version (Posix)
4575 {
4576     import core.stdc.stdio;
4577     import core.stdc.string;
4578     import core.sys.posix.unistd;
4579 
4580     void browse(scope const(char)[] url) nothrow @nogc @safe
4581     {
4582         const buffer = url.tempCString(); // Retain buffer until end of scope
4583         const(char)*[3] args;
4584 
4585         // Trusted because it's called with a zero-terminated literal
4586         const(char)* browser = (() @trusted => core.stdc.stdlib.getenv("BROWSER"))();
4587         if (browser)
4588         {
4589             // String already zero-terminated
4590             browser = (() @trusted => strdup(browser))();
4591             args[0] = browser;
4592         }
4593         else
4594         {
4595             version (OSX)
4596             {
4597                 args[0] = "open";
4598             }
4599             else
4600             {
4601                 //args[0] = "x-www-browser";  // doesn't work on some systems
4602                 args[0] = "xdg-open";
4603             }
4604         }
4605 
4606         args[1] = buffer;
4607         args[2] = null;
4608 
4609         auto childpid = core.sys.posix.unistd.fork();
4610         if (childpid == 0)
4611         {
4612             // Trusted because args and all entries are always zero-terminated
4613             (() @trusted {
4614                 core.sys.posix.unistd.execvp(args[0], &args[0]);
4615                 perror(args[0]);
4616                 core.sys.posix.unistd._exit(1);
4617             })();
4618             assert(0, "Child failed to exec");
4619         }
4620         if (browser)
4621             // Trusted because it's allocated via strdup above
4622             (() @trusted => free(cast(void*) browser))();
4623 
4624         version (StdUnittest)
4625         {
4626             // Verify that the test script actually suceeds
4627             int status;
4628             const check = (() @trusted => waitpid(childpid, &status, 0))();
4629             assert(check != -1);
4630             assert(status == 0);
4631         }
4632     }
4633 }
4634 else
4635     static assert(0, "os not supported");
4636 
4637 // Verify attributes are consistent between all implementations
4638 @safe @nogc nothrow unittest
4639 {
4640     if (false)
4641         browse("");
4642 }
4643 
4644 version (Windows) { /* Doesn't use BROWSER */ }
4645 else
4646 @system unittest
4647 {
4648     import std.conv : text;
4649     import std.range : repeat;
4650     immutable string url = text("http://", repeat('x', 249));
4651 
4652     TestScript prog = `if [ "$1" != "` ~ url ~ `" ]; then exit 1; fi`;
4653     environment["BROWSER"] = prog.path;
4654     browse(url);
4655 }