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¶kiewicz <misiek@misiek.eu.org>
- added Native Language Support
1999-05-05 Thorsten Kranzkowski <dl8bcu@gmx.net>
- enable hardware flow control before displaying /etc/issue
-
+
*/
#include <stdio.h>
#include <fcntl.h>
#include <stdarg.h>
#include <ctype.h>
-#include <utmp.h>
#include <getopt.h>
#include <termios.h>
#include "busybox.h"
-#define _PATH_LOGIN "/bin/login"
-
-#ifdef linux
-#include <sys/param.h>
-#define USE_SYSLOG
+#ifdef CONFIG_FEATURE_UTMP
+#include <utmp.h>
#endif
-extern void updwtmp(const char *filename, const struct utmp *ut);
+#define _PATH_LOGIN "/bin/login"
/* If USE_SYSLOG is undefined all diagnostics go directly to /dev/console. */
-#ifdef USE_SYSLOG
+#ifdef CONFIG_SYSLOGD
+#include <sys/param.h>
+#define USE_SYSLOG
#include <syslog.h>
#endif
#ifdef LOGIN_PROCESS /* defined in System V utmp.h */
#define SYSV_STYLE /* select System V style getty */
+#ifdef CONFIG_FEATURE_WTMP
+extern void updwtmp(const char *filename, const struct utmp *ut);
#endif
+#endif /* LOGIN_PROCESS */
/*
* 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 */
+ /* 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.
+ */
+#define ISSUE "/etc/issue" /* displayed before the login prompt */
/* Some shorthands for control characters. */
#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_EOL '\n'
#define DEF_SWITCH 0 /* default switch char */
/*
/* Initial values for the above. */
-struct chardata init_chardata = {
+static struct chardata init_chardata = {
DEF_ERASE, /* default erase character */
DEF_KILL, /* default kill character */
13, /* default eol char */
0, /* no capslock */
};
+#if 0
struct Speedtab {
long speed;
int code;
#endif
{0, 0},
};
+#endif
static void parse_args(int argc, char **argv, struct options *op);
static void parse_speeds(struct options *op, char *arg);
-static void update_utmp(char *line);
static void open_tty(char *tty, struct termio *tp, int local);
static void termio_init(struct termio *tp, int speed, struct options *op);
static void auto_baud(struct termio *tp);
struct chardata *cp);
static int caps_lock(const char *s);
-static int bcode(const char *s);
-static void error(const char *fmt, ...);
+static int bcode(char *s);
+static void error(const char *fmt, ...) __attribute__ ((noreturn));
+
+#ifdef SYSV_STYLE
+#ifdef CONFIG_FEATURE_UTMP
+static void update_utmp(char *line);
+#endif
+#endif
/* The following is used for understandable diagnostics. */
_PATH_LOGIN, /* default login program */
"tty1", /* default tty line */
"", /* modem init string */
+#ifdef ISSUE
ISSUE, /* default issue file */
+#else
+ NULL,
+#endif
0, /* no baud rates known yet */
};
#ifdef DEBUGGING
- dbf = xfopen(DEBUGTERM, "w");
+ dbf = bb_xfopen(DEBUGTERM, "w");
{
int i;
/* Update the utmp file. */
+
#ifdef SYSV_STYLE
+#ifdef CONFIG_FEATURE_UTMP
update_utmp(options.tty);
+#endif
#endif
debug("calling open_tty\n");
int iv;
iv = getpid();
- if (ioctl(0, TIOCSPGRP, &iv) < 0)
- perror_msg("ioctl() TIOCSPGRP call failed");
+ ioctl(0, TIOCSPGRP, &iv);
}
#endif
/* Initialize the termio settings (raw mode, eight-bit, blocking i/o). */
(void) execl(options.login, options.login, "--", logname, (char *) 0);
error("%s: can't exec %s: %m", options.tty, options.login);
- return (0); /* quiet GCC */
}
/* parse-args - parse command-line arguments */
while (isascii(c = getopt(argc, argv, "I:LH:f:hil:mt:wn"))) {
switch (c) {
case 'I':
- if (!(op->initstring = strdup(optarg))) {
- error("can't malloc initstring");
- break;
- }
+ if (!(op->initstring = strdup(optarg)))
+ error(bb_msg_memory_exhausted);
+
{
- char ch, *p, *q;
- int i;
+ const char *p;
+ char *q;
/* copy optarg into op->initstring decoding \ddd
octal codes into chars */
q = op->initstring;
p = optarg;
while (*p) {
- if (*p == '\\') { /* know \\ means \ */
+ if (*p == '\\') {
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;
+ *q++ = bb_process_escape_sequence(&p);
} else {
*q++ = *p++;
}
op->flags |= F_WAITCRLF;
break;
default:
- show_usage();
+ bb_show_usage();
}
}
debug("after getopt loop\n");
if (argc < optind + 2) /* check parameter count */
- show_usage();
+ bb_show_usage();
/* we loosen up a bit and accept both "baudrate tty" and "tty baudrate" */
if ('0' <= argv[optind][0] && argv[optind][0] <= '9') {
}
#ifdef SYSV_STYLE
+#ifdef CONFIG_FEATURE_UTMP
/* update_utmp - update our utmp entry */
static void update_utmp(char *line)
* utmp file can be opened for update, and if we are able to find our
* entry in the utmp file.
*/
+ if (access(_PATH_UTMP, R_OK|W_OK) == -1) {
+ close(creat(_PATH_UTMP, 0664));
+ }
utmpname(_PATH_UTMP);
setutent();
while ((utp = getutent())
pututline(&ut);
endutent();
- {
- updwtmp(_PATH_WTMP, &ut);
- }
+#ifdef CONFIG_FEATURE_WTMP
+ if (access(_PATH_WTMP, R_OK|W_OK) == -1)
+ close(creat(_PATH_WTMP, 0664));
+ updwtmp(_PATH_WTMP, &ut);
+#endif
}
-#endif
+#endif /* CONFIG_FEATURE_UTMP */
+#endif /* SYSV_STYLE */
/* open_tty - set up tty as standard { input, output, error } */
static void open_tty(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;
+ int fd;
/* Sanity checks... */
/* 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)
+ fd = open(tty, O_RDWR | O_NONBLOCK, 0);
+ if (dup2(fd, STDIN_FILENO) == -1)
error("/dev/%s: cannot open as standard input: %m", tty);
+ close(fd);
} else {
error("%s: not open for read/write", tty);
}
- /* Set up standard output and standard error file descriptors. */
+ /* Replace current standard output/error fd's with new ones */
debug("duping\n");
- if (dup(0) != 1 || dup(0) != 2) /* set up stdout and stderr */
+ if (dup2(STDIN_FILENO, STDOUT_FILENO) == -1 ||
+ dup2(STDIN_FILENO, STDERR_FILENO) == -1)
error("%s: dup problem: %m", tty); /* we have a problem */
/*
* 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
/* do_prompt - show login prompt, optionally preceded by /etc/issue contents */
static void do_prompt(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) {
- case 's':
- (void) printf("%s", uts.sysname);
- break;
-
- case 'n':
- (void) printf("%s", uts.nodename);
- break;
-
- case 'r':
- (void) printf("%s", uts.release);
- break;
-
- case 'v':
- (void) printf("%s", uts.version);
- break;
-
- case 'm':
- (void) printf("%s", uts.machine);
- break;
-
- case 'o':
- {
- char domainname[256];
-
- getdomainname(domainname, sizeof(domainname));
- domainname[sizeof(domainname) - 1] = '\0';
- printf("%s", domainname);
- }
- break;
-
- case 'd':
- case 't':
- {
- char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
- "Fri", "Sat"
- };
- char *month[] = { "Jan", "Feb", "Mar", "Apr", "May",
- "Jun", "Jul", "Aug", "Sep", "Oct",
- "Nov", "Dec"
- };
- time_t now;
- struct tm *tm;
-
- (void) time(&now);
- tm = localtime(&now);
-
- if (c == 'd')
- (void) printf("%s %s %d %d",
- weekday[tm->tm_wday],
- month[tm->tm_mon], tm->tm_mday,
- tm->tm_year <
- 70 ? tm->tm_year +
- 2000 : tm->tm_year + 1900);
- else
- (void) printf("%02d:%02d:%02d", tm->tm_hour,
- tm->tm_min, tm->tm_sec);
-
- break;
- }
-
- case 'l':
- (void) printf("%s", op->tty);
- break;
-
- case 'b':
- {
- int i;
-
- for (i = 0; speedtab[i].speed; i++) {
- if (speedtab[i].code == (tp->c_cflag & CBAUD)) {
- printf("%ld", speedtab[i].speed);
- break;
- }
- }
- break;
- }
- case 'u':
- case 'U':
- {
- int users = 0;
- struct utmp *ut;
-
- setutent();
- while ((ut = getutent()))
- if (ut->ut_type == USER_PROCESS)
- users++;
- endutent();
- printf("%d ", users);
- if (c == 'U')
- printf((users == 1) ? "user" : "users");
- break;
- }
- default:
- (void) putchar(c);
- }
- } else
- (void) putchar(c);
- }
- fflush(stdout);
-
- tp->c_oflag = oflag; /* restore settings */
- (void) ioctl(0, TCSETAW, tp); /* wait till output is gone */
- (void) fclose(fd);
- }
+ print_login_issue(op->issue, op->tty);
#endif
-#ifdef __linux__
- {
- char hn[MAXHOSTNAMELEN + 1];
-
- (void) gethostname(hn, MAXHOSTNAMELEN);
- write(1, hn, strlen(hn));
- }
-#endif
- (void) write(1, LOGIN, sizeof(LOGIN) - 1); /* always show login prompt */
+ print_login_prompt();
}
/* next_speed - select next baud rate */
tp->c_cc[VQUIT] = DEF_QUIT; /* default quit */
tp->c_cc[VEOF] = DEF_EOF; /* default EOF character */
tp->c_cc[VEOL] = DEF_EOL;
-#ifdef __linux__
tp->c_cc[VSWTC] = DEF_SWITCH; /* default switch character */
-#else
- tp->c_cc[VSWTCH] = DEF_SWITCH; /* default switch character */
-#endif
/* Account for special characters seen in input. */
}
/* bcode - convert speed string to speed code; return 0 on failure */
-static int bcode(const char *s)
+static int bcode(char *s)
{
- struct Speedtab *sp;
- long speed = atol(s);
-
- for (sp = speedtab; sp->speed; sp++)
- if (sp->speed == speed)
- return (sp->code);
- return (0);
+ int r;
+ unsigned long value;
+ if (safe_strtoul(s, &value)) {
+ return -1;
+ }
+ if ((r = bb_value_to_baud(value)) > 0) {
+ return r;
+ }
+ return 0;
}
/* error - report errors to console or syslog; only understands %s and %m */
buf[0] = '\0';
bp = buf;
#else
- strncpy(buf, applet_name, 256);
+ strncpy(buf, bb_applet_name, 256);
strncat(buf, ": ", 256);
buf[255] = 0;
bp = buf + strlen(buf);
va_end(va_alist);
#ifdef USE_SYSLOG
- syslog_msg(LOG_AUTH, LOG_ERR, buf);
+ openlog(bb_applet_name, 0, LOG_AUTH);
+ syslog(LOG_ERR, "%s", buf);
+ closelog();
#else
strncat(bp, "\r\n", 256 - strlen(buf));
buf[255] = 0;