The OpenD Programming Language

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