From 28666d167aa8e602c0bea25ebc4d51b55005db13 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 28 Mar 2017 18:05:19 +0200 Subject: Simplify Unix implementation of QProcess::start{Process|Detached} Use QStandardPaths::findExecutable instead of duplicated implementations. Change-Id: Ia944f1d343d8c215fc2b6e78dae6b2bfffbba688 Reviewed-by: Thiago Macieira --- src/corelib/io/qprocess_p.h | 2 +- src/corelib/io/qprocess_unix.cpp | 91 ++++++++++++---------------------------- 2 files changed, 28 insertions(+), 65 deletions(-) (limited to 'src/corelib/io') diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 9c4a2d8e1b..80ac631290 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -353,7 +353,7 @@ public: void start(QIODevice::OpenMode mode); void startProcess(); #if defined(Q_OS_UNIX) - void execChild(const char *workingDirectory, char **path, char **argv, char **envp); + void execChild(const char *workingDirectory, char **argv, char **envp); #endif bool processStarted(QString *errorMessage = Q_NULLPTR); void terminateProcess(); diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index dcbdebd4aa..047a8ddc11 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -87,6 +87,7 @@ QT_END_NAMESPACE #include "qprocess.h" #include "qprocess_p.h" +#include "qstandardpaths.h" #include "private/qcore_unix_p.h" #ifdef Q_OS_MAC @@ -420,8 +421,16 @@ void QProcessPrivate::startProcess() #endif // Add the program name to the argument list. - char *dupProgramName = ::strdup(encodedProgramName.constData()); - argv[0] = dupProgramName; + argv[0] = nullptr; + if (!program.contains(QLatin1Char('/'))) { + const QString &exeFilePath = QStandardPaths::findExecutable(program); + if (!exeFilePath.isEmpty()) { + const QByteArray &tmp = QFile::encodeName(exeFilePath); + argv[0] = ::strdup(tmp.constData()); + } + } + if (!argv[0]) + argv[0] = ::strdup(encodedProgramName.constData()); // Add every argument to the list for (int i = 0; i < arguments.count(); ++i) @@ -443,29 +452,6 @@ void QProcessPrivate::startProcess() workingDirPtr = encodedWorkingDirectory.constData(); } - // If the program does not specify a path, generate a list of possible - // locations for the binary using the PATH environment variable. - char **path = 0; - int pathc = 0; - if (!program.contains(QLatin1Char('/'))) { - const QString pathEnv = QString::fromLocal8Bit(qgetenv("PATH")); - if (!pathEnv.isEmpty()) { - QStringList pathEntries = pathEnv.split(QLatin1Char(':'), QString::SkipEmptyParts); - if (!pathEntries.isEmpty()) { - pathc = pathEntries.size(); - path = new char *[pathc + 1]; - path[pathc] = 0; - - for (int k = 0; k < pathEntries.size(); ++k) { - QByteArray tmp = QFile::encodeName(pathEntries.at(k)); - if (!tmp.endsWith('/')) tmp += '/'; - tmp += encodedProgramName; - path[k] = ::strdup(tmp.constData()); - } - } - } - } - // Start the process manager, and fork off the child process. pid_t childPid; forkfd = ::forkfd(FFD_CLOEXEC, &childPid); @@ -473,16 +459,12 @@ void QProcessPrivate::startProcess() if (forkfd != FFD_CHILD_PROCESS) { // Parent process. // Clean up duplicated memory. - free(dupProgramName); - for (int i = 1; i <= arguments.count(); ++i) + for (int i = 0; i <= arguments.count(); ++i) free(argv[i]); for (int i = 0; i < envc; ++i) free(envp[i]); - for (int i = 0; i < pathc; ++i) - free(path[i]); delete [] argv; delete [] envp; - delete [] path; } // On QNX, if spawnChild failed, childPid will be -1 but forkfd is still 0. @@ -503,7 +485,7 @@ void QProcessPrivate::startProcess() // Start the child. if (forkfd == FFD_CHILD_PROCESS) { - execChild(workingDirPtr, path, argv, envp); + execChild(workingDirPtr, argv, envp); ::_exit(-1); } @@ -544,7 +526,7 @@ void QProcessPrivate::startProcess() } } -void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv, char **envp) +void QProcessPrivate::execChild(const char *workingDir, char **argv, char **envp) { ::signal(SIGPIPE, SIG_DFL); // reset the signal that we ignored @@ -567,7 +549,7 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv } } - // make sure this fd is closed if execvp() succeeds + // make sure this fd is closed if execv() succeeds qt_safe_close(childStartedPipe[0]); // enter the working directory @@ -582,25 +564,13 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv // execute the process if (!envp) { - qt_safe_execvp(argv[0], argv); - callthatfailed = "execvp: "; + qt_safe_execv(argv[0], argv); + callthatfailed = "execv: "; } else { - if (path) { - char **arg = path; - while (*arg) { - argv[0] = *arg; #if defined (QPROCESS_DEBUG) - fprintf(stderr, "QProcessPrivate::execChild() searching / starting %s\n", argv[0]); + fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]); #endif - qt_safe_execve(argv[0], argv, envp); - ++arg; - } - } else { -#if defined (QPROCESS_DEBUG) - fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]); -#endif - qt_safe_execve(argv[0], argv, envp); - } + qt_safe_execve(argv[0], argv, envp); callthatfailed = "execve: "; } @@ -967,23 +937,16 @@ bool QProcessPrivate::startDetached(qint64 *pid) argv[i + 1] = ::strdup(QFile::encodeName(arguments.at(i)).constData()); argv[arguments.size() + 1] = 0; + QByteArray tmp; if (!program.contains(QLatin1Char('/'))) { - const QString path = QString::fromLocal8Bit(qgetenv("PATH")); - if (!path.isEmpty()) { - QStringList pathEntries = path.split(QLatin1Char(':')); - for (int k = 0; k < pathEntries.size(); ++k) { - QByteArray tmp = QFile::encodeName(pathEntries.at(k)); - if (!tmp.endsWith('/')) tmp += '/'; - tmp += QFile::encodeName(program); - argv[0] = tmp.data(); - qt_safe_execv(argv[0], argv); - } - } - } else { - QByteArray tmp = QFile::encodeName(program); - argv[0] = tmp.data(); - qt_safe_execv(argv[0], argv); + const QString &exeFilePath = QStandardPaths::findExecutable(program); + if (!exeFilePath.isEmpty()) + tmp = QFile::encodeName(exeFilePath); } + if (tmp.isEmpty()) + tmp = QFile::encodeName(program); + argv[0] = tmp.data(); + qt_safe_execv(argv[0], argv); struct sigaction noaction; memset(&noaction, 0, sizeof(noaction)); -- cgit v1.2.3