source: ogBrowser-Git/qtermwidget/lib/kprocess.cpp @ 9004d96

jenkinsmain
Last change on this file since 9004d96 was 64efc22, checked in by Vadim Troshchinskiy <vtroshchinskiy@…>, 19 months ago

Update qtermwidget to modern version

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