From 2718c709aad3d3d39bd83921910f940da391928e Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Tue, 9 Aug 2016 00:11:53 +0200 Subject: [PATCH] UTMP: Add support for INIT_PROCESS & DEAD_PROCESS Services started by Finit are now properly accounted for in UTMP. Signed-off-by: Joachim Nilsson --- exec.c | 12 ++++++++++-- service.c | 15 ++++++++++++--- utmp-api.c | 56 ++++++++++++++++++++++++++++++++++++++++-------------- utmp-api.h | 4 +++- 4 files changed, 67 insertions(+), 20 deletions(-) diff --git a/exec.c b/exec.c index 216c07ef..d0e3fc58 100644 --- a/exec.c +++ b/exec.c @@ -32,8 +32,9 @@ #include #include "finit.h" -#include "sig.h" #include "helpers.h" +#include "sig.h" +#include "utmp-api.h" #define NUM_ARGS 16 @@ -105,6 +106,9 @@ int run(char *cmd) for (i = 1; i < NSIG; i++) DFLSIG(sa, i, 0); + /* Set INIT_PROCESS UTMP entry */ + utmp_set_init(ttyname(0), 0); + /* Always redirect stdio for run() */ fp = fopen("/dev/null", "w"); if (fp) { @@ -216,13 +220,17 @@ int getty(char *tty, char *baud, char *term); pid_t run_getty(char *tty, char *speed, char *term, int console) { - pid_t pid = fork(); + pid_t pid; + pid = fork(); if (!pid) { /* Reset signal handlers that were set by the parent process */ sig_unblock(); setsid(); + /* Set INIT_PROCESS UTMP entry */ + utmp_set_init(tty, 0); + if (console) prctl(PR_SET_NAME, "console", 0, 0, 0); else diff --git a/service.c b/service.c index 6cad71b5..7e56be72 100755 --- a/service.c +++ b/service.c @@ -29,16 +29,17 @@ #include #include -#include "finit.h" #include "conf.h" #include "cond.h" +#include "finit.h" #include "helpers.h" +#include "inetd.h" #include "private.h" #include "sig.h" -#include "tty.h" #include "service.h" -#include "inetd.h" #include "sm.h" +#include "tty.h" +#include "utmp-api.h" #define RESPAWN_MAX 10 /* Prevent endless respawn of faulty services. */ @@ -151,6 +152,7 @@ static int service_start(svc_t *svc) pid = fork(); if (pid == 0) { int status; + char id[5]; char *home = NULL; #ifdef ENABLE_STATIC int uid = 0; /* XXX: Fix better warning that dropprivs is disabled. */ @@ -159,6 +161,10 @@ static int service_start(svc_t *svc) #endif char *args[MAX_NUM_SVC_ARGS]; + /* Set INIT_PROCESS UTMP entry */ + snprintf(id, sizeof(id), "%d", svc->job); + utmp_set_init(ttyname(0), id); + /* Set desired user */ if (uid >= 0) { setuid(uid); @@ -661,6 +667,9 @@ void service_monitor(pid_t lost) svc_t *svc; char pidfile[MAX_ARG_LEN]; + /* Set DEAD_PROCESS UTMP entry */ + utmp_set_dead(lost); + if (fexist(SYNC_SHUTDOWN) || lost <= 1) return; diff --git a/utmp-api.c b/utmp-api.c index 8653a6d4..3b938941 100644 --- a/utmp-api.c +++ b/utmp-api.c @@ -28,7 +28,7 @@ #include #include -int utmp_set(int type, int pid, char *user, char *line, char *id) +int utmp_set(int type, int pid, char *line, char *id, char *user) { int result; struct utmp ut; @@ -48,9 +48,12 @@ int utmp_set(int type, int pid, char *user, char *line, char *id) memset(&ut, 0, sizeof(ut)); ut.ut_type = type; ut.ut_pid = pid; - strlcpy(ut.ut_user, user, sizeof(ut.ut_user)); - strlcpy(ut.ut_line, line, sizeof(ut.ut_line)); - strlcpy(ut.ut_id, id, sizeof(ut.ut_id)); + if (user) + strlcpy(ut.ut_user, user, sizeof(ut.ut_user)); + if (line) + strlcpy(ut.ut_line, line, sizeof(ut.ut_line)); + if (id) + strlcpy(ut.ut_id, id, sizeof(ut.ut_id)); if (!uname(&uts)) strncpy(ut.ut_host, uts.release, sizeof(ut.ut_host)); ut.ut_tv.tv_sec = time(NULL); @@ -64,6 +67,41 @@ int utmp_set(int type, int pid, char *user, char *line, char *id) return result; } +int utmp_set_boot(void) +{ + return utmp_set(BOOT_TIME, 0, NULL, NULL, "reboot"); +} + +int utmp_set_halt(void) +{ + return utmp_set(RUN_LVL, 0, NULL, NULL, "shutdown"); +} + +int utmp_set_init(char *tty, char *id) +{ + char *line; + + if (!tty) + line = ""; + else if (!strncmp(tty, "/dev/", 5)) + line = tty + 5; + else + line = tty; + + if (!id) { + id = line; + if (!strncmp(id, "pts/", 4)) + id += 4; + } + + return utmp_set(INIT_PROCESS, getpid(), line, id, NULL); +} + +int utmp_set_dead(int pid) +{ + return utmp_set(DEAD_PROCESS, pid, NULL, NULL, NULL); +} + static int encode(int lvl) { if (!lvl) return 0; @@ -75,16 +113,6 @@ int utmp_set_runlevel(int pre, int now) return utmp_set(RUN_LVL, (encode(pre) << 8) | (encode(now) & 0xFF), "runlevel", NULL, NULL); } -int utmp_set_boot(void) -{ - return utmp_set(BOOT_TIME, 0, "reboot", NULL, NULL); -} - -int utmp_set_halt(void) -{ - return utmp_set(RUN_LVL, 0, "shutdown", NULL, NULL); -} - int utmp_show(char *file) { time_t sec; diff --git a/utmp-api.h b/utmp-api.h index 8c819f32..63368d6a 100644 --- a/utmp-api.h +++ b/utmp-api.h @@ -21,9 +21,11 @@ * THE SOFTWARE. */ -int utmp_set (int type, int pid, char *user, char *line, char *id); +int utmp_set (int type, int pid, char *line, char *id, char *user); int utmp_set_boot (void); int utmp_set_halt (void); +int utmp_set_init (char *tty, char *id); +int utmp_set_dead (int pid); int utmp_set_runlevel(int pre, int now); int utmp_show (char *file);