// Written in the D programming language.

/**
Functions for starting and interacting with other processes, and for
working with the current process' execution environment.

Process_handling:
$(UL $(LI
    $(LREF spawnProcess) spawns a new process, optionally assigning it an
    arbitrary set of standard input, output, and error streams.
    The function returns immediately, leaving the child process to execute
    in parallel with its parent.  All other functions in this module that
    spawn processes are built around `spawnProcess`.)
$(LI
    $(LREF wait) makes the parent process wait for a child process to
    terminate.  In general one should always do this, to avoid
    child processes becoming "zombies" when the parent process exits.
    Scope guards are perfect for this – see the $(LREF spawnProcess)
    documentation for examples.  $(LREF tryWait) is similar to `wait`,
    but does not block if the process has not yet terminated.)
$(LI
    $(LREF pipeProcess) also spawns a child process which runs
    in parallel with its parent.  However, instead of taking
    arbitrary streams, it automatically creates a set of
    pipes that allow the parent to communicate with the child
    through the child's standard input, output, and/or error streams.
    This function corresponds roughly to C's `popen` function.)
$(LI
    $(LREF execute) starts a new process and waits for it
    to complete before returning.  Additionally, it captures
    the process' standard output and error streams and returns
    the output of these as a string.)
$(LI
    $(LREF spawnShell), $(LREF pipeShell) and $(LREF executeShell) work like
    `spawnProcess`, `pipeProcess` and `execute`, respectively,
    except that they take a single command string and run it through
    the current user's default command interpreter.
    `executeShell` corresponds roughly to C's `system` function.)
$(LI
    $(LREF kill) attempts to terminate a running process.)
)

The following table compactly summarises the different process creation
functions and how they relate to each other:
$(BOOKTABLE,
    $(TR $(TH )
         $(TH Runs program directly)
         $(TH Runs shell command))
    $(TR $(TD Low-level process creation)
         $(TD $(LREF spawnProcess))
         $(TD $(LREF spawnShell)))
    $(TR $(TD Automatic input/output redirection using pipes)
         $(TD $(LREF pipeProcess))
         $(TD $(LREF pipeShell)))
    $(TR $(TD Execute and wait for completion, collect output)
         $(TD $(LREF execute))
         $(TD $(LREF executeShell)))
)

Other_functionality:
$(UL
$(LI
    $(LREF pipe) is used to create unidirectional pipes.)
$(LI
    $(LREF environment) is an interface through which the current process'
    environment variables can be read and manipulated.)
$(LI
    $(LREF escapeShellCommand) and $(LREF escapeShellFileName) are useful
    for constructing shell command lines in a portable way.)
)

Authors:
    $(LINK2 https://github.com/kyllingstad, Lars Tandle Kyllingstad),
    $(LINK2 https://github.com/schveiguy, Steven Schveighoffer),
    $(HTTP thecybershadow.net, Vladimir Panteleev)
Copyright:
    Copyright (c) 2013, the authors. All rights reserved.
License:
   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
Source:
    $(PHOBOSSRC std/process.d)
Macros:
    OBJECTREF=$(REF1 $0, object)

Note:
Most of the functionality in this module is not available on iOS, tvOS
and watchOS. The only functions available on those platforms are:
$(LREF environment), $(LREF thisProcessID) and $(LREF thisThreadID).
*/
module std.process;

import core.thread : ThreadID;

version (Posix)
{
    import core.sys.posix.sys.wait;
    import core.sys.posix.unistd;
}
version (Windows)
{
    import core.stdc.stdio;
    import core.sys.windows.winbase;
    import core.sys.windows.winnt;
    import std.utf;
    import std.windows.syserror;
}

import std.internal.cstring;
import std.range;
import std.stdio;

version (OSX)
    version = Darwin;
else version (iOS)
{
    version = Darwin;
    version = iOSDerived;
}
else version (TVOS)
{
    version = Darwin;
    version = iOSDerived;
}
else version (WatchOS)
{
    version = Darwin;
    version = iOSDerived;
}


// Some of the following should be moved to druntime.
private
{
    // Microsoft Visual C Runtime (MSVCRT) declarations.
    version (CRuntime_Microsoft)
    {
        import core.stdc.stdint;
        enum
        {
            STDIN_FILENO  = 0,
            STDOUT_FILENO = 1,
            STDERR_FILENO = 2,
        }
    }

    // POSIX API declarations.
    version (Posix)
    {
        import core.sys.posix.unistd : getEnvironPtr = environ;

        @system unittest
        {
            import core.thread : Thread;
            new Thread({assert(getEnvironPtr !is null);}).start();
        }
    }
} // private

// =============================================================================
// Environment variable manipulation.
// =============================================================================

/**
Manipulates _environment variables using an associative-array-like
interface.

This class contains only static methods, and cannot be instantiated.
See below for examples of use.
*/
abstract final class environment
{
    static import core.sys.posix.stdlib;
    import core.stdc.errno : errno, EINVAL;

static:
    /**
    Retrieves the value of the environment variable with the given `name`.
    ---
    auto path = environment["PATH"];
    ---

    Throws:
    $(OBJECTREF Exception) if the environment variable does not exist,
    or $(REF UTFException, std,utf) if the variable contains invalid UTF-16
    characters (Windows only).

    See_also:
    $(LREF environment.get), which doesn't throw on failure.
    */
    string opIndex(scope const(char)[] name) @safe
    {
        import std.exception : enforce;
        return get(name, null).enforce("Environment variable not found: "~name);
    }

    /**
    Retrieves the value of the environment variable with the given `name`,
    or a default value if the variable doesn't exist.

    Unlike $(LREF environment.opIndex), this function never throws on Posix.
    ---
    auto sh = environment.get("SHELL", "/bin/sh");
    ---
    This function is also useful in checking for the existence of an
    environment variable.
    ---
    auto myVar = environment.get("MYVAR");
    if (myVar is null)
    {
        // Environment variable doesn't exist.
        // Note that we have to use 'is' for the comparison, since
        // myVar == null is also true if the variable exists but is
        // empty.
    }
    ---
    Params:
        name = name of the environment variable to retrieve
        defaultValue = default value to return if the environment variable doesn't exist.

    Returns:
        the value of the environment variable if found, otherwise
        `null` if the environment doesn't exist.

    Throws:
    $(REF UTFException, std,utf) if the variable contains invalid UTF-16
    characters (Windows only).
    */
    string get(scope const(char)[] name, string defaultValue = null) @safe
    {
        string value;
        getImpl(name, (result) { value = result ? cachedToString(result) : defaultValue; });
        return value;
    }

    /**
    Assigns the given `value` to the environment variable with the given
    `name`.
    If `value` is null the variable is removed from environment.

    If the variable does not exist, it will be created. If it already exists,
    it will be overwritten.
    ---
    environment["foo"] = "bar";
    ---

    Throws:
    $(OBJECTREF Exception) if the environment variable could not be added
        (e.g. if the name is invalid).

    Note:
    On some platforms, modifying environment variables may not be allowed in
    multi-threaded programs. See e.g.
    $(LINK2 https://www.gnu.org/software/libc/manual/html_node/Environment-Access.html#Environment-Access, glibc).
    */
    inout(char)[] opIndexAssign(return scope inout char[] value, scope const(char)[] name) @trusted
    {
        version (Posix)
        {
            import std.exception : enforce, errnoEnforce;
            if (value is null)
            {
                remove(name);
                return value;
            }
            if (core.sys.posix.stdlib.setenv(name.tempCString(), value.tempCString(), 1) != -1)
            {
                return value;
            }
            // The default errno error message is very uninformative
            // in the most common case, so we handle it manually.
            enforce(errno != EINVAL,
                "Invalid environment variable name: '"~name~"'");
            errnoEnforce(false,
                "Failed to add environment variable");
            assert(0);
        }
        else version (Windows)
        {
            import std.windows.syserror : wenforce;
            wenforce(
                SetEnvironmentVariableW(name.tempCStringW(), value.tempCStringW()),
            );
            return value;
        }
        else static assert(0);
    }

    /**
    Removes the environment variable with the given `name`.

    If the variable isn't in the environment, this function returns
    successfully without doing anything.

    Note:
    On some platforms, modifying environment variables may not be allowed in
    multi-threaded programs. See e.g.
    $(LINK2 https://www.gnu.org/software/libc/manual/html_node/Environment-Access.html#Environment-Access, glibc).
    */
    void remove(scope const(char)[] name) @trusted nothrow @nogc
    {
        version (Windows)    SetEnvironmentVariableW(name.tempCStringW(), null);
        else version (Posix) core.sys.posix.stdlib.unsetenv(name.tempCString());
        else static assert(0);
    }

    /**
    Identify whether a variable is defined in the environment.

    Because it doesn't return the value, this function is cheaper than `get`.
    However, if you do need the value as well, you should just check the
    return of `get` for `null` instead of using this function first.

    Example:
    -------------
    // good usage
    if ("MY_ENV_FLAG" in environment)
        doSomething();

    // bad usage
    if ("MY_ENV_VAR" in environment)
        doSomething(environment["MY_ENV_VAR"]);

    // do this instead
    if (auto var = environment.get("MY_ENV_VAR"))
        doSomething(var);
    -------------
    */
    bool opBinaryRight(string op : "in")(scope const(char)[] name) @trusted
    {
        if (name is null)
            return false;
        version (Posix)
            return core.sys.posix.stdlib.getenv(name.tempCString()) !is null;
        else version (Windows)
        {
            SetLastError(NO_ERROR);
            if (GetEnvironmentVariableW(name.tempCStringW, null, 0) > 0)
                return true;
            immutable err = GetLastError();
            if (err == NO_ERROR)
                return true; // zero-length environment variable on Wine / XP
            if (err == ERROR_ENVVAR_NOT_FOUND)
                return false;
            // Some other Windows error, throw.
            throw new WindowsException(err);
        }
        else static assert(0);
    }

    /**
    Copies all environment variables into an associative array.

    Windows_specific:
    While Windows environment variable names are case insensitive, D's
    built-in associative arrays are not.  This function will store all
    variable names in uppercase (e.g. `PATH`).

    Throws:
    $(OBJECTREF Exception) if the environment variables could not
        be retrieved (Windows only).
    */
    string[string] toAA() @trusted
    {
        import std.conv : to;
        string[string] aa;
        version (Posix)
        {
            auto environ = getEnvironPtr;
            for (int i=0; environ[i] != null; ++i)
            {
                import std.string : indexOf;

                immutable varDef = to!string(environ[i]);
                immutable eq = indexOf(varDef, '=');
                assert(eq >= 0);

                immutable name = varDef[0 .. eq];
                immutable value = varDef[eq+1 .. $];

                // In POSIX, environment variables may be defined more
                // than once.  This is a security issue, which we avoid
                // by checking whether the key already exists in the array.
                // For more info:
                // http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/environment-variables.html
                if (name !in aa)  aa[name] = value;
            }
        }
        else version (Windows)
        {
            import std.exception : enforce;
            import std.uni : toUpper;
            auto envBlock = GetEnvironmentStringsW();
            enforce(envBlock, "Failed to retrieve environment variables.");
            scope(exit) FreeEnvironmentStringsW(envBlock);

            for (int i=0; envBlock[i] != '\0'; ++i)
            {
                auto start = i;
                while (envBlock[i] != '=') ++i;
                immutable name = toUTF8(toUpper(envBlock[start .. i]));

                start = i+1;
                while (envBlock[i] != '\0') ++i;

                // Ignore variables with empty names. These are used internally
                // by Windows to keep track of each drive's individual current
                // directory.
                if (!name.length)
                    continue;

                // Just like in POSIX systems, environment variables may be
                // defined more than once in an environment block on Windows,
                // and it is just as much of a security issue there.  Moreso,
                // in fact, due to the case insensensitivity of variable names,
                // which is not handled correctly by all programs.
                auto val = toUTF8(envBlock[start .. i]);
                if (name !in aa) aa[name] = val is null ? "" : val;
            }
        }
        else static assert(0);
        return aa;
    }

private:
    version (Windows) alias OSChar = WCHAR;
    else version (Posix) alias OSChar = char;

    // Retrieves the environment variable. Calls `sink` with a
    // temporary buffer of OS characters, or `null` if the variable
    // doesn't exist.
    void getImpl(scope const(char)[] name, scope void delegate(const(OSChar)[]) @safe sink) @trusted
    {
        // fix issue https://issues.dlang.org/show_bug.cgi?id=24549
        if (name is null)
            return sink(null);

        version (Windows)
        {
            // first we ask windows how long the environment variable is,
            // then we try to read it in to a buffer of that length. Lots
            // of error conditions because the windows API is nasty.

            import std.conv : to;
            const namezTmp = name.tempCStringW();
            WCHAR[] buf;

            // clear error because GetEnvironmentVariable only says it sets it
            // if the environment variable is missing, not on other errors.
            SetLastError(NO_ERROR);
            // len includes terminating null
            immutable len = GetEnvironmentVariableW(namezTmp, null, 0);
            if (len == 0)
            {
                immutable err = GetLastError();
                if (err == ERROR_ENVVAR_NOT_FOUND)
                    return sink(null);
                if (err != NO_ERROR) // Some other Windows error, throw.
                    throw new WindowsException(err);
            }
            if (len <= 1)
                return sink("");
            buf.length = len;

            while (true)
            {
                // lenRead is either the number of bytes read w/o null - if buf was long enough - or
                // the number of bytes necessary *including* null if buf wasn't long enough
                immutable lenRead = GetEnvironmentVariableW(namezTmp, buf.ptr, to!DWORD(buf.length));
                if (lenRead == 0)
                {
                    immutable err = GetLastError();
                    if (err == NO_ERROR) // sucessfully read a 0-length variable
                        return sink("");
                    if (err == ERROR_ENVVAR_NOT_FOUND) // variable didn't exist
                        return sink(null);
                    // some other windows error
                    throw new WindowsException(err);
                }
                assert(lenRead != buf.length, "impossible according to msft docs");
                if (lenRead < buf.length) // the buffer was long enough
                    return sink(buf[0 .. lenRead]);
                // resize and go around again, because the environment variable grew
                buf.length = lenRead;
            }
        }
        else version (Posix)
        {
            import core.stdc.string : strlen;

            const vz = core.sys.posix.stdlib.getenv(name.tempCString());
            if (vz == null) return sink(null);
            return sink(vz[0 .. strlen(vz)]);
       }
        else static assert(0);
    }

    string cachedToString(C)(scope const(C)[] v) @safe
    {
        import std.algorithm.comparison : equal;

        // Cache the last call's result.
        static string lastResult;
        if (v.empty)
        {
            // Return non-null array for blank result to distinguish from
            // not-present result.
            lastResult = "";
        }
        else if (!v.equal(lastResult))
        {
            import std.conv : to;
            lastResult = v.to!string;
        }
        return lastResult;
    }
}

@safe unittest
{
    import std.exception : assertThrown;
    // New variable
    environment["std_process"] = "foo";
    assert(environment["std_process"] == "foo");
    assert("std_process" in environment);

    // Set variable again (also tests length 1 case)
    environment["std_process"] = "b";
    assert(environment["std_process"] == "b");
    assert("std_process" in environment);

    // Remove variable
    environment.remove("std_process");
    assert("std_process" !in environment);

    // Remove again, should succeed
    environment.remove("std_process");
    assert("std_process" !in environment);

    // Throw on not found.
    assertThrown(environment["std_process"]);

    // get() without default value
    assert(environment.get("std_process") is null);

    // get() with default value
    assert(environment.get("std_process", "baz") == "baz");

    // get() on an empty (but present) value
    environment["std_process"] = "";
    auto res = environment.get("std_process");
    assert(res !is null);
    assert(res == "");
    assert("std_process" in environment);

    // Important to do the following round-trip after the previous test
    // because it tests toAA with an empty var

    // Convert to associative array
    auto aa = environment.toAA();
    assert(aa.length > 0);
    foreach (n, v; aa)
    {
        // Wine has some bugs related to environment variables:
        //  - Wine allows the existence of an env. variable with the name
        //    "\0", but GetEnvironmentVariable refuses to retrieve it.
        //    As of 2.067 we filter these out anyway (see comment in toAA).

        assert(v == environment[n]);
    }

    // ... and back again.
    foreach (n, v; aa)
        environment[n] = v;

    // Complete the roundtrip
    auto aa2 = environment.toAA();
    import std.conv : text;
    assert(aa == aa2, text(aa, " != ", aa2));
    assert("std_process" in environment);

    // Setting null must have the same effect as remove
    environment["std_process"] = null;
    assert("std_process" !in environment);
}

// https://issues.dlang.org/show_bug.cgi?id=24549
@safe unittest
{
    import std.exception : assertThrown;
    assert(environment.get(null) is null);
    assertThrown(environment[null]);
    assert(!(null in environment));
}

// =============================================================================
// Functions and classes for process management.
// =============================================================================

/**
 * Returns the process ID of the current process,
 * which is guaranteed to be unique on the system.
 *
 * Example:
 * ---
 * writefln("Current process ID: %d", thisProcessID);
 * ---
 */
@property int thisProcessID() @trusted nothrow @nogc //TODO: @safe
{
    version (Windows)    return GetCurrentProcessId();
    else version (Posix) return core.sys.posix.unistd.getpid();
}


/**
 * Returns the process ID of the current thread,
 * which is guaranteed to be unique within the current process.
 *
 * Returns:
 * A $(REF ThreadID, core,thread) value for the calling thread.
 *
 * Example:
 * ---
 * writefln("Current thread ID: %s", thisThreadID);
 * ---
 */
@property ThreadID thisThreadID() @trusted nothrow @nogc //TODO: @safe
{
    version (Windows)
        return GetCurrentThreadId();
    else
    version (Posix)
    {
        import core.sys.posix.pthread : pthread_self;
        return pthread_self();
    }
}


@system unittest
{
    int pidA, pidB;
    ThreadID tidA, tidB;
    pidA = thisProcessID;
    tidA = thisThreadID;

    import core.thread;
    auto t = new Thread({
        pidB = thisProcessID;
        tidB = thisThreadID;
    });
    t.start();
    t.join();

    assert(pidA == pidB);
    assert(tidA != tidB);
}


package(std) string uniqueTempPath() @safe
{
    import std.file : tempDir;
    import std.path : buildPath;
    import std.uuid : randomUUID;
    // Path should contain spaces to test escaping whitespace
    return buildPath(tempDir(), "std.process temporary file " ~
        randomUUID().toString());
}


version (iOSDerived) {}
else:

/**
Spawns a new process, optionally assigning it an arbitrary set of standard
input, output, and error streams.

The function returns immediately, leaving the child process to execute
in parallel with its parent.  It is recommended to always call $(LREF wait)
on the returned $(LREF Pid) unless the process was spawned with
`Config.detached` flag, as detailed in the documentation for `wait`.

Command_line:
There are four overloads of this function.  The first two take an array
of strings, `args`, which should contain the program name as the
zeroth element and any command-line arguments in subsequent elements.
The third and fourth versions are included for convenience, and may be
used when there are no command-line arguments.  They take a single string,
`program`, which specifies the program name.

Unless a directory is specified in `args[0]` or `program`,
`spawnProcess` will search for the program in a platform-dependent
manner.  On POSIX systems, it will look for the executable in the
directories listed in the PATH environment variable, in the order
they are listed.  On Windows, it will search for the executable in
the following sequence:
$(OL
    $(LI The directory from which the application loaded.)
    $(LI The current directory for the parent process.)
    $(LI The 32-bit Windows system directory.)
    $(LI The 16-bit Windows system directory.)
    $(LI The Windows directory.)
    $(LI The directories listed in the PATH environment variable.)
)
---
// Run an executable called "prog" located in the current working
// directory:
auto pid = spawnProcess("./prog");
scope(exit) wait(pid);
// We can do something else while the program runs.  The scope guard
// ensures that the process is waited for at the end of the scope.
...

// Run DMD on the file "myprog.d", specifying a few compiler switches:
auto dmdPid = spawnProcess(["dmd", "-O", "-release", "-inline", "myprog.d" ]);
if (wait(dmdPid) != 0)
    writeln("Compilation failed!");
---

Environment_variables:
By default, the child process inherits the environment of the parent
process, along with any additional variables specified in the `env`
parameter.  If the same variable exists in both the parent's environment
and in `env`, the latter takes precedence.

If the $(LREF Config.newEnv) flag is set in `config`, the child
process will $(I not) inherit the parent's environment.  Its entire
environment will then be determined by `env`.
---
wait(spawnProcess("myapp", ["foo" : "bar"], Config.newEnv));
---

Standard_streams:
The optional arguments `stdin`, `stdout` and `stderr` may
be used to assign arbitrary $(REF File, std,stdio) objects as the standard
input, output and error streams, respectively, of the child process.  The
former must be opened for reading, while the latter two must be opened for
writing.  The default is for the child process to inherit the standard
streams of its parent.
---
// Run DMD on the file myprog.d, logging any error messages to a
// file named errors.log.
auto logFile = File("errors.log", "w");
auto pid = spawnProcess(["dmd", "myprog.d"],
                        std.stdio.stdin,
                        std.stdio.stdout,
                        logFile);
if (wait(pid) != 0)
    writeln("Compilation failed. See errors.log for details.");
---

Note that if you pass a `File` object that is $(I not)
one of the standard input/output/error streams of the parent process,
that stream will by default be $(I closed) in the parent process when
this function returns.  See the $(LREF Config) documentation below for
information about how to disable this behaviour.

Beware of buffering issues when passing `File` objects to
`spawnProcess`.  The child process will inherit the low-level raw
read/write offset associated with the underlying file descriptor, but
it will not be aware of any buffered data.  In cases where this matters
(e.g. when a file should be aligned before being passed on to the
child process), it may be a good idea to use unbuffered streams, or at
least ensure all relevant buffers are flushed.

Params:
args    = An array which contains the program name as the zeroth element
          and any command-line arguments in the following elements.
stdin   = The standard input stream of the child process.
          This can be any $(REF File, std,stdio) that is opened for reading.
          By default the child process inherits the parent's input
          stream.
stdout  = The standard output stream of the child process.
          This can be any $(REF File, std,stdio) that is opened for writing.
          By default the child process inherits the parent's output stream.
stderr  = The standard error stream of the child process.
          This can be any $(REF File, std,stdio) that is opened for writing.
          By default the child process inherits the parent's error stream.
env     = Additional environment variables for the child process.
config  = Flags that control process creation. See $(LREF Config)
          for an overview of available flags.
workDir = The working directory for the new process.
          By default the child process inherits the parent's working
          directory.

Returns:
A $(LREF Pid) object that corresponds to the spawned process.

Throws:
$(LREF ProcessException) on failure to start the process.$(BR)
$(REF StdioException, std,stdio) on failure to pass one of the streams
    to the child process (Windows only).$(BR)
$(REF RangeError, core,exception) if `args` is empty.
*/
Pid spawnProcess(scope const(char[])[] args,
                 File stdin = std.stdio.stdin,
                 File stdout = std.stdio.stdout,
                 File stderr = std.stdio.stderr,
                 const string[string] env = null,
                 Config config = Config.none,
                 scope const char[] workDir = null)
    @safe
{
    version (Windows)
    {
        const commandLine = escapeShellArguments(args);
        const program = args.length ? args[0] : null;
        return spawnProcessWin(commandLine, program, stdin, stdout, stderr, env, config, workDir);
    }
    else version (Posix)
    {
        return spawnProcessPosix(args, stdin, stdout, stderr, env, config, workDir);
    }
    else
        static assert(0);
}

/// ditto
Pid spawnProcess(scope const(char[])[] args,
                 const string[string] env,
                 Config config = Config.none,
                 scope const(char)[] workDir = null)
    @trusted // TODO: Should be @safe
{
    return spawnProcess(args,
                        std.stdio.stdin,
                        std.stdio.stdout,
                        std.stdio.stderr,
                        env,
                        config,
                        workDir);
}

/// ditto
Pid spawnProcess(scope const(char)[] program,
                 File stdin = std.stdio.stdin,
                 File stdout = std.stdio.stdout,
                 File stderr = std.stdio.stderr,
                 const string[string] env = null,
                 Config config = Config.none,
                 scope const(char)[] workDir = null)
    @trusted
{
    return spawnProcess((&program)[0 .. 1],
                        stdin, stdout, stderr, env, config, workDir);
}

/// ditto
Pid spawnProcess(scope const(char)[] program,
                 const string[string] env,
                 Config config = Config.none,
                 scope const(char)[] workDir = null)
    @trusted
{
    return spawnProcess((&program)[0 .. 1], env, config, workDir);
}

version (Posix) private enum InternalError : ubyte
{
    noerror,
    exec,
    chdir,
    getrlimit,
    doubleFork,
    malloc,
    preExec,
    closefds_dup2,
}

/*
Implementation of spawnProcess() for POSIX.

envz should be a zero-terminated array of zero-terminated strings
on the form "var=value".
*/
version (Posix)
private Pid spawnProcessPosix(scope const(char[])[] args,
                              File stdin,
                              File stdout,
                              File stderr,
                              scope const string[string] env,
                              Config config,
                              scope const(char)[] workDir)
    @trusted // TODO: Should be @safe
{
    import core.exception : RangeError;
    import std.algorithm.searching : any;
    import std.conv : text;
    import std.path : isDirSeparator;
    import std.string : toStringz;

    if (args.empty) throw new RangeError();
    const(char)[] name = args[0];
    if (!any!isDirSeparator(name))
    {
        name = searchPathFor(name);
        if (name is null)
            throw new ProcessException(text("Executable file not found: ", args[0]));
    }

    // Convert program name and arguments to C-style strings.
    auto argz = new const(char)*[args.length+1];
    argz[0] = toStringz(name);
    foreach (i; 1 .. args.length) argz[i] = toStringz(args[i]);
    argz[$-1] = null;

    // Prepare environment.
    auto envz = createEnv(env, !(config.flags & Config.Flags.newEnv));

    // Open the working directory.
    // We use open in the parent and fchdir in the child
    // so that most errors (directory doesn't exist, not a directory)
    // can be propagated as exceptions before forking.
    int workDirFD = -1;
    scope(exit) if (workDirFD >= 0) close(workDirFD);
    if (workDir.length)
    {
        import core.sys.posix.fcntl : open, O_RDONLY, stat_t, fstat, S_ISDIR;
        workDirFD = open(workDir.tempCString(), O_RDONLY);
        if (workDirFD < 0)
            throw ProcessException.newFromErrno("Failed to open working directory");
        stat_t s;
        if (fstat(workDirFD, &s) < 0)
            throw ProcessException.newFromErrno("Failed to stat working directory");
        if (!S_ISDIR(s.st_mode))
            throw new ProcessException("Not a directory: " ~ cast(string) workDir);
    }

    static int getFD(ref File f) { return core.stdc.stdio.fileno(f.getFP()); }

    // Get the file descriptors of the streams.
    // These could potentially be invalid, but that is OK.  If so, later calls
    // to dup2() and close() will just silently fail without causing any harm.
    auto stdinFD  = getFD(stdin);
    auto stdoutFD = getFD(stdout);
    auto stderrFD = getFD(stderr);

    // We don't have direct access to the errors that may happen in a child process.
    // So we use this pipe to deliver them.
    int[2] forkPipe;
    if (core.sys.posix.unistd.pipe(forkPipe) == 0)
        setCLOEXEC(forkPipe[1], true);
    else
        throw ProcessException.newFromErrno("Could not create pipe to check startup of child");
    scope(exit) close(forkPipe[0]);

    /*
    To create detached process, we use double fork technique
    but we don't have a direct access to the second fork pid from the caller side thus use a pipe.
    We also can't reuse forkPipe for that purpose
    because we can't predict the order in which pid and possible error will be written
    since the first and the second forks will run in parallel.
    */
    int[2] pidPipe;
    if (config.flags & Config.Flags.detached)
    {
        if (core.sys.posix.unistd.pipe(pidPipe) != 0)
            throw ProcessException.newFromErrno("Could not create pipe to get process pid");
        setCLOEXEC(pidPipe[1], true);
    }
    scope(exit) if (config.flags & Config.Flags.detached) close(pidPipe[0]);

    static void abortOnError(int forkPipeOut, InternalError errorType, int error) nothrow
    {
        core.sys.posix.unistd.write(forkPipeOut, &errorType, errorType.sizeof);
        core.sys.posix.unistd.write(forkPipeOut, &error, error.sizeof);
        close(forkPipeOut);
        core.sys.posix.unistd._exit(1);
        assert(0);
    }

    void closePipeWriteEnds()
    {
        close(forkPipe[1]);
        if (config.flags & Config.Flags.detached)
            close(pidPipe[1]);
    }

    auto id = core.sys.posix.unistd.fork();
    if (id < 0)
    {
        closePipeWriteEnds();
        throw ProcessException.newFromErrno("Failed to spawn new process");
    }

    void forkChild() nothrow @nogc
    {
        static import core.sys.posix.stdio;

        // Child process

        // no need for the read end of pipe on child side
        if (config.flags & Config.Flags.detached)
            close(pidPipe[0]);
        close(forkPipe[0]);
        auto forkPipeOut = forkPipe[1];
        immutable pidPipeOut = pidPipe[1];

        // Set the working directory.
        if (workDirFD >= 0)
        {
            if (fchdir(workDirFD) < 0)
            {
                // Fail. It is dangerous to run a program
                // in an unexpected working directory.
                abortOnError(forkPipeOut, InternalError.chdir, .errno);
            }
            close(workDirFD);
        }

        void execProcess()
        {
            // Redirect streams and close the old file descriptors.
            // In the case that stderr is redirected to stdout, we need
            // to backup the file descriptor since stdout may be redirected
            // as well.
            if (stderrFD == STDOUT_FILENO) stderrFD = dup(stderrFD);
            dup2(stdinFD,  STDIN_FILENO);
            dup2(stdoutFD, STDOUT_FILENO);
            dup2(stderrFD, STDERR_FILENO);

            // Ensure that the standard streams aren't closed on execute, and
            // optionally close all other file descriptors.
            setCLOEXEC(STDIN_FILENO, false);
            setCLOEXEC(STDOUT_FILENO, false);
            setCLOEXEC(STDERR_FILENO, false);

            if (!(config.flags & Config.Flags.inheritFDs))
            {
                version (FreeBSD)
                    import core.sys.freebsd.unistd : closefrom;
                else version (OpenBSD)
                    import core.sys.openbsd.unistd : closefrom;

                static if (!__traits(compiles, closefrom))
                {
                    void fallback (int lowfd)
                    {
                        import core.sys.posix.dirent : dirent, opendir, readdir, closedir, DIR;
                        import core.sys.posix.unistd : close;
                        import core.sys.posix.stdlib : atoi, malloc, free;
                        import core.sys.posix.sys.resource : rlimit, getrlimit, RLIMIT_NOFILE;

                        // Get the maximum number of file descriptors that could be open.
                        rlimit r;
                        if (getrlimit(RLIMIT_NOFILE, &r) != 0)
                            abortOnError(forkPipeOut, InternalError.getrlimit, .errno);

                        immutable maxDescriptors = cast(int) r.rlim_cur;

                        // Missing druntime declaration
                        pragma(mangle, "dirfd")
                        extern(C) nothrow @nogc int dirfd(DIR* dir);

                        DIR* dir = null;

                        // We read from /dev/fd or /proc/self/fd only if the limit is high enough
                        if (maxDescriptors > 128*1024)
                        {
                            // Try to open the directory /dev/fd or /proc/self/fd
                            dir = opendir("/dev/fd");
                            if (dir is null) dir = opendir("/proc/self/fd");
                        }

                        // If we have a directory, close all file descriptors except stdin, stdout, and stderr
                        if (dir)
                        {
                            scope(exit) closedir(dir);

                            int opendirfd = dirfd(dir);

                            // Iterate over all file descriptors
                            while (true)
                            {
                                dirent* entry = readdir(dir);

                                if (entry is null) break;
                                if (entry.d_name[0] == '.') continue;

                                int fd = atoi(cast(char*) entry.d_name);

                                // Don't close stdin, stdout, stderr, or the directory file descriptor
                                if (fd < lowfd || fd == opendirfd) continue;

                                close(fd);
                            }
                        }
                        else
                        {
                            // This is going to allocate 8 bytes for each possible file descriptor from lowfd to r.rlim_cur
                            if (maxDescriptors <= 128*1024)
                            {
                                // NOTE: malloc() and getrlimit() are not on the POSIX async
                                // signal safe functions list, but practically this should
                                // not be a problem. Java VM and CPython also use malloc()
                                // in its own implementation via opendir().
                                import core.stdc.stdlib : malloc;
                                import core.sys.posix.poll : pollfd, poll, POLLNVAL;

                                immutable maxToClose = maxDescriptors - lowfd;

                                // Call poll() to see which ones are actually open:
                                auto pfds = cast(pollfd*) malloc(pollfd.sizeof * maxToClose);
                                if (pfds is null)
                                {
                                    abortOnError(forkPipeOut, InternalError.malloc, .errno);
                                }

                                foreach (i; 0 .. maxToClose)
                                {
                                    pfds[i].fd = i + lowfd;
                                    pfds[i].events = 0;
                                    pfds[i].revents = 0;
                                }

                                if (poll(pfds, maxToClose, 0) < 0)
                                    // couldn't use poll, use the slow path.
                                    goto LslowClose;

                                foreach (i; 0 .. maxToClose)
                                {
                                    // POLLNVAL will be set if the file descriptor is invalid.
                                    if (!(pfds[i].revents & POLLNVAL)) close(pfds[i].fd);
                                }
                            }
                            else
                            {
                            LslowClose:
                                // Fall back to closing everything.
                                foreach (i; lowfd .. maxDescriptors)
                                {
                                    close(i);
                                }
                            }
                        }
                    }

                    // closefrom may not be available on the version of glibc we build against.
                    // Until we find a way to perform this check we will try to use dlsym to
                    // check for the function. See: https://github.com/dlang/phobos/pull/9048
                    version (CRuntime_Glibc)
                    {
                        void closefrom (int lowfd) {
                            static bool tryGlibcClosefrom (int lowfd) {
                                import core.sys.posix.dlfcn : dlopen, dlclose, dlsym, dlerror, RTLD_LAZY;

                                void *handle = dlopen("libc.so.6", RTLD_LAZY);
                                if (!handle)
                                    return false;
                                scope(exit) dlclose(handle);

                                // Clear errors
                                dlerror();
                                alias closefromT = extern(C) void function(int) @nogc @system nothrow;
                                auto closefrom = cast(closefromT) dlsym(handle, "closefrom");
                                if (dlerror())
                                    return false;

                                closefrom(lowfd);
                                return true;
                            }

                            if (!tryGlibcClosefrom(lowfd))
                                fallback(lowfd);
                        }
                    }
                    else
                        alias closefrom = fallback;
                }

                // We need to close all open file descriptors excluding std{in,out,err}
                // and forkPipeOut because we still need it.
                // Since the various libc's provide us with `closefrom` move forkPipeOut
                // to position 3, right after STDERR_FILENO, and close all FDs following that.
                if (dup2(forkPipeOut, 3) == -1)
                    abortOnError(forkPipeOut, InternalError.closefds_dup2, .errno);
                forkPipeOut = 3;
                // forkPipeOut needs to be closed after we call `exec`.
                setCLOEXEC(forkPipeOut, true);
                closefrom(forkPipeOut + 1);
            }
            else // This is already done if we don't inherit descriptors.
            {
                // Close the old file descriptors, unless they are
                // either of the standard streams.
                if (stdinFD  > STDERR_FILENO)  close(stdinFD);
                if (stdoutFD > STDERR_FILENO)  close(stdoutFD);
                if (stderrFD > STDERR_FILENO)  close(stderrFD);
            }

            if (config.preExecFunction !is null)
            {
                if (config.preExecFunction() != true)
                {
                    abortOnError(forkPipeOut, InternalError.preExec, .errno);
                }
            }

            if (config.preExecDelegate !is null)
            {
                if (config.preExecDelegate() != true)
                {
                    abortOnError(forkPipeOut, InternalError.preExec, .errno);
                }
            }

            // Execute program.
            core.sys.posix.unistd.execve(argz[0], argz.ptr, envz is null ? getEnvironPtr : envz);

            // If execution fails, exit as quickly as possible.
            abortOnError(forkPipeOut, InternalError.exec, .errno);
        }

        if (config.flags & Config.Flags.detached)
        {
            auto secondFork = core.sys.posix.unistd.fork();
            if (secondFork == 0)
            {
                close(pidPipeOut);
                execProcess();
            }
            else if (secondFork == -1)
            {
                auto secondForkErrno = .errno;
                close(pidPipeOut);
                abortOnError(forkPipeOut, InternalError.doubleFork, secondForkErrno);
            }
            else
            {
                core.sys.posix.unistd.write(pidPipeOut, &secondFork, pid_t.sizeof);
                close(pidPipeOut);
                close(forkPipeOut);
                _exit(0);
            }
        }
        else
        {
            execProcess();
        }
    }

    if (id == 0)
    {
        forkChild();
        assert(0);
    }
    else
    {
        closePipeWriteEnds();

        T retryInterrupted(T)(scope T delegate() syscall)
        {
            import core.stdc.errno : errno, EINTR;
            T result;
            do
                result = syscall();
            while (result == -1 && .errno == EINTR);
            return result;
        }

        auto status = InternalError.noerror;
        auto readExecResult = retryInterrupted(() => core.sys.posix.unistd.read(forkPipe[0], &status, status.sizeof));
        // Save error number just in case if subsequent "waitpid" fails and overrides errno
        immutable lastError = .errno;

        if (config.flags & Config.Flags.detached)
        {
            // Forked child exits right after creating second fork. So it should be safe to wait here.
            import core.sys.posix.sys.wait : waitpid;
            int waitResult;
            retryInterrupted(() => waitpid(id, &waitResult, 0));
        }

        if (readExecResult == -1)
            throw ProcessException.newFromErrno(lastError, "Could not read from pipe to get child status");

        bool owned = true;
        if (status != InternalError.noerror)
        {
            int error;
            readExecResult = retryInterrupted(() => read(forkPipe[0], &error, error.sizeof));
            string errorMsg;
            final switch (status)
            {
                case InternalError.chdir:
                    errorMsg = "Failed to set working directory";
                    break;
                case InternalError.getrlimit:
                    errorMsg = "getrlimit failed";
                    break;
                case InternalError.exec:
                    errorMsg = "Failed to execute '" ~ cast(string) name ~ "'";
                    break;
                case InternalError.doubleFork:
                    // Can happen only when starting detached process
                    assert(config.flags & Config.Flags.detached);
                    errorMsg = "Failed to fork twice";
                    break;
                case InternalError.malloc:
                    errorMsg = "Failed to allocate memory";
                    break;
                case InternalError.preExec:
                    errorMsg = "Failed to execute preExecFunction or preExecDelegate";
                    break;
                case InternalError.closefds_dup2:
                    assert(!(config.flags & Config.Flags.inheritFDs));
                    errorMsg = "Failed to close inherited file descriptors";
                    break;
                case InternalError.noerror:
                    assert(false);
            }
            if (readExecResult == error.sizeof)
                throw ProcessException.newFromErrno(error, errorMsg);
            throw new ProcessException(errorMsg);
        }
        else if (config.flags & Config.Flags.detached)
        {
            owned = false;
            if (read(pidPipe[0], &id, id.sizeof) != id.sizeof)
                throw ProcessException.newFromErrno("Could not read from pipe to get detached process id");
        }

        // Parent process:  Close streams and return.
        if (!(config.flags & Config.Flags.retainStdin ) && stdinFD  > STDERR_FILENO
                                            && stdinFD  != getFD(std.stdio.stdin ))
            stdin.close();
        if (!(config.flags & Config.Flags.retainStdout) && stdoutFD > STDERR_FILENO
                                            && stdoutFD != getFD(std.stdio.stdout))
            stdout.close();
        if (!(config.flags & Config.Flags.retainStderr) && stderrFD > STDERR_FILENO
                                            && stderrFD != getFD(std.stdio.stderr))
            stderr.close();
        return new Pid(id, owned);
    }
}

version (Posix)
@system unittest
{
    import std.concurrency : ownerTid, receiveTimeout, send, spawn;
    import std.datetime : seconds;

    sigset_t ss;
    sigemptyset(&ss);
    sigaddset(&ss, SIGINT);
    pthread_sigmask(SIG_BLOCK, &ss, null);

    Config config = {
        preExecFunction: () @trusted @nogc nothrow {
            // Reset signal handlers
            sigset_t ss;
            if (sigfillset(&ss) != 0)
            {
                return false;
            }
            if (sigprocmask(SIG_UNBLOCK, &ss, null) != 0)
            {
                return false;
            }
            return true;
        },
    };

    auto pid = spawnProcess(["sleep", "10000"],
                            std.stdio.stdin,
                            std.stdio.stdout,
                            std.stdio.stderr,
                            null,
                            config,
                            null);
    scope(failure)
    {
        kill(pid, SIGKILL);
        wait(pid);
    }

    // kill the spawned process with SIGINT
    // and send its return code
    spawn((shared Pid pid) {
        auto p = cast() pid;
        kill(p, SIGINT);
        auto code = wait(p);
        assert(code < 0);
        send(ownerTid, code);
    }, cast(shared) pid);

    auto received = receiveTimeout(3.seconds, (int) {});
    assert(received);
}

version (Posix)
@system unittest
{
    __gshared int j;
    foreach (i; 0 .. 3)
    {
        auto config = Config(
            preExecFunction: function() @trusted {
                j = 1;
                return true;
            },
            preExecDelegate: delegate() @trusted {
                // j should now be 1, as preExecFunction is called before
                // preExecDelegate is.
                _Exit(i + j);
                return true;
            },
        );
        auto pid = spawnProcess(["false"], config: config);
        assert(wait(pid) == i + 1);
    }
}

/*
Implementation of spawnProcess() for Windows.

commandLine must contain the entire command line, properly
quoted/escaped as required by CreateProcessW().

envz must be a pointer to a block of UTF-16 characters on the form
"var1=value1\0var2=value2\0...varN=valueN\0\0".
*/
version (Windows)
private Pid spawnProcessWin(scope const(char)[] commandLine,
                            scope const(char)[] program,
                            File stdin,
                            File stdout,
                            File stderr,
                            scope const string[string] env,
                            Config config,
                            scope const(char)[] workDir)
    @trusted
{
    import core.exception : RangeError;
    import std.conv : text;

    if (commandLine.empty) throw new RangeError("Command line is empty");

    // Prepare environment.
    auto envz = createEnv(env, !(config.flags & Config.Flags.newEnv));

    // Startup info for CreateProcessW().
    STARTUPINFO_W startinfo;
    startinfo.cb = startinfo.sizeof;
    static int getFD(ref File f) { return f.isOpen ? f.fileno : -1; }

    // Extract file descriptors and HANDLEs from the streams and make the
    // handles inheritable.
    static void prepareStream(ref File file, DWORD stdHandle, string which,
                              out int fileDescriptor, out HANDLE handle)
    {
        enum _NO_CONSOLE_FILENO = cast(HANDLE)-2;
        fileDescriptor = getFD(file);
        handle = null;
        if (fileDescriptor >= 0)
            handle = file.windowsHandle;
        // Windows GUI applications have a fd but not a valid Windows HANDLE.
        if (handle is null || handle == INVALID_HANDLE_VALUE || handle == _NO_CONSOLE_FILENO)
            handle = GetStdHandle(stdHandle);

        DWORD dwFlags;
        if (GetHandleInformation(handle, &dwFlags))
        {
            if (!(dwFlags & HANDLE_FLAG_INHERIT))
            {
                if (!SetHandleInformation(handle,
                                          HANDLE_FLAG_INHERIT,
                                          HANDLE_FLAG_INHERIT))
                {
                    throw new StdioException(
                        "Failed to make "~which~" stream inheritable by child process ("
                        ~generateSysErrorMsg() ~ ')',
                        0);
                }
            }
        }
    }
    int stdinFD = -1, stdoutFD = -1, stderrFD = -1;
    prepareStream(stdin,  STD_INPUT_HANDLE,  "stdin" , stdinFD,  startinfo.hStdInput );
    prepareStream(stdout, STD_OUTPUT_HANDLE, "stdout", stdoutFD, startinfo.hStdOutput);
    prepareStream(stderr, STD_ERROR_HANDLE,  "stderr", stderrFD, startinfo.hStdError );

    if ((startinfo.hStdInput  != null && startinfo.hStdInput  != INVALID_HANDLE_VALUE)
     || (startinfo.hStdOutput != null && startinfo.hStdOutput != INVALID_HANDLE_VALUE)
     || (startinfo.hStdError  != null && startinfo.hStdError  != INVALID_HANDLE_VALUE))
        startinfo.dwFlags = STARTF_USESTDHANDLES;

    // Create process.
    PROCESS_INFORMATION pi;
    DWORD dwCreationFlags =
        CREATE_UNICODE_ENVIRONMENT |
        ((config.flags & Config.Flags.suppressConsole) ? CREATE_NO_WINDOW : 0);
    // workaround until https://issues.dlang.org/show_bug.cgi?id=14696 is fixed
    auto pworkDir = workDir.tempCStringW();
    if (!CreateProcessW(null, commandLine.tempCStringW().buffPtr,
                        null, null, true, dwCreationFlags,
                        envz, workDir.length ? pworkDir : null, &startinfo, &pi))
        throw ProcessException.newFromLastError("Failed to spawn process \"" ~ cast(string) program ~ '"');

    // figure out if we should close any of the streams
    if (!(config.flags & Config.Flags.retainStdin ) && stdinFD  > STDERR_FILENO
                                        && stdinFD  != getFD(std.stdio.stdin ))
        stdin.close();
    if (!(config.flags & Config.Flags.retainStdout) && stdoutFD > STDERR_FILENO
                                        && stdoutFD != getFD(std.stdio.stdout))
        stdout.close();
    if (!(config.flags & Config.Flags.retainStderr) && stderrFD > STDERR_FILENO
                                        && stderrFD != getFD(std.stdio.stderr))
        stderr.close();

    // close the thread handle in the process info structure
    CloseHandle(pi.hThread);
    if (config.flags & Config.Flags.detached)
    {
        CloseHandle(pi.hProcess);
        return new Pid(pi.dwProcessId);
    }
    return new Pid(pi.dwProcessId, pi.hProcess);
}

// Converts childEnv to a zero-terminated array of zero-terminated strings
// on the form "name=value", optionally adding those of the current process'
// environment strings that are not present in childEnv.  If the parent's
// environment should be inherited without modification, this function
// returns null.
version (Posix)
private const(char*)* createEnv(const string[string] childEnv,
                                bool mergeWithParentEnv)
{
    // Determine the number of strings in the parent's environment.
    int parentEnvLength = 0;
    auto environ = getEnvironPtr;
    if (mergeWithParentEnv)
    {
        if (childEnv.length == 0) return null;
        while (environ[parentEnvLength] != null) ++parentEnvLength;
    }

    // Convert the "new" variables to C-style strings.
    auto envz = new const(char)*[parentEnvLength + childEnv.length + 1];
    int pos = 0;
    foreach (var, val; childEnv)
        envz[pos++] = (var~'='~val~'\0').ptr;

    // Add the parent's environment.
    foreach (environStr; environ[0 .. parentEnvLength])
    {
        int eqPos = 0;
        while (environStr[eqPos] != '=' && environStr[eqPos] != '\0') ++eqPos;
        if (environStr[eqPos] != '=') continue;
        auto var = environStr[0 .. eqPos];
        if (var in childEnv) continue;
        envz[pos++] = environStr;
    }
    envz[pos] = null;
    return envz.ptr;
}

version (Posix) @system unittest
{
    auto e1 = createEnv(null, false);
    assert(e1 != null && *e1 == null);

    auto e2 = createEnv(null, true);
    assert(e2 == null);

    auto e3 = createEnv(["foo" : "bar", "hello" : "world"], false);
    assert(e3 != null && e3[0] != null && e3[1] != null && e3[2] == null);
    assert((e3[0][0 .. 8] == "foo=bar\0" && e3[1][0 .. 12] == "hello=world\0")
         || (e3[0][0 .. 12] == "hello=world\0" && e3[1][0 .. 8] == "foo=bar\0"));
}


// Converts childEnv to a Windows environment block, which is on the form
// "name1=value1\0name2=value2\0...nameN=valueN\0\0", optionally adding
// those of the current process' environment strings that are not present
// in childEnv.  Returns null if the parent's environment should be
// inherited without modification, as this is what is expected by
// CreateProcess().
version (Windows)
private LPVOID createEnv(const string[string] childEnv,
                         bool mergeWithParentEnv)
{
    if (mergeWithParentEnv && childEnv.length == 0) return null;
    import std.array : appender;
    import std.uni : toUpper;
    auto envz = appender!(wchar[])();
    void put(string var, string val)
    {
        envz.put(var);
        envz.put('=');
        envz.put(val);
        envz.put(cast(wchar) '\0');
    }

    // Add the variables in childEnv, removing them from parentEnv
    // if they exist there too.
    auto parentEnv = mergeWithParentEnv ? environment.toAA() : null;
    foreach (k, v; childEnv)
    {
        auto uk = toUpper(k);
        put(uk, v);
        if (uk in parentEnv) parentEnv.remove(uk);
    }

    // Add remaining parent environment variables.
    foreach (k, v; parentEnv) put(k, v);

    // Two final zeros are needed in case there aren't any environment vars,
    // and the last one does no harm when there are.
    envz.put("\0\0"w);
    return envz.data.ptr;
}

version (Windows) @system unittest
{
    assert(createEnv(null, true) == null);
    assert((cast(wchar*) createEnv(null, false))[0 .. 2] == "\0\0"w);
    auto e1 = (cast(wchar*) createEnv(["foo":"bar", "ab":"c"], false))[0 .. 14];
    assert(e1 == "FOO=bar\0AB=c\0\0"w || e1 == "AB=c\0FOO=bar\0\0"w);
}

// Searches the PATH variable for the given executable file,
// (checking that it is in fact executable).
version (Posix)
package(std) string searchPathFor(scope const(char)[] executable)
    @safe
{
    import std.algorithm.iteration : splitter;
    import std.conv : to;
    import std.path : chainPath;

    typeof(return) result;

    environment.getImpl("PATH",
        (scope const(char)[] path)
        {
            if (!path)
                return;

            foreach (dir; splitter(path, ":"))
            {
                auto execPath = chainPath(dir, executable);
                if (isExecutable(execPath))
                {
                    result = execPath.to!(typeof(result));
                    return;
                }
            }
        });

    return result;
}

// Checks whether the file exists and can be executed by the
// current user.
version (Posix)
private bool isExecutable(R)(R path) @trusted nothrow @nogc
if (isSomeFiniteCharInputRange!R)
{
    return (access(path.tempCString(), X_OK) == 0);
}

version (Posix) @safe unittest
{
    import std.algorithm;
    auto lsPath = searchPathFor("ls");
    assert(!lsPath.empty);
    assert(lsPath[0] == '/');
    assert(lsPath.endsWith("ls"));
    auto unlikely = searchPathFor("lkmqwpoialhggyaofijadsohufoiqezm");
    assert(unlikely is null, "Are you kidding me?");
}

// Sets or unsets the FD_CLOEXEC flag on the given file descriptor.
version (Posix)
private void setCLOEXEC(int fd, bool on) nothrow @nogc
{
    import core.sys.posix.fcntl : fcntl, F_GETFD, FD_CLOEXEC, F_SETFD;
    auto flags = fcntl(fd, F_GETFD);
    if (flags >= 0)
    {
        if (on) flags |= FD_CLOEXEC;
        else    flags &= ~(cast(typeof(flags)) FD_CLOEXEC);
        flags = fcntl(fd, F_SETFD, flags);
    }
    assert(flags != -1 || .errno == EBADF);
}

@system unittest // Command line arguments in spawnProcess().
{
    version (Windows) TestScript prog =
       "if not [%~1]==[foo] ( exit 1 )
        if not [%~2]==[bar] ( exit 2 )
        exit 0";
    else version (Posix) TestScript prog =
       `if test "$1" != "foo"; then exit 1; fi
        if test "$2" != "bar"; then exit 2; fi
        exit 0`;
    assert(wait(spawnProcess(prog.path)) == 1);
    assert(wait(spawnProcess([prog.path])) == 1);
    assert(wait(spawnProcess([prog.path, "foo"])) == 2);
    assert(wait(spawnProcess([prog.path, "foo", "baz"])) == 2);
    assert(wait(spawnProcess([prog.path, "foo", "bar"])) == 0);
}

// test that file descriptors are correctly closed / left open.
// ideally this would be done by the child process making libc
// calls, but we make do...
version (Posix) @system unittest
{
    import core.stdc.errno : errno;
    import core.sys.posix.fcntl : open, O_RDONLY;
    import core.sys.posix.unistd : close;
    import std.algorithm.searching : canFind, findSplitBefore;
    import std.array : split;
    import std.conv : to;
    static import std.file;
    import std.functional : reverseArgs;
    import std.path : buildPath;

    auto directory = uniqueTempPath();
    std.file.mkdir(directory);
    scope(exit) std.file.rmdirRecurse(directory);
    auto path = buildPath(directory, "tmp");
    std.file.write(path, null);
    errno = 0;
    auto fd = open(path.tempCString, O_RDONLY);
    if (fd == -1)
    {
        import core.stdc.string : strerror;
        import std.stdio : stderr;
        import std.string : fromStringz;

        // For the CI logs
        stderr.writefln("%s: could not open '%s': %s",
            __FUNCTION__, path, strerror(errno).fromStringz);
        // TODO: should we retry here instead?
        return;
    }
    scope(exit) close(fd);

    // command >&2 (or any other number) checks whethether that number
    // file descriptor is open.
    // Can't use this for arbitrary descriptors as many shells only support
    // single digit fds.
    TestScript testDefaults = `command >&0 && command >&1 && command >&2`;
    assert(execute(testDefaults.path).status == 0);
    assert(execute(testDefaults.path, null, Config.inheritFDs).status == 0);

    // Try a few different methods to check whether there are any
    // incorrectly-open files.
    void testFDs()
    {
        // try /proc/<pid>/fd/ on linux
        version (linux)
        {
            TestScript proc = "ls /proc/$$/fd";
            auto procRes = execute(proc.path, null);
            if (procRes.status == 0)
            {
                auto fdStr = fd.to!string;
                assert(!procRes.output.split.canFind(fdStr));
                assert(execute(proc.path, null, Config.inheritFDs)
                        .output.split.canFind(fdStr));
                return;
            }
        }

        // try fuser (might sometimes need permissions)
        TestScript fuser = "echo $$ && fuser -f " ~ path;
        auto fuserRes = execute(fuser.path, null);
        if (fuserRes.status == 0)
        {
            assert(!reverseArgs!canFind(fuserRes
                        .output.findSplitBefore("\n").expand));
            assert(reverseArgs!canFind(execute(fuser.path, null, Config.inheritFDs)
                        .output.findSplitBefore("\n").expand));
            return;
        }

        // last resort, try lsof (not available on all Posix)
        TestScript lsof = "lsof -p$$";
        auto lsofRes = execute(lsof.path, null);
        if (lsofRes.status == 0)
        {
            assert(!lsofRes.output.canFind(path));
            auto lsofOut = execute(lsof.path, null, Config.inheritFDs).output;
            if (!lsofOut.canFind(path))
            {
                std.stdio.stderr.writeln(__FILE__, ':', __LINE__,
                    ": Warning: unexpected lsof output:", lsofOut);
            }
            return;
        }

        std.stdio.stderr.writeln(__FILE__, ':', __LINE__,
                ": Warning: Couldn't find any way to check open files");
    }
    testFDs();
}

@system unittest // Environment variables in spawnProcess().
{
    // We really should use set /a on Windows, but Wine doesn't support it.
    version (Windows) TestScript envProg =
       `if [%STD_PROCESS_UNITTEST1%] == [1] (
            if [%STD_PROCESS_UNITTEST2%] == [2] (exit 3)
            exit 1
        )
        if [%STD_PROCESS_UNITTEST1%] == [4] (
            if [%STD_PROCESS_UNITTEST2%] == [2] (exit 6)
            exit 4
        )
        if [%STD_PROCESS_UNITTEST2%] == [2] (exit 2)
        exit 0`;
    version (Posix) TestScript envProg =
       `if test "$std_process_unittest1" = ""; then
            std_process_unittest1=0
        fi
        if test "$std_process_unittest2" = ""; then
            std_process_unittest2=0
        fi
        exit $(($std_process_unittest1+$std_process_unittest2))`;

    environment.remove("std_process_unittest1"); // Just in case.
    environment.remove("std_process_unittest2");
    assert(wait(spawnProcess(envProg.path)) == 0);
    assert(wait(spawnProcess(envProg.path, null, Config.newEnv)) == 0);

    environment["std_process_unittest1"] = "1";
    assert(wait(spawnProcess(envProg.path)) == 1);
    assert(wait(spawnProcess(envProg.path, null, Config.newEnv)) == 0);

    auto env = ["std_process_unittest2" : "2"];
    assert(wait(spawnProcess(envProg.path, env)) == 3);
    assert(wait(spawnProcess(envProg.path, env, Config.newEnv)) == 2);

    env["std_process_unittest1"] = "4";
    assert(wait(spawnProcess(envProg.path, env)) == 6);
    assert(wait(spawnProcess(envProg.path, env, Config.newEnv)) == 6);

    environment.remove("std_process_unittest1");
    assert(wait(spawnProcess(envProg.path, env)) == 6);
    assert(wait(spawnProcess(envProg.path, env, Config.newEnv)) == 6);
}

@system unittest // Stream redirection in spawnProcess().
{
    import std.path : buildPath;
    import std.string;
    version (Windows) TestScript prog =
       "set /p INPUT=
        echo %INPUT% output %~1
        echo %INPUT% error %~2 1>&2
        echo done > %3";
    else version (Posix) TestScript prog =
       "read INPUT
        echo $INPUT output $1
        echo $INPUT error $2 >&2
        echo done > \"$3\"";

    // Pipes
    void testPipes(Config config)
    {
        import std.file : tempDir, exists, remove;
        import std.uuid : randomUUID;
        import std.exception : collectException;
        auto pipei = pipe();
        auto pipeo = pipe();
        auto pipee = pipe();
        auto done = buildPath(tempDir(), randomUUID().toString());
        auto pid = spawnProcess([prog.path, "foo", "bar", done],
                                    pipei.readEnd, pipeo.writeEnd, pipee.writeEnd, null, config);
        pipei.writeEnd.writeln("input");
        pipei.writeEnd.flush();
        assert(pipeo.readEnd.readln().chomp() == "input output foo");
        assert(pipee.readEnd.readln().chomp().stripRight() == "input error bar");
        if (config.flags & Config.Flags.detached)
            while (!done.exists) Thread.sleep(10.msecs);
        else
            wait(pid);
        while (remove(done).collectException) Thread.sleep(10.msecs);
    }

    // Files
    void testFiles(Config config)
    {
        import std.ascii : newline;
        import std.file : tempDir, exists, remove, readText, write;
        import std.uuid : randomUUID;
        import std.exception : collectException;
        auto pathi = buildPath(tempDir(), randomUUID().toString());
        auto patho = buildPath(tempDir(), randomUUID().toString());
        auto pathe = buildPath(tempDir(), randomUUID().toString());
        write(pathi, "INPUT" ~ newline);
        auto filei = File(pathi, "r");
        auto fileo = File(patho, "w");
        auto filee = File(pathe, "w");
        auto done = buildPath(tempDir(), randomUUID().toString());
        auto pid = spawnProcess([prog.path, "bar", "baz", done], filei, fileo, filee, null, config);
        if (config.flags & Config.Flags.detached)
            while (!done.exists) Thread.sleep(10.msecs);
        else
            wait(pid);
        assert(readText(patho).chomp() == "INPUT output bar");
        assert(readText(pathe).chomp().stripRight() == "INPUT error baz");
        while (remove(pathi).collectException) Thread.sleep(10.msecs);
        while (remove(patho).collectException) Thread.sleep(10.msecs);
        while (remove(pathe).collectException) Thread.sleep(10.msecs);
        while (remove(done).collectException) Thread.sleep(10.msecs);
    }

    testPipes(Config.none);
    testFiles(Config.none);
    testPipes(Config.detached);
    testFiles(Config.detached);
}

@system unittest // Error handling in spawnProcess()
{
    import std.algorithm.searching : canFind;
    import std.exception : assertThrown, collectExceptionMsg;

    static void testNotFoundException(string program)
    {
        assert(collectExceptionMsg!ProcessException(spawnProcess(program)).canFind(program));
        assert(collectExceptionMsg!ProcessException(spawnProcess(program, null, Config.detached)).canFind(program));
    }
    testNotFoundException("ewrgiuhrifuheiohnmnvqweoijwf");
    testNotFoundException("./rgiuhrifuheiohnmnvqweoijwf");

    // can't execute malformed file with executable permissions
    version (Posix)
    {
        import std.path : buildPath;
        import std.file : remove, write, setAttributes, tempDir;
        import core.sys.posix.sys.stat : S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IXGRP, S_IROTH, S_IXOTH;
        import std.conv : to;
        string deleteme = buildPath(tempDir(), "deleteme.std.process.unittest.pid") ~ to!string(thisProcessID);
        write(deleteme, "");
        scope(exit) remove(deleteme);
        setAttributes(deleteme, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
        assertThrown!ProcessException(spawnProcess(deleteme));
        assertThrown!ProcessException(spawnProcess(deleteme, null, Config.detached));
    }
}

@system unittest // Specifying a working directory.
{
    import std.path;
    import std.file;
    TestScript prog = "echo foo>bar";

    auto directory = uniqueTempPath();
    mkdir(directory);
    scope(exit) rmdirRecurse(directory);

    auto pid = spawnProcess([prog.path], null, Config.none, directory);
    wait(pid);
    assert(exists(buildPath(directory, "bar")));
}

@system unittest // Specifying a bad working directory.
{
    import std.exception : assertThrown;
    import std.file;
    TestScript prog = "echo";

    auto directory = uniqueTempPath();
    assertThrown!ProcessException(spawnProcess([prog.path], null, Config.none, directory));
    assertThrown!ProcessException(spawnProcess([prog.path], null, Config.detached, directory));

    std.file.write(directory, "foo");
    scope(exit) remove(directory);
    assertThrown!ProcessException(spawnProcess([prog.path], null, Config.none, directory));
    assertThrown!ProcessException(spawnProcess([prog.path], null, Config.detached, directory));

    // can't run in directory if user does not have search permission on this directory
    version (Posix)
    {
        if (core.sys.posix.unistd.getuid() != 0)
        {
            import core.sys.posix.sys.stat : S_IRUSR;
            auto directoryNoSearch = uniqueTempPath();
            mkdir(directoryNoSearch);
            scope(exit) rmdirRecurse(directoryNoSearch);
            setAttributes(directoryNoSearch, S_IRUSR);
            assertThrown!ProcessException(spawnProcess(prog.path, null, Config.none, directoryNoSearch));
            assertThrown!ProcessException(spawnProcess(prog.path, null, Config.detached, directoryNoSearch));
        }
    }
}

@system unittest // Specifying empty working directory.
{
    TestScript prog = "";

    string directory = "";
    assert(directory.ptr && !directory.length);
    spawnProcess([prog.path], null, Config.none, directory).wait();
}

// Reopening the standard streams (https://issues.dlang.org/show_bug.cgi?id=13258)
@system unittest
{
    import std.string;
    import std.file;
    void fun()
    {
        spawnShell("echo foo").wait();
        spawnShell("echo bar").wait();
    }

    auto tmpFile = uniqueTempPath();
    scope(exit) if (exists(tmpFile)) remove(tmpFile);

    {
        auto oldOut = std.stdio.stdout;
        scope(exit) std.stdio.stdout = oldOut;

        std.stdio.stdout = File(tmpFile, "w");
        fun();
        std.stdio.stdout.close();
    }

    auto lines = readText(tmpFile).splitLines();
    assert(lines == ["foo", "bar"]);
}

// MSVCRT workaround (https://issues.dlang.org/show_bug.cgi?id=14422)
version (Windows)
@system unittest
{
    auto fn = uniqueTempPath();
    scope(exit) if (exists(fn)) remove(fn);
    std.file.write(fn, "AAAAAAAAAA");

    auto f = File(fn, "a");
    spawnProcess(["cmd", "/c", "echo BBBBB"], std.stdio.stdin, f).wait();

    auto data = readText(fn);
    assert(data == "AAAAAAAAAABBBBB\r\n", data);
}

// https://issues.dlang.org/show_bug.cgi?id=20765
// Test that running processes with relative path works in conjunction
// with indicating a workDir.
version (Posix) @system unittest
{
    import std.file : mkdir, write, setAttributes, rmdirRecurse;
    import std.conv : octal;

    auto dir = uniqueTempPath();
    mkdir(dir);
    scope(exit) rmdirRecurse(dir);
    write(dir ~ "/program", "#!/bin/sh\necho Hello");
    setAttributes(dir ~ "/program", octal!700);

    assert(execute(["./program"], null, Config.none, size_t.max, dir).output == "Hello\n");
}

/**
A variation on $(LREF spawnProcess) that runs the given _command through
the current user's preferred _command interpreter (aka. shell).

The string `command` is passed verbatim to the shell, and is therefore
subject to its rules about _command structure, argument/filename quoting
and escaping of special characters.
The path to the shell executable defaults to $(LREF nativeShell).

In all other respects this function works just like `spawnProcess`.
Please refer to the $(LREF spawnProcess) documentation for descriptions
of the other function parameters, the return value and any exceptions
that may be thrown.
---
// Run the command/program "foo" on the file named "my file.txt", and
// redirect its output into foo.log.
auto pid = spawnShell(`foo "my file.txt" > foo.log`);
wait(pid);
---

See_also:
$(LREF escapeShellCommand), which may be helpful in constructing a
properly quoted and escaped shell _command line for the current platform.
*/
Pid spawnShell(scope const(char)[] command,
               File stdin = std.stdio.stdin,
               File stdout = std.stdio.stdout,
               File stderr = std.stdio.stderr,
               scope const string[string] env = null,
               Config config = Config.none,
               scope const(char)[] workDir = null,
               scope string shellPath = nativeShell)
    @trusted // See reason below
{
    version (Windows)
    {
        // CMD does not parse its arguments like other programs.
        // It does not use CommandLineToArgvW.
        // Instead, it treats the first and last quote specially.
        // See CMD.EXE /? for details.
        const commandLine = escapeShellFileName(shellPath)
                            ~ ` ` ~ shellSwitch ~ ` "` ~ command ~ `"`;
        return spawnProcessWin(commandLine, shellPath, stdin, stdout, stderr, env, config, workDir);
    }
    else version (Posix)
    {
        const(char)[][3] args;
        args[0] = shellPath;
        args[1] = shellSwitch;
        args[2] = command;
        /* The passing of args converts the static array, which is initialized with `scope` pointers,
         * to a dynamic array, which is also a scope parameter. So, it is a scope pointer to a
         * scope pointer, which although is safely used here, D doesn't allow transitive scope.
         * See https://github.com/dlang/dmd/pull/10951
         */
        return spawnProcessPosix(args, stdin, stdout, stderr, env, config, workDir);
    }
    else
        static assert(0);
}

/// ditto
Pid spawnShell(scope const(char)[] command,
               scope const string[string] env,
               Config config = Config.none,
               scope const(char)[] workDir = null,
               scope string shellPath = nativeShell)
    @trusted // TODO: Should be @safe
{
    return spawnShell(command,
                      std.stdio.stdin,
                      std.stdio.stdout,
                      std.stdio.stderr,
                      env,
                      config,
                      workDir,
                      shellPath);
}

@system unittest
{
    version (Windows)
        auto cmd = "echo %FOO%";
    else version (Posix)
        auto cmd = "echo $foo";
    import std.file;
    auto tmpFile = uniqueTempPath();
    scope(exit) if (exists(tmpFile)) remove(tmpFile);
    auto redir = "> \""~tmpFile~'"';
    auto env = ["foo" : "bar"];
    assert(wait(spawnShell(cmd~redir, env)) == 0);
    auto f = File(tmpFile, "a");
    version (CRuntime_Microsoft) f.seek(0, SEEK_END); // MSVCRT probably seeks to the end when writing, not before
    assert(wait(spawnShell(cmd, std.stdio.stdin, f, std.stdio.stderr, env)) == 0);
    f.close();
    auto output = std.file.readText(tmpFile);
    assert(output == "bar\nbar\n" || output == "bar\r\nbar\r\n");
}

version (Windows)
@system unittest
{
    import std.string;
    import std.conv : text;
    TestScript prog = "echo %0 %*";
    auto outputFn = uniqueTempPath();
    scope(exit) if (exists(outputFn)) remove(outputFn);
    auto args = [`a b c`, `a\b\c\`, `a"b"c"`];
    auto result = executeShell(
        escapeShellCommand([prog.path] ~ args)
        ~ " > " ~
        escapeShellFileName(outputFn));
    assert(result.status == 0);
    auto args2 = outputFn.readText().strip().parseCommandLine()[1..$];
    assert(args == args2, text(args2));
}


/**
Options that control the behaviour of process creation functions in this
module. Most options only apply to $(LREF spawnProcess) and
$(LREF spawnShell).

Example:
---
auto logFile = File("myapp_error.log", "w");

// Start program, suppressing the console window (Windows only),
// redirect its error stream to logFile, and leave logFile open
// in the parent process as well.
auto pid = spawnProcess("myapp", stdin, stdout, logFile,
                        Config.retainStderr | Config.suppressConsole);
scope(exit)
{
    auto exitCode = wait(pid);
    logFile.writeln("myapp exited with code ", exitCode);
    logFile.close();
}
---
*/
struct Config
{
    /**
       Flag options.
       Use bitwise OR to combine flags.
    **/
    enum Flags
    {
        none = 0,

        /**
        By default, the child process inherits the parent's environment,
        and any environment variables passed to $(LREF spawnProcess) will
        be added to it.  If this flag is set, the only variables in the
        child process' environment will be those given to spawnProcess.
        */
        newEnv = 1,

        /**
        Unless the child process inherits the standard input/output/error
        streams of its parent, one almost always wants the streams closed
        in the parent when $(LREF spawnProcess) returns.  Therefore, by
        default, this is done.  If this is not desirable, pass any of these
        options to spawnProcess.
        */
        retainStdin  = 2,
        retainStdout = 4,                                  /// ditto
        retainStderr = 8,                                  /// ditto

        /**
        On Windows, if the child process is a console application, this
        flag will prevent the creation of a console window.  Otherwise,
        it will be ignored. On POSIX, `suppressConsole` has no effect.
        */
        suppressConsole = 16,

        /**
        On POSIX, open $(LINK2 http://en.wikipedia.org/wiki/File_descriptor,file descriptors)
        are by default inherited by the child process.  As this may lead
        to subtle bugs when pipes or multiple threads are involved,
        $(LREF spawnProcess) ensures that all file descriptors except the
        ones that correspond to standard input/output/error are closed
        in the child process when it starts.  Use `inheritFDs` to prevent
        this.

        On Windows, this option has no effect, and any handles which have been
        explicitly marked as inheritable will always be inherited by the child
        process.
        */
        inheritFDs = 32,

        /**
        Spawn process in detached state. This removes the need in calling
        $(LREF wait) to clean up the process resources.

        Note:
        Calling $(LREF wait) or $(LREF kill) with the resulting `Pid` is invalid.
        */
        detached = 64,

        /**
        By default, the $(LREF execute) and $(LREF executeShell) functions
        will capture child processes' both stdout and stderr. This can be
        undesirable if the standard output is to be processed or otherwise
        used by the invoking program, as `execute`'s result would then
        contain a mix of output and warning/error messages.

        Specify this flag when calling `execute` or `executeShell` to
        cause invoked processes' stderr stream to be sent to $(REF stderr,
        std,stdio), and only capture and return standard output.

        This flag has no effect on $(LREF spawnProcess) or $(LREF spawnShell).
        */
        stderrPassThrough = 128,
    }
    Flags flags; /// ditto

    /**
       For backwards compatibility, and cases when only flags need to
       be specified in the `Config`, these allow building `Config`
       instances using flag names only.
    */
    enum Config none = Config.init;
    enum Config newEnv = Config(Flags.newEnv); /// ditto
    enum Config retainStdin = Config(Flags.retainStdin); /// ditto
    enum Config retainStdout = Config(Flags.retainStdout); /// ditto
    enum Config retainStderr = Config(Flags.retainStderr); /// ditto
    enum Config suppressConsole = Config(Flags.suppressConsole); /// ditto
    enum Config inheritFDs = Config(Flags.inheritFDs); /// ditto
    enum Config detached = Config(Flags.detached); /// ditto
    enum Config stderrPassThrough = Config(Flags.stderrPassThrough); /// ditto
    Config opUnary(string op)()
    if (is(typeof(mixin(op ~ q{flags}))))
    {
        return Config(mixin(op ~ q{flags}));
    } /// ditto
    Config opBinary(string op)(Config other)
    if (is(typeof(mixin(q{flags} ~ op ~ q{other.flags}))))
    {
        return Config(mixin(q{flags} ~ op ~ q{other.flags}));
    } /// ditto
    Config opOpAssign(string op)(Config other)
    if (is(typeof(mixin(q{flags} ~ op ~ q{=other.flags}))))
    {
        return Config(mixin(q{flags} ~ op ~ q{=other.flags}));
    } /// ditto

    version (StdDdoc)
    {
        /**
        A function that is called before `exec` in $(LREF spawnProcess).
        It returns `true` if succeeded and otherwise returns `false`.

        $(RED Warning:
            Please note that the code in this function must only use
            async-signal-safe functions.)

        If $(LREF preExecDelegate) is also set, it is called last.

        On Windows, this member is not available.
        */
        bool function() nothrow @nogc @safe preExecFunction;

        /**
        A delegate that is called before `exec` in $(LREF spawnProcess).
        It returns `true` if succeeded and otherwise returns `false`.

        $(RED Warning:
            Please note that the code in this function must only use
            async-signal-safe functions.)

        If $(LREF preExecFunction) is also set, it is called first.

        On Windows, this member is not available.
        */
        bool delegate() nothrow @nogc @safe preExecDelegate;
    }
    else version (Posix)
    {
        bool function() nothrow @nogc @safe preExecFunction;
        bool delegate() nothrow @nogc @safe preExecDelegate;
    }
}

// https://issues.dlang.org/show_bug.cgi?id=22125
@safe unittest
{
    Config c = Config.retainStdin;
    c |= Config.retainStdout;
    c |= Config.retainStderr;
    c &= ~Config.retainStderr;
    assert(c == (Config.retainStdin | Config.retainStdout));
}

/// A handle that corresponds to a spawned process.
final class Pid
{
    /**
    The process ID number.

    This is a number that uniquely identifies the process on the operating
    system, for at least as long as the process is running.  Once $(LREF wait)
    has been called on the $(LREF Pid), this method will return an
    invalid (negative) process ID.
    */
    @property int processID() const @safe pure nothrow
    {
        return _processID;
    }

    /**
    An operating system handle to the process.

    This handle is used to specify the process in OS-specific APIs.
    On POSIX, this function returns a `core.sys.posix.sys.types.pid_t`
    with the same value as $(LREF Pid.processID), while on Windows it returns
    a `core.sys.windows.windows.HANDLE`.

    Once $(LREF wait) has been called on the $(LREF Pid), this method
    will return an invalid handle.
    */
    // Note: Since HANDLE is a reference, this function cannot be const.
    version (Windows)
    @property HANDLE osHandle() @nogc @safe pure nothrow
    {
        return _handle;
    }
    else version (Posix)
    @property pid_t osHandle() @nogc @safe pure nothrow
    {
        return _processID;
    }

private:
    /*
    Pid.performWait() does the dirty work for wait() and nonBlockingWait().

    If block == true, this function blocks until the process terminates,
    sets _processID to terminated, and returns the exit code or terminating
    signal as described in the wait() documentation.

    If block == false, this function returns immediately, regardless
    of the status of the process.  If the process has terminated, the
    function has the exact same effect as the blocking version.  If not,
    it returns 0 and does not modify _processID.
    */
    version (Posix)
    int performWait(bool block) @trusted
    {
        import std.exception : enforce;
        enforce!ProcessException(owned, "Can't wait on a detached process");
        if (_processID == terminated) return _exitCode;
        int exitCode;
        while (true)
        {
            int status;
            auto check = waitpid(_processID, &status, block ? 0 : WNOHANG);
            if (check == -1)
            {
                if (errno == ECHILD)
                {
                    throw new ProcessException(
                        "Process does not exist or is not a child process.");
                }
                else
                {
                    // waitpid() was interrupted by a signal.  We simply
                    // restart it.
                    assert(errno == EINTR);
                    continue;
                }
            }
            if (!block && check == 0) return 0;
            if (WIFEXITED(status))
            {
                exitCode = WEXITSTATUS(status);
                break;
            }
            else if (WIFSIGNALED(status))
            {
                exitCode = -WTERMSIG(status);
                break;
            }
            // We check again whether the call should be blocking,
            // since we don't care about other status changes besides
            // "exited" and "terminated by signal".
            if (!block) return 0;

            // Process has stopped, but not terminated, so we continue waiting.
        }
        // Mark Pid as terminated, and cache and return exit code.
        _processID = terminated;
        _exitCode = exitCode;
        return exitCode;
    }
    else version (Windows)
    {
        int performWait(const bool block, const DWORD timeout = INFINITE) @trusted
        {
            import std.exception : enforce;
            enforce!ProcessException(owned, "Can't wait on a detached process");
            if (_processID == terminated) return _exitCode;
            assert(_handle != INVALID_HANDLE_VALUE);
            if (block)
            {
                auto result = WaitForSingleObject(_handle, timeout);
                if (result != WAIT_OBJECT_0)
                {
                    // Wait time exceeded `timeout` milliseconds?
                    if (result == WAIT_TIMEOUT && timeout != INFINITE)
                        return 0;

                    throw ProcessException.newFromLastError("Wait failed.");
                }
            }
            if (!GetExitCodeProcess(_handle, cast(LPDWORD)&_exitCode))
                throw ProcessException.newFromLastError();
            if (!block && _exitCode == STILL_ACTIVE) return 0;
            CloseHandle(_handle);
            _handle = INVALID_HANDLE_VALUE;
            _processID = terminated;
            return _exitCode;
        }

        int performWait(Duration timeout) @safe
        {
            import std.exception : enforce;
            const msecs = timeout.total!"msecs";

            // Limit this implementation the maximum wait time offered by
            // WaitForSingleObject. One could theoretically break up larger
            // durations into multiple waits but (DWORD.max - 1).msecs
            // (> 7 weeks, 17 hours) should be enough for the usual case.
            // DWORD.max is reserved for INFINITE
            enforce!ProcessException(msecs < DWORD.max, "Timeout exceeds maximum wait time!");
            return performWait(true, cast(DWORD) msecs);
        }

        ~this()
        {
            if (_handle != INVALID_HANDLE_VALUE)
            {
                CloseHandle(_handle);
                _handle = INVALID_HANDLE_VALUE;
            }
        }
    }

    // Special values for _processID.
    enum invalid = -1, terminated = -2;

    // OS process ID number.  Only nonnegative IDs correspond to
    // running processes.
    int _processID = invalid;

    // Exit code cached by wait().  This is only expected to hold a
    // sensible value if _processID == terminated.
    int _exitCode;

    // Whether the process can be waited for by wait() for or killed by kill().
    // False if process was started as detached. True otherwise.
    bool owned;

    // Pids are only meant to be constructed inside this module, so
    // we make the constructor private.
    version (Windows)
    {
        HANDLE _handle = INVALID_HANDLE_VALUE;
        this(int pid, HANDLE handle) @safe pure nothrow
        {
            _processID = pid;
            _handle = handle;
            this.owned = true;
        }
        this(int pid) @safe pure nothrow
        {
            _processID = pid;
            this.owned = false;
        }
    }
    else
    {
        this(int id, bool owned) @safe pure nothrow
        {
            _processID = id;
            this.owned = owned;
        }
    }
}


/**
Waits for the process associated with `pid` to terminate, and returns
its exit status.

In general one should always _wait for child processes to terminate
before exiting the parent process unless the process was spawned as detached
(that was spawned with `Config.detached` flag).
Otherwise, they may become "$(HTTP en.wikipedia.org/wiki/Zombie_process,zombies)"
– processes that are defunct, yet still occupy a slot in the OS process table.
You should not and must not wait for detached processes, since you don't own them.

If the process has already terminated, this function returns directly.
The exit code is cached, so that if wait() is called multiple times on
the same $(LREF Pid) it will always return the same value.

POSIX_specific:
If the process is terminated by a signal, this function returns a
negative number whose absolute value is the signal number.
Since POSIX restricts normal exit codes to the range 0-255, a
negative return value will always indicate termination by signal.
Signal codes are defined in the `core.sys.posix.signal` module
(which corresponds to the `signal.h` POSIX header).

Throws:
$(LREF ProcessException) on failure or on attempt to wait for detached process.

Example:
See the $(LREF spawnProcess) documentation.

See_also:
$(LREF tryWait), for a non-blocking function.
*/
int wait(Pid pid) @safe
{
    assert(pid !is null, "Called wait on a null Pid.");
    return pid.performWait(true);
}


@system unittest // Pid and wait()
{
    version (Windows)    TestScript prog = "exit %~1";
    else version (Posix) TestScript prog = "exit $1";
    assert(wait(spawnProcess([prog.path, "0"])) == 0);
    assert(wait(spawnProcess([prog.path, "123"])) == 123);
    auto pid = spawnProcess([prog.path, "10"]);
    assert(pid.processID > 0);
    version (Windows)    assert(pid.osHandle != INVALID_HANDLE_VALUE);
    else version (Posix) assert(pid.osHandle == pid.processID);
    assert(wait(pid) == 10);
    assert(wait(pid) == 10); // cached exit code
    assert(pid.processID < 0);
    version (Windows)    assert(pid.osHandle == INVALID_HANDLE_VALUE);
    else version (Posix) assert(pid.osHandle < 0);
}

private import std.typecons : Tuple;

/**
Waits until either the process associated with `pid` terminates or the
elapsed time exceeds the given timeout.

If the process terminates within the given duration it behaves exactly like
`wait`, except that it returns a tuple `(true, exit code)`.

If the process does not terminate within the given duration it will stop
waiting and return `(false, 0).`

The timeout may not exceed `(uint.max - 1).msecs` (~ 7 weeks, 17 hours).

$(BLUE This function is Windows-Only.)

Returns:
An $(D std.typecons.Tuple!(bool, "terminated", int, "status")).

Throws:
$(LREF ProcessException) on failure or on attempt to wait for detached process.

Example:
See the $(LREF spawnProcess) documentation.

See_also:
$(LREF wait), for a blocking function without timeout.
$(LREF tryWait), for a non-blocking function without timeout.
*/
version (StdDdoc)
Tuple!(bool, "terminated", int, "status") waitTimeout(Pid pid, Duration timeout) @safe;

else version (Windows)
Tuple!(bool, "terminated", int, "status") waitTimeout(Pid pid, Duration timeout) @safe
{
    assert(pid !is null, "Called wait on a null Pid.");
    auto code = pid.performWait(timeout);
    return typeof(return)(pid._processID == Pid.terminated, code);
}

version (Windows)
@system unittest // Pid and waitTimeout()
{
    import std.exception : collectException;
    import std.typecons : tuple;

    TestScript prog = ":Loop\r\n" ~ "goto Loop";
    auto pid = spawnProcess(prog.path);

    // Doesn't block longer than one second
    assert(waitTimeout(pid, 1.seconds) == tuple(false, 0));

    kill(pid);
    assert(waitTimeout(pid, 1.seconds) == tuple(true, 1)); // exit 1 because the process is killed

    // Rejects timeouts exceeding the Windows API capabilities
    const dur = DWORD.max.msecs;
    const ex = collectException!ProcessException(waitTimeout(pid, dur));
    assert(ex);
    assert(ex.msg == "Timeout exceeds maximum wait time!");
}

/**
A non-blocking version of $(LREF wait).

If the process associated with `pid` has already terminated,
`tryWait` has the exact same effect as `wait`.
In this case, it returns a tuple where the `terminated` field
is set to `true` and the `status` field has the same
interpretation as the return value of `wait`.

If the process has $(I not) yet terminated, this function differs
from `wait` in that does not wait for this to happen, but instead
returns immediately.  The `terminated` field of the returned
tuple will then be set to `false`, while the `status` field
will always be 0 (zero).  `wait` or `tryWait` should then be
called again on the same `Pid` at some later time; not only to
get the exit code, but also to avoid the process becoming a "zombie"
when it finally terminates.  (See $(LREF wait) for details).

Returns:
An $(D std.typecons.Tuple!(bool, "terminated", int, "status")).

Throws:
$(LREF ProcessException) on failure or on attempt to wait for detached process.

Example:
---
auto pid = spawnProcess("dmd myapp.d");
scope(exit) wait(pid);
...
auto dmd = tryWait(pid);
if (dmd.terminated)
{
    if (dmd.status == 0) writeln("Compilation succeeded!");
    else writeln("Compilation failed");
}
else writeln("Still compiling...");
...
---
Note that in this example, the first `wait` call will have no
effect if the process has already terminated by the time `tryWait`
is called.  In the opposite case, however, the `scope` statement
ensures that we always wait for the process if it hasn't terminated
by the time we reach the end of the scope.
*/
auto tryWait(Pid pid) @safe
{
    import std.typecons : Tuple;
    assert(pid !is null, "Called tryWait on a null Pid.");
    auto code = pid.performWait(false);
    return Tuple!(bool, "terminated", int, "status")(pid._processID == Pid.terminated, code);
}
// unittest: This function is tested together with kill() below.


/**
Attempts to terminate the process associated with `pid`.

The effect of this function, as well as the meaning of `codeOrSignal`,
is highly platform dependent.  Details are given below.  Common to all
platforms is that this function only $(I initiates) termination of the process,
and returns immediately.  It does not wait for the process to end,
nor does it guarantee that the process does in fact get terminated.

Always call $(LREF wait) to wait for a process to complete, even if `kill`
has been called on it.

Windows_specific:
The process will be
$(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/ms686714%28v=vs.100%29.aspx,
forcefully and abruptly terminated).  If `codeOrSignal` is specified, it
must be a nonnegative number which will be used as the exit code of the process.
If not, the process wil exit with code 1.  Do not use $(D codeOrSignal = 259),
as this is a special value (aka. $(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/ms683189.aspx,STILL_ACTIVE))
used by Windows to signal that a process has in fact $(I not) terminated yet.
---
auto pid = spawnProcess("some_app");
kill(pid, 10);
assert(wait(pid) == 10);
---

POSIX_specific:
A $(LINK2 http://en.wikipedia.org/wiki/Unix_signal,signal) will be sent to
the process, whose value is given by `codeOrSignal`.  Depending on the
signal sent, this may or may not terminate the process.  Symbolic constants
for various $(LINK2 http://en.wikipedia.org/wiki/Unix_signal#POSIX_signals,
POSIX signals) are defined in `core.sys.posix.signal`, which corresponds to the
$(LINK2 http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html,
`signal.h` POSIX header).  If `codeOrSignal` is omitted, the
`SIGTERM` signal will be sent.  (This matches the behaviour of the
$(LINK2 http://pubs.opengroup.org/onlinepubs/9699919799/utilities/kill.html,
`_kill`) shell command.)
---
import core.sys.posix.signal : SIGKILL;
auto pid = spawnProcess("some_app");
kill(pid, SIGKILL);
assert(wait(pid) == -SIGKILL); // Negative return value on POSIX!
---

Throws:
$(LREF ProcessException) on error (e.g. if codeOrSignal is invalid).
    or on attempt to kill detached process.
    Note that failure to terminate the process is considered a "normal"
    outcome, not an error.$(BR)
*/
void kill(Pid pid)
{
    version (Windows) kill(pid, 1);
    else version (Posix)
    {
        import core.sys.posix.signal : SIGTERM;
        kill(pid, SIGTERM);
    }
}

/// ditto
void kill(Pid pid, int codeOrSignal)
{
    import std.exception : enforce;
    enforce!ProcessException(pid.owned, "Can't kill detached process");
    version (Windows)
    {
        if (codeOrSignal < 0) throw new ProcessException("Invalid exit code");
        // On Windows, TerminateProcess() appears to terminate the
        // *current* process if it is passed an invalid handle...
        if (pid.osHandle == INVALID_HANDLE_VALUE)
            throw new ProcessException("Invalid process handle");
        if (!TerminateProcess(pid.osHandle, codeOrSignal))
            throw ProcessException.newFromLastError();
    }
    else version (Posix)
    {
        import core.sys.posix.signal : kill;
        if (pid.osHandle == Pid.invalid)
            throw new ProcessException("Pid is invalid");
        if (pid.osHandle == Pid.terminated)
            throw new ProcessException("Pid is already terminated");
        if (kill(pid.osHandle, codeOrSignal) == -1)
            throw ProcessException.newFromErrno();
    }
}

@system unittest // tryWait() and kill()
{
    import core.thread;
    import std.exception : assertThrown;
    // The test script goes into an infinite loop.
    version (Windows)
    {
        TestScript prog = ":loop
                           goto loop";
    }
    else version (Posix)
    {
        import core.sys.posix.signal : SIGTERM, SIGKILL;
        TestScript prog = "while true; do sleep 1; done";
    }
    auto pid = spawnProcess(prog.path);
    // Android appears to automatically kill sleeping processes very quickly,
    // so shorten the wait before killing here.
    version (Android)
        Thread.sleep(dur!"msecs"(5));
    else
        Thread.sleep(dur!"msecs"(500));
    kill(pid);
    version (Windows)    assert(wait(pid) == 1);
    else version (Posix) assert(wait(pid) == -SIGTERM);

    pid = spawnProcess(prog.path);
    Thread.sleep(dur!"msecs"(500));
    auto s = tryWait(pid);
    assert(!s.terminated && s.status == 0);
    assertThrown!ProcessException(kill(pid, -123)); // Negative code not allowed.
    version (Windows)    kill(pid, 123);
    else version (Posix) kill(pid, SIGKILL);
    do { s = tryWait(pid); } while (!s.terminated);
    version (Windows)    assert(s.status == 123);
    else version (Posix) assert(s.status == -SIGKILL);
    assertThrown!ProcessException(kill(pid)); // Already terminated
}

@system unittest // wait() and kill() detached process
{
    import core.thread;
    import std.exception : assertThrown;
    TestScript prog = "exit 0";
    auto pid = spawnProcess([prog.path], null, Config.detached);
    /*
    This sleep is needed because we can't wait() for detached process to end
    and therefore TestScript destructor may run at the same time as /bin/sh tries to start the script.
    This leads to the annoying message like "/bin/sh: 0: Can't open /tmp/std.process temporary file" to appear when running tests.
    It does not happen in unittests with non-detached processes because we always wait() for them to finish.
    */
    Thread.sleep(500.msecs);
    assert(!pid.owned);
    version (Windows) assert(pid.osHandle == INVALID_HANDLE_VALUE);
    assertThrown!ProcessException(wait(pid));
    assertThrown!ProcessException(kill(pid));
}


/**
Creates a unidirectional _pipe.

Data is written to one end of the _pipe and read from the other.
---
auto p = pipe();
p.writeEnd.writeln("Hello World");
p.writeEnd.flush();
assert(p.readEnd.readln().chomp() == "Hello World");
---
Pipes can, for example, be used for interprocess communication
by spawning a new process and passing one end of the _pipe to
the child, while the parent uses the other end.
(See also $(LREF pipeProcess) and $(LREF pipeShell) for an easier
way of doing this.)
---
// Use cURL to download the dlang.org front page, pipe its
// output to grep to extract a list of links to ZIP files,
// and write the list to the file "D downloads.txt":
auto p = pipe();
auto outFile = File("D downloads.txt", "w");
auto cpid = spawnProcess(["curl", "http://dlang.org/download.html"],
                         std.stdio.stdin, p.writeEnd);
scope(exit) wait(cpid);
auto gpid = spawnProcess(["grep", "-o", `http://\S*\.zip`],
                         p.readEnd, outFile);
scope(exit) wait(gpid);
---

Returns:
A $(LREF Pipe) object that corresponds to the created _pipe.

Throws:
$(REF StdioException, std,stdio) on failure.
*/
version (Posix)
Pipe pipe() @trusted //TODO: @safe
{
    import core.sys.posix.stdio : fdopen;
    int[2] fds;
    if (core.sys.posix.unistd.pipe(fds) != 0)
        throw new StdioException("Unable to create pipe");
    Pipe p;
    auto readFP = fdopen(fds[0], "r");
    if (readFP == null)
        throw new StdioException("Cannot open read end of pipe");
    p._read = File(readFP, null);
    auto writeFP = fdopen(fds[1], "w");
    if (writeFP == null)
        throw new StdioException("Cannot open write end of pipe");
    p._write = File(writeFP, null);
    return p;
}
else version (Windows)
Pipe pipe() @trusted //TODO: @safe
{
    // use CreatePipe to create an anonymous pipe
    HANDLE readHandle;
    HANDLE writeHandle;
    if (!CreatePipe(&readHandle, &writeHandle, null, 0))
    {
        throw new StdioException(
            "Error creating pipe (" ~ generateSysErrorMsg() ~ ')',
            0);
    }

    scope(failure)
    {
        CloseHandle(readHandle);
        CloseHandle(writeHandle);
    }

    try
    {
        Pipe p;
        p._read .windowsHandleOpen(readHandle , "r");
        p._write.windowsHandleOpen(writeHandle, "a");
        return p;
    }
    catch (Exception e)
    {
        throw new StdioException("Error attaching pipe (" ~ e.msg ~ ")",
            0);
    }
}


/// An interface to a pipe created by the $(LREF pipe) function.
struct Pipe
{
    /// The read end of the pipe.
    @property File readEnd() @safe nothrow { return _read; }


    /// The write end of the pipe.
    @property File writeEnd() @safe nothrow { return _write; }


    /**
    Closes both ends of the pipe.

    Normally it is not necessary to do this manually, as $(REF File, std,stdio)
    objects are automatically closed when there are no more references
    to them.

    Note that if either end of the pipe has been passed to a child process,
    it will only be closed in the parent process.  (What happens in the
    child process is platform dependent.)

    Throws:
    $(REF ErrnoException, std,exception) if an error occurs.
    */
    void close() @safe
    {
        _read.close();
        _write.close();
    }

private:
    File _read, _write;
}

@system unittest
{
    import std.string;
    auto p = pipe();
    p.writeEnd.writeln("Hello World");
    p.writeEnd.flush();
    assert(p.readEnd.readln().chomp() == "Hello World");
    p.close();
    assert(!p.readEnd.isOpen);
    assert(!p.writeEnd.isOpen);
}


/**
Starts a new process, creating pipes to redirect its standard
input, output and/or error streams.

`pipeProcess` and `pipeShell` are convenient wrappers around
$(LREF spawnProcess) and $(LREF spawnShell), respectively, and
automate the task of redirecting one or more of the child process'
standard streams through pipes.  Like the functions they wrap,
these functions return immediately, leaving the child process to
execute in parallel with the invoking process.  It is recommended
to always call $(LREF wait) on the returned $(LREF ProcessPipes.pid),
as detailed in the documentation for `wait`.

The `args`/`program`/`command`, `env` and `config`
parameters are forwarded straight to the underlying spawn functions,
and we refer to their documentation for details.

Params:
args      = An array which contains the program name as the zeroth element
            and any command-line arguments in the following elements.
            (See $(LREF spawnProcess) for details.)
program   = The program name, $(I without) command-line arguments.
            (See $(LREF spawnProcess) for details.)
command   = A shell command which is passed verbatim to the command
            interpreter.  (See $(LREF spawnShell) for details.)
redirect  = Flags that determine which streams are redirected, and
            how.  See $(LREF Redirect) for an overview of available
            flags.
env       = Additional environment variables for the child process.
            (See $(LREF spawnProcess) for details.)
config    = Flags that control process creation. See $(LREF Config)
            for an overview of available flags, and note that the
            `retainStd...` flags have no effect in this function.
workDir   = The working directory for the new process.
            By default the child process inherits the parent's working
            directory.
shellPath = The path to the shell to use to run the specified program.
            By default this is $(LREF nativeShell).

Returns:
A $(LREF ProcessPipes) object which contains $(REF File, std,stdio)
handles that communicate with the redirected streams of the child
process, along with a $(LREF Pid) object that corresponds to the
spawned process.

Throws:
$(LREF ProcessException) on failure to start the process.$(BR)
$(REF StdioException, std,stdio) on failure to redirect any of the streams.$(BR)

Example:
---
// my_application writes to stdout and might write to stderr
auto pipes = pipeProcess("my_application", Redirect.stdout | Redirect.stderr);
scope(exit) wait(pipes.pid);

// Store lines of output.
string[] output;
foreach (line; pipes.stdout.byLine) output ~= line.idup;

// Store lines of errors.
string[] errors;
foreach (line; pipes.stderr.byLine) errors ~= line.idup;


// sendmail expects to read from stdin
pipes = pipeProcess(["/usr/bin/sendmail", "-t"], Redirect.stdin);
pipes.stdin.writeln("To: you");
pipes.stdin.writeln("From: me");
pipes.stdin.writeln("Subject: dlang");
pipes.stdin.writeln("");
pipes.stdin.writeln(message);

// a single period tells sendmail we are finished
pipes.stdin.writeln(".");

// but at this point sendmail might not see it, we need to flush
pipes.stdin.flush();

// sendmail happens to exit on ".", but some you have to close the file:
pipes.stdin.close();

// otherwise this wait will wait forever
wait(pipes.pid);

---
*/
ProcessPipes pipeProcess(scope const(char[])[] args,
                         Redirect redirect = Redirect.all,
                         const string[string] env = null,
                         Config config = Config.none,
                         scope const(char)[] workDir = null)
    @safe
{
    return pipeProcessImpl!spawnProcess(args, redirect, env, config, workDir);
}

/// ditto
ProcessPipes pipeProcess(scope const(char)[] program,
                         Redirect redirect = Redirect.all,
                         const string[string] env = null,
                         Config config = Config.none,
                         scope const(char)[] workDir = null)
    @safe
{
    return pipeProcessImpl!spawnProcess(program, redirect, env, config, workDir);
}

/// ditto
ProcessPipes pipeShell(scope const(char)[] command,
                       Redirect redirect = Redirect.all,
                       const string[string] env = null,
                       Config config = Config.none,
                       scope const(char)[] workDir = null,
                       string shellPath = nativeShell)
    @safe
{
    return pipeProcessImpl!spawnShell(command,
                                      redirect,
                                      env,
                                      config,
                                      workDir,
                                      shellPath);
}

// Implementation of the pipeProcess() family of functions.
private ProcessPipes pipeProcessImpl(alias spawnFunc, Cmd, ExtraSpawnFuncArgs...)
                                    (scope Cmd command,
                                     Redirect redirectFlags,
                                     const string[string] env = null,
                                     Config config = Config.none,
                                     scope const(char)[] workDir = null,
                                     ExtraSpawnFuncArgs extraArgs = ExtraSpawnFuncArgs.init)
    @trusted //TODO: @safe
{
    File childStdin, childStdout, childStderr;
    ProcessPipes pipes;
    pipes._redirectFlags = redirectFlags;

    if (redirectFlags & Redirect.stdin)
    {
        auto p = pipe();
        childStdin = p.readEnd;
        pipes._stdin = p.writeEnd;
    }
    else
    {
        childStdin = std.stdio.stdin;
    }

    if (redirectFlags & Redirect.stdout)
    {
        if ((redirectFlags & Redirect.stdoutToStderr) != 0)
            throw new StdioException("Cannot create pipe for stdout AND "
                                     ~"redirect it to stderr", 0);
        auto p = pipe();
        childStdout = p.writeEnd;
        pipes._stdout = p.readEnd;
    }
    else
    {
        childStdout = std.stdio.stdout;
    }

    if (redirectFlags & Redirect.stderr)
    {
        if ((redirectFlags & Redirect.stderrToStdout) != 0)
            throw new StdioException("Cannot create pipe for stderr AND "
                                     ~"redirect it to stdout", 0);
        auto p = pipe();
        childStderr = p.writeEnd;
        pipes._stderr = p.readEnd;
    }
    else
    {
        childStderr = std.stdio.stderr;
    }

    if (redirectFlags & Redirect.stdoutToStderr)
    {
        if (redirectFlags & Redirect.stderrToStdout)
        {
            // We know that neither of the other options have been
            // set, so we assign the std.stdio.std* streams directly.
            childStdout = std.stdio.stderr;
            childStderr = std.stdio.stdout;
        }
        else
        {
            childStdout = childStderr;
        }
    }
    else if (redirectFlags & Redirect.stderrToStdout)
    {
        childStderr = childStdout;
    }

    config.flags &= ~(Config.Flags.retainStdin | Config.Flags.retainStdout | Config.Flags.retainStderr);
    pipes._pid = spawnFunc(command, childStdin, childStdout, childStderr,
                           env, config, workDir, extraArgs);
    return pipes;
}


/**
Flags that can be passed to $(LREF pipeProcess) and $(LREF pipeShell)
to specify which of the child process' standard streams are redirected.
Use bitwise OR to combine flags.
*/
enum Redirect
{
    /// Redirect the standard input, output or error streams, respectively.
    stdin = 1,
    stdout = 2,                             /// ditto
    stderr = 4,                             /// ditto

    /**
    Redirect _all three streams.  This is equivalent to
    $(D Redirect.stdin | Redirect.stdout | Redirect.stderr).
    */
    all = stdin | stdout | stderr,

    /**
    Redirect the standard error stream into the standard output stream.
    This can not be combined with `Redirect.stderr`.
    */
    stderrToStdout = 8,

    /**
    Redirect the standard output stream into the standard error stream.
    This can not be combined with `Redirect.stdout`.
    */
    stdoutToStderr = 16,
}

@system unittest
{
    import std.string;
    version (Windows) TestScript prog =
       "call :sub %~1 %~2 0
        call :sub %~1 %~2 1
        call :sub %~1 %~2 2
        call :sub %~1 %~2 3
        exit 3

        :sub
        set /p INPUT=
        if -%INPUT%-==-stop- ( exit %~3 )
        echo %INPUT% %~1
        echo %INPUT% %~2 1>&2";
    else version (Posix) TestScript prog =
       `for EXITCODE in 0 1 2 3; do
            read INPUT
            if test "$INPUT" = stop; then break; fi
            echo "$INPUT $1"
            echo "$INPUT $2" >&2
        done
        exit $EXITCODE`;
    auto pp = pipeProcess([prog.path, "bar", "baz"]);
    pp.stdin.writeln("foo");
    pp.stdin.flush();
    assert(pp.stdout.readln().chomp() == "foo bar");
    assert(pp.stderr.readln().chomp().stripRight() == "foo baz");
    pp.stdin.writeln("1234567890");
    pp.stdin.flush();
    assert(pp.stdout.readln().chomp() == "1234567890 bar");
    assert(pp.stderr.readln().chomp().stripRight() == "1234567890 baz");
    pp.stdin.writeln("stop");
    pp.stdin.flush();
    assert(wait(pp.pid) == 2);

    pp = pipeProcess([prog.path, "12345", "67890"],
                     Redirect.stdin | Redirect.stdout | Redirect.stderrToStdout);
    pp.stdin.writeln("xyz");
    pp.stdin.flush();
    assert(pp.stdout.readln().chomp() == "xyz 12345");
    assert(pp.stdout.readln().chomp().stripRight() == "xyz 67890");
    pp.stdin.writeln("stop");
    pp.stdin.flush();
    assert(wait(pp.pid) == 1);

    pp = pipeShell(escapeShellCommand(prog.path, "AAAAA", "BBB"),
                   Redirect.stdin | Redirect.stdoutToStderr | Redirect.stderr);
    pp.stdin.writeln("ab");
    pp.stdin.flush();
    assert(pp.stderr.readln().chomp() == "ab AAAAA");
    assert(pp.stderr.readln().chomp().stripRight() == "ab BBB");
    pp.stdin.writeln("stop");
    pp.stdin.flush();
    assert(wait(pp.pid) == 1);
}

@system unittest
{
    import std.exception : assertThrown;
    TestScript prog = "exit 0";
    assertThrown!StdioException(pipeProcess(
        prog.path,
        Redirect.stdout | Redirect.stdoutToStderr));
    assertThrown!StdioException(pipeProcess(
        prog.path,
        Redirect.stderr | Redirect.stderrToStdout));
    auto p = pipeProcess(prog.path, Redirect.stdin);
    assertThrown!Error(p.stdout);
    assertThrown!Error(p.stderr);
    wait(p.pid);
    p = pipeProcess(prog.path, Redirect.stderr);
    assertThrown!Error(p.stdin);
    assertThrown!Error(p.stdout);
    wait(p.pid);
}

/**
Object which contains $(REF File, std,stdio) handles that allow communication
with a child process through its standard streams.
*/
struct ProcessPipes
{
    /// The $(LREF Pid) of the child process.
    @property Pid pid() @safe nothrow
    {
        return _pid;
    }

    /**
    An $(REF File, std,stdio) that allows writing to the child process'
    standard input stream.

    Throws:
    $(OBJECTREF Error) if the child process' standard input stream hasn't
    been redirected.
    */
    @property File stdin() @safe nothrow
    {
        if ((_redirectFlags & Redirect.stdin) == 0)
            throw new Error("Child process' standard input stream hasn't "
                            ~"been redirected.");
        return _stdin;
    }

    /**
    An $(REF File, std,stdio) that allows reading from the child process'
    standard output stream.

    Throws:
    $(OBJECTREF Error) if the child process' standard output stream hasn't
    been redirected.
    */
    @property File stdout() @safe nothrow
    {
        if ((_redirectFlags & Redirect.stdout) == 0)
            throw new Error("Child process' standard output stream hasn't "
                            ~"been redirected.");
        return _stdout;
    }

    /**
    An $(REF File, std,stdio) that allows reading from the child process'
    standard error stream.

    Throws:
    $(OBJECTREF Error) if the child process' standard error stream hasn't
    been redirected.
    */
    @property File stderr() @safe nothrow
    {
        if ((_redirectFlags & Redirect.stderr) == 0)
            throw new Error("Child process' standard error stream hasn't "
                            ~"been redirected.");
        return _stderr;
    }

private:
    Redirect _redirectFlags;
    Pid _pid;
    File _stdin, _stdout, _stderr;
}



/**
Executes the given program or shell command and returns its exit
code and output.

`execute` and `executeShell` start a new process using
$(LREF spawnProcess) and $(LREF spawnShell), respectively, and wait
for the process to complete before returning.  The functions capture
what the child process prints to both its standard output and
standard error streams, and return this together with its exit code.
---
auto dmd = execute(["dmd", "myapp.d"]);
if (dmd.status != 0) writeln("Compilation failed:\n", dmd.output);

auto ls = executeShell("ls -l");
if (ls.status != 0) writeln("Failed to retrieve file listing");
else writeln(ls.output);
---

The `args`/`program`/`command`, `env` and `config`
parameters are forwarded straight to the underlying spawn functions,
and we refer to their documentation for details.

Params:
args      = An array which contains the program name as the zeroth element
            and any command-line arguments in the following elements.
            (See $(LREF spawnProcess) for details.)
program   = The program name, $(I without) command-line arguments.
            (See $(LREF spawnProcess) for details.)
command   = A shell command which is passed verbatim to the command
            interpreter.  (See $(LREF spawnShell) for details.)
env       = Additional environment variables for the child process.
            (See $(LREF spawnProcess) for details.)
config    = Flags that control process creation. See $(LREF Config)
            for an overview of available flags, and note that the
            `retainStd...` flags have no effect in this function.
maxOutput = The maximum number of bytes of output that should be
            captured.
workDir   = The working directory for the new process.
            By default the child process inherits the parent's working
            directory.
shellPath = The path to the shell to use to run the specified program.
            By default this is $(LREF nativeShell).


Returns:
An $(D std.typecons.Tuple!(int, "status", string, "output")).

POSIX_specific:
If the process is terminated by a signal, the `status` field of
the return value will contain a negative number whose absolute
value is the signal number.  (See $(LREF wait) for details.)

Throws:
$(LREF ProcessException) on failure to start the process.$(BR)
$(REF StdioException, std,stdio) on failure to capture output.
*/
auto execute(scope const(char[])[] args,
             const string[string] env = null,
             Config config = Config.none,
             size_t maxOutput = size_t.max,
             scope const(char)[] workDir = null)
    @safe
{
    return executeImpl!pipeProcess(args, env, config, maxOutput, workDir);
}

/// ditto
auto execute(scope const(char)[] program,
             const string[string] env = null,
             Config config = Config.none,
             size_t maxOutput = size_t.max,
             scope const(char)[] workDir = null)
    @safe
{
    return executeImpl!pipeProcess(program, env, config, maxOutput, workDir);
}

/// ditto
auto executeShell(scope const(char)[] command,
                  const string[string] env = null,
                  Config config = Config.none,
                  size_t maxOutput = size_t.max,
                  scope const(char)[] workDir = null,
                  string shellPath = nativeShell)
    @safe
{
    return executeImpl!pipeShell(command,
                                 env,
                                 config,
                                 maxOutput,
                                 workDir,
                                 shellPath);
}

// Does the actual work for execute() and executeShell().
private auto executeImpl(alias pipeFunc, Cmd, ExtraPipeFuncArgs...)(
    Cmd commandLine,
    const string[string] env = null,
    Config config = Config.none,
    size_t maxOutput = size_t.max,
    scope const(char)[] workDir = null,
    ExtraPipeFuncArgs extraArgs = ExtraPipeFuncArgs.init)
    @trusted //TODO: @safe
{
    import std.algorithm.comparison : min;
    import std.array : appender;
    import std.typecons : Tuple;

    auto redirect = (config.flags & Config.Flags.stderrPassThrough)
        ? Redirect.stdout
        : Redirect.stdout | Redirect.stderrToStdout;

    auto p = pipeFunc(commandLine, redirect,
                      env, config, workDir, extraArgs);

    auto a = appender!string;
    enum size_t defaultChunkSize = 4096;
    immutable chunkSize = min(maxOutput, defaultChunkSize);

    // Store up to maxOutput bytes in a.
    foreach (ubyte[] chunk; p.stdout.byChunk(chunkSize))
    {
        immutable size_t remain = maxOutput - a.data.length;

        if (chunk.length < remain) a.put(chunk);
        else
        {
            a.put(chunk[0 .. remain]);
            break;
        }
    }
    // Exhaust the stream, if necessary.
    foreach (ubyte[] chunk; p.stdout.byChunk(defaultChunkSize)) { }

    return Tuple!(int, "status", string, "output")(wait(p.pid), a.data);
}

@system unittest
{
    import std.string;
    // To avoid printing the newline characters, we use the echo|set trick on
    // Windows, and printf on POSIX (neither echo -n nor echo \c are portable).
    version (Windows) TestScript prog =
       "echo|set /p=%~1
        echo|set /p=%~2 1>&2
        exit 123";
    else version (Android) TestScript prog =
       `echo -n $1
        echo -n $2 >&2
        exit 123`;
    else version (Posix) TestScript prog =
       `printf '%s' $1
        printf '%s' $2 >&2
        exit 123`;
    auto r = execute([prog.path, "foo", "bar"]);
    assert(r.status == 123);
    assert(r.output.stripRight() == "foobar");
    auto s = execute([prog.path, "Hello", "World"]);
    assert(s.status == 123);
    assert(s.output.stripRight() == "HelloWorld");
}

@safe unittest
{
    import std.string;
    auto r1 = executeShell("echo foo");
    assert(r1.status == 0);
    assert(r1.output.chomp() == "foo");
    auto r2 = executeShell("echo bar 1>&2");
    assert(r2.status == 0);
    assert(r2.output.chomp().stripRight() == "bar");
    auto r3 = executeShell("exit 123");
    assert(r3.status == 123);
    assert(r3.output.empty);
}

@system unittest
{
    // Temporarily disable output to stderr so as to not spam the build log.
    import std.stdio : stderr;
    import std.typecons : Tuple;
    import std.file : readText, exists, remove;
    import std.traits : ReturnType;

    ReturnType!executeShell r;
    auto tmpname = uniqueTempPath;
    scope(exit) if (exists(tmpname)) remove(tmpname);
    auto t = stderr;
    // Open a new scope to minimize code ran with stderr redirected.
    {
        stderr.open(tmpname, "w");
        scope(exit) stderr = t;
        r = executeShell("echo D rox>&2", null, Config.stderrPassThrough);
    }
    assert(r.status == 0);
    assert(r.output.empty);
    auto witness = readText(tmpname);
    import std.ascii : newline;
    assert(witness == "D rox" ~ newline, "'" ~ witness ~ "'");
}

@safe unittest
{
    import std.typecons : Tuple;
    void foo() //Just test the compilation
    {
        auto ret1 = execute(["dummy", "arg"]);
        auto ret2 = executeShell("dummy arg");
        static assert(is(typeof(ret1) == typeof(ret2)));

        Tuple!(int, string) ret3 = execute(["dummy", "arg"]);
    }
}

/// An exception that signals a problem with starting or waiting for a process.
class ProcessException : Exception
{
    import std.exception : basicExceptionCtors;
    mixin basicExceptionCtors;

    // Creates a new ProcessException based on errno.
    static ProcessException newFromErrno(string customMsg = null,
                                         string file = __FILE__,
                                         size_t line = __LINE__)
    {
        import core.stdc.errno : errno;
        return newFromErrno(errno, customMsg, file, line);
    }

    // ditto, but error number is provided by caller
    static ProcessException newFromErrno(int error,
                                         string customMsg = null,
                                         string file = __FILE__,
                                         size_t line = __LINE__)
    {
        import std.exception : errnoString;
        auto errnoMsg = errnoString(error);
        auto msg = customMsg.empty ? errnoMsg
                                   : customMsg ~ " (" ~ errnoMsg ~ ')';
        return new ProcessException(msg, file, line);
    }

    // Creates a new ProcessException based on GetLastError() (Windows only).
    version (Windows)
    static ProcessException newFromLastError(string customMsg = null,
                                             string file = __FILE__,
                                             size_t line = __LINE__)
    {
        auto lastMsg = generateSysErrorMsg();
        auto msg = customMsg.empty ? lastMsg
                                   : customMsg ~ " (" ~ lastMsg ~ ')';
        return new ProcessException(msg, file, line);
    }
}


/**
Determines the path to the current user's preferred command interpreter.

On Windows, this function returns the contents of the COMSPEC environment
variable, if it exists.  Otherwise, it returns the result of $(LREF nativeShell).

On POSIX, `userShell` returns the contents of the SHELL environment
variable, if it exists and is non-empty.  Otherwise, it returns the result of
$(LREF nativeShell).
*/
@property string userShell() @safe
{
    version (Windows)      return environment.get("COMSPEC", nativeShell);
    else version (Posix)   return environment.get("SHELL", nativeShell);
}

/**
The platform-specific native shell path.

This function returns `"cmd.exe"` on Windows, `"/bin/sh"` on POSIX, and
`"/system/bin/sh"` on Android.
*/
@property string nativeShell() @safe @nogc pure nothrow
{
    version (Windows)      return "cmd.exe";
    else version (Android) return "/system/bin/sh";
    else version (Posix)   return "/bin/sh";
}

// A command-line switch that indicates to the shell that it should
// interpret the following argument as a command to be executed.
version (Posix)   private immutable string shellSwitch = "-c";
version (Windows) private immutable string shellSwitch = "/C";

// Unittest support code:  TestScript takes a string that contains a
// shell script for the current platform, and writes it to a temporary
// file. On Windows the file name gets a .cmd extension, while on
// POSIX its executable permission bit is set.  The file is
// automatically deleted when the object goes out of scope.
version (StdUnittest)
private struct TestScript
{
    this(string code) @system
    {
        // @system due to chmod
        import std.ascii : newline;
        import std.file : write;
        version (Windows)
        {
            auto ext = ".cmd";
            auto firstLine = "@echo off";
        }
        else version (Posix)
        {
            auto ext = "";
            auto firstLine = "#!" ~ nativeShell;
        }
        path = uniqueTempPath()~ext;
        write(path, firstLine ~ newline ~ code ~ newline);
        version (Posix)
        {
            import core.sys.posix.sys.stat : chmod;
            import std.conv : octal;
            chmod(path.tempCString(), octal!777);
        }
    }

    ~this()
    {
        import std.file : remove, exists;
        if (!path.empty && exists(path))
        {
            try { remove(path); }
            catch (Exception e)
            {
                debug std.stdio.stderr.writeln(e.msg);
            }
        }
    }

    string path;
}


// =============================================================================
// Functions for shell command quoting/escaping.
// =============================================================================


/*
    Command line arguments exist in three forms:
    1) string or char* array, as received by main.
       Also used internally on POSIX systems.
    2) Command line string, as used in Windows'
       CreateProcess and CommandLineToArgvW functions.
       A specific quoting and escaping algorithm is used
       to distinguish individual arguments.
    3) Shell command string, as written at a shell prompt
       or passed to cmd /C - this one may contain shell
       control characters, e.g. > or | for redirection /
       piping - thus, yet another layer of escaping is
       used to distinguish them from program arguments.

    Except for escapeWindowsArgument, the intermediary
    format (2) is hidden away from the user in this module.
*/

/**
Escapes an argv-style argument array to be used with $(LREF spawnShell),
$(LREF pipeShell) or $(LREF executeShell).
---
string url = "http://dlang.org/";
executeShell(escapeShellCommand("wget", url, "-O", "dlang-index.html"));
---

Concatenate multiple `escapeShellCommand` and
$(LREF escapeShellFileName) results to use shell redirection or
piping operators.
---
executeShell(
    escapeShellCommand("curl", "http://dlang.org/download.html") ~
    "|" ~
    escapeShellCommand("grep", "-o", `http://\S*\.zip`) ~
    ">" ~
    escapeShellFileName("D download links.txt"));
---

Throws:
$(OBJECTREF Exception) if any part of the command line contains unescapable
characters (NUL on all platforms, as well as CR and LF on Windows).
*/
string escapeShellCommand(scope const(char[])[] args...) @safe pure
{
    if (args.empty)
        return null;
    version (Windows)
    {
        // Do not ^-escape the first argument (the program path),
        // as the shell parses it differently from parameters.
        // ^-escaping a program path that contains spaces will fail.
        string result = escapeShellFileName(args[0]);
        if (args.length > 1)
        {
            result ~= " " ~ escapeShellCommandString(
                escapeShellArguments(args[1..$]));
        }
        return result;
    }
    version (Posix)
    {
        return escapeShellCommandString(escapeShellArguments(args));
    }
}

@safe unittest
{
    // This is a simple unit test without any special requirements,
    // in addition to the unittest_burnin one below which requires
    // special preparation.

    struct TestVector { string[] args; string windows, posix; }
    TestVector[] tests =
    [
        {
            args    : ["foo bar"],
            windows : `"foo bar"`,
            posix   : `'foo bar'`
        },
        {
            args    : ["foo bar", "hello"],
            windows : `"foo bar" hello`,
            posix   : `'foo bar' hello`
        },
        {
            args    : ["foo bar", "hello world"],
            windows : `"foo bar" ^"hello world^"`,
            posix   : `'foo bar' 'hello world'`
        },
        {
            args    : ["foo bar", "hello", "world"],
            windows : `"foo bar" hello world`,
            posix   : `'foo bar' hello world`
        },
        {
            args    : ["foo bar", `'"^\`],
            windows : `"foo bar" ^"'\^"^^\\^"`,
            posix   : `'foo bar' ''\''"^\'`
        },
        {
            args    : ["foo bar", ""],
            windows : `"foo bar" ^"^"`,
            posix   : `'foo bar' ''`
        },
        {
            args    : ["foo bar", "2"],
            windows : `"foo bar" ^"2^"`,
            posix   : `'foo bar' '2'`
        },
    ];

    foreach (test; tests)
    {
        auto actual = escapeShellCommand(test.args);
        version (Windows)
            string expected = test.windows;
        else
            string expected = test.posix;
        assert(actual == expected, "\nExpected: " ~ expected ~ "\nGot: " ~ actual);
    }
}

private string escapeShellCommandString(return scope string command) @safe pure
{
    version (Windows)
        return escapeWindowsShellCommand(command);
    else
        return command;
}

private string escapeWindowsShellCommand(scope const(char)[] command) @safe pure
{
    import std.array : appender;
    auto result = appender!string();
    result.reserve(command.length);

    foreach (c; command)
        switch (c)
        {
            case '\0':
                throw new Exception("Cannot put NUL in command line");
            case '\r':
            case '\n':
                throw new Exception("CR/LF are not escapable");
            case '\x01': .. case '\x09':
            case '\x0B': .. case '\x0C':
            case '\x0E': .. case '\x1F':
            case '"':
            case '^':
            case '&':
            case '<':
            case '>':
            case '|':
                result.put('^');
                goto default;
            default:
                result.put(c);
        }
    return result.data;
}

private string escapeShellArguments(scope const(char[])[] args...)
    @trusted pure nothrow
{
    import std.exception : assumeUnique;
    char[] buf;

    @safe nothrow
    char[] allocator(size_t size)
    {
        if (buf.length == 0)
            return buf = new char[size];
        else
        {
            auto p = buf.length;
            buf.length = buf.length + 1 + size;
            buf[p++] = ' ';
            return buf[p .. p+size];
        }
    }

    foreach (arg; args)
        escapeShellArgument!allocator(arg);
    return assumeUnique(buf);
}

private auto escapeShellArgument(alias allocator)(scope const(char)[] arg) @safe nothrow
{
    // The unittest for this function requires special
    // preparation - see below.

    version (Windows)
        return escapeWindowsArgumentImpl!allocator(arg);
    else
        return escapePosixArgumentImpl!allocator(arg);
}

/**
Quotes a command-line argument in a manner conforming to the behavior of
$(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx,
CommandLineToArgvW).
*/
string escapeWindowsArgument(scope const(char)[] arg) @trusted pure nothrow
{
    // Rationale for leaving this function as public:
    // this algorithm of escaping paths is also used in other software,
    // e.g. DMD's response files.
    import std.exception : assumeUnique;
    auto buf = escapeWindowsArgumentImpl!charAllocator(arg);
    return assumeUnique(buf);
}


private char[] charAllocator(size_t size) @safe pure nothrow
{
    return new char[size];
}


private char[] escapeWindowsArgumentImpl(alias allocator)(scope const(char)[] arg)
    @safe nothrow
if (is(typeof(allocator(size_t.init)[0] = char.init)))
{
    // References:
    // * http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx
    // * http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx

    // Check if the string needs to be escaped,
    // and calculate the total string size.

    // Trailing backslashes must be escaped
    bool escaping = true;
    bool needEscape = false;
    // Result size = input size + 2 for surrounding quotes + 1 for the
    // backslash for each escaped character.
    size_t size = 1 + arg.length + 1;

    foreach_reverse (char c; arg)
    {
        if (c == '"')
        {
            needEscape = true;
            escaping = true;
            size++;
        }
        else
        if (c == '\\')
        {
            if (escaping)
                size++;
        }
        else
        {
            if (c == ' ' || c == '\t')
                needEscape = true;
            escaping = false;
        }
    }

    import std.ascii : isDigit;
    // Empty arguments need to be specified as ""
    if (!arg.length)
        needEscape = true;
    else
    // Arguments ending with digits need to be escaped,
    // to disambiguate with 1>file redirection syntax
    if (isDigit(arg[$-1]))
        needEscape = true;

    if (!needEscape)
        return allocator(arg.length)[] = arg;

    // Construct result string.

    auto buf = allocator(size);
    size_t p = size;
    buf[--p] = '"';
    escaping = true;
    foreach_reverse (char c; arg)
    {
        if (c == '"')
            escaping = true;
        else
        if (c != '\\')
            escaping = false;

        buf[--p] = c;
        if (escaping)
            buf[--p] = '\\';
    }
    buf[--p] = '"';
    assert(p == 0);

    return buf;
}

version (Windows) version (StdUnittest)
{
private:
    import core.stdc.stddef;
    import core.stdc.wchar_ : wcslen;
    import core.sys.windows.shellapi : CommandLineToArgvW;
    import core.sys.windows.winbase;
    import core.sys.windows.winnt;
    import std.array;

    string[] parseCommandLine(string line)
    {
        import std.algorithm.iteration : map;
        import std.array : array;
        import std.conv : to;
        auto lpCommandLine = (to!(WCHAR[])(line) ~ '\0').ptr;
        int numArgs;
        auto args = CommandLineToArgvW(lpCommandLine, &numArgs);
        scope(exit) LocalFree(args);
        return args[0 .. numArgs]
            .map!(arg => to!string(arg[0 .. wcslen(arg)]))
            .array();
    }

    @system unittest
    {
        import std.conv : text;
        string[] testStrings = [
            `Hello`,
            `Hello, world`,
            `Hello, "world"`,
            `C:\`,
            `C:\dmd`,
            `C:\Program Files\`,
        ];

        enum CHARS = `_x\" *&^` ~ "\t"; // _ is placeholder for nothing
        foreach (c1; CHARS)
        foreach (c2; CHARS)
        foreach (c3; CHARS)
        foreach (c4; CHARS)
            testStrings ~= [c1, c2, c3, c4].replace("_", "");

        foreach (s; testStrings)
        {
            auto q = escapeWindowsArgument(s);
            auto args = parseCommandLine("Dummy.exe " ~ q);
            assert(args.length == 2, s ~ " => " ~ q ~ " #" ~ text(args.length-1));
            assert(args[1] == s, s ~ " => " ~ q ~ " => " ~ args[1]);
        }
    }
}

private string escapePosixArgument(scope const(char)[] arg) @trusted pure nothrow
{
    import std.exception : assumeUnique;
    auto buf = escapePosixArgumentImpl!charAllocator(arg);
    return assumeUnique(buf);
}

private char[] escapePosixArgumentImpl(alias allocator)(scope const(char)[] arg)
    @safe nothrow
if (is(typeof(allocator(size_t.init)[0] = char.init)))
{
    bool needQuoting = {
        import std.ascii : isAlphaNum, isDigit;
        import std.algorithm.comparison : among;

        // Empty arguments need to be specified as ''
        if (arg.length == 0)
            return true;
        // Arguments ending with digits need to be escaped,
        // to disambiguate with 1>file redirection syntax
        if (isDigit(arg[$-1]))
            return true;

        // Obtained using:
        // for n in $(seq 1 255) ; do
        //     c=$(printf \\$(printf "%o" $n))
        //     q=$(/bin/printf '%q' "$c")
        //     if [[ "$q" == "$c" ]] ; then printf "%s, " "'$c'" ; fi
        // done
        // printf '\n'
        foreach (char c; arg)
            if (!isAlphaNum(c) && !c.among('%', '+', ',', '-', '.', '/', ':', '@', ']', '_'))
                return true;
        return false;
    }();
    if (!needQuoting)
    {
        auto buf = allocator(arg.length);
        buf[] = arg;
        return buf;
    }

    // '\'' means: close quoted part of argument, append an escaped
    // single quote, and reopen quotes

    // Below code is equivalent to:
    // return `'` ~ std.array.replace(arg, `'`, `'\''`) ~ `'`;

    size_t size = 1 + arg.length + 1;
    foreach (char c; arg)
        if (c == '\'')
            size += 3;

    auto buf = allocator(size);
    size_t p = 0;
    buf[p++] = '\'';
    foreach (char c; arg)
        if (c == '\'')
        {
            buf[p .. p+4] = `'\''`;
            p += 4;
        }
        else
            buf[p++] = c;
    buf[p++] = '\'';
    assert(p == size);

    return buf;
}

/**
Escapes a filename to be used for shell redirection with $(LREF spawnShell),
$(LREF pipeShell) or $(LREF executeShell).
*/
string escapeShellFileName(scope const(char)[] fileName) @trusted pure nothrow
{
    // The unittest for this function requires special
    // preparation - see below.

    version (Windows)
    {
        // If a file starts with &, it can cause cmd.exe to misinterpret
        // the file name as the stream redirection syntax:
        //     command > "&foo.txt"
        // gets interpreted as
        //     command >&foo.txt
        // Prepend .\ to disambiguate.

        if (fileName.length && fileName[0] == '&')
            return cast(string)(`".\` ~ fileName ~ '"');

        return cast(string)('"' ~ fileName ~ '"');
    }
    else
        return escapePosixArgument(fileName);
}

// Loop generating strings with random characters
//version = unittest_burnin;

version (unittest_burnin)
@system unittest
{
    // There are no readily-available commands on all platforms suitable
    // for properly testing command escaping. The behavior of CMD's "echo"
    // built-in differs from the POSIX program, and Windows ports of POSIX
    // environments (Cygwin, msys, gnuwin32) may interfere with their own
    // "echo" ports.

    // To run this unit test, create std_process_unittest_helper.d with the
    // following content and compile it:
    // import std.stdio, std.array; void main(string[] args) { write(args.join("\0")); }
    // Then, test this module with:
    // rdmd --main -unittest -version=unittest_burnin process.d

    import std.file : readText, remove;
    import std.format : format;
    import std.path : absolutePath;
    import std.random : uniform;

    auto helper = absolutePath("std_process_unittest_helper");
    assert(executeShell(helper ~ " hello").output.split("\0")[1..$] == ["hello"], "Helper malfunction");

    void test(string[] s, string fn)
    {
        string e;
        string[] g;

        e = escapeShellCommand(helper ~ s);
        {
            scope(failure) writefln("executeShell() failed.\nExpected:\t%s\nEncoded:\t%s", s, [e]);
            auto result = executeShell(e);
            assert(result.status == 0, "std_process_unittest_helper failed");
            g = result.output.split("\0")[1..$];
        }
        assert(s == g, format("executeShell() test failed.\nExpected:\t%s\nGot:\t\t%s\nEncoded:\t%s", s, g, [e]));

        e = escapeShellCommand(helper ~ s) ~ ">" ~ escapeShellFileName(fn);
        {
            scope(failure) writefln(
                "executeShell() with redirect failed.\nExpected:\t%s\nFilename:\t%s\nEncoded:\t%s", s, [fn], [e]);
            auto result = executeShell(e);
            assert(result.status == 0, "std_process_unittest_helper failed");
            assert(!result.output.length, "No output expected, got:\n" ~ result.output);
            g = readText(fn).split("\0")[1..$];
        }
        remove(fn);
        assert(s == g,
            format("executeShell() with redirect test failed.\nExpected:\t%s\nGot:\t\t%s\nEncoded:\t%s", s, g, [e]));
    }

    while (true)
    {
        string[] args;
        foreach (n; 0 .. uniform(1, 4))
        {
            string arg;
            foreach (l; 0 .. uniform(0, 10))
            {
                dchar c;
                while (true)
                {
                    version (Windows)
                    {
                        // As long as DMD's system() uses CreateProcessA,
                        // we can't reliably pass Unicode
                        c = uniform(0, 128);
                    }
                    else
                        c = uniform!ubyte();

                    if (c == 0)
                        continue; // argv-strings are zero-terminated
                    version (Windows)
                        if (c == '\r' || c == '\n')
                            continue; // newlines are unescapable on Windows
                    break;
                }
                arg ~= c;
            }
            args ~= arg;
        }

        // generate filename
        string fn;
        foreach (l; 0 .. uniform(1, 10))
        {
            dchar c;
            while (true)
            {
                version (Windows)
                    c = uniform(0, 128); // as above
                else
                    c = uniform!ubyte();

                if (c == 0 || c == '/')
                    continue; // NUL and / are the only characters
                              // forbidden in POSIX filenames
                version (Windows)
                    if (c < '\x20' || c == '<' || c == '>' || c == ':' ||
                        c == '"' || c == '\\' || c == '|' || c == '?' || c == '*')
                        continue; // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx
                break;
            }

            fn ~= c;
        }
        fn = fn[0..$/2] ~ "_testfile_" ~ fn[$/2..$];

        test(args, fn);
    }
}

// =============================================================================
// Everything below this line was part of the old std.process, and most of
// it will be deprecated and removed.
// =============================================================================


/*
Copyright: Copyright The D Language Foundation 2007 - 2009.
License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
Authors:   $(HTTP digitalmars.com, Walter Bright),
           $(HTTP erdani.org, Andrei Alexandrescu),
           $(HTTP thecybershadow.net, Vladimir Panteleev)
Source:    $(PHOBOSSRC std/_process.d)
*/
/*
         Copyright The D Language Foundation 2007 - 2009.
Distributed under the Boost Software License, Version 1.0.
   (See accompanying file LICENSE_1_0.txt or copy at
         http://www.boost.org/LICENSE_1_0.txt)
*/


import core.stdc.errno;
import core.stdc.stdlib;
import core.stdc.string;
import core.thread;

version (Windows)
{
    import std.file, std.format, std.random;
}
version (Posix)
{
    import core.sys.posix.stdlib;
}

private const(char)** toAStringz(in string[] a)
{
    import std.string : toStringz;
    auto p = (new const(char)*[1 + a.length]).ptr;
    foreach (i, string s; a)
        p[i] = toStringz(s);
    p[a.length] = null;
    return p;
}


/* ========================================================== */

//version (Windows)
//{
//    int spawnvp(int mode, string pathname, string[] argv)
//    {
//      char** argv_ = cast(char**) core.stdc.stdlib.malloc((char*).sizeof * (1 + argv.length));
//      scope(exit) core.stdc.stdlib.free(argv_);
//
//      toAStringz(argv, argv_);
//
//      return spawnvp(mode, pathname.tempCString(), argv_);
//    }
//}

// Incorporating idea (for spawnvp() on Posix) from Dave Fladebo

enum { _P_WAIT, _P_NOWAIT, _P_OVERLAY }
version (Windows) extern(C) int spawnvp(int, scope const(char) *, scope const(char*)*);
alias P_WAIT = _P_WAIT;
alias P_NOWAIT = _P_NOWAIT;

/* ========================================================== */

version (StdDdoc)
{
    /**
    Replaces the current process by executing a command, `pathname`, with
    the arguments in `argv`.

    $(BLUE This function is Posix-Only.)

    Typically, the first element of `argv` is
    the command being executed, i.e. $(D argv[0] == pathname). The 'p'
    versions of `exec` search the PATH environment variable for $(D
    pathname). The 'e' versions additionally take the new process'
    environment variables as an array of strings of the form key=value.

    Does not return on success (the current process will have been
    replaced). Returns -1 on failure with no indication of the
    underlying error.

    Windows_specific:
    These functions are only supported on POSIX platforms, as the Windows
    operating systems do not provide the ability to overwrite the current
    process image with another. In single-threaded programs it is possible
    to approximate the effect of `execv*` by using $(LREF spawnProcess)
    and terminating the current process once the child process has returned.
    For example:
    ---
    auto commandLine = [ "program", "arg1", "arg2" ];
    version (Posix)
    {
        execv(commandLine[0], commandLine);
        throw new Exception("Failed to execute program");
    }
    else version (Windows)
    {
        import core.stdc.stdlib : _Exit;
        _Exit(wait(spawnProcess(commandLine)));
    }
    ---
    This is, however, NOT equivalent to POSIX' `execv*`.  For one thing, the
    executed program is started as a separate process, with all this entails.
    Secondly, in a multithreaded program, other threads will continue to do
    work while the current thread is waiting for the child process to complete.

    A better option may sometimes be to terminate the current program immediately
    after spawning the child process.  This is the behaviour exhibited by the
    $(LINK2 http://msdn.microsoft.com/en-us/library/431x4c1w.aspx,`__exec`)
    functions in Microsoft's C runtime library, and it is how D's now-deprecated
    Windows `execv*` functions work. Example:
    ---
    auto commandLine = [ "program", "arg1", "arg2" ];
    version (Posix)
    {
        execv(commandLine[0], commandLine);
        throw new Exception("Failed to execute program");
    }
    else version (Windows)
    {
        spawnProcess(commandLine);
        import core.stdc.stdlib : _exit;
        _exit(0);
    }
    ---
    */
    int execv(in string pathname, in string[] argv);
    ///ditto
    int execve(in string pathname, in string[] argv, in string[] envp);
    /// ditto
    int execvp(in string pathname, in string[] argv);
    /// ditto
    int execvpe(in string pathname, in string[] argv, in string[] envp);
}
else version (Posix)
{
    int execv(in string pathname, in string[] argv)
    {
        return execv_(pathname, argv);
    }
    int execve(in string pathname, in string[] argv, in string[] envp)
    {
        return execve_(pathname, argv, envp);
    }
    int execvp(in string pathname, in string[] argv)
    {
        return execvp_(pathname, argv);
    }
    int execvpe(in string pathname, in string[] argv, in string[] envp)
    {
        return execvpe_(pathname, argv, envp);
    }
}

// Move these C declarations to druntime if we decide to keep the D wrappers
extern(C)
{
    int execv(scope const(char) *, scope const(char *)*);
    int execve(scope const(char)*, scope const(char*)*, scope const(char*)*);
    int execvp(scope const(char)*, scope const(char*)*);
    version (Windows) int execvpe(scope const(char)*, scope const(char*)*, scope const(char*)*);
}

private int execv_(in string pathname, in string[] argv)
{
    return execv(pathname.tempCString(), toAStringz(argv));
}

private int execve_(in string pathname, in string[] argv, in string[] envp)
{
    return execve(pathname.tempCString(), toAStringz(argv), toAStringz(envp));
}

private int execvp_(in string pathname, in string[] argv)
{
    return execvp(pathname.tempCString(), toAStringz(argv));
}

private int execvpe_(in string pathname, in string[] argv, in string[] envp)
{
version (Posix)
{
    import std.array : split;
    import std.conv : to;
    // Is pathname rooted?
    if (pathname[0] == '/')
    {
        // Yes, so just call execve()
        return execve(pathname, argv, envp);
    }
    else
    {
        // No, so must traverse PATHs, looking for first match
        string[]    envPaths    =   split(
            to!string(core.stdc.stdlib.getenv("PATH")), ":");
        int         iRet        =   0;

        // Note: if any call to execve() succeeds, this process will cease
        // execution, so there's no need to check the execve() result through
        // the loop.

        foreach (string pathDir; envPaths)
        {
            string  composite   =  cast(string) (pathDir ~ "/" ~ pathname);

            iRet = execve(composite, argv, envp);
        }
        if (0 != iRet)
        {
            iRet = execve(pathname, argv, envp);
        }

        return iRet;
    }
}
else version (Windows)
{
    return execvpe(pathname.tempCString(), toAStringz(argv), toAStringz(envp));
}
else
{
    static assert(0);
} // version
}

version (StdDdoc)
{
    /****************************************
     * Start up the browser and set it to viewing the page at url.
     */
    void browse(scope const(char)[] url);
}
else
version (Windows)
{
    import core.sys.windows.shellapi, core.sys.windows.winuser;

    pragma(lib,"shell32.lib");

    void browse(scope const(char)[] url) nothrow @nogc @trusted
    {
        ShellExecuteW(null, "open", url.tempCStringW(), null, null, SW_SHOWNORMAL);
    }
}
else version (Posix)
{
    import core.stdc.stdio;
    import core.stdc.string;
    import core.sys.posix.unistd;

    void browse(scope const(char)[] url) nothrow @nogc @safe
    {
        const buffer = url.tempCString(); // Retain buffer until end of scope
        const(char)*[3] args;

        // Trusted because it's called with a zero-terminated literal
        const(char)* browser = (() @trusted => core.stdc.stdlib.getenv("BROWSER"))();
        if (browser)
        {
            // String already zero-terminated
            browser = (() @trusted => strdup(browser))();
            args[0] = browser;
        }
        else
        {
            version (OSX)
            {
                args[0] = "open";
            }
            else
            {
                //args[0] = "x-www-browser";  // doesn't work on some systems
                args[0] = "xdg-open";
            }
        }

        args[1] = buffer;
        args[2] = null;

        auto childpid = core.sys.posix.unistd.fork();
        if (childpid == 0)
        {
            // Trusted because args and all entries are always zero-terminated
            (() @trusted {
                core.sys.posix.unistd.execvp(args[0], &args[0]);
                perror(args[0]);
                core.sys.posix.unistd._exit(1);
            })();
            assert(0, "Child failed to exec");
        }
        if (browser)
            // Trusted because it's allocated via strdup above
            (() @trusted => free(cast(void*) browser))();

        version (StdUnittest)
        {
            // Verify that the test script actually suceeds
            int status;
            const check = (() @trusted => waitpid(childpid, &status, 0))();
            assert(check != -1);
            assert(status == 0);
        }
    }
}
else
    static assert(0, "os not supported");

// Verify attributes are consistent between all implementations
@safe @nogc nothrow unittest
{
    if (false)
        browse("");
}

version (Windows) { /* Doesn't use BROWSER */ }
else
@system unittest
{
    import std.conv : text;
    import std.range : repeat;
    immutable string url = text("http://", repeat('x', 249));

    TestScript prog = `if [ "$1" != "` ~ url ~ `" ]; then exit 1; fi`;
    environment["BROWSER"] = prog.path;
    browse(url);
}
