add support for writing reboot and shutdown records to wtmp

This commit is contained in:
William Hubbs 2017-06-02 14:07:40 -05:00
parent 1564e155b7
commit 7689106aa1
5 changed files with 121 additions and 24 deletions

26
src/includes/rc-wtmp.h Normal file
View File

@ -0,0 +1,26 @@
/*
* rc-wtmp.h
* This is private to us and not for user consumption
*/
/*
* Copyright (c) 2017 The OpenRC Authors.
* See the Authors file at the top-level directory of this distribution and
* https://github.com/OpenRC/openrc/blob/master/AUTHORS
*
* This file is part of OpenRC. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
* This file may not be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file.
*/
#ifndef __RC_WTMP_H__
#define __RC_WTMP_H__
#include <utmp.h>
void log_wtmp(const char *user, const char *id, pid_t pid, int type,
const char *line);
#endif

View File

@ -14,7 +14,7 @@ SRCS+= rc-selinux.c
endif endif
ifeq (${OS},Linux) ifeq (${OS},Linux)
SRCS+= kill_all.c openrc-init.c openrc-shutdown.c SRCS+= kill_all.c openrc-init.c openrc-shutdown.c rc-wtmp.c
endif endif
CLEANFILES= version.h rc-selinux.o CLEANFILES= version.h rc-selinux.o
@ -111,7 +111,7 @@ veinfo vewarn vebegin veend vewend veindent veoutdent: do_e.o rc-misc.o
fstabinfo: fstabinfo.o _usage.o rc-misc.o fstabinfo: fstabinfo.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
openrc-init: openrc-init.o openrc-init: openrc-init.o rc-wtmp.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
is_newer_than: is_newer_than.o rc-misc.o is_newer_than: is_newer_than.o rc-misc.o
@ -132,7 +132,7 @@ mountinfo: mountinfo.o _usage.o rc-misc.o
openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o _usage.o openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o _usage.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
openrc-shutdown: openrc-shutdown.o _usage.o openrc-shutdown: openrc-shutdown.o _usage.o rc-wtmp.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o

View File

@ -32,6 +32,7 @@
#include "helpers.h" #include "helpers.h"
#include "rc.h" #include "rc.h"
#include "rc-wtmp.h"
#include "version.h" #include "version.h"
static const char *rc_default_runlevel = "default"; static const char *rc_default_runlevel = "default";
@ -82,6 +83,7 @@ static void init(const char *default_runlevel)
} }
pid = do_openrc(runlevel); pid = do_openrc(runlevel);
waitpid(pid, NULL, 0); waitpid(pid, NULL, 0);
log_wtmp("reboot", "~~", 0, RUN_LVL, "~~");
} }
static void handle_reexec(char *my_name) static void handle_reexec(char *my_name)

View File

@ -27,46 +27,63 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/utsname.h>
#include "einfo.h" #include "einfo.h"
#include "rc.h" #include "rc.h"
#include "helpers.h" #include "helpers.h"
#include "_usage.h" #include "_usage.h"
#include "rc-wtmp.h"
const char *applet = NULL; const char *applet = NULL;
const char *extraopts = NULL; const char *extraopts = NULL;
const char *getoptstring = "dHkpRr" getoptstring_COMMON; const char *getoptstring = "dDHKpRrw" getoptstring_COMMON;
const struct option longopts[] = { const struct option longopts[] = {
{ "dry-run", no_argument, NULL, 'd'}, { "no-write", no_argument, NULL, 'd'},
{ "dry-run", no_argument, NULL, 'D'},
{ "halt", no_argument, NULL, 'H'}, { "halt", no_argument, NULL, 'H'},
{ "kexec", no_argument, NULL, 'k'}, { "kexec", no_argument, NULL, 'K'},
{ "poweroff", no_argument, NULL, 'p'}, { "poweroff", no_argument, NULL, 'p'},
{ "reexec", no_argument, NULL, 'R'}, { "reexec", no_argument, NULL, 'R'},
{ "reboot", no_argument, NULL, 'r'}, { "reboot", no_argument, NULL, 'r'},
{ "write-only", no_argument, NULL, 'w'},
longopts_COMMON longopts_COMMON
}; };
const char * const longopts_help[] = { const char * const longopts_help[] = {
"do not write wtmp record",
"print actions instead of executing them", "print actions instead of executing them",
"halt the system", "halt the system",
"reboot the system using kexec", "reboot the system using kexec",
"power off the system", "power off the system",
"re-execute init (use after upgrading)", "re-execute init (use after upgrading)",
"reboot the system", "reboot the system",
"write wtmp boot record and exit",
longopts_help_COMMON longopts_help_COMMON
}; };
const char *usagestring = NULL; const char *usagestring = NULL;
const char *exclusive = "Select one of " const char *exclusive = "Select one of "
"--halt, --kexec, --poweroff, --reexec or --reboot"; "--halt, --kexec, --poweroff, --reexec or --reboot";
static void send_cmd(const char *cmd, bool dryrun) static bool do_dryrun = false;
static bool do_halt = false;
static bool do_kexec = false;
static bool do_poweroff = false;
static bool do_reboot = false;
static bool do_reexec = false;
static bool do_wtmp = true;
static bool do_wtmp_only = false;
static void send_cmd(const char *cmd)
{ {
FILE *fifo; FILE *fifo;
size_t ignored; size_t ignored;
if (dryrun) { if (do_dryrun) {
einfo("Would send %s to init", cmd); einfo("Would send %s to init", cmd);
return; return;
} }
if (do_wtmp && (do_halt || do_kexec || do_reboot || do_poweroff))
log_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");
fifo = fopen(RC_INIT_FIFO, "w"); fifo = fopen(RC_INIT_FIFO, "w");
if (!fifo) { if (!fifo) {
perror("fopen"); perror("fopen");
@ -83,26 +100,23 @@ int main(int argc, char **argv)
{ {
int opt; int opt;
int cmd_count = 0; int cmd_count = 0;
bool do_dryrun = false;
bool do_halt = false;
bool do_kexec = false;
bool do_poweroff = false;
bool do_reboot = false;
bool do_reexec = false;
applet = basename_c(argv[0]); applet = basename_c(argv[0]);
while ((opt = getopt_long(argc, argv, getoptstring, while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1) longopts, (int *) 0)) != -1)
{ {
switch (opt) { switch (opt) {
case 'd': case 'd':
do_wtmp = false;
break;
case 'D':
do_dryrun = true; do_dryrun = true;
break; break;
case 'H': case 'H':
do_halt = true; do_halt = true;
cmd_count++; cmd_count++;
break; break;
case 'k': case 'K':
do_kexec = true; do_kexec = true;
cmd_count++; cmd_count++;
break; break;
@ -118,26 +132,31 @@ int main(int argc, char **argv)
do_reboot = true; do_reboot = true;
cmd_count++; cmd_count++;
break; break;
case 'w':
do_wtmp_only = true;
break;
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT
} }
} }
if (geteuid() != 0 && ! do_dryrun) if (geteuid() != 0 && ! do_dryrun)
eerrorx("%s: you must be root\n", applet); eerrorx("%s: you must be root\n", applet);
if (cmd_count > 1) { if (cmd_count > 1) {
eerror("%s: %s\n", applet, exclusive); eerror("%s: %s\n", applet, exclusive);
usage(EXIT_FAILURE); usage(EXIT_FAILURE);
} }
if (do_halt) if (do_halt)
send_cmd("halt", do_dryrun); send_cmd("halt");
else if (do_kexec) else if (do_kexec)
send_cmd("kexec", do_dryrun); send_cmd("kexec");
else if (do_poweroff) else if (do_poweroff)
send_cmd("poweroff", do_dryrun); send_cmd("poweroff");
else if (do_reboot) else if (do_reboot)
send_cmd("reboot", do_dryrun); send_cmd("reboot");
else if (do_reexec) else if (do_reexec)
send_cmd("reexec", do_dryrun); send_cmd("reexec");
else if (do_wtmp_only)
log_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");
else else
send_cmd("single", do_dryrun); send_cmd("single");
return 0; return 0;
} }

50
src/rc/rc-wtmp.c Normal file
View File

@ -0,0 +1,50 @@
/*
* rc-wtmp.c
* This file contains routines to deal with the wtmp file.
*/
/*
* Copyright 2017 The OpenRC Authors.
* See the Authors file at the top-level directory of this distribution and
* https://github.com/OpenRC/openrc/blob/master/AUTHORS
*
* This file is part of OpenRC. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
* This file may not be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file.
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include "rc-wtmp.h"
void log_wtmp(const char *user, const char *id, pid_t pid, int type,
const char *line)
{
struct timeval tv;
struct utmp utmp;
struct utsname uname_buf;
memset(&utmp, 0, sizeof(utmp));
gettimeofday(&tv, NULL);
utmp.ut_tv.tv_sec = tv.tv_sec;
utmp.ut_tv.tv_usec = tv.tv_usec;
utmp.ut_pid = pid;
utmp.ut_type = type;
strncpy(utmp.ut_name, user, sizeof(utmp.ut_name));
strncpy(utmp.ut_id , id , sizeof(utmp.ut_id ));
strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
/* Put the OS version in place of the hostname */
if (uname(&uname_buf) == 0)
strncpy(utmp.ut_host, uname_buf.release, sizeof(utmp.ut_host));
updwtmp(WTMP_FILE, &utmp);
}