summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qprocess.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2008-11-25 15:44:11 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2009-08-21 13:03:05 (GMT)
commit02ef8fab7e511f50e901676eac15229eb456b01c (patch)
tree107d58effefa02942f3a715b8b60894852aee83d /src/corelib/io/qprocess.cpp
parentf13908359f08d856c2825988e65651dbf744c0e4 (diff)
downloadQt-02ef8fab7e511f50e901676eac15229eb456b01c.zip
Qt-02ef8fab7e511f50e901676eac15229eb456b01c.tar.gz
Qt-02ef8fab7e511f50e901676eac15229eb456b01c.tar.bz2
Add a new class for handling a process's environment variables.
First of all, make it a lot easier to access individual variables by having them in an associative container (a QHash). This fixes task 232427, albeit one release later than I had originally planned. On Windows, the variable names in the environment are case-insensitive, so a direct QHash isn't a good solution. Implement code that does the uppercasing on Windows and leaves untransformed on other platforms. Since we're doing this anyways, use QByteArray on Unix systems, since, in theory, the environment could contain any random binary data, which is not representable in QString. Task-number: 232427
Diffstat (limited to 'src/corelib/io/qprocess.cpp')
-rw-r--r--src/corelib/io/qprocess.cpp242
1 files changed, 189 insertions, 53 deletions
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index ccc16b2..3d143e9 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -101,27 +101,169 @@ QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
-static QHash<QString, QString> environmentHashFromList(const QStringList &environment)
+#ifdef Q_OS_WIN
+static inline QProcessEnvironmentPrivate::Unit prepareName(const QString &name)
+{ return name.toUpper(); }
+static inline QProcessEnvironmentPrivate::Unit prepareName(const QByteArray &name)
+{ return QString::fromLocal8Bit(name).toUpper(); }
+static inline QString nameToString(const QProcessEnvironmentPrivate::Unit &name)
+{ return name; }
+static inline QProcessEnvironmentPrivate::Unit prepareValue(const QString &value)
+{ return value; }
+static inline QProcessEnvironmentPrivate::Unit prepareValue(const QByteArray &value)
+{ return QString::fromLocal8Bit(value); }
+static inline QString valueToString(const QProcessEnvironmentPrivate::Unit &value)
+{ return value; }
+static inline QByteArray valueToByteArray(const QProcessEnvironmentPrivate::Unit &value)
+{ return value.toLocal8Bit(); }
+#else
+static inline QProcessEnvironmentPrivate::Unit prepareName(const QByteArray &name)
+{ return name; }
+static inline QProcessEnvironmentPrivate::Unit prepareName(const QString &name)
+{ return name.toLocal8Bit(); }
+static inline QString nameToString(const QProcessEnvironmentPrivate::Unit &name)
+{ return QString::fromLocal8Bit(name); }
+static inline QProcessEnvironmentPrivate::Unit prepareValue(const QByteArray &value)
+{ return value; }
+static inline QProcessEnvironmentPrivate::Unit prepareValue(const QString &value)
+{ return value.toLocal8Bit(); }
+static inline QString valueToString(const QProcessEnvironmentPrivate::Unit &value)
+{ return QString::fromLocal8Bit(value); }
+static inline QByteArray valueToByteArray(const QProcessEnvironmentPrivate::Unit &value)
+{ return value; }
+#endif
+
+template<> void QSharedDataPointer<QProcessEnvironmentPrivate>::detach()
{
- QHash<QString, QString> result;
- QStringList::ConstIterator it = environment.constBegin(),
- end = environment.constEnd();
+ if (d && d->ref == 1)
+ return;
+ QProcessEnvironmentPrivate *x = (d ? new QProcessEnvironmentPrivate(*d)
+ : new QProcessEnvironmentPrivate);
+ x->ref.ref();
+ if (d && !d->ref.deref())
+ delete d;
+ d = x;
+}
+
+QStringList QProcessEnvironmentPrivate::toList() const
+{
+ QStringList result;
+ QHash<Unit, Unit>::ConstIterator it = hash.constBegin(),
+ end = hash.constEnd();
for ( ; it != end; ++it) {
- int equals = it->indexOf(QLatin1Char('='));
+ QString data = nameToString(it.key());
+ QString value = valueToString(it.value());
+ data.reserve(data.length() + value.length() + 1);
+ data.append(QLatin1Char('='));
+ data.append(value);
+ result << data;
+ }
+ return result;
+}
+
+QProcessEnvironment QProcessEnvironmentPrivate::fromList(const QStringList &list)
+{
+ QProcessEnvironment env;
+ QStringList::ConstIterator it = list.constBegin(),
+ end = list.constEnd();
+ for ( ; it != end; ++it) {
+ int pos = it->indexOf(QLatin1Char('='));
+ if (pos < 1)
+ continue;
+ QString value = it->mid(pos + 1);
QString name = *it;
- QString value;
- if (equals != -1) {
- name.truncate(equals);
-#ifdef Q_OS_WIN
- name = name.toUpper();
-#endif
- value = it->mid(equals + 1);
- }
- result.insert(name, value);
+ name.truncate(pos);
+ env.insert(name, value);
}
+ return env;
+}
- return result;
+QProcessEnvironment::QProcessEnvironment()
+ : d(0)
+{
+}
+
+QProcessEnvironment::~QProcessEnvironment()
+{
+}
+
+QProcessEnvironment::QProcessEnvironment(const QProcessEnvironment &other)
+ : d(other.d)
+{
+}
+
+QProcessEnvironment &QProcessEnvironment::operator=(const QProcessEnvironment &other)
+{
+ d = other.d;
+ return *this;
+}
+
+bool QProcessEnvironment::operator==(const QProcessEnvironment &other) const
+{
+ return d->hash == other.d->hash;
+}
+
+bool QProcessEnvironment::isEmpty() const
+{
+ return d ? d->hash.isEmpty() : true;
+}
+
+void QProcessEnvironment::clear()
+{
+ d->hash.clear();
+}
+
+bool QProcessEnvironment::contains(const QString &name) const
+{
+ return d ? d->hash.contains(prepareName(name)) : false;
+}
+
+void QProcessEnvironment::insert(const QString &name, const QString &value)
+{
+ d->hash.insert(prepareName(name), prepareValue(value));
+}
+
+void QProcessEnvironment::remove(const QString &name)
+{
+ d->hash.remove(prepareName(name));
+}
+
+QString QProcessEnvironment::value(const QString &name, const QString &defaultValue) const
+{
+ if (!d)
+ return defaultValue;
+
+ QProcessEnvironmentPrivate::Unit result = d->hash.value(prepareName(name), prepareValue(defaultValue));
+ return valueToString(result);
+}
+
+bool QProcessEnvironment::containsRaw(const QByteArray &name) const
+{
+ return d ? d->hash.contains(prepareName(name)) : false;
+}
+
+void QProcessEnvironment::insertRaw(const QByteArray &name, const QByteArray &value)
+{
+ d->hash.insert(prepareName(name), prepareValue(value));
+}
+
+void QProcessEnvironment::removeRaw(const QByteArray &name)
+{
+ d->hash.remove(prepareName(name));
+}
+
+QByteArray QProcessEnvironment::valueRaw(const QByteArray &name, const QByteArray &defaultValue) const
+{
+ if (!d)
+ return defaultValue;
+ QProcessEnvironmentPrivate::Unit result = d->hash.value(prepareName(name), prepareValue(defaultValue));
+ return valueToByteArray(result);
+}
+
+QStringList QProcessEnvironment::toStringList() const
+{
+ return d ? d->toList() : QStringList();
}
void QProcessPrivate::Channel::clear()
@@ -446,7 +588,6 @@ QProcessPrivate::QProcessPrivate()
sequenceNumber = 0;
exitCode = 0;
exitStatus = QProcess::NormalExit;
- environment = 0;
startupSocketNotifier = 0;
deathNotifier = 0;
notifier = 0;
@@ -473,7 +614,6 @@ QProcessPrivate::QProcessPrivate()
*/
QProcessPrivate::~QProcessPrivate()
{
- delete environment;
if (stdinChannel.process)
stdinChannel.process->stdoutChannel.clear();
if (stdoutChannel.process)
@@ -1215,6 +1355,7 @@ QProcess::ProcessState QProcess::state() const
}
/*!
+ \deprecated
Sets the environment that QProcess will use when starting a process to the
\a environment specified which consists of a list of key=value pairs.
@@ -1223,14 +1364,15 @@ QProcess::ProcessState QProcess::state() const
\snippet doc/src/snippets/qprocess-environment/main.cpp 0
- \sa environment(), systemEnvironment(), setEnvironmentHash()
+ \sa environment(), setProcessEnvironment(), systemEnvironment()
*/
void QProcess::setEnvironment(const QStringList &environment)
{
- setEnvironmentHash(environmentHashFromList(environment));
+ setProcessEnvironment(QProcessEnvironmentPrivate::fromList(environment));
}
/*!
+ \deprecated
Returns the environment that QProcess will use when starting a
process, or an empty QStringList if no environment has been set
using setEnvironment() or setEnvironmentHash(). If no environment
@@ -1239,67 +1381,50 @@ void QProcess::setEnvironment(const QStringList &environment)
\note The environment settings are ignored on Windows CE,
as there is no concept of an environment.
- \sa environmentHash(), setEnvironment(), systemEnvironment()
+ \sa processEnvironment(), setEnvironment(), systemEnvironment()
*/
QStringList QProcess::environment() const
{
Q_D(const QProcess);
-
- QStringList result;
- if (!d->environment)
- return result;
-
- QHash<QString, QString>::ConstIterator it = d->environment->constBegin(),
- end = d->environment->constEnd();
- for ( ; it != end; ++it) {
- QString data = it.key();
- data.reserve(data.length() + it.value().length() + 1);
- data.append(QLatin1Char('='));
- data.append(it.value());
- result << data;
- }
- return result;
+ return d->environment.toStringList();
}
/*!
\since 4.5
Sets the environment that QProcess will use when starting a process to the
- \a environment hash map.
+ \a environment object.
For example, the following code adds the \c{C:\\BIN} directory to the list of
executable paths (\c{PATHS}) on Windows and sets \c{TMPDIR}:
\snippet doc/src/snippets/qprocess-environment/main.cpp 1
- \sa environment(), systemEnvironmentHash(), setEnvironment()
+ Note how, on Windows, environment variable names are case-insensitive.
+
+ \sa processEnvironment(), QProcessEnvironment::systemEnvironment(), setEnvironment()
*/
-void QProcess::setEnvironmentHash(const QHash<QString, QString> &environment)
+void QProcess::setProcessEnvironment(const QProcessEnvironment &environment)
{
Q_D(QProcess);
- if (!d->environment)
- d->environment = new QHash<QString, QString>(environment);
- else
- *d->environment = environment;
+ d->environment = environment;
}
/*!
\since 4.5
Returns the environment that QProcess will use when starting a
- process, or an empty QHash if no environment has been set using
- setEnvironment() or setEnvironmentHash(). If no environment has
+ process, or an empty object if no environment has been set using
+ setEnvironment() or setProcessEnvironment(). If no environment has
been set, the environment of the calling process will be used.
\note The environment settings are ignored on Windows CE,
as there is no concept of an environment.
- \sa setEnvironmentHash(), setEnvironment(), systemEnvironmentHash()
+ \sa setProcessEnvironment(), setEnvironment(), QProcessEnvironment::isValid()
*/
-QHash<QString, QString> QProcess::environmentHash() const
+QProcessEnvironment QProcess::processEnvironment() const
{
Q_D(const QProcess);
- if (d->environment)
- return *d->environment;
- return QHash<QString, QString>();
+ return d->environment;
}
/*!
@@ -1898,7 +2023,7 @@ QT_END_INCLUDE_NAMESPACE
\snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 8
- \sa systemEnvironmentHash(), environment(), setEnvironment()
+ \sa QProcessEnvironment::systemEnvironment(), environment(), setEnvironment()
*/
QStringList QProcess::systemEnvironment()
{
@@ -1915,11 +2040,22 @@ QStringList QProcess::systemEnvironment()
Returns the environment of the calling process as a QHash.
- \sa systemEnvironment(), environmentHash(), setEnvironmentHash()
+ \sa QProcess::systemEnvironment()
*/
-QHash<QString, QString> QProcess::systemEnvironmentHash()
+QProcessEnvironment QProcessEnvironment::systemEnvironment()
{
- return environmentHashFromList(systemEnvironment());
+ QProcessEnvironment env;
+ 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.insertRaw(name, value);
+ }
+ return env;
}
/*!