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)
222 kdDebug(175) <<
"KPty::_attachPty(): " << pty_master <<
endl;
223 #if defined(HAVE_PTSNAME) && defined(HAVE_GRANTPT) 224 char *ptsn = ptsname(d->masterFd);
226 grantpt(d->masterFd);
229 ::close(d->masterFd);
235 if (stat(d->ttyName.data(), &st))
239 if (((st.st_uid != getuid()) ||
240 (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) &&
244 <<
"KPty::_attachPty(): " <<
"chownpty failed for device " << ptyName <<
"::" << d->ttyName << endl
245 <<
"KPty::_attachPty(): " <<
"This means the communication can be eavesdropped." <<
endl;
249 revoke(d->ttyName.data());
253 unlockpt(d->masterFd);
256 d->slaveFd = ::open(d->ttyName.data(), O_RDWR | O_NOCTTY);
259 kdWarning(175) <<
"KPty::_attachPty(): " <<
"Can't open slave pseudo teletype" <<
endl;
260 ::close(d->masterFd);
265 #if (defined(__svr4__) || defined(__sgi__)) 267 ioctl(d->slaveFd, I_PUSH,
"ptem");
268 ioctl(d->slaveFd, I_PUSH,
"ldterm");
275 struct ::termios ttmode;
277 _tcgetattr(d->slaveFd, &ttmode);
280 ttmode.c_iflag &= ~(IXOFF | IXON);
282 ttmode.c_iflag |= (IXOFF | IXON);
286 ttmode.c_iflag &= ~IUTF8;
288 ttmode.c_iflag |= IUTF8;
291 ttmode.c_cc[VINTR] = CINTR;
292 ttmode.c_cc[VQUIT] = CQUIT;
293 ttmode.c_cc[VERASE] = CERASE;
295 _tcsetattr(d->slaveFd, &ttmode);
298 ioctl(d->slaveFd, TIOCSWINSZ, (
char *)&d->winSize);
300 fcntl(d->masterFd, F_SETFD, FD_CLOEXEC);
301 fcntl(d->slaveFd, F_SETFD, FD_CLOEXEC);
308 if (d->masterFd >= 0)
311 #if defined(__OpenBSD__) || defined(__FreeBSD__) 314 if (openpty(&d->masterFd, &d->slaveFd, cpty, NULL, &d->winSize) == 0) {
317 kdWarning(175) <<
"Can't open slave pseudo teletype" <<
endl;
331 #if defined(HAVE_PTSNAME) && defined(HAVE_GRANTPT) 333 d->masterFd = ::open(
"/dev/ptc",O_RDWR);
335 d->masterFd = ::open(
"/dev/ptmx",O_RDWR);
337 if (d->masterFd >= 0)
339 char *ptsn = ptsname(d->masterFd);
341 grantpt(d->masterFd);
345 ::close(d->masterFd);
352 for (
const char* s3 =
"pqrstuvwxyzabcdefghijklmno"; *s3; s3++)
354 for (
const char* s4 =
"0123456789abcdefghijklmnopqrstuvwxyz"; *s4; s4++)
356 ptyName.sprintf(
"/dev/pty%c%c", *s3, *s4);
357 d->ttyName.sprintf(
"/dev/tty%c%c", *s3, *s4);
359 d->masterFd = ::open(ptyName.data(), O_RDWR);
360 if (d->masterFd >= 0)
368 if (ioctl(d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) {
369 ::close(d->masterFd);
374 if (!access(d->ttyName.data(),R_OK|W_OK))
378 struct group* p = getgrnam(TTY_GROUP);
380 p = getgrnam(
"wheel");
381 gid_t gid = p ? p->gr_gid : getgid ();
383 chown(d->ttyName.data(), getuid(), gid);
384 chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);
388 ::close(d->masterFd);
394 kdWarning(175) <<
"KPty::open(): " <<
"Can't open a pseudo teletype" <<
endl;
399 return _attachPty(d->masterFd);
409 if (memcmp(d->ttyName.data(),
"/dev/pts/", 9)) {
412 if (!stat(d->ttyName.data(), &st)) {
413 chown(d->ttyName.data(), 0, st.st_gid == getgid() ? 0 : -1);
414 chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
417 fcntl(d->masterFd, F_SETFD, 0);
422 ::close(d->masterFd);
423 d->masterFd = d->slaveFd = -1;
436 ioctl(d->slaveFd, TIOCSCTTY, 0);
439 ::close(::open(d->ttyName, O_WRONLY, 0));
444 #if defined(_POSIX_VERSION) || defined(__svr4__) 445 tcsetpgrp (d->slaveFd, pgrp);
446 #elif defined(TIOCSPGRP) 447 ioctl(d->slaveFd, TIOCSPGRP, (
char *)&pgrp);
454 TDEProcess_Utmp utmp;
455 utmp.cmdFd = d->masterFd;
456 utmp <<
"/usr/lib/utempter/utempter" <<
"add";
461 Q_UNUSED(remotehost);
462 #elif defined(USE_LOGIN) 464 struct utmp l_struct;
465 memset(&l_struct, 0,
sizeof(
struct utmp));
469 strncpy(l_struct.ut_name, user, UT_NAMESIZE);
472 strncpy(l_struct.ut_host, remotehost, UT_HOSTSIZE);
475 str_ptr = d->ttyName.data();
476 if (!memcmp(str_ptr,
"/dev/", 5))
478 strncpy(l_struct.ut_line, str_ptr, UT_LINESIZE);
486 l_struct.ut_time=ut_time_temp;
492 Q_UNUSED(remotehost);
499 TDEProcess_Utmp utmp;
500 utmp.cmdFd = d->masterFd;
501 utmp <<
"/usr/lib/utempter/utempter" <<
"del";
503 #elif defined(USE_LOGIN) 504 const char *str_ptr = d->ttyName.data();
505 if (!memcmp(str_ptr,
"/dev/", 5))
509 const char *sl_ptr = strrchr(str_ptr,
'/');
511 str_ptr = sl_ptr + 1;
520 d->winSize.ws_row = (
unsigned short)lines;
521 d->winSize.ws_col = (
unsigned short)columns;
522 if (d->masterFd >= 0)
523 ioctl( d->masterFd, TIOCSWINSZ, (
char *)&d->winSize );
528 d->xonXoff = useXonXoff;
529 if (d->masterFd >= 0) {
533 struct ::termios ttmode;
535 _tcgetattr(d->masterFd, &ttmode);
538 ttmode.c_iflag &= ~(IXOFF | IXON);
540 ttmode.c_iflag |= (IXOFF | IXON);
542 _tcsetattr(d->masterFd, &ttmode);
550 if (d->masterFd >= 0) {
554 struct ::termios ttmode;
556 _tcgetattr(d->masterFd, &ttmode);
559 ttmode.c_iflag &= ~IUTF8;
561 ttmode.c_iflag |= IUTF8;
563 _tcsetattr(d->masterFd, &ttmode);
570 return d->ttyName.data();
584 bool KPty::chownpty(
bool grant)
586 #if !defined(__OpenBSD__) && !defined(__FreeBSD__) 588 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.