📄 agetty.c
字号:
/* agetty.c - another getty program for Linux. By W. Z. Venema 1989 Ported to Linux by Peter Orbaek <poe@daimi.aau.dk> This program is freely distributable. The entire man-page used to be here. Now read the real man-page agetty.8 instead. -f option added by Eric Rasmussen <ear@usfirst.org> - 12/28/95 1999-02-22 Arkadiusz Mi秌iewicz <misiek@pld.ORG.PL> - added Native Language Support 1999-05-05 Thorsten Kranzkowski <dl8bcu@gmx.net> - enable hardware flow control before displaying /etc/issue */#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/ioctl.h>#include <termio.h>#include <signal.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdarg.h>#include <ctype.h>#include <utmp.h>#include <getopt.h>#include <time.h>#include <sys/file.h>#include "xstrncpy.h"#include "nls.h"#ifdef __linux__#include "pathnames.h"#include <sys/param.h>#define USE_SYSLOG#endif /* If USE_SYSLOG is undefined all diagnostics go directly to /dev/console. */#ifdef USE_SYSLOG#include <syslog.h>#endif /* * Some heuristics to find out what environment we are in: if it is not * System V, assume it is SunOS 4. */#ifdef LOGIN_PROCESS /* defined in System V utmp.h */#define SYSV_STYLE /* select System V style getty */#endif /* * Things you may want to modify. * * If ISSUE is not defined, agetty will never display the contents of the * /etc/issue file. You will not want to spit out large "issue" files at the * wrong baud rate. Relevant for System V only. * * You may disagree with the default line-editing etc. characters defined * below. Note, however, that DEL cannot be used for interrupt generation * and for line editing at the same time. */#ifdef SYSV_STYLE#define ISSUE "/etc/issue" /* displayed before the login prompt */#include <sys/utsname.h>#include <time.h>#endif#define LOGIN " login: " /* login prompt *//* Some shorthands for control characters. */#define CTL(x) (x ^ 0100) /* Assumes ASCII dialect */#define CR CTL('M') /* carriage return */#define NL CTL('J') /* line feed */#define BS CTL('H') /* back space */#define DEL CTL('?') /* delete *//* Defaults for line-editing etc. characters; you may want to change this. */#define DEF_ERASE DEL /* default erase character */#define DEF_INTR CTL('C') /* default interrupt character */#define DEF_QUIT CTL('\\') /* default quit char */#define DEF_KILL CTL('U') /* default kill char */#define DEF_EOF CTL('D') /* default EOF char */#define DEF_EOL 0#define DEF_SWITCH 0 /* default switch char */ /* * SunOS 4.1.1 termio is broken. We must use the termios stuff instead, * because the termio -> termios translation does not clear the termios * CIBAUD bits. Therefore, the tty driver would sometimes report that input * baud rate != output baud rate. I did not notice that problem with SunOS * 4.1. We will use termios where available, and termio otherwise. *//* linux 0.12 termio is broken too, if we use it c_cc[VERASE] isn't set properly, but all is well if we use termios?! */#ifdef TCGETS#undef TCGETA#undef TCSETA#undef TCSETAW#define termio termios#define TCGETA TCGETS#define TCSETA TCSETS#define TCSETAW TCSETSW#endif /* * This program tries to not use the standard-i/o library. This keeps the * executable small on systems that do not have shared libraries (System V * Release <3). */#ifndef BUFSIZ#define BUFSIZ 1024#endif /* * When multiple baud rates are specified on the command line, the first one * we will try is the first one specified. */#define FIRST_SPEED 0/* Storage for command-line options. */#define MAX_SPEED 10 /* max. nr. of baud rates */struct options { int flags; /* toggle switches, see below */ int timeout; /* time-out period */ char *login; /* login program */ char *tty; /* name of tty */ char *initstring; /* modem init string */ char *issue; /* alternative issue file */ int numspeed; /* number of baud rates to try */ int speeds[MAX_SPEED]; /* baud rates to be tried */};#define F_PARSE (1<<0) /* process modem status messages */#define F_ISSUE (1<<1) /* display /etc/issue */#define F_RTSCTS (1<<2) /* enable RTS/CTS flow control */#define F_LOCAL (1<<3) /* force local */#define F_INITSTRING (1<<4) /* initstring is set */#define F_WAITCRLF (1<<5) /* wait for CR or LF */#define F_CUSTISSUE (1<<6) /* give alternative issue file */#define F_NOPROMPT (1<<7) /* don't ask for login name! *//* Storage for things detected while the login name was read. */struct chardata { int erase; /* erase character */ int kill; /* kill character */ int eol; /* end-of-line character */ int parity; /* what parity did we see */ int capslock; /* upper case without lower case */};/* Initial values for the above. */struct chardata init_chardata = { DEF_ERASE, /* default erase character */ DEF_KILL, /* default kill character */ 13, /* default eol char */ 0, /* space parity */ 0, /* no capslock */};struct Speedtab { long speed; int code;};static struct Speedtab speedtab[] = { { 50, B50 }, { 75, B75 }, { 110, B110 }, { 134, B134 }, { 150, B150 }, { 200, B200 }, { 300, B300 }, { 600, B600 }, { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, { 4800, B4800 }, { 9600, B9600 },#ifdef B19200 { 19200, B19200 },#endif#ifdef B38400 { 38400, B38400 },#endif#ifdef EXTA { 19200, EXTA },#endif#ifdef EXTB { 38400, EXTB },#endif#ifdef B57600 { 57600, B57600 },#endif#ifdef B115200 { 115200, B115200 },#endif#ifdef B230400 { 230400, B230400 },#endif { 0, 0 },};#define P_(s) sint main P_((int argc, char **argv));void parse_args P_((int argc, char **argv, struct options *op));void parse_speeds P_((struct options *op, char *arg));void update_utmp P_((char *line));void open_tty P_((char *tty, struct termio *tp, int local));void termio_init P_((struct termio *tp, int speed, struct options *op));void auto_baud P_((struct termio *tp));void do_prompt P_((struct options *op, struct termio *tp));void next_speed P_((struct termio *tp, struct options *op));char *get_logname P_((struct options *op, struct chardata *cp, struct termio *tp));void termio_final P_((struct options *op, struct termio *tp, struct chardata *cp));int caps_lock P_((char *s));int bcode P_((char *s));void usage P_((void));void error P_((const char *, ...));#undef P_/* The following is used for understandable diagnostics. */char *progname;/* Fake hostname for ut_host specified on command line. */char *fakehost = NULL;/* ... */#ifdef DEBUGGING#define debug(s) fprintf(dbf,s); fflush(dbf)FILE *dbf;#else#define debug(s) /* nothing */#endifintmain(argc, argv) int argc; char **argv;{ char *logname = NULL; /* login name, given to /bin/login */ struct chardata chardata; /* set by get_logname() */ struct termio termio; /* terminal mode bits */ static struct options options = { F_ISSUE, /* show /etc/issue (SYSV_STYLE) */ 0, /* no timeout */ _PATH_LOGIN, /* default login program */ "tty1", /* default tty line */ "", /* modem init string */ ISSUE, /* default issue file */ 0, /* no baud rates known yet */ }; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); /* The BSD-style init command passes us a useless process name. */#ifdef SYSV_STYLE { char *ptr; progname = argv[0]; if ((ptr = strrchr(argv[0], '/'))) progname = ++ptr; }#else progname = "agetty";#endif#ifdef DEBUGGING dbf = fopen("/dev/ttyp0", "w"); { int i; for(i = 1; i < argc; i++) { debug(argv[i]); } }#endif /* Parse command-line arguments. */ parse_args(argc, argv, &options);#ifdef __linux__ setsid();#endif /* Update the utmp file. */#ifdef SYSV_STYLE update_utmp(options.tty);#endif debug(_("calling open_tty\n")); /* Open the tty as standard { input, output, error }. */ open_tty(options.tty, &termio, options.flags & F_LOCAL);#ifdef __linux__ { int iv; iv = getpid(); (void) ioctl(0, TIOCSPGRP, &iv); }#endif /* Initialize the termio settings (raw mode, eight-bit, blocking i/o). */ debug(_("calling termio_init\n")); termio_init(&termio, options.speeds[FIRST_SPEED], &options); /* write the modem init string and DON'T flush the buffers */ if (options.flags & F_INITSTRING) { debug(_("writing init string\n")); write(1, options.initstring, strlen(options.initstring)); } if (!(options.flags & F_LOCAL)) { /* go to blocking write mode unless -L is specified */ fcntl(1, F_SETFL, fcntl(1, F_GETFL, 0) & ~O_NONBLOCK); } /* Optionally detect the baud rate from the modem status message. */ debug(_("before autobaud\n")); if (options.flags & F_PARSE) auto_baud(&termio); /* Set the optional timer. */ if (options.timeout) (void) alarm((unsigned) options.timeout); /* optionally wait for CR or LF before writing /etc/issue */ if (options.flags & F_WAITCRLF) { char ch; debug(_("waiting for cr-lf\n")); while(read(0, &ch, 1) == 1) { ch &= 0x7f; /* strip "parity bit" */#ifdef DEBUGGING fprintf(dbf, _("read %c\n"), ch);#endif if (ch == '\n' || ch == '\r') break; } } chardata = init_chardata; if (!(options.flags & F_NOPROMPT)) { /* Read the login name. */ debug(_("reading login name\n")); while ((logname = get_logname(&options, &chardata, &termio)) == 0) next_speed(&termio, &options); } /* Disable timer. */ if (options.timeout) (void) alarm(0); /* Finalize the termio settings. */ termio_final(&options, &termio, &chardata); /* Now the newline character should be properly written. */ (void) write(1, "\n", 1); /* Let the login program take care of password validation. */ (void) execl(options.login, options.login, "--", logname, (char *) 0); error(_("%s: can't exec %s: %m"), options.tty, options.login); exit(0); /* quiet GCC */}/* parse-args - parse command-line arguments */voidparse_args(argc, argv, op) int argc; char **argv; struct options *op;{ extern char *optarg; /* getopt */ extern int optind; /* getopt */ int c; while (isascii(c = getopt(argc, argv, "I:LH:f:hil:mt:wn"))) { switch (c) { case 'I': if (!(op->initstring = malloc(strlen(optarg)))) { error(_("can't malloc initstring")); break; } { char ch, *p, *q; int i; /* copy optarg into op->initstring decoding \ddd octal codes into chars */ q = op->initstring; p = optarg; while (*p) { if (*p == '\\') { /* know \\ means \ */ p++; if (*p == '\\') { ch = '\\'; p++; } else { /* handle \000 - \177 */ ch = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -