📄 ckupty.c
字号:
default:#ifdef HAVE_WAITPID waitpid(retval, &status, 0);#else /*HAVE_WAITPID*/ wait(&status);#endif /* HAVE_WAITPID */#ifdef CK_POSIX_SIG sigprocmask(SIG_SETMASK, &old, 0);#else /*CK_POSIX_SIG*/ sigsetmask(mask);#endif /*CK_POSIX_SIG*/ break; } }#endif /*VHANG_LAST*/#endif /* HAVE_REVOKE*/#ifndef HAVE_STREAMS slave[strlen("/dev/")] = 'p';#ifdef SETUID chmod(slave, 0666); chown(slave, 0, 0);#endif /* SETUID */#endif /* HAVE_STREAMS */ return(0);}longpty_getpty(fd, slave, slavelength) int slavelength; int *fd; char *slave; { char *cp; char *p; int i, ptynum; struct stat stb;#ifndef HAVE_OPENPTY#ifndef HAVE__GETPTY char slavebuf[1024];#endif /* HAVE__GETPTY */#endif /* HAVE_OPENPTY */#ifdef HAVE__GETPTY char *slaveret; /* Temp to hold pointer to slave */#endif /*HAVE__GETPTY*/#ifdef HAVE_OPENPTY int slavefd; if (openpty(fd, &slavefd, slave, (struct termios *)0, (struct winsize *)0 ) ) return(1); close(slavefd); return(0);#else /* HAVE_OPENPTY */#ifdef HAVE__GETPTY/* This code is included for Irix; as of version 5.3, Irix has /dev/ptmx, but it fails to work properly; even after calling unlockpt, root gets permission denied opening the pty. The code to support _getpty should be removed if Irix gets working streams ptys in favor of maintaining the least needed code paths.*/ if ((slaveret = _getpty(fd, O_RDWR|O_NDELAY, 0600, 0)) == 0) { *fd = -1; return(PTY_GETPTY_NOPTY); } if (strlen(slaveret) > slavelength - 1) { close(*fd); *fd = -1; return(PTY_GETPTY_SLAVE_TOOLONG); } else { strcpy(slave, slaveret); } return(0);#else /* HAVE__GETPTY */ *fd = open("/dev/ptym/clone", O_RDWR|O_NDELAY); /* HPUX */ if (*fd >= 0) { debug(F110,"pty_getpty()","open(/dev/ptym/clone) success",0); goto have_fd; }#ifdef HAVE_STREAMS *fd = open("/dev/ptmx",O_RDWR|O_NDELAY); /*Solaris*/ if (*fd >= 0) { debug(F110,"pty_getpty()","open(/dev/ptmx) success",0); goto have_fd; }#endif /* HAVE_STREAMS */ *fd = open("/dev/ptc", O_RDWR|O_NDELAY); /* AIX */ if (*fd >= 0) { debug(F110,"pty_getpty()","open(/dev/ptc) success",0); goto have_fd; } *fd = open("/dev/pty", O_RDWR|O_NDELAY); /* sysvimp */ if (*fd >= 0) debug(F110,"pty_getpty()","open(/dev/pty) success",0); have_fd: if (*fd >= 0) {#ifdef HAVE_GRANTPT#ifdef HAVE_STREAMS if (grantpt(*fd) || unlockpt(*fd)) return(PTY_GETPTY_STREAMS);#endif /* HAVE_STREAMS */#endif /* HAVE_GRANTPT */#ifdef HAVE_PTSNAME p = (char *)ptsname(*fd); debug(F110,"pty_getpty() ptsname()",p,0);#else#ifdef HAVE_TTYNAME p = ttyname(*fd); debug(F110,"pty_getpty() ttyname()",p,0);#else /* XXX If we don't have either what do we do? */ return(PTY_GETPTY_NOPTY); /* punt */#endif /* HAVE_TTYNAME */#endif /* HAVE_PTSNAME */ if (p) { if (strlen(p) > slavelength - 1) { close (*fd); *fd = -1; return(PTY_GETPTY_SLAVE_TOOLONG); } strcpy(slave, p); return(0); } if (fstat(*fd, &stb) < 0) { close(*fd); return(PTY_GETPTY_FSTAT); } ptynum = (int)(stb.st_rdev&0xFF); sprintf(slavebuf, "/dev/ttyp%x", ptynum); if (strlen(slavebuf) > slavelength - 1) { close(*fd); *fd = -1; return(PTY_GETPTY_SLAVE_TOOLONG); } debug(F110,"pty_getpty() slavebuf",slavebuf,0); ckstrncpy(slave, slavebuf, slavelength); return(0); } else { for (cp = "pqrstuvwxyzPQRST";*cp; cp++) { sprintf(slavebuf,"/dev/ptyXX"); slavebuf[sizeof("/dev/pty") - 1] = *cp; slavebuf[sizeof("/dev/ptyp") - 1] = '0'; if (stat(slavebuf, &stb) < 0) break; for (i = 0; i < 16; i++) { slavebuf[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i]; *fd = open(slavebuf, O_RDWR|O_NDELAY); if (*fd < 0) continue; debug(F110,"pty_getpty() found pty master",slavebuf,0); slavebuf[sizeof("/dev/") - 1] = 't'; /* got pty */ if (strlen(slavebuf) > slavelength -1) { close(*fd); *fd = -1; return(PTY_GETPTY_SLAVE_TOOLONG); } debug(F110,"pty_getpty() slavebuf [2]",slavebuf,0); ckstrncpy(slave, slavebuf, slavelength); return(0); } } return(PTY_GETPTY_NOPTY); }#endif /*HAVE__GETPTY*/#endif /* HAVE_OPENPTY */}longpty_init() {#ifdef HAVE_PTYM static char dummy; tty_bank = &master_name[strlen("/dev/ptym/pty")]; tty_num = &master_name[strlen("/dev/ptym/ptyX")]; slave_bank = &slave_name[strlen("/dev/pty/tty")]; slave_num = &slave_name[strlen("/dev/pty/ttyX")];#endif return(0L);}/* The following is an array of modules that should be pushed on the stream. See configure.in for caviats and notes about when this array is used and not used.*/#ifdef HAVE_STREAMS#ifndef HAVE_LINE_PUSHstatic char *push_list[] = {#ifdef PUSH_PTEM "ptem",#endif#ifdef PUSH_LDTERM "ldterm",#endif#ifdef PUSH_TTCOMPAT "ttcompat",#endif 0};#endif /* HAVE_LINE_PUSH */#endif /* HAVE_STREAMS */longpty_initialize_slave (fd) int fd; {#ifdef POSIX_TERMIOS#ifndef ultrix struct termios new_termio;#else struct sgttyb b;#endif /* ultrix */#else struct sgttyb b;#endif /* POSIX_TERMIOS */ int pid; int rc; debug(F111,"pty_initialize_slave()","fd",fd);#ifdef HAVE_STREAMS#ifdef HAVE_LINE_PUSH while (ioctl(fd,I_POP,0) == 0) ; /* Clear out any old lined's */ if (line_push(fd) < 0) { debug(F110,"pty_initialize_slave()","line_push() failed",0); close(fd); fd = -1; return(PTY_OPEN_SLAVE_LINE_PUSHFAIL); }#else /*No line_push */ { char **module = &push_list[0]; while (*module) { if (ioctl(fd, I_PUSH, *(module++)) < 0) { debug(F110,"pty_initialize_slave()","ioctl(I_PUSH) failed",0); return(PTY_OPEN_SLAVE_PUSH_FAIL); } } }#endif /*LINE_PUSH*/#endif /*HAVE_STREAMS*//* Under Ultrix 3.0, the pgrp of the slave pty terminal needs to be set explicitly. Why rlogind works at all without this on 4.3BSD is a mystery.*/#ifdef GETPGRP_ONEARG pid = getpgrp(getpid());#else pid = getpgrp();#endif /* GETPGRP_ONEARG */ debug(F111,"pty_initialize_slave()","pid",pid);#ifdef TIOCSPGRP ioctl(fd, TIOCSPGRP, &pid);#endif /* TIOCSPGRP */#ifdef POSIX_TERMIOS#ifndef ultrix tcsetpgrp(fd, pid); errno = 0; rc = tcgetattr(fd,&new_termio); debug(F111,"pty_initialize_slave tcgetattr(fd)",ckitoa(rc),errno); if (rc == 0) { new_termio.c_cc[VMIN] = 1; new_termio.c_cc[VTIME] = 0; rc = tcsetattr(fd,TCSANOW,&new_termio); debug(F111,"pty_initialize_slave tcsetattr(fd)",ckitoa(rc),errno); }#endif /* ultrix */#endif /* POSIX_TERMIOS */ return(0L);}#ifdef WANT_UTMPlongpty_logwtmp (tty, user, host) char *user, *tty, *host; {#ifdef HAVE_LOGWTMP logwtmp(tty,user,host); return(0);#else struct utmp ut; char *tmpx; char utmp_id[5]; int loggingin = user[0]; /* Will be empty for logout */#ifndef NO_UT_HOST strncpy(ut.ut_host, host, sizeof(ut.ut_host));#endif /* NO_UT_HOST */ strncpy(ut.ut_line, tty, sizeof(ut.ut_line)); ut.ut_time = time(0);#ifndef NO_UT_PID ut.ut_pid = getpid(); strncpy(ut.ut_user, user, sizeof(ut.ut_user)); tmpx = tty + strlen(tty) - 2; sprintf(utmp_id, "kr%s", tmpx); strncpy(ut.ut_id, utmp_id, sizeof(ut.ut_id)); ut.ut_pid = (loggingin ? getpid() : 0); ut.ut_type = (loggingin ? USER_PROCESS : DEAD_PROCESS);#else strncpy(ut.ut_name, user, sizeof(ut.ut_name));#endif /* NO_UT_PID */ return(ptyint_update_wtmp(&ut, host, user));#endif /* HAVE_LOGWTMP */}#endif /* WANT_UTMP *//* This routine is called twice. It's not particularly important that the setsid() or TIOCSTTY ioctls succeed (they may not the second time), but rather that we have a controlling terminal at the end. It is assumed that vhangup doesn't exist and confuse the process's notion of controlling terminal on any system without TIOCNOTTY. That is, either vhangup() leaves the controlling terminal in tact, breaks the association completely, or the system provides TIOCNOTTY to get things back into a reasonable state. In practice, vhangup() either breaks the association completely or doesn't effect controlling terminals, so this condition is met.*/longpty_open_ctty(slave, fd) char * slave; int *fd; { int retval; debug(F110,"pty_open_ctty() slave",slave,0);/* First, dissociate from previous terminal */ if ((retval = ptyint_void_association()) != 0) { debug(F111, "pty_open_ctty()", "ptyint_void_association() failed", retval ); return(retval); }#ifdef MUST_SETPGRP/* The Ultrix (and other BSD tty drivers) require the process group to be zero in order to acquire the new tty as a controlling tty.*/ setpgrp(0,0);#endif /* MUST_SETPGRP */ errno = 0; *fd = open(slave, O_RDWR); if (*fd < 0) { debug(F111,"pty_open_ctty() open failure", slave, errno); return(PTY_OPEN_SLAVE_OPENFAIL); }#ifdef DEBUG else if (deblog) { debug(F110, "pty_open_ctty() open ok", slave, 0); }#endif /* DEBUG */#ifdef MUST_SETPGRP setpgrp(0, getpid());#endif /* MUST_SETPGRP */#ifdef TIOCSCTTY errno = 0; retval = ioctl(*fd, TIOCSCTTY, 0); /* Don't check return.*/ debug(F111,"pty_open_ctty() ioctl TIOCSCTTY",ckitoa(retval),errno);#endif /* TIOCSTTY */ return(0L);}longpty_open_slave(slave, fd) char *slave; int *fd; { int vfd, testfd; long retval;#ifdef CK_POSIX_SIG struct sigaction sa; sigemptyset(&sa.sa_mask); /* Initialize "sa" structure. */ sa.sa_flags = 0;#endif /* CK_POSIX_SIG *//* First, chmod and chown the slave. If we have vhangup then we really need pty_open_ctty to make sure our controlling terminal is the pty we're opening. However, if we are using revoke or nothing then we just need a file descriiptor for the pty. Considering some OSes in this category break on the second call to open_ctty (currently OSF but others may), we simply use a descriptor if we can.*/#ifdef VHANG_FIRST if ((retval = pty_open_ctty(slave, &vfd)) != 0) { debug(F111, "pty_open_slave() VHANG_FIRST", "pty_open_ctty() failed", retval ); return(retval); } if (vfd < 0) { debug(F111, "pty_open_slave() VHANG_FIRST", "PTY_OPEN_SLAVE_OPENFAIL", vfd ); return(PTY_OPEN_SLAVE_OPENFAIL); }#endif /* VHANG_FIRST */ if (slave == NULL || *slave == '\0') { debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_TOOSHORT",0); return(PTY_OPEN_SLAVE_TOOSHORT); }#ifdef SETUID if (chmod(slave, 0)) { debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_CHMODFAIL",0); return(PTY_OPEN_SLAVE_CHMODFAIL); } if (chown(slave, 0, 0 ) == -1 ) { debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_CHOWNFAIL",0); return(PTY_OPEN_SLAVE_CHOWNFAIL); }#endif /* SETUID */#ifdef VHANG_FIRST ptyint_vhangup(); close(vfd);#endif /* VHANG_FIRST */ if ((retval = ptyint_void_association()) != 0) { debug(F111, "pty_open_slave()", "ptyint_void_association() failed", retval ); return(retval); }#ifdef HAVE_REVOKE if (revoke (slave) < 0 ) { debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_REVOKEFAIL",0); return(PTY_OPEN_SLAVE_REVOKEFAIL); }#endif /* HAVE_REVOKE *//* Open the pty for real. */ retval = pty_open_ctty(slave, fd); if (retval != 0) { debug(F111,"pty_open_slave()","pty_open_ctty() failed",retval); return(PTY_OPEN_SLAVE_OPENFAIL); } retval = pty_initialize_slave(*fd); if (retval) { debug(F111,"pty_open_slave()","pty_initialize_slave() failed",retval); return(retval); }#ifndef NO_DEVTTY testfd = open("/dev/tty", O_RDWR|O_NDELAY); if (testfd < 0) { debug(F110,"pty_open_slave() open failed","/dev/tty",0); close(*fd); *fd = -1; return(PTY_OPEN_SLAVE_NOCTTY); } close(testfd);#endif /* NO_DEVTTY */ debug(F110,"pty_open_slave()","success",0); return(0L);}#ifdef WANT_UTMP#ifndef UTMP_FILE#ifdef _PATH_UTMP#define UTMP_FILE _PATH_UTMP#endif /* _PATH_UTMP */#endif /* UTMP_FILE *//* If it is *still* missing, assume /etc/utmp */#ifndef UTMP_FILE#define UTMP_FILE "/etc/utmp"#endif /* UTMP_FILE */#ifndef NO_UT_PID#define WTMP_REQUIRES_USERNAME#endif /* NO_UT_PID */longpty_update_utmp(process_type, pid, username, line, host, flags) int process_type; int pid; char *username, *line, *host; int flags;/* pty_update_utmp */ { struct utmp ent, ut;#ifndef HAVE_SETUTENT struct stat statb; int tty;#endif /* HAVE_SETUTENT */#ifdef HAVE_SETUTXENT struct utmpx utx;#endif /* HAVE_SETUTXENT */#ifndef NO_UT_PID char *tmpx; char utmp_id[5];#endif /* NO_UT_PID */ char userbuf[32]; int fd; debug(F100,"pty_update_utmp()","",0); strncpy(ent.ut_line, line+sizeof("/dev/")-1, sizeof(ent.ut_line)); ent.ut_time = time(0);#ifdef NO_UT_PID if (process_type == PTY_LOGIN_PROCESS) return(0L);#else /* NO_UT_PID */ ent.ut_pid = pid; switch (process_type) { case PTY_LOGIN_PROCESS: ent.ut_type = LOGIN_PROCESS; break; case PTY_USER_PROCESS: ent.ut_type = USER_PROCESS; break; case PTY_DEAD_PROCESS: ent.ut_type = DEAD_PROCESS; break; default: return(PTY_UPDATE_UTMP_PROCTYPE_INVALID); }#endif /*NO_UT_PID*/#ifndef NO_UT_HOST if (host) strncpy(ent.ut_host, host, sizeof(ent.ut_host)); else ent.ut_host[0] = '\0';#endif /* NO_UT_HOST */#ifndef NO_UT_PID if (!strcmp (line, "/dev/console")) { char * s = NULL;#ifdef sun#ifdef __SVR4 s = "co";#else s = "cons";#endif /* __SVR4 */#else s = "cons";#endif /* sun */ strncpy(ent.ut_id, s, 4); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -