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

KDECore

  • 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
48void 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
74void 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
84void 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
93void 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
106KProcess::KProcess(QObject *parent) :
107 QProcess(parent),
108 d_ptr(new KProcessPrivate)
109{
110 d_ptr->q_ptr = this;
111 setOutputChannelMode(ForwardedChannels);
112}
113
114KProcess::KProcess(KProcessPrivate *d, QObject *parent) :
115 QProcess(parent),
116 d_ptr(d)
117{
118 d_ptr->q_ptr = this;
119 setOutputChannelMode(ForwardedChannels);
120}
121
122KProcess::~KProcess()
123{
124 delete d_ptr;
125}
126
127void 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
148KProcess::OutputChannelMode KProcess::outputChannelMode() const
149{
150 Q_D(const KProcess);
151
152 return d->outputChannelMode;
153}
154
155void KProcess::setNextOpenMode(QIODevice::OpenMode mode)
156{
157 Q_D(KProcess);
158
159 d->openMode = mode;
160}
161
162#define DUMMYENV "_KPROCESS_DUMMY_="
163
164void KProcess::clearEnvironment()
165{
166 setEnvironment(QStringList() << QString::fromLatin1(DUMMYENV));
167}
168
169void 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
190void 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
209void 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
220void 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
232KProcess &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
243KProcess &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
254void 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
265void 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
331QStringList 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
340void KProcess::start()
341{
342 Q_D(KProcess);
343
344 QProcess::start(d->prog, d->args, d->openMode);
345}
346
347int 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
359int 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
367int KProcess::execute(const QStringList &argv, int msecs)
368{
369 KProcess p;
370 p.setProgram(argv);
371 return p.execute(msecs);
372}
373
374int 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
385int 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
394int KProcess::startDetached(const QStringList &argv)
395{
396 QStringList args = argv;
397 QString prog = args.takeFirst();
398 return startDetached(prog, args);
399}
400
401int 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"
KProcessPrivate
Definition: kprocess_p.h:27
KProcessPrivate::q_ptr
KProcess * q_ptr
Definition: kprocess_p.h:44
KProcessPrivate::forwardStd
void forwardStd(KProcess::ProcessChannel good, int fd)
Definition: kprocess.cpp:74
KProcessPrivate::_k_forwardStdout
void _k_forwardStdout()
Definition: kprocess.cpp:84
KProcessPrivate::_k_forwardStderr
void _k_forwardStderr()
Definition: kprocess.cpp:93
KProcessPrivate::writeAll
void writeAll(const QByteArray &buf, int fd)
Definition: kprocess.cpp:48
KProcess
Child process invocation, monitoring and control.
Definition: kprocess.h:45
KProcess::pid
int pid() const
Obtain the process' ID as known to the system.
Definition: kprocess.cpp:401
KProcess::start
void start()
Start the process.
Definition: kprocess.cpp:340
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
KProcess::setNextOpenMode
void setNextOpenMode(QIODevice::OpenMode mode)
Set the QIODevice open mode the process will be opened in.
Definition: kprocess.cpp:155
KProcess::d_ptr
KProcessPrivate *const d_ptr
Definition: kprocess.h:327
KProcess::clearProgram
void clearProgram()
Clear the program and command line argument list.
Definition: kprocess.cpp:254
KProcess::OutputChannelMode
OutputChannelMode
Modes in which the output channels can be opened.
Definition: kprocess.h:54
KProcess::OnlyStdoutChannel
@ OnlyStdoutChannel
Only standard output is handled; standard error is forwarded.
Definition: kprocess.h:64
KProcess::ForwardedChannels
@ ForwardedChannels
Both standard output and standard error are forwarded to the parent process' respective channel.
Definition: kprocess.h:61
KProcess::OnlyStderrChannel
@ OnlyStderrChannel
Only standard error is handled; standard output is forwarded.
Definition: kprocess.h:66
KProcess::unsetEnv
void unsetEnv(const QString &name)
Removes the variable name from the process' environment.
Definition: kprocess.cpp:190
KProcess::operator<<
KProcess & operator<<(const QString &arg)
Append an element to the command line argument list for this process.
Definition: kprocess.cpp:232
KProcess::outputChannelMode
OutputChannelMode outputChannelMode() const
Query how the output channels of the child process are handled.
Definition: kprocess.cpp:148
KProcess::program
QStringList program() const
Obtain the currently set program and arguments.
Definition: kprocess.cpp:331
KProcess::startDetached
int startDetached()
Start the process and detach from it.
Definition: kprocess.cpp:374
KProcess::setOutputChannelMode
void setOutputChannelMode(OutputChannelMode mode)
Set how to handle the output channels of the child process.
Definition: kprocess.cpp:127
KProcess::KProcess
KProcess(QObject *parent=0)
Constructor.
Definition: kprocess.cpp:106
KProcess::clearEnvironment
void clearEnvironment()
Empties the process' environment.
Definition: kprocess.cpp:164
KProcess::~KProcess
virtual ~KProcess()
Destructor.
Definition: kprocess.cpp:122
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
KProcess::execute
int execute(int msecs=-1)
Start the process, wait for it to finish, and return the exit code.
Definition: kprocess.cpp:347
KProcess::setProgram
void setProgram(const QString &exe, const QStringList &args=QStringList())
Set the program and the command line arguments.
Definition: kprocess.cpp:209
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:1334
QObject
QProcess
QStringList
QString
qint64
pid
static pid_t pid
Definition: k3resolvermanager.cpp:249
DUMMYENV
#define DUMMYENV
Definition: kprocess.cpp:162
kprocess_p.h
kshell.h
kshell_p.h
PERCENT_VARIABLE
#define PERCENT_VARIABLE
Definition: kshell_p.h:34
kstandarddirs.h
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
KShell::TildeExpand
@ TildeExpand
Perform tilde expansion.
Definition: kshell.h:47
KShell::AbortOnMeta
@ AbortOnMeta
Put the parser into full shell mode and bail out if a too complex construct is encoutered.
Definition: kshell.h:78
KShell::Errors
Errors
Status codes from splitArgs()
Definition: kshell.h:85
KShell::NoError
@ NoError
Success.
Definition: kshell.h:89
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 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-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 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
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