diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-06 15:56:40 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-06 15:56:40 -0600 |
commit | e16866e072f94410321d70daedbcb855ea878cac (patch) | |
tree | ee3f52eabde7da1a0e6ca845fb9c2813cf1558cf /kdesu/process.cpp | |
parent | a58c20c1a7593631a1b50213c805507ebc16adaf (diff) | |
download | tdelibs-e16866e072f94410321d70daedbcb855ea878cac.tar.gz tdelibs-e16866e072f94410321d70daedbcb855ea878cac.zip |
Actually move the kde files that were renamed in the last commit
Diffstat (limited to 'kdesu/process.cpp')
-rw-r--r-- | kdesu/process.cpp | 626 |
1 files changed, 0 insertions, 626 deletions
diff --git a/kdesu/process.cpp b/kdesu/process.cpp deleted file mode 100644 index d52308f63..000000000 --- a/kdesu/process.cpp +++ /dev/null @@ -1,626 +0,0 @@ -/* vi: ts=8 sts=4 sw=4 - * - * $Id$ - * - * This file is part of the KDE project, module tdesu. - * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org> - * - * This file contains code from TEShell.C of the KDE konsole. - * Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> - * - * This is free software; you can use this library under the GNU Library - * General Public License, version 2. See the file "COPYING.LIB" for the - * exact licensing terms. - * - * process.cpp: Functionality to build a front end to password asking - * terminal programs. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <signal.h> -#include <errno.h> -#include <string.h> -#include <termios.h> -#include <signal.h> - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <sys/ioctl.h> - -#if defined(__SVR4) && defined(sun) -#include <stropts.h> -#include <sys/stream.h> -#endif - -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> // Needed on some systems. -#endif - -#include <tqglobal.h> -#include <tqcstring.h> -#include <tqfile.h> - -#include <kconfig.h> -#include <kdebug.h> -#include <kstandarddirs.h> - -#include "process.h" -#include "tdesu_pty.h" -#include "kcookie.h" - -int PtyProcess::waitMS(int fd,int ms) -{ - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 1000*ms; - - fd_set fds; - FD_ZERO(&fds); - FD_SET(fd,&fds); - return select(fd+1, &fds, 0L, 0L, &tv); -} - -/* -** Basic check for the existence of @p pid. -** Returns true iff @p pid is an extant process. -*/ -bool PtyProcess::checkPid(pid_t pid) -{ - KConfig* config = KGlobal::config(); - config->setGroup("super-user-command"); - TQString superUserCommand = config->readEntry("super-user-command", DEFAULT_SUPER_USER_COMMAND); - //sudo does not accept signals from user so we except it - if (superUserCommand == "sudo") { - return true; - } else { - return kill(pid,0) == 0; - } -} - -/* -** Check process exit status for process @p pid. -** On error (no child, no exit), return Error (-1). -** If child @p pid has exited, return its exit status, -** (which may be zero). -** If child @p has not exited, return NotExited (-2). -*/ - -int PtyProcess::checkPidExited(pid_t pid) -{ - int state, ret; - ret = waitpid(pid, &state, WNOHANG); - - if (ret < 0) - { - kdError(900) << k_lineinfo << "waitpid(): " << perror << "\n"; - return Error; - } - if (ret == pid) - { - if (WIFEXITED(state)) - return WEXITSTATUS(state); - return Killed; - } - - return NotExited; -} - - -class PtyProcess::PtyProcessPrivate -{ -public: - QCStringList env; -}; - - -PtyProcess::PtyProcess() -{ - m_bTerminal = false; - m_bErase = false; - m_pPTY = 0L; - d = new PtyProcessPrivate; -} - - -int PtyProcess::init() -{ - delete m_pPTY; - m_pPTY = new PTY(); - m_Fd = m_pPTY->getpt(); - if (m_Fd < 0) - return -1; - if ((m_pPTY->grantpt() < 0) || (m_pPTY->unlockpt() < 0)) - { - kdError(900) << k_lineinfo << "Master setup failed.\n"; - m_Fd = -1; - return -1; - } - m_TTY = m_pPTY->ptsname(); - m_Inbuf.resize(0); - return 0; -} - - -PtyProcess::~PtyProcess() -{ - delete m_pPTY; - delete d; -} - -/** Set additinal environment variables. */ -void PtyProcess::setEnvironment( const QCStringList &env ) -{ - d->env = env; -} - -const QCStringList& PtyProcess::environment() const -{ - return d->env; -} - -/* - * Read one line of input. The terminal is in canonical mode, so you always - * read a line at at time, but it's possible to receive multiple lines in - * one time. - */ - -TQCString PtyProcess::readLine(bool block) -{ - int pos; - TQCString ret; - - if (!m_Inbuf.isEmpty()) - { - pos = m_Inbuf.find('\n'); - if (pos == -1) - { - ret = m_Inbuf; - m_Inbuf.resize(0); - } else - { - ret = m_Inbuf.left(pos); - m_Inbuf = m_Inbuf.mid(pos+1); - } - return ret; - } - - int flags = fcntl(m_Fd, F_GETFL); - if (flags < 0) - { - kdError(900) << k_lineinfo << "fcntl(F_GETFL): " << perror << "\n"; - return ret; - } - int oflags = flags; - if (block) - flags &= ~O_NONBLOCK; - else - flags |= O_NONBLOCK; - - if ((flags != oflags) && (fcntl(m_Fd, F_SETFL, flags) < 0)) - { - // We get an error here when the child process has closed - // the file descriptor already. - return ret; - } - - int nbytes; - char buf[256]; - while (1) - { - nbytes = read(m_Fd, buf, 255); - if (nbytes == -1) - { - if (errno == EINTR) - continue; - else break; - } - if (nbytes == 0) - break; // eof - - buf[nbytes] = '\000'; - m_Inbuf += buf; - - pos = m_Inbuf.find('\n'); - if (pos == -1) - { - ret = m_Inbuf; - m_Inbuf.resize(0); - } else - { - ret = m_Inbuf.left(pos); - m_Inbuf = m_Inbuf.mid(pos+1); - } - break; - } - - return ret; -} - -TQCString PtyProcess::readAll(bool block) -{ - TQCString ret; - - if (!m_Inbuf.isEmpty()) - { - // if there is still something in the buffer, we need not block. - // we should still try to read any further output, from the fd, though. - block = false; - ret = m_Inbuf; - m_Inbuf.resize(0); - } - - int flags = fcntl(m_Fd, F_GETFL); - if (flags < 0) - { - kdError(900) << k_lineinfo << "fcntl(F_GETFL): " << perror << "\n"; - return ret; - } - int oflags = flags; - if (block) - flags &= ~O_NONBLOCK; - else - flags |= O_NONBLOCK; - - if ((flags != oflags) && (fcntl(m_Fd, F_SETFL, flags) < 0)) - { - // We get an error here when the child process has closed - // the file descriptor already. - return ret; - } - - int nbytes; - char buf[256]; - while (1) - { - nbytes = read(m_Fd, buf, 255); - if (nbytes == -1) - { - if (errno == EINTR) - continue; - else break; - } - if (nbytes == 0) - break; // eof - - buf[nbytes] = '\000'; - ret += buf; - break; - } - - return ret; -} - - -void PtyProcess::writeLine(const TQCString &line, bool addnl) -{ - if (!line.isEmpty()) - write(m_Fd, line, line.length()); - if (addnl) - write(m_Fd, "\n", 1); -} - - -void PtyProcess::unreadLine(const TQCString &line, bool addnl) -{ - TQCString tmp = line; - if (addnl) - tmp += '\n'; - if (!tmp.isEmpty()) - m_Inbuf.prepend(tmp); -} - -/* - * Fork and execute the command. This returns in the parent. - */ - -int PtyProcess::exec(const TQCString &command, const QCStringList &args) -{ - kdDebug(900) << k_lineinfo << "Running `" << command << "'\n"; - - if (init() < 0) - return -1; - - // Open the pty slave before forking. See SetupTTY() - int slave = open(m_TTY, O_RDWR); - if (slave < 0) - { - kdError(900) << k_lineinfo << "Could not open slave pty.\n"; - return -1; - } - - if ((m_Pid = fork()) == -1) - { - kdError(900) << k_lineinfo << "fork(): " << perror << "\n"; - return -1; - } - - // Parent - if (m_Pid) - { - close(slave); - return 0; - } - - // Child - if (SetupTTY(slave) < 0) - _exit(1); - - for(QCStringList::ConstIterator it = d->env.begin(); - it != d->env.end(); it++) - { - putenv(const_cast<TQCString&>(*it).data()); - } - unsetenv("TDE_FULL_SESSION"); - - // set temporarily LC_ALL to C, for su (to be able to parse "Password:") - const char* old_lc_all = getenv( "LC_ALL" ); - if( old_lc_all != NULL ) - setenv( "KDESU_LC_ALL", old_lc_all, 1 ); - else - unsetenv( "KDESU_LC_ALL" ); - setenv("LC_ALL", "C", 1); - - // From now on, terminal output goes through the tty. - - TQCString path; - if (command.contains('/')) - path = command; - else - { - TQString file = KStandardDirs::findExe(command); - if (file.isEmpty()) - { - kdError(900) << k_lineinfo << command << " not found\n"; - _exit(1); - } - path = TQFile::encodeName(file); - } - - const char **argp = (const char **)malloc((args.count()+2)*sizeof(char *)); - int i = 0; - argp[i++] = path; - for (QCStringList::ConstIterator it=args.begin(); it!=args.end(); ++it) - argp[i++] = *it; - - argp[i] = 0L; - - execv(path, (char * const *)argp); - kdError(900) << k_lineinfo << "execv(\"" << path << "\"): " << perror << "\n"; - _exit(1); - return -1; // Shut up compiler. Never reached. -} - - -/* - * Wait until the terminal is set into no echo mode. At least one su - * (RH6 w/ Linux-PAM patches) sets noecho mode AFTER writing the Password: - * prompt, using TCSAFLUSH. This flushes the terminal I/O queues, possibly - * taking the password with it. So we wait until no echo mode is set - * before writing the password. - * Note that this is done on the slave fd. While Linux allows tcgetattr() on - * the master side, Solaris doesn't. - */ - -int PtyProcess::WaitSlave() -{ - int slave = open(m_TTY, O_RDWR); - if (slave < 0) - { - kdError(900) << k_lineinfo << "Could not open slave tty.\n"; - return -1; - } - - kdDebug(900) << k_lineinfo << "Child pid " << m_Pid << endl; - - struct termios tio; - while (1) - { - if (!checkPid(m_Pid)) - { - close(slave); - return -1; - } - if (tcgetattr(slave, &tio) < 0) - { - kdError(900) << k_lineinfo << "tcgetattr(): " << perror << "\n"; - close(slave); - return -1; - } - if (tio.c_lflag & ECHO) - { - kdDebug(900) << k_lineinfo << "Echo mode still on.\n"; - waitMS(slave,100); - continue; - } - break; - } - close(slave); - return 0; -} - - -int PtyProcess::enableLocalEcho(bool enable) -{ - int slave = open(m_TTY, O_RDWR); - if (slave < 0) - { - kdError(900) << k_lineinfo << "Could not open slave tty.\n"; - return -1; - } - struct termios tio; - if (tcgetattr(slave, &tio) < 0) - { - kdError(900) << k_lineinfo << "tcgetattr(): " << perror << "\n"; - close(slave); return -1; - } - if (enable) - tio.c_lflag |= ECHO; - else - tio.c_lflag &= ~ECHO; - if (tcsetattr(slave, TCSANOW, &tio) < 0) - { - kdError(900) << k_lineinfo << "tcsetattr(): " << perror << "\n"; - close(slave); return -1; - } - close(slave); - return 0; -} - - -/* - * Copy output to stdout until the child process exists, or a line of output - * matches `m_Exit'. - * We have to use waitpid() to test for exit. Merely waiting for EOF on the - * pty does not work, because the target process may have children still - * attached to the terminal. - */ - -int PtyProcess::waitForChild() -{ - int retval = 1; - - fd_set fds; - FD_ZERO(&fds); - - while (1) - { - FD_SET(m_Fd, &fds); - int ret = select(m_Fd+1, &fds, 0L, 0L, 0L); - if (ret == -1) - { - if (errno != EINTR) - { - kdError(900) << k_lineinfo << "select(): " << perror << "\n"; - return -1; - } - ret = 0; - } - - if (ret) - { - TQCString output = readAll(false); - bool lineStart = true; - while (!output.isNull()) - { - if (!m_Exit.isEmpty()) - { - // match exit string only at line starts - int pos = output.find(m_Exit.data()); - if ((pos >= 0) && ((pos == 0 && lineStart) || (output.at (pos - 1) == '\n'))) - { - kill(m_Pid, SIGTERM); - } - } - if (m_bTerminal) - { - fputs(output, stdout); - fflush(stdout); - } - lineStart = output.tqat( output.length() - 1 ) == '\n'; - output = readAll(false); - } - } - - ret = checkPidExited(m_Pid); - if (ret == Error) - { - if (errno == ECHILD) retval = 0; - else retval = 1; - break; - } - else if (ret == Killed) - { - retval = 0; - break; - } - else if (ret == NotExited) - { - // keep checking - } - else - { - retval = ret; - break; - } - } - return retval; -} - -/* - * SetupTTY: Creates a new session. The filedescriptor "fd" should be - * connected to the tty. It is closed after the tty is reopened to make it - * our controlling terminal. This way the tty is always opened at least once - * so we'll never get EIO when reading from it. - */ - -int PtyProcess::SetupTTY(int fd) -{ - // Reset signal handlers - for (int sig = 1; sig < NSIG; sig++) - signal(sig, SIG_DFL); - signal(SIGHUP, SIG_IGN); - - // Close all file handles - struct rlimit rlp; - getrlimit(RLIMIT_NOFILE, &rlp); - for (int i = 0; i < (int)rlp.rlim_cur; i++) - if (i != fd) close(i); - - // Create a new session. - setsid(); - - // Open slave. This will make it our controlling terminal - int slave = open(m_TTY, O_RDWR); - if (slave < 0) - { - kdError(900) << k_lineinfo << "Could not open slave side: " << perror << "\n"; - return -1; - } - close(fd); - -#if defined(__SVR4) && defined(sun) - - // Solaris STREAMS environment. - // Push these modules to make the stream look like a terminal. - ioctl(slave, I_PUSH, "ptem"); - ioctl(slave, I_PUSH, "ldterm"); - -#endif - -#ifdef TIOCSCTTY - ioctl(slave, TIOCSCTTY, NULL); -#endif - - // Connect stdin, stdout and stderr - dup2(slave, 0); dup2(slave, 1); dup2(slave, 2); - if (slave > 2) - close(slave); - - // Disable OPOST processing. Otherwise, '\n' are (on Linux at least) - // translated to '\r\n'. - struct termios tio; - if (tcgetattr(0, &tio) < 0) - { - kdError(900) << k_lineinfo << "tcgetattr(): " << perror << "\n"; - return -1; - } - tio.c_oflag &= ~OPOST; - if (tcsetattr(0, TCSANOW, &tio) < 0) - { - kdError(900) << k_lineinfo << "tcsetattr(): " << perror << "\n"; - return -1; - } - - return 0; -} - -void PtyProcess::virtual_hook( int, void* ) -{ /*BASE::virtual_hook( id, data );*/ } |