From: Lennart Poettering Date: Fri, 8 Oct 2010 14:06:23 +0000 (+0200) Subject: service: optionally, create INIT_PROCESS/DEAD_PROCESS entries for a service X-Git-Tag: v12~258 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=169c1bda807d183a362b47efe0b5b56e9320e430 service: optionally, create INIT_PROCESS/DEAD_PROCESS entries for a service This should fix accounting for pam_limits and suchlike. https://bugzilla.redhat.com/show_bug.cgi?id=636036 --- diff --git a/Makefile.am b/Makefile.am index 021babc43..c4d4d2773 100644 --- a/Makefile.am +++ b/Makefile.am @@ -374,6 +374,7 @@ libsystemd_core_la_SOURCES = \ src/path.c \ src/load-dropin.c \ src/execute.c \ + src/utmp-wtmp.c \ src/exit-status.c \ src/dbus.c \ src/dbus-manager.c \ @@ -440,7 +441,6 @@ EXTRA_DIST += \ src/dbus-common.h \ src/bus-errors.h \ src/cgroup-show.h \ - src/utmp-wtmp.h \ src/build.h \ src/shutdownd.h \ src/readahead-common.h diff --git a/TODO b/TODO index cdb4cc57f..0a7efa111 100644 --- a/TODO +++ b/TODO @@ -24,8 +24,6 @@ - bluetoothd (/var/run/sdp! @/org/bluez/audio!) - distccd -* write utmp record a la upstart for processes - * selinux policy loading * fingerprint.target, wireless.target, gps.target diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 38b9e0608..51dcdcd94 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -728,6 +728,27 @@ it. + + UtmpIdentifier= + + Takes a a four + character identifier string for an + utmp/wtmp entry for this service. This + should only be set for services such + as getty + implementations where utmp/wtmp + entries must be created and cleared + before and after execution. If the + configured string is longer than four + characters it is truncated and the + terminal four characters are + used. This setting interprets %I style + string replacements. This setting is + unset by default, i.e. no utmp/wtmp + entries are created or cleaned up for + this service. + + diff --git a/src/dbus-execute.h b/src/dbus-execute.h index f1814315f..3d84c2061 100644 --- a/src/dbus-execute.h +++ b/src/dbus-execute.h @@ -84,8 +84,9 @@ " \n" \ " \n" \ " \n" \ - " \n" \ - " \n" + " \n" \ + " \n" \ + " \n" #define BUS_EXEC_COMMAND_INTERFACE(name) \ " \n" @@ -142,7 +143,8 @@ { interface, "PrivateTmp", bus_property_append_bool, "b", &(context).private_tmp }, \ { interface, "SameProcessGroup", bus_property_append_bool, "b", &(context).same_pgrp }, \ { interface, "KillMode", bus_execute_append_kill_mode, "s", &(context).kill_mode }, \ - { interface, "KillSignal", bus_property_append_int, "i", &(context).kill_signal } + { interface, "KillSignal", bus_property_append_int, "i", &(context).kill_signal }, \ + { interface, "UtmpIdentifier", bus_property_append_string, "s", &(context).utmp_id } #define BUS_EXEC_STATUS_PROPERTIES(interface, estatus, prefix) \ { interface, prefix "StartTimestamp", bus_property_append_usec, "t", &(estatus).start_timestamp.realtime }, \ diff --git a/src/execute.c b/src/execute.c index 6db048c5f..9c7e0d6b7 100644 --- a/src/execute.c +++ b/src/execute.c @@ -54,6 +54,7 @@ #include "tcpwrap.h" #include "exit-status.h" #include "missing.h" +#include "utmp-wtmp.h" /* This assumes there is a 'tty' group */ #define TTY_MODE 0620 @@ -1129,6 +1130,9 @@ int exec_spawn(ExecCommand *command, goto fail; } + if (context->utmp_id) + utmp_put_init_process(0, context->utmp_id, getpid(), getsid(0), context->tty_path); + if (context->user) { username = context->user; if (get_user_creds(&username, &uid, &gid, &home) < 0) { @@ -1604,6 +1608,12 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { "%sKillSignal: SIG%s\n", prefix, kill_mode_to_string(c->kill_mode), prefix, signal_to_string(c->kill_signal)); + + if (c->utmp_id) + fprintf(f, + "%sUtmpIdentifier: %s\n", + prefix, c->utmp_id); + } void exec_status_start(ExecStatus *s, pid_t pid) { @@ -1614,7 +1624,7 @@ void exec_status_start(ExecStatus *s, pid_t pid) { dual_timestamp_get(&s->start_timestamp); } -void exec_status_exit(ExecStatus *s, pid_t pid, int code, int status) { +void exec_status_exit(ExecStatus *s, pid_t pid, int code, int status, const char *utmp_id) { assert(s); if ((s->pid && s->pid != pid) || @@ -1626,6 +1636,9 @@ void exec_status_exit(ExecStatus *s, pid_t pid, int code, int status) { s->code = code; s->status = status; + + if (utmp_id) + utmp_put_dead_process(utmp_id, pid, code, status); } void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) { diff --git a/src/execute.h b/src/execute.h index b61214502..ed61e3c62 100644 --- a/src/execute.h +++ b/src/execute.h @@ -127,6 +127,8 @@ struct ExecContext { char *pam_name; + char *utmp_id; + char **read_write_dirs, **read_only_dirs, **inaccessible_dirs; unsigned long mount_flags; @@ -191,7 +193,7 @@ void exec_context_done(ExecContext *c); void exec_context_dump(ExecContext *c, FILE* f, const char *prefix); void exec_status_start(ExecStatus *s, pid_t pid); -void exec_status_exit(ExecStatus *s, pid_t pid, int code, int status); +void exec_status_exit(ExecStatus *s, pid_t pid, int code, int status, const char *utmp_id); void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix); const char* exec_output_to_string(ExecOutput i); diff --git a/src/load-fragment.c b/src/load-fragment.c index 740c11c3c..b22955b42 100644 --- a/src/load-fragment.c +++ b/src/load-fragment.c @@ -1669,7 +1669,8 @@ static int load_from_path(Unit *u, const char *path) { { "TCPWrapName", config_parse_string_printf, &(context).tcpwrap_name, section }, \ { "PAMName", config_parse_string_printf, &(context).pam_name, section }, \ { "KillMode", config_parse_kill_mode, &(context).kill_mode, section }, \ - { "KillSignal", config_parse_kill_signal, &(context).kill_signal, section } + { "KillSignal", config_parse_kill_signal, &(context).kill_signal, section }, \ + { "UtmpIdentifier", config_parse_string_printf, &(context).utmp_id, section } const ConfigItem items[] = { { "Names", config_parse_names, u, "Unit" }, diff --git a/src/mount.c b/src/mount.c index fefe76bb4..3320bf120 100644 --- a/src/mount.c +++ b/src/mount.c @@ -1057,7 +1057,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { m->failure = m->failure || !success; if (m->control_command) { - exec_status_exit(&m->control_command->exec_status, pid, code, status); + exec_status_exit(&m->control_command->exec_status, pid, code, status, m->exec_context.utmp_id); m->control_command = NULL; m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID; } diff --git a/src/service.c b/src/service.c index 195f04a31..04496a2dd 100644 --- a/src/service.c +++ b/src/service.c @@ -2406,7 +2406,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { if (s->main_pid == pid) { s->main_pid = 0; - exec_status_exit(&s->main_exec_status, pid, code, status); + exec_status_exit(&s->main_exec_status, pid, code, status, s->exec_context.utmp_id); if (s->type != SERVICE_FORKING && s->control_command) { s->control_command->exec_status = s->main_exec_status; @@ -2483,7 +2483,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { s->control_pid = 0; if (s->control_command) { - exec_status_exit(&s->control_command->exec_status, pid, code, status); + exec_status_exit(&s->control_command->exec_status, pid, code, status, s->exec_context.utmp_id); if (s->control_command->ignore) success = true; diff --git a/src/socket.c b/src/socket.c index 2567d0feb..fc6088c26 100644 --- a/src/socket.c +++ b/src/socket.c @@ -1601,7 +1601,7 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) { success = is_clean_exit(code, status); if (s->control_command) { - exec_status_exit(&s->control_command->exec_status, pid, code, status); + exec_status_exit(&s->control_command->exec_status, pid, code, status, s->exec_context.utmp_id); if (s->control_command->ignore) success = true; diff --git a/src/utmp-wtmp.c b/src/utmp-wtmp.c index 77baaffac..41589303b 100644 --- a/src/utmp-wtmp.c +++ b/src/utmp-wtmp.c @@ -92,19 +92,26 @@ int utmp_get_runlevel(int *runlevel, int *previous) { return r; } -static void init_entry(struct utmpx *store, usec_t t) { - struct utsname uts; - +static void init_timestamp(struct utmpx *store, usec_t t) { assert(store); zero(*store); - zero(uts); if (t <= 0) t = now(CLOCK_REALTIME); store->ut_tv.tv_sec = t / USEC_PER_SEC; store->ut_tv.tv_usec = t % USEC_PER_SEC; +} + +static void init_entry(struct utmpx *store, usec_t t) { + struct utsname uts; + + assert(store); + + init_timestamp(store, t); + + zero(uts); if (uname(&uts) >= 0) strncpy(store->ut_host, uts.release, sizeof(store->ut_host)); @@ -187,6 +194,69 @@ int utmp_put_reboot(usec_t t) { return write_entry_both(&store); } +static const char *sanitize_id(const char *id) { + size_t l; + + assert(id); + l = strlen(id); + + if (l <= sizeof(((struct utmpx*) NULL)->ut_id)) + return id; + + return id + l - sizeof(((struct utmpx*) NULL)->ut_id); +} + +int utmp_put_init_process(usec_t t, const char *id, pid_t pid, pid_t sid, const char *line) { + struct utmpx store; + + assert(id); + + init_timestamp(&store, t); + + store.ut_type = INIT_PROCESS; + store.ut_pid = pid; + store.ut_session = sid; + + strncpy(store.ut_id, sanitize_id(id), sizeof(store.ut_id)); + + if (line) + strncpy(store.ut_line, file_name_from_path(line), sizeof(store.ut_line)); + + return write_entry_both(&store); +} + +int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) { + struct utmpx lookup, store, *found; + + assert(id); + + setutxent(); + + zero(lookup); + lookup.ut_type = INIT_PROCESS; /* looks for DEAD_PROCESS, LOGIN_PROCESS, USER_PROCESS, too */ + strncpy(lookup.ut_id, sanitize_id(id), sizeof(lookup.ut_id)); + + if (!(found = getutxid(&lookup))) + return 0; + + if (found->ut_pid != pid) + return 0; + + zero(store); + + memcpy(&store, &lookup, sizeof(store)); + store.ut_type = DEAD_PROCESS; + store.ut_exit.e_termination = code; + store.ut_exit.e_exit = status; + + zero(store.ut_user); + zero(store.ut_host); + zero(store.ut_tv); + + return write_entry_both(&store); +} + + int utmp_put_runlevel(usec_t t, int runlevel, int previous) { struct utmpx store; int r; diff --git a/src/utmp-wtmp.h b/src/utmp-wtmp.h index 0d608f6a5..86bc6bd3f 100644 --- a/src/utmp-wtmp.h +++ b/src/utmp-wtmp.h @@ -30,6 +30,9 @@ int utmp_put_shutdown(usec_t timestamp); int utmp_put_reboot(usec_t timestamp); int utmp_put_runlevel(usec_t timestamp, int runlevel, int previous); +int utmp_put_dead_process(const char *id, pid_t pid, int code, int status); +int utmp_put_init_process(usec_t timestamp, const char *id, pid_t pid, pid_t sid, const char *line); + int utmp_wall(const char *message); #endif diff --git a/units/getty@.service.m4 b/units/getty@.service.m4 index 8df77c701..be5916a15 100644 --- a/units/getty@.service.m4 +++ b/units/getty@.service.m4 @@ -33,6 +33,7 @@ Environment=TERM=linux ExecStart=-GETTY %I Restart=always RestartSec=0 +UtmpIdentifier=%I KillMode=process-group # Some login implementations ignore SIGTERM, so we send SIGHUP