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++)
275 ptyName =
QString().sprintf(
"/dev/pty%c%c", *s3, *s4).toLatin1();
276 d->ttyName =
QString().sprintf(
"/dev/tty%c%c", *s3, *s4).toLatin1();
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();
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.
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.
bool openSlave()
Open the pty slave descriptor.
int access(const QString &path, int mode)
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.