ChildProcess quoted paths/parameters


#1

If you try and construct a File object with a quoted path it asserts…

Shouldn’t the constructor be:

File::File (const String& fullPathName)
    : fullPath (parseAbsolutePath (fullPathName.unquoted()))
{
}

Thanks,

Rail


#2

No, it's not the responsibility of the File object to know whether or not the quote characters should be there. If you're parsing user input as a filename then that's the point at which you'd want to remove quotes (if appropriate)


#3

Then you need to fix ChildProcess::ActiveProcess() to handle that the file path may be quoted to contain spaces in the path. There’s more to change than just the above – but I’m still figuring out the rest.

Rail


#4

This works…

    ActiveProcess (const StringArray& arguments, int streamFlags)
        : childPID (0), pipeHandle (0), readHandle (0)
    {
        // Looks like you're trying to launch a non-existent exe or a folder (perhaps on OSX
        // you're trying to launch the .app folder rather than the actual binary inside it?)

    /*
        jassert ((! arguments[0].containsChar ('/'))
                  || File::getCurrentWorkingDirectory().getChildFile (arguments[0]).existsAsFile());
    */

        Logger::writeToLog ("ChildProcess::ActiveProcess()");

        for (int i = 0; i < arguments.size(); ++i)
            Logger::writeToLog (String (i) + " " + arguments[i]);

        jassert (File (arguments[0].unquoted()).existsAsFile());

        int pipeHandles[2] = { 0 };

        if (pipe (pipeHandles) == 0)
        {
            const pid_t result = fork();

            if (result < 0)
            {
                close (pipeHandles[0]);
                close (pipeHandles[1]);
            }
            else if (result == 0)
            {
                Logger::writeToLog ("we're the child process");         // Never gets here in debug build

                // we're the child process..
                close (pipeHandles[0]);   // close the read handle

                if ((streamFlags & wantStdOut) != 0)
                    dup2 (pipeHandles[1], 1); // turns the pipe into stdout
                else
                    close (STDOUT_FILENO);

                if ((streamFlags & wantStdErr) != 0)
                    dup2 (pipeHandles[1], 2);
                else
                    close (STDERR_FILENO);

                close (pipeHandles[1]);

                Array<char*> argv;
                for (int i = 0; i < arguments.size(); ++i)
                    if (arguments[i].isNotEmpty())
                        argv.add (const_cast<char*> (arguments[i].toUTF8().getAddress()));

                argv.add (nullptr);

                // execvp (argv[0], argv.getRawDataPointer());  // original code

                if (execvp (arguments[0].unquoted().toRawUTF8(), argv.getRawDataPointer()) == -1)
                    {
                    // An error has occured

                    String szErr = strerror (errno);

                    Logger::writeToLog ("execvp() error: " + szErr);
                    }

                exit (-1);
            }
            else
            {
                Logger::writeToLog ("we're the parent process");

                // we're the parent process..
                childPID = result;
                pipeHandle = pipeHandles[0];
                close (pipeHandles[1]); // close the write handle
            }
        }
    }

The executable path is quoted and one of the parameters also has a quoted path.

This does fail if we keep your original asserts – so are those really required?

Rail


#5

Thanks Rail - am having a look at this now, will push something shortly..


#6

Thanks for the commit

Cheers,

Rail