44 #ifdef __INTEL_COMPILER
50 #include <sys/types.h>
51 #include <sys/ioctl.h>
53 #include <sys/resource.h>
55 #include <sys/param.h>
57 #ifdef HAVE_SYS_STROPTS_H
58 # include <sys/stropts.h>
59 # define _NEW_TTY_CTRL
71 #if defined(HAVE_LIBUTIL_H)
73 # if (!defined(__FreeBSD__) || __FreeBSD_version < 900007)
77 #if defined(HAVE_UTIL_H)
101 #if defined(HAVE_TCGETATTR)
102 # define _tcgetattr(fd, ttmode) tcgetattr(fd, ttmode)
103 #elif defined(TIOCGETA)
104 # define _tcgetattr(fd, ttmode) ioctl(fd, TIOCGETA, (char *)ttmode)
105 #elif defined(TCGETS)
106 # define _tcgetattr(fd, ttmode) ioctl(fd, TCGETS, (char *)ttmode)
111 #if defined(HAVE_TCSETATTR) && defined(TCSANOW)
112 # define _tcsetattr(fd, ttmode) tcsetattr(fd, TCSANOW, ttmode)
113 #elif defined(TIOCSETA)
114 # define _tcsetattr(fd, ttmode) ioctl(fd, TIOCSETA, (char *)ttmode)
115 #elif defined(TCSETS)
116 # define _tcsetattr(fd, ttmode) ioctl(fd, TCSETS, (char *)ttmode)
121 #if defined (_HPUX_SOURCE)
122 # define _TERMIOS_INCLUDED
126 #if defined(HAVE_PTY_H)
131 #include <kstandarddirs.h>
143 #define TTY_GROUP "tty"
164 #define BASE_CHOWN "kgrantpty"
176 masterFd(-1), slaveFd(-1)
178 memset(&winSize, 0,
sizeof(winSize));
187 struct winsize winSize;
210 if(d->masterFd >= 0) {
211 kdWarning(175) <<
"KPty::setPty(): " <<
"d->masterFd >= 0" <<
endl;
214 d->masterFd = pty_master;
215 return _attachPty(pty_master);
218 bool KPty::_attachPty(
int pty_master)
220 if (d->slaveFd < 0 ) {
222 kdDebug(175) <<
"KPty::_attachPty(): " << pty_master <<
endl;
223 #if defined(HAVE_PTSNAME)
224 char *ptsn = ptsname(d->masterFd);
234 #if defined(HAVE_GRANTPT)
235 if (grantpt(d->masterFd)) {
240 if (stat(d->ttyName.data(), &st))
244 if (((st.st_uid != getuid()) ||
245 (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) &&
249 <<
"KPty::_attachPty(): " <<
"chownpty failed for device " << d->ttyName << endl
250 <<
"KPty::_attachPty(): " <<
"This means the communication can be eavesdropped." <<
endl;
255 revoke(d->ttyName.data());
259 unlockpt(d->masterFd);
262 d->slaveFd =
::open(d->ttyName.data(), O_RDWR | O_NOCTTY);
265 kdWarning(175) <<
"KPty::_attachPty(): " <<
"Can't open slave pseudo teletype" <<
endl;
272 ioctl(d->slaveFd, TIOCSWINSZ, (
char *)&d->winSize);
276 #if (defined(__svr4__) || defined(__sgi__))
278 ioctl(d->slaveFd, I_PUSH,
"ptem");
279 ioctl(d->slaveFd, I_PUSH,
"ldterm");
286 struct ::termios ttmode;
288 _tcgetattr(d->slaveFd, &ttmode);
291 ttmode.c_iflag &= ~(IXOFF | IXON);
293 ttmode.c_iflag |= (IXOFF | IXON);
297 ttmode.c_iflag &= ~IUTF8;
299 ttmode.c_iflag |= IUTF8;
302 ttmode.c_cc[VINTR] = CINTR;
303 ttmode.c_cc[VQUIT] = CQUIT;
304 ttmode.c_cc[VERASE] = CERASE;
306 _tcsetattr(d->slaveFd, &ttmode);
310 ioctl(d->slaveFd, TIOCSWINSZ, (
char *)&d->winSize);
313 fcntl(d->masterFd, F_SETFD, FD_CLOEXEC);
314 fcntl(d->slaveFd, F_SETFD, FD_CLOEXEC);
321 if (d->masterFd >= 0)
324 #if defined(HAVE_OPENPTY)
327 if (openpty(&d->masterFd, &d->slaveFd, cpty, NULL, &d->winSize) == 0) {
330 kdWarning(175) <<
"Can't open slave pseudo teletype" <<
endl;
344 #if defined(HAVE_PTSNAME) && defined(HAVE_GRANTPT)
345 #if defined(HAVE_GETPT)
346 d->masterFd = ::getpt();
347 #elif defined(HAVE_POSIX_OPENPT)
348 d->masterFd = ::posix_openpt(O_RDWR);
350 d->masterFd =
::open(
"/dev/ptc",O_RDWR);
352 d->masterFd =
::open(
"/dev/ptmx",O_RDWR);
354 if (d->masterFd >= 0)
356 char *ptsn = ptsname(d->masterFd);
358 grantpt(d->masterFd);
369 for (
const char* s3 =
"pqrstuvwxyzabcdefghijklmno"; *s3; s3++)
371 for (
const char* s4 =
"0123456789abcdefghijklmnopqrstuvwxyz"; *s4; s4++)
373 ptyName.sprintf(
"/dev/pty%c%c", *s3, *s4);
374 d->ttyName.sprintf(
"/dev/tty%c%c", *s3, *s4);
376 d->masterFd =
::open(ptyName.data(), O_RDWR);
377 if (d->masterFd >= 0)
385 if (ioctl(d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) {
391 if (!access(d->ttyName.data(),R_OK|W_OK))
395 struct group* p = getgrnam(TTY_GROUP);
397 p = getgrnam(
"wheel");
398 gid_t gid = p ? p->gr_gid : getgid ();
400 chown(d->ttyName.data(), getuid(), gid);
401 chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);
411 kdWarning(175) <<
"KPty::open(): " <<
"Can't open a pseudo teletype" <<
endl;
416 return _attachPty(d->masterFd);
426 if (memcmp(d->ttyName.data(),
"/dev/pts/", 9)) {
429 if (!stat(d->ttyName.data(), &st)) {
430 chown(d->ttyName.data(), 0, st.st_gid == getgid() ? 0 : -1);
431 chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
434 fcntl(d->masterFd, F_SETFD, 0);
440 d->masterFd = d->slaveFd = -1;
453 ioctl(d->slaveFd, TIOCSCTTY, 0);
461 #if defined(_POSIX_VERSION) || defined(__svr4__)
462 tcsetpgrp (d->slaveFd, pgrp);
463 #elif defined(TIOCSPGRP)
464 ioctl(d->slaveFd, TIOCSPGRP, (
char *)&pgrp);
471 TDEProcess_Utmp utmp;
472 utmp.cmdFd = d->masterFd;
473 utmp << UTEMPTER_HELPER <<
"add";
478 Q_UNUSED(remotehost);
479 #elif defined(USE_LOGIN)
481 struct utmp l_struct;
482 memset(&l_struct, 0,
sizeof(
struct utmp));
486 strncpy(l_struct.ut_name, user, UT_NAMESIZE);
489 strncpy(l_struct.ut_host, remotehost, UT_HOSTSIZE);
492 str_ptr = d->ttyName.data();
493 if (!memcmp(str_ptr,
"/dev/", 5))
495 strncpy(l_struct.ut_line, str_ptr, UT_LINESIZE);
503 l_struct.ut_time=ut_time_temp;
509 Q_UNUSED(remotehost);
516 TDEProcess_Utmp utmp;
517 utmp.cmdFd = d->masterFd;
518 utmp << UTEMPTER_HELPER <<
"del";
520 #elif defined(USE_LOGIN)
521 const char *str_ptr = d->ttyName.data();
522 if (!memcmp(str_ptr,
"/dev/", 5))
526 const char *sl_ptr = strrchr(str_ptr,
'/');
528 str_ptr = sl_ptr + 1;
537 d->winSize.ws_row = (
unsigned short)lines;
538 d->winSize.ws_col = (
unsigned short)columns;
539 if (d->masterFd >= 0)
540 ioctl( d->masterFd, TIOCSWINSZ, (
char *)&d->winSize );
545 d->xonXoff = useXonXoff;
546 if (d->masterFd >= 0) {
550 struct ::termios ttmode;
552 _tcgetattr(d->masterFd, &ttmode);
555 ttmode.c_iflag &= ~(IXOFF | IXON);
557 ttmode.c_iflag |= (IXOFF | IXON);
559 _tcsetattr(d->masterFd, &ttmode);
567 if (d->masterFd >= 0) {
571 struct ::termios ttmode;
573 _tcgetattr(d->masterFd, &ttmode);
576 ttmode.c_iflag &= ~IUTF8;
578 ttmode.c_iflag |= IUTF8;
580 _tcsetattr(d->masterFd, &ttmode);
587 return d->ttyName.data();
601 bool KPty::chownpty(
bool grant)
603 #if !defined(__OpenBSD__) && !defined(__FreeBSD__)
605 proc << locate(
"exe", BASE_CHOWN) << (grant?
"--grant":
"--revoke") << TQString::number(d->masterFd);
const char * ttyName() const
void login(const char *user=0, const char *remotehost=0)
Creates an utmp entry for the tty.
bool normalExit() const
Checks whether the process exited cleanly.
virtual bool start(RunMode runmode=NotifyOnExit, Communication comm=NoCommunication)
Starts the process.
int exitStatus() const
Returns the exit status of the process.
bool open()
Create a pty master/slave pair.
The application is suspended until the started process is finished.
void setUtf8Mode(bool useUtf8)
Set the pty in utf8 mode on systems that support it.
void 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.
Child process invocation, monitoring and control.
kndbgstream & endl(kndbgstream &s)
Does nothing.
void setCTty()
Creates a new session and process group and makes this pty the controlling tty.
void setXonXoff(bool useXonXoff)
Set whether the pty should honor Xon/Xoff flow control.
virtual int commSetupDoneC()
Called right after a (successful) fork(), but before an exec() on the child process' side...
bool setPty(int pty_master)
Attach a existing pty master.