27#include "tdeprocess.h" 
   39#ifdef __INTEL_COMPILER 
   48#include <sys/resource.h> 
   52#ifdef HAVE_SYS_STROPTS_H 
   53# include <sys/stropts.h>    
   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) 
  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 <tdestandarddirs.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);
 
  211bool 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);
 
  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;
 
  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);
 
  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) {
 
  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);
 
  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);
 
  433   d->masterFd = d->slaveFd = -1;
 
  446    ioctl(d->slaveFd, TIOCSCTTY, 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();
 
  594bool KPty::chownpty(
bool grant)
 
  596#if !defined(__OpenBSD__) && !defined(__FreeBSD__) 
  598  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.