int createProcess(int *ppid) { char *devname; int ptm, pts; pid_t pid; int res; LOG("createProcess"); char *const argv[] = { "su", "-c", "/data/data/org.androix.nativenetbook/nativeinit /native", NULL }; char *const envp[] = { /*"PATH=/system/bin:/data/data/org.androix.nativenetbook",*/ "DISPLAY=:0", NULL }; ptm = open("/dev/ptmx", O_RDWR); fcntl(ptm, F_SETFD, FD_CLOEXEC); if(grantpt(ptm) || unlockpt(ptm) || ((devname = (char*)ptsname(ptm)) == 0)) { return -1; } pid = fork(); if (pid < 0) return -1; if (pid) { *ppid = pid; LOG("[native] parent returning"); return ptm; } else { /* child */ close(ptm); setsid(); pts = open(devname, O_RDWR); if (pts < 0) exit(-1); dup2(pts, 0); dup2(pts, 1); dup2(pts, 2); //execl("/data/data/org.androix.nativenetbook/lib/init.so", "./init", "/native", NULL); //res = execve("/system/bin/su", "su"); //res = execve("/bin/su", "su"); printf("in child\n"); //execlp("ls", "ls", "/", NULL); //execl("su", "-c", "./init", "/native", NULL); //execve("/system/bin/su", argv, envp); //execve("/bin/su", argv, envp); // execlp("su", "su", "-c", "/data/data/org.androix.nativenetbook/nativeinit /native", NULL); // execlp("su", "su", "-c", "ls /native", NULL); execve("/system/bin/su", argv, envp); execve("/system/xbin/su", argv, envp); execve("/bin/su", argv, envp); LOG("[native] child exiting this should not happen"); exit(-1); }; };
/* This function sets child_pid and masterfd */ void exec_target(char* argv[]) { int fd; int pid; masterfd = open ("/dev/ptmx", O_RDWR); if (masterfd < 0) { perror("Cannot open pseudo tty"); exit (1); } pid = fork (); if (pid < 0) { perror ("Failed to fork"); return; } if (pid == 0) { int slave; setsid(); /* this open raises console window on Windows 7 RC, hide_console_window () hides it. */ slave = open (ptsname (masterfd), O_RDWR); hide_console_window (); if (slave < 0) { perror ("Failed to open slave fd"); exit (1); } for (fd = 0 ; fd < 3 ; fd++) { if (slave != fd) { if (dup2 (slave, fd) < 0) { perror ("Failed to dup2"); exit (1); } } fcntl (fd, F_SETFD, 0); } if (slave > 2) close (slave); execvp (argv[0], argv); fprintf (stderr, "Failed to execute \"%s\".", argv[0]); perror ("execvp"); exit (1); } child_pid = pid; return; }
pid_t forkpty(int *master, char *name, struct termios *tio, struct winsize *ws) { int slave = -1; char *path; pid_t pid; if ((*master = open("/dev/ptmx", O_RDWR|O_NOCTTY)) == -1) return (-1); if (grantpt(*master) != 0) goto out; if (unlockpt(*master) != 0) goto out; if ((path = ptsname(*master)) == NULL) goto out; if (name != NULL) strlcpy(name, path, TTY_NAME_MAX); if ((slave = open(path, O_RDWR|O_NOCTTY)) == -1) goto out; switch (pid = fork()) { case -1: goto out; case 0: close(*master); setsid(); #ifdef TIOCSCTTY if (ioctl(slave, TIOCSCTTY, NULL) == -1) fatal("ioctl failed"); #endif if (ioctl(slave, I_PUSH, "ptem") == -1) fatal("ioctl failed"); if (ioctl(slave, I_PUSH, "ldterm") == -1) fatal("ioctl failed"); if (tio != NULL && tcsetattr(slave, TCSAFLUSH, tio) == -1) fatal("tcsetattr failed"); if (ioctl(slave, TIOCSWINSZ, ws) == -1) fatal("ioctl failed"); dup2(slave, 0); dup2(slave, 1); dup2(slave, 2); if (slave > 2) close(slave); return (0); } close(slave); return (pid); out: if (*master != -1) close(*master); if (slave != -1) close(slave); return (-1); }
/** * @brief call ssh run shell command * @note the code is copied form open program "sshpass" * @param argc,the paragram number * @param argv,the point of point of cmd * @returns 0 sucess ,other failed * @exception */ int runprogram( int argc, char *argv[],char*result,int len) { int ii = 0; struct winsize ttysize; // The size of our tty // We need to interrupt a select with a SIGCHLD. In order to do so, we need a SIGCHLD handler signal( SIGCHLD,sigchld_handler ); // Create a pseudo terminal for our process masterpt=posix_openpt(O_RDWR); if( masterpt==-1 ) { perror("Failed to get a pseudo terminal"); return RETURN_RUNTIME_ERROR; } fcntl(masterpt, F_SETFL, O_NONBLOCK); if( grantpt( masterpt )!=0 ) { perror("Failed to change pseudo terminal's permission"); return RETURN_RUNTIME_ERROR; } if( unlockpt( masterpt )!=0 ) { perror("Failed to unlock pseudo terminal"); return RETURN_RUNTIME_ERROR; } ourtty=open("/dev/tty", 0); if( ourtty!=-1 && ioctl( ourtty, TIOCGWINSZ, &ttysize )==0 ) { signal(SIGWINCH, window_resize_handler); ioctl( masterpt, TIOCSWINSZ, &ttysize ); } const char *name=ptsname(masterpt); int slavept; /* Comment no. 3.14159 This comment documents the history of code. We need to open the slavept inside the child process, after "setsid", so that it becomes the controlling TTY for the process. We do not, otherwise, need the file descriptor open. The original approach was to close the fd immediately after, as it is no longer needed. It turns out that (at least) the Linux kernel considers a master ptty fd that has no open slave fds to be unused, and causes "select" to return with "error on fd". The subsequent read would fail, causing us to go into an infinite loop. This is a bug in the kernel, as the fact that a master ptty fd has no slaves is not a permenant problem. As long as processes exist that have the slave end as their controlling TTYs, new slave fds can be created by opening /dev/tty, which is exactly what ssh is, in fact, doing. Our attempt at solving this problem, then, was to have the child process not close its end of the slave ptty fd. We do, essentially, leak this fd, but this was a small price to pay. This worked great up until openssh version 5.6. Openssh version 5.6 looks at all of its open file descriptors, and closes any that it does not know what they are for. While entirely within its prerogative, this breaks our fix, causing sshpass to either hang, or do the infinite loop again. Our solution is to keep the slave end open in both parent AND child, at least until the handshake is complete, at which point we no longer need to monitor the TTY anyways. */ int childpid=fork(); if( childpid==0 ) { // Child // Detach us from the current TTY setsid(); // This line makes the ptty our controlling tty. We do not otherwise need it open slavept=open(name, O_RDWR ); dup2(slavept,STDIN_FILENO); dup2(slavept,STDOUT_FILENO); dup2(slavept,STDERR_FILENO); close( masterpt ); char **new_argv=(char**)malloc(sizeof(char *)*(argc+1)); int i; for( i=0; i<argc; ++i ) { new_argv[i]=argv[i]; } new_argv[i]=NULL; execvp( new_argv[0], new_argv ); perror("sshpass: Failed to run command"); close( slavept ); exit(RETURN_RUNTIME_ERROR); } else if( childpid<0 ) { perror("sshpass: Failed to create child process"); return RETURN_RUNTIME_ERROR; } // We are the parent //slavept=open(name, O_RDWR|O_NOCTTY ); int status=0; int terminate=0; pid_t wait_id; sigset_t sigmask, sigmask_select; // Set the signal mask during the select sigemptyset(&sigmask_select); // And during the regular run sigemptyset(&sigmask); sigaddset(&sigmask, SIGCHLD); sigprocmask( SIG_SETMASK, &sigmask, NULL ); do { if( !terminate ) { fd_set readfd; FD_ZERO(&readfd); FD_SET(masterpt, &readfd); int selret=pselect( masterpt+1, &readfd, NULL, NULL, NULL, &sigmask_select ); if( selret>0 ) { if( FD_ISSET( masterpt, &readfd ) ) { int ret; if( (ret=handleoutput( masterpt,result,len)) ) { // Authentication failed or any other error // handleoutput returns positive error number in case of some error, and a negative value // if all that happened is that the slave end of the pt is closed. if( ret>0 ) { close( masterpt ); // Signal ssh that it's controlling TTY is now closed } terminate=ret; if( terminate ) { } } } } wait_id=waitpid( childpid, &status, WNOHANG ); } else { wait_id=waitpid( childpid, &status, 0 ); } } while( wait_id==0 || (!WIFEXITED( status ) && !WIFSIGNALED( status )) ); if( terminate>0 ) return terminate; else if( WIFEXITED( status ) ) return WEXITSTATUS(status); else return 255; }
int getpty(int *ptynum) { #ifdef __osf__ /* XXX */ int master; int slave; if(openpty(&master, &slave, line, 0, 0) == 0){ close(slave); return master; } return -1; #else #ifdef HAVE__GETPTY int master, slave; char *p; p = _getpty(&master, O_RDWR, 0600, 1); if(p == NULL) return -1; strlcpy(line, p, sizeof(Xline)); return master; #else int p; char *cp, *p1, *p2; int i; #if SunOS == 40 int dummy; #endif #if __linux int master; int slave; if(openpty(&master, &slave, line, 0, 0) == 0){ close(slave); return master; } #else #ifdef STREAMSPTY char *clone[] = { "/dev/ptc", "/dev/ptmx", "/dev/ptm", "/dev/ptym/clone", 0 }; char **q; for(q=clone; *q; q++){ p=open(*q, O_RDWR); if(p >= 0){ #ifdef HAVE_GRANTPT grantpt(p); #endif #ifdef HAVE_UNLOCKPT unlockpt(p); #endif strlcpy(line, ptsname(p), sizeof(Xline)); really_stream = 1; return p; } } #endif /* STREAMSPTY */ #ifndef _CRAY #ifndef __hpux snprintf(line, sizeof(Xline), "/dev/ptyXX"); p1 = &line[8]; p2 = &line[9]; #else snprintf(line, sizeof(Xline), "/dev/ptym/ptyXX"); p1 = &line[13]; p2 = &line[14]; #endif for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { struct stat stb; *p1 = *cp; *p2 = '0'; /* * This stat() check is just to keep us from * looping through all 256 combinations if there * aren't that many ptys available. */ if (stat(line, &stb) < 0) break; for (i = 0; i < 16; i++) { *p2 = "0123456789abcdef"[i]; p = open(line, O_RDWR); if (p > 0) { #ifndef __hpux line[5] = 't'; #else for (p1 = &line[8]; *p1; p1++) *p1 = *(p1+1); line[9] = 't'; #endif chown(line, 0, 0); chmod(line, 0600); #if SunOS == 40 if (ioctl(p, TIOCGPGRP, &dummy) == 0 || errno != EIO) { chmod(line, 0666); close(p); line[5] = 'p'; } else #endif /* SunOS == 40 */ return(p); } } } #else /* CRAY */ extern lowpty, highpty; struct stat sb; for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { snprintf(myline, sizeof(myline), "/dev/pty/%03d", *ptynum); p = open(myline, 2); if (p < 0) continue; snprintf(line, sizeof(Xline), "/dev/ttyp%03d", *ptynum); /* * Here are some shenanigans to make sure that there * are no listeners lurking on the line. */ if(stat(line, &sb) < 0) { close(p); continue; } if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { chown(line, 0, 0); chmod(line, 0600); close(p); p = open(myline, 2); if (p < 0) continue; } /* * Now it should be safe...check for accessability. */ if (access(line, 6) == 0) return(p); else { /* no tty side to pty so skip it */ close(p); } } #endif /* CRAY */ #endif /* STREAMSPTY */ #endif /* OPENPTY */ return(-1); #endif }
bool KPty::open() { Q_D(KPty); if (d->masterFd >= 0) return true; QByteArray ptyName; // Find a master pty that we can open //////////////////////////////// // Because not all the pty animals are created equal, they want to // be opened by several different methods. // We try, as we know them, one by one. #ifdef HAVE_OPENPTY char ptsn[PATH_MAX]; if (::openpty( &d->masterFd, &d->slaveFd, ptsn, 0, 0)) { d->masterFd = -1; d->slaveFd = -1; kWarning(175) << "Can't open a pseudo teletype"; return false; } d->ttyName = ptsn; #else #ifdef HAVE__GETPTY // irix char *ptsn = _getpty(&d->masterFd, O_RDWR|O_NOCTTY, S_IRUSR|S_IWUSR, 0); if (ptsn) { d->ttyName = ptsn; goto grantedpt; } #elif defined(HAVE_PTSNAME) || defined(TIOCGPTN) //#ifdef HAVE_POSIX_OPENPT d->masterFd = ::posix_openpt(O_RDWR|O_NOCTTY); //#elif defined(HAVE_GETPT) // d->masterFd = ::getpt(); //#elif defined(PTM_DEVICE) // d->masterFd = ::open(PTM_DEVICE, O_RDWR|O_NOCTTY); //#else //;//# error No method to open a PTY master detected. //#endif if (d->masterFd >= 0) { #ifdef HAVE_PTSNAME char *ptsn = ptsname(d->masterFd); if (ptsn) { d->ttyName = ptsn; #else int ptyno; if (!ioctl(d->masterFd, TIOCGPTN, &ptyno)) { d->ttyName = QByteArray("/dev/pts/") + QByteArray::number(ptyno); #endif #ifdef HAVE_GRANTPT if (!grantpt(d->masterFd)) goto grantedpt; #else goto gotpty; #endif } ::close(d->masterFd); d->masterFd = -1; } #endif // HAVE_PTSNAME || TIOCGPTN // Linux device names, FIXME: Trouble on other systems? for (const char* s3 = "pqrstuvwxyzabcde"; *s3; s3++) { for (const char* s4 = "0123456789abcdef"; *s4; s4++) { ptyName = QString().sprintf("/dev/pty%c%c", *s3, *s4).toAscii(); d->ttyName = QString().sprintf("/dev/tty%c%c", *s3, *s4).toAscii(); d->masterFd = ::open(ptyName.data(), O_RDWR); if (d->masterFd >= 0) { #ifdef Q_OS_SOLARIS /* Need to check the process group of the pty. * If it exists, then the slave pty is in use, * and we need to get another one. */ int pgrp_rtn; if (ioctl(d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) { ::close(d->masterFd); d->masterFd = -1; continue; } #endif /* Q_OS_SOLARIS */ if (!access(d->ttyName.data(),R_OK|W_OK)) // checks availability based on permission bits { if (!geteuid()) { struct group* p = getgrnam(TTY_GROUP); if (!p) p = getgrnam("wheel"); gid_t gid = p ? p->gr_gid : getgid (); chown(d->ttyName.data(), getuid(), gid); chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP); } goto gotpty; } ::close(d->masterFd); d->masterFd = -1; } } } qWarning() << "Can't open a pseudo teletype"; return false; gotpty: struct stat st; if (stat(d->ttyName.data(), &st)) { return false; // this just cannot happen ... *cough* Yeah right, I just // had it happen when pty #349 was allocated. I guess // there was some sort of leak? I only had a few open. } if (((st.st_uid != getuid()) || (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) && !d->chownpty(true)) { qWarning() << "chownpty failed for device " << ptyName << "::" << d->ttyName << "\nThis means the communication can be eavesdropped." << endl; } #if defined (HAVE__GETPTY) || defined (HAVE_GRANTPT) grantedpt: #endif #ifdef HAVE_REVOKE revoke(d->ttyName.data()); #endif #ifdef HAVE_UNLOCKPT unlockpt(d->masterFd); #elif defined(TIOCSPTLCK) int flag = 0; ioctl(d->masterFd, TIOCSPTLCK, &flag); #endif d->slaveFd = ::open(d->ttyName.data(), O_RDWR | O_NOCTTY); if (d->slaveFd < 0) { qWarning() << "Can't open slave pseudo teletype"; ::close(d->masterFd); d->masterFd = -1; return false; } #if (defined(__svr4__) || defined(__sgi__)) // Solaris ioctl(d->slaveFd, I_PUSH, "ptem"); ioctl(d->slaveFd, I_PUSH, "ldterm"); #endif #endif /* HAVE_OPENPTY */ fcntl(d->masterFd, F_SETFD, FD_CLOEXEC); fcntl(d->slaveFd, F_SETFD, FD_CLOEXEC); return true; } void KPty::closeSlave() { Q_D(KPty); if (d->slaveFd < 0) return; ::close(d->slaveFd); d->slaveFd = -1; }
int slirp_openpty(int *amaster, int *aslave) { register int master, slave; #ifdef HAVE_GRANTPT char *ptr; if ((master = open("/dev/ptmx", O_RDWR)) < 0 || grantpt(master) < 0 || unlockpt(master) < 0 || (ptr = ptsname(master)) == NULL) { close(master); return -1; } if ((slave = open(ptr, O_RDWR)) < 0 || ioctl(slave, I_PUSH, "ptem") < 0 || ioctl(slave, I_PUSH, "ldterm") < 0 || ioctl(slave, I_PUSH, "ttcompat") < 0) { close(master); close(slave); return -1; } *amaster = master; *aslave = slave; return 0; #else static char line[] = "/dev/ptyXX"; register const char *cp1, *cp2; for (cp1 = "pqrsPQRS"; *cp1; cp1++) { line[8] = *cp1; for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) { line[9] = *cp2; if ((master = open(line, O_RDWR, 0)) == -1) { if (errno == ENOENT) return (-1); /* out of ptys */ } else { line[5] = 't'; /* These will fail */ (void) chown(line, getuid(), 0); (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP); #ifdef HAVE_REVOKE (void) revoke(line); #endif if ((slave = open(line, O_RDWR, 0)) != -1) { *amaster = master; *aslave = slave; return 0; } (void) close(master); line[5] = 'p'; } } } errno = ENOENT; /* out of ptys */ return (-1); #endif }
void ps_program_exec(int fd_master, char *arguments) { struct winsize windowsize; char *argv[64]; char *p; int i, n, fd_slave; if (setsid() == -1) ps_log(EXIT_FAILURE, LOG_ERROR("setsid failed - error [%s]"), strerror(errno)); fd_slave=open(ptsname(fd_master), O_RDWR); if (fd_slave == -1) ps_log(EXIT_FAILURE, LOG_ERROR("unable to open slave with name [%s] - error [%s]"), ptsname(fd_master), strerror(errno)); ps_log(0, LOG_INFO("fd_master [%d] fd_slave [%d] ptsname [%s]"), fd_master, fd_slave, ptsname(fd_master)); if (dup2(fd_slave, STDIN_FILENO) != STDIN_FILENO) ps_log(EXIT_FAILURE, LOG_ERROR("failed to set STDIN_FILENO - error [%s]"), strerror(errno)); if (dup2(fd_slave, STDOUT_FILENO) != STDOUT_FILENO) ps_log(EXIT_FAILURE, LOG_ERROR("failed to set STDOUT_FILENO - error [%s]"), strerror(errno)); if (dup2(fd_slave, STDERR_FILENO) != STDERR_FILENO) ps_log(EXIT_FAILURE, LOG_ERROR("failed to set STDERR_FILENO - error [%s]"), strerror(errno)); if (fd_slave > STDERR_FILENO) close(fd_slave); close(fd_master); // get terminal columns and rows memset(&windowsize, 0, sizeof(windowsize)); p=arguments; windowsize.ws_col=atoi(p); p+=strlen(p)+1; windowsize.ws_row=atoi(p); p+=strlen(p)+1; if (ioctl(STDOUT_FILENO, TIOCSWINSZ, &windowsize) == -1) ps_log(0, LOG_INFO("failed to set window size to w [%d] h [%d] - error [%s]"), windowsize.ws_col, windowsize.ws_row, strerror(errno)); // program arguments n=atoi(p); p+=strlen(p)+1; for (i=0; i < n; i++) { argv[i]=p; p+=strlen(p)+1; } argv[i]=0; execvp(argv[0], argv); // this code only executes if execvp failes ps_log(EXIT_FAILURE, LOG_ERROR("failed to run program [%s] - error [%s]"), argv[0], strerror(errno)); }
/* lpty_new * * create a new lpty object, initialize it, put it into a userdata and * return it to the user. * * Arguments: * L Lua State * * Lua Stack: * - * * Lua Returns: * +1 the lpty userdata */ static int lpty_new(lua_State *L) { /* create pty master side */ int mfd = posix_openpt(O_RDWR); int sfd = -1; int failed = (mfd < 0); int throwe = 0; /* throw errors, default = no */ int usep = 1; /* use path, default = yes */ int nle = 0; /* no local echo, default = no */ int rawm = 0; /* raw mode, default = no */ int sepse = 0; /* separate stderr, default = no */ /* check for options */ if (lua_gettop(L) > 0) { luaL_checktype(L, 1, LUA_TTABLE); lua_pushnil(L); while (lua_next(L, 1) != 0) { const char* k = lua_tostring(L, -2); if (!strcmp(k, "throw_errors")) throwe = lua_toboolean(L, -1); else if (!strcmp(k, "no_local_echo")) nle = lua_toboolean(L, -1); else if (!strcmp(k, "raw_mode")) rawm = lua_toboolean(L, -1); else if (!strcmp(k, "use_path")) usep = lua_toboolean(L, -1); else if (!strcmp(k, "separate_stderr")) { sepse = lua_toboolean(L, -1); } else return _lpty_error(L, 1, "invalid configuration option: %s", k); lua_pop(L, 1); } } if (mfd > 0) { /* setup parent side of pty. BEWARE: * behaviour of grantpt is undefined if a SIGCHLD handler is active */ _lpty_set_sigchld_handler(SIG_DFL); failed = grantpt(mfd); _lpty_set_sigchld_handler(_lpty_sigchld_handler); failed = failed || unlockpt(mfd); /* open slave side of pty */ if (!failed) { char *ttyn = ptsname(mfd); if (ttyn) { sfd = open(ttyn, O_RDWR); failed = (sfd < 0); } else failed = 1; } /* cleanup if anything went wrong */ if (failed) { close(mfd); mfd = -1; } } if (failed) return _lpty_error(L, throwe, "pty initialisation failed: %s", strerror(errno)); lPty *pty = lpty_pushLPty(L); pty->m_fd = mfd; pty->s_fd = sfd; pty->child = -1; pty->flags.throwerrors = throwe; pty->flags.nolocalecho = nle; pty->flags.rawmode = rawm; pty->flags.usepath = usep; pty->e_mfd = -1; pty->e_sfd = -1; /* get original tty flags */ tcgetattr(sfd, &pty->otios); if (!_lpty_separate_stderr(pty, sepse)) return _lpty_error(L, throwe, "pty initialisation failed: %s", strerror(errno)); return 1; }
int main(int argc, char ** argv) { int fdm, fds, status; char *slavename; pid_t pid; test_init(argc, argv); fdm = open("/dev/ptmx", O_RDWR); if (fdm == -1) { err("Can't open a master pseudoterminal"); return 1; } grantpt(fdm); unlockpt(fdm); slavename = ptsname(fdm); pid = test_fork(); if (pid < 0) { err("fork() failed"); return 1; } if (pid == 0) { close(fdm); signal(SIGHUP, sighup_handler); if (setsid() == -1) return 1; /* set up a controlling terminal */ fds = open(slavename, O_RDWR); if (fds == -1) { err("Can't open a slave pseudoterminal %s", slavename); return 1; } if (ioctl(fdm, TIOCSCTTY, 1) < 0) { err("Can't setup a controlling terminal"); return 1; } close(fds); test_waitsig(); if (sighup) return 0; return 1; } test_daemon(); test_waitsig(); close(fdm); if (kill(pid, SIGTERM) == -1) { err("kill failed"); return 1; } pid = waitpid(pid, &status, 0); if (pid < 0) return 1; if (WIFEXITED(status)) { if (WEXITSTATUS(status)) { fail("The child returned %d", WEXITSTATUS(status)); return 1; } } else err("The child has been killed by %d", WTERMSIG(status)); pass(); return 0; }
int openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp) { #if defined(HAVE__GETPTY) /* * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more * pty's automagically when needed */ char *slave; if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL) return (-1); /* Open the slave side. */ if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) { close(*amaster); return (-1); } return (0); #elif defined(HAVE_DEV_PTMX) /* * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 * also has bsd-style ptys, but they simply do not work.) */ int ptm; char *pts; mysig_t old_signal; if ((ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) return (-1); /* XXX: need to close ptm on error? */ old_signal = signal(SIGCHLD, SIG_DFL); if (grantpt(ptm) < 0) return (-1); signal(SIGCHLD, old_signal); if (unlockpt(ptm) < 0) return (-1); if ((pts = ptsname(ptm)) == NULL) return (-1); *amaster = ptm; /* Open the slave side. */ if ((*aslave = open(pts, O_RDWR | O_NOCTTY)) == -1) { close(*amaster); return (-1); } /* * Try to push the appropriate streams modules, as described * in Solaris pts(7). */ ioctl(*aslave, I_PUSH, "ptem"); ioctl(*aslave, I_PUSH, "ldterm"); # ifndef __hpux ioctl(*aslave, I_PUSH, "ttcompat"); # endif /* __hpux */ return (0); #elif defined(HAVE_DEV_PTS_AND_PTC) /* AIX-style pty code. */ const char *ttname; if ((*amaster = open("/dev/ptc", O_RDWR | O_NOCTTY)) == -1) return (-1); if ((ttname = ttyname(*amaster)) == NULL) return (-1); if ((*aslave = open(ttname, O_RDWR | O_NOCTTY)) == -1) { close(*amaster); return (-1); } return (0); #elif defined(_UNICOS) char ptbuf[64], ttbuf[64]; int i; int highpty; highpty = 128; #ifdef _SC_CRAY_NPTY if ((highpty = sysconf(_SC_CRAY_NPTY)) == -1) highpty = 128; #endif /* _SC_CRAY_NPTY */ for (i = 0; i < highpty; i++) { snprintf(ptbuf, sizeof(ptbuf), "/dev/pty/%03d", i); snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%03d", i); if ((*amaster = open(ptbuf, O_RDWR|O_NOCTTY)) == -1) continue; /* Open the slave side. */ if ((*aslave = open(ttbuf, O_RDWR|O_NOCTTY)) == -1) { close(*amaster); return (-1); } return (0); } return (-1); #else /* BSD-style pty code. */ char ptbuf[64], ttbuf[64]; int i; const char *ptymajors = "pqrstuvwxyzabcdefghijklmno" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const char *ptyminors = "0123456789abcdef"; int num_minors = strlen(ptyminors); int num_ptys = strlen(ptymajors) * num_minors; struct termios tio; for (i = 0; i < num_ptys; i++) { snprintf(ptbuf, sizeof(ptbuf), "/dev/pty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); snprintf(ttbuf, sizeof(ttbuf), "/dev/tty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) { /* Try SCO style naming */ snprintf(ptbuf, sizeof(ptbuf), "/dev/ptyp%d", i); snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%d", i); if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) continue; } /* Open the slave side. */ if ((*aslave = open(ttbuf, O_RDWR | O_NOCTTY)) == -1) { close(*amaster); return (-1); } /* set tty modes to a sane state for broken clients */ if (tcgetattr(*amaster, &tio) != -1) { tio.c_lflag |= (ECHO | ISIG | ICANON); tio.c_oflag |= (OPOST | ONLCR); tio.c_iflag |= ICRNL; tcsetattr(*amaster, TCSANOW, &tio); } return (0); } return (-1); #endif }