Ahem: add new faq entry to list at top of FAQ.html
[oweals/busybox.git] / loginutils / getty.c
index 1b9c6ac4d61a1aaa832ed75278efe974831dd6c9..9bad008c60bbabe7c0f40cda71d57730ab017841 100644 (file)
@@ -5,13 +5,13 @@
    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"
 
+#ifdef CONFIG_FEATURE_UTMP
+#include <utmp.h>
+#endif
+
 #define _PATH_LOGIN     "/bin/login"
 
-#ifdef linux
+ /* If USE_SYSLOG is undefined all diagnostics go directly to /dev/console. */
+#ifdef CONFIG_SYSLOGD
 #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
 
 
 #ifdef LOGIN_PROCESS                   /* defined in System V utmp.h */
 #define        SYSV_STYLE                              /* select System V style getty */
-#ifdef CONFIG_FEATURE_U_W_TMP
+#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
 
+ /* 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 CTL(x)         (x ^ 0100)      /* Assumes ASCII dialect */
@@ -88,7 +89,7 @@ extern void updwtmp(const char *filename, const struct utmp *ut);
 #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 */
 
  /*
@@ -164,7 +165,7 @@ struct chardata {
 
 /* 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 */
@@ -172,6 +173,7 @@ struct chardata init_chardata = {
        0,                                                      /* no capslock */
 };
 
+#if 0
 struct Speedtab {
        long speed;
        int code;
@@ -214,6 +216,7 @@ static struct Speedtab speedtab[] = {
 #endif
        {0, 0},
 };
+#endif
 
 static void parse_args(int argc, char **argv, struct options *op);
 static void parse_speeds(struct options *op, char *arg);
@@ -229,12 +232,14 @@ static void termio_final(struct options *op, struct termio *tp,
 
                                  struct chardata *cp);
 static int caps_lock(const char *s);
-static int bcode(const char *s);
+static int bcode(char *s);
 static void error(const char *fmt, ...) __attribute__ ((noreturn));
 
-#ifdef CONFIG_FEATURE_U_W_TMP
+#ifdef SYSV_STYLE
+#ifdef CONFIG_FEATURE_UTMP
 static void update_utmp(char *line);
 #endif
+#endif
 
 /* The following is used for understandable diagnostics. */
 
@@ -261,12 +266,16 @@ int getty_main(int argc, char **argv)
                _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;
@@ -290,7 +299,7 @@ int getty_main(int argc, char **argv)
 
 
 #ifdef SYSV_STYLE
-#ifdef CONFIG_FEATURE_U_W_TMP
+#ifdef CONFIG_FEATURE_UTMP
        update_utmp(options.tty);
 #endif
 #endif
@@ -386,8 +395,8 @@ static void parse_args(int argc, char **argv, struct options *op)
                switch (c) {
                case 'I':
                        if (!(op->initstring = strdup(optarg)))
-                               error(memory_exhausted);
-                               
+                               error(bb_msg_memory_exhausted);
+
                        {
                                const char *p;
                                char *q;
@@ -399,7 +408,7 @@ static void parse_args(int argc, char **argv, struct options *op)
                                while (*p) {
                                        if (*p == '\\') {
                                                p++;
-                                               *q++ = process_escape_sequence(&p);
+                                               *q++ = bb_process_escape_sequence(&p);
                                        } else {
                                                *q++ = *p++;
                                        }
@@ -442,12 +451,12 @@ static void parse_args(int argc, char **argv, struct options *op)
                        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') {
@@ -483,7 +492,7 @@ static void parse_speeds(struct options *op, char *arg)
 }
 
 #ifdef SYSV_STYLE
-#ifdef CONFIG_FEATURE_U_W_TMP
+#ifdef CONFIG_FEATURE_UTMP
 
 /* update_utmp - update our utmp entry */
 static void update_utmp(char *line)
@@ -504,6 +513,9 @@ 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())
@@ -531,27 +543,24 @@ static void update_utmp(char *line)
        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 /* CONFIG_FEATURE_U_W_TMP */
+#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... */
 
@@ -564,12 +573,11 @@ static void open_tty(char *tty, struct termio *tp, int local)
 
                /* 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 {
 
@@ -582,9 +590,10 @@ static void open_tty(char *tty, struct termio *tp, int local)
                        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 */
 
        /*
@@ -701,9 +710,9 @@ static void auto_baud(struct termio *tp)
         * 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
@@ -954,15 +963,17 @@ static int caps_lock(const char *s)
 }
 
 /* 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 */
@@ -985,7 +996,7 @@ static void error(const char *fmt, ...)
        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);
@@ -997,7 +1008,9 @@ static void error(const char *fmt, ...)
        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;