From 72bc3b1a913a96eceab35b46e3877d7577a5c383 Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Sun, 24 Dec 2017 01:54:07 +0100 Subject: [PATCH] Fix #91: Add support for `tty nologin`, to start /bin/sh immediately This patch adds a `nologin` flag to the `tty` configuration directive, making it possible to set up really simple embedded systems with no login. Example, put the following line in `/etc/finit.d/getty.conf` to get a "Please press Enter to ..." prompt before being presented with a root shell prompt. tty [12345] @console noclear nologin Needless to say, this is not very secure, but can be really useful for developer setups, during board bringup, or similar. Signed-off-by: Joachim Nilsson --- src/exec.c | 14 ++++++++++++++ src/getty.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/helpers.h | 2 ++ src/tty.c | 10 +++++++++- src/tty.h | 1 + 5 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/exec.c b/src/exec.c index 53deb0ab..c4c69061 100644 --- a/src/exec.c +++ b/src/exec.c @@ -423,6 +423,20 @@ pid_t run_getty2(char *tty, char *cmd, char *args[], int noclear, int nowait, st return pid; } +pid_t run_sh(char *tty, int noclear, int nowait, struct rlimit rlimit[]) +{ + pid_t pid; + + pid = fork(); + if (!pid) { + prepare_tty(tty, B0, "finit-sh", rlimit); + if (activate_console(noclear, nowait)) + _exit(sh(tty)); + } + + return pid; +} + int run_parts(char *dir, char *cmd) { struct dirent **e; diff --git a/src/getty.c b/src/getty.c index e27a9daa..169b0fcc 100644 --- a/src/getty.c +++ b/src/getty.c @@ -243,6 +243,48 @@ int getty(char *tty, speed_t speed, char *term, char *user) return do_login(name); } +int sh(char *tty) +{ + int fd; + char *arg0; + char *args[2] = { + NULL, + NULL + }; + size_t len; + + /* Detach from initial controlling TTY */ + vhangup(); + + fd = open(tty, O_RDWR); + if (fd < 0) + err(1, "Failed opening %s", tty); + + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + + if (ioctl(STDIN_FILENO, TIOCSCTTY, 1) < 0) + warn("Failed TIOCSCTTY"); + + /* The getty process is usually responsible for the UTMP login record */ + utmp_set_login(tty, NULL); + + /* Set up TTY, re-enabling ISIG et al. */ + stty(fd, B0); + close(fd); + + /* Start /bin/sh as a login shell, i.e. with a prefix '-' */ + len = strlen(_PATH_BSHELL) + 2; + arg0 = malloc(len); + if (!arg0) + err(1, "Failed allocating memory"); + snprintf(arg0, len, "-%s", _PATH_BSHELL); + args[0] = arg0; + + return execv(_PATH_BSHELL, args); +} + /** * Local Variables: * indent-tabs-mode: t diff --git a/src/helpers.h b/src/helpers.h index d4378482..a3fd0c69 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -52,6 +52,7 @@ struct fstab *getfsent (void); char *strip_line (char *line); int getty (char *tty, speed_t speed, char *term, char *user); +int sh (char *tty); int stty (int fd, speed_t speed); speed_t stty_parse_speed(char *baud); @@ -74,6 +75,7 @@ int run_interactive (char *cmd, char *fmt, ...); int exec_runtask (char *cmd, char *args[]); pid_t run_getty (char *tty, char *baud, char *term, int noclear, int nowait, struct rlimit rlimit[]); pid_t run_getty2 (char *tty, char *cmd, char *args[], int noclear, int nowait, struct rlimit rlimit[]); +pid_t run_sh (char *tty, int noclear, int nowait, struct rlimit rlimit[]); int run_parts (char *dir, char *cmd); static inline void create(char *path, mode_t mode, uid_t uid, gid_t gid) diff --git a/src/tty.c b/src/tty.c index 47be0a46..e22c2459 100644 --- a/src/tty.c +++ b/src/tty.c @@ -137,7 +137,7 @@ void tty_sweep(void) int tty_register(char *line, struct rlimit rlimit[], char *file) { tty_node_t *entry; - int insert = 0, noclear = 0, nowait = 0; + int insert = 0, noclear = 0, nowait = 0, nologin = 0; size_t i, num = 0; char *tok, *cmd = NULL, *args[TTY_MAX_ARGS]; char *dev = NULL, *baud = NULL; @@ -159,6 +159,8 @@ int tty_register(char *line, struct rlimit rlimit[], char *file) noclear = 1; else if (!strcmp(tok, "nowait")) nowait = 1; + else if (!strcmp(tok, "nologin")) + nologin = 1; else args[num++] = tok; @@ -241,6 +243,7 @@ int tty_register(char *line, struct rlimit rlimit[], char *file) entry->data.term = term ? strdup(term) : NULL; entry->data.noclear = noclear; entry->data.nowait = nowait; + entry->data.nologin = nologin; entry->data.runlevels = conf_parse_runlevels(runlevels); /* External getty */ @@ -392,6 +395,11 @@ void tty_start(finit_tty_t *tty) return; } + if (tty->nologin) { + tty->pid = run_sh(dev, tty->noclear, tty->nowait, tty->rlimit); + return; + } + if (!tty->cmd) tty->pid = run_getty(dev, tty->baud, tty->term, tty->noclear, tty->nowait, tty->rlimit); else diff --git a/src/tty.h b/src/tty.h index b739eaaa..1ed5d50b 100644 --- a/src/tty.h +++ b/src/tty.h @@ -38,6 +38,7 @@ typedef struct { char *term; int noclear; int nowait; + int nologin; int runlevels; char *cmd; /* NULL when running built-in getty */