The init process now writes the current runlevel to /var/run/runlevel.

This information can be read by the "runlevel" command as well as "halt"
and "reboot". Having the information logged in /var/run/runlevel as
well as the utmp file means systems without utmp (like those running
the musl C library) can still check the current runlevel. This is
useful when running halt/reboot as these programs want to check the
runlevel.

Updated the changelog, and manual pages for halt and runlevel.
This commit is contained in:
Jesse Smith 2018-07-07 20:19:03 -03:00
parent 6b26692584
commit 6e8323e9fb
8 changed files with 37 additions and 14 deletions

View File

@ -9,7 +9,13 @@ sysvinit (2.91) UNRELEASED; urgency=low
Updated manual page for init.8 to match. Updated manual page for init.8 to match.
* Version information is now fetched and defined by the Makefile. * Version information is now fetched and defined by the Makefile.
No more need to update the version manually in the init.c source. No more need to update the version manually in the init.c source.
* The init process now writes the current runlevel to /var/run/runlevel.
This information can be read by the "runlevel" command as well as "halt"
and "reboot". Having the information logged in /var/run/runlevel as
well as the utmp file means systems without utmp (like those running
the musl C library) can still check the current runlevel. This is
useful when running halt/reboot as these programs want to check the
runlevel.
sysvinit (2.90) world; urgency=low sysvinit (2.90) world; urgency=low

View File

@ -95,7 +95,8 @@ never be called directly. From release 2.74 on \fBhalt\fP and \fBreboot\fP
invoke \fBshutdown\fP(8) if the system is not in runlevel 0 or 6. This invoke \fBshutdown\fP(8) if the system is not in runlevel 0 or 6. This
means that if \fBhalt\fP or \fBreboot\fP cannot find out the current means that if \fBhalt\fP or \fBreboot\fP cannot find out the current
runlevel (for example, when \fI/var/run/utmp\fP hasn't been initialized runlevel (for example, when \fI/var/run/utmp\fP hasn't been initialized
correctly) \fBshutdown\fP will be called, which might not be what you want. correctly and /var/run/runlevel does not exist) \fBshutdown\fP will be called,
which might not be what you want.
Use the \fB-f\fP flag if you want to do a hard \fBhalt\fP or \fBreboot\fP. Use the \fB-f\fP flag if you want to do a hard \fBhalt\fP or \fBreboot\fP.
.PP .PP
The \fB-h\fP flag puts all hard disks in standby mode just before halt The \fB-h\fP flag puts all hard disks in standby mode just before halt

View File

@ -34,7 +34,9 @@ runlevel, the letter \fBN\fP will be printed instead.
.PP .PP
If no If no
.I utmp .I utmp
file exists, or if no runlevel record can be found, file exists, and if no runlevel record can be found in the
.I /var/run/runlevel
file,
.B runlevel .B runlevel
prints the word \fBunknown\fP and exits with an error. prints the word \fBunknown\fP and exits with an error.
.PP .PP

View File

@ -107,10 +107,10 @@ all: $(BIN) $(SBIN) $(USRBIN)
# $(CC) $(CFLAGS) $(CPPFLAGS) -c $^ -o $@ # $(CC) $(CFLAGS) $(CPPFLAGS) -c $^ -o $@
init: LDLIBS += $(INITLIBS) $(STATIC) init: LDLIBS += $(INITLIBS) $(STATIC)
init: init.o init_utmp.o init: init.o init_utmp.o runlevellog.o
halt: LDLIBS += $(STATIC) halt: LDLIBS += $(STATIC)
halt: halt.o ifdown.o hddown.o utmp.o halt: halt.o ifdown.o hddown.o utmp.o runlevellog.o
last: LDLIBS += $(STATIC) last: LDLIBS += $(STATIC)
last: last.o last: last.o
@ -148,7 +148,7 @@ sulogin.o: sulogin.c
runlevellog.o: runlevellog.h runlevellog.c paths.h runlevellog.o: runlevellog.h runlevellog.c paths.h
init.o: CPPFLAGS += $(SELINUX_DEF) init.o: CPPFLAGS += $(SELINUX_DEF)
init.o: init.c init.h initreq.h paths.h reboot.h set.h init.o: init.c init.h initreq.h paths.h reboot.h runlevellog.h runlevellog.c set.h paths.h
utmp.o: utmp.o:
@ -160,7 +160,7 @@ utmpdump.o: utmpdump.c oldutmp.h
shutdown.o: shutdown.c paths.h reboot.h initreq.h init.h shutdown.o: shutdown.c paths.h reboot.h initreq.h init.h
halt.o: halt.c reboot.h halt.o: halt.c reboot.h paths.h runlevellog.c runlevellog.h
last.o: last.c oldutmp.h last.o: last.c oldutmp.h

View File

@ -57,6 +57,7 @@
#include <stdio.h> #include <stdio.h>
#include <getopt.h> #include <getopt.h>
#include "reboot.h" #include "reboot.h"
#include "runlevellog.h"
char *Version = "@(#)halt 2.86 31-Jul-2004 miquels@cistron.nl"; char *Version = "@(#)halt 2.86 31-Jul-2004 miquels@cistron.nl";
char *progname; char *progname;
@ -90,11 +91,14 @@ void usage(void)
/* /*
* See if we were started directly from init. * See if we were started directly from init.
* Get the runlevel from /var/run/utmp or the environment. * Get the runlevel from /var/run/utmp or the environment.
* Or the /var/run/runlevel log.
*/ */
int get_runlevel(void) int get_runlevel(void)
{ {
struct utmp *ut; struct utmp *ut;
char *r; char *r;
int runlevel, status;
#if RUNLVL_PICKY #if RUNLVL_PICKY
time_t boottime; time_t boottime;
#endif #endif
@ -134,6 +138,11 @@ int get_runlevel(void)
} }
endutent(); endutent();
/* Did not find utmp entry, try to read from log file */
status = Read_Runlevel_Log(&runlevel);
if (status)
return runlevel;
/* This should not happen but warn the user! */ /* This should not happen but warn the user! */
fprintf(stderr, "WARNING: could not determine runlevel" fprintf(stderr, "WARNING: could not determine runlevel"
" - doing soft %s\n", progname); " - doing soft %s\n", progname);

View File

@ -80,6 +80,7 @@ Version information is not placed in the top-level Makefile by default
#include "initreq.h" #include "initreq.h"
#include "paths.h" #include "paths.h"
#include "reboot.h" #include "reboot.h"
#include "runlevellog.h"
#include "set.h" #include "set.h"
#ifndef SIGPWR #ifndef SIGPWR
@ -1905,6 +1906,7 @@ int get_init_default(void)
/* /*
* Log the fact that we have a runlevel now. * Log the fact that we have a runlevel now.
*/ */
Write_Runlevel_Log(lvl);
return lvl; return lvl;
} }
@ -2020,6 +2022,7 @@ int read_level(int arg)
write_utmp_wtmp("runlevel", "~~", foo + 256*runlevel, RUN_LVL, "~"); write_utmp_wtmp("runlevel", "~~", foo + 256*runlevel, RUN_LVL, "~");
thislevel = foo; thislevel = foo;
prevlevel = runlevel; prevlevel = runlevel;
Write_Runlevel_Log(runlevel);
return foo; return foo;
} }
@ -2284,6 +2287,7 @@ void fifo_new_level(int level)
setproctitle("init [%c]", (int)runlevel); setproctitle("init [%c]", (int)runlevel);
} }
} }
Write_Runlevel_Log(runlevel);
} }
@ -2572,6 +2576,7 @@ void boot_transitions()
prevlevel = oldlevel; prevlevel = oldlevel;
setproctitle("init [%c]", (int)runlevel); setproctitle("init [%c]", (int)runlevel);
} }
Write_Runlevel_Log(runlevel);
} }
} }
@ -2683,6 +2688,7 @@ void process_signals()
setproctitle("init [%c]", (int)runlevel); setproctitle("init [%c]", (int)runlevel);
DELSET(got_signals, SIGHUP); DELSET(got_signals, SIGHUP);
} }
Write_Runlevel_Log(runlevel);
} }
} }
if (ISMEMBER(got_signals, SIGUSR1)) { if (ISMEMBER(got_signals, SIGUSR1)) {

View File

@ -52,10 +52,10 @@ char **argv;
status = Read_Runlevel_Log(&runlevel); status = Read_Runlevel_Log(&runlevel);
if (status) if (status)
{ {
printf("%c\n", runlevel); printf("N %c\n", runlevel);
return 0; return 0;
} }
printf("Unknown.\n"); printf("unknown\n");
return(1); return(1);
} }

View File

@ -42,7 +42,7 @@ int Write_Runlevel_Log(int new_runlevel)
if (status < 1) if (status < 1)
return FALSE; return FALSE;
return TRUE; return TRUE;
} // end of writing to log function }
/* /*
@ -60,12 +60,11 @@ int Read_Runlevel_Log(int *runlevel)
if (! log_file) if (! log_file)
return FALSE; return FALSE;
status = fscanf(log_file, "%c", runlevel); status = fscanf(log_file, "%c", (char *) runlevel);
fclose(log_file); fclose(log_file);
if (status == EOF) if (status < 1)
return FALSE; return FALSE;
return TRUE; return TRUE;
} // end of reading from log function }