204 lines
6.3 KiB
Diff
204 lines
6.3 KiB
Diff
|
--- src/init.c
|
||
|
+++ src/init.c 2006-08-22 15:04:27.000000000 +0200
|
||
|
@@ -115,6 +115,8 @@ sig_atomic_t got_signals; /* Set if we r
|
||
|
int emerg_shell = 0; /* Start emergency shell? */
|
||
|
int wrote_wtmp_reboot = 1; /* Set when we wrote the reboot record */
|
||
|
int wrote_utmp_reboot = 1; /* Set when we wrote the reboot record */
|
||
|
+int wrote_wtmp_rlevel = 1; /* Set when we wrote the runlevel record */
|
||
|
+int wrote_utmp_rlevel = 1; /* Set when we wrote the runlevel record */
|
||
|
int sltime = 5; /* Sleep time between TERM and KILL */
|
||
|
char *argv0; /* First arguments; show up in ps listing */
|
||
|
int maxproclen; /* Maximal length of argv[0] with \0 */
|
||
|
@@ -184,6 +186,8 @@ struct {
|
||
|
{ "-WU", D_WROTE_UTMP_REBOOT},
|
||
|
{ "-ST", D_SLTIME },
|
||
|
{ "-DB", D_DIDBOOT },
|
||
|
+ { "-LW", D_WROTE_WTMP_RLEVEL},
|
||
|
+ { "-LU", D_WROTE_UTMP_RLEVEL},
|
||
|
{ "", 0 }
|
||
|
};
|
||
|
struct {
|
||
|
@@ -379,6 +383,12 @@ static CHILD *get_record(FILE *f)
|
||
|
case D_DIDBOOT:
|
||
|
fscanf(f, "%d\n", &did_boot);
|
||
|
break;
|
||
|
+ case D_WROTE_WTMP_RLEVEL:
|
||
|
+ fscanf(f, "%d\n", &wrote_wtmp_rlevel);
|
||
|
+ break;
|
||
|
+ case D_WROTE_UTMP_RLEVEL:
|
||
|
+ fscanf(f, "%d\n", &wrote_utmp_rlevel);
|
||
|
+ break;
|
||
|
default:
|
||
|
if (cmd > 0 || cmd == C_EOF) {
|
||
|
oops_error = -1;
|
||
|
@@ -1705,6 +1715,8 @@ int read_level(int arg)
|
||
|
}
|
||
|
|
||
|
/* Store both the old and the new runlevel. */
|
||
|
+ wrote_utmp_rlevel = 0;
|
||
|
+ wrote_wtmp_rlevel = 0;
|
||
|
write_utmp_wtmp("runlevel", "~~", foo + 256*runlevel, RUN_LVL, "~");
|
||
|
thislevel = foo;
|
||
|
prevlevel = runlevel;
|
||
|
@@ -1905,6 +1917,25 @@ void re_exec(void)
|
||
|
initlog(L_CO, "Attempt to re-exec failed");
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * Redo utmp/wtmp entries if required or requested
|
||
|
+ * Check for written records and size of utmp
|
||
|
+ */
|
||
|
+static
|
||
|
+void redo_utmp_wtmp(void)
|
||
|
+{
|
||
|
+ struct stat ustat;
|
||
|
+ const int ret = stat(UTMP_FILE, &ustat);
|
||
|
+
|
||
|
+ if ((ret < 0) || (ustat.st_size == 0))
|
||
|
+ wrote_utmp_rlevel = wrote_utmp_reboot = 0;
|
||
|
+
|
||
|
+ if ((wrote_wtmp_reboot == 0) || (wrote_utmp_reboot == 0))
|
||
|
+ write_utmp_wtmp("reboot", "~~", 0, BOOT_TIME, "~");
|
||
|
+
|
||
|
+ if ((wrote_wtmp_rlevel == 0) || (wrote_wtmp_rlevel == 0))
|
||
|
+ write_utmp_wtmp("runlevel", "~~", thislevel + 256 * prevlevel, RUN_LVL, "~");
|
||
|
+}
|
||
|
|
||
|
/*
|
||
|
* We got a change runlevel request through the
|
||
|
@@ -1936,6 +1967,7 @@ void fifo_new_level(int level)
|
||
|
if (oldlevel != 'S' && runlevel == 'S') console_stty();
|
||
|
if (runlevel == '6' || runlevel == '0' ||
|
||
|
runlevel == '1') console_stty();
|
||
|
+ if (runlevel > '1' && runlevel < '6') redo_utmp_wtmp();
|
||
|
read_inittab();
|
||
|
fail_cancel();
|
||
|
setproctitle("init [%c]", runlevel);
|
||
|
@@ -2231,6 +2263,8 @@ void boot_transitions()
|
||
|
}
|
||
|
if (loglevel > 0) {
|
||
|
initlog(L_VB, "Entering runlevel: %c", runlevel);
|
||
|
+ wrote_utmp_rlevel = 0;
|
||
|
+ wrote_wtmp_rlevel = 0;
|
||
|
write_utmp_wtmp("runlevel", "~~", runlevel + 256 * oldlevel, RUN_LVL, "~");
|
||
|
thislevel = runlevel;
|
||
|
prevlevel = oldlevel;
|
||
|
@@ -2409,6 +2443,7 @@ int init_main()
|
||
|
console_init();
|
||
|
|
||
|
if (!reload) {
|
||
|
+ int fd;
|
||
|
|
||
|
/* Close whatever files are open, and reset the console. */
|
||
|
close(0);
|
||
|
@@ -2426,7 +2461,8 @@ int init_main()
|
||
|
* Initialize /var/run/utmp (only works if /var is on
|
||
|
* root and mounted rw)
|
||
|
*/
|
||
|
- (void) close(open(UTMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0644));
|
||
|
+ if ((fd = open(UTMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0644)) >= 0)
|
||
|
+ close(fd);
|
||
|
|
||
|
/*
|
||
|
* Say hello to the world
|
||
|
--- src/init.h
|
||
|
+++ src/init.h 2006-08-22 14:29:39.000000000 +0200
|
||
|
@@ -99,6 +99,10 @@ typedef struct _child_ {
|
||
|
extern CHILD *family;
|
||
|
extern int wrote_wtmp_reboot;
|
||
|
extern int wrote_utmp_reboot;
|
||
|
+extern int wrote_wtmp_rlevel;
|
||
|
+extern int wrote_utmp_rlevel;
|
||
|
+extern char thislevel;
|
||
|
+extern char prevlevel;
|
||
|
|
||
|
/* Tokens in state parser */
|
||
|
#define C_VER 1
|
||
|
@@ -120,4 +124,6 @@ extern int wrote_utmp_reboot;
|
||
|
#define D_WROTE_UTMP_REBOOT -7
|
||
|
#define D_SLTIME -8
|
||
|
#define D_DIDBOOT -9
|
||
|
+#define D_WROTE_WTMP_RLEVEL -16
|
||
|
+#define D_WROTE_UTMP_RLEVEL -17
|
||
|
|
||
|
--- src/utmp.c
|
||
|
+++ src/utmp.c 2006-08-22 14:28:52.000000000 +0200
|
||
|
@@ -49,6 +49,12 @@ char *line) /* Which line is this */
|
||
|
struct utsname uname_buf;
|
||
|
|
||
|
/*
|
||
|
+ * Can't do much if WTMP_FILE is not present or not writable.
|
||
|
+ */
|
||
|
+ if (access(WTMP_FILE, W_OK) < 0)
|
||
|
+ return;
|
||
|
+
|
||
|
+ /*
|
||
|
* Try to open the wtmp file. Note that we even try
|
||
|
* this if we have updwtmp() so we can see if the
|
||
|
* wtmp file is accessible.
|
||
|
@@ -69,6 +75,23 @@ char *line) /* Which line is this */
|
||
|
*/
|
||
|
if (wrote_wtmp_reboot == 0 && type != BOOT_TIME)
|
||
|
write_wtmp("reboot", "~~", 0, BOOT_TIME, "~");
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Note if we are going to write a runlevel record.
|
||
|
+ */
|
||
|
+ if (type == RUN_LVL) wrote_wtmp_rlevel++;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * See if we need to write a runlevel record. The reason that
|
||
|
+ * we are being so paranoid is that when we first tried to
|
||
|
+ * write the reboot record, /var was possibly not mounted
|
||
|
+ * yet. As soon as we can open WTMP we write a delayed runlevel record.
|
||
|
+ */
|
||
|
+ if (wrote_wtmp_rlevel == 0 && type != RUN_LVL) {
|
||
|
+ int runlevel = thislevel;
|
||
|
+ int oldlevel = prevlevel;
|
||
|
+ write_wtmp("runlevel", "~~", runlevel + 256 * oldlevel, RUN_LVL, "~");
|
||
|
+ }
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
@@ -115,9 +138,9 @@ char *oldline) /* Line of old utmp ent
|
||
|
struct utmp *utmptr;
|
||
|
|
||
|
/*
|
||
|
- * Can't do much if UTMP_FILE is not present.
|
||
|
+ * Can't do much if UTMP_FILE is not present or not writable.
|
||
|
*/
|
||
|
- if (access(UTMP_FILE, F_OK) < 0)
|
||
|
+ if (access(UTMP_FILE, W_OK) < 0)
|
||
|
return;
|
||
|
|
||
|
#ifdef INIT_MAIN
|
||
|
@@ -130,10 +153,27 @@ char *oldline) /* Line of old utmp ent
|
||
|
* See if we need to write a reboot record. The reason that
|
||
|
* we are being so paranoid is that when we first tried to
|
||
|
* write the reboot record, /var was possibly not mounted
|
||
|
- * yet. As soon as we can open WTMP we write a delayed boot record.
|
||
|
+ * yet. As soon as we can open UTMP we write a delayed boot record.
|
||
|
*/
|
||
|
if (wrote_utmp_reboot == 0 && type != BOOT_TIME)
|
||
|
write_utmp("reboot", "~~", 0, BOOT_TIME, "~", NULL);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Note if we are going to write a runlevel record.
|
||
|
+ */
|
||
|
+ if (type == RUN_LVL) wrote_utmp_rlevel++;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * See if we need to write a runlevel record. The reason that
|
||
|
+ * we are being so paranoid is that when we first tried to
|
||
|
+ * write the reboot record, /var was possibly not mounted
|
||
|
+ * yet. As soon as we can open UTMP we write a delayed runlevel record.
|
||
|
+ */
|
||
|
+ if (wrote_utmp_rlevel == 0 && type != RUN_LVL) {
|
||
|
+ int runlevel = thislevel;
|
||
|
+ int oldlevel = prevlevel;
|
||
|
+ write_utmp("runlevel", "~~", runlevel + 256 * oldlevel, RUN_LVL, "~", NULL);
|
||
|
+ }
|
||
|
#endif
|
||
|
|
||
|
/*
|