44 #ifdef __INTEL_COMPILER
50 #include <sys/types.h>
51 #include <sys/ioctl.h>
53 #include <sys/resource.h>
55 #include <sys/param.h>
66 #if defined(HAVE_PTY_H)
72 #elif defined(HAVE_UTIL_H)
78 # include <utempter.h>
85 # if !defined(_PATH_UTMPX) && defined(_UTMPX_FILE)
86 # define _PATH_UTMPX _UTMPX_FILE
88 # if !defined(_PATH_WTMPX) && defined(_WTMPX_FILE)
89 # define _PATH_WTMPX _WTMPX_FILE
97 #if defined(HAVE_TERMIO_H)
102 #if defined (_HPUX_SOURCE)
103 # define _TERMIOS_INCLUDED
107 #ifdef HAVE_SYS_STROPTS_H
108 # include <sys/stropts.h>
109 # define _NEW_TTY_CTRL
112 #if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__bsdi__) || defined(__APPLE__) || defined (__DragonFly__)
113 # define _tcgetattr(fd, ttmode) ioctl(fd, TIOCGETA, (char *)ttmode)
115 # if defined(_HPUX_SOURCE) || defined(__Lynx__) || defined (__CYGWIN__) || defined(__sun)
116 # define _tcgetattr(fd, ttmode) tcgetattr(fd, ttmode)
118 # define _tcgetattr(fd, ttmode) ioctl(fd, TCGETS, (char *)ttmode)
122 #if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__bsdi__) || defined(__APPLE__) || defined (__DragonFly__)
123 # define _tcsetattr(fd, ttmode) ioctl(fd, TIOCSETA, (char *)ttmode)
125 # if defined(_HPUX_SOURCE) || defined(__CYGWIN__) || defined(__sun)
126 # define _tcsetattr(fd, ttmode) tcsetattr(fd, TCSANOW, ttmode)
128 # define _tcsetattr(fd, ttmode) ioctl(fd, TCSETS, (char *)ttmode)
134 #include <kde_file.h>
136 #include <QtCore/Q_PID>
138 #define TTY_GROUP "tty"
142 # define PATH_MAX MAXPATHLEN
144 # define PATH_MAX 1024
157 masterFd(-1), slaveFd(-1), ownMaster(true), q_ptr(parent)
198 if (d->masterFd >= 0)
215 if (::openpty( &d->masterFd, &d->slaveFd, ptsn, 0, 0))
219 kWarning(175) <<
"Can't open a pseudo teletype";
226 #ifdef HAVE__GETPTY // irix
228 char *ptsn = _getpty(&d->masterFd, O_RDWR|O_NOCTTY, S_IRUSR|S_IWUSR, 0);
234 #elif defined(HAVE_PTSNAME) || defined(TIOCGPTN)
236 #ifdef HAVE_POSIX_OPENPT
237 d->masterFd = ::posix_openpt(O_RDWR|O_NOCTTY);
238 #elif defined(HAVE_GETPT)
239 d->masterFd = ::getpt();
240 #elif defined(PTM_DEVICE)
241 d->masterFd = KDE_open(PTM_DEVICE, O_RDWR|O_NOCTTY);
243 # error No method to open a PTY master detected.
245 if (d->masterFd >= 0)
248 char *ptsn = ptsname(d->masterFd);
253 if (!ioctl(d->masterFd, TIOCGPTN, &ptyno)) {
255 sprintf(buf,
"/dev/pts/%d", ptyno);
259 if (!grantpt(d->masterFd))
268 #endif // HAVE_PTSNAME || TIOCGPTN
271 for (
const char* s3 =
"pqrstuvwxyzabcde"; *s3; s3++)
273 for (
const char* s4 =
"0123456789abcdef"; *s4; s4++)
278 d->masterFd = KDE_open(ptyName.
data(), O_RDWR);
279 if (d->masterFd >= 0)
287 if (ioctl(d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) {
293 if (!
access(d->ttyName.data(),R_OK|W_OK))
299 p = getgrnam(
"wheel");
300 gid_t gid = p ? p->gr_gid : getgid ();
302 chown(d->ttyName.data(), getuid(), gid);
303 chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);
313 kWarning(175) <<
"Can't open a pseudo teletype";
318 if (KDE_stat(d->ttyName.data(), &st))
322 if (((st.st_uid != getuid()) ||
323 (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) &&
327 <<
"chownpty failed for device " << ptyName <<
"::" << d->ttyName
328 <<
"\nThis means the communication can be eavesdropped." << endl;
334 revoke(d->ttyName.data());
338 unlockpt(d->masterFd);
339 #elif defined(TIOCSPTLCK)
341 ioctl(d->masterFd, TIOCSPTLCK, &flag);
344 d->slaveFd = KDE_open(d->ttyName.data(), O_RDWR | O_NOCTTY);
347 kWarning(175) <<
"Can't open slave pseudo teletype";
353 #if (defined(__svr4__) || defined(__sgi__) || defined(Q_OS_SOLARIS))
359 static const char *pt =
"ptem";
360 static const char *ld =
"ldterm";
361 if (ioctl(d->slaveFd, I_FIND, pt) == 0)
362 ioctl(d->slaveFd, I_PUSH, pt);
363 if (ioctl(d->slaveFd, I_FIND, ld) == 0)
364 ioctl(d->slaveFd, I_PUSH, ld);
370 fcntl(d->masterFd, F_SETFD, FD_CLOEXEC);
371 fcntl(d->slaveFd, F_SETFD, FD_CLOEXEC);
378 #if !defined(HAVE_PTSNAME) && !defined(TIOCGPTN)
379 kWarning(175) <<
"Unsupported attempt to open pty with fd" << fd;
384 if (d->masterFd >= 0) {
385 kWarning(175) <<
"Attempting to open an already open pty";
389 d->ownMaster =
false;
392 char *ptsn = ptsname(fd);
397 if (!ioctl(fd, TIOCGPTN, &ptyno)) {
399 sprintf(buf,
"/dev/pts/%d", ptyno);
403 kWarning(175) <<
"Failed to determine pty slave device for fd" << fd;
433 if (d->masterFd < 0) {
434 kWarning(175) <<
"Attempting to open pty slave while master is closed";
437 d->slaveFd = KDE_open(d->ttyName.data(), O_RDWR | O_NOCTTY);
438 if (d->slaveFd < 0) {
439 kWarning(175) <<
"Can't open slave pseudo teletype";
442 fcntl(d->slaveFd, F_SETFD, FD_CLOEXEC);
456 if (memcmp(d->ttyName.data(),
"/dev/pts/", 9)) {
459 if (!
stat(d->ttyName.data(), &st)) {
460 chown(d->ttyName.data(), 0, st.st_gid == getgid() ? 0 : -1);
461 chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
464 fcntl(d->masterFd, F_SETFD, 0);
486 ioctl(d->slaveFd, TIOCSCTTY, 0);
489 ::close(KDE_open(d->ttyName, O_WRONLY, 0));
494 #if defined(_POSIX_VERSION) || defined(__svr4__)
495 tcsetpgrp(d->slaveFd, pgrp);
496 #elif defined(TIOCSPGRP)
497 ioctl(d->slaveFd, TIOCSPGRP, (
char *)&pgrp);
506 addToUtmp(d->ttyName, remotehost, d->masterFd);
510 struct utmpx l_struct;
512 struct utmp l_struct;
514 memset(&l_struct, 0,
sizeof(l_struct));
518 strncpy(l_struct.ut_name, user,
sizeof(l_struct.ut_name));
521 strncpy(l_struct.ut_host, remotehost,
sizeof(l_struct.ut_host));
522 # ifdef HAVE_STRUCT_UTMP_UT_SYSLEN
523 l_struct.ut_syslen = qMin(strlen(remotehost),
sizeof(l_struct.ut_host));
529 const char *str_ptr = d->ttyName.data();
530 if (!memcmp(str_ptr,
"/dev/", 5))
532 strncpy(l_struct.ut_line, str_ptr,
sizeof(l_struct.ut_line));
533 # ifdef HAVE_STRUCT_UTMP_UT_ID
534 strncpy(l_struct.ut_id,
535 str_ptr + strlen(str_ptr) -
sizeof(l_struct.ut_id),
536 sizeof(l_struct.ut_id));
541 gettimeofday(&l_struct.ut_tv, 0);
543 l_struct.ut_time = time(0);
553 # ifdef HAVE_STRUCT_UTMP_UT_TYPE
554 l_struct.ut_type = USER_PROCESS;
556 # ifdef HAVE_STRUCT_UTMP_UT_PID
557 l_struct.ut_pid = getpid();
558 # ifdef HAVE_STRUCT_UTMP_UT_SESSION
559 l_struct.ut_session = getsid(0);
563 utmpxname(_PATH_UTMPX);
565 pututxline(&l_struct);
567 updwtmpx(_PATH_WTMPX, &l_struct);
569 utmpname(_PATH_UTMP);
571 pututline(&l_struct);
573 updwtmp(_PATH_WTMP, &l_struct);
584 removeLineFromUtmp(d->ttyName, d->masterFd);
588 const char *str_ptr = d->ttyName.data();
589 if (!memcmp(str_ptr,
"/dev/", 5))
593 const char *sl_ptr = strrchr(str_ptr,
'/');
595 str_ptr = sl_ptr + 1;
600 ::logoutx(str_ptr, 0, DEAD_PROCESS);
606 struct utmpx l_struct, *ut;
608 struct utmp l_struct, *ut;
610 memset(&l_struct, 0,
sizeof(l_struct));
612 strncpy(l_struct.ut_line, str_ptr,
sizeof(l_struct.ut_line));
615 utmpxname(_PATH_UTMPX);
617 if ((ut = getutxline(&l_struct))) {
619 utmpname(_PATH_UTMP);
621 if ((ut = getutline(&l_struct))) {
623 memset(ut->ut_name, 0,
sizeof(*ut->ut_name));
624 memset(ut->ut_host, 0,
sizeof(*ut->ut_host));
625 # ifdef HAVE_STRUCT_UTMP_UT_SYSLEN
628 # ifdef HAVE_STRUCT_UTMP_UT_TYPE
629 ut->ut_type = DEAD_PROCESS;
632 gettimeofday(&(ut->ut_tv), 0);
637 ut->ut_time = time(0);
651 if (
_tcgetattr(d->slaveFd, ttmode) == 0)
return true;
661 if (
_tcsetattr(d->slaveFd, ttmode) == 0)
return true;
670 struct winsize winSize;
671 memset(&winSize, 0,
sizeof(winSize));
672 winSize.ws_row = (
unsigned short)lines;
673 winSize.ws_col = (
unsigned short)columns;
674 return ioctl(d->masterFd, TIOCSWINSZ, (
char *)&winSize) == 0;
679 struct ::termios ttmode;
683 ttmode.c_lflag &= ~ECHO;
685 ttmode.c_lflag |= ECHO;
693 return d->ttyName.data();
int execute(const QString &program, const QStringList &arguments)
bool chownpty(bool grant)
const char * ttyName() const
#define _tcgetattr(fd, ttmode)
void login(const char *user=0, const char *remotehost=0)
Creates an utmp entry for the tty.
bool tcGetAttr(struct::termios *ttmode) const
Wrapper around tcgetattr(3).
int stat(const QString &path, KDE_struct_stat *buf)
int chmod(const QString &path, mode_t mode)
void closeSlave()
Close the pty slave descriptor.
bool open()
Create a pty master/slave pair.
QString number(int n, int base)
bool setWinSize(int lines, int columns)
Change the logical (screen) size of the pty.
void logout()
Removes the utmp entry for this tty.
void close()
Close the pty master/slave pair.
bool tcSetAttr(struct::termios *ttmode)
Wrapper around tcsetattr(3) with mode TCSANOW.
QByteArray toLatin1() const
bool openSlave()
Open the pty slave descriptor.
int access(const QString &path, int mode)
QString & sprintf(const char *cformat,...)
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
KPtyPrivate(KPty *parent)
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
#define _tcsetattr(fd, ttmode)
bool setEcho(bool echo)
Set whether the pty should echo input.
Provides primitives for opening & closing a pseudo TTY pair, assigning the controlling TTY...
void setCTty()
Creates a new session and process group and makes this pty the controlling tty.