📄 sys_term.c
字号:
tty_setlitecho(int on){# ifdef ECHOCTL if (on) termbuf.c_lflag &= ~ECHOCTL; else termbuf.c_lflag |= ECHOCTL;# endif# ifdef TCTLECH if (on) termbuf.c_lflag &= ~TCTLECH; else termbuf.c_lflag |= TCTLECH;# endif}inttty_iscrnl(void){ return (termbuf.c_iflag & ICRNL);}/* * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). */#if B4800 != 4800#define DECODE_BAUD#endif#ifdef DECODE_BAUD/* * A table of available terminal speeds */struct termspeeds { int speed; int value;} termspeeds[] = { { 0, B0 }, { 50, B50 }, { 75, B75 }, { 110, B110 }, { 134, B134 }, { 150, B150 }, { 200, B200 }, { 300, B300 }, { 600, B600 }, { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, { 4800, B4800 },#ifdef B7200 { 7200, B7200 },#endif { 9600, B9600 },#ifdef B14400 { 14400, B14400 },#endif#ifdef B19200 { 19200, B19200 },#endif#ifdef B28800 { 28800, B28800 },#endif#ifdef B38400 { 38400, B38400 },#endif#ifdef B57600 { 57600, B57600 },#endif#ifdef B115200 { 115200, B115200 },#endif#ifdef B230400 { 230400, B230400 },#endif { -1, 0 }};#endif /* DECODE_BUAD */voidtty_tspeed(int val){#ifdef DECODE_BAUD struct termspeeds *tp; for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) ; if (tp->speed == -1) /* back up to last valid value */ --tp; cfsetospeed(&termbuf, tp->value);#else /* DECODE_BUAD */ cfsetospeed(&termbuf, val);#endif /* DECODE_BUAD */}voidtty_rspeed(int val){#ifdef DECODE_BAUD struct termspeeds *tp; for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) ; if (tp->speed == -1) /* back up to last valid value */ --tp; cfsetispeed(&termbuf, tp->value);#else /* DECODE_BAUD */ cfsetispeed(&termbuf, val);#endif /* DECODE_BAUD */}#ifdef PARENT_DOES_UTMPextern struct utmp wtmp;extern char wtmpf[];extern void utmp_sig_init (void);extern void utmp_sig_reset (void);extern void utmp_sig_wait (void);extern void utmp_sig_notify (int);# endif /* PARENT_DOES_UTMP */#ifdef STREAMSPTY/* I_FIND seems to live a life of its own */static int my_find(int fd, char *module){#if defined(I_FIND) && defined(I_LIST) static int flag; static struct str_list sl; int n; int i; if(!flag){ n = ioctl(fd, I_LIST, 0); if(n < 0){ perror("ioctl(fd, I_LIST, 0)"); return -1; } sl.sl_modlist=(struct str_mlist*)malloc(n * sizeof(struct str_mlist)); sl.sl_nmods = n; n = ioctl(fd, I_LIST, &sl); if(n < 0){ perror("ioctl(fd, I_LIST, n)"); return -1; } flag = 1; } for(i=0; i<sl.sl_nmods; i++) if(!strcmp(sl.sl_modlist[i].l_name, module)) return 1;#endif return 0;}static void maybe_push_modules(int fd, char **modules){ char **p; int err; for(p=modules; *p; p++){ err = my_find(fd, *p); if(err == 1) break; if(err < 0 && errno != EINVAL) fatalperror(net, "my_find()"); /* module not pushed or does not exist */ } /* p points to null or to an already pushed module, now push all modules before this one */ for(p--; p >= modules; p--){ err = ioctl(fd, I_PUSH, *p); if(err < 0 && errno != EINVAL) fatalperror(net, "I_PUSH"); }}#endif/* * 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. */void getptyslave(void){ int t = -1; struct winsize ws; extern int def_row, def_col; extern int def_tspeed, def_rspeed; /* * 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 re-set them if we need to. */ if (slavefd != -1) { t = slavefd; goto gottty; } /* * Make sure that we don't have a controlling tty, and * that we are the session (process group) leader. */#ifdef HAVE_SETSID if(setsid()<0) fatalperror(net, "setsid()");#else# ifdef TIOCNOTTY t = open(_PATH_TTY, O_RDWR); if (t >= 0) { ioctl(t, TIOCNOTTY, (char *)0); close(t); }# endif#endif# ifdef PARENT_DOES_UTMP /* * Wait for our parent to get the utmp stuff to get done. */ utmp_sig_wait();# endif t = cleanopen(line);gottty: if (t < 0) fatalperror(net, line);#ifdef STREAMSPTY ttyfd = t; /* * Not all systems have (or need) modules ttcompat and pckt so * don't flag it as a fatal error if they don't exist. */ if (really_stream) { /* these are the streams modules that we want pushed. note that they are in reverse order, ptem will be pushed first. maybe_push_modules() will try to push all modules before the first one that isn't already pushed. i.e if ldterm is pushed, only ttcompat will be attempted. all this is because we don't know which modules are available, and we don't know which modules are already pushed (via autopush, for instance). */ char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL }; char *ptymodules[] = { "pckt", NULL }; maybe_push_modules(t, ttymodules); maybe_push_modules(ourpty, ptymodules); }#endif /* * set up the tty modes as we like them to be. */ init_termbuf();# ifdef TIOCSWINSZ if (def_row || def_col) { memset(&ws, 0, sizeof(ws)); ws.ws_col = def_col; ws.ws_row = def_row; ioctl(t, TIOCSWINSZ, (char *)&ws); }# endif /* * Settings for sgtty based systems */ /* * Settings for UNICOS (and HPUX) */# if defined(_CRAY) || defined(__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;# endif /* * Settings for all other termios/termio based * systems, other than 4.4BSD. In 4.4BSD the * kernel does the initial terminal setup. */# if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43)# ifndef OXTABS# define OXTABS 0# endif termbuf.c_lflag |= ECHO; termbuf.c_oflag |= ONLCR|OXTABS; termbuf.c_iflag |= ICRNL; termbuf.c_iflag &= ~IXOFF;# endif tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); /* * Set the tty modes, and make this our controlling tty. */ set_termbuf(); if (login_tty(t) == -1) fatalperror(net, "login_tty"); if (net > 2) close(net); if (ourpty > 2) { close(ourpty); ourpty = -1; }}#ifndef O_NOCTTY#define O_NOCTTY 0#endif/* * Open the specified slave side of the pty, * making sure that we have a clean tty. */int cleanopen(char *line){ int t;#ifdef STREAMSPTY if (!really_stream)#endif { /* * Make sure that other people can't open the * slave side of the connection. */ chown(line, 0, 0); chmod(line, 0600); }#ifdef HAVE_REVOKE revoke(line);#endif t = open(line, O_RDWR|O_NOCTTY); if (t < 0) return(-1); /* * Hangup anybody else using this ttyp, then reopen it for * ourselves. */# if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) signal(SIGHUP, SIG_IGN);#ifdef HAVE_VHANGUP vhangup();#else#endif signal(SIGHUP, SIG_DFL); t = open(line, O_RDWR|O_NOCTTY); if (t < 0) return(-1);# endif# if defined(_CRAY) && defined(TCVHUP) { int i; signal(SIGHUP, SIG_IGN); ioctl(t, TCVHUP, (char *)0); signal(SIGHUP, SIG_DFL); i = open(line, O_RDWR); if (i < 0) return(-1); close(t); t = i; }# endif /* defined(CRAY) && defined(TCVHUP) */ return(t);}#if !defined(BSD4_4)int login_tty(int t){# if defined(TIOCSCTTY) && !defined(__hpux) if (ioctl(t, TIOCSCTTY, (char *)0) < 0) fatalperror(net, "ioctl(sctty)");# ifdef _CRAY /* * Close the hard fd to /dev/ttypXXX, and re-open through * the indirect /dev/tty interface. */ close(t); if ((t = open("/dev/tty", O_RDWR)) < 0) fatalperror(net, "open(/dev/tty)");# endif# else /* * We get our controlling tty assigned as a side-effect * of opening up a tty device. But on BSD based systems, * this only happens if our process group is zero. The * setsid() call above may have set our pgrp, so clear * it out before opening the tty... */#ifdef HAVE_SETPGID setpgid(0, 0);#else setpgrp(0, 0); /* if setpgid isn't available, setpgrp probably takes arguments */#endif close(open(line, O_RDWR));# endif if (t != 0) dup2(t, 0); if (t != 1) dup2(t, 1); if (t != 2) dup2(t, 2); if (t > 2) close(t); return(0);}#endif /* BSD <= 43 *//* * This comes from ../../bsd/tty.c and should not really be here. *//* * Clean the tty name. Return a pointer to the cleaned version. */static char *clean_ttyname (char *tty){ char *res = tty; if (strncmp (res, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) res += sizeof(_PATH_DEV) - 1; if (strncmp (res, "pty/", 4) == 0) res += 4; if (strncmp (res, "ptym/", 5) == 0) res += 5; return res;}/* * Generate a name usable as an `ut_id', typically without `tty'. */#ifdef HAVE_STRUCT_UTMP_UT_IDstatic char *make_id (char *tty){ char *res = tty; if (strncmp (res, "pts/", 4) == 0) res += 4; if (strncmp (res, "tty", 3) == 0) res += 3; return res;}#endif/* * startslave(host) * * Given a hostname, do whatever * is necessary to startup the login process on the slave side of the pty. *//* ARGSUSED */voidstartslave(const char *host, const char *utmp_host, int autologin, char *autoname){ int i;#ifdef AUTHENTICATION if (!autoname || !autoname[0]) autologin = 0; if (autologin < auth_level) { fatal(net, "Authorization failed"); exit(1); }#endif# ifdef PARENT_DOES_UTMP utmp_sig_init();# endif /* PARENT_DOES_UTMP */ if ((i = fork()) < 0) fatalperror(net, "fork"); if (i) {# ifdef PARENT_DOES_UTMP /* * Cray parent will create utmp entry for child and send * signal to child to tell when done. Child waits for signal * before doing anything important. */ int pid = i; void sigjob (int); setpgrp(); utmp_sig_reset(); /* reset handler to default */ /* * Create utmp entry for child */ wtmp.ut_time = time(NULL); wtmp.ut_type = LOGIN_PROCESS; wtmp.ut_pid = pid; strncpy(wtmp.ut_user, "LOGIN", sizeof(wtmp.ut_user)); strncpy(wtmp.ut_host, utmp_host, sizeof(wtmp.ut_host)); strncpy(wtmp.ut_line, clean_ttyname(line), sizeof(wtmp.ut_line));#ifdef HAVE_STRUCT_UTMP_UT_ID strncpy(wtmp.ut_id, wtmp.ut_line + 3, sizeof(wtmp.ut_id));#endif pututline(&wtmp); endutent(); if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { write(i, &wtmp, sizeof(struct utmp)); close(i); }#ifdef _CRAY signal(WJSIGNAL, sigjob);#endif utmp_sig_notify(pid);# endif /* PARENT_DOES_UTMP */ } else { getptyslave();#if defined(DCE) /* if we authenticated via K5, try and join the PAG */ kerberos5_dfspag();#endif start_login(host, autologin, autoname); /*NOTREACHED*/ }}char *envinit[3];extern char **environ;voidinit_env(void){ char **envp; envp = envinit; if ((*envp = getenv("TZ"))) *envp++ -= 3;#if defined(_CRAY) || defined(__hpux) else *envp++ = "TZ=GMT0";#endif *envp = 0; environ = envinit;}/* We won't agree with the Heimdal people about the right way to check for * bad environment variables, so we don't use this code. * See envvarok() in state.c instead. */#if 0/* * scrub_env() * * We only accept the environment variables listed below. */static voidscrub_env(void){ static const char *reject[] = { "TERMCAP=/", NULL }; static const char *accept[] = { "XAUTH=", "XAUTHORITY=", "DISPLAY=", "TERM=", "EDITOR=", "PAGER=", "PRINTER=", "LOGNAME=", "POSIXLY_CORRECT=", "TERMCAP=", NULL }; char **cpp, **cpp2; const char **p; for (cpp2 = cpp = environ; *cpp; cpp++) { int reject_it = 0; for(p = reject; *p; p++) if(strncmp(*cpp, *p, strlen(*p)) == 0) { reject_it = 1; break; } if (reject_it) continue; for(p = accept; *p; p++) if(strncmp(*cpp, *p, strlen(*p)) == 0) break; if(*p != NULL) *cpp2++ = *cpp; } *cpp2 = NULL;}#endifstruct arg_val { int size; int argc; const char **argv;};static void addarg(struct arg_val*, const char*);/* * start_login(host) * * Assuming that we are now running as a child processes, this * function will turn us into the login process. */voidstart_login(const char *host, int autologin, char *name){ struct arg_val argv;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -