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.
---
 toys/pending/getty.c | 59 +++++++++++++++++++++-----------------------
 1 file changed, 28 insertions(+), 31 deletions(-)
From 84c873a2fec29cd627e8c3c33049c0823e98692d Mon Sep 17 00:00:00 2001
From: Elliott Hughes <e...@google.com>
Date: Tue, 11 Aug 2020 12:17:13 -0700
Subject: [PATCH] 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.
---
 toys/pending/getty.c | 59 +++++++++++++++++++++-----------------------
 1 file 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();
-- 
2.28.0.236.gb10cc79966-goog

_______________________________________________
Toybox mailing list
Toybox@lists.landley.net
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to