diff options
author | axis <qt-info@nokia.com> | 2009-08-21 13:23:42 (GMT) |
---|---|---|
committer | axis <qt-info@nokia.com> | 2009-08-21 13:23:42 (GMT) |
commit | 044680951401487590c0ed554092dd9b7e0ee783 (patch) | |
tree | ed2492ad2fd49481148fdd7a1486cbf197c9bfe7 /src/corelib/io/qprocess.cpp | |
parent | ab1df6dea670a60bfef5efd81d6687f9534cfc5d (diff) | |
parent | 00ba962d428dcdff70fcde74a9e5cb316545cef6 (diff) | |
download | Qt-044680951401487590c0ed554092dd9b7e0ee783.zip Qt-044680951401487590c0ed554092dd9b7e0ee783.tar.gz Qt-044680951401487590c0ed554092dd9b7e0ee783.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt
Conflicts:
src/corelib/io/qprocess.h
Diffstat (limited to 'src/corelib/io/qprocess.cpp')
-rw-r--r-- | src/corelib/io/qprocess.cpp | 394 |
1 files changed, 337 insertions, 57 deletions
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 18ed676..057492d 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -101,27 +101,294 @@ QT_END_NAMESPACE QT_BEGIN_NAMESPACE -static QHash<QString, QString> environmentHashFromList(const QStringList &environment) +/*! + \class QProcessEnvironment + + \brief The QProcessEnvironment class holds the environment variables that + can be passed to a program. + + \ingroup io + \ingroup misc + \mainclass + \reentrant + \since 4.6 + + A process's environment is composed of a set of key=value pairs known as + environment variables. The QProcessEnvironment class wraps that concept + and allows easy manipulation of those variables. It's meant to be used + along with QProcess, to set the environment for child processes. It + cannot be used to change the current process's environment. + + The environment of the calling process can be obtained using + QProcessEnvironment::systemEnvironment(). + + On Unix systems, the variable names are case-sensitive. For that reason, + this class will not touch the names of the variables. Note as well that + Unix environment allows both variable names and contents to contain arbitrary + binary data (except for the NUL character), but this is not supported by + QProcessEnvironment. This class only supports names and values that are + encodable by the current locale settings (see QTextCodec::codecForLocale). + + On Windows, the variable names are case-insensitive. Therefore, + QProcessEnvironment will always uppercase the names and do case-insensitive + comparisons. + + On Windows CE, the concept of environment does not exist. This class will + keep the values set for compatibility with other platforms, but the values + set will have no effect on the processes being created. + + \sa QProcess, QProcess::systemEnvironment(), QProcess::setProcessEnvironment() +*/ +#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() +{ + 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 { - QHash<QString, QString> result; - QStringList::ConstIterator it = environment.constBegin(), - end = environment.constEnd(); + 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; +/*! + Creates a new QProcessEnvironment object. This constructor creates an + empty environment. If set on a QProcess, this will cause the current + environment variables to be removed. +*/ +QProcessEnvironment::QProcessEnvironment() + : d(0) +{ +} + +/*! + Frees the resources associated with this QProcessEnvironment object. +*/ +QProcessEnvironment::~QProcessEnvironment() +{ +} + +/*! + Creates a QProcessEnvironment object that is a copy of \a other. +*/ +QProcessEnvironment::QProcessEnvironment(const QProcessEnvironment &other) + : d(other.d) +{ +} + +/*! + Copies the contents of the \a other QProcessEnvironment object into this + one. +*/ +QProcessEnvironment &QProcessEnvironment::operator=(const QProcessEnvironment &other) +{ + d = other.d; + return *this; +} + +/*! + \fn bool QProcessEnvironment::operator !=(const QProcessEnvironment &other) const + + Returns true if this and the \a other QProcessEnvironment objects are different. + + \sa operator==() +*/ + +/*! + Returns true if this and the \a other QProcessEnvironment objects are equal. + + Two QProcessEnvironment objects are considered equal if they have the same + set of key=value pairs. The comparison of keys is done case-sensitive on + platforms where the environment is case-sensitive. + + \sa operator!=(), contains() +*/ +bool QProcessEnvironment::operator==(const QProcessEnvironment &other) const +{ + return d->hash == other.d->hash; +} + +/*! + Returns true if this QProcessEnvironment object is empty: that is + there are no key=value pairs set. + + \sa clear(), systemEnvironment(), insert() +*/ +bool QProcessEnvironment::isEmpty() const +{ + return d ? d->hash.isEmpty() : true; +} + +/*! + Removes all key=value pairs from this QProcessEnvironment object, making + it empty. + + \sa isEmpty(), systemEnvironment() +*/ +void QProcessEnvironment::clear() +{ + if (d) + d->hash.clear(); +} + +/*! + Returns true if the environment variable of name \a name is found in + this QProcessEnvironment object. + + On Windows, variable names are case-insensitive, so the key is converted + to uppercase before searching. On other systems, names are case-sensitive + so no trasformation is applied. + + \sa insert(), value() +*/ +bool QProcessEnvironment::contains(const QString &name) const +{ + return d ? d->hash.contains(prepareName(name)) : false; +} + +/*! + Inserts the environment variable of name \a name and contents \a value + into this QProcessEnvironment object. If that variable already existed, + it is replaced by the new value. + + On Windows, variable names are case-insensitive, so this function always + uppercases the variable name before inserting. On other systems, names + are case-sensitive, so no transformation is applied. + + On most systems, inserting a variable with no contents will have the + same effect for applications as if the variable had not been set at all. + However, to guarantee that there are no incompatibilities, to remove a + variable, please use the remove() function. + + \sa contains(), remove(), value() +*/ +void QProcessEnvironment::insert(const QString &name, const QString &value) +{ + d->hash.insert(prepareName(name), prepareValue(value)); +} + +/*! + Removes the environment variable identified by \a name from this + QProcessEnvironment object. If that variable did not exist before, + nothing happens. + + On Windows, variable names are case-insensitive, so the key is converted + to uppercase before searching. On other systems, names are case-sensitive + so no trasformation is applied. + + \sa contains(), insert(), value() +*/ +void QProcessEnvironment::remove(const QString &name) +{ + if (d) + d->hash.remove(prepareName(name)); +} + +/*! + Searches this QProcessEnvironment object for a variable identified by + \a name and returns its value. If the variable is not found in this object, + then \a defaultValue is returned instead. + + On Windows, variable names are case-insensitive, so the key is converted + to uppercase before searching. On other systems, names are case-sensitive + so no trasformation is applied. + + \sa contains(), insert(), remove() +*/ +QString QProcessEnvironment::value(const QString &name, const QString &defaultValue) const +{ + if (!d) + return defaultValue; + + QProcessEnvironmentPrivate::Hash::ConstIterator it = d->hash.constFind(prepareName(name)); + if (it == d->hash.constEnd()) + return defaultValue; + + return valueToString(it.value()); +} + +/*! + Converts this QProcessEnvironment object into a list of strings, one for + each environment variable that is set. The environment variable's name + and its value are separated by an equal character ('='). + + The QStringList contents returned by this function are suitable for use + with the QProcess::setEnvironment function. However, it is recommended + to use QProcess::setProcessEnvironment instead since that will avoid + unnecessary copying of the data. + + \sa systemEnvironment(), QProcess::systemEnvironment(), QProcess::environment(), + QProcess::setEnvironment() +*/ +QStringList QProcessEnvironment::toStringList() const +{ + return d ? d->toList() : QStringList(); } void QProcessPrivate::Channel::clear() @@ -451,7 +718,6 @@ QProcessPrivate::QProcessPrivate() sequenceNumber = 0; exitCode = 0; exitStatus = QProcess::NormalExit; - environment = 0; startupSocketNotifier = 0; deathNotifier = 0; notifier = 0; @@ -482,7 +748,6 @@ QProcessPrivate::QProcessPrivate() */ QProcessPrivate::~QProcessPrivate() { - delete environment; if (stdinChannel.process) stdinChannel.process->stdoutChannel.clear(); if (stdoutChannel.process) @@ -1235,6 +1500,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. @@ -1243,14 +1509,18 @@ QProcess::ProcessState QProcess::state() const \snippet doc/src/snippets/qprocess-environment/main.cpp 0 - \sa environment(), systemEnvironment(), setEnvironmentHash() + \note This function is less efficient than the setProcessEnvironment() + function. + + \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 @@ -1259,67 +1529,50 @@ void QProcess::setEnvironment(const QStringList &environment) \note The environment settings are ignored on Windows CE and Symbian, 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 + \since 4.6 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 + \since 4.6 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; } /*! @@ -1924,7 +2177,16 @@ QT_END_INCLUDE_NAMESPACE \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 8 - \sa systemEnvironmentHash(), environment(), setEnvironment() + This function does not cache the system environment. Therefore, it's + possible to obtain an updated version of the environment if low-level C + library functions like \tt setenv ot \tt putenv have been called. + + However, note that repeated calls to this function will recreate the + list of environment variables, which is a non-trivial operation. + + \note For new code, it is recommended to use QProcessEvironment::systemEnvironment() + + \sa QProcessEnvironment::systemEnvironment(), environment(), setEnvironment() */ QStringList QProcess::systemEnvironment() { @@ -1937,15 +2199,33 @@ QStringList QProcess::systemEnvironment() } /*! - \since 4.5 + \since 4.6 + + Returns the environment of the calling process as a QProcessEnvironment. - Returns the environment of the calling process as a QHash. + This function does not cache the system environment. Therefore, it's + possible to obtain an updated version of the environment if low-level C + library functions like \tt setenv ot \tt putenv have been called. - \sa systemEnvironment(), environmentHash(), setEnvironmentHash() + However, note that repeated calls to this function will recreate the + QProcessEnvironment object, which is a non-trivial operation. + + \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.insert(QString::fromLocal8Bit(name), QString::fromLocal8Bit(value)); + } + return env; } /*! |