From 94c0d1b8331827fc6fb40ca22afc02a1cb7571d6 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 30 May 2021 09:28:10 +0200 Subject: [PATCH] Refactor built-in getty into a standalone getty in /libexec This patch moves the built-in getty out of Finit into /libexec/finit/, reducing the size of the Finit binary and simplifying the code. Signed-off-by: Joachim Wiberg --- src/.gitignore | 1 + src/Makefile.am | 9 +++-- src/exec.c | 41 +++++++++++++++++++-- src/getty.c | 95 ++++++++++++++++--------------------------------- src/helpers.h | 5 +-- src/initctl.c | 1 + src/util.c | 10 ------ src/util.h | 1 - src/utmp-api.h | 10 ++++++ 9 files changed, 89 insertions(+), 84 deletions(-) diff --git a/src/.gitignore b/src/.gitignore index dd3cb9ef..a95be46b 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,5 +1,6 @@ .deps/* finit +getty initctl keventd logit diff --git a/src/Makefile.am b/src/Makefile.am index 8c32f777..bee9ae62 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,7 @@ AM_LDFLAGS = -export-dynamic endif sbin_PROGRAMS = finit initctl -pkglibexec_PROGRAMS = logit sulogin +pkglibexec_PROGRAMS = getty logit sulogin if KEVENTD pkglibexec_PROGRAMS += keventd endif @@ -19,6 +19,11 @@ endif finit_pkglibdir = $(pkglibdir) finit_pkglib_SCRIPTS = rescue.conf sample.conf +getty_SOURCES = getty.c helpers.h logrotate.c stty.c utmp-api.c utmp-api.h +getty_CFLAGS = -W -Wall -Wextra -std=gnu99 +getty_CFLAGS += $(lite_CFLAGS) +getty_LDADD = $(lite_LIBS) + keventd_SOURCES = keventd.c iwatch.c iwatch.h util.c util.h keventd_CFLAGS = -W -Wall -Wextra -std=gnu99 keventd_CFLAGS += $(lite_CFLAGS) @@ -37,7 +42,7 @@ finit_SOURCES = api.c cgroup.c cgroup.h \ cond.c cond-w.c cond.h \ conf.c conf.h \ exec.c finit.c finit.h \ - getty.c stty.c \ + stty.c \ helpers.c helpers.h \ iwatch.c iwatch.h \ log.c log.h \ diff --git a/src/exec.c b/src/exec.c index b20938f8..457046b3 100644 --- a/src/exec.c +++ b/src/exec.c @@ -26,6 +26,7 @@ #include /* isdigit() */ #include +#include #include #include #include @@ -388,9 +389,19 @@ pid_t run_getty(char *tty, char *baud, char *term, int noclear, int nowait, stru speed = stty_parse_speed(baud); prepare_tty(tty, speed, "tty", rlimit); if (activate_console(noclear, nowait)) { - logit(LOG_INFO, "Starting built-in getty on %s, speed %u", tty, speed); - rc = getty(tty, speed, term, NULL); + char spd[15]; + char *args[5] = { + "getty", + tty, + spd, + term, + NULL + }; + snprintf(spd, sizeof(spd), "%d", speed); + logit(LOG_ERR, "Starting built-in getty on %s, speed %u", tty, speed); + rc = execv("/libexec/finit/getty", args); } + logit(LOG_ERR, "Failed starting built-in getty on %s, speed %u", tty, speed); return rc; } @@ -414,6 +425,32 @@ pid_t run_getty2(char *tty, char *cmd, char *args[], int noclear, int nowait, st return rc; } +int sh(char *tty) +{ + char *args[2] = { + NULL, + NULL + }; + char *arg0; + size_t len; + + /* The getty process is usually responsible for the UTMP login record */ + utmp_set_login(tty, NULL); + + /* 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; + + /* Unblock signals inherited from parent */ + sig_unblock(); + + return execv(_PATH_BSHELL, args); +} + pid_t run_sh(char *tty, int noclear, int nowait, struct rlimit rlimit[]) { int rc = 1; diff --git a/src/getty.c b/src/getty.c index 5cd1d4cd..8a8dcf45 100644 --- a/src/getty.c +++ b/src/getty.c @@ -26,15 +26,13 @@ #include #include #include +#include #include #include #include /* Not included by default in musl libc */ #include -#include "finit.h" -#include "cgroup.h" #include "helpers.h" -#include "sig.h" #include "utmp-api.h" #ifndef _PATH_LOGIN @@ -44,19 +42,14 @@ /* * Read one character from stdin. */ -static int readch(char *tty) +static int readch(void) { - int st; char ch1; + int st; st = read(STDIN_FILENO, &ch1, 1); - if (st == 0) { - dprint(STDOUT_FILENO, "\n", 0); - _exit(0); - } - - if (st < 0) - errx(1, "getty: %s: read error", tty); + if (st <= 0) + return -1; return ch1 & 0xFF; } @@ -141,10 +134,10 @@ static void do_issue(char *tty) /* * Handle the process of a GETTY. */ -static void do_getty(char *tty, char *name, size_t len) +static int get_logname(char *tty, char *name, size_t len) { - int ch; char *np; + int ch; /* * Display prompt. @@ -155,14 +148,9 @@ static void do_getty(char *tty, char *name, size_t len) do_issue(tty); np = name; - while ((ch = readch(tty)) != '\n') { - if (ch == CTRL('U')) { - while (np > name) { - dprint(STDOUT_FILENO, "\b \b", 3); - np--; - } - continue; - } + while ((ch = readch()) != '\n') { + if (ch < 0) + return 1; if (np < name + len) *np++ = ch; @@ -174,6 +162,7 @@ static void do_getty(char *tty, char *name, size_t len) } name[len - 1] = 0; + return 0; } /* @@ -185,7 +174,6 @@ static int do_login(char *name) { struct stat st; - cgroup_user(name, 0); execl(_PATH_LOGIN, _PATH_LOGIN, name, NULL); /* @@ -196,12 +184,12 @@ static int do_login(char *name) */ warnx("Failed exec %s, attempting fallback to %s ...", _PATH_LOGIN, _PATH_BSHELL); if (fstat(0, &st) == 0 && S_ISCHR(st.st_mode)) - execl(_PATH_BSHELL, _PATH_BSHELL, NULL); + execl(_PATH_BSHELL, _PATH_BSHELL, NULL); /* XXX: run sulogin instead! */ return 1; /* We shouldn't get here ... */ } -int getty(char *tty, speed_t speed, char *term, char *user) +static int getty(char *tty, speed_t speed, char *term, char *user) { const char cln[] = "\r\e[2K\n"; char name[33]; /* useradd(1) limit at 32 chars */ @@ -212,15 +200,20 @@ int getty(char *tty, speed_t speed, char *term, char *user) if (!strncmp(tty, _PATH_DEV, strlen(_PATH_DEV))) tty += 5; - /* Set up TTY, re-enabling ISIG et al. */ - stty(STDIN_FILENO, speed); - dprint(STDERR_FILENO, cln, strlen(cln)); - /* The getty process is responsible for the UTMP login record */ utmp_set_login(tty, NULL); - if (!user) - do_getty(tty, name, sizeof(name)); - else + + /* Replace "Please press enter ..." with login: */ + dprint(STDERR_FILENO, cln, strlen(cln)); + +restart: + stty(STDIN_FILENO, speed); + if (!user) { + if (get_logname(tty, name, sizeof(name))) { + sleep(5); + goto restart; + } + } else strlcpy(name, user, sizeof(name)); if (term && term[0]) @@ -229,42 +222,14 @@ int getty(char *tty, speed_t speed, char *term, char *user) return do_login(name); } -int sh(char *tty) +int main(int argc, char *argv[]) { - struct termios term; - char *args[2] = { - NULL, - NULL - }; - char *arg0; - size_t len; - - /* 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(STDIN_FILENO, B0); - - /* 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; - - /* Reenable Ctrl-D and Ctrl-C, and ... */ - if (!tcgetattr(STDIN_FILENO, &term)) { - term.c_lflag |= ISIG; - term.c_cc[VEOF] = CEOF; - term.c_cc[VINTR] = CINTR; - tcsetattr(STDIN_FILENO, TCSAFLUSH, &term); + if (argc < 4) { + warnx("usage: getty tty speed term"); + return 1; } - /* ... unblock signals in general */ - sig_unblock(); - - return execv(_PATH_BSHELL, args); + return getty(argv[1], atoi(argv[2]), argv[3], NULL); } /** diff --git a/src/helpers.h b/src/helpers.h index 54fdd55a..38a65064 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -68,11 +68,8 @@ char *strip_line (char *line); void enable_progress (int onoff); void show_progress (pstyle_t style); -int getty (char *tty, speed_t speed, char *term, char *user); -int sh (char *tty); - -void stty (int fd, speed_t speed); speed_t stty_parse_speed(char *baud); +void stty (int fd, speed_t speed); void print_banner (const char *heading); void printv (const char *fmt, va_list ap); diff --git a/src/initctl.c b/src/initctl.c index 7cb6c46f..feb08659 100644 --- a/src/initctl.c +++ b/src/initctl.c @@ -41,6 +41,7 @@ #include "service.h" #include "cgutil.h" #include "util.h" +#include "utmp-api.h" struct cmd { char *cmd; diff --git a/src/util.c b/src/util.c index 9f90a2a7..84eab601 100644 --- a/src/util.c +++ b/src/util.c @@ -229,16 +229,6 @@ int fngetint(char *path, int *val) return 0; } -/* - * musl libc default to /dev/null/utmp and /dev/null/wtmp, respectively. - * See https://www.openwall.com/lists/musl/2012/03/04/4 for reasoning. - * Also, there's no __MUSL__, so we cannot make a libc-specific #ifdef - */ -int has_utmp(void) -{ - return strncmp(_PATH_UTMP, "/dev/null", 9); -} - int strtobytes(char *arg) { int mod = 0, bytes; diff --git a/src/util.h b/src/util.h index bb7cb97e..45c66545 100644 --- a/src/util.h +++ b/src/util.h @@ -54,7 +54,6 @@ int fnread (char *buf, size_t len, char *fmt, ...); int fnwrite (char *value, char *fmt, ...); int fngetint (char *path, int *val); -int has_utmp (void); int strtobytes (char *arg); char *sig2str (int sig); char *code2str (int code); diff --git a/src/utmp-api.h b/src/utmp-api.h index f3ddfd39..a9bddf36 100644 --- a/src/utmp-api.h +++ b/src/utmp-api.h @@ -42,6 +42,16 @@ int utmp_show (char *file); void runlevel_set (int pre, int now); +/* + * musl libc default to /dev/null/utmp and /dev/null/wtmp, respectively. + * See https://www.openwall.com/lists/musl/2012/03/04/4 for reasoning. + * Also, there's no __MUSL__, so we cannot make a libc-specific #ifdef + */ +static inline int has_utmp(void) +{ + return strncmp(_PATH_UTMP, "/dev/null", 9); +} + #endif /* FINIT_UTMP_API_H_ */ /**