diff options
author | Elliott Hughes <enh@google.com> | 2020-08-11 12:17:13 -0700 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2020-08-12 04:52:51 -0500 |
commit | 32b8a54ca2c08d54447917c80a5a6311932004e5 (patch) | |
tree | a01a695663da3aa2410c644f2f22c0221bee712c | |
parent | 98943e25c8d24423c74e4a31d70f274c78e35e51 (diff) | |
download | toybox-32b8a54ca2c08d54447917c80a5a6311932004e5.tar.gz |
getty: ensure utmp is updated.
The key issues here turned out to be that getty is responsible for
creating the file if it doesn't exist, and that the -H flag doesn't
control whether utmp is updated, but whether or not to override the
hostname within the utmp entry.
While I'm here switch to the more modern utx APIs that all the non-pending
parts of toybox use, and remove the duplication.
-rw-r--r-- | toys/pending/getty.c | 59 |
1 files changed, 28 insertions, 31 deletions
diff --git a/toys/pending/getty.c b/toys/pending/getty.c index 51b58962..159ce9b0 100644 --- a/toys/pending/getty.c +++ b/toys/pending/getty.c @@ -25,9 +25,9 @@ config GETTY -I INITSTR Send INITSTR before anything else -H HOST Log HOST into the utmp file as the hostname */ + #define FOR_getty #include "toys.h" -#include <utmp.h> GLOBALS( char *issue_str; @@ -259,38 +259,35 @@ static int read_login_name(void) return 1; } -// Put hostname entry in utmp file static void utmp_entry(void) { - struct utmp entry; - struct utmp *utp_ptr; - pid_t pid = getpid(); - char *utmperr = "can't make utmp entry, host length greater than UT_HOSTSIZE(256)"; - - utmpname(_PATH_UTMP); - setutent(); // Starts from start - while ((utp_ptr = getutent())) - if (utp_ptr->ut_pid == pid && utp_ptr->ut_type >= INIT_PROCESS) break; - if (!utp_ptr) { - entry.ut_type = LOGIN_PROCESS; - entry.ut_pid = getpid(); - xstrncpy(entry.ut_line, ttyname(STDIN_FILENO) + - strlen("/dev/"), UT_LINESIZE); - time((time_t *)&entry.ut_time); - xstrncpy(entry.ut_user, "LOGIN", UT_NAMESIZE); - if (strlen(TT.host_str) > UT_HOSTSIZE) perror_msg_raw(utmperr); - else xstrncpy(entry.ut_host, TT.host_str, UT_HOSTSIZE); - setutent(); - pututline(&entry); - return; + struct utmpx entry = {.ut_pid = getpid()}, *ep; + int fd; + + // We're responsible for ensuring that the utmp file exists. + if (access(_PATH_UTMP, F_OK) && (fd = open(_PATH_UTMP, O_CREAT, 0664)) != -1) + close(fd); + + // Find any existing entry. + setutxent(); + while ((ep = getutxent())) + if (ep->ut_pid == entry.ut_pid && ep->ut_type >= INIT_PROCESS) break; + if (ep) entry = *ep; + else entry.ut_type = LOGIN_PROCESS; + + // Modify. + entry.ut_tv.tv_sec = time(0); + xstrncpy(entry.ut_user, "LOGIN", sizeof(entry.ut_user)); + xstrncpy(entry.ut_line, ttyname(0) + strlen("/dev/"), sizeof(entry.ut_line)); + if (FLAG(H)) { + if (strlen(TT.host_str) >= sizeof(entry.ut_host)) + perror_msg_raw("hostname too long"); + else xstrncpy(entry.ut_host, TT.host_str, sizeof(entry.ut_host)); } - xstrncpy(entry.ut_line, ttyname(STDIN_FILENO) + strlen("/dev/"), UT_LINESIZE); - xstrncpy(entry.ut_user, "LOGIN", UT_NAMESIZE); - if (strlen(TT.host_str) > UT_HOSTSIZE) perror_msg_raw(utmperr); - else xstrncpy(entry.ut_host, TT.host_str, UT_HOSTSIZE); - time((time_t *)&entry.ut_time); - setutent(); - pututline(&entry); + + // Write. + pututxline(&entry); + endutxent(); } void getty_main(void) @@ -304,7 +301,7 @@ void getty_main(void) open_tty(); termios_init(); tcsetpgrp(STDIN_FILENO, pid); - if (toys.optflags & FLAG_H) utmp_entry(); + utmp_entry(); if (toys.optflags & FLAG_I) writeall(STDOUT_FILENO,TT.init_str,strlen(TT.init_str)); if (toys.optflags & FLAG_m) sense_baud(); |