File sysvinit-2.86-utmp.patch of Package sysvinit
--- 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
/*