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

KDECore

  • sources
  • kde-4.14
  • kdelibs
  • kdecore
  • io
kprocess.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the KDE libraries
3 
4  Copyright (C) 2007 Oswald Buddenhagen <ossi@kde.org>
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License as published by the Free Software Foundation; either
9  version 2 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Library General Public License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to
18  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  Boston, MA 02110-1301, USA.
20 */
21 
22 #include "kprocess_p.h"
23 
24 #include <kstandarddirs.h>
25 #include <kshell.h>
26 #ifdef Q_OS_WIN
27 # include <kshell_p.h>
28 #endif
29 
30 #include <qfile.h>
31 
32 #ifdef Q_OS_WIN
33 # include <windows.h>
34 #else
35 # include <unistd.h>
36 # include <errno.h>
37 #endif
38 
39 #ifndef Q_OS_WIN
40 # define STD_OUTPUT_HANDLE 1
41 # define STD_ERROR_HANDLE 2
42 #endif
43 
44 #ifdef _WIN32_WCE
45 #include <stdio.h>
46 #endif
47 
48 void KProcessPrivate::writeAll(const QByteArray &buf, int fd)
49 {
50 #ifdef Q_OS_WIN
51 #ifndef _WIN32_WCE
52  HANDLE h = GetStdHandle(fd);
53  if (h) {
54  DWORD wr;
55  WriteFile(h, buf.data(), buf.size(), &wr, 0);
56  }
57 #else
58  fwrite(buf.data(), 1, buf.size(), (FILE*)fd);
59 #endif
60 #else
61  int off = 0;
62  do {
63  int ret = ::write(fd, buf.data() + off, buf.size() - off);
64  if (ret < 0) {
65  if (errno != EINTR)
66  return;
67  } else {
68  off += ret;
69  }
70  } while (off < buf.size());
71 #endif
72 }
73 
74 void KProcessPrivate::forwardStd(KProcess::ProcessChannel good, int fd)
75 {
76  Q_Q(KProcess);
77 
78  QProcess::ProcessChannel oc = q->readChannel();
79  q->setReadChannel(good);
80  writeAll(q->readAll(), fd);
81  q->setReadChannel(oc);
82 }
83 
84 void KProcessPrivate::_k_forwardStdout()
85 {
86 #ifndef _WIN32_WCE
87  forwardStd(KProcess::StandardOutput, STD_OUTPUT_HANDLE);
88 #else
89  forwardStd(KProcess::StandardOutput, (int)stdout);
90 #endif
91 }
92 
93 void KProcessPrivate::_k_forwardStderr()
94 {
95 #ifndef _WIN32_WCE
96  forwardStd(KProcess::StandardError, STD_ERROR_HANDLE);
97 #else
98  forwardStd(KProcess::StandardError, (int)stderr);
99 #endif
100 }
101 
103 // public member functions //
105 
106 KProcess::KProcess(QObject *parent) :
107  QProcess(parent),
108  d_ptr(new KProcessPrivate)
109 {
110  d_ptr->q_ptr = this;
111  setOutputChannelMode(ForwardedChannels);
112 }
113 
114 KProcess::KProcess(KProcessPrivate *d, QObject *parent) :
115  QProcess(parent),
116  d_ptr(d)
117 {
118  d_ptr->q_ptr = this;
119  setOutputChannelMode(ForwardedChannels);
120 }
121 
122 KProcess::~KProcess()
123 {
124  delete d_ptr;
125 }
126 
127 void KProcess::setOutputChannelMode(OutputChannelMode mode)
128 {
129  Q_D(KProcess);
130 
131  d->outputChannelMode = mode;
132  disconnect(this, SIGNAL(readyReadStandardOutput()));
133  disconnect(this, SIGNAL(readyReadStandardError()));
134  switch (mode) {
135  case OnlyStdoutChannel:
136  connect(this, SIGNAL(readyReadStandardError()), SLOT(_k_forwardStderr()));
137  break;
138  case OnlyStderrChannel:
139  connect(this, SIGNAL(readyReadStandardOutput()), SLOT(_k_forwardStdout()));
140  break;
141  default:
142  QProcess::setProcessChannelMode((ProcessChannelMode)mode);
143  return;
144  }
145  QProcess::setProcessChannelMode(QProcess::SeparateChannels);
146 }
147 
148 KProcess::OutputChannelMode KProcess::outputChannelMode() const
149 {
150  Q_D(const KProcess);
151 
152  return d->outputChannelMode;
153 }
154 
155 void KProcess::setNextOpenMode(QIODevice::OpenMode mode)
156 {
157  Q_D(KProcess);
158 
159  d->openMode = mode;
160 }
161 
162 #define DUMMYENV "_KPROCESS_DUMMY_="
163 
164 void KProcess::clearEnvironment()
165 {
166  setEnvironment(QStringList() << QString::fromLatin1(DUMMYENV));
167 }
168 
169 void KProcess::setEnv(const QString &name, const QString &value, bool overwrite)
170 {
171  QStringList env = environment();
172  if (env.isEmpty()) {
173  env = systemEnvironment();
174  env.removeAll(QString::fromLatin1(DUMMYENV));
175  }
176  QString fname(name);
177  fname.append(QLatin1Char('='));
178  for (QStringList::Iterator it = env.begin(); it != env.end(); ++it)
179  if ((*it).startsWith(fname)) {
180  if (overwrite) {
181  *it = fname.append(value);
182  setEnvironment(env);
183  }
184  return;
185  }
186  env.append(fname.append(value));
187  setEnvironment(env);
188 }
189 
190 void KProcess::unsetEnv(const QString &name)
191 {
192  QStringList env = environment();
193  if (env.isEmpty()) {
194  env = systemEnvironment();
195  env.removeAll(QString::fromLatin1(DUMMYENV));
196  }
197  QString fname(name);
198  fname.append(QLatin1Char('='));
199  for (QStringList::Iterator it = env.begin(); it != env.end(); ++it)
200  if ((*it).startsWith(fname)) {
201  env.erase(it);
202  if (env.isEmpty())
203  env.append(QString::fromLatin1(DUMMYENV));
204  setEnvironment(env);
205  return;
206  }
207 }
208 
209 void KProcess::setProgram(const QString &exe, const QStringList &args)
210 {
211  Q_D(KProcess);
212 
213  d->prog = exe;
214  d->args = args;
215 #ifdef Q_OS_WIN
216  setNativeArguments(QString());
217 #endif
218 }
219 
220 void KProcess::setProgram(const QStringList &argv)
221 {
222  Q_D(KProcess);
223 
224  Q_ASSERT( !argv.isEmpty() );
225  d->args = argv;
226  d->prog = d->args.takeFirst();
227 #ifdef Q_OS_WIN
228  setNativeArguments(QString());
229 #endif
230 }
231 
232 KProcess &KProcess::operator<<(const QString &arg)
233 {
234  Q_D(KProcess);
235 
236  if (d->prog.isEmpty())
237  d->prog = arg;
238  else
239  d->args << arg;
240  return *this;
241 }
242 
243 KProcess &KProcess::operator<<(const QStringList &args)
244 {
245  Q_D(KProcess);
246 
247  if (d->prog.isEmpty())
248  setProgram(args);
249  else
250  d->args << args;
251  return *this;
252 }
253 
254 void KProcess::clearProgram()
255 {
256  Q_D(KProcess);
257 
258  d->prog.clear();
259  d->args.clear();
260 #ifdef Q_OS_WIN
261  setNativeArguments(QString());
262 #endif
263 }
264 
265 void KProcess::setShellCommand(const QString &cmd)
266 {
267  Q_D(KProcess);
268 
269  KShell::Errors err;
270  d->args = KShell::splitArgs(
271  cmd, KShell::AbortOnMeta | KShell::TildeExpand, &err);
272  if (err == KShell::NoError && !d->args.isEmpty()) {
273  d->prog = KStandardDirs::findExe(d->args[0]);
274  if (!d->prog.isEmpty()) {
275  d->args.removeFirst();
276 #ifdef Q_OS_WIN
277  setNativeArguments(QString());
278 #endif
279  return;
280  }
281  }
282 
283  d->args.clear();
284 
285 #ifdef Q_OS_UNIX
286 // #ifdef NON_FREE // ... as they ship non-POSIX /bin/sh
287 # if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) && !defined(__GNU__)
288  // If /bin/sh is a symlink, we can be pretty sure that it points to a
289  // POSIX shell - the original bourne shell is about the only non-POSIX
290  // shell still in use and it is always installed natively as /bin/sh.
291  d->prog = QFile::symLinkTarget(QString::fromLatin1("/bin/sh"));
292  if (d->prog.isEmpty()) {
293  // Try some known POSIX shells.
294  d->prog = KStandardDirs::findExe(QString::fromLatin1("ksh"));
295  if (d->prog.isEmpty()) {
296  d->prog = KStandardDirs::findExe(QString::fromLatin1("ash"));
297  if (d->prog.isEmpty()) {
298  d->prog = KStandardDirs::findExe(QString::fromLatin1("bash"));
299  if (d->prog.isEmpty()) {
300  d->prog = KStandardDirs::findExe(QString::fromLatin1("zsh"));
301  if (d->prog.isEmpty())
302  // We're pretty much screwed, to be honest ...
303  d->prog = QString::fromLatin1("/bin/sh");
304  }
305  }
306  }
307  }
308 # else
309  d->prog = QString::fromLatin1("/bin/sh");
310 # endif
311 
312  d->args << QString::fromLatin1("-c") << cmd;
313 #else // Q_OS_UNIX
314  // KMacroExpander::expandMacrosShellQuote(), KShell::quoteArg() and
315  // KShell::joinArgs() may generate these for security reasons.
316  setEnv(PERCENT_VARIABLE, QLatin1String("%"));
317 
318 #ifndef _WIN32_WCE
319  WCHAR sysdir[MAX_PATH + 1];
320  UINT size = GetSystemDirectoryW(sysdir, MAX_PATH + 1);
321  d->prog = QString::fromUtf16((const ushort *) sysdir, size);
322  d->prog += QLatin1String("\\cmd.exe");
323  setNativeArguments(QLatin1String("/V:OFF /S /C \"") + cmd + QLatin1Char('"'));
324 #else
325  d->prog = QLatin1String("\\windows\\cmd.exe");
326  setNativeArguments(QLatin1String("/S /C \"") + cmd + QLatin1Char('"'));
327 #endif
328 #endif
329 }
330 
331 QStringList KProcess::program() const
332 {
333  Q_D(const KProcess);
334 
335  QStringList argv = d->args;
336  argv.prepend(d->prog);
337  return argv;
338 }
339 
340 void KProcess::start()
341 {
342  Q_D(KProcess);
343 
344  QProcess::start(d->prog, d->args, d->openMode);
345 }
346 
347 int KProcess::execute(int msecs)
348 {
349  start();
350  if (!waitForFinished(msecs)) {
351  kill();
352  waitForFinished(-1);
353  return -2;
354  }
355  return (exitStatus() == QProcess::NormalExit) ? exitCode() : -1;
356 }
357 
358 // static
359 int KProcess::execute(const QString &exe, const QStringList &args, int msecs)
360 {
361  KProcess p;
362  p.setProgram(exe, args);
363  return p.execute(msecs);
364 }
365 
366 // static
367 int KProcess::execute(const QStringList &argv, int msecs)
368 {
369  KProcess p;
370  p.setProgram(argv);
371  return p.execute(msecs);
372 }
373 
374 int KProcess::startDetached()
375 {
376  Q_D(KProcess);
377 
378  qint64 pid;
379  if (!QProcess::startDetached(d->prog, d->args, workingDirectory(), &pid))
380  return 0;
381  return (int) pid;
382 }
383 
384 // static
385 int KProcess::startDetached(const QString &exe, const QStringList &args)
386 {
387  qint64 pid;
388  if (!QProcess::startDetached(exe, args, QString(), &pid))
389  return 0;
390  return (int) pid;
391 }
392 
393 // static
394 int KProcess::startDetached(const QStringList &argv)
395 {
396  QStringList args = argv;
397  QString prog = args.takeFirst();
398  return startDetached(prog, args);
399 }
400 
401 int KProcess::pid() const
402 {
403 #ifdef Q_OS_UNIX
404  return (int) QProcess::pid();
405 #else
406  return QProcess::pid() ? QProcess::pid()->dwProcessId : 0;
407 #endif
408 }
409 
410 #include "kprocess.moc"
QIODevice::OpenMode
typedef OpenMode
KProcess::setNextOpenMode
void setNextOpenMode(QIODevice::OpenMode mode)
Set the QIODevice open mode the process will be opened in.
Definition: kprocess.cpp:155
KProcess::setShellCommand
void setShellCommand(const QString &cmd)
Set a command to execute through a shell (a POSIX sh on *NIX and cmd.exe on Windows).
Definition: kprocess.cpp:265
QProcess::readyReadStandardError
void readyReadStandardError()
qint64
kshell_p.h
QString::append
QString & append(QChar ch)
KProcess
Child process invocation, monitoring and control.
Definition: kprocess.h:44
QProcess::kill
void kill()
QProcess::systemEnvironment
QStringList systemEnvironment()
KProcess::KProcess
KProcess(QObject *parent=0)
Constructor.
Definition: kprocess.cpp:106
QByteArray
KProcess::OnlyStdoutChannel
Only standard output is handled; standard error is forwarded.
Definition: kprocess.h:64
QProcess::startDetached
bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
kshell.h
DUMMYENV
#define DUMMYENV
Definition: kprocess.cpp:162
KProcess::operator<<
KProcess & operator<<(const QString &arg)
Append an element to the command line argument list for this process.
Definition: kprocess.cpp:232
QList::erase
iterator erase(iterator pos)
KProcess::setOutputChannelMode
void setOutputChannelMode(OutputChannelMode mode)
Set how to handle the output channels of the child process.
Definition: kprocess.cpp:127
QProcess::readyReadStandardOutput
void readyReadStandardOutput()
QObject::disconnect
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
KProcess::~KProcess
virtual ~KProcess()
Destructor.
Definition: kprocess.cpp:122
KShell::splitArgs
QStringList splitArgs(const QString &cmd, Options flags=NoOptions, Errors *err=0)
Splits cmd according to system shell word splitting and quoting rules.
Definition: kshell_unix.cpp:70
KProcessPrivate
Definition: kprocess_p.h:27
QList::append
void append(const T &value)
QIODevice::size
virtual qint64 size() const
KProcess::program
QStringList program() const
Obtain the currently set program and arguments.
Definition: kprocess.cpp:331
QString::fromUtf16
QString fromUtf16(const ushort *unicode, int size)
QProcess
QObject
KProcess::clearProgram
void clearProgram()
Clear the program and command line argument list.
Definition: kprocess.cpp:254
KProcess::setEnv
void setEnv(const QString &name, const QString &value, bool overwrite=true)
Adds the variable name to the process' environment.
Definition: kprocess.cpp:169
QFile::symLinkTarget
QString symLinkTarget() const
QList::isEmpty
bool isEmpty() const
QList::removeAll
int removeAll(const T &value)
KProcess::clearEnvironment
void clearEnvironment()
Empties the process' environment.
Definition: kprocess.cpp:164
KShell::Errors
Errors
Status codes from splitArgs()
Definition: kshell.h:85
QProcess::environment
QStringList environment() const
QList::Iterator
typedef Iterator
QProcess::setEnvironment
void setEnvironment(const QStringList &environment)
QString
KProcessPrivate::writeAll
void writeAll(const QByteArray &buf, int fd)
Definition: kprocess.cpp:48
KProcessPrivate::forwardStd
void forwardStd(KProcess::ProcessChannel good, int fd)
Definition: kprocess.cpp:74
KProcess::unsetEnv
void unsetEnv(const QString &name)
Removes the variable name from the process' environment.
Definition: kprocess.cpp:190
QStringList
KProcess::d_ptr
KProcessPrivate *const d_ptr
Definition: kprocess.h:327
KProcess::start
void start()
Start the process.
Definition: kprocess.cpp:340
QList::end
iterator end()
QProcess::pid
Q_PID pid() const
QLatin1Char
QProcess::setProcessChannelMode
void setProcessChannelMode(ProcessChannelMode mode)
QIODevice::mode
int mode() const
KProcess::ForwardedChannels
Both standard output and standard error are forwarded to the parent process' respective channel...
Definition: kprocess.h:61
QList::takeFirst
T takeFirst()
QLatin1String
kstandarddirs.h
QProcess::workingDirectory
QString workingDirectory() const
KStandardDirs::findExe
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
Finds the executable in the system path.
Definition: kstandarddirs.cpp:1328
KShell::NoError
Success.
Definition: kshell.h:89
KProcess::execute
int execute(int msecs=-1)
Start the process, wait for it to finish, and return the exit code.
Definition: kprocess.cpp:347
QByteArray::data
char * data()
QString::fromLatin1
QString fromLatin1(const char *str, int size)
QList::prepend
void prepend(const T &value)
KProcessPrivate::_k_forwardStderr
void _k_forwardStderr()
Definition: kprocess.cpp:93
KProcess::pid
int pid() const
Obtain the process' ID as known to the system.
Definition: kprocess.cpp:401
QByteArray::size
int size() const
KProcessPrivate::q_ptr
KProcess * q_ptr
Definition: kprocess_p.h:44
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KProcess::OnlyStderrChannel
Only standard error is handled; standard output is forwarded.
Definition: kprocess.h:66
QProcess::setNativeArguments
void setNativeArguments(const QString &arguments)
KProcess::startDetached
int startDetached()
Start the process and detach from it.
Definition: kprocess.cpp:374
QProcess::exitStatus
QProcess::ExitStatus exitStatus() const
QList::begin
iterator begin()
QProcess::exitCode
int exitCode() const
KProcessPrivate::_k_forwardStdout
void _k_forwardStdout()
Definition: kprocess.cpp:84
QProcess::start
void start(const QString &program, const QStringList &arguments, QFlags< QIODevice::OpenModeFlag > mode)
KShell::AbortOnMeta
Put the parser into full shell mode and bail out if a too complex construct is encoutered.
Definition: kshell.h:78
PERCENT_VARIABLE
#define PERCENT_VARIABLE
Definition: kshell_p.h:34
KShell::TildeExpand
Perform tilde expansion.
Definition: kshell.h:47
KProcess::OutputChannelMode
OutputChannelMode
Modes in which the output channels can be opened.
Definition: kprocess.h:54
KProcess::outputChannelMode
OutputChannelMode outputChannelMode() const
Query how the output channels of the child process are handled.
Definition: kprocess.cpp:148
kprocess_p.h
KProcess::setProgram
void setProgram(const QString &exe, const QStringList &args=QStringList())
Set the program and the command line arguments.
Definition: kprocess.cpp:209
QProcess::waitForFinished
bool waitForFinished(int msecs)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:11 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

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

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal