31 #include <sys/types.h>
35 #include <sys/resource.h>
37 #ifdef HAVE_SYS_SELECT_H
38 #include <sys/select.h>
41 #include <QtCore/QBool>
42 #include <QtCore/QFile>
54 using namespace KDESuPrivate;
62 int PtyProcess::waitMS(
int fd,
int ms)
71 return select(fd+1, &fds, 0L, 0L, &tv);
87 if (superUserCommand ==
"sudo") {
90 return kill(pid, 0) == 0;
105 ret = waitpid(pid, &state, WNOHANG);
114 if (WIFEXITED(state))
115 return WEXITSTATUS(state);
123 class PtyProcess::PtyProcessPrivate
126 PtyProcessPrivate() : m_pPTY(0L) {}
131 QList<QByteArray> env;
138 :d(new PtyProcessPrivate)
145 int PtyProcess::init()
148 d->m_pPTY =
new KPty();
149 if (!d->m_pPTY->open())
154 d->m_Inbuf.resize(0);
172 return d->m_pPTY ? d->m_pPTY->masterFd() : -1;
190 if (!d->m_Inbuf.isEmpty())
196 d->m_Inbuf.resize(0);
199 int flags = fcntl(
fd(), F_GETFL);
207 flags &= ~O_NONBLOCK;
211 if ((flags != oflags) && (fcntl(
fd(), F_SETFL, flags) < 0))
220 ret.reserve(ret.size() + 0x8000);
221 int nbytes = read(
fd(), ret.data() + ret.size(), 0x8000);
231 ret.resize(ret.size() + nbytes);
245 if (!d->m_Inbuf.isEmpty())
247 pos = d->m_Inbuf.indexOf(
'\n');
252 d->m_Inbuf.resize(0);
255 ret = d->m_Inbuf.left(pos);
256 d->m_Inbuf.remove(0, pos+1);
267 write(
fd(), line, line.length());
269 write(
fd(),
"\n", 1);
275 QByteArray tmp = line;
279 d->m_Inbuf.prepend(tmp);
299 if ((
m_Pid = fork()) == -1)
308 d->m_pPTY->closeSlave();
316 for (i = 0; i < d->env.count(); ++i)
318 putenv(const_cast<char *>(d->env.at(i).constData()));
320 unsetenv(
"KDE_FULL_SESSION");
322 unsetenv(
"SESSION_MANAGER");
325 unsetenv(
"DBUS_SESSION_BUS_ADDRESS");
328 const QByteArray old_lc_all = qgetenv(
"LC_ALL" );
329 if( !old_lc_all.isEmpty() )
330 qputenv(
"KDESU_LC_ALL", old_lc_all );
332 unsetenv(
"KDESU_LC_ALL" );
333 qputenv(
"LC_ALL",
"C");
338 if (command.contains(
'/'))
348 path = QFile::encodeName(file);
351 const char **argp = (
const char **)malloc((args.count()+2)*
sizeof(
char *));
355 for (QList<QByteArray>::ConstIterator it=args.begin(); it!=args.end(); ++it, ++i)
360 execv(path, const_cast<char **>(argp));
389 if (!d->m_pPTY->tcGetAttr(&tio))
394 if (tio.c_lflag & ECHO)
408 return d->m_pPTY->setEcho(enable) ? 0 : -1;
434 QByteArray remainder;
446 timeout.tv_usec = 100000;
447 int ret = select(
fd()+1, &fds, 0L, 0L, &timeout);
462 if (output.isEmpty())
466 fwrite(output.constData(), output.size(), 1, stdout);
473 while (remainder.length() >=
m_Exit.length()) {
474 if (remainder.startsWith(
m_Exit)) {
475 kill(
m_Pid, SIGTERM);
476 remainder.remove(0,
m_Exit.length());
478 int off = remainder.indexOf(
'\n');
481 remainder.remove(0, off + 1);
490 if (errno == ECHILD)
return 0;
515 int PtyProcess::setupTTY()
518 for (
int sig = 1; sig < NSIG; sig++)
519 KDE_signal(sig, SIG_DFL);
520 KDE_signal(SIGHUP, SIG_IGN);
522 d->m_pPTY->setCTty();
525 int slave = d->m_pPTY->slaveFd();
526 dup2(slave, 0); dup2(slave, 1); dup2(slave, 2);
532 getrlimit(RLIMIT_NOFILE, &rlp);
533 for (
int i = 3; i < (int)rlp.rlim_cur; i++)
538 struct ::termios tio;
539 if (tcgetattr(0, &tio) < 0)
544 tio.c_oflag &= ~OPOST;
545 if (tcsetattr(0, TCSANOW, &tio) < 0)