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();
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");
364 const char* old_lc_all = getenv(
"LC_ALL" );
365 if( old_lc_all != NULL )
366 setenv(
"TDESU_LC_ALL", old_lc_all, 1 );
368 unsetenv(
"TDESU_LC_ALL" );
369 setenv(
"LC_ALL",
"C", 1);
374 if (command.contains(
'/'))
378 TQString file = TDEStandardDirs::findExe(command);
381 kdError(900) << k_lineinfo << command <<
" not found\n";
384 path = TQFile::encodeName(file);
387 const char **argp = (
const char **)malloc((args.count()+2)*
sizeof(
char *));
390 for (QCStringList::ConstIterator it=args.begin(); it!=args.end(); ++it)
395 execv(path, (
char *
const *)argp);
396 kdError(900) << k_lineinfo <<
"execv(\"" << path <<
"\"): " << perror <<
"\n";
414 int slave = open(m_TTY, O_RDWR);
417 kdError(900) << k_lineinfo <<
"Could not open slave tty.\n";
421 kdDebug(900) << k_lineinfo <<
"Child pid " << m_Pid << endl;
431 if (tcgetattr(slave, &tio) < 0)
433 kdError(900) << k_lineinfo <<
"tcgetattr(): " << perror <<
"\n";
437 if (tio.c_lflag & ECHO)
439 kdDebug(900) << k_lineinfo <<
"Echo mode still on.\n";
452 int slave = open(m_TTY, O_RDWR);
455 kdError(900) << k_lineinfo <<
"Could not open slave tty.\n";
459 if (tcgetattr(slave, &tio) < 0)
461 kdError(900) << k_lineinfo <<
"tcgetattr(): " << perror <<
"\n";
462 close(slave);
return -1;
467 tio.c_lflag &= ~ECHO;
468 if (tcsetattr(slave, TCSANOW, &tio) < 0)
470 kdError(900) << k_lineinfo <<
"tcsetattr(): " << perror <<
"\n";
471 close(slave);
return -1;
500 ret = select(m_Fd+1, &fds, 0L, 0L, 0L);
506 kdError(900) << k_lineinfo <<
"select(): " << perror <<
"\n";
514 TQCString output =
readAll(
false);
515 bool lineStart =
true;
516 while (!output.isNull())
518 if (!m_Exit.isEmpty())
521 int pos = output.find(m_Exit.data());
522 if ((pos >= 0) && ((pos == 0 && lineStart) || (output.at (pos - 1) ==
'\n')))
524 kill(m_Pid, SIGTERM);
529 fputs(output, stdout);
532 lineStart = output.at( output.length() - 1 ) ==
'\n';
537 ret = checkPidExited(m_Pid);
540 if (errno == ECHILD) retval = 0;
544 else if (ret == Killed)
549 else if (ret == NotExited)
569 int PtyProcess::SetupTTY(
int fd)
572 for (
int sig = 1; sig < NSIG; sig++)
573 signal(sig, SIG_DFL);
574 signal(SIGHUP, SIG_IGN);
578 getrlimit(RLIMIT_NOFILE, &rlp);
579 for (
int i = 0; i < (int)rlp.rlim_cur; i++)
580 if (i != fd) close(i);
586 int slave = open(m_TTY, O_RDWR);
589 kdError(900) << k_lineinfo <<
"Could not open slave side: " << perror <<
"\n";
594 #if defined(__SVR4) && defined(sun) 598 ioctl(slave, I_PUSH,
"ptem");
599 ioctl(slave, I_PUSH,
"ldterm");
604 ioctl(slave, TIOCSCTTY, NULL);
608 dup2(slave, 0); dup2(slave, 1); dup2(slave, 2);
615 if (tcgetattr(0, &tio) < 0)
617 kdError(900) << k_lineinfo <<
"tcgetattr(): " << perror <<
"\n";
620 tio.c_oflag &= ~OPOST;
621 if (tcsetattr(0, TCSANOW, &tio) < 0)
623 kdError(900) << k_lineinfo <<
"tcsetattr(): " << perror <<
"\n";
630 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.