46#ifdef __INTEL_COMPILER
55#include <sys/resource.h>
71# if defined(HAVE_PTY_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)
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)
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)
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).toAscii();
298 d->ttyName = QString().sprintf(
"/dev/tty%c%c", *s3, *s4).toAscii();
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))
321 p = getgrnam(
"wheel");
322 gid_t gid = p ? p->gr_gid :
getgid ();
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.
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)