• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

kprocess.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of the KDE libraries
00003 
00004     Copyright (C) 2007 Oswald Buddenhagen <ossi@kde.org>
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to
00018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019     Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include "kprocess_p.h"
00023 
00024 #include <kstandarddirs.h>
00025 #include <kshell.h>
00026 #ifdef Q_OS_WIN
00027 # include <kshell_p.h>
00028 #endif
00029 
00030 #include <qfile.h>
00031 
00032 #ifdef Q_OS_WIN
00033 # include <windows.h>
00034 #else
00035 # include <unistd.h>
00036 # include <errno.h>
00037 #endif
00038 
00039 #ifndef Q_OS_WIN
00040 # define STD_OUTPUT_HANDLE 1
00041 # define STD_ERROR_HANDLE 2
00042 #endif
00043 
00044 void KProcessPrivate::writeAll(const QByteArray &buf, int fd)
00045 {
00046 #ifdef Q_OS_WIN
00047     HANDLE h = GetStdHandle(fd);
00048     if (h) {
00049         DWORD wr;
00050         WriteFile(h, buf.data(), buf.size(), &wr, 0);
00051     }
00052 #else
00053     int off = 0;
00054     do {
00055         int ret = ::write(fd, buf.data() + off, buf.size() - off);
00056         if (ret < 0) {
00057             if (errno != EINTR)
00058                 return;
00059         } else {
00060             off += ret;
00061         }
00062     } while (off < buf.size());
00063 #endif
00064 }
00065 
00066 void KProcessPrivate::forwardStd(KProcess::ProcessChannel good, int fd)
00067 {
00068     Q_Q(KProcess);
00069 
00070     QProcess::ProcessChannel oc = q->readChannel();
00071     q->setReadChannel(good);
00072     writeAll(q->readAll(), fd);
00073     q->setReadChannel(oc);
00074 }
00075 
00076 void KProcessPrivate::_k_forwardStdout()
00077 {
00078     forwardStd(KProcess::StandardOutput, STD_OUTPUT_HANDLE);
00079 }
00080 
00081 void KProcessPrivate::_k_forwardStderr()
00082 {
00083     forwardStd(KProcess::StandardError, STD_ERROR_HANDLE);
00084 }
00085 
00087 // public member functions //
00089 
00090 KProcess::KProcess(QObject *parent) :
00091     QProcess(parent),
00092     d_ptr(new KProcessPrivate)
00093 {
00094     d_ptr->q_ptr = this;
00095     setOutputChannelMode(ForwardedChannels);
00096 }
00097 
00098 KProcess::KProcess(KProcessPrivate *d, QObject *parent) :
00099     QProcess(parent),
00100     d_ptr(d)
00101 {
00102     d_ptr->q_ptr = this;
00103     setOutputChannelMode(ForwardedChannels);
00104 }
00105 
00106 KProcess::~KProcess()
00107 {
00108     delete d_ptr;
00109 }
00110 
00111 void KProcess::setOutputChannelMode(OutputChannelMode mode)
00112 {
00113     Q_D(KProcess);
00114 
00115     d->outputChannelMode = mode;
00116     disconnect(this, SIGNAL(readyReadStandardOutput()));
00117     disconnect(this, SIGNAL(readyReadStandardError()));
00118     switch (mode) {
00119     case OnlyStdoutChannel:
00120         connect(this, SIGNAL(readyReadStandardError()), SLOT(_k_forwardStderr()));
00121         break;
00122     case OnlyStderrChannel:
00123         connect(this, SIGNAL(readyReadStandardOutput()), SLOT(_k_forwardStdout()));
00124         break;
00125     default:
00126         QProcess::setProcessChannelMode((ProcessChannelMode)mode);
00127         return;
00128     }
00129     QProcess::setProcessChannelMode(QProcess::SeparateChannels);
00130 }
00131 
00132 KProcess::OutputChannelMode KProcess::outputChannelMode() const
00133 {
00134     Q_D(const KProcess);
00135 
00136     return d->outputChannelMode;
00137 }
00138 
00139 void KProcess::setNextOpenMode(QIODevice::OpenMode mode)
00140 {
00141     Q_D(KProcess);
00142 
00143     d->openMode = mode;
00144 }
00145 
00146 #define DUMMYENV "_KPROCESS_DUMMY_="
00147 
00148 void KProcess::clearEnvironment()
00149 {
00150     setEnvironment(QStringList() << QString::fromLatin1(DUMMYENV));
00151 }
00152 
00153 void KProcess::setEnv(const QString &name, const QString &value, bool overwrite)
00154 {
00155     QStringList env = environment();
00156     if (env.isEmpty()) {
00157         env = systemEnvironment();
00158         env.removeAll(QString::fromLatin1(DUMMYENV));
00159     }
00160     QString fname(name);
00161     fname.append('=');
00162     for (QStringList::Iterator it = env.begin(); it != env.end(); ++it)
00163         if ((*it).startsWith(fname)) {
00164             if (overwrite) {
00165                 *it = fname.append(value);
00166                 setEnvironment(env);
00167             }
00168             return;
00169         }
00170     env.append(fname.append(value));
00171     setEnvironment(env);
00172 }
00173 
00174 void KProcess::unsetEnv(const QString &name)
00175 {
00176     QStringList env = environment();
00177     if (env.isEmpty()) {
00178         env = systemEnvironment();
00179         env.removeAll(QString::fromLatin1(DUMMYENV));
00180     }
00181     QString fname(name);
00182     fname.append('=');
00183     for (QStringList::Iterator it = env.begin(); it != env.end(); ++it)
00184         if ((*it).startsWith(fname)) {
00185             env.erase(it);
00186             if (env.isEmpty())
00187                 env.append(DUMMYENV);
00188             setEnvironment(env);
00189             return;
00190         }
00191 }
00192 
00193 void KProcess::setProgram(const QString &exe, const QStringList &args)
00194 {
00195     Q_D(KProcess);
00196 
00197     d->prog = exe;
00198     d->args = args;
00199 }
00200 
00201 void KProcess::setProgram(const QStringList &argv)
00202 {
00203     Q_D(KProcess);
00204 
00205     Q_ASSERT( !argv.isEmpty() );
00206     d->args = argv;
00207     d->prog = d->args.takeFirst();
00208 }
00209 
00210 KProcess &KProcess::operator<<(const QString &arg)
00211 {
00212     Q_D(KProcess);
00213 
00214     if (d->prog.isEmpty())
00215         d->prog = arg;
00216     else
00217         d->args << arg;
00218     return *this;
00219 }
00220 
00221 KProcess &KProcess::operator<<(const QStringList &args)
00222 {
00223     Q_D(KProcess);
00224 
00225     if (d->prog.isEmpty())
00226         setProgram(args);
00227     else
00228         d->args << args;
00229     return *this;
00230 }
00231 
00232 void KProcess::clearProgram()
00233 {
00234     Q_D(KProcess);
00235 
00236     d->prog.clear();
00237     d->args.clear();
00238 }
00239 
00240 void KProcess::setShellCommand(const QString &cmd)
00241 {
00242     Q_D(KProcess);
00243 
00244     KShell::Errors err;
00245     d->args = KShell::splitArgs(
00246             cmd, KShell::AbortOnMeta | KShell::TildeExpand, &err);
00247     if (err == KShell::NoError && !d->args.isEmpty()) {
00248         d->prog = KStandardDirs::findExe(d->args[0]);
00249         if (!d->prog.isEmpty()) {
00250             d->args.removeFirst();
00251             return;
00252         }
00253     }
00254 
00255     d->args.clear();
00256 
00257 #ifdef Q_OS_UNIX
00258 // #ifdef NON_FREE // ... as they ship non-POSIX /bin/sh
00259 # if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) && !defined(__GNU__)
00260     // If /bin/sh is a symlink, we can be pretty sure that it points to a
00261     // POSIX shell - the original bourne shell is about the only non-POSIX
00262     // shell still in use and it is always installed natively as /bin/sh.
00263     d->prog = QFile::symLinkTarget(QString::fromLatin1("/bin/sh"));
00264     if (d->prog.isEmpty()) {
00265         // Try some known POSIX shells.
00266         d->prog = KStandardDirs::findExe("ksh");
00267         if (d->prog.isEmpty()) {
00268             d->prog = KStandardDirs::findExe("ash");
00269             if (d->prog.isEmpty()) {
00270                 d->prog = KStandardDirs::findExe("bash");
00271                 if (d->prog.isEmpty()) {
00272                     d->prog = KStandardDirs::findExe("zsh");
00273                     if (d->prog.isEmpty())
00274                         // We're pretty much screwed, to be honest ...
00275                         d->prog = QString::fromLatin1("/bin/sh");
00276                 }
00277             }
00278         }
00279     }
00280 # else
00281     d->prog = QString::fromLatin1("/bin/sh");
00282 # endif
00283 
00284     d->args << "-c" << cmd;
00285 #else // Q_OS_UNIX
00286     // KMacroExpander::expandMacrosShellQuote(), KShell::quoteArg() and
00287     // KShell::joinArgs() may generate these for security reasons.
00288     setEnv(PERCENT_VARIABLE, "%");
00289 
00290     //see also TrollTechTaskTracker entry 88373.
00291     d->prog = KStandardDirs::findExe("kcmdwrapper");
00292 
00293     UINT size;
00294     WCHAR sysdir[MAX_PATH + 1];
00295     size = GetSystemDirectoryW(sysdir, MAX_PATH + 1);
00296     QString cmdexe = QString::fromUtf16((const ushort *) sysdir, size);
00297     cmdexe.append("\\cmd.exe");
00298 
00299     d->args << cmdexe << cmd;
00300 #endif
00301 }
00302 
00303 QStringList KProcess::program() const
00304 {
00305     Q_D(const KProcess);
00306 
00307     QStringList argv = d->args;
00308     argv.prepend(d->prog);
00309     return argv;
00310 }
00311 
00312 void KProcess::start()
00313 {
00314     Q_D(KProcess);
00315 
00316     QProcess::start(d->prog, d->args, d->openMode);
00317 }
00318 
00319 int KProcess::execute(int msecs)
00320 {
00321     start();
00322     if (!waitForFinished(msecs)) {
00323         kill();
00324         waitForFinished(-1);
00325         return -2;
00326     }
00327     return (exitStatus() == QProcess::NormalExit) ? exitCode() : -1;
00328 }
00329 
00330 // static
00331 int KProcess::execute(const QString &exe, const QStringList &args, int msecs)
00332 {
00333     KProcess p;
00334     p.setProgram(exe, args);
00335     return p.execute(msecs);
00336 }
00337 
00338 // static
00339 int KProcess::execute(const QStringList &argv, int msecs)
00340 {
00341     KProcess p;
00342     p.setProgram(argv);
00343     return p.execute(msecs);
00344 }
00345 
00346 int KProcess::startDetached()
00347 {
00348     Q_D(KProcess);
00349 
00350     qint64 pid;
00351     if (!QProcess::startDetached(d->prog, d->args, workingDirectory(), &pid))
00352         return 0;
00353     return (int) pid;
00354 }
00355 
00356 // static
00357 int KProcess::startDetached(const QString &exe, const QStringList &args)
00358 {
00359     qint64 pid;
00360     if (!QProcess::startDetached(exe, args, QString(), &pid))
00361         return 0;
00362     return (int) pid;
00363 }
00364 
00365 // static
00366 int KProcess::startDetached(const QStringList &argv)
00367 {
00368     QStringList args = argv;
00369     QString prog = args.takeFirst();
00370     return startDetached(prog, args);
00371 }
00372 
00373 int KProcess::pid() const
00374 {
00375 #ifdef Q_OS_UNIX
00376     return (int) QProcess::pid();
00377 #else
00378     return QProcess::pid() ? QProcess::pid()->dwProcessId : 0;
00379 #endif
00380 }
00381 
00382 #include "kprocess.moc"

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal