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
 
 	/*
openSUSE Build Service is sponsored by