summaryrefslogtreecommitdiffstats
path: root/login-utils/agetty.c
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:25:33 +0100
committerKarel Zak2006-12-07 00:25:33 +0100
commit726f69e29ca9d4842f3acb20fffd2466fda62c09 (patch)
treeabbc1b6e9bfb0dfe32e81a83648e261ccb2d5a5f /login-utils/agetty.c
parentImported from util-linux-2.2 tarball. (diff)
downloadkernel-qcow2-util-linux-726f69e29ca9d4842f3acb20fffd2466fda62c09.tar.gz
kernel-qcow2-util-linux-726f69e29ca9d4842f3acb20fffd2466fda62c09.tar.xz
kernel-qcow2-util-linux-726f69e29ca9d4842f3acb20fffd2466fda62c09.zip
Imported from util-linux-2.5 tarball.
Diffstat (limited to 'login-utils/agetty.c')
-rw-r--r--login-utils/agetty.c126
1 files changed, 100 insertions, 26 deletions
diff --git a/login-utils/agetty.c b/login-utils/agetty.c
index a8cd45db8..c7595bf37 100644
--- a/login-utils/agetty.c
+++ b/login-utils/agetty.c
@@ -132,12 +132,15 @@ struct options {
int numspeed; /* number of baud rates to try */
int speeds[MAX_SPEED]; /* baud rates to be tried */
char *tty; /* name of tty */
+ char *initstring; /* modem init string */
};
#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 */
/* Storage for things detected while the login name was read. */
@@ -194,7 +197,6 @@ main(argc, argv)
char **argv;
{
char *logname; /* login name, given to /bin/login */
- char *get_logname();
struct chardata chardata; /* set by get_logname() */
struct termio termio; /* terminal mode bits */
static struct options options = {
@@ -251,7 +253,13 @@ main(argc, argv)
/* Initialize the termio settings (raw mode, eight-bit, blocking i/o). */
termio_init(&termio, options.speeds[FIRST_SPEED], options.flags & F_LOCAL);
-
+
+ /* write the modem init string and flush the buffers */
+ if (options.flags & F_INITSTRING) {
+ write(1, options.initstring, strlen(options.initstring));
+ ioctl(1, TCFLSH, 2);
+ }
+
/* Optionally detect the baud rate from the modem status message. */
if (options.flags & F_PARSE)
@@ -262,6 +270,16 @@ main(argc, argv)
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;
+
+ while(read(0, &ch, 1) == 1) {
+ ch &= 0x7f; /* strip "parity bit" */
+ if (ch == '\n' || ch == '\r') break;
+ }
+ }
+
/* Read the login name. */
while ((logname = get_logname(&options, &chardata, &termio)) == 0)
@@ -299,8 +317,48 @@ parse_args(argc, argv, op)
extern int optind; /* getopt */
int c;
- while (isascii(c = getopt(argc, argv, "Lhil:mt:"))) {
+ while (isascii(c = getopt(argc, argv, "I:Lhil:mt:w"))) {
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;
+ 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;
@@ -320,6 +378,9 @@ parse_args(argc, argv, op)
if ((op->timeout = atoi(optarg)) <= 0)
error("bad timeout value: %s", optarg);
break;
+ case 'w':
+ op->flags |= F_WAITCRLF;
+ break;
default:
usage();
}
@@ -379,10 +440,11 @@ update_utmp(line)
long time();
long lseek();
char *strncpy();
+ struct utmp *utp;
/*
* The utmp file holds miscellaneous information about things started by
- * /etc/init and other system-related events. Our purpose is to update
+ * /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
@@ -390,24 +452,36 @@ update_utmp(line)
*/
#ifdef linux
- utmpname(_PATH_UTMP);
- memset(&ut, 0, sizeof(ut));
- (void) strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user));
- (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line));
- (void) strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
- (void) time(&ut.ut_time);
- ut.ut_type = LOGIN_PROCESS;
- ut.ut_pid = mypid;
-
- pututline(&ut);
- endutent();
-
- if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
- flock(ut_fd, LOCK_EX);
- write(ut_fd, &ut, sizeof(ut));
- flock(ut_fd, LOCK_UN);
- close(ut_fd);
- }
+ utmpname(_PATH_UTMP);
+ setutent();
+ while ((utp = getutent())
+ && !(utp->ut_type == INIT_PROCESS
+ && utp->ut_pid == mypid)) /* nothing */;
+
+ 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));
+ }
+ endutent();
+
+ strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user));
+ strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+ time(&ut.ut_time);
+ ut.ut_type = LOGIN_PROCESS;
+ ut.ut_pid = mypid;
+
+ pututline(&ut);
+ endutent();
+
+ if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
+ flock(ut_fd, LOCK_EX);
+ write(ut_fd, &ut, sizeof(ut));
+ flock(ut_fd, LOCK_UN);
+ close(ut_fd);
+ }
#else
if ((ut_fd = open(UTMP_FILE, 2)) < 0) {
error("%s: open for update: %m", UTMP_FILE);
@@ -592,7 +666,7 @@ auto_baud(tp)
buf[nread] = '\0';
for (bp = buf; bp < buf + nread; bp++) {
if (isascii(*bp) && isdigit(*bp)) {
- if (speed = bcode(bp)) {
+ if ((speed = bcode(bp))) {
tp->c_cflag &= ~CBAUD;
tp->c_cflag |= speed;
}
@@ -709,7 +783,7 @@ do_prompt(op, tp)
int users = 0;
struct utmp *ut;
setutent();
- while (ut = getutent())
+ while ((ut = getutent()))
if (ut->ut_type == USER_PROCESS)
users++;
endutent();
@@ -764,7 +838,7 @@ char *get_logname(op, cp, tp)
struct chardata *cp;
struct termio *tp;
{
- char logname[BUFSIZ];
+ static char logname[BUFSIZ];
char *bp;
char c; /* input character, full eight bits */
char ascval; /* low 7 bits of input character */
@@ -860,7 +934,7 @@ char *get_logname(op, cp, tp)
}
/* Handle names with upper case and no lower case. */
- if (cp->capslock = caps_lock(logname)) {
+ if ((cp->capslock = caps_lock(logname))) {
for (bp = logname; *bp; bp++)
if (isupper(*bp))
*bp = tolower(*bp); /* map name to lower case */