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