46 #ifdef __INTEL_COMPILER
52 #include <sys/types.h>
53 #include <sys/ioctl.h>
55 #include <sys/resource.h>
57 #include <sys/param.h>
71 # if defined(HAVE_PTY_H)
74 # ifdef HAVE_LIBUTIL_H
76 # elif defined(HAVE_UTIL_H)
104 #if defined(HAVE_TERMIO_H)
109 #if defined (_HPUX_SOURCE)
110 # define _TERMIOS_INCLUDED
114 #ifdef HAVE_SYS_STROPTS_H
115 # include <sys/stropts.h>
116 # define _NEW_TTY_CTRL
119 #if defined(HAVE_TCGETATTR)
120 # define _tcgetattr(fd, ttmode) tcgetattr(fd, ttmode)
121 #elif defined(TIOCGETA)
122 # define _tcgetattr(fd, ttmode) ioctl(fd, TIOCGETA, (char *)ttmode)
123 #elif defined(TCGETS)
124 # define _tcgetattr(fd, ttmode) ioctl(fd, TCGETS, (char *)ttmode)
126 # error No method available to get terminal attributes
129 #if defined(HAVE_TCSETATTR) && defined(TCSANOW)
130 # define _tcsetattr(fd, ttmode) tcsetattr(fd, TCSANOW, ttmode)
131 #elif defined(TIOCSETA)
132 # define _tcsetattr(fd, ttmode) ioctl(fd, TIOCSETA, (char *)ttmode)
133 #elif defined(TCSETS)
134 # define _tcsetattr(fd, ttmode) ioctl(fd, TCSETS, (char *)ttmode)
136 # error No method available to set terminal attributes
143 # define CTRL(x) ((x) & 037)
146 #define TTY_GROUP "tty"
150 # define PATH_MAX MAXPATHLEN
152 # define PATH_MAX 1024
165 masterFd(-1), slaveFd(-1), ownMaster(true), q_ptr(parent)
170 masterFd(_masterFd), slaveFd(_slaveFd), ownMaster(true), q_ptr(parent)
216 if (
d->masterFd >= 0) {
234 if (::openpty( &
d->masterFd, &
d->slaveFd, ptsn,
nullptr,
nullptr))
238 qWarning() <<
"Can't open a pseudo teletype";
247 char *ptsn = _getpty(&
d->masterFd, O_RDWR|O_NOCTTY, S_IRUSR|S_IWUSR, 0);
253 #elif defined(HAVE_PTSNAME) || defined(TIOCGPTN)
255 #ifdef HAVE_POSIX_OPENPT
256 d->masterFd = ::posix_openpt(O_RDWR|O_NOCTTY);
257 #elif defined(HAVE_GETPT)
258 d->masterFd = ::getpt();
259 #elif defined(PTM_DEVICE)
260 d->masterFd =
::open(PTM_DEVICE, O_RDWR|O_NOCTTY);
262 # error No method to open a PTY master detected.
264 if (
d->masterFd >= 0)
267 char *ptsn = ptsname(
d->masterFd);
272 if (!ioctl(
d->masterFd, TIOCGPTN, &ptyno)) {
274 sprintf(buf,
"/dev/pts/%d", ptyno);
278 if (!grantpt(
d->masterFd))
290 for (
const char* s3 =
"pqrstuvwxyzabcde"; *s3; s3++)
292 for (
const char* s4 =
"0123456789abcdef"; *s4; s4++)
294 ptyName = QString().sprintf(
"/dev/pty%c%c", *s3, *s4).toAscii();
295 d->ttyName = QString().sprintf(
"/dev/tty%c%c", *s3, *s4).toAscii();
297 d->masterFd =
::open(ptyName.data(), O_RDWR);
298 if (
d->masterFd >= 0)
306 if (ioctl(
d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) {
312 if (!access(
d->ttyName.data(),R_OK|W_OK))
318 p = getgrnam(
"wheel");
319 gid_t gid = p ? p->gr_gid :
getgid ();
321 if (!chown(
d->ttyName.data(),
getuid(), gid)) {
322 chmod(
d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);
333 qWarning() <<
"Can't open a pseudo teletype";
338 if (
stat(
d->ttyName.data(), &st))
342 if (((st.st_uid !=
getuid()) ||
343 (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) &&
347 <<
"chownpty failed for device " << ptyName <<
"::" <<
d->ttyName
348 <<
"\nThis means the communication can be eavesdropped." << endl;
351 #if defined(HAVE_GRANTPT) || defined(HAVE__GETPTY)
356 revoke(
d->ttyName.data());
360 unlockpt(
d->masterFd);
361 #elif defined(TIOCSPTLCK)
363 ioctl(
d->masterFd, TIOCSPTLCK, &flag);
366 d->slaveFd =
::open(
d->ttyName.data(), O_RDWR | O_NOCTTY);
369 qWarning() <<
"Can't open slave pseudo teletype";
375 #if (defined(__svr4__) || defined(__sgi__))
377 ioctl(
d->slaveFd, I_PUSH,
"ptem");
378 ioctl(
d->slaveFd, I_PUSH,
"ldterm");
382 fcntl(
d->masterFd, F_SETFD, FD_CLOEXEC);
383 fcntl(
d->slaveFd, F_SETFD, FD_CLOEXEC);
388 t.c_lflag &= ~ECHOCTL;
413 if (memcmp(
d->ttyName.data(),
"/dev/pts/", 9)) {
416 if (!
stat(
d->ttyName.data(), &st)) {
417 if (!chown(
d->ttyName.data(), 0, st.st_gid ==
getgid() ? 0 : -1)) {
418 chmod(
d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
422 fcntl(
d->masterFd, F_SETFD, 0);
439 return _tcgetattr(
d->masterFd, ttmode) == 0;
446 return _tcsetattr(
d->masterFd, ttmode) == 0;
453 struct winsize winSize;
454 memset(&winSize, 0,
sizeof(winSize));
455 winSize.ws_row = (
unsigned short)lines;
456 winSize.ws_col = (
unsigned short)columns;
457 return ioctl(
d->masterFd, TIOCSWINSZ, (
char *)&winSize) == 0;
462 struct ::termios ttmode;
466 ttmode.c_lflag &= ~
ECHO;
468 ttmode.c_lflag |=
ECHO;
476 return d->ttyName.data();
Provides primitives for opening & closing a pseudo TTY pair, assigning the controlling TTY,...
bool setEcho(bool echo)
Set whether the pty should echo input.
bool open()
Create a pty master/slave pair.
bool tcGetAttr(struct ::termios *ttmode) const
Wrapper around tcgetattr(3).
void closeSlave()
Close the pty slave descriptor.
const char * ttyName() const
bool tcSetAttr(struct ::termios *ttmode)
Wrapper around tcsetattr(3) with mode TCSANOW.
bool setWinSize(int lines, int columns)
Change the logical (screen) size of the pty.
void close()
Close the pty master/slave pair.
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
int fcntl(int fd, int cmd, long arg)
KPtyPrivate(KPty *parent)
bool chownpty(bool grant)
subroutine stat(x, n, av, var, xmin, xmax)