📄 agetty.c
字号:
for (i = 1; i <= 3; i++) { if (*p >= '0' && *p <= '7') { ch <<= 3; ch += *p - '0'; p++; } else break; } } *q++ = ch; } else { *q++ = *p++; } } *q = '\0'; } op->flags |= F_INITSTRING; break; case 'L': /* force local */ op->flags |= F_LOCAL; break; case 'H': /* fake login host */ fakehost = optarg; break; case 'f': /* custom issue file */ op->flags |= F_CUSTISSUE; op->issue = optarg; break; case 'h': /* enable h/w flow control */ op->flags |= F_RTSCTS; break; case 'i': /* do not show /etc/issue */ op->flags &= ~F_ISSUE; break; case 'l': op->login = optarg; /* non-default login program */ break; case 'm': /* parse modem status message */ op->flags |= F_PARSE; break; case 'n': op->flags |= F_NOPROMPT; break; case 't': /* time out */ if ((op->timeout = atoi(optarg)) <= 0) error(_("bad timeout value: %s"), optarg); break; case 'w': op->flags |= F_WAITCRLF; break; default: usage(); } } debug(_("after getopt loop\n")); if (argc < optind + 2) /* check parameter count */ usage(); /* we loosen up a bit and accept both "baudrate tty" and "tty baudrate" */ if('0' <= argv[optind][0] && argv[optind][0] <= '9') { /* a number first, assume it's a speed (BSD style) */ parse_speeds(op, argv[optind++]); /* baud rate(s) */ op->tty = argv[optind]; /* tty name */ } else { op->tty = argv[optind++]; /* tty name */ parse_speeds(op, argv[optind]); /* baud rate(s) */ } optind++; if (argc > optind && argv[optind]) setenv ("TERM", argv[optind], 1);#ifdef DO_DEVFS_FIDDLING /* * some devfs junk, following Goswin Brederlow: * turn ttyS<n> into tts/<n> * turn tty<n> into vc/<n> */ if (op->tty && strlen(op->tty) < 90) { char dev_name[100]; struct stat st; if (strncmp(op->tty, "ttyS", 4) == 0) { strcpy(dev_name, "/dev/"); strcat(dev_name, op->tty); if (stat(dev_name, &st) < 0) { strcpy(dev_name, "/dev/tts/"); strcat(dev_name, op->tty + 4); if (stat(dev_name, &st) == 0) op->tty = strdup(dev_name + 5); } } else if (strncmp(op->tty, "tty", 3) == 0) { strcpy(dev_name, "/dev/"); strncat(dev_name, op->tty, 90); if (stat(dev_name, &st) < 0) { strcpy(dev_name, "/dev/vc/"); strcat(dev_name, op->tty + 3); if (stat(dev_name, &st) == 0) op->tty = strdup(dev_name + 5); } } }#endif debug(_("exiting parseargs\n"));}/* parse_speeds - parse alternate baud rates */voidparse_speeds(op, arg) struct options *op; char *arg;{ char *cp; debug(_("entered parse_speeds\n")); for (cp = strtok(arg, ","); cp != 0; cp = strtok((char *) 0, ",")) { if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0) error(_("bad speed: %s"), cp); if (op->numspeed >= MAX_SPEED) error(_("too many alternate speeds")); } debug(_("exiting parsespeeds\n"));}#ifdef SYSV_STYLE/* update_utmp - update our utmp entry */voidupdate_utmp(line) char *line;{ struct utmp ut; time_t t; int mypid = getpid(); struct utmp *utp; /* * The utmp file holds miscellaneous information about things started by * /sbin/init and other system-related events. Our purpose is to update * the utmp entry for the current process, in particular the process type * and the tty line we are listening to. Return successfully only if the * utmp file can be opened for update, and if we are able to find our * entry in the utmp file. */ utmpname(_PATH_UTMP); setutent(); /* Find mypid in utmp. Earlier code here tested only utp->ut_type != INIT_PROCESS, so maybe the >= here should be >. The present code is taken from login.c, so if this is changed, maybe login has to be changed as well. */ while ((utp = getutent())) if (utp->ut_pid == mypid && utp->ut_type >= INIT_PROCESS && utp->ut_type <= DEAD_PROCESS) break; if (utp) { memcpy(&ut, utp, sizeof(ut)); } else { /* some inits don't initialize utmp... */ memset(&ut, 0, sizeof(ut)); strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id)); } strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user)); strncpy(ut.ut_line, line, sizeof(ut.ut_line)); if (fakehost) strncpy(ut.ut_host, fakehost, sizeof(ut.ut_host)); time(&t); ut.ut_time = t; ut.ut_type = LOGIN_PROCESS; ut.ut_pid = mypid; pututline(&ut); endutent(); {#ifdef HAVE_updwtmp updwtmp(_PATH_WTMP, &ut);#else int ut_fd; int lf; if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) { flock(lf, LOCK_EX); if ((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) { write(ut_fd, &ut, sizeof(ut)); close(ut_fd); } flock(lf, LOCK_UN); close(lf); }#endif }}#endif/* open_tty - set up tty as standard { input, output, error } */voidopen_tty(tty, tp, local) char *tty; struct termio *tp; int local;{ /* Get rid of the present standard { output, error} if any. */ (void) close(1); (void) close(2); errno = 0; /* ignore above errors */ /* Set up new standard input, unless we are given an already opened port. */ if (strcmp(tty, "-")) { struct stat st; /* Sanity checks... */ if (chdir("/dev")) error(_("/dev: chdir() failed: %m")); if (stat(tty, &st) < 0) error("/dev/%s: %m", tty); if ((st.st_mode & S_IFMT) != S_IFCHR) error(_("/dev/%s: not a character device"), tty); /* Open the tty as standard input. */ (void) close(0); errno = 0; /* ignore close(2) errors */ debug(_("open(2)\n")); if (open(tty, O_RDWR|O_NONBLOCK, 0) != 0) error(_("/dev/%s: cannot open as standard input: %m"), tty); } else { /* * Standard input should already be connected to an open port. Make * sure it is open for read/write. */ if ((fcntl(0, F_GETFL, 0) & O_RDWR) != O_RDWR) error(_("%s: not open for read/write"), tty); } /* Set up standard output and standard error file descriptors. */ debug(_("duping\n")); if (dup(0) != 1 || dup(0) != 2) /* set up stdout and stderr */ error(_("%s: dup problem: %m"), tty); /* we have a problem */ /* * The following ioctl will fail if stdin is not a tty, but also when * there is noise on the modem control lines. In the latter case, the * common course of action is (1) fix your cables (2) give the modem more * time to properly reset after hanging up. SunOS users can achieve (2) * by patching the SunOS kernel variable "zsadtrlow" to a larger value; * 5 seconds seems to be a good value. */ if (ioctl(0, TCGETA, tp) < 0) error("%s: ioctl: %m", tty); /* * It seems to be a terminal. Set proper protections and ownership. Mode * 0622 is suitable for SYSV <4 because /bin/login does not change * protections. SunOS 4 login will change the protections to 0620 (write * access for group tty) after the login has succeeded. */ /* * Let us use 0600 for Linux for the period between getty and login */ (void) chown(tty, 0, 0); /* root, sys */ (void) chmod(tty, 0600); /* 0622: crw--w--w- */ errno = 0; /* ignore above errors */}/* termio_init - initialize termio settings */char gbuf[1024];char area[1024];voidtermio_init(tp, speed, op) struct termio *tp; int speed; struct options *op;{ /* * Initial termio settings: 8-bit characters, raw-mode, blocking i/o. * Special characters are set after we have read the login name; all * reads will be done in raw mode anyway. Errors will be dealt with * lateron. */#ifdef __linux__ /* flush input and output queues, important for modems! */ (void) ioctl(0, TCFLSH, TCIOFLUSH);#endif tp->c_cflag = CS8 | HUPCL | CREAD | speed; if (op->flags & F_LOCAL) { tp->c_cflag |= CLOCAL; } tp->c_iflag = tp->c_lflag = tp->c_oflag = tp->c_line = 0; tp->c_cc[VMIN] = 1; tp->c_cc[VTIME] = 0; /* Optionally enable hardware flow control */#ifdef CRTSCTS if (op->flags & F_RTSCTS) tp->c_cflag |= CRTSCTS;#endif (void) ioctl(0, TCSETA, tp); /* go to blocking input even in local mode */ fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NONBLOCK); debug(_("term_io 2\n"));}/* auto_baud - extract baud rate from modem status message */voidauto_baud(tp) struct termio *tp;{ int speed; int vmin; unsigned iflag; char buf[BUFSIZ]; char *bp; int nread; /* * This works only if the modem produces its status code AFTER raising * the DCD line, and if the computer is fast enough to set the proper * baud rate before the message has gone by. We expect a message of the * following format: * * <junk><number><junk> * * The number is interpreted as the baud rate of the incoming call. If the * modem does not tell us the baud rate within one second, we will keep * using the current baud rate. It is advisable to enable BREAK * processing (comma-separated list of baud rates) if the processing of * modem status messages is enabled. */ /* * Use 7-bit characters, don't block if input queue is empty. Errors will * be dealt with lateron. */ iflag = tp->c_iflag; tp->c_iflag |= ISTRIP; /* enable 8th-bit stripping */ vmin = tp->c_cc[VMIN]; tp->c_cc[VMIN] = 0; /* don't block if queue empty */ (void) ioctl(0, TCSETA, tp); /* * Wait for a while, then read everything the modem has said so far and * try to extract the speed of the dial-in call. */ (void) sleep(1); if ((nread = read(0, buf, sizeof(buf) - 1)) > 0) { buf[nread] = '\0'; for (bp = buf; bp < buf + nread; bp++) { if (isascii(*bp) && isdigit(*bp)) { if ((speed = bcode(bp))) { tp->c_cflag &= ~CBAUD; tp->c_cflag |= speed; } break; } } } /* Restore terminal settings. Errors will be dealt with lateron. */ tp->c_iflag = iflag; tp->c_cc[VMIN] = vmin; (void) ioctl(0, TCSETA, tp);}/* do_prompt - show login prompt, optionally preceded by /etc/issue contents */voiddo_prompt(op, tp) struct options *op; struct termio *tp;{#ifdef ISSUE FILE *fd; int oflag; int c; struct utsname uts; (void) uname(&uts);#endif (void) write(1, "\r\n", 2); /* start a new line */#ifdef ISSUE /* optional: show /etc/issue */ if ((op->flags & F_ISSUE) && (fd = fopen(op->issue, "r"))) { oflag = tp->c_oflag; /* save current setting */ tp->c_oflag |= (ONLCR | OPOST); /* map NL in output to CR-NL */ (void) ioctl(0, TCSETAW, tp); while ((c = getc(fd)) != EOF) { if (c == '\\') { c = getc(fd); switch (c) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -