1 |
commit: 7689106aa10f7852b707b4c21ec080ccb2767280 |
2 |
Author: William Hubbs <w.d.hubbs <AT> gmail <DOT> com> |
3 |
AuthorDate: Fri Jun 2 19:07:40 2017 +0000 |
4 |
Commit: William Hubbs <williamh <AT> gentoo <DOT> org> |
5 |
CommitDate: Mon Jun 5 01:56:03 2017 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/openrc.git/commit/?id=7689106a |
7 |
|
8 |
add support for writing reboot and shutdown records to wtmp |
9 |
|
10 |
src/includes/rc-wtmp.h | 26 +++++++++++++++++++++ |
11 |
src/rc/Makefile | 6 ++--- |
12 |
src/rc/openrc-init.c | 2 ++ |
13 |
src/rc/openrc-shutdown.c | 61 +++++++++++++++++++++++++++++++----------------- |
14 |
src/rc/rc-wtmp.c | 50 +++++++++++++++++++++++++++++++++++++++ |
15 |
5 files changed, 121 insertions(+), 24 deletions(-) |
16 |
|
17 |
diff --git a/src/includes/rc-wtmp.h b/src/includes/rc-wtmp.h |
18 |
new file mode 100644 |
19 |
index 00000000..6645774b |
20 |
--- /dev/null |
21 |
+++ b/src/includes/rc-wtmp.h |
22 |
@@ -0,0 +1,26 @@ |
23 |
+/* |
24 |
+ * rc-wtmp.h |
25 |
+ * This is private to us and not for user consumption |
26 |
+*/ |
27 |
+ |
28 |
+/* |
29 |
+ * Copyright (c) 2017 The OpenRC Authors. |
30 |
+ * See the Authors file at the top-level directory of this distribution and |
31 |
+ * https://github.com/OpenRC/openrc/blob/master/AUTHORS |
32 |
+ * |
33 |
+ * This file is part of OpenRC. It is subject to the license terms in |
34 |
+ * the LICENSE file found in the top-level directory of this |
35 |
+ * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE |
36 |
+ * This file may not be copied, modified, propagated, or distributed |
37 |
+ * except according to the terms contained in the LICENSE file. |
38 |
+ */ |
39 |
+ |
40 |
+#ifndef __RC_WTMP_H__ |
41 |
+#define __RC_WTMP_H__ |
42 |
+ |
43 |
+#include <utmp.h> |
44 |
+ |
45 |
+void log_wtmp(const char *user, const char *id, pid_t pid, int type, |
46 |
+ const char *line); |
47 |
+ |
48 |
+#endif |
49 |
|
50 |
diff --git a/src/rc/Makefile b/src/rc/Makefile |
51 |
index 5874ed17..19adcafb 100644 |
52 |
--- a/src/rc/Makefile |
53 |
+++ b/src/rc/Makefile |
54 |
@@ -14,7 +14,7 @@ SRCS+= rc-selinux.c |
55 |
endif |
56 |
|
57 |
ifeq (${OS},Linux) |
58 |
-SRCS+= kill_all.c openrc-init.c openrc-shutdown.c |
59 |
+SRCS+= kill_all.c openrc-init.c openrc-shutdown.c rc-wtmp.c |
60 |
endif |
61 |
|
62 |
CLEANFILES= version.h rc-selinux.o |
63 |
@@ -111,7 +111,7 @@ veinfo vewarn vebegin veend vewend veindent veoutdent: do_e.o rc-misc.o |
64 |
fstabinfo: fstabinfo.o _usage.o rc-misc.o |
65 |
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} |
66 |
|
67 |
-openrc-init: openrc-init.o |
68 |
+openrc-init: openrc-init.o rc-wtmp.o |
69 |
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} |
70 |
|
71 |
is_newer_than: is_newer_than.o rc-misc.o |
72 |
@@ -132,7 +132,7 @@ mountinfo: mountinfo.o _usage.o rc-misc.o |
73 |
openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o _usage.o |
74 |
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} |
75 |
|
76 |
-openrc-shutdown: openrc-shutdown.o _usage.o |
77 |
+openrc-shutdown: openrc-shutdown.o _usage.o rc-wtmp.o |
78 |
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD} |
79 |
|
80 |
openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o |
81 |
|
82 |
diff --git a/src/rc/openrc-init.c b/src/rc/openrc-init.c |
83 |
index 003ce31f..eb346f59 100644 |
84 |
--- a/src/rc/openrc-init.c |
85 |
+++ b/src/rc/openrc-init.c |
86 |
@@ -32,6 +32,7 @@ |
87 |
|
88 |
#include "helpers.h" |
89 |
#include "rc.h" |
90 |
+#include "rc-wtmp.h" |
91 |
#include "version.h" |
92 |
|
93 |
static const char *rc_default_runlevel = "default"; |
94 |
@@ -82,6 +83,7 @@ static void init(const char *default_runlevel) |
95 |
} |
96 |
pid = do_openrc(runlevel); |
97 |
waitpid(pid, NULL, 0); |
98 |
+ log_wtmp("reboot", "~~", 0, RUN_LVL, "~~"); |
99 |
} |
100 |
|
101 |
static void handle_reexec(char *my_name) |
102 |
|
103 |
diff --git a/src/rc/openrc-shutdown.c b/src/rc/openrc-shutdown.c |
104 |
index ecb251a8..4ba619c5 100644 |
105 |
--- a/src/rc/openrc-shutdown.c |
106 |
+++ b/src/rc/openrc-shutdown.c |
107 |
@@ -27,46 +27,63 @@ |
108 |
#include <string.h> |
109 |
#include <unistd.h> |
110 |
#include <sys/types.h> |
111 |
+#include <sys/utsname.h> |
112 |
|
113 |
#include "einfo.h" |
114 |
#include "rc.h" |
115 |
#include "helpers.h" |
116 |
#include "_usage.h" |
117 |
+#include "rc-wtmp.h" |
118 |
|
119 |
const char *applet = NULL; |
120 |
const char *extraopts = NULL; |
121 |
-const char *getoptstring = "dHkpRr" getoptstring_COMMON; |
122 |
+const char *getoptstring = "dDHKpRrw" getoptstring_COMMON; |
123 |
const struct option longopts[] = { |
124 |
- { "dry-run", no_argument, NULL, 'd'}, |
125 |
+ { "no-write", no_argument, NULL, 'd'}, |
126 |
+ { "dry-run", no_argument, NULL, 'D'}, |
127 |
{ "halt", no_argument, NULL, 'H'}, |
128 |
- { "kexec", no_argument, NULL, 'k'}, |
129 |
+ { "kexec", no_argument, NULL, 'K'}, |
130 |
{ "poweroff", no_argument, NULL, 'p'}, |
131 |
{ "reexec", no_argument, NULL, 'R'}, |
132 |
{ "reboot", no_argument, NULL, 'r'}, |
133 |
+ { "write-only", no_argument, NULL, 'w'}, |
134 |
longopts_COMMON |
135 |
}; |
136 |
const char * const longopts_help[] = { |
137 |
+ "do not write wtmp record", |
138 |
"print actions instead of executing them", |
139 |
"halt the system", |
140 |
"reboot the system using kexec", |
141 |
"power off the system", |
142 |
"re-execute init (use after upgrading)", |
143 |
"reboot the system", |
144 |
+ "write wtmp boot record and exit", |
145 |
longopts_help_COMMON |
146 |
}; |
147 |
const char *usagestring = NULL; |
148 |
const char *exclusive = "Select one of " |
149 |
"--halt, --kexec, --poweroff, --reexec or --reboot"; |
150 |
|
151 |
-static void send_cmd(const char *cmd, bool dryrun) |
152 |
+static bool do_dryrun = false; |
153 |
+static bool do_halt = false; |
154 |
+static bool do_kexec = false; |
155 |
+static bool do_poweroff = false; |
156 |
+static bool do_reboot = false; |
157 |
+static bool do_reexec = false; |
158 |
+static bool do_wtmp = true; |
159 |
+static bool do_wtmp_only = false; |
160 |
+ |
161 |
+static void send_cmd(const char *cmd) |
162 |
{ |
163 |
FILE *fifo; |
164 |
size_t ignored; |
165 |
|
166 |
- if (dryrun) { |
167 |
+ if (do_dryrun) { |
168 |
einfo("Would send %s to init", cmd); |
169 |
return; |
170 |
} |
171 |
+ if (do_wtmp && (do_halt || do_kexec || do_reboot || do_poweroff)) |
172 |
+ log_wtmp("shutdown", "~~", 0, RUN_LVL, "~~"); |
173 |
fifo = fopen(RC_INIT_FIFO, "w"); |
174 |
if (!fifo) { |
175 |
perror("fopen"); |
176 |
@@ -83,26 +100,23 @@ int main(int argc, char **argv) |
177 |
{ |
178 |
int opt; |
179 |
int cmd_count = 0; |
180 |
- bool do_dryrun = false; |
181 |
- bool do_halt = false; |
182 |
- bool do_kexec = false; |
183 |
- bool do_poweroff = false; |
184 |
- bool do_reboot = false; |
185 |
- bool do_reexec = false; |
186 |
|
187 |
applet = basename_c(argv[0]); |
188 |
while ((opt = getopt_long(argc, argv, getoptstring, |
189 |
longopts, (int *) 0)) != -1) |
190 |
{ |
191 |
switch (opt) { |
192 |
- case 'd': |
193 |
+ case 'd': |
194 |
+ do_wtmp = false; |
195 |
+ break; |
196 |
+ case 'D': |
197 |
do_dryrun = true; |
198 |
break; |
199 |
case 'H': |
200 |
do_halt = true; |
201 |
cmd_count++; |
202 |
break; |
203 |
- case 'k': |
204 |
+ case 'K': |
205 |
do_kexec = true; |
206 |
cmd_count++; |
207 |
break; |
208 |
@@ -118,26 +132,31 @@ int main(int argc, char **argv) |
209 |
do_reboot = true; |
210 |
cmd_count++; |
211 |
break; |
212 |
+ case 'w': |
213 |
+ do_wtmp_only = true; |
214 |
+ break; |
215 |
case_RC_COMMON_GETOPT |
216 |
} |
217 |
} |
218 |
-if (geteuid() != 0 && ! do_dryrun) |
219 |
- eerrorx("%s: you must be root\n", applet); |
220 |
+ if (geteuid() != 0 && ! do_dryrun) |
221 |
+ eerrorx("%s: you must be root\n", applet); |
222 |
if (cmd_count > 1) { |
223 |
eerror("%s: %s\n", applet, exclusive); |
224 |
usage(EXIT_FAILURE); |
225 |
} |
226 |
if (do_halt) |
227 |
- send_cmd("halt", do_dryrun); |
228 |
+ send_cmd("halt"); |
229 |
else if (do_kexec) |
230 |
- send_cmd("kexec", do_dryrun); |
231 |
+ send_cmd("kexec"); |
232 |
else if (do_poweroff) |
233 |
- send_cmd("poweroff", do_dryrun); |
234 |
+ send_cmd("poweroff"); |
235 |
else if (do_reboot) |
236 |
- send_cmd("reboot", do_dryrun); |
237 |
+ send_cmd("reboot"); |
238 |
else if (do_reexec) |
239 |
- send_cmd("reexec", do_dryrun); |
240 |
+ send_cmd("reexec"); |
241 |
+ else if (do_wtmp_only) |
242 |
+ log_wtmp("shutdown", "~~", 0, RUN_LVL, "~~"); |
243 |
else |
244 |
- send_cmd("single", do_dryrun); |
245 |
+ send_cmd("single"); |
246 |
return 0; |
247 |
} |
248 |
|
249 |
diff --git a/src/rc/rc-wtmp.c b/src/rc/rc-wtmp.c |
250 |
new file mode 100644 |
251 |
index 00000000..913fa06b |
252 |
--- /dev/null |
253 |
+++ b/src/rc/rc-wtmp.c |
254 |
@@ -0,0 +1,50 @@ |
255 |
+/* |
256 |
+ * rc-wtmp.c |
257 |
+ * This file contains routines to deal with the wtmp file. |
258 |
+ */ |
259 |
+ |
260 |
+/* |
261 |
+ * Copyright 2017 The OpenRC Authors. |
262 |
+ * See the Authors file at the top-level directory of this distribution and |
263 |
+ * https://github.com/OpenRC/openrc/blob/master/AUTHORS |
264 |
+ * |
265 |
+ * This file is part of OpenRC. It is subject to the license terms in |
266 |
+ * the LICENSE file found in the top-level directory of this |
267 |
+ * distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE |
268 |
+ * This file may not be copied, modified, propagated, or distributed |
269 |
+ * except according to the terms contained in the LICENSE file. |
270 |
+ */ |
271 |
+ |
272 |
+#include <stdbool.h> |
273 |
+#include <stdio.h> |
274 |
+#include <stdlib.h> |
275 |
+#include <string.h> |
276 |
+#include <unistd.h> |
277 |
+#include <sys/types.h> |
278 |
+#include <sys/utsname.h> |
279 |
+ |
280 |
+#include "rc-wtmp.h" |
281 |
+ |
282 |
+void log_wtmp(const char *user, const char *id, pid_t pid, int type, |
283 |
+ const char *line) |
284 |
+{ |
285 |
+ struct timeval tv; |
286 |
+ struct utmp utmp; |
287 |
+ struct utsname uname_buf; |
288 |
+ |
289 |
+ memset(&utmp, 0, sizeof(utmp)); |
290 |
+ gettimeofday(&tv, NULL); |
291 |
+ utmp.ut_tv.tv_sec = tv.tv_sec; |
292 |
+ utmp.ut_tv.tv_usec = tv.tv_usec; |
293 |
+ utmp.ut_pid = pid; |
294 |
+ utmp.ut_type = type; |
295 |
+ strncpy(utmp.ut_name, user, sizeof(utmp.ut_name)); |
296 |
+ strncpy(utmp.ut_id , id , sizeof(utmp.ut_id )); |
297 |
+ strncpy(utmp.ut_line, line, sizeof(utmp.ut_line)); |
298 |
+ |
299 |
+ /* Put the OS version in place of the hostname */ |
300 |
+ if (uname(&uname_buf) == 0) |
301 |
+ strncpy(utmp.ut_host, uname_buf.release, sizeof(utmp.ut_host)); |
302 |
+ |
303 |
+ updwtmp(WTMP_FILE, &utmp); |
304 |
+} |