• Skip to content
  • Skip to link menu
KDE 4.1 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 #ifdef Q_OS_WIN
00026 # include <kshell_p.h>
00027 #endif
00028 
00029 #include <qfile.h>
00030 
00031 #ifdef Q_OS_WIN
00032 # include <windows.h>
00033 #else
00034 # include <unistd.h>
00035 # include <errno.h>
00036 #endif
00037 
00038 #ifndef Q_OS_WIN
00039 # define STD_OUTPUT_HANDLE 1
00040 # define STD_ERROR_HANDLE 2
00041 #endif
00042 
00043 void KProcessPrivate::writeAll(const QByteArray &buf, int fd)
00044 {
00045 #ifdef Q_OS_WIN
00046     HANDLE h = GetStdHandle(fd);
00047     if (h) {
00048         DWORD wr;
00049         WriteFile(h, buf.data(), buf.size(), &wr, 0);
00050     }
00051 #else
00052     int off = 0;
00053     do {
00054         int ret = ::write(fd, buf.data() + off, buf.size() - off);
00055         if (ret < 0) {
00056             if (errno != EINTR)
00057                 return;
00058         } else {
00059             off += ret;
00060         }
00061     } while (off < buf.size());
00062 #endif
00063 }
00064 
00065 void KProcessPrivate::forwardStd(KProcess::ProcessChannel good, int fd)
00066 {
00067     Q_Q(KProcess);
00068 
00069     QProcess::ProcessChannel oc = q->readChannel();
00070     q->setReadChannel(good);
00071     writeAll(q->readAll(), fd);
00072     q->setReadChannel(oc);
00073 }
00074 
00075 void KProcessPrivate::_k_forwardStdout()
00076 {
00077     forwardStd(KProcess::StandardOutput, STD_OUTPUT_HANDLE);
00078 }
00079 
00080 void KProcessPrivate::_k_forwardStderr()
00081 {
00082     forwardStd(KProcess::StandardError, STD_ERROR_HANDLE);
00083 }
00084 
00086 // public member functions //
00088 
00089 KProcess::KProcess(QObject *parent) :
00090     QProcess(parent),
00091     d_ptr(new KProcessPrivate)
00092 {
00093     d_ptr->q_ptr = this;
00094     setOutputChannelMode(ForwardedChannels);
00095 }
00096 
00097 KProcess::KProcess(KProcessPrivate *d, QObject *parent) :
00098     QProcess(parent),
00099     d_ptr(d)
00100 {
00101     d_ptr->q_ptr = this;
00102     setOutputChannelMode(ForwardedChannels);
00103 }
00104 
00105 KProcess::~KProcess()
00106 {
00107     delete d_ptr;
00108 }
00109 
00110 void KProcess::setOutputChannelMode(OutputChannelMode mode)
00111 {
00112     Q_D(KProcess);
00113 
00114     d->outputChannelMode = mode;
00115     disconnect(this, SIGNAL(readyReadStandardOutput()));
00116     disconnect(this, SIGNAL(readyReadStandardError()));
00117     switch (mode) {
00118     case OnlyStdoutChannel:
00119         connect(this, SIGNAL(readyReadStandardError()), SLOT(_k_forwardStderr()));
00120         break;
00121     case OnlyStderrChannel:
00122         connect(this, SIGNAL(readyReadStandardOutput()), SLOT(_k_forwardStdout()));
00123         break;
00124     default:
00125         QProcess::setProcessChannelMode((ProcessChannelMode)mode);
00126         return;
00127     }
00128     QProcess::setProcessChannelMode(QProcess::SeparateChannels);
00129 }
00130 
00131 KProcess::OutputChannelMode KProcess::outputChannelMode() const
00132 {
00133     Q_D(const KProcess);
00134 
00135     return d->outputChannelMode;
00136 }
00137 
00138 void KProcess::setNextOpenMode(QIODevice::OpenMode mode)
00139 {
00140     Q_D(KProcess);
00141 
00142     d->openMode = mode;
00143 }
00144 
00145 #define DUMMYENV "_KPROCESS_DUMMY_="
00146 
00147 void KProcess::clearEnvironment()
00148 {
00149     setEnvironment(QStringList() << QString::fromLatin1(DUMMYENV));
00150 }
00151 
00152 void KProcess::setEnv(const QString &name, const QString &value, bool overwrite)
00153 {
00154     QStringList env = environment();
00155     if (env.isEmpty()) {
00156         env = systemEnvironment();
00157         env.removeAll(QString::fromLatin1(DUMMYENV));
00158     }
00159     QString fname(name);
00160     fname.append('=');
00161     for (QStringList::Iterator it = env.begin(); it != env.end(); ++it)
00162         if ((*it).startsWith(fname)) {
00163             if (overwrite) {
00164                 *it = fname.append(value);
00165                 setEnvironment(env);
00166             }
00167             return;
00168         }
00169     env.append(fname.append(value));
00170     setEnvironment(env);
00171 }
00172 
00173 void KProcess::unsetEnv(const QString &name)
00174 {
00175     QStringList env = environment();
00176     if (env.isEmpty()) {
00177         env = systemEnvironment();
00178         env.removeAll(QString::fromLatin1(DUMMYENV));
00179     }
00180     QString fname(name);
00181     fname.append('=');
00182     for (QStringList::Iterator it = env.begin(); it != env.end(); ++it)
00183         if ((*it).startsWith(fname)) {
00184             env.erase(it);
00185             if (env.isEmpty())
00186                 env.append(DUMMYENV);
00187             setEnvironment(env);
00188             return;
00189         }
00190 }
00191 
00192 void KProcess::setProgram(const QString &exe, const QStringList &args)
00193 {
00194     Q_D(KProcess);
00195 
00196     d->prog = exe;
00197     d->args = args;
00198 }
00199 
00200 void KProcess::setProgram(const QStringList &argv)
00201 {
00202     Q_D(KProcess);
00203 
00204     Q_ASSERT( !argv.isEmpty() );
00205     d->args = argv;
00206     d->prog = d->args.takeFirst();
00207 }
00208 
00209 KProcess &KProcess::operator<<(const QString &arg)
00210 {
00211     Q_D(KProcess);
00212 
00213     if (d->prog.isEmpty())
00214         d->prog = arg;
00215     else
00216         d->args << arg;
00217     return *this;
00218 }
00219 
00220 KProcess &KProcess::operator<<(const QStringList &args)
00221 {
00222     Q_D(KProcess);
00223 
00224     if (d->prog.isEmpty())
00225         setProgram(args);
00226     else
00227         d->args << args;
00228     return *this;
00229 }
00230 
00231 void KProcess::clearProgram()
00232 {
00233     Q_D(KProcess);
00234 
00235     d->prog.clear();
00236     d->args.clear();
00237 }
00238 
00239 void KProcess::setShellCommand(const QString &cmd)
00240 {
00241     Q_D(KProcess);
00242 
00243     d->args.clear();
00244 
00245 #ifdef Q_OS_UNIX
00246 // #ifdef NON_FREE // ... as they ship non-POSIX /bin/sh
00247 # if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) && !defined(__GNU__)
00248     // If /bin/sh is a symlink, we can be pretty sure that it points to a
00249     // POSIX shell - the original bourne shell is about the only non-POSIX
00250     // shell still in use and it is always installed natively as /bin/sh.
00251     d->prog = QFile::symLinkTarget(QString::fromLatin1("/bin/sh"));
00252     if (d->prog.isEmpty()) {
00253         // Try some known POSIX shells.
00254         d->prog = KStandardDirs::findExe("ksh");
00255         if (d->prog.isEmpty()) {
00256             d->prog = KStandardDirs::findExe("ash");
00257             if (d->prog.isEmpty()) {
00258                 d->prog = KStandardDirs::findExe("bash");
00259                 if (d->prog.isEmpty()) {
00260                     d->prog = KStandardDirs::findExe("zsh");
00261                     if (d->prog.isEmpty())
00262                         // We're pretty much screwed, to be honest ...
00263                         d->prog = QString::fromLatin1("/bin/sh");
00264                 }
00265             }
00266         }
00267     }
00268 # else
00269     d->prog = QString::fromLatin1("/bin/sh");
00270 # endif
00271 
00272     d->args << "-c" << cmd;
00273 #else // Q_OS_UNIX
00274     // KMacroExpander::expandMacrosShellQuote(), KShell::quoteArg() and
00275     // KShell::joinArgs() may generate these for security reasons.
00276     setEnv(PERCENT_VARIABLE, "%");
00277 
00278     //see also TrollTechTaskTracker entry 88373.
00279     d->prog = KStandardDirs::findExe("kcmdwrapper");
00280 
00281     UINT size;
00282     WCHAR sysdir[MAX_PATH + 1];
00283     size = GetSystemDirectoryW(sysdir, MAX_PATH + 1);
00284     QString cmdexe = QString::fromUtf16((const ushort *) sysdir, size);
00285     cmdexe.append("\\cmd.exe");
00286 
00287     d->args << cmdexe << cmd;
00288 #endif
00289 }
00290 
00291 QStringList KProcess::program() const
00292 {
00293     Q_D(const KProcess);
00294 
00295     QStringList argv = d->args;
00296     argv.prepend(d->prog);
00297     return argv;
00298 }
00299 
00300 void KProcess::start()
00301 {
00302     Q_D(KProcess);
00303 
00304     QProcess::start(d->prog, d->args, d->openMode);
00305 }
00306 
00307 int KProcess::execute(int msecs)
00308 {
00309     start();
00310     if (!waitForFinished(msecs)) {
00311         kill();
00312         waitForFinished(-1);
00313         return -2;
00314     }
00315     return (exitStatus() == QProcess::NormalExit) ? exitCode() : -1;
00316 }
00317 
00318 // static
00319 int KProcess::execute(const QString &exe, const QStringList &args, int msecs)
00320 {
00321     KProcess p;
00322     p.setProgram(exe, args);
00323     return p.execute(msecs);
00324 }
00325 
00326 // static
00327 int KProcess::execute(const QStringList &argv, int msecs)
00328 {
00329     KProcess p;
00330     p.setProgram(argv);
00331     return p.execute(msecs);
00332 }
00333 
00334 int KProcess::startDetached()
00335 {
00336     Q_D(KProcess);
00337 
00338     qint64 pid;
00339     if (!QProcess::startDetached(d->prog, d->args, workingDirectory(), &pid))
00340         return 0;
00341     return (int) pid;
00342 }
00343 
00344 // static
00345 int KProcess::startDetached(const QString &exe, const QStringList &args)
00346 {
00347     qint64 pid;
00348     if (!QProcess::startDetached(exe, args, QString(), &pid))
00349         return 0;
00350     return (int) pid;
00351 }
00352 
00353 // static
00354 int KProcess::startDetached(const QStringList &argv)
00355 {
00356     QStringList args = argv;
00357     QString prog = args.takeFirst();
00358     return startDetached(prog, args);
00359 }
00360 
00361 int KProcess::pid() const
00362 {
00363 #ifdef Q_OS_UNIX
00364     return (int) QProcess::pid();
00365 #else
00366     return QProcess::pid() ? QProcess::pid()->dwProcessId : 0;
00367 #endif
00368 }
00369 
00370 #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
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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