Introduce a configure option for QProcessEnvironment

This decouples QProcess and QProcessEnvironment, since the latter may
actually be available on platforms where the former is not.

Change-Id: I3dc799ffdf94486b64143ed01a369897fff44a96
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Jake Petroules 2016-12-14 20:13:29 -08:00
parent 66c2b87547
commit b9f56751cb
7 changed files with 99 additions and 68 deletions

View File

@ -445,6 +445,13 @@
"condition": "!config.winrt && !config.uikit && !config.integrity && !config.vxworks",
"output": [ "publicFeature", "feature" ]
},
"processenvironment": {
"label": "QProcessEnvironment",
"purpose": "Provides a higher-level abstraction of environment variables.",
"section": "File I/O",
"condition": "!config.winrt && !config.uikit && !config.integrity && !config.vxworks",
"output": [ "publicFeature" ]
},
"temporaryfile": {
"label": "QTemporaryFile",
"purpose": "Provides an I/O device that operates on temporary files.",

View File

@ -99,7 +99,7 @@ QT_END_NAMESPACE
#include <private/qcore_unix_p.h>
#endif
#ifndef QT_NO_PROCESS
#if QT_CONFIG(processenvironment)
QT_BEGIN_NAMESPACE
@ -430,6 +430,10 @@ void QProcessEnvironment::insert(const QProcessEnvironment &e)
d->insert(*e.d);
}
#endif // QT_CONFIG(processenvironment)
#if QT_CONFIG(process)
void QProcessPrivate::Channel::clear()
{
switch (type) {

View File

@ -48,8 +48,9 @@
QT_BEGIN_NAMESPACE
class QProcessPrivate;
#ifndef QT_NO_PROCESS
#if QT_CONFIG(processenvironment)
#if !defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
typedef qint64 Q_PID;
@ -61,7 +62,6 @@ typedef struct _STARTUPINFOW Q_STARTUPINFO;
QT_BEGIN_NAMESPACE
#endif
class QProcessPrivate;
class QProcessEnvironmentPrivate;
class Q_CORE_EXPORT QProcessEnvironment
@ -105,6 +105,10 @@ private:
Q_DECLARE_SHARED(QProcessEnvironment)
#endif // QT_CONFIG(processenvironment)
#if QT_CONFIG(process)
class Q_CORE_EXPORT QProcess : public QIODevice
{
Q_OBJECT

View File

@ -70,8 +70,6 @@ typedef int Q_PIPE;
#define INVALID_Q_PIPE -1
#endif
#ifndef QT_NO_PROCESS
QT_BEGIN_NAMESPACE
class QSocketNotifier;
@ -80,6 +78,8 @@ class QWindowsPipeWriter;
class QWinEventNotifier;
class QTimer;
#if QT_CONFIG(processenvironment)
#ifdef Q_OS_WIN
class QProcEnvKey : public QString
{
@ -233,6 +233,10 @@ template<> Q_INLINE_TEMPLATE void QSharedDataPointer<QProcessEnvironmentPrivate>
d = x;
}
#endif // QT_CONFIG(processenvironment)
#if QT_CONFIG(process)
class QProcessPrivate : public QIODevicePrivate
{
public:
@ -386,8 +390,8 @@ public:
void setErrorAndEmit(QProcess::ProcessError error, const QString &description = QString());
};
QT_END_NAMESPACE
#endif // QT_NO_PROCESS
QT_END_NAMESPACE
#endif // QPROCESS_P_H

View File

@ -41,9 +41,7 @@
//#define QPROCESS_DEBUG
#include "qdebug.h"
#ifndef QT_NO_PROCESS
#if defined QPROCESS_DEBUG
#if QT_CONFIG(process) && defined(QPROCESS_DEBUG)
#include "private/qtools_p.h"
#include <ctype.h>
@ -114,10 +112,47 @@ QT_END_NAMESPACE
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#if QT_CONFIG(process)
#include <forkfd.h>
#endif
QT_BEGIN_NAMESPACE
#if QT_CONFIG(processenvironment)
QT_BEGIN_INCLUDE_NAMESPACE
#if defined(Q_OS_MACOS)
# include <crt_externs.h>
# define environ (*_NSGetEnviron())
#else
extern char **environ;
#endif
QT_END_INCLUDE_NAMESPACE
QProcessEnvironment QProcessEnvironment::systemEnvironment()
{
QProcessEnvironment env;
#if !defined(QT_PLATFORM_UIKIT)
const char *entry;
for (int count = 0; (entry = environ[count]); ++count) {
const char *equal = strchr(entry, '=');
if (!equal)
continue;
QByteArray name(entry, equal - entry);
QByteArray value(equal + 1);
env.d->hash.insert(QProcessEnvironmentPrivate::Key(name),
QProcessEnvironmentPrivate::Value(value));
}
#endif
return env;
}
#endif // QT_CONFIG(processenvironment)
#if QT_CONFIG(process)
// POSIX requires PIPE_BUF to be 512 or larger
// so we will use 512
static const int errorBufferMax = 512;
@ -310,34 +345,6 @@ bool QProcessPrivate::openChannel(Channel &channel)
}
}
QT_BEGIN_INCLUDE_NAMESPACE
#if defined(Q_OS_MACX)
# include <crt_externs.h>
# define environ (*_NSGetEnviron())
#else
extern char **environ;
#endif
QT_END_INCLUDE_NAMESPACE
QProcessEnvironment QProcessEnvironment::systemEnvironment()
{
QProcessEnvironment env;
#if !defined(QT_PLATFORM_UIKIT)
const char *entry;
for (int count = 0; (entry = environ[count]); ++count) {
const char *equal = strchr(entry, '=');
if (!equal)
continue;
QByteArray name(entry, equal - entry);
QByteArray value(equal + 1);
env.d->hash.insert(QProcessEnvironmentPrivate::Key(name),
QProcessEnvironmentPrivate::Value(value));
}
#endif
return env;
}
static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Hash &environment, int *envc)
{
*envc = 0;
@ -1044,6 +1051,6 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
return success;
}
QT_END_NAMESPACE
#endif // QT_NO_PROCESS
QT_END_NAMESPACE

View File

@ -38,6 +38,7 @@
**
****************************************************************************/
//#define QPROCESS_DEBUG
#include "qprocess.h"
#include "qprocess_p.h"
#include "qwindowspipereader_p.h"
@ -59,11 +60,35 @@
#define PIPE_REJECT_REMOTE_CLIENTS 0x08
#endif
#ifndef QT_NO_PROCESS
QT_BEGIN_NAMESPACE
//#define QPROCESS_DEBUG
#if QT_CONFIG(processenvironment)
QProcessEnvironment QProcessEnvironment::systemEnvironment()
{
QProcessEnvironment env;
// Calls to setenv() affect the low-level environment as well.
// This is not the case the other way round.
if (wchar_t *envStrings = GetEnvironmentStringsW()) {
for (const wchar_t *entry = envStrings; *entry; ) {
const int entryLen = int(wcslen(entry));
// + 1 to permit magic cmd variable names starting with =
if (const wchar_t *equal = wcschr(entry + 1, L'=')) {
int nameLen = equal - entry;
QString name = QString::fromWCharArray(entry, nameLen);
QString value = QString::fromWCharArray(equal + 1, entryLen - nameLen - 1);
env.d->hash.insert(QProcessEnvironmentPrivate::Key(name), value);
}
entry += entryLen + 1;
}
FreeEnvironmentStringsW(envStrings);
}
return env;
}
#endif // QT_CONFIG(processenvironment)
#if QT_CONFIG(process)
static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe)
{
@ -369,28 +394,6 @@ static QString qt_create_commandline(const QString &program, const QStringList &
return args;
}
QProcessEnvironment QProcessEnvironment::systemEnvironment()
{
QProcessEnvironment env;
// Calls to setenv() affect the low-level environment as well.
// This is not the case the other way round.
if (wchar_t *envStrings = GetEnvironmentStringsW()) {
for (const wchar_t *entry = envStrings; *entry; ) {
const int entryLen = int(wcslen(entry));
// + 1 to permit magic cmd variable names starting with =
if (const wchar_t *equal = wcschr(entry + 1, L'=')) {
int nameLen = equal - entry;
QString name = QString::fromWCharArray(entry, nameLen);
QString value = QString::fromWCharArray(equal + 1, entryLen - nameLen - 1);
env.d->hash.insert(QProcessEnvironmentPrivate::Key(name), value);
}
entry += entryLen + 1;
}
FreeEnvironmentStringsW(envStrings);
}
return env;
}
static QByteArray qt_create_environment(const QProcessEnvironmentPrivate::Hash &environment)
{
QByteArray envlist;
@ -891,6 +894,6 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
return success;
}
QT_END_NAMESPACE
#endif // QT_NO_PROCESS
QT_END_NAMESPACE

View File

@ -59,9 +59,11 @@ SUBDIRS=\
win32:!qtConfig(private_tests): SUBDIRS -= \
qfilesystementry
!qtConfig(processenvironment): SUBDIRS -= \
qprocessenvironment
winrt: SUBDIRS -= \
qprocess \
qprocess-noapplication \
qprocessenvironment \
qstorageinfo \
qwinoverlappedionotifier