27 #include "tdeprocess.h" 39 #ifdef __INTEL_COMPILER 45 #include <sys/types.h> 46 #include <sys/ioctl.h> 48 #include <sys/resource.h> 50 #include <sys/param.h> 52 #ifdef HAVE_SYS_STROPTS_H 53 # include <sys/stropts.h> 54 # define _NEW_TTY_CTRL 66 #if defined(HAVE_LIBUTIL_H) 68 # if (!defined(__FreeBSD__) || __FreeBSD_version < 900007) 72 #if defined(HAVE_UTIL_H) 94 #if defined(HAVE_TCGETATTR) 95 # define _tcgetattr(fd, ttmode) tcgetattr(fd, ttmode) 96 #elif defined(TIOCGETA) 97 # define _tcgetattr(fd, ttmode) ioctl(fd, TIOCGETA, (char *)ttmode) 99 # define _tcgetattr(fd, ttmode) ioctl(fd, TCGETS, (char *)ttmode) 104 #if defined(HAVE_TCSETATTR) && defined(TCSANOW) 105 # define _tcsetattr(fd, ttmode) tcsetattr(fd, TCSANOW, ttmode) 106 #elif defined(TIOCSETA) 107 # define _tcsetattr(fd, ttmode) ioctl(fd, TIOCSETA, (char *)ttmode) 108 #elif defined(TCSETS) 109 # define _tcsetattr(fd, ttmode) ioctl(fd, TCSETS, (char *)ttmode) 114 #if defined (_HPUX_SOURCE) 115 # define _TERMIOS_INCLUDED 119 #if defined(HAVE_PTY_H) 124 #include <kstandarddirs.h> 136 #define TTY_GROUP "tty" 157 #define BASE_CHOWN "kgrantpty" 169 masterFd(-1), slaveFd(-1)
171 memset(&winSize, 0,
sizeof(winSize));
180 struct winsize winSize;
203 if(d->masterFd >= 0) {
204 kdWarning(175) <<
"KPty::setPty(): " <<
"d->masterFd >= 0" <<
endl;
207 d->masterFd = pty_master;
208 return _attachPty(pty_master);
211 bool KPty::_attachPty(
int pty_master)
213 if (d->slaveFd < 0 ) {
215 kdDebug(175) <<
"KPty::_attachPty(): " << pty_master <<
endl;
216 #if defined(HAVE_PTSNAME) 217 char *ptsn = ptsname(d->masterFd);
221 ::close(d->masterFd);
227 #if defined(HAVE_GRANTPT) 228 if (grantpt(d->masterFd)) {
233 if (stat(d->ttyName.data(), &st))
237 if (((st.st_uid != getuid()) ||
238 (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) &&
242 <<
"KPty::_attachPty(): " <<
"chownpty failed for device " << d->ttyName << endl
243 <<
"KPty::_attachPty(): " <<
"This means the communication can be eavesdropped." <<
endl;
248 revoke(d->ttyName.data());
252 unlockpt(d->masterFd);
255 d->slaveFd = ::open(d->ttyName.data(), O_RDWR | O_NOCTTY);
258 kdWarning(175) <<
"KPty::_attachPty(): " <<
"Can't open slave pseudo teletype" <<
endl;
259 ::close(d->masterFd);
265 ioctl(d->slaveFd, TIOCSWINSZ, (
char *)&d->winSize);
269 #if (defined(__svr4__) || defined(__sgi__)) 271 ioctl(d->slaveFd, I_PUSH,
"ptem");
272 ioctl(d->slaveFd, I_PUSH,
"ldterm");
279 struct ::termios ttmode;
281 _tcgetattr(d->slaveFd, &ttmode);
284 ttmode.c_iflag &= ~(IXOFF | IXON);
286 ttmode.c_iflag |= (IXOFF | IXON);
290 ttmode.c_iflag &= ~IUTF8;
292 ttmode.c_iflag |= IUTF8;
295 ttmode.c_cc[VINTR] = CINTR;
296 ttmode.c_cc[VQUIT] = CQUIT;
297 ttmode.c_cc[VERASE] = CERASE;
299 _tcsetattr(d->slaveFd, &ttmode);
303 ioctl(d->slaveFd, TIOCSWINSZ, (
char *)&d->winSize);
306 fcntl(d->masterFd, F_SETFD, FD_CLOEXEC);
307 fcntl(d->slaveFd, F_SETFD, FD_CLOEXEC);
314 if (d->masterFd >= 0)
317 #if defined(HAVE_OPENPTY) 320 if (openpty(&d->masterFd, &d->slaveFd, cpty, NULL, &d->winSize) == 0) {
323 kdWarning(175) <<
"Can't open slave pseudo teletype" <<
endl;
337 #if defined(HAVE_PTSNAME) && defined(HAVE_GRANTPT) 338 #if defined(HAVE_GETPT) 339 d->masterFd = ::getpt();
340 #elif defined(HAVE_POSIX_OPENPT) 341 d->masterFd = ::posix_openpt(O_RDWR);
343 d->masterFd = ::open(
"/dev/ptc",O_RDWR);
345 d->masterFd = ::open(
"/dev/ptmx",O_RDWR);
347 if (d->masterFd >= 0)
349 char *ptsn = ptsname(d->masterFd);
351 grantpt(d->masterFd);
355 ::close(d->masterFd);
362 for (
const char* s3 =
"pqrstuvwxyzabcdefghijklmno"; *s3; s3++)
364 for (
const char* s4 =
"0123456789abcdefghijklmnopqrstuvwxyz"; *s4; s4++)
366 ptyName.sprintf(
"/dev/pty%c%c", *s3, *s4);
367 d->ttyName.sprintf(
"/dev/tty%c%c", *s3, *s4);
369 d->masterFd = ::open(ptyName.data(), O_RDWR);
370 if (d->masterFd >= 0)
378 if (ioctl(d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) {
379 ::close(d->masterFd);
384 if (!access(d->ttyName.data(),R_OK|W_OK))
388 struct group* p = getgrnam(TTY_GROUP);
390 p = getgrnam(
"wheel");
391 gid_t gid = p ? p->gr_gid : getgid ();
393 chown(d->ttyName.data(), getuid(), gid);
394 chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);
398 ::close(d->masterFd);
404 kdWarning(175) <<
"KPty::open(): " <<
"Can't open a pseudo teletype" <<
endl;
409 return _attachPty(d->masterFd);
419 if (memcmp(d->ttyName.data(),
"/dev/pts/", 9)) {
422 if (!stat(d->ttyName.data(), &st)) {
423 chown(d->ttyName.data(), 0, st.st_gid == getgid() ? 0 : -1);
424 chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
427 fcntl(d->masterFd, F_SETFD, 0);
432 ::close(d->masterFd);
433 d->masterFd = d->slaveFd = -1;
446 ioctl(d->slaveFd, TIOCSCTTY, 0);
449 ::close(::open(d->ttyName, O_WRONLY, 0));
454 #if defined(_POSIX_VERSION) || defined(__svr4__) 455 tcsetpgrp (d->slaveFd, pgrp);
456 #elif defined(TIOCSPGRP) 457 ioctl(d->slaveFd, TIOCSPGRP, (
char *)&pgrp);
464 TDEProcess_Utmp utmp;
465 utmp.cmdFd = d->masterFd;
466 utmp << UTEMPTER_HELPER <<
"add";
471 Q_UNUSED(remotehost);
472 #elif defined(USE_LOGIN) 474 struct utmp l_struct;
475 memset(&l_struct, 0,
sizeof(
struct utmp));
479 strncpy(l_struct.ut_name, user, UT_NAMESIZE);
482 strncpy(l_struct.ut_host, remotehost, UT_HOSTSIZE);
485 str_ptr = d->ttyName.data();
486 if (!memcmp(str_ptr,
"/dev/", 5))
488 strncpy(l_struct.ut_line, str_ptr, UT_LINESIZE);
496 l_struct.ut_time=ut_time_temp;
502 Q_UNUSED(remotehost);
509 TDEProcess_Utmp utmp;
510 utmp.cmdFd = d->masterFd;
511 utmp << UTEMPTER_HELPER <<
"del";
513 #elif defined(USE_LOGIN) 514 const char *str_ptr = d->ttyName.data();
515 if (!memcmp(str_ptr,
"/dev/", 5))
519 const char *sl_ptr = strrchr(str_ptr,
'/');
521 str_ptr = sl_ptr + 1;
530 d->winSize.ws_row = (
unsigned short)lines;
531 d->winSize.ws_col = (
unsigned short)columns;
532 if (d->masterFd >= 0)
533 ioctl( d->masterFd, TIOCSWINSZ, (
char *)&d->winSize );
538 d->xonXoff = useXonXoff;
539 if (d->masterFd >= 0) {
543 struct ::termios ttmode;
545 _tcgetattr(d->masterFd, &ttmode);
548 ttmode.c_iflag &= ~(IXOFF | IXON);
550 ttmode.c_iflag |= (IXOFF | IXON);
552 _tcsetattr(d->masterFd, &ttmode);
560 if (d->masterFd >= 0) {
564 struct ::termios ttmode;
566 _tcgetattr(d->masterFd, &ttmode);
569 ttmode.c_iflag &= ~IUTF8;
571 ttmode.c_iflag |= IUTF8;
573 _tcsetattr(d->masterFd, &ttmode);
580 return d->ttyName.data();
594 bool KPty::chownpty(
bool grant)
596 #if !defined(__OpenBSD__) && !defined(__FreeBSD__) 598 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.
virtual bool start(RunMode runmode=NotifyOnExit, Communication comm=NoCommunication)
Starts 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.
int exitStatus() const
Returns the exit status of the process.
void setWinSize(int lines, int columns)
Change the logical (screen) size of the pty.
bool normalExit() const
Checks whether the process exited cleanly.
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.