31 #include <sys/types.h> 35 #include <sys/resource.h> 36 #include <sys/ioctl.h> 38 #if defined(__SVR4) && defined(sun) 40 #include <sys/stream.h> 43 #ifdef HAVE_SYS_SELECT_H 44 #include <sys/select.h> 48 #include <tqcstring.h> 53 #include <kstandarddirs.h> 56 #include "kdesu_pty.h" 68 return select(fd+1, &fds, 0L, 0L, &tv);
77 KConfig* config = KGlobal::config();
78 config->setGroup(
"super-user-command");
79 TQString superUserCommand = config->readEntry(
"super-user-command", DEFAULT_SUPER_USER_COMMAND);
81 if (superUserCommand ==
"sudo") {
84 return kill(pid,0) == 0;
96 int PtyProcess::checkPidExited(pid_t
pid)
99 ret = waitpid(pid, &state, WNOHANG);
103 kdError(900) << k_lineinfo <<
"waitpid(): " << perror <<
"\n";
108 if (WIFEXITED(state))
109 return WEXITSTATUS(state);
117 class PtyProcess::PtyProcessPrivate
124 PtyProcess::PtyProcess()
129 d =
new PtyProcessPrivate;
133 int PtyProcess::init()
137 m_Fd = m_pPTY->getpt();
140 if ((m_pPTY->grantpt() < 0) || (m_pPTY->unlockpt() < 0))
142 kdError(900) << k_lineinfo <<
"Master setup failed.\n";
146 m_TTY = m_pPTY->ptsname();
152 PtyProcess::~PtyProcess()
164 const QCStringList& PtyProcess::environment()
const 180 if (!m_Inbuf.isEmpty())
182 pos = m_Inbuf.find(
'\n');
189 ret = m_Inbuf.left(pos);
190 m_Inbuf = m_Inbuf.mid(pos+1);
195 int flags = fcntl(m_Fd, F_GETFL);
198 kdError(900) << k_lineinfo <<
"fcntl(F_GETFL): " << perror <<
"\n";
203 flags &= ~O_NONBLOCK;
207 if ((flags != oflags) && (fcntl(m_Fd, F_SETFL, flags) < 0))
218 nbytes = read(m_Fd, buf, 255);
228 buf[nbytes] =
'\000';
231 pos = m_Inbuf.find(
'\n');
238 ret = m_Inbuf.left(pos);
239 m_Inbuf = m_Inbuf.mid(pos+1);
251 if (!m_Inbuf.isEmpty())
260 int flags = fcntl(m_Fd, F_GETFL);
263 kdError(900) << k_lineinfo <<
"fcntl(F_GETFL): " << perror <<
"\n";
268 flags &= ~O_NONBLOCK;
272 if ((flags != oflags) && (fcntl(m_Fd, F_SETFL, flags) < 0))
283 nbytes = read(m_Fd, buf, 255);
293 buf[nbytes] =
'\000';
305 write(m_Fd, line, line.length());
307 write(m_Fd,
"\n", 1);
313 TQCString tmp = line;
317 m_Inbuf.prepend(tmp);
326 kdDebug(900) << k_lineinfo <<
"Running `" << command <<
"'\n";
332 int slave = open(m_TTY, O_RDWR);
335 kdError(900) << k_lineinfo <<
"Could not open slave pty.\n";
339 if ((m_Pid = fork()) == -1)
341 kdError(900) << k_lineinfo <<
"fork(): " << perror <<
"\n";
353 if (SetupTTY(slave) < 0)
356 for(QCStringList::ConstIterator it = d->env.begin();
357 it != d->env.end(); it++)
359 putenv(const_cast<TQCString&>(*it).data());
361 unsetenv(
"TDE_FULL_SESSION");
362 unsetenv(
"XDG_RUNTIME_DIR");
365 const char* old_lc_all = getenv(
"LC_ALL" );
366 if( old_lc_all != NULL )
367 setenv(
"KDESU_LC_ALL", old_lc_all, 1 );
369 unsetenv(
"KDESU_LC_ALL" );
370 setenv(
"LC_ALL",
"C", 1);
375 if (command.contains(
'/'))
379 TQString file = KStandardDirs::findExe(command);
382 kdError(900) << k_lineinfo << command <<
" not found\n";
385 path = TQFile::encodeName(file);
388 const char **argp = (
const char **)malloc((args.count()+2)*
sizeof(
char *));
391 for (QCStringList::ConstIterator it=args.begin(); it!=args.end(); ++it)
396 execv(path, (
char *
const *)argp);
397 kdError(900) << k_lineinfo <<
"execv(\"" << path <<
"\"): " << perror <<
"\n";
415 int slave = open(m_TTY, O_RDWR);
418 kdError(900) << k_lineinfo <<
"Could not open slave tty.\n";
422 kdDebug(900) << k_lineinfo <<
"Child pid " << m_Pid << endl;
432 if (tcgetattr(slave, &tio) < 0)
434 kdError(900) << k_lineinfo <<
"tcgetattr(): " << perror <<
"\n";
438 if (tio.c_lflag & ECHO)
440 kdDebug(900) << k_lineinfo <<
"Echo mode still on.\n";
453 int slave = open(m_TTY, O_RDWR);
456 kdError(900) << k_lineinfo <<
"Could not open slave tty.\n";
460 if (tcgetattr(slave, &tio) < 0)
462 kdError(900) << k_lineinfo <<
"tcgetattr(): " << perror <<
"\n";
463 close(slave);
return -1;
468 tio.c_lflag &= ~ECHO;
469 if (tcsetattr(slave, TCSANOW, &tio) < 0)
471 kdError(900) << k_lineinfo <<
"tcsetattr(): " << perror <<
"\n";
472 close(slave);
return -1;
501 ret = select(m_Fd+1, &fds, 0L, 0L, 0L);
507 kdError(900) << k_lineinfo <<
"select(): " << perror <<
"\n";
515 TQCString output =
readAll(
false);
516 bool lineStart =
true;
517 while (!output.isNull())
519 if (!m_Exit.isEmpty())
522 int pos = output.find(m_Exit.data());
523 if ((pos >= 0) && ((pos == 0 && lineStart) || (output.at (pos - 1) ==
'\n')))
525 kill(m_Pid, SIGTERM);
530 fputs(output, stdout);
533 lineStart = output.at( output.length() - 1 ) ==
'\n';
538 ret = checkPidExited(m_Pid);
541 if (errno == ECHILD) retval = 0;
545 else if (ret == Killed)
550 else if (ret == NotExited)
570 int PtyProcess::SetupTTY(
int fd)
573 for (
int sig = 1; sig < NSIG; sig++)
574 signal(sig, SIG_DFL);
575 signal(SIGHUP, SIG_IGN);
579 getrlimit(RLIMIT_NOFILE, &rlp);
580 for (
int i = 0; i < (int)rlp.rlim_cur; i++)
581 if (i != fd) close(i);
587 int slave = open(m_TTY, O_RDWR);
590 kdError(900) << k_lineinfo <<
"Could not open slave side: " << perror <<
"\n";
595 #if defined(__SVR4) && defined(sun) 599 ioctl(slave, I_PUSH,
"ptem");
600 ioctl(slave, I_PUSH,
"ldterm");
605 ioctl(slave, TIOCSCTTY, NULL);
609 dup2(slave, 0); dup2(slave, 1); dup2(slave, 2);
616 if (tcgetattr(0, &tio) < 0)
618 kdError(900) << k_lineinfo <<
"tcgetattr(): " << perror <<
"\n";
621 tio.c_oflag &= ~OPOST;
622 if (tcsetattr(0, TCSANOW, &tio) < 0)
624 kdError(900) << k_lineinfo <<
"tcsetattr(): " << perror <<
"\n";
631 void PtyProcess::virtual_hook(
int,
void* )
PTY compatibility routines.
void writeLine(const TQCString &line, bool addNewline=true)
Writes a line of text to the program's standard in.
int pid()
Returns the pid of the process.
int waitForChild()
Waits for the child to exit.
int WaitSlave()
Waits until the pty has cleared the ECHO flag.
void setEnvironment(const QCStringList &env)
Set additinal environment variables.
int exec(const TQCString &command, const QCStringList &args)
Forks off and execute a command.
void unreadLine(const TQCString &line, bool addNewline=true)
Puts back a line of input.
int enableLocalEcho(bool enable=true)
Enables/disables local echo on the pseudo tty.
TQCString readLine(bool block=true)
Reads a line from the program's standard out.
static bool checkPid(pid_t pid)
Basic check for the existence of pid.
TQCString readAll(bool block=true)
Read all available output from the program's standard out.
static int waitMS(int fd, int ms)
Wait ms miliseconds (ie.
int fd()
Returns the filedescriptor of the process.