📄 ckupty.c
字号:
#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 { tmpx = line + strlen(line)-1; if (*(tmpx-1) != '/') tmpx--; /* last 2 chars unless it's a '/' */#ifdef __hpux ckstrncpy(utmp_id, tmpx, 5);#else ckmakmsg(utmp_id,5,"kl",tmpx,NULL,NULL);#endif /* __hpux */ strncpy(ent.ut_id, utmp_id, sizeof(ent.ut_id)); } strncpy(ent.ut_user, username, sizeof(ent.ut_user));#else strncpy(ent.ut_name, username, sizeof(ent.ut_name));#endif /* NO_UT_PID */ if (username[0]) strncpy(userbuf, username, sizeof(userbuf)); else userbuf[0] = '\0';#ifdef HAVE_SETUTENT utmpname(UTMP_FILE); setutent();/* If we need to preserve the user name in the wtmp structure and Our flags tell us we can obtain it from the utmp and we succeed in obtaining it, we then save the utmp structure we obtain, write out the utmp structure and change the username pointer so it is used by update_wtmp.*/#ifdef WTMP_REQUIRES_USERNAME if ((!username[0]) && (flags&PTY_UTMP_USERNAME_VALID) &&line) { struct utmp *utptr; strncpy(ut.ut_line, line, sizeof(ut.ut_line)); utptr = getutline(&ut); if (utptr) strncpy(userbuf,utptr->ut_user,sizeof(ut.ut_user)); }#endif /* WTMP_REQUIRES_USERNAME */ pututline(&ent); endutent();#ifdef HAVE_SETUTXENT setutxent();#ifdef HAVE_GETUTMPX getutmpx(&ent, &utx);#else /* HAVE_GETUTMPX */ /* For platforms like HPUX and Dec Unix which don't have getutmpx */ strncpy(utx.ut_user, ent.ut_user, sizeof(ent.ut_user)); strncpy(utx.ut_id, ent.ut_id, sizeof(ent.ut_id)); strncpy(utx.ut_line, ent.ut_line, sizeof(ent.ut_line)); utx.ut_pid = pid; /* kludge for Irix, etc. to avoid trunc. */ utx.ut_type = ent.ut_type;#ifdef UT_EXIT_STRUCTURE_DIFFER utx.ut_exit.ut_exit = ent.ut_exit.e_exit;#else /* UT_EXIT_STRUCTURE_DIFFER *//* KLUDGE for now; eventually this will be a feature test... See PR#[40] */#ifdef __hpux utx.ut_exit.__e_termination = ent.ut_exit.e_termination; utx.ut_exit.__e_exit = ent.ut_exit.e_exit;#else /* __hpux */ /* XXX do nothing for now; we don't even know the struct member exists */#endif /* __hpux */#endif /* UT_EXIT_STRUCTURE_DIFFER */ utx.ut_tv.tv_sec = ent.ut_time; utx.ut_tv.tv_usec = 0;#endif /* HAVE_GETUTMPX */ if (host) strncpy(utx.ut_host, host, sizeof(utx.ut_host)); else utx.ut_host[0] = 0; pututxline(&utx); endutxent();#endif /* HAVE_SETUTXENT */#else /* HAVE_SETUTENT */ if (flags&PTY_TTYSLOT_USABLE) { tty = ttyslot(); } else { int lc; tty = -1; if ((fd = open(UTMP_FILE, O_RDWR)) < 0) return(errno); for (lc = 0; lseek(fd, (off_t)(lc * sizeof(struct utmp)), SEEK_SET) != -1; lc++ ) { if (read(fd, (char *)&ut, sizeof(struct utmp) ) != sizeof(struct utmp) ) break; if (strncmp(ut.ut_line, ent.ut_line, sizeof(ut.ut_line)) == 0) { tty = lc;#ifdef WTMP_REQUIRES_USERNAME if (!username&&(flags&PTY_UTMP_USERNAME_VALID)) strncpy(userbuf, ut.ut_user, sizeof(ut.ut_user));#endif /* WTMP_REQUIRES_USERNAME */ break; } } close(fd); } if (tty > 0 && (fd = open(UTMP_FILE, O_WRONLY, 0)) >= 0) { lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET); write(fd, (char *)&ent, sizeof(struct utmp)); close(fd); }#endif /* HAVE_SETUTENT */ /* Don't record LOGIN_PROCESS entries. */ if (process_type == PTY_LOGIN_PROCESS) return(0); else return(ptyint_update_wtmp(&ent, host, userbuf));}#ifndef WTMP_FILE#ifdef _PATH_WTMP#define WTMP_FILE _PATH_WTMP#endif /* _PATH_WTMP */#endif /* WTMP_FILE */#ifndef WTMPX_FILE#ifdef _PATH_WTMPX#ifdef HAVE_UPDWTMPX#define WTMPX_FILE _PATH_WTMPX#endif /* HAVE_UPDWTMPX */#endif /* _PATH_WTMPX */#endif /* WTMPX_FILE *//* If it is *still* missing, assume /usr/adm/wtmp */#ifndef WTMP_FILE#define WTMP_FILE "/usr/adm/wtmp"#endif /* WTMP_FILE */#ifdef COMMENT/* The following test can not be made portably *//* #if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) *//* This is ugly, but the lack of standardization in the utmp/utmpx space, and what glibc implements and doesn't make available, is even worse.*//* #undef HAVE_UPDWTMPX */ /* Don't use updwtmpx for glibc 2.1 *//* #endif */ /* __GLIBC__ etc */#else /* COMMENT */#ifdef __GLIBC__#undef HAVE_UPDWTMPX /* Don't use updwtmpx for glibc period */#endif /* __GLIBC__ */#endif /* COMMENT */longptyint_update_wtmp(ent,host,user) struct utmp *ent; char *host; char *user; { struct utmp ut; struct stat statb; int fd; time_t uttime;#ifdef HAVE_UPDWTMPX struct utmpx utx; getutmpx(ent, &utx); if (host) strncpy(utx.ut_host, host, sizeof(utx.ut_host) ); else utx.ut_host[0] = 0; if (user) strncpy(utx.ut_user, user, sizeof(utx.ut_user)); updwtmpx(WTMPX_FILE, &utx);#endif /* HAVE_UPDWTMPX */#ifdef HAVE_UPDWTMP#ifndef HAVE_UPDWTMPX /* This is already performed byupdwtmpx if present.*/ updwtmp(WTMP_FILE, ent);#endif /* HAVE_UPDWTMPX*/#else /* HAVE_UPDWTMP */ if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) >= 0) { if (!fstat(fd, &statb)) { memset((char *)&ut, 0, sizeof(ut));#ifdef __hpux strncpy(ut.ut_id, ent->ut_id, sizeof (ut.ut_id));#endif /* __hpux */ strncpy(ut.ut_line, ent->ut_line, sizeof(ut.ut_line)); strncpy(ut.ut_name, ent->ut_name, sizeof(ut.ut_name));#ifndef NO_UT_HOST strncpy(ut.ut_host, ent->ut_host, sizeof(ut.ut_host));#endif /* NO_UT_HOST */ time(&uttime); ut.ut_time = uttime;#ifdef HAVE_GETUTENT#ifdef USER_PROCESS if (ent->ut_name) { if (!ut.ut_pid) ut.ut_pid = getpid();#ifndef __hpux ut.ut_type = USER_PROCESS;#else /* __hpux */ ut.ut_type = ent->ut_type;#endif /* __hpux */ } else {#ifdef EMPTY ut.ut_type = EMPTY;#else ut.ut_type = DEAD_PROCESS; /* For Linux brokenness*/#endif /* EMPTY */ }#endif /* USER_PROCESS */#endif /* HAVE_GETUTENT */ if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp))#ifndef COHERENT ftruncate(fd, statb.st_size);#else chsize(fd, statb.st_size);#endif /* COHERENT */ } close(fd); }#endif /* HAVE_UPDWTMP */ return(0); /* no current failure cases; file not found is not failure!*/}#endif /* WANT_UTMP */static char Xline[17] = { 0, 0 };int pty_fork_pid = -1;/* getptyslave() Open the slave side of the pty, and do any initialization that is necessary. The return value is a file descriptor for the slave side.*/intgetptyslave() { int t = -1; long retval;#ifdef TIOCGWINSZ struct winsize ws; extern int cmd_rows, cmd_cols;#endif /* TIOCGWINSZ */ debug(F100,"getptyslave()","",0); /* * Opening the slave side may cause initilization of the * kernel tty structure. We need remember the state of: * if linemode was turned on * terminal window size * terminal speed * so that we can reset them if we need to. */ if ((retval = pty_open_slave(Xline, &t)) != 0) { perror(Xline); msg++; debug(F111,"getptyslave()","Unable to open slave",retval); return(-1); } debug(F111,"getptyslave","ttyfd",ttyfd); debug(F111,"getptyslave","t",t);#ifdef INIT_SPTY spty = t;#endif /* INIT_SPTY */#ifdef STREAMSPTY if (ioctl(t,I_PUSH,"pckt") < 0) { debug(F111,"getptyslave()","ioctl(I_PUSH) failed",errno);#ifndef _AIX fatal("I_PUSH pckt");#endif /* _AIX */ }#endif /* STREAMSPTY */ /* Set up the tty modes as we like them to be. */ init_termbuf();#ifdef TIOCGWINSZ if (cmd_rows || cmd_cols) { memset((char *)&ws, 0, sizeof(ws)); ws.ws_col = cmd_cols; ws.ws_row = cmd_rows; ioctl(t, TIOCSWINSZ, (char *)&ws); }#endif /* TIOCGWINSZ */ /* Settings for sgtty based systems */#ifndef USE_TERMIO termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;#endif /* USE_TERMIO */#ifndef OXTABS#define OXTABS 0#endif /* OXTABS */ /* Settings for UNICOS and HPUX */#ifdef CRAY termbuf.c_oflag = OPOST|ONLCR|TAB3; termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; termbuf.c_cflag = EXTB|HUPCL|CS8;#else /* CRAY */#ifdef HPUX termbuf.c_oflag = OPOST|ONLCR|TAB3; termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; termbuf.c_cflag = EXTB|HUPCL|CS8;#else /* HPUX */#ifdef USE_TERMIO /* Settings for all other termios/termio based systems, other than 4.4BSD. In 4.4BSD the kernel does the initial terminal setup. */#ifdef BSD42#ifndef BSD44 termbuf.c_lflag |= ECHO|ICANON|IEXTEN|ISIG; termbuf.c_oflag |= ONLCR|OXTABS|OPOST; termbuf.c_iflag |= ICRNL|IGNPAR; termbuf.c_cflag |= HUPCL; termbuf.c_iflag &= ~IXOFF;#endif /* BSD44 */#else /* BSD42 */ termbuf.c_lflag |= ECHO|ICANON|IEXTEN|ISIG; termbuf.c_oflag |= ONLCR|OXTABS|OPOST; termbuf.c_iflag |= ICRNL|IGNPAR; termbuf.c_cflag |= HUPCL; termbuf.c_iflag &= ~IXOFF;#endif /* BSD42 */#endif /* USE_TERMIO */#endif /* HPUX */#endif /* CRAY */ set_termbuf(); /* Set the tty modes, and make this our controlling tty. */ if (t != 0) dup2(t, 0); if (t != 1) dup2(t, 1); if (t != 2) dup2(t, 2); if (t > 2) close(t); if (ttyfd > 2) { close(ttyfd); ttyfd = -1; } return(0);}#ifdef HAVE_PTYTRAP/* To be called to determine if a trap is pending on a pty if and only if select() cannot be used.*/intpty_trap_pending(fd) int fd; { int pending; int rc; rc = ioctl(fd, TIOCTRAPSTATUS, (char *)&pending, sizeof(pending)); if (rc == 0) { debug(F101,"pty_trap_pending()","",pending); return(pending); } else { debug(F111,"pty_trap_pending()","ioctl() failed",rc); return(-1); }}/* To be called after select() has returned indicating that an exception is waiting on a pty. It should be called with the file descriptor of the pty. Returns -1 on error; 0 if pty is still open; 1 if pty has closed.*/intpty_trap_handler(fd) int fd; { struct request_info ri; memset(&ri,0,sizeof(ri)); if (ioctl(fd,TIOCREQCHECK,(char *)&ri, sizeof(ri)) != 0) { debug(F111,"pty_trap_handler()","ioctl(TIOCREQCHECK) failed",errno); return(-1); } switch (ri.request) { case TIOCOPEN: debug(F110,"pty_trap_handler()","an open() call",0); break; case TIOCCLOSE: debug(F110,"pty_trap_handler()","a close() call",0); break; default: debug(F110,"pty_trap_handler()","an ioctl() call",0); ri.errno_error = EINVAL; } if (ioctl(fd, TIOCREQSET, (char *)&ri,sizeof(ri)) != 0) { debug(F111,"pty_trap_handler()","ioctl(TIOCREQSET) failed",errno); return(-1); } if (ri.request == TIOCCLOSE) return(1); else return(0);}#endif /* HAVE_PTYTRAP */VOIDexec_cmd(s) char * s; { struct stringarray * q; char ** args = NULL; if (!s) return; if (!*s) return; q = cksplit(1,0,s,NULL,"\\%[]&$+-/=*^_@!{}/<>|.#~'`:;?",7,0,0); if (!q) return; args = q->a_head + 1; execvp(args[0],args);}/* Get a pty, scan input lines. */intdo_pty(cmd) char * cmd; { long retval; int syncpipe[2]; int i;#ifdef HAVE_PTYTRAP int x;#endif /* HAVE_PTYTRAP */ msg = 0; /* Message counter */ pty_init(); /* Find an available pty to use. */ errno = 0; if ((retval = pty_getpty(&ttyfd, Xline, 20)) != 0) { if (msg++ == 0) perror(Xline); debug(F111,"do_pty()","pty_getpty() fails",retval); return(-1); } debug(F110,"do_pty() Xline",Xline,0);#ifdef SIGTTOU/* Ignoring SIGTTOU keeps the kernel from blocking us. we tweak the tty with an ioctl() (in ttioct() in /sys/tty.c in a BSD kernel)*/ signal(SIGTTOU, SIG_IGN);#endif /* SIGTTOU *//* Start up the command on the slave side of the terminal */ if (pipe(syncpipe) < 0) { debug(F110,"do_pty()","pipe() fails",0); perror("pipe() failed"); msg++; debug(F111,"do_pty()","pipe fails",errno); return(-1); } if ((i = fork()) < 0) { /* XXX - need to clean up the allocated pty */ perror("fork() failed"); msg++; debug(F111,"do_pty()","fork fails",errno); return(-1); } if (i) { /* Wait for child before writing to parent side of pty. */ char c;#ifdef HAVE_PTYTRAP int on = 1;#endif /* HAVE_PTYTRAP */ close(syncpipe[1]); errno = 0; if (read(syncpipe[0], &c, 1) == 0) { /* Slave side died */ perror("Pipe read() failed"); msg++; debug(F110,"do_pty()","Slave fails to initialize",0); close(syncpipe[0]); return(-1); } pty_fork_pid = i; /* So we can clean it up later */ debug(F101,"do_pty pty_fork_pid","",pty_fork_pid);#ifdef HAVE_PTYTRAP /* HPUX does not allow the master to read end of file. */ /* Therefore, we must determine that the slave has been */ /* closed by trapping the call to close(). */ errno = 0; x = ioctl(ttyfd, TIOCTRAP, (char *)&on); debug(F111,"do_pty ioctl(TIOCTRAP)",ckitoa(x),errno);#endif /* HAVE_PTYTRAP */ debug(F111,"do_pty()","synchronized - pty_fork_pid",pty_fork_pid); close(syncpipe[0]); } else { debug(F110,"do_pty()","Slave starts",0); if (getptyslave() == 0) {#ifdef WANT_UTMP pty_update_utmp(PTY_USER_PROCESS, getpid(), "KERMIT", Xline, cmd, PTY_TTYSLOT_USABLE );#endif /* WANT_UTMP */ /* Notify our parent we're ready to continue.*/ debug(F110,"do_pty()","slave synchronizing",0); write(syncpipe[1],"y",1); close(syncpipe[0]); close(syncpipe[1]); exec_cmd(cmd); debug(F111,"do_pty()","exec_cmd() returns - why?",errno); } debug(F110,"do_pty()","getptyslave() fails - exiting",0); exit(1); } return(0);} /* end of do_pty() */VOIDend_pty() { msg = 0; /* Message counter */ if (Xline[0] && pty_fork_pid >= 0) { pty_cleanup(Xline,pty_fork_pid,1); Xline[0] = '\0'; pty_fork_pid = -1; }}#endif /* NETPTY */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -