KDESu
13 #include "ptyprocess.h"
14 #include "kcookie_p.h"
15 #include "ptyprocess_p.h"
17 #include <config-kdesu.h>
18 #include <ksu_debug.h>
27 #include <sys/resource.h>
33 #include <sys/select.h>
37 #include <QStandardPaths>
39 #include <KConfigGroup>
40 #include <KSharedConfig>
42 extern int kdesuDebugArea();
46 using namespace KDESuPrivate;
58 tv.tv_usec = 1000 * ms;
63 return select(fd + 1, &fds,
nullptr,
nullptr, &tv);
82 return kill(pid, 0) == 0;
97 ret = waitpid(pid, &state, WNOHANG);
100 qCCritical(KSU_LOG) <<
"[" << __FILE__ <<
":" << __LINE__ <<
"] "
101 <<
"waitpid():" << strerror(errno);
105 if (WIFEXITED(state)) {
106 return WEXITSTATUS(state);
115 PtyProcess::PtyProcess()
120 PtyProcess::PtyProcess(PtyProcessPrivate &dd)
127 PtyProcess::~PtyProcess() =
default;
129 int PtyProcess::init()
133 if (!d->pty->open()) {
134 qCCritical(KSU_LOG) <<
"[" << __FILE__ <<
":" << __LINE__ <<
"] "
135 <<
"Failed to open PTY.";
138 if (!d->wantLocalEcho) {
141 d->inputBuffer.resize(0);
153 return d->pty ? d->pty->masterFd() : -1;
170 if (!d->inputBuffer.isEmpty()) {
174 ret = d->inputBuffer;
175 d->inputBuffer.resize(0);
178 int flags = fcntl(
fd(), F_GETFL);
180 qCCritical(KSU_LOG) <<
"[" << __FILE__ <<
":" << __LINE__ <<
"] "
181 <<
"fcntl(F_GETFL):" << strerror(errno);
186 flags &= ~O_NONBLOCK;
191 if ((flags != oflags) && (fcntl(
fd(), F_SETFL, flags) < 0)) {
199 int nbytes = read(
fd(), ret.
data() + ret.
size(), 0x8000);
201 if (errno == EINTR) {
220 d->inputBuffer =
readAll(block);
224 if (!d->inputBuffer.isEmpty()) {
225 pos = d->inputBuffer.indexOf(
'\n');
228 ret = d->inputBuffer;
229 d->inputBuffer.resize(0);
231 ret = d->inputBuffer.left(pos);
232 d->inputBuffer.remove(0, pos + 1);
245 write(
fd(),
"\n", 1);
256 d->inputBuffer.prepend(tmp);
276 if ((
m_pid = fork()) == -1) {
277 qCCritical(KSU_LOG) <<
"[" << __FILE__ <<
":" << __LINE__ <<
"] "
278 <<
"fork():" << strerror(errno);
284 d->pty->closeSlave();
289 if (setupTTY() < 0) {
293 for (
const QByteArray &var : std::as_const(d->env)) {
294 putenv(
const_cast<char *
>(var.constData()));
296 unsetenv(
"KDE_FULL_SESSION");
298 unsetenv(
"SESSION_MANAGER");
301 unsetenv(
"DBUS_SESSION_BUS_ADDRESS");
304 const QByteArray old_lc_all = qgetenv(
"LC_ALL");
306 qputenv(
"KDESU_LC_ALL", old_lc_all);
308 unsetenv(
"KDESU_LC_ALL");
310 qputenv(
"LC_ALL",
"C");
320 qCCritical(KSU_LOG) <<
"[" << __FILE__ <<
":" << __LINE__ <<
"] " << command <<
"not found.";
326 const char **argp = (
const char **)malloc((args.
count() + 2) *
sizeof(
char *));
331 argp[i++] = arg.constData();
336 execv(path.
constData(),
const_cast<char **
>(argp));
337 qCCritical(KSU_LOG) <<
"[" << __FILE__ <<
":" << __LINE__ <<
"] "
338 <<
"execv(" << path <<
"):" << strerror(errno);
357 qCCritical(KSU_LOG) <<
"process has exited while waiting for password.";
360 if (!d->pty->tcGetAttr(&tio)) {
361 qCCritical(KSU_LOG) <<
"[" << __FILE__ <<
":" << __LINE__ <<
"] "
362 <<
"tcgetattr():" << strerror(errno);
365 if (tio.c_lflag & ECHO) {
377 d->wantLocalEcho = enable;
383 return d->pty->setEcho(enable) ? 0 : -1;
418 timeout.tv_usec = 100000;
419 int ret = select(
fd() + 1, &fds,
nullptr,
nullptr, &timeout);
421 if (errno != EINTR) {
422 qCCritical(KSU_LOG) <<
"[" << __FILE__ <<
":" << __LINE__ <<
"] "
423 <<
"select():" << strerror(errno);
444 kill(
m_pid, SIGTERM);
447 int off = remainder.
indexOf(
'\n');
451 remainder.
remove(0, off + 1);
459 if (errno == ECHILD) {
464 }
else if (ret ==
Killed) {
480 int PtyProcess::setupTTY()
483 for (
int sig = 1; sig < NSIG; sig++) {
484 signal(sig, SIG_DFL);
486 signal(SIGHUP, SIG_IGN);
491 int slave = d->pty->slaveFd();
500 getrlimit(RLIMIT_NOFILE, &rlp);
501 for (
int i = 3; i < (int)rlp.rlim_cur; i++) {
507 struct ::termios tio;
508 if (tcgetattr(0, &tio) < 0) {
509 qCCritical(KSU_LOG) <<
"[" << __FILE__ <<
":" << __LINE__ <<
"] "
510 <<
"tcgetattr():" << strerror(errno);
513 tio.c_oflag &= ~OPOST;
514 if (tcsetattr(0, TCSANOW, &tio) < 0) {
515 qCCritical(KSU_LOG) <<
"[" << __FILE__ <<
":" << __LINE__ <<
"] "
516 <<
"tcsetattr():" << strerror(errno);
QString readEntry(const char *key, const char *aDefault=nullptr) const
void setErase(bool erase)
Overwrites the password as soon as it is used.
const QChar * constData() const const
QByteArray readAll(bool block=true)
Read all available output from the program's standard out.
void writeLine(const QByteArray &line, bool addNewline=true)
Writes a line of text to the program's standard in.
int indexOf(char ch, int from) const const
void setEnvironment(const QList< QByteArray > &env)
Set additinal environment variables.
static bool checkPid(pid_t pid)
Basic check for the existence of pid.
int enableLocalEcho(bool enable=true)
Enables/disables local echo on the pseudo tty.
int count(const T &value) const const
QByteArray encodeName(const QString &fileName)
static int waitMS(int fd, int ms)
Wait ms milliseconds (ie.
@ NotExited
Child hasn't exited.
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
@ Killed
Child terminated by signal.
QString findExecutable(const QString &executableName, const QStringList &paths)
QByteArray & remove(int pos, int len)
QByteArray readLine(bool block=true)
Reads a line from the program's standard out.
virtual void virtual_hook(int id, void *data)
Standard hack to add virtual methods in a BC way.
int exec(const QByteArray &command, const QList< QByteArray > &args)
Forks off and execute a command.
static int checkPidExited(pid_t pid)
Check process exit status for process pid.
int waitForChild()
Waits for the child to exit.
QList< QByteArray > environment() const
Returns the additional environment variables set by setEnvironment()
bool isEmpty() const const
int waitSlave()
Waits until the pty has cleared the ECHO flag.
int m_pid
PID of child process.
bool startsWith(const QByteArray &ba) const const
QByteArray m_exitString
String to scan for in output that indicates child has exited.
KSharedConfigPtr config()
bool m_terminal
Indicates running in a terminal, causes additional newlines to be printed after output.
bool contains(char ch) const const
bool isEmpty() const const
const char * constData() const const
void setTerminal(bool terminal)
Enables/disables terminal output.
int pid() const
Returns the pid of the process.
int fd() const
Returns the filedescriptor of the process.
void setExitString(const QByteArray &exit)
Sets the exit string.
void unreadLine(const QByteArray &line, bool addNewline=true)
Puts back a line of input.
QString decodeName(const QByteArray &localFileName)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Fri Sep 29 2023 04:02:38 by
doxygen 1.8.17 written
by
Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.