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 #if defined (HAVE_STROPTS_H)
115 # include <stropts.h>
116 # define _NEW_TTY_CTRL
117 #elif defined (HAVE_SYS_STROPTS_H)
118 # include <sys/stropts.h>
119 # define _NEW_TTY_CTRL
122 #if defined(HAVE_TCGETATTR)
123 # define _tcgetattr(fd, ttmode) tcgetattr(fd, ttmode)
124 #elif defined(TIOCGETA)
125 # define _tcgetattr(fd, ttmode) ioctl(fd, TIOCGETA, (char *)ttmode)
126 #elif defined(TCGETS)
127 # define _tcgetattr(fd, ttmode) ioctl(fd, TCGETS, (char *)ttmode)
129 # error No method available to get terminal attributes
132 #if defined(HAVE_TCSETATTR) && defined(TCSANOW)
133 # define _tcsetattr(fd, ttmode) tcsetattr(fd, TCSANOW, ttmode)
134 #elif defined(TIOCSETA)
135 # define _tcsetattr(fd, ttmode) ioctl(fd, TIOCSETA, (char *)ttmode)
136 #elif defined(TCSETS)
137 # define _tcsetattr(fd, ttmode) ioctl(fd, TCSETS, (char *)ttmode)
139 # error No method available to set terminal attributes
146 # define CTRL(x) ((x) & 037)
149 #define TTY_GROUP "tty"
153 # define PATH_MAX MAXPATHLEN
155 # define PATH_MAX 1024
168 masterFd(-1), slaveFd(-1), ownMaster(true), q_ptr(parent)
173 masterFd(_masterFd), slaveFd(_slaveFd), ownMaster(true), q_ptr(parent)
219 if (
d->masterFd >= 0) {
237 if (::openpty( &
d->masterFd, &
d->slaveFd, ptsn,
nullptr,
nullptr))
241 qWarning() <<
"Can't open a pseudo teletype";
250 char *ptsn = _getpty(&
d->masterFd, O_RDWR|O_NOCTTY, S_IRUSR|S_IWUSR, 0);
256 #elif defined(HAVE_PTSNAME) || defined(TIOCGPTN)
258 #ifdef HAVE_POSIX_OPENPT
259 d->masterFd = ::posix_openpt(O_RDWR|O_NOCTTY);
260 #elif defined(HAVE_GETPT)
261 d->masterFd = ::getpt();
262 #elif defined(PTM_DEVICE)
263 d->masterFd =
::open(PTM_DEVICE, O_RDWR|O_NOCTTY);
265 # error No method to open a PTY master detected.
267 if (
d->masterFd >= 0)
270 char *ptsn = ptsname(
d->masterFd);
275 if (!ioctl(
d->masterFd, TIOCGPTN, &ptyno)) {
277 sprintf(buf,
"/dev/pts/%d", ptyno);
281 if (!grantpt(
d->masterFd))
293 for (
const char* s3 =
"pqrstuvwxyzabcde"; *s3; s3++)
295 for (
const char* s4 =
"0123456789abcdef"; *s4; s4++)
297 ptyName = QString().sprintf(
"/dev/pty%c%c", *s3, *s4).toLatin1();
298 d->ttyName = QString().sprintf(
"/dev/tty%c%c", *s3, *s4).toLatin1();
300 d->masterFd =
::open(ptyName.data(), O_RDWR);
301 if (
d->masterFd >= 0)
309 if (ioctl(
d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) {
315 if (!access(
d->ttyName.data(),R_OK|W_OK))
324 if (!chown(
d->ttyName.data(),
getuid(),
gid)) {
325 chmod(
d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);
336 qWarning() <<
"Can't open a pseudo teletype";
341 if (
stat(
d->ttyName.data(), &st))
345 if (((st.st_uid !=
getuid()) ||
346 (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) &&
350 <<
"chownpty failed for device " << ptyName <<
"::" <<
d->ttyName
351 <<
"\nThis means the communication can be eavesdropped." << endl;
354 #if defined(HAVE_GRANTPT) || defined(HAVE__GETPTY)
359 revoke(
d->ttyName.data());
363 unlockpt(
d->masterFd);
364 #elif defined(TIOCSPTLCK)
366 ioctl(
d->masterFd, TIOCSPTLCK, &flag);
369 d->slaveFd =
::open(
d->ttyName.data(), O_RDWR | O_NOCTTY);
372 qWarning() <<
"Can't open slave pseudo teletype";
378 #if (defined(__svr4__) || defined(__sgi__))
380 ioctl(
d->slaveFd, I_PUSH,
"ptem");
381 ioctl(
d->slaveFd, I_PUSH,
"ldterm");
385 fcntl(
d->masterFd, F_SETFD, FD_CLOEXEC);
386 fcntl(
d->slaveFd, F_SETFD, FD_CLOEXEC);
391 t.c_lflag &= ~ECHOCTL;
416 if (memcmp(
d->ttyName.data(),
"/dev/pts/", 9)) {
419 if (!
stat(
d->ttyName.data(), &st)) {
420 if (!chown(
d->ttyName.data(), 0, st.st_gid ==
getgid() ? 0 : -1)) {
421 chmod(
d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
425 fcntl(
d->masterFd, F_SETFD, 0);
442 return _tcgetattr(
d->masterFd, ttmode) == 0;
449 return _tcsetattr(
d->masterFd, ttmode) == 0;
456 struct winsize winSize;
457 memset(&winSize, 0,
sizeof(winSize));
458 winSize.ws_row = (
unsigned short)lines;
459 winSize.ws_col = (
unsigned short)columns;
460 return ioctl(
d->masterFd, TIOCSWINSZ, (
char *)&winSize) == 0;
465 struct ::termios ttmode;
469 ttmode.c_lflag &= ~
ECHO;
471 ttmode.c_lflag |=
ECHO;
479 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.
static group getgrnam(const std::string &nm)
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)