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 #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
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
00247 # if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) && !defined(__GNU__)
00248
00249
00250
00251 d->prog = QFile::symLinkTarget(QString::fromLatin1("/bin/sh"));
00252 if (d->prog.isEmpty()) {
00253
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
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
00275
00276 setEnv(PERCENT_VARIABLE, "%");
00277
00278
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
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
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
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
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"