kprocess.cpp
/*
$Id: kprocess.cpp 549079 2006-06-07 11:18:16Z mueller $
This file is part of the KDE libraries
Copyright (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kprocess.h"
#include "kprocctrl.h"
#include "kpty.h"
#include <config.h>
#ifdef __sgi
#define __svr4__
#endif
#ifdef __osf__
#define _OSF_SOURCE
#include <float.h>
#endif
#ifdef _AIX
#define _ALL_SOURCE
#endif
#ifdef Q_OS_UNIX
#include <sys/socket.h>
#include <sys/ioctl.h>
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/wait.h>
#ifdef HAVE_SYS_STROPTS_H
#include <sys/stropts.h> // Defines I_PUSH
#define _NEW_TTY_CTRL
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <errno.h>
#include <assert.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <qfile.h>
#include <qsocketnotifier.h>
#include <qapplication.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <kuser.h>
// private data //
class KProcessPrivate {
public:
KProcessPrivate() :
usePty(KProcess::NoCommunication),
addUtmp(false), useShell(false),
#ifdef Q_OS_UNIX
pty(0),
#endif
priority(0)
{
}
KProcess::Communication usePty;
bool addUtmp : 1;
bool useShell : 1;
#ifdef Q_OS_UNIX
KPty *pty;
#endif
int priority;
QMap<QString,QString> env;
QString wd;
QCString shell;
QCString executable;
};
// public member functions //
KProcess::KProcess( QObject* parent, const char *name )
: QObject( parent, name ),
run_mode(NotifyOnExit),
runs(false),
pid_(0),
status(0),
keepPrivs(false),
innot(0),
outnot(0),
errnot(0),
communication(NoCommunication),
input_data(0),
input_sent(0),
input_total(0)
{
KProcessController::ref();
KProcessController::theKProcessController->addKProcess(this);
d = new KProcessPrivate;
out[0] = out[1] = -1;
in[0] = in[1] = -1;
err[0] = err[1] = -1;
}
KProcess::KProcess()
: QObject(),
run_mode(NotifyOnExit),
runs(false),
pid_(0),
status(0),
keepPrivs(false),
innot(0),
outnot(0),
errnot(0),
communication(NoCommunication),
input_data(0),
input_sent(0),
input_total(0)
{
KProcessController::ref();
KProcessController::theKProcessController->addKProcess(this);
d = new KProcessPrivate;
out[0] = out[1] = -1;
in[0] = in[1] = -1;
err[0] = err[1] = -1;
}
void
KProcess::setEnvironment(const QString &name, const QString &value)
{
d->env.insert(name, value);
}
void
KProcess::setWorkingDirectory(const QString &dir)
{
d->wd = dir;
}
void
KProcess::setupEnvironment()
{
QMap<QString,QString>::Iterator it;
for(it = d->env.begin(); it != d->env.end(); ++it)
{
setenv(QFile::encodeName(it.key()).data(),
QFile::encodeName(it.data()).data(), 1);
}
if (!d->wd.isEmpty())
{
chdir(QFile::encodeName(d->wd).data());
}
}
void
KProcess::setRunPrivileged(bool keepPrivileges)
{
keepPrivs = keepPrivileges;
}
bool
KProcess::runPrivileged() const
{
return keepPrivs;
}
bool
KProcess::setPriority(int prio)
{
#ifdef Q_OS_UNIX
if (runs) {
if (setpriority(PRIO_PROCESS, pid_, prio))
return false;
} else {
if (prio > 19 || prio < (geteuid() ? getpriority(PRIO_PROCESS, 0) : -20))
return false;
}
#endif
d->priority = prio;
return true;
}
KProcess::~KProcess()
{
if (run_mode != DontCare)
kill(SIGKILL);
detach();
#ifdef Q_OS_UNIX
delete d->pty;
#endif
delete d;
KProcessController::theKProcessController->removeKProcess(this);
KProcessController::deref();
}
void KProcess::detach()
{
if (runs) {
KProcessController::theKProcessController->addProcess(pid_);
runs = false;
pid_ = 0; // close without draining
commClose(); // Clean up open fd's and socket notifiers.
}
}
void KProcess::setBinaryExecutable(const char *filename)
{
d->executable = filename;
}
bool KProcess::setExecutable(const QString& proc)
{
if (runs) return false;
if (proc.isEmpty()) return false;
if (!arguments.isEmpty())
arguments.remove(arguments.begin());
arguments.prepend(QFile::encodeName(proc));
return true;
}
KProcess &KProcess::operator<<(const QStringList& args)
{
QStringList::ConstIterator it = args.begin();
for ( ; it != args.end() ; ++it )
arguments.append(QFile::encodeName(*it));
return *this;
}
KProcess &KProcess::operator<<(const QCString& arg)
{
return operator<< (arg.data());
}
KProcess &KProcess::operator<<(const char* arg)
{
arguments.append(arg);
return *this;
}
KProcess &KProcess::operator<<(const QString& arg)
{
arguments.append(QFile::encodeName(arg));
return *this;
}
void KProcess::clearArguments()
{
arguments.clear();
}
bool KProcess::start(RunMode runmode, Communication comm)
{
if (runs) {
kdDebug(175) << "Attempted to start an already running process" << endl;
return false;
}
uint n = arguments.count();
if (n == 0) {
kdDebug(175) << "Attempted to start a process without arguments" << endl;
return false;
}
#ifdef Q_OS_UNIX
char **arglist;
QCString shellCmd;
if (d->useShell)
{
if (d->shell.isEmpty()) {
kdDebug(175) << "Invalid shell specified" << endl;
return false;
}
for (uint i = 0; i < n; i++) {
shellCmd += arguments[i];
shellCmd += " "; // CC: to separate the arguments
}
arglist = static_cast<char **>(malloc( 4 * sizeof(char *)));
arglist[0] = d->shell.data();
arglist[1] = (char *) "-c";
arglist[2] = shellCmd.data();
arglist[3] = 0;
}
else
{
arglist = static_cast<char **>(malloc( (n + 1) * sizeof(char *)));
for (uint i = 0; i < n; i++)
arglist[i] = arguments[i].data();
arglist[n] = 0;
}
run_mode = runmode;
if (!setupCommunication(comm))
{
kdDebug(175) << "Could not setup Communication!" << endl;
free(arglist);
return false;
}
// We do this in the parent because if we do it in the child process
// gdb gets confused when the application runs from gdb.
#ifdef HAVE_INITGROUPS
struct passwd *pw = geteuid() ? 0 : getpwuid(getuid());
#endif
int fd[2];
if (pipe(fd))
fd[0] = fd[1] = -1; // Pipe failed.. continue
// we don't use vfork() because
// - it has unclear semantics and is not standardized
// - we do way too much magic in the child
pid_ = fork();
if (pid_ == 0) {
// The child process
close(fd[0]);
// Closing of fd[1] indicates that the execvp() succeeded!
fcntl(fd[1], F_SETFD, FD_CLOEXEC);
if (!commSetupDoneC())
kdDebug(175) << "Could not finish comm setup in child!" << endl;
// reset all signal handlers
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_handler = SIG_DFL;
act.sa_flags = 0;
for (int sig = 1; sig < NSIG; sig++)
sigaction(sig, &act, 0L);
if (d->priority)
setpriority(PRIO_PROCESS, 0, d->priority);
if (!runPrivileged())
{
setgid(getgid());
#ifdef HAVE_INITGROUPS
if (pw)
initgroups(pw->pw_name, pw->pw_gid);
#endif
if (geteuid() != getuid())
setuid(getuid());
if (geteuid() != getuid())
_exit(1);
}
setupEnvironment();
if (runmode == DontCare || runmode == OwnGroup)
setsid();
const char *executable = arglist[0];
if (!d->executable.isEmpty())
executable = d->executable.data();
execvp(executable, arglist);
char resultByte = 1;
write(fd[1], &resultByte, 1);
_exit(-1);
} else if (pid_ == -1) {
// forking failed
// commAbort();
pid_ = 0;
free(arglist);
return false;
}
// the parent continues here
free(arglist);
if (!commSetupDoneP())
kdDebug(175) << "Could not finish comm setup in parent!" << endl;
// Check whether client could be started.
close(fd[1]);
for(;;)
{
char resultByte;
int n = ::read(fd[0], &resultByte, 1);
if (n == 1)
{
// exec() failed
close(fd[0]);
waitpid(pid_, 0, 0);
pid_ = 0;
commClose();
return false;
}
if (n == -1)
{
if (errno == EINTR)
continue; // Ignore
}
break; // success
}
close(fd[0]);
runs = true;
switch (runmode)
{
case Block:
for (;;)
{
commClose(); // drain only, unless obsolete reimplementation
if (!runs)
{
// commClose detected data on the process exit notifification pipe
KProcessController::theKProcessController->unscheduleCheck();
if (waitpid(pid_, &status, WNOHANG) != 0) // error finishes, too
{
commClose(); // this time for real (runs is false)
KProcessController::theKProcessController->rescheduleCheck();
break;
}
runs = true; // for next commClose() iteration
}
else
{
// commClose is an obsolete reimplementation and waited until
// all output channels were closed (or it was interrupted).
// there is a chance that it never gets here ...
waitpid(pid_, &status, 0);
runs = false;
break;
}
}
// why do we do this? i think this signal should be emitted _only_
// after the process has successfully run _asynchronously_ --ossi
emit processExited(this);
break;
default: // NotifyOnExit & OwnGroup
input_data = 0; // Discard any data for stdin that might still be there
break;
}
return true;
#else
//TODO
return false;
#endif
}
bool KProcess::kill(int signo)
{
#ifdef Q_OS_UNIX
if (runs && pid_ > 0 && !::kill(run_mode == OwnGroup ? -pid_ : pid_, signo))
return true;
#endif
return false;
}
bool KProcess::isRunning() const
{
return runs;
}
pid_t KProcess::pid() const
{
return pid_;
}
#ifndef timersub
# define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
#endif
bool KProcess::wait(int timeout)
{
if (!runs)
return true;
#ifndef __linux__
struct timeval etv;
#endif
struct timeval tv, *tvp;
if (timeout < 0)
tvp = 0;
else
{
#ifndef __linux__
gettimeofday(&etv, 0);
etv.tv_sec += timeout;
#else
tv.tv_sec = timeout;
tv.tv_usec = 0;
#endif
tvp = &tv;
}
#ifdef Q_OS_UNIX
int fd = KProcessController::theKProcessController->notifierFd();
for(;;)
{
fd_set fds;
FD_ZERO( &fds );
FD_SET( fd, &fds );
#ifndef __linux__
if (tvp)
{
gettimeofday(&tv, 0);
timersub(&etv, &tv, &tv);
if (tv.tv_sec < 0)
tv.tv_sec = tv.tv_usec = 0;
}
#endif
switch( select( fd+1, &fds, 0, 0, tvp ) )
{
case -1:
if( errno == EINTR )
break;
// fall through; should happen if tvp->tv_sec < 0
case 0:
KProcessController::theKProcessController->rescheduleCheck();
return false;
default:
KProcessController::theKProcessController->unscheduleCheck();
if (waitpid(pid_, &status, WNOHANG) != 0) // error finishes, too
{
processHasExited(status);
KProcessController::theKProcessController->rescheduleCheck();
return true;
}
}
}
#endif //Q_OS_UNIX
return false;
}
bool KProcess::normalExit() const
{
return (pid_ != 0) && !runs && WIFEXITED(status);
}
bool KProcess::signalled() const
{
return (pid_ != 0) && !runs && WIFSIGNALED(status);
}
bool KProcess::coreDumped() const
{
#ifdef WCOREDUMP
return signalled() && WCOREDUMP(status);
#else
return false;
#endif
}
int KProcess::exitStatus() const
{
return WEXITSTATUS(status);
}
int KProcess::exitSignal() const
{
return WTERMSIG(status);
}
bool KProcess::writeStdin(const char *buffer, int buflen)
{
// if there is still data pending, writing new data
// to stdout is not allowed (since it could also confuse
// kprocess ...)
if (input_data != 0)
return false;
if (communication & Stdin) {
input_data = buffer;
input_sent = 0;
input_total = buflen;
innot->setEnabled(true);
if (input_total)
slotSendData(0);
return true;
} else
return false;
}
void KProcess::suspend()
{
if (outnot)
outnot->setEnabled(false);
}
void KProcess::resume()
{
if (outnot)
outnot->setEnabled(true);
}
bool KProcess::closeStdin()
{
if (communication & Stdin) {
communication = (Communication) (communication & ~Stdin);
delete innot;
innot = 0;
if (!(d->usePty & Stdin))
close(in[1]);
in[1] = -1;
return true;
} else
return false;
}
bool KProcess::closeStdout()
{
if (communication & Stdout) {
communication = (Communication) (communication & ~Stdout);
delete outnot;
outnot = 0;
if (!(d->usePty & Stdout))
close(out[0]);
out[0] = -1;
return true;
} else
return false;
}
bool KProcess::closeStderr()
{
if (communication & Stderr) {
communication = (Communication) (communication & ~Stderr);
delete errnot;
errnot = 0;
if (!(d->usePty & Stderr))
close(err[0]);
err[0] = -1;
return true;
} else
return false;
}
bool KProcess::closePty()
{
#ifdef Q_OS_UNIX
if (d->pty && d->pty->masterFd() >= 0) {
if (d->addUtmp)
d->pty->logout();
d->pty->close();
return true;
} else
return false;
#else
return false;
#endif
}
void KProcess::closeAll()
{
closeStdin();
closeStdout();
closeStderr();
closePty();
}
// protected slots //
void KProcess::slotChildOutput(int fdno)
{
if (!childOutput(fdno))
closeStdout();
}
void KProcess::slotChildError(int fdno)
{
if (!childError(fdno))
closeStderr();
}
void KProcess::slotSendData(int)
{
if (input_sent == input_total) {
innot->setEnabled(false);
input_data = 0;
emit wroteStdin(this);
} else {
int result = ::write(in[1], input_data+input_sent, input_total-input_sent);
if (result >= 0)
{
input_sent += result;
}
else if ((errno != EAGAIN) && (errno != EINTR))
{
kdDebug(175) << "Error writing to stdin of child process" << endl;
closeStdin();
}
}
}
void KProcess::setUseShell(bool useShell, const char *shell)
{
d->useShell = useShell;
if (shell && *shell)
d->shell = shell;
else
// #ifdef NON_FREE // ... as they ship non-POSIX /bin/sh
#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__GNU__) && !defined(__DragonFly__)
// Solaris POSIX ...
if (!access( "/usr/xpg4/bin/sh", X_OK ))
d->shell = "/usr/xpg4/bin/sh";
else
// ... which links here anyway
if (!access( "/bin/ksh", X_OK ))
d->shell = "/bin/ksh";
else
// dunno, maybe superfluous?
if (!access( "/usr/ucb/sh", X_OK ))
d->shell = "/usr/ucb/sh";
else
#endif
d->shell = "/bin/sh";
}
#ifdef Q_OS_UNIX
void KProcess::setUsePty(Communication usePty, bool addUtmp)
{
d->usePty = usePty;
d->addUtmp = addUtmp;
if (usePty) {
if (!d->pty)
d->pty = new KPty;
} else {
delete d->pty;
d->pty = 0;
}
}
KPty *KProcess::pty() const
{
return d->pty;
}
#endif //Q_OS_UNIX
QString KProcess::quote(const QString &arg)
{
QChar q('\'');
return QString(arg).replace(q, "'\\''").prepend(q).append(q);
}
// private member functions //
void KProcess::processHasExited(int state)
{
// only successfully run NotifyOnExit processes ever get here
status = state;
runs = false; // do this before commClose, so it knows we're dead
commClose(); // cleanup communication sockets
if (run_mode != DontCare)
emit processExited(this);
}
int KProcess::childOutput(int fdno)
{
if (communication & NoRead) {
int len = -1;
emit receivedStdout(fdno, len);
errno = 0; // Make sure errno doesn't read "EAGAIN"
return len;
}
else
{
char buffer[1025];
int len;
len = ::read(fdno, buffer, 1024);
if (len > 0) {
buffer[len] = 0; // Just in case.
emit receivedStdout(this, buffer, len);
}
return len;
}
}
int KProcess::childError(int fdno)
{
char buffer[1025];
int len;
len = ::read(fdno, buffer, 1024);
if (len > 0) {
buffer[len] = 0; // Just in case.
emit receivedStderr(this, buffer, len);
}
return len;
}
int KProcess::setupCommunication(Communication comm)
{
#ifdef Q_OS_UNIX
// PTY stuff //
if (d->usePty)
{
// cannot communicate on both stderr and stdout if they are both on the pty
if (!(~(comm & d->usePty) & (Stdout | Stderr))) {
kdWarning(175) << "Invalid usePty/communication combination (" << d->usePty << "/" << comm << ")" << endl;
return 0;
}
if (!d->pty->open())
return 0;
int rcomm = comm & d->usePty;
int mfd = d->pty->masterFd();
if (rcomm & Stdin)
in[1] = mfd;
if (rcomm & Stdout)
out[0] = mfd;
if (rcomm & Stderr)
err[0] = mfd;
}
communication = comm;
comm = (Communication) (comm & ~d->usePty);
if (comm & Stdin) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, in))
goto fail0;
fcntl(in[0], F_SETFD, FD_CLOEXEC);
fcntl(in[1], F_SETFD, FD_CLOEXEC);
}
if (comm & Stdout) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, out))
goto fail1;
fcntl(out[0], F_SETFD, FD_CLOEXEC);
fcntl(out[1], F_SETFD, FD_CLOEXEC);
}
if (comm & Stderr) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, err))
goto fail2;
fcntl(err[0], F_SETFD, FD_CLOEXEC);
fcntl(err[1], F_SETFD, FD_CLOEXEC);
}
return 1; // Ok
fail2:
if (comm & Stdout)
{
close(out[0]);
close(out[1]);
out[0] = out[1] = -1;
}
fail1:
if (comm & Stdin)
{
close(in[0]);
close(in[1]);
in[0] = in[1] = -1;
}
fail0:
communication = NoCommunication;
#endif //Q_OS_UNIX
return 0; // Error
}
int KProcess::commSetupDoneP()
{
int rcomm = communication & ~d->usePty;
if (rcomm & Stdin)
close(in[0]);
if (rcomm & Stdout)
close(out[1]);
if (rcomm & Stderr)
close(err[1]);
in[0] = out[1] = err[1] = -1;
// Don't create socket notifiers if no interactive comm is to be expected
if (run_mode != NotifyOnExit && run_mode != OwnGroup)
return 1;
if (communication & Stdin) {
fcntl(in[1], F_SETFL, O_NONBLOCK | fcntl(in[1], F_GETFL));
innot = new QSocketNotifier(in[1], QSocketNotifier::Write, this);
Q_CHECK_PTR(innot);
innot->setEnabled(false); // will be enabled when data has to be sent
QObject::connect(innot, SIGNAL(activated(int)),
this, SLOT(slotSendData(int)));
}
if (communication & Stdout) {
outnot = new QSocketNotifier(out[0], QSocketNotifier::Read, this);
Q_CHECK_PTR(outnot);
QObject::connect(outnot, SIGNAL(activated(int)),
this, SLOT(slotChildOutput(int)));
if (communication & NoRead)
suspend();
}
if (communication & Stderr) {
errnot = new QSocketNotifier(err[0], QSocketNotifier::Read, this );
Q_CHECK_PTR(errnot);
QObject::connect(errnot, SIGNAL(activated(int)),
this, SLOT(slotChildError(int)));
}
return 1;
}
int KProcess::commSetupDoneC()
{
int ok = 1;
#ifdef Q_OS_UNIX
if (d->usePty & Stdin) {
if (dup2(d->pty->slaveFd(), STDIN_FILENO) < 0) ok = 0;
} else if (communication & Stdin) {
if (dup2(in[0], STDIN_FILENO) < 0) ok = 0;
} else {
int null_fd = open( "/dev/null", O_RDONLY );
if (dup2( null_fd, STDIN_FILENO ) < 0) ok = 0;
close( null_fd );
}
struct linger so;
memset(&so, 0, sizeof(so));
if (d->usePty & Stdout) {
if (dup2(d->pty->slaveFd(), STDOUT_FILENO) < 0) ok = 0;
} else if (communication & Stdout) {
if (dup2(out[1], STDOUT_FILENO) < 0 ||
setsockopt(out[1], SOL_SOCKET, SO_LINGER, (char *)&so, sizeof(so)))
ok = 0;
if (communication & MergedStderr) {
if (dup2(out[1], STDERR_FILENO) < 0)
ok = 0;
}
}
if (d->usePty & Stderr) {
if (dup2(d->pty->slaveFd(), STDERR_FILENO) < 0) ok = 0;
} else if (communication & Stderr) {
if (dup2(err[1], STDERR_FILENO) < 0 ||
setsockopt(err[1], SOL_SOCKET, SO_LINGER, (char *)&so, sizeof(so)))
ok = 0;
}
// don't even think about closing all open fds here or anywhere else
// PTY stuff //
if (d->usePty) {
d->pty->setCTty();
if (d->addUtmp)
d->pty->login(KUser(KUser::UseRealUserID).loginName().local8Bit().data(), getenv("DISPLAY"));
}
#endif //Q_OS_UNIX
return ok;
}
void KProcess::commClose()
{
closeStdin();
#ifdef Q_OS_UNIX
if (pid_) { // detached, failed, and killed processes have no output. basta. :)
// If both channels are being read we need to make sure that one socket
// buffer doesn't fill up whilst we are waiting for data on the other
// (causing a deadlock). Hence we need to use select.
int notfd = KProcessController::theKProcessController->notifierFd();
while ((communication & (Stdout | Stderr)) || runs) {
fd_set rfds;
FD_ZERO(&rfds);
struct timeval timeout, *p_timeout;
int max_fd = 0;
if (communication & Stdout) {
FD_SET(out[0], &rfds);
max_fd = out[0];
}
if (communication & Stderr) {
FD_SET(err[0], &rfds);
if (err[0] > max_fd)
max_fd = err[0];
}
if (runs) {
FD_SET(notfd, &rfds);
if (notfd > max_fd)
max_fd = notfd;
// If the process is still running we block until we
// receive data or the process exits.
p_timeout = 0; // no timeout
} else {
// If the process has already exited, we only check
// the available data, we don't wait for more.
timeout.tv_sec = timeout.tv_usec = 0; // timeout immediately
p_timeout = &timeout;
}
int fds_ready = select(max_fd+1, &rfds, 0, 0, p_timeout);
if (fds_ready < 0) {
if (errno == EINTR)
continue;
break;
} else if (!fds_ready)
break;
if ((communication & Stdout) && FD_ISSET(out[0], &rfds))
slotChildOutput(out[0]);
if ((communication & Stderr) && FD_ISSET(err[0], &rfds))
slotChildError(err[0]);
if (runs && FD_ISSET(notfd, &rfds)) {
runs = false; // hack: signal potential exit
return; // don't close anything, we will be called again
}
}
}
#endif //Q_OS_UNIX
closeStdout();
closeStderr();
closePty();
}
void KProcess::virtual_hook( int, void* )
{ /*BASE::virtual_hook( id, data );*/ }
// CC: Class KShellProcess
KShellProcess::KShellProcess(const char *shellname):
KProcess()
{
setUseShell( true, shellname ? shellname : getenv("SHELL") );
}
KShellProcess::~KShellProcess() {
}
QString KShellProcess::quote(const QString &arg)
{
return KProcess::quote(arg);
}
bool KShellProcess::start(RunMode runmode, Communication comm)
{
return KProcess::start(runmode, comm);
}
void KShellProcess::virtual_hook( int id, void* data )
{ KProcess::virtual_hook( id, data ); }
#include "kprocess.moc"
KProcess::setupEnvironment
void setupEnvironment()
Sets up the environment according to the data passed via setEnvironment()
Definition: kprocess.cpp:183
KProcess::run_mode
RunMode run_mode
How to run the process (Block, NotifyOnExit, DontCare).
Definition: kprocess.h:696
KProcess::innot
QSocketNotifier * innot
The socket notifier for in[1].
Definition: kprocess.h:833
KProcess::kill
virtual bool kill(int signo=SIGTERM)
Stop the process (by sending it a signal).
Definition: kprocess.cpp:493
KProcess
Child process invocation, monitoring and control.
Definition: kprocess.h:125
KProcess::slotChildError
void slotChildError(int fdno)
This slot gets activated when data from the child's stderr arrives.
Definition: kprocess.cpp:738
KProcess::NotifyOnExit
The application is notified when the subprocess dies.
Definition: kprocess.h:173
KProcess::errnot
QSocketNotifier * errnot
The socket notifier for err[0].
Definition: kprocess.h:841
KProcess::clearArguments
void clearArguments()
Clear a command line argument list that has been set by using operator<<.
Definition: kprocess.cpp:293
KProcess::outnot
QSocketNotifier * outnot
The socket notifier for out[0].
Definition: kprocess.h:837
KProcess::setWorkingDirectory
void setWorkingDirectory(const QString &dir)
Changes the current working directory (CWD) of the process to be started.
Definition: kprocess.cpp:177
KShellProcess::KShellProcess
KShellProcess(const char *shellname=0)
Constructor.
Definition: kprocess.cpp:1115
KProcessController::theKProcessController
static KProcessController * theKProcessController
Only a single instance of this class is allowed at a time, and this static variable is used to track ...
Definition: kprocctrl.h:60
KProcess::setUseShell
void setUseShell(bool useShell, const char *shell=0)
Specify whether to start the command via a shell or directly.
Definition: kprocess.cpp:765
KShellProcess::~KShellProcess
~KShellProcess()
Destructor.
Definition: kprocess.cpp:1121
KProcess::receivedStderr
void receivedStderr(KProcess *proc, char *buffer, int buflen)
Emitted, when output from the child process has been received on stderr.
KProcess::wait
bool wait(int timeout=-1)
Suspend execution of the current thread until the child process dies or the timeout hits...
Definition: kprocess.cpp:528
KUser::UseRealUserID
Use the real user id.
Definition: kuser.h:51
KProcess::operator<<
KProcess & operator<<(const QString &arg)
Sets the executable and the command line argument list for this process.
Definition: kprocess.cpp:287
KProcess::err
int err[2]
The socket descriptors for stderr.
Definition: kprocess.h:828
KProcess::setExecutable
bool setExecutable(const QString &proc) KDE_DEPRECATED
Definition: kprocess.cpp:255
KProcess::slotSendData
void slotSendData(int dummy)
Called when another bulk of data can be sent to the child's stdin.
Definition: kprocess.cpp:745
KProcess::input_sent
int input_sent
The number of bytes already transmitted.
Definition: kprocess.h:870
KProcess::closeStdout
bool closeStdout()
Shuts down the Stdout communication link.
Definition: kprocess.cpp:674
KProcess::closePty
bool closePty()
Deletes the optional utmp entry and closes the pty.
Definition: kprocess.cpp:702
KProcess::receivedStdout
void receivedStdout(KProcess *proc, char *buffer, int buflen)
Emitted, when output from the child process has been received on stdout.
KProcess::start
virtual bool start(RunMode runmode=NotifyOnExit, Communication comm=NoCommunication)
Starts the process.
Definition: kprocess.cpp:298
KProcess::wroteStdin
void wroteStdin(KProcess *proc)
Emitted after all the data that has been specified by a prior call to writeStdin() has actually been ...
KProcess::~KProcess
virtual ~KProcess()
Destructor:
Definition: kprocess.cpp:225
KProcessController::ref
static void ref()
Create an instance if none exists yet.
Definition: kprocctrl.cpp:39
KProcess::commSetupDoneC
virtual int commSetupDoneC()
Called right after a (successful) fork(), but before an exec() on the child process' side...
Definition: kprocess.cpp:987
KUser
Represents a user on your system.
Definition: kuser.h:45
KProcess::OwnGroup
Same as NotifyOnExit, but the process is run in an own session, just like with DontCare.
Definition: kprocess.h:182
KProcess::setupCommunication
virtual int setupCommunication(Communication comm)
This function is called from start() right before a fork() takes place.
Definition: kprocess.cpp:874
KProcess::slotChildOutput
void slotChildOutput(int fdno)
This slot gets activated when data from the child's stdout arrives.
Definition: kprocess.cpp:731
KProcess::coreDumped
bool coreDumped() const
Checks whether a killed process dumped core.
Definition: kprocess.cpp:606
KProcess::arguments
QValueList< QCString > arguments
The list of the process' command line arguments.
Definition: kprocess.h:691
KProcess::out
int out[2]
The socket descriptors for stdout.
Definition: kprocess.h:820
KProcess::closeStdin
bool closeStdin()
Shuts down the Stdin communication link.
Definition: kprocess.cpp:660
KProcess::pty
KPty * pty() const
Obtains the pty object used by this process.
Definition: kprocess.cpp:803
KProcess::setEnvironment
void setEnvironment(const QString &name, const QString &value)
Adds the variable name to the process' environment.
Definition: kprocess.cpp:171
KProcess::closeAll
void closeAll()
Close stdin, stdout, stderr and the pty.
Definition: kprocess.cpp:717
KProcess::status
int status
The process' exit status as returned by waitpid().
Definition: kprocess.h:721
KProcess::runs
bool runs
true if the process is currently running.
Definition: kprocess.h:703
KProcessController::unscheduleCheck
void unscheduleCheck()
Call this function to defer processing of the data that became available on notifierFd().
Definition: kprocctrl.cpp:170
KProcess::commSetupDoneP
virtual int commSetupDoneP()
Called right after a (successful) fork() on the parent side.
Definition: kprocess.cpp:942
KProcess::communication
Communication communication
Lists the communication links that are activated for the child process.
Definition: kprocess.h:847
KProcess::processHasExited
virtual void processHasExited(int state)
Immediately called after a successfully started process in NotifyOnExit mode has exited.
Definition: kprocess.cpp:821
KProcess::isRunning
bool isRunning() const
Checks whether the process is running.
Definition: kprocess.cpp:504
KProcess::pid
pid_t pid() const
Returns the process id of the process.
Definition: kprocess.cpp:511
KProcess::detach
void detach()
Detaches KProcess from child process.
Definition: kprocess.cpp:240
KProcess::exitSignal
int exitSignal() const
Returns the signal the process was killed by.
Definition: kprocess.cpp:622
KShellProcess::start
virtual bool start(RunMode runmode=NotifyOnExit, Communication comm=NoCommunication)
Starts the process.
Definition: kprocess.cpp:1129
KProcess::exitStatus
int exitStatus() const
Returns the exit status of the process.
Definition: kprocess.cpp:616
KProcess::DontCare
The application does not receive notifications from the subprocess when it is finished or aborted...
Definition: kprocess.h:169
KProcess::processExited
void processExited(KProcess *proc)
Emitted after the process has terminated when the process was run in the NotifyOnExit (==default opti...
KProcess::suspend
void suspend()
Suspend processing of data from stdout of the child process.
Definition: kprocess.cpp:648
KProcess::quote
static QString quote(const QString &arg)
This function can be used to quote an argument string such that the shell processes it properly...
Definition: kprocess.cpp:809
KProcess::input_total
int input_total
The total length of input_data.
Definition: kprocess.h:874
KProcess::childError
int childError(int fdno)
Called by slotChildError() this function copies data arriving from the child process' stderr to the r...
Definition: kprocess.cpp:859
KProcess::writeStdin
bool writeStdin(const char *buffer, int buflen)
Transmit data to the child process' stdin.
Definition: kprocess.cpp:628
KProcess::keepPrivs
bool keepPrivs
If false, the child process' effective uid & gid will be reset to the real values.
Definition: kprocess.h:729
KProcess::normalExit
bool normalExit() const
Checks whether the process exited cleanly.
Definition: kprocess.cpp:594
KProcess::closeStderr
bool closeStderr()
Shuts down the Stderr communication link.
Definition: kprocess.cpp:688
KProcess::Block
The application is suspended until the started process is finished.
Definition: kprocess.h:177
KProcess::setBinaryExecutable
void setBinaryExecutable(const char *filename)
Specify the actual executable that should be started (first argument to execve) Normally the the firs...
Definition: kprocess.cpp:250
KProcess::commClose
virtual void commClose()
Cleans up the communication links to the child after it has exited.
Definition: kprocess.cpp:1037
KProcess::setPriority
bool setPriority(int prio)
Sets the scheduling priority of the process.
Definition: kprocess.cpp:210
KProcessController::rescheduleCheck
void rescheduleCheck()
This function must be called at some point after calling unscheduleCheck().
Definition: kprocctrl.cpp:178
KProcessController::deref
static void deref()
Destroy the instance if one exists and it is not referenced any more.
Definition: kprocctrl.cpp:48
KProcess::resume
void resume()
Resume processing of data from stdout of the child process.
Definition: kprocess.cpp:654
KProcess::in
int in[2]
The socket descriptors for stdin.
Definition: kprocess.h:824
KProcess::pid_
pid_t pid_
The PID of the currently running process.
Definition: kprocess.h:712
KProcess::Communication
Communication
Modes in which the communication channel can be opened.
Definition: kprocess.h:152
endl
kndbgstream & endl(kndbgstream &s)
Does nothing.
Definition: kdebug.h:583
KPty
Provides a high level representation of a pseudo tty pair, including utmp support.
Definition: kpty.h:40
KProcess::signalled
bool signalled() const
Checks whether the process was killed by a signal.
Definition: kprocess.cpp:600
KProcess::runPrivileged
bool runPrivileged() const
Returns whether the started process will drop any setuid/setgid privileges or whether it will keep th...
Definition: kprocess.cpp:204
KProcess::KProcess
KProcess()
Constructor.
Definition: kprocess.cpp:145
KProcess::setRunPrivileged
void setRunPrivileged(bool keepPrivileges)
Controls whether the started process should drop any setuid/setgid privileges or whether it should ke...
Definition: kprocess.cpp:198
KProcess::childOutput
int childOutput(int fdno)
Called by slotChildOutput() this function copies data arriving from the child process' stdout to the ...
Definition: kprocess.cpp:836
KProcess::setUsePty
void setUsePty(Communication comm, bool addUtmp)
Specify whether to create a pty (pseudo-terminal) for running the command.
Definition: kprocess.cpp:790
KProcess::RunMode
RunMode
Run-modes for a child process.
Definition: kprocess.h:164
KProcess::input_data
const char * input_data
The buffer holding the data that has to be sent to the child.
Definition: kprocess.h:866

KDE Home | KDE Accessibility Home | Description of Access Keys