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>
51 #include <tdeconfig.h>
53 #include <kstandarddirs.h>
56 #include "tdesu_pty.h"
68 return select(
fd+1, &fds, 0L, 0L, &tv);
77 TDEConfig* config = TDEGlobal::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();
142 kdError(900) << k_lineinfo <<
"Master setup failed.\n";
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(
"TDESU_LC_ALL", old_lc_all, 1 );
369 unsetenv(
"TDESU_LC_ALL" );
370 setenv(
"LC_ALL",
"C", 1);
375 if (command.contains(
'/'))
379 TQString file = TDEStandardDirs::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.
int unlockpt()
Unlock the slave side.
int grantpt()
Grant access to the slave side.
TQCString ptsname()
Get the slave name.
int getpt()
Allocate a pty.
static int waitMS(int fd, int ms)
Wait ms miliseconds (ie.
int fd()
Returns the filedescriptor of the process.
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.
static bool checkPid(pid_t pid)
Basic check for the existence of pid.
TQCString readLine(bool block=true)
Reads a line from the program's standard out.
TQCString readAll(bool block=true)
Read all available output from the program's standard out.
int enableLocalEcho(bool enable=true)
Enables/disables local echo on the pseudo tty.
void setEnvironment(const QCStringList &env)
Set additinal environment variables.
int WaitSlave()
Waits until the pty has cleared the ECHO flag.
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.