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);
bool setPty(int pty_master)
Attach a existing pty master.
void setXonXoff(bool useXonXoff)
Set whether the pty should honor Xon/Xoff flow control.
void setCTty()
Creates a new session and process group and makes this pty the controlling tty.
void setWinSize(int lines, int columns)
Change the logical (screen) size of the pty.
void login(const char *user=0, const char *remotehost=0)
Creates an utmp entry for the tty.
bool open()
Create a pty master/slave pair.
void setUtf8Mode(bool useUtf8)
Set the pty in utf8 mode on systems that support it.
void logout()
Removes the utmp entry for this tty.
const char * ttyName() const
void close()
Close the pty master/slave pair.
Child process invocation, monitoring and control.
virtual int commSetupDoneC()
Called right after a (successful) fork(), but before an exec() on the child process' side.
virtual bool start(RunMode runmode=NotifyOnExit, Communication comm=NoCommunication)
Starts the process.
int exitStatus() const
Returns the exit status of the process.
@ Block
The application is suspended until the started process is finished.
bool normalExit() const
Checks whether the process exited cleanly.
kndbgstream & endl(kndbgstream &s)
Does nothing.