diff options
author | Marcin Juszkiewicz <hrw@openembedded.org> | 2006-04-28 18:42:33 +0000 |
---|---|---|
committer | OpenEmbedded Project <openembedded-devel@lists.openembedded.org> | 2006-04-28 18:42:33 +0000 |
commit | d775757b77aba05c2766546682db2915b5cc12e1 (patch) | |
tree | 44faa5aa666ca625f97ed7d5e35efc760c7c83b8 /packages/sysvinit/sysvinit-2.86 | |
parent | 6cf5f8aac13ae6c3850e1a4b71b657ffa000d76c (diff) |
sysvinit: use upstream 2.86 release instead of patching 2.85 locally
Diffstat (limited to 'packages/sysvinit/sysvinit-2.86')
-rw-r--r-- | packages/sysvinit/sysvinit-2.86/sysvinit-2.86.patch | 4880 |
1 files changed, 0 insertions, 4880 deletions
diff --git a/packages/sysvinit/sysvinit-2.86/sysvinit-2.86.patch b/packages/sysvinit/sysvinit-2.86/sysvinit-2.86.patch deleted file mode 100644 index b83f525c3e..0000000000 --- a/packages/sysvinit/sysvinit-2.86/sysvinit-2.86.patch +++ /dev/null @@ -1,4880 +0,0 @@ -diff -urNd -urNd sysvinit-2.85/COPYRIGHT sysvinit-2.86/COPYRIGHT ---- sysvinit-2.85/COPYRIGHT 2003-04-15 03:45:44.000000000 -0500 -+++ sysvinit-2.86/COPYRIGHT 2004-07-30 07:12:12.000000000 -0500 -@@ -1,4 +1,4 @@ --Sysvinit is Copyright (C) 1991-2003 Miquel van Smoorenburg -+Sysvinit is Copyright (C) 1991-2004 Miquel van Smoorenburg - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by -diff -urNd -urNd sysvinit-2.85/doc/Changelog sysvinit-2.86/doc/Changelog ---- sysvinit-2.85/doc/Changelog 2003-04-15 09:37:58.000000000 -0500 -+++ sysvinit-2.86/doc/Changelog 2004-07-30 07:15:06.000000000 -0500 -@@ -1,3 +1,29 @@ -+sysvinit (2.86) cistron; urgency=low -+ -+ * Fixed up bootlogd to read /proc/cmdline. Also keep an internal -+ linebuffer to process \r, \t and ^H. It is becoming useable. -+ * Applied trivial OWL patches -+ * Block signals in syslog(), since syslog() is not re-entrant -+ (James Olin Oden <joden@malachi.lee.k12.nc.us>, redhat bug #97534) -+ * Minor adjustements so that sysvinit compiles on the Hurd -+ * killall5 now skips kernel threads -+ * Inittab entries with both 'S' and other runlevels were broken. -+ Fix by Bryan Kadzban <bryan@kadzban.is-a-geek.net> -+ * Changed initreq.h to be more flexible and forwards-compatible. -+ * You can now through /dev/initctl set environment variables in -+ init that will be inherited by its children. For now, only -+ variables prefixed with INIT_ can be set and the maximum is -+ 16 variables. There's also a length limit due to the size -+ of struct init_request, so it should be safe from abuse. -+ * Option -P and -H to shutdown set INIT_HALT=POWERDOWN and -+ INIT_HALT=HALT as environment variables as described above -+ * Add "mountpoint" utility. -+ * Slightly better algorithm in killall5.c:pidof() -+ * Added some patches from fedora-core (halt-usage, last -t, -+ sulogin-message, user-console) -+ -+ -- Miquel van Smoorenburg <miquels@cistron.nl> Fri, 30 Jul 2004 14:14:58 +0200 -+ - sysvinit (2.85) cistron; urgency=low - - * Add IPv6 support in last(1) -diff -urNd -urNd sysvinit-2.85/doc/Install sysvinit-2.86/doc/Install ---- sysvinit-2.85/doc/Install 2003-04-15 03:46:49.000000000 -0500 -+++ sysvinit-2.86/doc/Install 2004-07-30 07:15:40.000000000 -0500 -@@ -1,5 +1,5 @@ - -- README for the System V style init, version 2.85 -+ README for the System V style init, version 2.86 - - init, shutdown, halt, reboot, wall, last, mesg, runlevel, - killall5, pidof, sulogin. -diff -urNd -urNd sysvinit-2.85/doc/bootlogd.README sysvinit-2.86/doc/bootlogd.README ---- sysvinit-2.85/doc/bootlogd.README 2000-09-12 16:54:31.000000000 -0500 -+++ sysvinit-2.86/doc/bootlogd.README 2004-06-09 07:47:45.000000000 -0500 -@@ -1,10 +1,12 @@ - - bootlogd: a way to capture all console output during bootup -- in a logfile. ** PROOF OF CONCEPT IMPLEMENTATION ** -+ in a logfile. - --- bootlogd opens /dev/console --- finds out what the real console is with an ioctl() --- then opens the real console -+- bootlogd opens /dev/console and finds out what the real console is -+ with an ioctl() if TIOCCONS is available -+- otherwise bootlogd tries to parse /proc/cmdline for console= -+ kernel command line arguments -+- then opens the (most probable) real console - - allocates a pty pair - - redirects console I/O to the pty pair - - then goes in a loop reading from the pty, writing to the real -diff -urNd -urNd sysvinit-2.85/doc/sysvinit-2.85.lsm sysvinit-2.86/doc/sysvinit-2.85.lsm ---- sysvinit-2.85/doc/sysvinit-2.85.lsm 2003-04-18 16:04:12.000000000 -0500 -+++ sysvinit-2.86/doc/sysvinit-2.85.lsm 2004-06-09 07:47:45.000000000 -0500 -@@ -1,7 +1,7 @@ - Begin3 - Title: sysvinit and utilities - Version: 2.85 --Entered-Date: 18APR2003 -+Entered-Date: 15APR2003 - Description: This is the Linux System V init. - This version can be compiled with glibc 2.0.6 and up. - Author: miquels@cistron.nl (Miquel van Smoorenburg) -diff -urNd -urNd sysvinit-2.85/doc/sysvinit-2.86.lsm sysvinit-2.86/doc/sysvinit-2.86.lsm ---- sysvinit-2.85/doc/sysvinit-2.86.lsm 1969-12-31 18:00:00.000000000 -0600 -+++ sysvinit-2.86/doc/sysvinit-2.86.lsm 2004-07-31 08:35:28.000000000 -0500 -@@ -0,0 +1,14 @@ -+Begin3 -+Title: sysvinit and utilities -+Version: 2.86 -+Entered-Date: 30JUL2004 -+Description: This is the Linux System V init. -+ This version can be compiled with glibc 2.0.6 and up. -+Author: miquels@cistron.nl (Miquel van Smoorenburg) -+Primary-Site: ftp.cistron.nl /pub/people/miquels/software -+ 92K sysvinit-2.86.tar.gz -+Alternate-Site: sunsite.unc.edu /pub/Linux/system/daemons/init -+ 92K sysvinit-2.86.tar.gz -+Copying-Policy: GPL -+Keywords: init shutdown halt reboot -+End -diff -urNd -urNd sysvinit-2.85/man/bootlogd.8 sysvinit-2.86/man/bootlogd.8 ---- sysvinit-2.85/man/bootlogd.8 1969-12-31 18:00:00.000000000 -0600 -+++ sysvinit-2.86/man/bootlogd.8 2004-06-09 07:47:45.000000000 -0500 -@@ -0,0 +1,39 @@ -+.TH BOOTLOGD 8 "Jul 21, 2003" "" "Linux System Administrator's Manual" -+.SH NAME -+bootlogd \- record boot messages -+.SH SYNOPSIS -+.B /sbin/bootlogd -+.RB [ \-d ] -+.RB [ \-r ] -+.RB [ \-v ] -+.RB [ " -l logfile " ] -+.RB [ " -p pidfile " ] -+.SH DESCRIPTION -+\fBBootlogd\fP runs in the background and copies all strings sent to the -+\fI/dev/console\fP device to a logfile. If the logfile is not accessible, -+the messages will be buffered in-memory until it is. -+.SH OPTIONS -+.IP \fB\-d\fP -+Do not fork and run in the background. -+.IP \fB\-r\fP -+If there is an existing logfile called \fIlogfile\fP rename it to -+\fIlogfile~\fP unless \fIlogfile~\fP already exists. -+.IP \fB\-v\fP -+Show version. -+.IP \fB\-l logfile\fP -+Log to this logfile. The default is \fI/var/log/boot\fP. -+.IP \fB\-p pidfile\fP -+Put process-id in this file. The default is no pidfile. -+.SH BUGS -+Bootlogd works by redirecting the console output from the console -+device. It copies that output to the real console device and a -+logfile. There is no standard way to find out the real console device -+if you have a new-style \fI/dev/console\fP device (major 5, minor 1). -+\fBBootlogd\fP tries to parse the kernel command line, looking for -+console= lines and deducts the real console device from that. If that -+syntax is ever changed by the kernel, or a console-type is used -+bootlogd does not know about, bootlogd will not work. -+.SH AUTHOR -+Miquel van Smoorenburg, miquels@cistron.nl -+.SH "SEE ALSO" -+.BR dmesg (8) -diff -urNd -urNd sysvinit-2.85/man/init.8 sysvinit-2.86/man/init.8 ---- sysvinit-2.85/man/init.8 2003-04-18 16:05:03.000000000 -0500 -+++ sysvinit-2.86/man/init.8 2004-07-29 06:21:31.000000000 -0500 -@@ -1,6 +1,6 @@ - .\"{{{}}} - .\"{{{ Title --.TH INIT 8 "18 April 2003" "" "Linux System Administrator's Manual" -+.TH INIT 8 "29 Jul 2004" "" "Linux System Administrator's Manual" - .\"}}} - .\"{{{ Name - .SH NAME -@@ -160,7 +160,7 @@ - .SH ENVIRONMENT - \fBInit\fP sets the following environment variables for all its children: - .IP \fBPATH\fP --\fI/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin\fP -+\fI/bin:/usr/bin:/sbin:/usr/sbin\fP - .IP \fBINIT_VERSION\fP - As the name says. Useful to determine if a script runs directly from \fBinit\fP. - .IP \fBRUNLEVEL\fP -diff -urNd -urNd sysvinit-2.85/man/initscript.5 sysvinit-2.86/man/initscript.5 ---- sysvinit-2.85/man/initscript.5 1999-12-24 16:31:21.000000000 -0600 -+++ sysvinit-2.86/man/initscript.5 2004-06-09 07:47:45.000000000 -0500 -@@ -1,4 +1,4 @@ --.TH INITSCRIPT 5 "December 24, 1999" "" "Linux System Administrator's Manual" -+.TH INITSCRIPT 5 "July 10, 2003" "" "Linux System Administrator's Manual" - .SH NAME - initscript \- script that executes inittab commands. - .SH SYNOPSIS -@@ -40,6 +40,12 @@ - - .sp - .RE -+.SH NOTES -+This script is not meant as startup script for daemons or somesuch. -+It has nothing to do with a \fIrc.local\fP style script. It's just -+a handler for things executed from \fB/etc/inittab\fP. Experimenting -+with this can make your system un(re)bootable. -+.RE - .SH FILES - /etc/inittab, - /etc/initscript. -diff -urNd -urNd sysvinit-2.85/man/killall5.8 sysvinit-2.86/man/killall5.8 ---- sysvinit-2.85/man/killall5.8 1997-05-27 05:34:21.000000000 -0500 -+++ sysvinit-2.86/man/killall5.8 2004-06-09 07:47:45.000000000 -0500 -@@ -1,4 +1,4 @@ --.TH KILLALL5 8 "27 May 1997" "" "Linux System Administrator's Manual" -+.TH KILLALL5 8 "04 Nov 2003" "" "Linux System Administrator's Manual" - .SH NAME - killall5 -- send a signal to all processes. - .SH SYNOPSIS -@@ -7,9 +7,9 @@ - .SH DESCRIPTION - .B killall5 - is the SystemV killall command. It sends a signal to all processes except --the processes in its own session, so it won't kill the shell that is --running the script it was called from. Its primary (only) use is in the --\fBrc\fP scripts found in the /etc/init.d directory. -+kernel threads and the processes in its own session, so it won't kill -+the shell that is running the script it was called from. Its primary -+(only) use is in the \fBrc\fP scripts found in the /etc/init.d directory. - .SH SEE ALSO - .BR halt (8), - .BR reboot (8) -diff -urNd -urNd sysvinit-2.85/man/last.1 sysvinit-2.86/man/last.1 ---- sysvinit-2.85/man/last.1 1999-07-29 05:50:34.000000000 -0500 -+++ sysvinit-2.86/man/last.1 2004-07-30 06:39:18.000000000 -0500 -@@ -1,6 +1,6 @@ - .\"{{{}}} - .\"{{{ Title --.TH LAST,LASTB 1 "Jul 29, 1999" "" "Linux System Administrator's Manual" -+.TH LAST,LASTB 1 "Jul 31, 2004" "" "Linux System Administrator's Manual" - .\"}}} - .\"{{{ Name - .SH NAME -@@ -14,6 +14,7 @@ - .RB "[ \-\fBn\fP \fInum\fP ]" - .RB [ \-adiox ] - .RB "[ \-\fBf\fP \fIfile\fP ]" -+.RB "[ \-\fBt\fP \fIYYYYMMDDHHMMSS\fP ]" - .RI [ name... ] - .RI [ tty... ] - .br -@@ -54,6 +55,11 @@ - This is a count telling \fBlast\fP how many lines to show. - .IP "\fB\-n\fP \fInum\fP" - The same. -+.IP "\fB\-t\fP \fIYYYYMMDDHHMMSS\fP" -+Display the state of logins as of the specified time. This is -+useful, e.g., to determine easily who was logged in at a particular -+time -- specify that time with \fB\-t\fP and look for "still logged -+in". - .IP \fB\-R\fP - Suppresses the display of the hostname field. - .IP \fB\-a\fP -diff -urNd -urNd sysvinit-2.85/man/mesg.1 sysvinit-2.86/man/mesg.1 ---- sysvinit-2.85/man/mesg.1 2001-02-26 06:01:10.000000000 -0600 -+++ sysvinit-2.86/man/mesg.1 2004-06-09 07:47:45.000000000 -0500 -@@ -27,7 +27,7 @@ - If no option is given, \fBmesg\fP prints out the current access state of your - terminal. - .PP NOTES --\fBMesg\fP assumes that it's standard input is connected to your -+\fBMesg\fP assumes that its standard input is connected to your - terminal. That also means that if you are logged in multiple times, - you can get/set the mesg status of other sessions by using redirection. - For example "mesg n < /dev/pts/46". -diff -urNd -urNd sysvinit-2.85/man/mountpoint.1 sysvinit-2.86/man/mountpoint.1 ---- sysvinit-2.85/man/mountpoint.1 1969-12-31 18:00:00.000000000 -0600 -+++ sysvinit-2.86/man/mountpoint.1 2004-06-09 07:47:45.000000000 -0500 -@@ -0,0 +1,37 @@ -+.TH MOUNTPOINT 8 "Mar 15, 2004" "" "Linux System Administrator's Manual" -+.SH NAME -+mountpoint \- see if a directory is a mountpoint -+.SH SYNOPSIS -+.B /bin/mountpoint -+.RB [ \-q ] -+.RB [ \-d ] -+.I /path/to/directory -+.br -+.B /bin/mountpoint -+.RB \-x -+.I /dev/device -+.SH DESCRIPTION -+\fBMountpoint\fP checks if the directory is a mountpoint. -+ -+.SH OPTIONS -+.IP \fB\-q\fP -+Be quiet - don't print anything. -+.IP \fB\-d\fP -+Print major/minor device number of the filesystem on stdout. -+.IP \fB\-x\fP -+Print major/minor device number of the blockdevice on stdout. -+.SH EXIT STATUS -+Zero if the directory is a mountpoint, non-zero if not. -+.SH NOTES -+Symbolic links are not followed, except when the \fB-x\fP option is -+used. To force following symlinks, add a trailing slash to the -+path of the directory. -+.PP -+The name of the command is misleading when the -x option is used, -+but the option is useful for comparing if a directory and a device -+match up, and there is no other command that can print the info easily. -+.PP -+.SH AUTHOR -+Miquel van Smoorenburg, miquels@cistron.nl -+.SH "SEE ALSO" -+.BR stat (1) -diff -urNd -urNd sysvinit-2.85/man/shutdown.8 sysvinit-2.86/man/shutdown.8 ---- sysvinit-2.85/man/shutdown.8 2001-10-02 16:27:50.000000000 -0500 -+++ sysvinit-2.86/man/shutdown.8 2004-06-09 07:47:45.000000000 -0500 -@@ -1,6 +1,6 @@ - .\"{{{}}} - .\"{{{ Title --.TH SHUTDOWN 8 "Juli 31, 2001" "" "Linux System Administrator's Manual" -+.TH SHUTDOWN 8 "November 12, 2003" "" "Linux System Administrator's Manual" - .\"}}} - .\"{{{ Name - .SH NAME -@@ -11,7 +11,7 @@ - .B /sbin/shutdown - .RB [ \-t - .IR sec ] --.RB [ \-arkhncfF ] -+.RB [ \-arkhncfFHP ] - .I time - .RI [ warning-message ] - .\"}}} -@@ -54,7 +54,16 @@ - .\"}}} - .\"{{{ -h - .IP \fB\-h\fP --Halt after shutdown. -+Halt or poweroff after shutdown. -+.\"}}} -+.\"{{{ -H -+.IP \fB\-H\fP -+Halt action is to halt or drop into boot monitor on systems that -+support it. -+.\"}}} -+.\"{{{ -P -+.IP \fB\-P\fP -+Halt action is to turn off the power. - .\"}}} - .\"{{{ -n - .IP \fB\-n\fP -@@ -141,6 +150,14 @@ - .sp 1 - Note that if \fI/etc/shutdown.allow\fP is not present, the \fB-a\fP - argument is ignored. -+.SH HALT OR POWEROFF -+The \fB-H\fP option just sets the \fIinit\fP environment variable -+\fIINIT_HALT\fP to \fIHALT\fP, and the \fB-P\fP option just sets -+that variable to \fIPOWEROFF\fP. The shutdown script that calls -+\fBhalt\fP(8) as the last thing in the shutdown sequence should -+check these environment variables and call \fBhalt\fP(8) with -+the right options for these options to actually have any effect. -+Debian 3.1 (sarge) supports this. - .SH FILES - .nf - /fastboot -diff -urNd -urNd sysvinit-2.85/man/sulogin.8 sysvinit-2.86/man/sulogin.8 ---- sysvinit-2.85/man/sulogin.8 2000-09-11 07:19:25.000000000 -0500 -+++ sysvinit-2.86/man/sulogin.8 2004-06-09 07:47:45.000000000 -0500 -@@ -1,4 +1,4 @@ --.TH SULOGIN 8 "11 Sep 2000" "" "Linux System Administrator's Manual" -+.TH SULOGIN 8 "04 Nov 2003" "" "Linux System Administrator's Manual" - .SH NAME - sulogin -- Single-user login - .SH SYNOPSIS -@@ -20,7 +20,7 @@ - .br - (or type Control-D for normal startup): - .PP --\fIsulogin\fP will connected to the current terminal, or to the -+\fIsulogin\fP will be connected to the current terminal, or to the - optional device that can be specified on the command line - (typically \fB/dev/console\fP). - .PP -@@ -45,16 +45,18 @@ - .PP - boot: linux -b rw sushell=/sbin/sash - .SH FALLBACK METHODS --\fIsulogin\fP checks the root password using the standard methods first. --If the \fB-e\fP option was specified, --\fIsulogin\fP examines the next files to find the root password. If --they are damaged, or non-existant, it will use fallback methods that --even go so far as to provide you with a shell prompt without asking --for the root password if they are irrepairably damaged. -+\fIsulogin\fP checks the root password using the standard method (getpwnam) -+first. -+Then, if the \fB-e\fP option was specified, -+\fIsulogin\fP examines these files directly to find the root password: - .PP - /etc/passwd, - .br - /etc/shadow (if present) -+.PP -+If they are damaged or non-existant, sulogin will start a root shell -+without asking for a password. Only use the \fB-e\fP option if you -+are sure the console is physically protected against unauthorized access. - .SH AUTHOR - Miquel van Smoorenburg <miquels@cistron.nl> - .SH SEE ALSO -diff -urNd -urNd sysvinit-2.85/man/wall.1 sysvinit-2.86/man/wall.1 ---- sysvinit-2.85/man/wall.1 2003-04-16 04:17:38.000000000 -0500 -+++ sysvinit-2.86/man/wall.1 2004-06-09 07:47:45.000000000 -0500 -@@ -47,7 +47,7 @@ - .I Wall - ignores the - .B TZ --variable - the time printed in the banner is based on the systems -+variable - the time printed in the banner is based on the system's - local time. - - .SH SEE ALSO -diff -urNd -urNd sysvinit-2.85/src/Makefile sysvinit-2.86/src/Makefile ---- sysvinit-2.85/src/Makefile 2001-11-06 05:58:16.000000000 -0600 -+++ sysvinit-2.86/src/Makefile 2004-06-09 07:47:45.000000000 -0500 -@@ -5,34 +5,56 @@ - # clean cleans up object files - # clobber really cleans up - # --# Version: @(#)Makefile 2.83-3 06-Nov-2001 miquels@cistron.nl -+# Version: @(#)Makefile 2.85-13 23-Mar-2004 miquels@cistron.nl - # - --CC = cc --CFLAGS = -Wall -O2 -D_GNU_SOURCE -+CC = gcc -+CFLAGS = -Wall -O2 -fomit-frame-pointer -D_GNU_SOURCE - LDFLAGS = -s - STATIC = - --# For Debian we do not build all programs, otherwise we do. --ifeq ($(DEBIAN),) --PROGS = init halt shutdown killall5 runlevel sulogin utmpdump \ -- last mesg wall --else --PROGS = init halt shutdown killall5 runlevel sulogin last mesg -+# For some known distributions we do not build all programs, otherwise we do. -+BIN = -+SBIN = init halt shutdown runlevel killall5 -+USRBIN = last mesg -+ -+MAN1 = last.1 lastb.1 mesg.1 -+MAN5 = initscript.5 inittab.5 -+MAN8 = halt.8 init.8 killall5.8 pidof.8 poweroff.8 reboot.8 runlevel.8 -+MAN8 += shutdown.8 telinit.8 -+ -+ifeq ($(DISTRO),) -+BIN += mountpoint -+SBIN += sulogin bootlogd -+USRBIN += utmpdump wall -+MAN1 += mountpoint.1 wall.1 -+MAN8 += sulogin.8 bootlogd.8 -+endif -+ -+ifeq ($(DISTRO),Debian) -+BIN += mountpoint -+SBIN += sulogin bootlogd -+MAN1 += mountpoint.1 -+MAN8 += sulogin.8 bootlogd.8 -+endif -+ -+ifeq ($(DISTRO),Owl) -+USRBIN += wall -+MAN1 += wall.1 - endif - - BIN_OWNER = root - BIN_GROUP = root --BIN_COMBO = $(BIN_OWNER).$(BIN_GROUP) -+BIN_COMBO = $(BIN_OWNER):$(BIN_GROUP) - INSTALL = install -o $(BIN_OWNER) -g $(BIN_GROUP) - MANDIR = /usr/share/man - --# Additional libs for Gnu Libc -+# Additional libs for GNU libc. - ifneq ($(wildcard /usr/lib/libcrypt.a),) - LCRYPT = -lcrypt - endif - --all: $(PROGS) -+all: $(BIN) $(SBIN) $(USRBIN) - - init: init.o init_utmp.o - $(CC) $(LDFLAGS) $(STATIC) -o $@ init.o init_utmp.o -@@ -46,6 +68,9 @@ - mesg: mesg.o - $(CC) $(LDFLAGS) -o $@ mesg.o - -+mountpoint: mountpoint.o -+ $(CC) $(LDFLAGS) -o $@ mountpoint.o -+ - utmpdump: utmpdump.o - $(CC) $(LDFLAGS) -o $@ utmpdump.o - -@@ -62,9 +87,9 @@ - $(CC) $(LDFLAGS) -o $@ dowall.o shutdown.o utmp.o - - bootlogd: bootlogd.o -- $(CC) $(LDFLAGS) -o $@ bootlogd.o -+ $(CC) $(LDFLAGS) -o $@ bootlogd.o -lutil - --init.o: init.c init.h set.h reboot.h -+init.o: init.c init.h set.h reboot.h initreq.h - $(CC) -c $(CFLAGS) init.c - - utmp.o: utmp.c init.h -@@ -80,36 +105,44 @@ - @echo Type \"make clobber\" to really clean up. - - clobber: cleanobjs -- rm -f $(PROGS) -+ rm -f $(BIN) $(SBIN) $(USRBIN) - - distclean: clobber - - install: -- $(INSTALL) -m 755 halt init killall5 sulogin \ -- runlevel shutdown $(ROOT)/sbin -- # These are not installed by default --ifeq ($(DEBIAN),) -- $(INSTALL) -m 555 utmpdump wall $(ROOT)/usr/bin --endif -- # $(INSTALL) -m 755 etc/initscript.sample $(ROOT)/etc -- $(INSTALL) -m 755 mesg last $(ROOT)/usr/bin -- cd $(ROOT)/sbin; ln -sf halt reboot; chown $(BIN_COMBO) reboot -- cd $(ROOT)/sbin; ln -sf halt poweroff; chown $(BIN_COMBO) poweroff -- cd $(ROOT)/sbin; ln -sf init telinit; chown $(BIN_COMBO) telinit -- cd $(ROOT)/bin; ln -sf ../sbin/killall5 pidof; chown $(BIN_COMBO) pidof -- cd $(ROOT)/usr/bin; ln -sf last lastb; chown $(BIN_COMBO) lastb -- $(INSTALL) -m 644 initreq.h $(ROOT)/usr/include -- $(INSTALL) -m 644 ../man/*.8 $(ROOT)$(MANDIR)/man8 -- $(INSTALL) -m 644 ../man/*.5 $(ROOT)$(MANDIR)/man5 --ifeq ($(DEBIAN),) -- $(INSTALL) -m 644 ../man/wall.1 $(ROOT)$(MANDIR)/man1 --endif -- $(INSTALL) -m 644 ../man/last.1 ../man/lastb.1 ../man/mesg.1 \ -- $(ROOT)$(MANDIR)/man1 -+ for i in $(BIN); do \ -+ $(INSTALL) -m 755 $$i $(ROOT)/bin/; \ -+ done -+ for i in $(SBIN); do \ -+ $(INSTALL) -m 755 $$i $(ROOT)/sbin/; \ -+ done -+ for i in $(USRBIN); do \ -+ $(INSTALL) -m 755 $$i $(ROOT)/usr/bin/; \ -+ done -+ # $(INSTALL) -m 755 etc/initscript.sample $(ROOT)/etc/ -+ ln -sf halt $(ROOT)/sbin/reboot -+ ln -sf halt $(ROOT)/sbin/poweroff -+ ln -sf init $(ROOT)/sbin/telinit -+ ln -sf ../sbin/killall5 $(ROOT)/bin/pidof -+ if [ ! -f $(ROOT)/usr/bin/lastb ]; then \ -+ ln -sf last $(ROOT)/usr/bin/lastb; \ -+ fi -+ $(INSTALL) -m 644 initreq.h $(ROOT)/usr/include/ -+ for i in $(MAN1); do \ -+ $(INSTALL) -m 644 ../man/$$i $(ROOT)$(MANDIR)/man1/; \ -+ done -+ for i in $(MAN5); do \ -+ $(INSTALL) -m 644 ../man/$$i $(ROOT)$(MANDIR)/man5/; \ -+ done -+ for i in $(MAN8); do \ -+ $(INSTALL) -m 644 ../man/$$i $(ROOT)$(MANDIR)/man8/; \ -+ done -+ifeq ($(ROOT),) - # -- # This part is skipped on debian systems, the -+ # This part is skipped on Debian systems, the - # debian.preinst script takes care of it. - @if [ ! -p /dev/initctl ]; then \ - echo "Creating /dev/initctl"; \ - rm -f /dev/initctl; \ - mknod -m 600 /dev/initctl p; fi -+endif -Binary files sysvinit-2.85/src/bootlogd and sysvinit-2.86/src/bootlogd differ -diff -urNd -urNd sysvinit-2.85/src/bootlogd.c sysvinit-2.86/src/bootlogd.c ---- sysvinit-2.85/src/bootlogd.c 2001-12-09 08:01:28.000000000 -0600 -+++ sysvinit-2.86/src/bootlogd.c 2004-06-09 07:47:45.000000000 -0500 -@@ -3,12 +3,12 @@ - * The file is usually located on the /var partition, and - * gets written (and fsynced) as soon as possible. - * -- * Version: @(#)bootlogd 2.79 11-Sep-2000 miquels@cistron.nl -+ * Version: @(#)bootlogd 2.86pre 12-Jan-2004 miquels@cistron.nl - * - * Bugs: Uses openpty(), only available in glibc. Sorry. - * - * This file is part of the sysvinit suite, -- * Copyright 1991-2000 Miquel van Smoorenburg. -+ * Copyright 1991-2004 Miquel van Smoorenburg. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License -@@ -17,7 +17,9 @@ - * - * *NOTE* *NOTE* *NOTE* - * This is a PROOF OF CONCEPT IMPLEMENTATION -- * I do not recommend using this on production systems. -+ * -+ * I have bigger plans for Debian, but for now -+ * this has to do ;) - * - */ - -@@ -38,18 +40,14 @@ - #include <dirent.h> - #include <fcntl.h> - #include <pty.h> -- --char *Version = "@(#) bootlogd 2.79 11-Sep-2000 MvS"; -- --/* -- * Until the kernel knows about TIOCGDEV, use a really ugly -- * non-portable (not even between architectures) hack. -- */ --#ifndef TIOCGDEV --# define TIOCTTYGSTRUCT_HACK 1 -+#include <ctype.h> -+#ifdef __linux__ -+#include <sys/mount.h> - #endif - --#define LOGFILE "/var/log/boot.log" -+char *Version = "@(#) bootlogd 2.86 03-Jun-2004 miquels@cistron.nl"; -+ -+#define LOGFILE "/var/log/boot" - - char ringbuf[32768]; - char *endptr = ringbuf + sizeof(ringbuf); -@@ -59,29 +57,32 @@ - int got_signal = 0; - int didnl = 1; - -+struct line { -+ char buf[256]; -+ int pos; -+} line; - --#ifdef TIOCTTYGSTRUCT_HACK --struct tty_offsets { -- char *kver; -- int offset; --} tty_offsets[] = { --#if ((~0UL) == 0xffffffff) /* 32 bits */ -- { "2.0.", 236 }, -- { "2.1.", 268 }, -- { "2.2.", 272 }, -- { "2.3.", 272 }, -- { "2.4.", 272 }, -- { "2.5.", 272 }, --#else /* 64 bits */ -- { "2.2.", 480 }, -- { "2.3.", 480 }, -- { "2.4.", 480 }, -- { "2.5.", 480 }, --#endif -- { NULL, 0 }, -+/* -+ * Console devices as listed on the kernel command line and -+ * the mapping to actual devices in /dev -+ */ -+struct consdev { -+ char *cmdline; -+ char *dev1; -+ char *dev2; -+} consdev[] = { -+ { "ttySC", "/dev/ttySC%s", "/dev/ttsc/%s" }, -+ { "ttyS", "/dev/ttyS%s", "/dev/tts/%s" }, -+ { "tty", "/dev/tty%s", "/dev/vc/%s" }, -+ { "hvc", "/dev/hvc%s", "/dev/hvc/%s" }, -+ { NULL, NULL, NULL }, - }; --#endif - -+/* -+ * Devices to try as console if not found on kernel command line. -+ * Tried from left to right (as opposed to kernel cmdline). -+ */ -+char *defcons[] = { "tty0", "hvc0", "ttyS0", "ttySC0", NULL }; - - /* - * Catch signals. -@@ -95,6 +96,8 @@ - /* - * Scan /dev and find the device name. - * Side-effect: directory is changed to /dev -+ * -+ * FIXME: scan subdirectories for devfs support ? - */ - int findtty(char *res, int rlen, dev_t dev) - { -@@ -117,18 +120,88 @@ - } - } - if (ent == NULL) { -- fprintf(stderr, "bootlogd: cannot find console device\n"); -+ fprintf(stderr, "bootlogd: cannot find console device " -+ "%d:%d in /dev\n", major(dev), minor(dev)); - r = -1; -- } else if (strlen(ent->d_name) >= rlen) { -+ } else if (strlen(ent->d_name) + 5 >= rlen) { - fprintf(stderr, "bootlogd: console device name too long\n"); - r = -1; - } else -- strcpy(res, ent->d_name); -+ snprintf(res, rlen, "/dev/%s", ent->d_name); - closedir(dir); - - return r; - } - -+/* -+ * For some reason, openpty() in glibc sometimes doesn't -+ * work at boot-time. It must be a bug with old-style pty -+ * names, as new-style (/dev/pts) is not available at that -+ * point. So, we find a pty/tty pair ourself if openpty() -+ * fails for whatever reason. -+ */ -+int findpty(int *master, int *slave, char *name) -+{ -+ char pty[16]; -+ char tty[16]; -+ int i, j; -+ int found; -+ -+ if (openpty(master, slave, name, NULL, NULL) >= 0) -+ return 0; -+ -+ found = 0; -+ -+ for (i = 'p'; i <= 'z'; i++) { -+ for (j = '0'; j <= 'f'; j++) { -+ if (j == '9' + 1) j = 'a'; -+ sprintf(pty, "/dev/pty%c%c", i, j); -+ sprintf(tty, "/dev/tty%c%c", i, j); -+ if ((*master = open(pty, O_RDWR|O_NOCTTY)) >= 0) { -+ *slave = open(tty, O_RDWR|O_NOCTTY); -+ if (*slave >= 0) { -+ found = 1; -+ break; -+ } -+ } -+ } -+ if (found) break; -+ } -+ if (found < 0) return -1; -+ -+ if (name) strcpy(name, tty); -+ -+ return 0; -+} -+/* -+ * See if a console taken from the kernel command line maps -+ * to a character device we know about, and if we can open it. -+ */ -+int isconsole(char *s, char *res, int rlen) -+{ -+ struct consdev *c; -+ int l, sl, i, fd; -+ char *p, *q; -+ -+ sl = strlen(s); -+ -+ for (c = consdev; c->cmdline; c++) { -+ l = strlen(c->cmdline); -+ if (sl <= l) continue; -+ p = s + l; -+ if (strncmp(s, c->cmdline, l) != 0 || !isdigit(*p)) -+ continue; -+ for (i = 0; i < 2; i++) { -+ snprintf(res, rlen, i ? c->dev1 : c->dev2, p); -+ if ((q = strchr(res, ',')) != NULL) *q = 0; -+ if ((fd = open(res, O_RDONLY|O_NONBLOCK)) >= 0) { -+ close(fd); -+ return 1; -+ } -+ } -+ } -+ return 0; -+} - - /* - * Find out the _real_ console. Assume that stdin is connected to -@@ -136,21 +209,18 @@ - */ - int consolename(char *res, int rlen) - { -- struct stat st; --#if TIOCTTYGSTRUCT_HACK -- struct utsname uts; -- struct tty_offsets *tt; -- dev_t dev; -- unsigned short *kdev; -- char buf[4096]; -- int offset = -1; --#endif - #ifdef TIOCGDEV -- kdev_t kdev; -+ unsigned int kdev; - #endif -+ struct stat st, st2; -+ char buf[256]; -+ char *p; -+ int didmount = 0; -+ int n, r; -+ int fd; - - fstat(0, &st); -- if (st.st_rdev != 0x0501) { -+ if (major(st.st_rdev) != 5 || minor(st.st_rdev) != 1) { - /* - * Old kernel, can find real device easily. - */ -@@ -160,33 +230,78 @@ - #ifdef TIOCGDEV - if (ioctl(0, TIOCGDEV, &kdev) == 0) - return findtty(res, rlen, (dev_t)kdev); -- return -1; -+ if (errno != ENOIOCTLCMD) return -1; - #endif - -+#ifdef __linux__ - /* -- * New kernel and new console device - hard to find -- * out what device the real console is .. -+ * Read /proc/cmdline. - */ --#if TIOCTTYGSTRUCT_HACK -- if (ioctl(0, TIOCTTYGSTRUCT, buf) != 0) { -- perror("bootlogd: TIOCTTYGSTRUCT"); -+ stat("/", &st); -+ if (stat("/proc", &st2) < 0) { -+ perror("bootlogd: /proc"); - return -1; - } -- uname(&uts); -- for (tt = tty_offsets; tt->kver; tt++) -- if (!strncmp(uts.release, tt->kver, strlen(tt->kver))) { -- offset = tt->offset; -+ if (st.st_dev == st2.st_dev) { -+ if (mount("proc", "/proc", "proc", 0, NULL) < 0) { -+ perror("bootlogd: mount /proc"); -+ return -1; -+ } -+ didmount = 1; -+ } -+ -+ n = 0; -+ r = -1; -+ if ((fd = open("/proc/cmdline", O_RDONLY)) < 0) { -+ perror("bootlogd: /proc/cmdline"); -+ } else { -+ buf[0] = 0; -+ if ((n = read(fd, buf, sizeof(buf) - 1)) >= 0) -+ r = 0; -+ else -+ perror("bootlogd: /proc/cmdline"); -+ close(fd); -+ } -+ if (didmount) umount("/proc"); -+ -+ if (r < 0) return r; -+ -+ /* -+ * OK, so find console= in /proc/cmdline. -+ * Parse in reverse, opening as we go. -+ * -+ * Valid console devices: ttySC, ttyS, tty, hvc. -+ */ -+ p = buf + n; -+ *p-- = 0; -+ r = -1; -+ while (p >= buf) { -+ if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { -+ *p-- = 0; -+ continue; -+ } -+ if (strncmp(p, "console=", 8) == 0 && -+ isconsole(p + 8, res, rlen)) { -+ r = 0; - break; - } -- if (offset < 0) { -- fprintf(stderr, "bootlogd: don't know offsetof" -- "(struct tty_struct, device) for kernel %s\n", uts.release); -- return -1; -+ p--; - } -- kdev = (unsigned short *)(&buf[offset]); -- dev = (dev_t)(*kdev); -- return findtty(res, rlen, dev); -+ -+ if (r == 0) return r; - #endif -+ -+ /* -+ * Okay, no console on the command line - -+ * guess the default console. -+ */ -+ for (n = 0; defcons[n]; n++) -+ if (isconsole(defcons[n], res, rlen)) -+ return 0; -+ -+ fprintf(stderr, "bootlogd: cannot deduce real console device\n"); -+ -+ return -1; - } - - -@@ -197,9 +312,13 @@ - { - time_t t; - char *s; -+ char tmp[8]; - int olen = len; -+ int dosync = 0; -+ int tlen; - - while (len > 0) { -+ tmp[0] = 0; - if (didnl) { - time(&t); - s = ctime(&t); -@@ -207,24 +326,51 @@ - didnl = 0; - } - switch (*ptr) { -+ case 27: /* ESC */ -+ strcpy(tmp, "^["); -+ break; - case '\r': -+ line.pos = 0; -+ break; -+ case 8: /* ^H */ -+ if (line.pos > 0) line.pos--; - break; - case '\n': - didnl = 1; -+ dosync = 1; -+ break; - case '\t': -+ line.pos += (line.pos / 8 + 1) * 8; -+ if (line.pos >= sizeof(line.buf)) -+ line.pos = sizeof(line.buf) - 1; -+ break; - case 32 ... 127: - case 161 ... 255: -- fputc(*ptr, fp); -+ tmp[0] = *ptr; -+ tmp[1] = 0; - break; - default: -- fprintf(fp, "\\%03o", *ptr); -+ sprintf(tmp, "\\%03o", *ptr); - break; - } - ptr++; - len--; -+ -+ tlen = strlen(tmp); -+ if (tlen && (line.pos + tlen < sizeof(line.buf))) { -+ memcpy(line.buf + line.pos, tmp, tlen); -+ line.pos += tlen; -+ } -+ if (didnl) { -+ fprintf(fp, "%s\n", line.buf); -+ memset(&line, 0, sizeof(line)); -+ } -+ } -+ -+ if (dosync) { -+ fflush(fp); -+ fdatasync(fileno(fp)); - } -- fflush(fp); -- fdatasync(fileno(fp)); - - outptr += olen; - if (outptr >= endptr) -@@ -242,6 +388,40 @@ - exit(1); - } - -+int open_nb(char *buf) -+{ -+ int fd, n; -+ -+ if ((fd = open(buf, O_WRONLY|O_NONBLOCK|O_NOCTTY)) < 0) -+ return -1; -+ n = fcntl(fd, F_GETFL); -+ n &= ~(O_NONBLOCK); -+ fcntl(fd, F_SETFL, n); -+ -+ return fd; -+} -+ -+/* -+ * We got a write error on the real console. If its an EIO, -+ * somebody hung up our filedescriptor, so try to re-open it. -+ */ -+int write_err(int pts, int realfd, char *realcons, int e) -+{ -+ int fd; -+ -+ if (e != EIO) { -+werr: -+ close(pts); -+ fprintf(stderr, "bootlogd: writing to console: %s\n", -+ strerror(e)); -+ return -1; -+ } -+ close(realfd); -+ if ((fd = open_nb(realcons)) < 0) -+ goto werr; -+ -+ return fd; -+} - - int main(int argc, char **argv) - { -@@ -249,6 +429,7 @@ - struct timeval tv; - fd_set fds; - char buf[1024]; -+ char realcons[1024]; - char *p; - char *logfile; - char *pidfile; -@@ -298,23 +479,32 @@ - /* - * Open console device directly. - */ -- if (consolename(buf, sizeof(buf)) < 0) -+ if (consolename(realcons, sizeof(realcons)) < 0) - return 1; -- if ((realfd = open(buf, O_WRONLY|O_NONBLOCK)) < 0) { -+ -+ if (strcmp(realcons, "/dev/tty0") == 0) -+ strcpy(realcons, "/dev/tty1"); -+ if (strcmp(realcons, "/dev/vc/0") == 0) -+ strcpy(realcons, "/dev/vc/1"); -+ -+ if ((realfd = open_nb(realcons)) < 0) { - fprintf(stderr, "bootlogd: %s: %s\n", buf, strerror(errno)); - return 1; - } -- n = fcntl(realfd, F_GETFL); -- n &= ~(O_NONBLOCK); -- fcntl(realfd, F_SETFL, n); - - /* - * Grab a pty, and redirect console messages to it. - */ -- if (openpty(&ptm, &pts, buf, NULL, NULL) < 0) { -- fprintf(stderr, "bootlogd: cannot allocate pseudo tty\n"); -+ ptm = -1; -+ pts = -1; -+ buf[0] = 0; -+ if (findpty(&ptm, &pts, buf) < 0) { -+ fprintf(stderr, -+ "bootlogd: cannot allocate pseudo tty: %s\n", -+ strerror(errno)); - return 1; - } -+ - (void)ioctl(0, TIOCCONS, NULL); - #if 1 - /* Work around bug in 2.1/2.2 kernels. Fixed in 2.2.13 and 2.3.18 */ -@@ -357,8 +547,8 @@ - * open the logfile. There might be buffered messages - * we want to write. - */ -- tv.tv_sec = fp ? 86400 : 5; -- tv.tv_usec = 0; -+ tv.tv_sec = 0; -+ tv.tv_usec = 500000; - FD_ZERO(&fds); - FD_SET(ptm, &fds); - if (select(ptm + 1, &fds, NULL, NULL, &tv) == 1) { -@@ -374,10 +564,22 @@ - p = inptr; - while (m > 0) { - i = write(realfd, p, m); -- if (i <= 0) break; -- m -= i; -- p += i; -+ if (i >= 0) { -+ m -= i; -+ p += i; -+ continue; -+ } -+ /* -+ * Handle EIO (somebody hung -+ * up our filedescriptor) -+ */ -+ realfd = write_err(pts, realfd, -+ realcons, errno); -+ if (realfd >= 0) continue; -+ got_signal = 1; /* Not really */ -+ break; - } -+ - /* - * Increment buffer position. Handle - * wraps, and also drag output pointer -@@ -410,8 +612,8 @@ - writelog(fp, outptr, todo); - } - -- if (fp && !didnl) { -- fputc('\n', fp); -+ if (fp) { -+ if (!didnl) fputc('\n', fp); - fclose(fp); - } - -Binary files sysvinit-2.85/src/bootlogd.o and sysvinit-2.86/src/bootlogd.o differ -diff -urNd -urNd sysvinit-2.85/src/dowall.c sysvinit-2.86/src/dowall.c ---- sysvinit-2.85/src/dowall.c 2003-04-17 06:32:01.000000000 -0500 -+++ sysvinit-2.86/src/dowall.c 2004-06-09 07:47:45.000000000 -0500 -@@ -3,7 +3,7 @@ - * - * Author: Miquel van Smoorenburg, miquels@cistron.nl - * -- * Version: @(#)dowall.c 2.85-1 15-Apr-2003 miquels@cistron.nl -+ * Version: @(#)dowall.c 2.85-5 02-Jul-2003 miquels@cistron.nl - * - * This file is part of the sysvinit suite, - * Copyright 1991-2003 Miquel van Smoorenburg. -@@ -135,6 +135,13 @@ - char *user, *tty; - int fd, flags; - -+ /* -+ * Make sure tp and fd aren't in a register. Some versions -+ * of gcc clobber those after longjmp (or so I understand). -+ */ -+ (void) &tp; -+ (void) &fd; -+ - getuidtty(&user, &tty); - - /* Get the time */ -Binary files sysvinit-2.85/src/dowall.o and sysvinit-2.86/src/dowall.o differ -Binary files sysvinit-2.85/src/halt and sysvinit-2.86/src/halt differ -diff -urNd -urNd sysvinit-2.85/src/halt.c sysvinit-2.86/src/halt.c ---- sysvinit-2.85/src/halt.c 2001-11-27 06:12:03.000000000 -0600 -+++ sysvinit-2.86/src/halt.c 2004-07-30 07:16:18.000000000 -0500 -@@ -8,12 +8,14 @@ - * execute an "shutdown -r". This is for compatibility with - * sysvinit 2.4. - * -- * Usage: halt [-n] [-w] [-d] [-f] [-p] -+ * Usage: halt [-n] [-w] [-d] [-f] [-h] [-i] [-p] - * -n: don't sync before halting the system - * -w: only write a wtmp reboot record and exit. - * -d: don't write a wtmp record. - * -f: force halt/reboot, don't call shutdown. -- * -p: power down the system (if possible, otherwise halt) -+ * -h: put harddisks in standby mode -+ * -i: shut down all network interfaces. -+ * -p: power down the system (if possible, otherwise halt). - * - * Reboot and halt are both this program. Reboot - * is just a link to halt. Invoking the program -@@ -21,10 +23,10 @@ - * - * Author: Miquel van Smoorenburg, miquels@cistron.nl - * -- * Version: 2.84, 27-Nov-2001 -+ * Version: 2.86, 30-Jul-2004 - * - * This file is part of the sysvinit suite, -- * Copyright 1991-2001 Miquel van Smoorenburg. -+ * Copyright 1991-2004 Miquel van Smoorenburg. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License -@@ -47,7 +49,7 @@ - #include <getopt.h> - #include "reboot.h" - --char *Version = "@(#)halt 2.84 27-Nov-2001 miquels@cistron.nl"; -+char *Version = "@(#)halt 2.86 31-Jul-2004 miquels@cistron.nl"; - char *progname; - - #define KERNEL_MONITOR 1 /* If halt() puts you into the kernel monitor. */ -@@ -62,7 +64,16 @@ - */ - void usage(void) - { -- fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f] [-i] [-p]\n", progname); -+ fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f] [-h] [-i]%s\n", -+ progname, strcmp(progname, "halt") ? "" : " [-p]"); -+ fprintf(stderr, "\t-n: don't sync before halting the system\n"); -+ fprintf(stderr, "\t-w: only write a wtmp reboot record and exit.\n"); -+ fprintf(stderr, "\t-d: don't write a wtmp record.\n"); -+ fprintf(stderr, "\t-f: force halt/reboot, don't call shutdown.\n"); -+ fprintf(stderr, "\t-h: put harddisks in standby mode.\n"); -+ fprintf(stderr, "\t-i: shut down all network interfaces.\n"); -+ if (!strcmp(progname, "halt")) -+ fprintf(stderr, "\t-p: power down the system (if possible, otherwise halt).\n"); - exit(1); - } - -@@ -172,11 +183,6 @@ - else - progname = argv[0]; - -- if (geteuid() != 0) { -- fprintf(stderr, "%s: must be superuser.\n", progname); -- exit(1); -- } -- - if (!strcmp(progname, "reboot")) do_reboot = 1; - if (!strcmp(progname, "poweroff")) do_poweroff = 1; - -@@ -216,6 +222,11 @@ - } - if (argc != optind) usage(); - -+ if (geteuid() != 0) { -+ fprintf(stderr, "%s: must be superuser.\n", progname); -+ exit(1); -+ } -+ - (void)chdir("/"); - - if (!do_hard && !do_nothing) { -@@ -236,7 +247,7 @@ - /* - * Exit if all we wanted to do was write a wtmp record. - */ -- if (do_nothing) exit(0); -+ if (do_nothing && !do_hddown && !do_ifdown) exit(0); - - if (do_sync) { - sync(); -@@ -249,13 +260,17 @@ - if (do_hddown) - (void)hddown(); - -+ if (do_nothing) exit(0); -+ - if (do_reboot) { - init_reboot(BMAGIC_REBOOT); - } else { - /* - * Turn on hard reboot, CTRL-ALT-DEL will reboot now - */ -+#ifdef BMAGIC_HARD - init_reboot(BMAGIC_HARD); -+#endif - - /* - * Stop init; it is insensitive to the signals sent -@@ -277,7 +292,9 @@ - /* - * If we return, we (c)ontinued from the kernel monitor. - */ -+#ifdef BMAGIC_SOFT - init_reboot(BMAGIC_SOFT); -+#endif - kill(1, SIGCONT); - - exit(0); -Binary files sysvinit-2.85/src/halt.o and sysvinit-2.86/src/halt.o differ -diff -urNd -urNd sysvinit-2.85/src/hddown.c sysvinit-2.86/src/hddown.c ---- sysvinit-2.85/src/hddown.c 2001-11-07 09:11:21.000000000 -0600 -+++ sysvinit-2.86/src/hddown.c 2004-06-09 07:47:45.000000000 -0500 -@@ -3,7 +3,7 @@ - * shut them down. - * - */ --char *v_hddown = "@(#)hddown.c 1.01 07-Nov-2001 miquels@cistron.nl"; -+char *v_hddown = "@(#)hddown.c 1.02 22-Apr-2003 miquels@cistron.nl"; - - #include <stdio.h> - #include <stdlib.h> -@@ -13,8 +13,9 @@ - #include <fcntl.h> - #include <dirent.h> - --#include <sys/ioctl.h> -+#ifdef __linux__ - -+#include <sys/ioctl.h> - #include <linux/hdreg.h> - - #define MAX_DISKS 64 -@@ -104,6 +105,15 @@ - return 0; - } - -+#else /* __linux__ */ -+ -+int hddown(void) -+{ -+ return 0; -+} -+ -+#endif /* __linux__ */ -+ - #ifdef STANDALONE - int main(int argc, char **argv) - { -Binary files sysvinit-2.85/src/hddown.o and sysvinit-2.86/src/hddown.o differ -Binary files sysvinit-2.85/src/ifdown.o and sysvinit-2.86/src/ifdown.o differ -Binary files sysvinit-2.85/src/init and sysvinit-2.86/src/init differ -diff -urNd -urNd sysvinit-2.85/src/init.c sysvinit-2.86/src/init.c ---- sysvinit-2.85/src/init.c 2003-04-15 06:16:41.000000000 -0500 -+++ sysvinit-2.86/src/init.c 2004-07-30 07:16:20.000000000 -0500 -@@ -5,34 +5,28 @@ - * init [0123456SsQqAaBbCc] - * telinit [0123456SsQqAaBbCc] - * -- * Version: @(#)init.c 2.85 15-Apr-2003 miquels@cistron.nl -+ * Version: @(#)init.c 2.86 30-Jul-2004 miquels@cistron.nl - */ --#define VERSION "2.85" --#define DATE "15-Apr-2003" -+#define VERSION "2.86" -+#define DATE "31-Jul-2004" - /* - * This file is part of the sysvinit suite, -- * Copyright 1991-2003 Miquel van Smoorenburg. -+ * Copyright 1991-2004 Miquel van Smoorenburg. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * -- * Modified: 21 Feb 1998, Al Viro: -- * 'U' flag added to telinit. It forces init to re-exec itself -- * (passing its state through exec, certainly). -- * May be useful for smoother (heh) upgrades. -- * 24 Feb 1998, AV: -- * did_boot made global and added to state - thanks, Miquel. -- * Yet another file descriptors leak - close state pipe if -- * re_exec fails. - */ - - #include <sys/types.h> - #include <sys/stat.h> - #include <sys/ioctl.h> - #include <sys/wait.h> -+#ifdef __linux__ - #include <sys/kd.h> -+#endif - #include <sys/resource.h> - #include <stdlib.h> - #include <unistd.h> -@@ -70,6 +64,13 @@ - # define SIGPWR SIGUSR2 - #endif - -+#ifndef CBAUD -+# define CBAUD 0 -+#endif -+#ifndef CBAUDEX -+# define CBAUDEX 0 -+#endif -+ - /* Set a signal handler. */ - #define SETSIG(sa, sig, fun, flags) \ - do { \ -@@ -88,13 +89,13 @@ - CHILD *newFamily = NULL; /* The list after inittab re-read */ - - CHILD ch_emerg = { /* Emergency shell */ -- 0, 0, 0, 0, 0, -- "~~", -- "S", -- 3, -- "/sbin/sulogin", -- NULL, -- NULL -+ 0, 0, 0, 0, 0, -+ "~~", -+ "S", -+ 3, -+ "/sbin/sulogin", -+ NULL, -+ NULL - }; - - char runlevel = 'S'; /* The current run level */ -@@ -108,8 +109,9 @@ - int wrote_utmp_reboot = 1; /* Set when we wrote the reboot 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] without \0 */ -+int maxproclen; /* Maximal length of argv[0] with \0 */ - struct utmp utproto; /* Only used for sizeof(utproto.ut_id) */ -+char *user_console = NULL; /* User console device */ - char *console_dev; /* Console device. */ - int pipe_fd = -1; /* /dev/initctl */ - int did_boot = 0; /* Did we already do BOOT* stuff? */ -@@ -186,6 +188,10 @@ - {NULL,0} - }; - -+#define NR_EXTRA_ENV 16 -+char *extra_env[NR_EXTRA_ENV]; -+ -+ - /* - * Sleep a number of seconds. - * -@@ -203,6 +209,35 @@ - ; - } - -+ -+/* -+ * Non-failing allocation routines (init cannot fail). -+ */ -+void *imalloc(size_t size) -+{ -+ void *m; -+ -+ while ((m = malloc(size)) == NULL) { -+ initlog(L_VB, "out of memory"); -+ do_sleep(5); -+ } -+ memset(m, 0, size); -+ return m; -+} -+ -+ -+char *istrdup(char *s) -+{ -+ char *m; -+ int l; -+ -+ l = strlen(s) + 1; -+ m = imalloc(l); -+ memcpy(m, s, l); -+ return m; -+} -+ -+ - /* - * Send the state info of the previous running init to - * the new one, in a version-independant way. -@@ -344,12 +379,9 @@ - } - } while (cmd != C_REC); - -- while ((p = (CHILD *)malloc(sizeof(CHILD))) == NULL ) { -- log(L_VB, "out of memory"); -- do_sleep(5); -- } -- memset(p, 0, sizeof(CHILD)); -+ p = imalloc(sizeof(CHILD)); - get_string(p->id, sizeof(p->id), f); -+ - do switch(cmd = get_cmd(f)) { - case 0: - case C_EOR: -@@ -420,7 +452,7 @@ - #ifdef __GNUC__ - __attribute__ ((format (printf, 1, 2))) - #endif --int setproctitle(char *fmt, ...) -+static int setproctitle(char *fmt, ...) - { - va_list ap; - int len; -@@ -432,8 +464,10 @@ - len = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - -- memset(argv0, 0, maxproclen + 1); -- strncpy(argv0, buf, maxproclen - 1); -+ if (maxproclen > 2) { -+ memset(argv0, 0, maxproclen); -+ strncpy(argv0, buf, maxproclen - 2); -+ } - - return len; - } -@@ -448,7 +482,9 @@ - int tried_vtmaster = 0; - char *s; - -- if ((s = getenv("CONSOLE")) != NULL) -+ if (user_console) { -+ console_dev = user_console; -+ } else if ((s = getenv("CONSOLE")) != NULL) - console_dev = s; - else { - console_dev = CONSOLE; -@@ -528,10 +564,9 @@ - if (errno == ECHILD) break; - for( ch = family; ch; ch = ch->next ) - if ( ch->pid == pid && (ch->flags & RUNNING) ) { --#if DEBUG -- log(L_VB, "chld_handler: marked %d as zombie", -+ INITDBG(L_VB, -+ "chld_handler: marked %d as zombie", - ch->pid); --#endif - ADDSET(got_signals, SIGCHLD); - ch->exstat = st; - ch->flags |= ZOMBIE; -@@ -541,11 +576,9 @@ - } - break; - } --#if DEBUG - if (ch == NULL) -- log(L_VB, "chld_handler: unknown child %d exited.", -+ INITDBG(L_VB, "chld_handler: unknown child %d exited.", - pid); --#endif - } - errno = saved_errno; - } -@@ -563,28 +596,34 @@ - } - - /* -- * Dump core. Returns 0 if we are the child, so that the caller -- * can return if it is a signal handler - SIGSEGV is blocked in -- * the handler, so it will be raised when the handler returns. -+ * Fork and dump core in /. - */ --int coredump(void) -+void coredump(void) - { -- static int dumped = 0; -- struct rlimit rlim; -+ static int dumped = 0; -+ struct rlimit rlim; -+ sigset_t mask; - -- if (dumped) return 1; -+ if (dumped) return; - dumped = 1; - -- if (fork() != 0) return 1; -+ if (fork() != 0) return; -+ -+ sigfillset(&mask); -+ sigprocmask(SIG_SETMASK, &mask, NULL); - - rlim.rlim_cur = RLIM_INFINITY; - rlim.rlim_max = RLIM_INFINITY; - setrlimit(RLIMIT_CORE, &rlim); -- - chdir("/"); -+ - signal(SIGSEGV, SIG_DFL); - raise(SIGSEGV); -- return 0; -+ sigdelset(&mask, SIGSEGV); -+ sigprocmask(SIG_SETMASK, &mask, NULL); -+ -+ do_sleep(5); -+ exit(0); - } - - /* -@@ -592,7 +631,7 @@ - * If we have the info, print where it occured. - * Then sleep 30 seconds and try to continue. - */ --#ifdef STACK_DEBUG -+#if defined(STACK_DEBUG) && defined(__linux__) - void segv_handler(int sig, struct sigcontext ctx) - { - char *p = ""; -@@ -601,10 +640,10 @@ - if ((void *)ctx.eip >= (void *)do_sleep && - (void *)ctx.eip < (void *)main) - p = " (code)"; -- log(L_VB, "PANIC: segmentation violation at %p%s! " -+ initlog(L_VB, "PANIC: segmentation violation at %p%s! " - "sleeping for 30 seconds.", (void *)ctx.eip, p); -- if (coredump() != 0) -- do_sleep(30); -+ coredump(); -+ do_sleep(30); - errno = saved_errno; - } - #else -@@ -612,9 +651,10 @@ - { - int saved_errno = errno; - -- log(L_VB, "PANIC: segmentation violation! sleeping for 30 seconds."); -- if (coredump() != 0) -- do_sleep(30); -+ initlog(L_VB, -+ "PANIC: segmentation violation! sleeping for 30 seconds."); -+ coredump(); -+ do_sleep(30); - errno = saved_errno; - } - #endif -@@ -641,7 +681,7 @@ - int fd; - - if ((fd = console_open(O_RDWR|O_NOCTTY)) < 0) { -- log(L_VB, "can't open %s", console_dev); -+ initlog(L_VB, "can't open %s", console_dev); - return; - } - -@@ -697,10 +737,11 @@ - #ifdef __GNUC__ - __attribute__ ((format (printf, 2, 3))) - #endif --void log(int loglevel, char *s, ...) -+void initlog(int loglevel, char *s, ...) - { - va_list va_alist; - char buf[256]; -+ sigset_t nmask, omask; - - va_start(va_alist, s); - vsnprintf(buf, sizeof(buf), s, va_alist); -@@ -708,11 +749,15 @@ - - if (loglevel & L_SY) { - /* -- * Re-etablish connection with syslogd every time. -+ * Re-establish connection with syslogd every time. -+ * Block signals while talking to syslog. - */ -+ sigfillset(&nmask); -+ sigprocmask(SIG_BLOCK, &nmask, &omask); - openlog("init", 0, LOG_DAEMON); - syslog(LOG_INFO, "%s", buf); - closelog(); -+ sigprocmask(SIG_SETMASK, &omask, NULL); - } - - /* -@@ -727,14 +772,51 @@ - - - /* -- * See if one character of s2 is in s1 -+ * Build a new environment for execve(). - */ --int any(char *s1, char *s2) -+char **init_buildenv(int child) - { -- while(*s2) -- if (strchr(s1, *s2++) != NULL) -- return(1); -- return(0); -+ char i_lvl[] = "RUNLEVEL=x"; -+ char i_prev[] = "PREVLEVEL=x"; -+ char i_cons[32]; -+ char **e; -+ int n, i; -+ -+ for (n = 0; environ[n]; n++) -+ ; -+ n += NR_EXTRA_ENV + 8; -+ e = calloc(n, sizeof(char *)); -+ -+ for (n = 0; environ[n]; n++) -+ e[n] = istrdup(environ[n]); -+ -+ for (i = 0; i < NR_EXTRA_ENV; i++) -+ if (extra_env[i]) -+ e[n++] = istrdup(extra_env[i]); -+ -+ if (child) { -+ snprintf(i_cons, sizeof(i_cons), "CONSOLE=%s", console_dev); -+ i_lvl[9] = thislevel; -+ i_prev[10] = prevlevel; -+ e[n++] = istrdup(i_lvl); -+ e[n++] = istrdup(i_prev); -+ e[n++] = istrdup(i_cons); -+ e[n++] = istrdup(E_VERSION); -+ } -+ -+ e[n++] = NULL; -+ -+ return e; -+} -+ -+ -+void init_freeenv(char **e) -+{ -+ int n; -+ -+ for (n = 0; e[n]; n++) -+ free(e[n]); -+ free(e); - } - - -@@ -753,9 +835,6 @@ - time_t t; /* System time */ - int oldAlarm; /* Previous alarm value */ - char *proc = ch->process; /* Command line */ -- char i_lvl[] = "RUNLEVEL=x"; /* Runlevel in environment. */ -- char i_prev[] = "PREVLEVEL=x";/* Previous runlevel. */ -- char i_cons[32]; /* console device. */ - pid_t pid, pgrp; /* child, console process group. */ - sigset_t nmask, omask; /* For blocking SIGCHLD */ - struct sigaction sa; -@@ -781,8 +860,9 @@ - /* Do we try to respawn too fast? */ - if (ch->count >= MAXSPAWN) { - -- log(L_VB, "Id \"%s\" respawning too fast: disabled for %d minutes", -- ch->id, SLEEPTIME / 60); -+ initlog(L_VB, -+ "Id \"%s\" respawning too fast: disabled for %d minutes", -+ ch->id, SLEEPTIME / 60); - ch->flags &= ~RUNNING; - ch->flags |= FAILING; - -@@ -813,7 +893,7 @@ - } - args[6] = proc; - args[7] = NULL; -- } else if (any(proc, "~`!$^&*()=|\\{}[];\"'<>?")) { -+ } else if (strpbrk(proc, "~`!$^&*()=|\\{}[];\"'<>?")) { - /* See if we need to fire off a shell for this command */ - /* Give command line to shell */ - args[1] = SHELL; -@@ -868,15 +948,6 @@ - - sigprocmask(SIG_SETMASK, &omask, NULL); - -- /* Now set RUNLEVEL and PREVLEVEL */ -- snprintf(i_cons, sizeof(i_cons), "CONSOLE=%s", console_dev); -- i_lvl[9] = thislevel; -- i_prev[10] = prevlevel; -- putenv(i_lvl); -- putenv(i_prev); -- putenv(i_cons); -- putenv(E_VERSION); -- - /* - * In sysinit, boot, bootwait or single user mode: - * for any wait-type subprocess we _force_ the console -@@ -896,7 +967,7 @@ - dup(f); - } - if ((pid = fork()) < 0) { -- log(L_VB, "cannot fork"); -+ initlog(L_VB, "cannot fork"); - exit(1); - } - if (pid > 0) { -@@ -926,7 +997,7 @@ - * this with a temporary process. - */ - if ((pid = fork()) < 0) { -- log(L_VB, "cannot fork"); -+ initlog(L_VB, "cannot fork"); - exit(1); - } - if (pid == 0) { -@@ -946,7 +1017,7 @@ - } else { - setsid(); - if ((f = console_open(O_RDWR|O_NOCTTY)) < 0) { -- log(L_VB, "open(%s): %s", console_dev, -+ initlog(L_VB, "open(%s): %s", console_dev, - strerror(errno)); - f = open("/dev/null", O_RDWR); - } -@@ -954,15 +1025,15 @@ - dup(f); - } - -- /* Reset all the signals */ -+ /* Reset all the signals, set up environment */ - for(f = 1; f < NSIG; f++) SETSIG(sa, f, SIG_DFL, SA_RESTART); -- execvp(args[1], args + 1); -+ environ = init_buildenv(1); - - /* -- * Is this a bug in execvp? It does _not_ execute shell -- * scripts (/etc/rc !), so we try again with -- * 'sh -c exec ...' -+ * Execute prog. In case of ENOEXEC try again -+ * as a shell script. - */ -+ execvp(args[1], args + 1); - if (errno == ENOEXEC) { - args[1] = SHELL; - args[2] = "-c"; -@@ -972,18 +1043,16 @@ - args[4] = NULL; - execvp(args[1], args + 1); - } -- log(L_VB, "cannot execute \"%s\"", args[1]); -+ initlog(L_VB, "cannot execute \"%s\"", args[1]); - exit(1); - } - *res = pid; - sigprocmask(SIG_SETMASK, &omask, NULL); - --#if DEBUG -- log(L_VB, "Started id %s (pid %d)", ch->id, pid); --#endif -+ INITDBG(L_VB, "Started id %s (pid %d)", ch->id, pid); - - if (pid == -1) { -- log(L_VB, "cannot fork, retry.."); -+ initlog(L_VB, "cannot fork, retry.."); - do_sleep(5); - continue; - } -@@ -1032,66 +1101,45 @@ - } - } - --/* -- * My version of strtok(3). -- */ --char *get_part(char *str, int tok) --{ -- static char *s; -- char *p, *q; -- -- if (str != NULL) -- s = str; -- if (s == NULL || *s == 0) -- return(NULL); -- q = p = s; -- while(*p != tok && *p) -- p++; -- if (*p == tok) -- *p++ = 0; -- s = p; -- -- return q; --} - - /* - * Read the inittab file. - */ - void read_inittab(void) - { -- FILE *fp; /* The INITTAB file */ -- char buf[256]; /* Line buffer */ -- char err[64]; /* Error message. */ -- char *id, *rlevel, -- *action, *process; /* Fields of a line */ -- char *p; -- CHILD *ch, *old, *i; /* Pointers to CHILD structure */ -- CHILD *head = NULL; /* Head of linked list */ -- int lineNo = 0; /* Line number in INITTAB file */ -- int actionNo; /* Decoded action field */ -- int f; /* Counter */ -- int round; /* round 0 for SIGTERM, round 1 for SIGKILL */ -- int foundOne = 0; /* No killing no sleep */ -- int talk; /* Talk to the user */ -- int done = 0; /* Ready yet? */ -- sigset_t nmask, omask; /* For blocking SIGCHLD. */ -+ FILE *fp; /* The INITTAB file */ -+ CHILD *ch, *old, *i; /* Pointers to CHILD structure */ -+ CHILD *head = NULL; /* Head of linked list */ - #ifdef INITLVL -- struct stat st; /* To stat INITLVL */ -+ struct stat st; /* To stat INITLVL */ - #endif -+ sigset_t nmask, omask; /* For blocking SIGCHLD. */ -+ char buf[256]; /* Line buffer */ -+ char err[64]; /* Error message. */ -+ char *id, *rlevel, -+ *action, *process; /* Fields of a line */ -+ char *p; -+ int lineNo = 0; /* Line number in INITTAB file */ -+ int actionNo; /* Decoded action field */ -+ int f; /* Counter */ -+ int round; /* round 0 for SIGTERM, 1 for SIGKILL */ -+ int foundOne = 0; /* No killing no sleep */ -+ int talk; /* Talk to the user */ -+ int done = 0; /* Ready yet? */ - - #if DEBUG - if (newFamily != NULL) { -- log(L_VB, "PANIC newFamily != NULL"); -+ INITDBG(L_VB, "PANIC newFamily != NULL"); - exit(1); - } -- log(L_VB, "Reading inittab"); -+ INITDBG(L_VB, "Reading inittab"); - #endif - - /* - * Open INITTAB and real line by line. - */ - if ((fp = fopen(INITTAB, "r")) == NULL) -- log(L_VB, "No inittab file found"); -+ initlog(L_VB, "No inittab file found"); - - while(!done) { - /* -@@ -1103,9 +1151,9 @@ - * See if we have a single user entry. - */ - for(old = newFamily; old; old = old->next) -- if (strcmp(old->rlevel, "S") == 0) break; -+ if (strpbrk(old->rlevel, "S")) break; - if (old == NULL) -- snprintf(buf, sizeof(buf), "~~:S:wait:%s\n", SHELL); -+ snprintf(buf, sizeof(buf), "~~:S:wait:%s\n", SULOGIN); - else - continue; - } -@@ -1120,10 +1168,10 @@ - /* - * Decode the fields - */ -- id = get_part(p, ':'); -- rlevel = get_part(NULL, ':'); -- action = get_part(NULL, ':'); -- process = get_part(NULL, '\n'); -+ id = strsep(&p, ":"); -+ rlevel = strsep(&p, ":"); -+ action = strsep(&p, ":"); -+ process = strsep(&p, "\n"); - - /* - * Check if syntax is OK. Be very verbose here, to -@@ -1145,10 +1193,8 @@ - if (action && strlen(action) > 32) - strcpy(err, "action field too long"); - if (err[0] != 0) { -- log(L_VB, "%s[%d]: %s", INITTAB, lineNo, err); --#if DEBUG -- log(L_VB, "%s:%s:%s:%s", id, rlevel, action, process); --#endif -+ initlog(L_VB, "%s[%d]: %s", INITTAB, lineNo, err); -+ INITDBG(L_VB, "%s:%s:%s:%s", id, rlevel, action, process); - continue; - } - -@@ -1162,7 +1208,7 @@ - break; - } - if (actionNo == -1) { -- log(L_VB, "%s[%d]: %s: unknown action field", -+ initlog(L_VB, "%s[%d]: %s: unknown action field", - INITTAB, lineNo, action); - continue; - } -@@ -1172,7 +1218,7 @@ - */ - for(old = newFamily; old; old = old->next) { - if(strcmp(old->id, id) == 0 && strcmp(id, "~~")) { -- log(L_VB, "%s[%d]: duplicate ID field \"%s\"", -+ initlog(L_VB, "%s[%d]: duplicate ID field \"%s\"", - INITTAB, lineNo, id); - break; - } -@@ -1182,11 +1228,7 @@ - /* - * Allocate a CHILD structure - */ -- while ((ch = malloc(sizeof(CHILD))) == NULL) { -- log(L_VB, "out of memory"); -- do_sleep(5); -- } -- memset(ch, 0, sizeof(CHILD)); -+ ch = imalloc(sizeof(CHILD)); - - /* - * And fill it in. -@@ -1275,9 +1317,7 @@ - * be killed. - */ - --#if DEBUG -- log(L_VB, "Checking for children to kill"); --#endif -+ INITDBG(L_VB, "Checking for children to kill"); - for(round = 0; round < 2; round++) { - talk = 1; - for(ch = family; ch; ch = ch->next) { -@@ -1328,19 +1368,19 @@ - ch->flags &= ~KILLME; - continue; - } --#if DEBUG -- log(L_VB, "Killing \"%s\"", ch->process); --#endif -+ INITDBG(L_VB, "Killing \"%s\"", ch->process); - switch(round) { - case 0: /* Send TERM signal */ - if (talk) -- log(L_CO, "Sending processes the TERM signal"); -+ initlog(L_CO, -+ "Sending processes the TERM signal"); - kill(-(ch->pid), SIGTERM); - foundOne = 1; - break; - case 1: /* Send KILL signal and collect status */ - if (talk) -- log(L_CO, "Sending processes the KILL signal"); -+ initlog(L_CO, -+ "Sending processes the KILL signal"); - kill(-(ch->pid), SIGKILL); - break; - } -@@ -1380,12 +1420,11 @@ - for(ch = family; ch; ch = ch->next) - if (ch->flags & KILLME) { - if (!(ch->flags & ZOMBIE)) -- log(L_CO, "Pid %d [id %s] seems to hang", ch->pid, -+ initlog(L_CO, "Pid %d [id %s] seems to hang", ch->pid, - ch->id); - else { --#if DEBUG -- log(L_VB, "Updating utmp for pid %d [id %s]", ch->pid, ch->id); --#endif -+ INITDBG(L_VB, "Updating utmp for pid %d [id %s]", -+ ch->pid, ch->id); - ch->flags &= ~RUNNING; - if (ch->process[0] != '+') - write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL); -@@ -1451,15 +1490,13 @@ - CHILD *ch; /* Pointer to child */ - int delete; /* Delete this entry from list? */ - --#if DEBUG -- log(L_VB, "Checking for children to start"); --#endif -+ INITDBG(L_VB, "Checking for children to start"); - - for(ch = family; ch; ch = ch->next) { - - #if DEBUG - if (ch->rlevel[0] == 'C') { -- log(L_VB, "%s: flags %d", ch->process, ch->flags); -+ INITDBG(L_VB, "%s: flags %d", ch->process, ch->flags); - } - #endif - -@@ -1545,7 +1582,8 @@ - if (lvl > 0) { - if (islower(lvl)) lvl = toupper(lvl); - if (strchr("0123456789S", lvl) == NULL) { -- log(L_VB, "Initdefault level '%c' is invalid", lvl); -+ initlog(L_VB, -+ "Initdefault level '%c' is invalid", lvl); - lvl = 0; - } - } -@@ -1570,98 +1608,99 @@ - */ - int read_level(int arg) - { -- unsigned char foo = 'X'; /* Contents of INITLVL */ -- CHILD *ch; /* Walk through list */ -- int ok = 1; -+ CHILD *ch; /* Walk through list */ -+ unsigned char foo = 'X'; /* Contents of INITLVL */ -+ int ok = 1; - #ifdef INITLVL -- FILE *fp; -- int st; -- struct stat stt; -+ FILE *fp; -+ struct stat stt; -+ int st; - #endif - -- if (arg) foo = arg; -+ if (arg) foo = arg; - - #ifdef INITLVL -- ok = 0; -+ ok = 0; - -- if (arg == 0) { -- fp = NULL; -- if (stat(INITLVL, &stt) != 0 || stt.st_size != 0L) -- fp = fopen(INITLVL, "r"); -+ if (arg == 0) { -+ fp = NULL; -+ if (stat(INITLVL, &stt) != 0 || stt.st_size != 0L) -+ fp = fopen(INITLVL, "r"); - #ifdef INITLVL2 -- if (fp == NULL && (stat(INITLVL2, &stt) != 0 || stt.st_size != 0L)) -- fp = fopen(INITLVL2, "r"); -+ if (fp == NULL && -+ (stat(INITLVL2, &stt) != 0 || stt.st_size != 0L)) -+ fp = fopen(INITLVL2, "r"); - #endif -- if (fp == NULL) { -- /* INITLVL file is empty or not there - act as 'init q' */ -- log(L_SY, "Re-reading inittab"); -- return(runlevel); -+ if (fp == NULL) { -+ /* INITLVL file empty or not there - act as 'init q' */ -+ initlog(L_SY, "Re-reading inittab"); -+ return(runlevel); -+ } -+ ok = fscanf(fp, "%c %d", &foo, &st); -+ fclose(fp); -+ } else { -+ /* We go to the new runlevel passed as an argument. */ -+ foo = arg; -+ ok = 1; - } -- ok = fscanf(fp, "%c %d", &foo, &st); -- fclose(fp); -- } else { -- /* We go to the new runlevel passed as an argument. */ -- foo = arg; -- ok = 1; -- } -- if (ok == 2) sltime = st; -+ if (ok == 2) sltime = st; - - #endif /* INITLVL */ - -- if (islower(foo)) foo = toupper(foo); -- if (ok < 1 || ok > 2 || strchr("QS0123456789ABCU", foo) == NULL) { -- log(L_VB, "bad runlevel: %c", foo); -- return(runlevel); -- } -+ if (islower(foo)) foo = toupper(foo); -+ if (ok < 1 || ok > 2 || strchr("QS0123456789ABCU", foo) == NULL) { -+ initlog(L_VB, "bad runlevel: %c", foo); -+ return runlevel; -+ } - -- /* Log this action */ -- switch(foo) { -- case 'S': -- log(L_VB, "Going single user"); -- break; -- case 'Q': -- log(L_SY, "Re-reading inittab"); -- break; -- case 'A': -- case 'B': -- case 'C': -- log(L_SY, "Activating demand-procedures for '%c'", foo); -- break; -- case 'U': -- log(L_SY, "Trying to re-exec init"); -- return 'U'; -- default: -- log(L_VB, "Switching to runlevel: %c", foo); -- } -+ /* Log this action */ -+ switch(foo) { -+ case 'S': -+ initlog(L_VB, "Going single user"); -+ break; -+ case 'Q': -+ initlog(L_SY, "Re-reading inittab"); -+ break; -+ case 'A': -+ case 'B': -+ case 'C': -+ initlog(L_SY, -+ "Activating demand-procedures for '%c'", foo); -+ break; -+ case 'U': -+ initlog(L_SY, "Trying to re-exec init"); -+ return 'U'; -+ default: -+ initlog(L_VB, "Switching to runlevel: %c", foo); -+ } - -- if (foo == 'Q') return(runlevel); -+ if (foo == 'Q') return runlevel; - -- /* Check if this is a runlevel a, b or c */ -- if (strchr("ABC", foo)) { -- if (runlevel == 'S') return(runlevel); -+ /* Check if this is a runlevel a, b or c */ -+ if (strchr("ABC", foo)) { -+ if (runlevel == 'S') return(runlevel); - -- /* Read inittab again first! */ -- read_inittab(); -+ /* Read inittab again first! */ -+ read_inittab(); - -- /* Mark those special tasks */ -- for(ch = family; ch; ch = ch->next) -- if (strchr(ch->rlevel, foo) != NULL || -- strchr(ch->rlevel, tolower(foo)) != NULL) { -- ch->flags |= DEMAND; -- ch->flags &= ~XECUTED; --#if DEBUG -- log(L_VB, "Marking (%s) as ondemand, flags %d", -- ch->id, ch->flags); --#endif -- } -- return(runlevel); -- } -+ /* Mark those special tasks */ -+ for(ch = family; ch; ch = ch->next) -+ if (strchr(ch->rlevel, foo) != NULL || -+ strchr(ch->rlevel, tolower(foo)) != NULL) { -+ ch->flags |= DEMAND; -+ ch->flags &= ~XECUTED; -+ INITDBG(L_VB, -+ "Marking (%s) as ondemand, flags %d", -+ ch->id, ch->flags); -+ } -+ return runlevel; -+ } - -- /* Store both the old and the new runlevel. */ -- write_utmp_wtmp("runlevel", "~~", foo + 256*runlevel, RUN_LVL, "~"); -- thislevel = foo; -- prevlevel = runlevel; -- return(foo); -+ /* Store both the old and the new runlevel. */ -+ write_utmp_wtmp("runlevel", "~~", foo + 256*runlevel, RUN_LVL, "~"); -+ thislevel = foo; -+ prevlevel = runlevel; -+ return foo; - } - - -@@ -1674,32 +1713,33 @@ - */ - void fail_check(void) - { -- time_t t; /* System time */ -- CHILD *ch; /* Pointer to child structure */ -- time_t next_alarm = 0; /* When to set next alarm */ -+ CHILD *ch; /* Pointer to child structure */ -+ time_t t; /* System time */ -+ time_t next_alarm = 0; /* When to set next alarm */ - -- time(&t); -+ time(&t); - -- for(ch = family; ch; ch = ch->next) { -+ for(ch = family; ch; ch = ch->next) { - -- if (ch->flags & FAILING) { -- /* Can we free this sucker? */ -- if (ch->tm + SLEEPTIME < t) { -- ch->flags &= ~FAILING; -- ch->count = 0; -- ch->tm = 0; -- } else { -- /* No, we'll look again later */ -- if (next_alarm == 0 || ch->tm + SLEEPTIME > next_alarm) -- next_alarm = ch->tm + SLEEPTIME; -+ if (ch->flags & FAILING) { -+ /* Can we free this sucker? */ -+ if (ch->tm + SLEEPTIME < t) { -+ ch->flags &= ~FAILING; -+ ch->count = 0; -+ ch->tm = 0; -+ } else { -+ /* No, we'll look again later */ -+ if (next_alarm == 0 || -+ ch->tm + SLEEPTIME > next_alarm) -+ next_alarm = ch->tm + SLEEPTIME; -+ } - } - } -- } -- if (next_alarm) { -- next_alarm -= t; -- if (next_alarm < 1) next_alarm = 1; -- alarm(next_alarm); -- } -+ if (next_alarm) { -+ next_alarm -= t; -+ if (next_alarm < 1) next_alarm = 1; -+ alarm(next_alarm); -+ } - } - - /* Set all 'Fail' timers to 0 */ -@@ -1752,9 +1792,9 @@ - */ - int check_pipe(int fd) - { -- struct timeval t; -- fd_set s; -- char signature[8]; -+ struct timeval t; -+ fd_set s; -+ char signature[8]; - - FD_ZERO(&s); - FD_SET(fd, &s); -@@ -1789,10 +1829,11 @@ - */ - void re_exec(void) - { -- sigset_t mask, oldset; -- pid_t pid; -- int fd; -- CHILD *ch; -+ CHILD *ch; -+ sigset_t mask, oldset; -+ pid_t pid; -+ char **env; -+ int fd; - - if (strchr("S12345",runlevel) == NULL) - return; -@@ -1825,27 +1866,26 @@ - */ - for(ch = family; ch; ch = ch->next) - if (ch->flags & ZOMBIE) { --#if DEBUG -- log(L_VB, "Child died, PID= %d", ch->pid); --#endif -+ INITDBG(L_VB, "Child died, PID= %d", ch->pid); - ch->flags &= ~(RUNNING|ZOMBIE|WAITING); - if (ch->process[0] != '+') - write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL); - } - -- if ((pid = fork()) > 0) { -- /* -- * Yup. _Parent_ exec's ... -- */ -- execl(myname, myname, "--init", NULL); -- } else if (pid == 0) { -+ if ((pid = fork()) == 0) { - /* -- * ... while child sends her the -- * state information and dies -+ * Child sends state information to the parent. - */ - send_state(fd); - exit(0); - } -+ -+ /* -+ * The existing init process execs a new init binary. -+ */ -+ env = init_buildenv(0); -+ execl(myname, myname, "--init", NULL, env); -+ - /* - * We shouldn't be here, something failed. - * Bitch, close the state pipe, unblock signals and return. -@@ -1853,7 +1893,8 @@ - close(fd); - close(STATE_PIPE); - sigprocmask(SIG_SETMASK, &oldset, NULL); -- log(L_CO, "Attempt to re-exec failed"); -+ init_freeenv(env); -+ initlog(L_CO, "Attempt to re-exec failed"); - } - - -@@ -1863,10 +1904,10 @@ - */ - void fifo_new_level(int level) - { -- int oldlevel; - #if CHANGE_WAIT -- CHILD *ch; -+ CHILD *ch; - #endif -+ int oldlevel; - - if (level == runlevel) return; - -@@ -1894,6 +1935,59 @@ - } - } - -+ -+/* -+ * Set/unset environment variables. The variables are -+ * encoded as KEY=VAL\0KEY=VAL\0\0. With "=VAL" it means -+ * setenv, without it means unsetenv. -+ */ -+void initcmd_setenv(char *data, int size) -+{ -+ char *env, *p, *e, *eq; -+ int i, sz; -+ -+ e = data + size; -+ -+ while (*data && data < e) { -+ eq = NULL; -+ for (p = data; *p && p < e; p++) -+ if (*p == '=') eq = p; -+ if (*p) break; -+ env = data; -+ data = ++p; -+ -+ sz = eq ? (eq - env) : (p - env); -+ -+ /*initlog(L_SY, "init_setenv: %s, %s, %d", env, eq, sz);*/ -+ -+ /* -+ * We only allow INIT_* to be set. -+ */ -+ if (strncmp(env, "INIT_", 5) != 0) -+ continue; -+ -+ /* Free existing vars. */ -+ for (i = 0; i < NR_EXTRA_ENV; i++) { -+ if (extra_env[i] == NULL) continue; -+ if (!strncmp(extra_env[i], env, sz) && -+ extra_env[i][sz] == '=') { -+ free(extra_env[i]); -+ extra_env[i] = NULL; -+ } -+ } -+ -+ /* Set new vars if needed. */ -+ if (eq == NULL) continue; -+ for (i = 0; i < NR_EXTRA_ENV; i++) { -+ if (extra_env[i] == NULL) { -+ extra_env[i] = istrdup(env); -+ break; -+ } -+ } -+ } -+} -+ -+ - /* - * Read from the init FIFO. Processes like telnetd and rlogind can - * ask us to create login processes on their behalf. -@@ -1906,12 +2000,12 @@ - */ - void check_init_fifo(void) - { -- struct init_request request; -- int n; -- fd_set fds; -- int quit = 0; -- struct stat st, st2; -- struct timeval tv; -+ struct init_request request; -+ struct timeval tv; -+ struct stat st, st2; -+ fd_set fds; -+ int n; -+ int quit = 0; - - /* - * First, try to create /dev/initctl if not present. -@@ -1940,7 +2034,7 @@ - if ((pipe_fd = open(INIT_FIFO, O_RDWR|O_NONBLOCK)) >= 0) { - fstat(pipe_fd, &st); - if (!S_ISFIFO(st.st_mode)) { -- log(L_VB, "%s is not a fifo", INIT_FIFO); -+ initlog(L_VB, "%s is not a fifo", INIT_FIFO); - close(pipe_fd); - pipe_fd = -1; - } -@@ -1987,7 +2081,7 @@ - } - if (n <= 0) { - if (errno == EINTR) return; -- log(L_VB, "error reading initrequest"); -+ initlog(L_VB, "error reading initrequest"); - continue; - } - -@@ -2001,7 +2095,7 @@ - * Process request. - */ - if (request.magic != INIT_MAGIC || n != sizeof(request)) { -- log(L_VB, "got bogus initrequest"); -+ initlog(L_VB, "got bogus initrequest"); - continue; - } - switch(request.cmd) { -@@ -2025,8 +2119,23 @@ - do_power_fail('O'); - quit = 1; - break; -+ case INIT_CMD_SETENV: -+ initcmd_setenv(request.i.data, sizeof(request.i.data)); -+ break; -+ case INIT_CMD_CHANGECONS: -+ if (user_console) { -+ free(user_console); -+ user_console = NULL; -+ } -+ if (!request.i.bsd.reserved[0]) -+ user_console = NULL; -+ else -+ user_console = strdup(request.i.bsd.reserved); -+ console_init(); -+ quit = 1; -+ break; - default: -- log(L_VB, "got unimplemented initrequest."); -+ initlog(L_VB, "got unimplemented initrequest."); - break; - } - } -@@ -2045,11 +2154,11 @@ - */ - void boot_transitions() - { -- CHILD *ch; -- static int newlevel = 0; -- int loglevel; -- int oldlevel; -- static int warn = 1; -+ CHILD *ch; -+ static int newlevel = 0; -+ static int warn = 1; -+ int loglevel; -+ int oldlevel; - - /* Check if there is something to wait for! */ - for( ch = family; ch; ch = ch->next ) -@@ -2061,9 +2170,7 @@ - oldlevel = 'N'; - switch(runlevel) { - case '#': /* SYSINIT -> BOOT */ --#if DEBUG -- log(L_VB, "SYSINIT -> BOOT"); --#endif -+ INITDBG(L_VB, "SYSINIT -> BOOT"); - - /* Write a boot record. */ - wrote_utmp_reboot = 0; -@@ -2080,9 +2187,7 @@ - runlevel = '*'; - break; - case '*': /* BOOT -> NORMAL */ --#if DEBUG -- log(L_VB, "BOOT -> NORMAL"); --#endif -+ INITDBG(L_VB, "BOOT -> NORMAL"); - if (runlevel != newlevel) - loglevel = newlevel; - runlevel = newlevel; -@@ -2091,9 +2196,7 @@ - break; - case 'S': /* Ended SU mode */ - case 's': --#if DEBUG -- log(L_VB, "END SU MODE"); --#endif -+ INITDBG(L_VB, "END SU MODE"); - newlevel = get_init_default(); - if (!did_boot && newlevel != 'S') - runlevel = '*'; -@@ -2110,7 +2213,8 @@ - break; - default: - if (warn) -- log(L_VB, "no more processes left in this runlevel"); -+ initlog(L_VB, -+ "no more processes left in this runlevel"); - warn = 0; - loglevel = -1; - if (got_signals == 0) -@@ -2118,7 +2222,7 @@ - break; - } - if (loglevel > 0) { -- log(L_VB, "Entering runlevel: %c", runlevel); -+ initlog(L_VB, "Entering runlevel: %c", runlevel); - write_utmp_wtmp("runlevel", "~~", runlevel + 256 * oldlevel, RUN_LVL, "~"); - thislevel = runlevel; - prevlevel = oldlevel; -@@ -2133,16 +2237,14 @@ - */ - void process_signals() - { -- int pwrstat; -- int oldlevel; -- int fd; -- CHILD *ch; -- char c; -+ CHILD *ch; -+ int pwrstat; -+ int oldlevel; -+ int fd; -+ char c; - - if (ISMEMBER(got_signals, SIGPWR)) { --#if DEBUG -- log(L_VB, "got SIGPWR"); --#endif -+ INITDBG(L_VB, "got SIGPWR"); - /* See _what_ kind of SIGPWR this is. */ - pwrstat = 0; - if ((fd = open(PWRSTAT, O_RDONLY)) >= 0) { -@@ -2157,9 +2259,7 @@ - } - - if (ISMEMBER(got_signals, SIGINT)) { --#if DEBUG -- log(L_VB, "got SIGINT"); --#endif -+ INITDBG(L_VB, "got SIGINT"); - /* Tell ctrlaltdel entry to start up */ - for(ch = family; ch; ch = ch->next) - if (ch->action == CTRLALTDEL) -@@ -2168,9 +2268,7 @@ - } - - if (ISMEMBER(got_signals, SIGWINCH)) { --#if DEBUG -- log(L_VB, "got SIGWINCH"); --#endif -+ INITDBG(L_VB, "got SIGWINCH"); - /* Tell kbrequest entry to start up */ - for(ch = family; ch; ch = ch->next) - if (ch->action == KBREQUEST) -@@ -2179,26 +2277,20 @@ - } - - if (ISMEMBER(got_signals, SIGALRM)) { --#if DEBUG -- log(L_VB, "got SIGALRM"); --#endif -+ INITDBG(L_VB, "got SIGALRM"); - /* The timer went off: check it out */ - DELSET(got_signals, SIGALRM); - } - - if (ISMEMBER(got_signals, SIGCHLD)) { --#if DEBUG -- log(L_VB, "got SIGCHLD"); --#endif -+ INITDBG(L_VB, "got SIGCHLD"); - /* First set flag to 0 */ - DELSET(got_signals, SIGCHLD); - - /* See which child this was */ - for(ch = family; ch; ch = ch->next) - if (ch->flags & ZOMBIE) { --#if DEBUG -- log(L_VB, "Child died, PID= %d", ch->pid); --#endif -+ INITDBG(L_VB, "Child died, PID= %d", ch->pid); - ch->flags &= ~(RUNNING|ZOMBIE|WAITING); - if (ch->process[0] != '+') - write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL); -@@ -2207,9 +2299,7 @@ - } - - if (ISMEMBER(got_signals, SIGHUP)) { --#if DEBUG -- log(L_VB, "got SIGHUP"); --#endif -+ INITDBG(L_VB, "got SIGHUP"); - #if CHANGE_WAIT - /* Are we waiting for a child? */ - for(ch = family; ch; ch = ch->next) -@@ -2240,9 +2330,7 @@ - /* - * SIGUSR1 means close and reopen /dev/initctl - */ --#if DEBUG -- log(L_VB, "got SIGUSR1"); --#endif -+ INITDBG(L_VB, "got SIGUSR1"); - close(pipe_fd); - pipe_fd = -1; - DELSET(got_signals, SIGUSR1); -@@ -2254,11 +2342,11 @@ - */ - int init_main() - { -- int f, st; -- pid_t rc; -- CHILD *ch; -- sigset_t sgt; -- struct sigaction sa; -+ CHILD *ch; -+ struct sigaction sa; -+ sigset_t sgt; -+ pid_t rc; -+ int f, st; - - if (!reload) { - -@@ -2278,6 +2366,7 @@ - } - #endif - -+#ifdef __linux__ - /* - * Tell the kernel to send us SIGINT when CTRL-ALT-DEL - * is pressed, and that we want to handle keyboard signals. -@@ -2288,6 +2377,7 @@ - close(f); - } else - (void) ioctl(0, KDSIGACCEPT, SIGWINCH); -+#endif - - /* - * Ignore all signals. -@@ -2320,9 +2410,9 @@ - setsid(); - - /* -- * Set default PATH variable (for ksh) -+ * Set default PATH variable. - */ -- if (getenv("PATH") == NULL) putenv(PATH_DFL); -+ putenv(PATH_DFL); - - /* - * Initialize /var/run/utmp (only works if /var is on -@@ -2333,7 +2423,7 @@ - /* - * Say hello to the world - */ -- log(L_CO, bootmsg, "booting"); -+ initlog(L_CO, bootmsg, "booting"); - - /* - * See if we have to start an emergency shell. -@@ -2358,7 +2448,7 @@ - /* - * Restart: unblock signals and let the show go on - */ -- log(L_CO, bootmsg, "reloading"); -+ initlog(L_CO, bootmsg, "reloading"); - sigfillset(&sgt); - sigprocmask(SIG_UNBLOCK, &sgt, NULL); - } -@@ -2368,9 +2458,7 @@ - - /* See if we need to make the boot transitions. */ - boot_transitions(); --#if DEBUG -- log(L_VB, "init_main: waiting.."); --#endif -+ INITDBG(L_VB, "init_main: waiting.."); - - /* Check if there are processes to be waited on. */ - for(ch = family; ch; ch = ch->next) -@@ -2405,10 +2493,10 @@ - /* - * Tell the user about the syntax we expect. - */ --void Usage(char *s) -+void usage(char *s) - { -- fprintf(stderr, "Usage: %s 0123456SsQqAaBbCcUu\n", s); -- exit(1); -+ fprintf(stderr, "Usage: %s 0123456SsQqAaBbCcUu\n", s); -+ exit(1); - } - - int telinit(char *progname, int argc, char **argv) -@@ -2418,28 +2506,51 @@ - #endif - struct init_request request; - struct sigaction sa; -- int f, fd; -+ int f, fd, l; -+ char *env = NULL; - -- while((f = getopt(argc, argv, "t:")) != EOF) switch(f) { -+ memset(&request, 0, sizeof(request)); -+ request.magic = INIT_MAGIC; -+ -+ while ((f = getopt(argc, argv, "t:e:")) != EOF) switch(f) { - case 't': - sltime = atoi(optarg); - break; -+ case 'e': -+ if (env == NULL) -+ env = request.i.data; -+ l = strlen(optarg); -+ if (env + l + 2 > request.i.data + sizeof(request.i.data)) { -+ fprintf(stderr, "%s: -e option data " -+ "too large\n", progname); -+ exit(1); -+ } -+ memcpy(env, optarg, l); -+ env += l; -+ *env++ = 0; -+ break; - default: -- Usage(progname); -+ usage(progname); - break; - } - -- /* Check syntax. */ -- if (argc - optind != 1 || strlen(argv[optind]) != 1) Usage(progname); -- if (!strchr("0123456789SsQqAaBbCcUu", argv[optind][0])) Usage(progname); -+ if (env) *env++ = 0; - -- /* Open the fifo and write a command. */ -- memset(&request, 0, sizeof(request)); -- request.magic = INIT_MAGIC; -- request.cmd = INIT_CMD_RUNLVL; -- request.runlevel = argv[optind][0]; -- request.sleeptime = sltime; -+ if (env) { -+ if (argc != optind) -+ usage(progname); -+ request.cmd = INIT_CMD_SETENV; -+ } else { -+ if (argc - optind != 1 || strlen(argv[optind]) != 1) -+ usage(progname); -+ if (!strchr("0123456789SsQqAaBbCcUu", argv[optind][0])) -+ usage(progname); -+ request.cmd = INIT_CMD_RUNLVL; -+ request.runlevel = env ? 0 : argv[optind][0]; -+ request.sleeptime = sltime; -+ } - -+ /* Open the fifo and write a command. */ - /* Make sure we don't hang on opening /dev/initctl */ - SETSIG(sa, SIGALRM, signal_handler, 0); - alarm(3); -@@ -2449,7 +2560,27 @@ - alarm(0); - return 0; - } --#ifndef TELINIT_USES_INITLVL -+ -+#ifdef TELINIT_USES_INITLVL -+ if (request.cmd == INIT_CMD_RUNLVL) { -+ /* Fallthrough to the old method. */ -+ -+ /* Now write the new runlevel. */ -+ if ((fp = fopen(INITLVL, "w")) == NULL) { -+ fprintf(stderr, "%s: cannot create %s\n", -+ progname, INITLVL); -+ exit(1); -+ } -+ fprintf(fp, "%s %d", argv[optind], sltime); -+ fclose(fp); -+ -+ /* And tell init about the pending runlevel change. */ -+ if (kill(INITPID, SIGHUP) < 0) perror(progname); -+ -+ return 0; -+ } -+#endif -+ - fprintf(stderr, "%s: ", progname); - if (ISMEMBER(got_signals, SIGALRM)) { - fprintf(stderr, "timeout opening/writing control channel %s\n", -@@ -2458,24 +2589,6 @@ - perror(INIT_FIFO); - } - return 1; --#endif -- -- /* Fallthrough to the old method. */ -- --#ifdef TELINIT_USES_INITLVL -- /* Now write the new runlevel. */ -- if ((fp = fopen(INITLVL, "w")) == NULL) { -- fprintf(stderr, "%s: cannot create %s\n", progname, INITLVL); -- exit(1); -- } -- fprintf(fp, "%s %d", argv[optind], sltime); -- fclose(fp); -- -- /* And tell init about the pending runlevel change. */ -- if (kill(INITPID, SIGHUP) < 0) perror(progname); -- -- return 0; --#endif - } - - /* -@@ -2518,7 +2631,7 @@ - - receive_state(STATE_PIPE); - -- myname = strdup(argv[0]); -+ myname = istrdup(argv[0]); - argv0 = argv[0]; - maxproclen = 0; - for (f = 0; f < argc; f++) -diff -urNd -urNd sysvinit-2.85/src/init.h sysvinit-2.86/src/init.h ---- sysvinit-2.85/src/init.h 1999-06-03 14:22:59.000000000 -0500 -+++ sysvinit-2.86/src/init.h 2004-07-29 06:21:01.000000000 -0500 -@@ -2,9 +2,8 @@ - * init.h Several defines and declarations to be - * included by all modules of the init program. - * -- * Version: @(#)init.h 2.74 09-Mar-1998 miquels@cistron.nl -+ * Version: @(#)init.h 2.85-5 02-Jul-2003 miquels@cistron.nl - * -- * Modified: Re-exec patch; 24 Feb 1998, Al Viro. - */ - - /* Standard configuration */ -@@ -24,17 +23,26 @@ - #define TESTTIME 120 /* this much seconds */ - #define SLEEPTIME 300 /* Disable time */ - --/* Default path inherited by every child if it's not set. */ --#define PATH_DFL "PATH=/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin" -+/* Default path inherited by every child. */ -+#define PATH_DFL "PATH=/bin:/usr/bin:/sbin:/usr/sbin" - - - /* Prototypes. */ - void write_utmp_wtmp(char *user, char *id, int pid, int type, char *line); - void write_wtmp(char *user, char *id, int pid, int type, char *line); --void log(int loglevel, char *fmt, ...); -+#ifdef __GNUC__ -+__attribute__ ((format (printf, 2, 3))) -+#endif -+void initlog(int loglevel, char *fmt, ...); - void set_term(int how); - void print(char *fmt); - -+#if DEBUG -+# define INITDBG(level, fmt, args...) initlog(level, fmt, ##args) -+#else -+# define INITDBG(level, fmt, args...) -+#endif -+ - /* Actions to be taken by init */ - #define RESPAWN 1 - #define WAIT 2 -Binary files sysvinit-2.85/src/init.o and sysvinit-2.86/src/init.o differ -Binary files sysvinit-2.85/src/init_utmp.o and sysvinit-2.86/src/init_utmp.o differ -diff -urNd -urNd sysvinit-2.85/src/initreq.h sysvinit-2.86/src/initreq.h ---- sysvinit-2.85/src/initreq.h 1996-01-02 12:22:06.000000000 -0600 -+++ sysvinit-2.86/src/initreq.h 2004-07-30 06:56:51.000000000 -0500 -@@ -1,41 +1,77 @@ - /* -- * initreq.h Interface to let init spawn programs on behalf of -- * other programs/daemons. -- * Definitions based on sys_term.c from the BSD 4.4 -- * telnetd source. -+ * initreq.h Interface to talk to init through /dev/initctl. - * -- * Version: @(#)initreq.h 1.25 28-Dec-1995 MvS -+ * Copyright (C) 1995-2004 Miquel van Smoorenburg -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * Version: @(#)initreq.h 1.28 31-Mar-2004 MvS - * -- * Notes: Implemented in sysvinit-2.58 and up, but only -- * for "telinit". Support for rlogind, telnetd -- * and rxvt/xterm will follow shortly. - */ - #ifndef _INITREQ_H - #define _INITREQ_H - - #include <sys/param.h> - -+#if defined(__FreeBSD_kernel__) -+# define INIT_FIFO "/etc/.initctl" -+#else -+# define INIT_FIFO "/dev/initctl" -+#endif -+ - #define INIT_MAGIC 0x03091969 --#define INIT_FIFO "/dev/initctl" --#define INIT_CMD_START 0 --#define INIT_CMD_RUNLVL 1 --#define INIT_CMD_POWERFAIL 2 --#define INIT_CMD_POWERFAILNOW 3 --#define INIT_CMD_POWEROK 4 -+#define INIT_CMD_START 0 -+#define INIT_CMD_RUNLVL 1 -+#define INIT_CMD_POWERFAIL 2 -+#define INIT_CMD_POWERFAILNOW 3 -+#define INIT_CMD_POWEROK 4 -+#define INIT_CMD_BSD 5 -+#define INIT_CMD_SETENV 6 -+#define INIT_CMD_UNSETENV 7 -+ -+#define INIT_CMD_CHANGECONS 12345 -+ -+#ifdef MAXHOSTNAMELEN -+# define INITRQ_HLEN MAXHOSTNAMELEN -+#else -+# define INITRQ_HLEN 64 -+#endif -+ -+/* -+ * This is what BSD 4.4 uses when talking to init. -+ * Linux doesn't use this right now. -+ */ -+struct init_request_bsd { -+ char gen_id[8]; /* Beats me.. telnetd uses "fe" */ -+ char tty_id[16]; /* Tty name minus /dev/tty */ -+ char host[INITRQ_HLEN]; /* Hostname */ -+ char term_type[16]; /* Terminal type */ -+ int signal; /* Signal to send */ -+ int pid; /* Process to send to */ -+ char exec_name[128]; /* Program to execute */ -+ char reserved[128]; /* For future expansion. */ -+}; -+ - -+/* -+ * Because of legacy interfaces, "runlevel" and "sleeptime" -+ * aren't in a seperate struct in the union. -+ * -+ * The weird sizes are because init expects the whole -+ * struct to be 384 bytes. -+ */ - struct init_request { -- int magic; /* Magic number */ -- int cmd; /* What kind of request */ -- int runlevel; /* Runlevel to change to */ -- int sleeptime; /* Time between TERM and KILL */ -- char gen_id[8]; /* Beats me.. telnetd uses "fe" */ -- char tty_id[16]; /* Tty name minus /dev/tty */ -- char host[MAXHOSTNAMELEN]; /* Hostname */ -- char term_type[16]; /* Terminal type */ -- int signal; /* Signal to send */ -- int pid; /* Process to send to */ -- char exec_name[128]; /* Program to execute */ -- char reserved[128]; /* For future expansion. */ -+ int magic; /* Magic number */ -+ int cmd; /* What kind of request */ -+ int runlevel; /* Runlevel to change to */ -+ int sleeptime; /* Time between TERM and KILL */ -+ union { -+ struct init_request_bsd bsd; -+ char data[368]; -+ } i; - }; - - #endif -Binary files sysvinit-2.85/src/killall5 and sysvinit-2.86/src/killall5 differ -diff -urNd -urNd sysvinit-2.85/src/killall5.c sysvinit-2.86/src/killall5.c ---- sysvinit-2.85/src/killall5.c 2003-04-14 04:59:11.000000000 -0500 -+++ sysvinit-2.86/src/killall5.c 2004-07-30 07:16:23.000000000 -0500 -@@ -5,7 +5,7 @@ - * - * pidof.c Tries to get the pid of the process[es] named. - * -- * Version: 2.85 14-Apr-2003 MvS -+ * Version: 2.86 30-Jul-2004 MvS - * - * Usage: killall5 [-][signal] - * pidof [-s] [-o omitpid [-o omitpid]] program [program..] -@@ -20,7 +20,7 @@ - * - swapped out programs pids are caught now - * - * This file is part of the sysvinit suite, -- * Copyright 1991-2003 Miquel van Smoorenburg. -+ * Copyright 1991-2004 Miquel van Smoorenburg. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License -@@ -41,34 +41,43 @@ - #include <getopt.h> - #include <stdarg.h> - --char *Version = "@(#)killall5 2.85 14-Apr-2003 miquels@cistron.nl"; -+char *Version = "@(#)killall5 2.86 31-Jul-2004 miquels@cistron.nl"; -+ -+#define STATNAMELEN 15 - - /* Info about a process. */ --typedef struct _proc_ --{ -- char *fullname; /* Name as found out from argv[0] */ -- char *basename; /* Only the part after the last / */ -- char *statname; /* the statname without braces */ -- ino_t ino; /* Inode number */ -- dev_t dev; /* Device it is on */ -- pid_t pid; /* Process ID. */ -- int sid; /* Session ID. */ -- struct _proc_ *next; /* Pointer to next struct. */ -+typedef struct proc { -+ char *argv0; /* Name as found out from argv[0] */ -+ char *argv0base; /* `basename argv[1]` */ -+ char *argv1; /* Name as found out from argv[1] */ -+ char *argv1base; /* `basename argv[1]` */ -+ char *statname; /* the statname without braces */ -+ ino_t ino; /* Inode number */ -+ dev_t dev; /* Device it is on */ -+ pid_t pid; /* Process ID. */ -+ int sid; /* Session ID. */ -+ int kernel; /* Kernel thread or zombie. */ -+ struct proc *next; /* Pointer to next struct. */ - } PROC; - - /* pid queue */ --typedef struct _pidq_ { -- struct _pidq_ *front; -- struct _pidq_ *next; -- struct _pidq_ *rear; -- PROC *proc; -+ -+typedef struct pidq { -+ PROC *proc; -+ struct pidq *next; - } PIDQ; - -+typedef struct { -+ PIDQ *head; -+ PIDQ *tail; -+ PIDQ *next; -+} PIDQ_HEAD; -+ - /* List of processes. */ - PROC *plist; - --/* Did we stop a number of processes? */ --int stopped; -+/* Did we stop all processes ? */ -+int sent_sigstop; - - int scripts_too = 0; - -@@ -86,7 +95,7 @@ - void *p; - - if ((p = malloc(bytes)) == NULL) { -- if (stopped) kill(-1, SIGCONT); -+ if (sent_sigstop) kill(-1, SIGCONT); - nsyslog(LOG_ERR, "out of memory"); - exit(1); - } -@@ -98,14 +107,14 @@ - */ - int mount_proc(void) - { -- struct stat st; -- pid_t pid, rc; -- int wst; -- char *args[] = { "mount", "-t", "proc", "none", "/proc", NULL }; -- int did_mount = 0; -+ struct stat st; -+ char *args[] = { "mount", "-t", "proc", "proc", "/proc", 0 }; -+ pid_t pid, rc; -+ int wst; -+ int did_mount = 0; - - /* Stat /proc/version to see if /proc is mounted. */ -- if (stat("/proc/version", &st) < 0) { -+ if (stat("/proc/version", &st) < 0 && errno == ENOENT) { - - /* It's not there, so mount it. */ - if ((pid = fork()) < 0) { -@@ -115,7 +124,6 @@ - if (pid == 0) { - /* Try a few mount binaries. */ - execv("/sbin/mount", args); -- execv("/etc/mount", args); - execv("/bin/mount", args); - - /* Okay, I give up. */ -@@ -134,28 +142,42 @@ - - /* See if mount succeeded. */ - if (stat("/proc/version", &st) < 0) { -- nsyslog(LOG_ERR, "/proc not mounted, failed to mount."); -+ if (errno == ENOENT) -+ nsyslog(LOG_ERR, "/proc not mounted, failed to mount."); -+ else -+ nsyslog(LOG_ERR, "/proc unavailable."); - exit(1); - } - - return did_mount; - } - -+int readarg(FILE *fp, char *buf, int sz) -+{ -+ int c = 0, f = 0; -+ -+ while (f < (sz-1) && (c = fgetc(fp)) != EOF && c) -+ buf[f++] = c; -+ buf[f] = 0; -+ -+ return (c == EOF && f == 0) ? c : f; -+} -+ - /* - * Read the proc filesystem. - */ - int readproc() - { -- DIR *dir; -- struct dirent *d; -- char path[256]; -- char buf[256]; -- char *s, *q; -- FILE *fp; -- int pid, f; -- PROC *p, *n; -- struct stat st; -- int c; -+ DIR *dir; -+ FILE *fp; -+ PROC *p, *n; -+ struct dirent *d; -+ struct stat st; -+ char path[256]; -+ char buf[256]; -+ char *s, *q; -+ unsigned long startcode, endcode; -+ int pid, f; - - /* Open the /proc directory. */ - if ((dir = opendir("/proc")) == NULL) { -@@ -167,7 +189,8 @@ - n = plist; - for (p = plist; n; p = n) { - n = p->next; -- if (p->fullname) free(p->fullname); -+ if (p->argv0) free(p->argv0); -+ if (p->argv1) free(p->argv1); - free(p); - } - plist = NULL; -@@ -188,7 +211,7 @@ - /* Read SID & statname from it. */ - if ((fp = fopen(path, "r")) != NULL) { - buf[0] = 0; -- fgets(buf, 256, fp); -+ fgets(buf, sizeof(buf), fp); - - /* See if name starts with '(' */ - s = buf; -@@ -215,14 +238,21 @@ - p->statname = (char *)xmalloc(strlen(s)+1); - strcpy(p->statname, s); - -- /* This could be replaced by getsid(pid) */ -- if (sscanf(q, "%*c %*d %*d %d", &p->sid) != 1) { -+ /* Get session, startcode, endcode. */ -+ startcode = endcode = 0; -+ if (sscanf(q, "%*c %*d %*d %d %*d %*d %*u %*u " -+ "%*u %*u %*u %*u %*u %*d %*d " -+ "%*d %*d %*d %*d %*u %*u %*d " -+ "%*u %lu %lu", -+ &p->sid, &startcode, &endcode) != 3) { - p->sid = 0; - nsyslog(LOG_ERR, "can't read sid from %s\n", - path); - free(p); - continue; - } -+ if (startcode == 0 && endcode == 0) -+ p->kernel = 1; - fclose(fp); - } else { - /* Process disappeared.. */ -@@ -230,24 +260,44 @@ - continue; - } - -- /* Now read argv[0] */ - snprintf(path, sizeof(path), "/proc/%s/cmdline", d->d_name); - if ((fp = fopen(path, "r")) != NULL) { -- f = 0; -- while(f < 127 && (c = fgetc(fp)) != EOF && c) -- buf[f++] = c; -- buf[f++] = 0; -- fclose(fp); - -- /* Store the name into malloced memory. */ -- p->fullname = (char *)xmalloc(f); -- strcpy(p->fullname, buf); -+ /* Now read argv[0] */ -+ f = readarg(fp, buf, sizeof(buf)); -+ -+ if (buf[0]) { -+ /* Store the name into malloced memory. */ -+ p->argv0 = (char *)xmalloc(f + 1); -+ strcpy(p->argv0, buf); -+ -+ /* Get a pointer to the basename. */ -+ p->argv0base = strrchr(p->argv0, '/'); -+ if (p->argv0base != NULL) -+ p->argv0base++; -+ else -+ p->argv0base = p->argv0; -+ } -+ -+ /* And read argv[1] */ -+ while ((f = readarg(fp, buf, sizeof(buf))) != EOF) -+ if (buf[0] != '-') break; -+ -+ if (buf[0]) { -+ /* Store the name into malloced memory. */ -+ p->argv1 = (char *)xmalloc(f + 1); -+ strcpy(p->argv1, buf); -+ -+ /* Get a pointer to the basename. */ -+ p->argv1base = strrchr(p->argv1, '/'); -+ if (p->argv1base != NULL) -+ p->argv1base++; -+ else -+ p->argv1base = p->argv1; -+ } -+ -+ fclose(fp); - -- /* Get a pointer to the basename. */ -- if ((p->basename = strrchr(p->fullname, '/')) != NULL) -- p->basename++; -- else -- p->basename = p->fullname; - } else { - /* Process disappeared.. */ - free(p); -@@ -272,19 +322,18 @@ - return 0; - } - --PIDQ *init_pid_q(PIDQ *q) -+PIDQ_HEAD *init_pid_q(PIDQ_HEAD *q) - { -- q->front = q->next = q->rear = NULL; -- q->proc = NULL; -+ q->head = q->next = q->tail = NULL; - return q; - } - --int empty_q(PIDQ *q) -+int empty_q(PIDQ_HEAD *q) - { -- return (q->front == NULL); -+ return (q->head == NULL); - } - --int add_pid_to_q(PIDQ *q, PROC *p) -+int add_pid_to_q(PIDQ_HEAD *q, PROC *p) - { - PIDQ *tmp; - -@@ -294,23 +343,23 @@ - tmp->next = NULL; - - if (empty_q(q)) { -- q->front = tmp; -- q->rear = tmp; -+ q->head = tmp; -+ q->tail = tmp; - } else { -- q->rear->next = tmp; -- q->rear = tmp; -+ q->tail->next = tmp; -+ q->tail = tmp; - } - return 0; - } - --PROC *get_next_from_pid_q(PIDQ *q) -+PROC *get_next_from_pid_q(PIDQ_HEAD *q) - { -- PROC *p; -- PIDQ *tmp = q->front; -+ PROC *p; -+ PIDQ *tmp = q->head; - - if (!empty_q(q)) { -- p = q->front->proc; -- q->front = tmp->next; -+ p = q->head->proc; -+ q->head = tmp->next; - free(tmp); - return p; - } -@@ -319,15 +368,15 @@ - } - - /* Try to get the process ID of a given process. */ --PIDQ *pidof(char *prog) -+PIDQ_HEAD *pidof(char *prog) - { -- struct stat st; -- int dostat = 0; -- PROC *p; -- PIDQ *q; -- char *s; -- int foundone = 0; -- int ok = 0; -+ PROC *p; -+ PIDQ_HEAD *q; -+ struct stat st; -+ char *s; -+ int dostat = 0; -+ int foundone = 0; -+ int ok = 0; - - /* Try to stat the executable. */ - if (prog[0] == '/' && stat(prog, &st) == 0) dostat++; -@@ -338,7 +387,7 @@ - else - s++; - -- q = (PIDQ *)xmalloc(sizeof(PIDQ)); -+ q = (PIDQ_HEAD *)xmalloc(sizeof(PIDQ_HEAD)); - q = init_pid_q(q); - - /* First try to find a match based on dev/ino pair. */ -@@ -352,20 +401,31 @@ - } - - /* If we didn't find a match based on dev/ino, try the name. */ -- if (!foundone) { -- for (p = plist; p; p = p->next) { -- ok = 0; -+ if (!foundone) for (p = plist; p; p = p->next) { -+ ok = 0; - -- ok += (strcmp(p->fullname, prog) == 0); -- ok += (strcmp(p->basename, s) == 0); -+ /* Compare name (both basename and full path) */ -+ ok += (p->argv0 && strcmp(p->argv0, prog) == 0); -+ ok += (p->argv0 && strcmp(p->argv0base, s) == 0); - -- if (p->fullname[0] == 0 || -- strchr(p->fullname, ' ') || -- scripts_too) -- ok += (strcmp(p->statname, s) == 0); -+ /* For scripts, compare argv[1] as well. */ -+ if (scripts_too && p->argv1 && -+ !strncmp(p->statname, p->argv1base, STATNAMELEN)) { -+ ok += (strcmp(p->argv1, prog) == 0); -+ ok += (strcmp(p->argv1base, s) == 0); -+ } - -- if (ok) add_pid_to_q(q, p); -+ /* -+ * if we have a space in argv0, process probably -+ * used setproctitle so try statname. -+ */ -+ if (strlen(s) <= STATNAMELEN && -+ (p->argv0 == NULL || -+ p->argv0[0] == 0 || -+ strchr(p->argv0, ' '))) { -+ ok += (strcmp(p->statname, s) == 0); - } -+ if (ok) add_pid_to_q(q, p); - } - - return q; -@@ -410,12 +470,12 @@ - */ - int main_pidof(int argc, char **argv) - { -- PROC *p; -- PIDQ *q; -- int f; -- int first = 1; -- int i,oind, opt, flags = 0; -- pid_t opid[PIDOF_OMITSZ], spid; -+ PIDQ_HEAD *q; -+ PROC *p; -+ pid_t opid[PIDOF_OMITSZ], spid; -+ int f; -+ int first = 1; -+ int i, oind, opt, flags = 0; - - for (oind = PIDOF_OMITSZ-1; oind > 0; oind--) - opid[oind] = 0; -@@ -498,9 +558,9 @@ - /* Main for either killall or pidof. */ - int main(int argc, char **argv) - { -- PROC *p; -- int pid, sid = -1; -- int sig = SIGKILL; -+ PROC *p; -+ int pid, sid = -1; -+ int sig = SIGKILL; - - /* Get program name. */ - if ((progname = strrchr(argv[0], '/')) == NULL) -@@ -511,9 +571,6 @@ - /* Now connect to syslog. */ - openlog(progname, LOG_CONS|LOG_PID, LOG_DAEMON); - -- /* First get the /proc filesystem online. */ -- mount_proc(); -- - /* Were we called as 'pidof' ? */ - if (strcmp(progname, "pidof") == 0) - return main_pidof(argc, argv); -@@ -525,6 +582,9 @@ - if ((sig = atoi(argv[1])) <= 0 || sig > 31) usage(); - } - -+ /* First get the /proc filesystem online. */ -+ mount_proc(); -+ - /* - * Ignoring SIGKILL and SIGSTOP do not make sense, but - * someday kill(-1, sig) might kill ourself if we don't -@@ -537,24 +597,19 @@ - - /* Now stop all processes. */ - kill(-1, SIGSTOP); -- stopped = 1; -+ sent_sigstop = 1; - -- /* Find out our own 'sid'. */ -+ /* Read /proc filesystem */ - if (readproc() < 0) { - kill(-1, SIGCONT); - exit(1); - } - -- pid = getpid(); -- for (p = plist; p; p = p->next) -- if (p->pid == pid) { -- sid = p->sid; -- break; -- } -- - /* Now kill all processes except our session. */ -+ sid = (int)getsid(0); -+ pid = (int)getpid(); - for (p = plist; p; p = p->next) -- if (p->pid != pid && p->sid != sid) -+ if (p->pid != pid && p->sid != sid && !p->kernel) - kill(p->pid, sig); - - /* And let them continue. */ -Binary files sysvinit-2.85/src/last and sysvinit-2.86/src/last differ -diff -urNd -urNd sysvinit-2.85/src/last.c sysvinit-2.86/src/last.c ---- sysvinit-2.85/src/last.c 2003-04-17 06:38:56.000000000 -0500 -+++ sysvinit-2.86/src/last.c 2004-07-30 07:16:26.000000000 -0500 -@@ -6,10 +6,10 @@ - * - * Author: Miquel van Smoorenburg, miquels@cistron.nl - * -- * Version: @(#)last 2.85 16-Apr-2003 miquels@cistron.nl -+ * Version: @(#)last 2.85 30-Jul-2004 miquels@cistron.nl - * - * This file is part of the sysvinit suite, -- * Copyright 1991-2003 Miquel van Smoorenburg. -+ * Copyright 1991-2004 Miquel van Smoorenburg. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License -@@ -40,7 +40,7 @@ - # define SHUTDOWN_TIME 254 - #endif - --char *Version = "@(#) last 2.85 16-Apr-2003 miquels"; -+char *Version = "@(#) last 2.85 31-Apr-2004 miquels"; - - #define CHOP_DOMAIN 0 /* Define to chop off local domainname. */ - #define NEW_UTMP 1 /* Fancy & fast utmp read code. */ -@@ -491,10 +491,48 @@ - void usage(char *s) - { - fprintf(stderr, "Usage: %s [-num | -n num] [-f file] " -+ "[-t YYYYMMDDHHMMSS] " - "[-R] [-x] [-o] [username..] [tty..]\n", s); - exit(1); - } - -+time_t parsetm(char *ts) -+{ -+ struct tm u = {0}, origu; -+ time_t tm; -+ -+ if (sscanf(ts, "%4d%2d%2d%2d%2d%2d", &u.tm_year, -+ &u.tm_mon, &u.tm_mday, &u.tm_hour, &u.tm_min, -+ &u.tm_sec) != 6) -+ return (time_t)-1; -+ -+ u.tm_year -= 1900; -+ u.tm_mon -= 1; -+ u.tm_isdst = -1; -+ -+ origu = u; -+ -+ if ((tm = mktime(&u)) == (time_t)-1) -+ return tm; -+ -+ /* -+ * Unfortunately mktime() is much more forgiving than -+ * it should be. For example, it'll gladly accept -+ * "30" as a valid month number. This behavior is by -+ * design, but we don't like it, so we want to detect -+ * it and complain. -+ */ -+ if (u.tm_year != origu.tm_year || -+ u.tm_mon != origu.tm_mon || -+ u.tm_mday != origu.tm_mday || -+ u.tm_hour != origu.tm_hour || -+ u.tm_min != origu.tm_min || -+ u.tm_sec != origu.tm_sec) -+ return (time_t)-1; -+ -+ return tm; -+} -+ - int main(int argc, char **argv) - { - FILE *fp; /* Filepointer of wtmp file */ -@@ -518,10 +556,12 @@ - int extended = 0; /* Lots of info. */ - char *altufile = NULL;/* Alternate wtmp */ - -+ time_t until = 0; /* at what time to stop parsing the file */ -+ - progname = mybasename(argv[0]); - - /* Process the arguments. */ -- while((c = getopt(argc, argv, "f:n:Rxadio0123456789")) != EOF) -+ while((c = getopt(argc, argv, "f:n:Rxadiot:0123456789")) != EOF) - switch(c) { - case 'R': - showhost = 0; -@@ -552,6 +592,13 @@ - case 'a': - altlist++; - break; -+ case 't': -+ if ((until = parsetm(optarg)) == (time_t)-1) { -+ fprintf(stderr, "%s: Invalid time value \"%s\"\n", -+ progname, optarg); -+ usage(progname); -+ } -+ break; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - maxrecs = 10*maxrecs + c - '0'; -@@ -650,6 +697,9 @@ - if (uread(fp, &ut, &quit) != 1) - break; - -+ if (until && until < ut.ut_time) -+ continue; -+ - if (memcmp(&ut, &oldut, sizeof(struct utmp)) == 0) continue; - memcpy(&oldut, &ut, sizeof(struct utmp)); - lastdate = ut.ut_time; -Binary files sysvinit-2.85/src/last.o and sysvinit-2.86/src/last.o differ -Binary files sysvinit-2.85/src/mesg and sysvinit-2.86/src/mesg differ -Binary files sysvinit-2.85/src/mesg.o and sysvinit-2.86/src/mesg.o differ -Binary files sysvinit-2.85/src/mountpoint and sysvinit-2.86/src/mountpoint differ -diff -urNd -urNd sysvinit-2.85/src/mountpoint.c sysvinit-2.86/src/mountpoint.c ---- sysvinit-2.85/src/mountpoint.c 1969-12-31 18:00:00.000000000 -0600 -+++ sysvinit-2.86/src/mountpoint.c 2004-06-09 07:47:45.000000000 -0500 -@@ -0,0 +1,119 @@ -+/* -+ * mountpoint See if a directory is a mountpoint. -+ * -+ * Author: Miquel van Smoorenburg. -+ * -+ * Version: @(#)mountpoint 2.85-12 17-Mar-2004 miquels@cistron.nl -+ * -+ * This file is part of the sysvinit suite, -+ * Copyright 1991-2004 Miquel van Smoorenburg. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+ -+#include <sys/stat.h> -+#include <unistd.h> -+#include <stdlib.h> -+#include <string.h> -+#include <errno.h> -+#include <stdarg.h> -+#include <getopt.h> -+#include <stdio.h> -+ -+int dostat(char *path, struct stat *st, int do_lstat, int quiet) -+{ -+ int n; -+ -+ if (do_lstat) -+ n = lstat(path, st); -+ else -+ n = stat(path, st); -+ -+ if (n != 0) { -+ if (!quiet) -+ fprintf(stderr, "mountpoint: %s: %s\n", path, -+ strerror(errno)); -+ return -1; -+ } -+ return 0; -+} -+ -+void usage(void) { -+ fprintf(stderr, "Usage: mountpoint [-q] [-d] [-x] path\n"); -+ exit(1); -+} -+ -+int main(int argc, char **argv) -+{ -+ struct stat st, st2; -+ char buf[256]; -+ char *path; -+ int quiet = 0; -+ int showdev = 0; -+ int xdev = 0; -+ int c, r; -+ -+ while ((c = getopt(argc, argv, "dqx")) != EOF) switch(c) { -+ case 'd': -+ showdev = 1; -+ break; -+ case 'q': -+ quiet = 1; -+ break; -+ case 'x': -+ xdev = 1; -+ break; -+ default: -+ usage(); -+ break; -+ } -+ if (optind != argc - 1) usage(); -+ path = argv[optind]; -+ -+ if (dostat(path, &st, !xdev, quiet) < 0) -+ return 1; -+ -+ if (xdev) { -+#ifdef __linux__ -+ if (!S_ISBLK(st.st_mode)) -+#else -+ if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) -+#endif -+ { -+ if (quiet) -+ printf("\n"); -+ else -+ fprintf(stderr, "mountpoint: %s: not a block device\n", -+ path); -+ return 1; -+ } -+ printf("%u:%u\n", major(st.st_rdev), minor(st.st_rdev)); -+ return 0; -+ } -+ -+ if (!S_ISDIR(st.st_mode)) { -+ if (!quiet) -+ fprintf(stderr, "mountpoint: %s: not a directory\n", -+ path); -+ return 1; -+ } -+ -+ memset(buf, 0, sizeof(buf)); -+ strncpy(buf, path, sizeof(buf) - 4); -+ strcat(buf, "/.."); -+ if (dostat(buf, &st2, 0, quiet) < 0) -+ return 1; -+ -+ r = (st.st_dev != st2.st_dev) || -+ (st.st_dev == st2.st_dev && st.st_ino == st2.st_ino); -+ -+ if (!quiet && !showdev) -+ printf("%s is %sa mountpoint\n", path, r ? "" : "not "); -+ if (showdev) -+ printf("%u:%u\n", major(st.st_dev), minor(st.st_dev)); -+ -+ return r ? 0 : 1; -+} -Binary files sysvinit-2.85/src/mountpoint.o and sysvinit-2.86/src/mountpoint.o differ -diff -urNd -urNd sysvinit-2.85/src/paths.h sysvinit-2.86/src/paths.h ---- sysvinit-2.85/src/paths.h 2003-04-14 06:37:01.000000000 -0500 -+++ sysvinit-2.86/src/paths.h 2004-06-09 07:47:45.000000000 -0500 -@@ -1,7 +1,7 @@ - /* - * paths.h Paths of files that init and related utilities need. - * -- * Version: @(#) paths.h 2.84 27-Nov-2001 -+ * Version: @(#) paths.h 2.85-8 05-Nov-2003 - * - * Author: Miquel van Smoorenburg, <miquels@cistron.nl> - * -@@ -24,6 +24,7 @@ - #define FORCEFSCK "/forcefsck" /* Force fsck on boot */ - #define SDPID "/var/run/shutdown.pid" /* PID of shutdown program */ - #define SHELL "/bin/sh" /* Default shell */ -+#define SULOGIN "/sbin/sulogin" /* Sulogin */ - #define INITSCRIPT "/etc/initscript" /* Initscript. */ - #define PWRSTAT "/etc/powerstatus" /* COMPAT: SIGPWR reason (OK/BAD) */ - -diff -urNd -urNd sysvinit-2.85/src/reboot.h sysvinit-2.86/src/reboot.h ---- sysvinit-2.85/src/reboot.h 1997-09-24 03:55:52.000000000 -0500 -+++ sysvinit-2.86/src/reboot.h 2004-06-09 07:47:45.000000000 -0500 -@@ -2,22 +2,35 @@ - * reboot.h Headerfile that defines how to handle - * the reboot() system call. - * -- * Version: @(#)reboot.h 1.00 23-Jul-1996 miquels@cistron.nl -+ * Version: @(#)reboot.h 2.85-17 04-Jun-2004 miquels@cistron.nl - * - */ - --#if defined(__GLIBC__) --# include <sys/reboot.h> -+#include <sys/reboot.h> -+ -+#ifdef RB_ENABLE_CAD -+# define BMAGIC_HARD RB_ENABLE_CAD - #endif - --#define BMAGIC_HARD 0x89ABCDEF --#define BMAGIC_SOFT 0 --#define BMAGIC_REBOOT 0x01234567 --#define BMAGIC_HALT 0xCDEF0123 --#define BMAGIC_POWEROFF 0x4321FEDC -+#ifdef RB_DISABLE_CAD -+# define BMAGIC_SOFT RB_DISABLE_CAD -+#endif - --#if defined(__GLIBC__) -- #define init_reboot(magic) reboot(magic) -+#ifdef RB_HALT_SYSTEM -+# define BMAGIC_HALT RB_HALT_SYSTEM - #else -- #define init_reboot(magic) reboot(0xfee1dead, 672274793, magic) -+# define BMAGIC_HALT RB_HALT - #endif -+ -+#define BMAGIC_REBOOT RB_AUTOBOOT -+ -+#ifdef RB_POWER_OFF -+# define BMAGIC_POWEROFF RB_POWER_OFF -+#elif defined(RB_POWEROFF) -+# define BMAGIC_POWEROFF RB_POWEROFF -+#else -+# define BMAGIC_POWEROFF BMAGIC_HALT -+#endif -+ -+#define init_reboot(magic) reboot(magic) -+ -Binary files sysvinit-2.85/src/runlevel and sysvinit-2.86/src/runlevel differ -Binary files sysvinit-2.85/src/runlevel.o and sysvinit-2.86/src/runlevel.o differ -Binary files sysvinit-2.85/src/shutdown and sysvinit-2.86/src/shutdown differ -diff -urNd -urNd sysvinit-2.85/src/shutdown.c sysvinit-2.86/src/shutdown.c ---- sysvinit-2.85/src/shutdown.c 2003-04-14 06:35:51.000000000 -0500 -+++ sysvinit-2.86/src/shutdown.c 2004-07-30 06:59:04.000000000 -0500 -@@ -13,10 +13,10 @@ - * - * Author: Miquel van Smoorenburg, miquels@cistron.nl - * -- * Version: @(#)shutdown 2.85 14-Apr-2003 miquels@cistron.nl -+ * Version: @(#)shutdown 2.86-1 31-Jul-2004 miquels@cistron.nl - * - * This file is part of the sysvinit suite, -- * Copyright 1991-2003 Miquel van Smoorenburg. -+ * Copyright 1991-2004 Miquel van Smoorenburg. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License -@@ -36,10 +36,12 @@ - #include <fcntl.h> - #include <stdarg.h> - #include <utmp.h> -+#include <syslog.h> - #include "paths.h" - #include "reboot.h" -+#include "initreq.h" - --char *Version = "@(#) shutdown 2.85 14-Apr-2003 miquels@cistron.nl"; -+char *Version = "@(#) shutdown 2.86-1 31-Jul-2004 miquels@cistron.nl"; - - #define MESSAGELEN 256 - -@@ -52,6 +54,7 @@ - char *sltime = 0; /* Sleep time */ - char newstate[64]; /* What are we gonna do */ - int doself = 0; /* Don't use init */ -+int got_alrm = 0; - - char *clean_env[] = { - "HOME=/", -@@ -67,93 +70,152 @@ - extern void write_wtmp(char *user, char *id, int pid, int type, char *line); - - /* -- * Sleep without being interrupted. -+ * Sleep without being interrupted. - */ - void hardsleep(int secs) - { -- struct timespec ts, rem; -+ struct timespec ts, rem; - -- ts.tv_sec = secs; -- ts.tv_nsec = 0; -+ ts.tv_sec = secs; -+ ts.tv_nsec = 0; - -- while(nanosleep(&ts, &rem) < 0 && errno == EINTR) -+ while(nanosleep(&ts, &rem) < 0 && errno == EINTR) - ts = rem; - } - - /* -- * Break off an already running shutdown. -+ * Break off an already running shutdown. - */ --void stopit() -+void stopit(int sig) - { -- unlink(NOLOGIN); -- unlink(FASTBOOT); -- unlink(FORCEFSCK); -- unlink(SDPID); -- printf("\r\nShutdown cancelled.\r\n"); -- exit(0); -+ unlink(NOLOGIN); -+ unlink(FASTBOOT); -+ unlink(FORCEFSCK); -+ unlink(SDPID); -+ printf("\r\nShutdown cancelled.\r\n"); -+ exit(0); - } - - /* -- * Show usage message. -+ * Show usage message. - */ --void usage() -+void usage(void) - { -- fprintf(stderr, -- "Usage:\t shutdown [-akrhfnc] [-t secs] time [warning message]\n" -+ fprintf(stderr, -+ "Usage:\t shutdown [-akrhHPfnc] [-t secs] time [warning message]\n" - "\t\t -a: use /etc/shutdown.allow\n" - "\t\t -k: don't really shutdown, only warn.\n" - "\t\t -r: reboot after shutdown.\n" - "\t\t -h: halt after shutdown.\n" -+ "\t\t -P: halt action is to turn off power.\n" -+ "\t\t -H: halt action is to just halt.\n" - "\t\t -f: do a 'fast' reboot (skip fsck).\n" - "\t\t -F: Force fsck on reboot.\n" - "\t\t -n: do not go through \"init\" but go down real fast.\n" - "\t\t -c: cancel a running shutdown.\n" - "\t\t -t secs: delay between warning and kill signal.\n" - "\t\t ** the \"time\" argument is mandatory! (try \"now\") **\n"); -- exit(1); -+ exit(1); - } - -+ -+void alrm_handler(int sig) -+{ -+ got_alrm = sig; -+} -+ -+ - /* -- * Tell everyone the system is going down in 'mins' minutes. -+ * Set environment variables in the init process. - */ --void warn(mins) --int mins; -+int init_setenv(char *name, char *value) - { -- char buf[MESSAGELEN + sizeof(newstate)]; -- int len; -+ struct init_request request; -+ struct sigaction sa; -+ int fd; -+ int nl, vl; - -- buf[0] = 0; -- strncat(buf, message, sizeof(buf) - 1); -- len = strlen(buf); -+ memset(&request, 0, sizeof(request)); -+ request.magic = INIT_MAGIC; -+ request.cmd = INIT_CMD_SETENV; -+ nl = strlen(name); -+ vl = value ? strlen(value) : 0; - -- if (mins == 0) -- snprintf(buf + len, sizeof(buf) - len, -- "\rThe system is going down %s NOW!\r\n", -- newstate); -- else -- snprintf(buf + len, sizeof(buf) - len, -- "\rThe system is going DOWN %s in %d minute%s!\r\n", -- newstate, mins, mins == 1 ? "" : "s"); -- wall(buf, 1, 0); -+ if (nl + vl + 3 >= sizeof(request.i.data)) -+ return -1; -+ -+ memcpy(request.i.data, name, nl); -+ if (value) { -+ request.i.data[nl] = '='; -+ memcpy(request.i.data + nl + 1, value, vl); -+ } -+ -+ /* -+ * Open the fifo and write the command. -+ * Make sure we don't hang on opening /dev/initctl -+ */ -+ memset(&sa, 0, sizeof(sa)); -+ sa.sa_handler = alrm_handler; -+ sigaction(SIGALRM, &sa, NULL); -+ got_alrm = 0; -+ alarm(3); -+ if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0 && -+ write(fd, &request, sizeof(request)) == sizeof(request)) { -+ close(fd); -+ alarm(0); -+ return 0; -+ } -+ -+ fprintf(stderr, "shutdown: "); -+ if (got_alrm) { -+ fprintf(stderr, "timeout opening/writing control channel %s\n", -+ INIT_FIFO); -+ } else { -+ perror(INIT_FIFO); -+ } -+ return -1; - } - -+ - /* -- * Create the /etc/nologin file. -+ * Tell everyone the system is going down in 'mins' minutes. -+ */ -+void warn(int mins) -+{ -+ char buf[MESSAGELEN + sizeof(newstate)]; -+ int len; -+ -+ buf[0] = 0; -+ strncat(buf, message, sizeof(buf) - 1); -+ len = strlen(buf); -+ -+ if (mins == 0) -+ snprintf(buf + len, sizeof(buf) - len, -+ "\rThe system is going down %s NOW!\r\n", -+ newstate); -+ else -+ snprintf(buf + len, sizeof(buf) - len, -+ "\rThe system is going DOWN %s in %d minute%s!\r\n", -+ newstate, mins, mins == 1 ? "" : "s"); -+ wall(buf, 1, 0); -+} -+ -+/* -+ * Create the /etc/nologin file. - */ - void donologin(int min) - { -- FILE *fp; -- time_t t; -+ FILE *fp; -+ time_t t; - -- time(&t); -- t += 60 * min; -+ time(&t); -+ t += 60 * min; - -- unlink(NOLOGIN); -- if ((fp = fopen(NOLOGIN, "w")) != NULL) { -- fprintf(fp, "\rThe system is going down on %s\r\n", ctime(&t)); -- if (message[0]) fputs(message, fp); -- fclose(fp); -- } -+ if ((fp = fopen(NOLOGIN, "w")) != NULL) { -+ fprintf(fp, "\rThe system is going down on %s\r\n", ctime(&t)); -+ if (message[0]) fputs(message, fp); -+ fclose(fp); -+ } - } - - /* -@@ -202,131 +264,146 @@ - return 0; - } - --/* Kill all processes, call /etc/init.d/halt (if present) */ -+/* -+ * Kill all processes, call /etc/init.d/halt (if present) -+ */ - void fastdown() - { -- int do_halt = (down_level[0] == '0'); -- int i; -+ int do_halt = (down_level[0] == '0'); -+ int i; - #if 0 -- char cmd[128]; -- char *script; -+ char cmd[128]; -+ char *script; - -- /* Currently, the halt script is either init.d/halt OR rc.d/rc.0, -- * likewise for the reboot script. Test for the presence -- * of either. -- */ -- if (do_halt) { -- if (access(HALTSCRIPT1, X_OK) == 0) -- script = HALTSCRIPT1; -- else -- script = HALTSCRIPT2; -- } else { -- if (access(REBOOTSCRIPT1, X_OK) == 0) -- script = REBOOTSCRIPT1; -- else -- script = REBOOTSCRIPT2; -- } -+ /* -+ * Currently, the halt script is either init.d/halt OR rc.d/rc.0, -+ * likewise for the reboot script. Test for the presence -+ * of either. -+ */ -+ if (do_halt) { -+ if (access(HALTSCRIPT1, X_OK) == 0) -+ script = HALTSCRIPT1; -+ else -+ script = HALTSCRIPT2; -+ } else { -+ if (access(REBOOTSCRIPT1, X_OK) == 0) -+ script = REBOOTSCRIPT1; -+ else -+ script = REBOOTSCRIPT2; -+ } - #endif - -- /* First close all files. */ -- for(i = 0; i < 3; i++) -- if (!isatty(i)) { -- close(i); -- open("/dev/null", O_RDWR); -- } -- for(i = 3; i < 20; i++) close(i); -- close(255); -+ /* First close all files. */ -+ for(i = 0; i < 3; i++) -+ if (!isatty(i)) { -+ close(i); -+ open("/dev/null", O_RDWR); -+ } -+ for(i = 3; i < 20; i++) close(i); -+ close(255); - -- /* First idle init. */ -- if (kill(1, SIGTSTP) < 0) { -- fprintf(stderr, "shutdown: can't idle init.\r\n"); -- exit(1); -- } -+ /* First idle init. */ -+ if (kill(1, SIGTSTP) < 0) { -+ fprintf(stderr, "shutdown: can't idle init.\r\n"); -+ exit(1); -+ } - -- /* Kill all processes. */ -- fprintf(stderr, "shutdown: sending all processes the TERM signal...\r\n"); -- (void) kill(-1, SIGTERM); -- if (sltime) -- sleep(atoi(sltime)); -- else -- sleep(3); -- fprintf(stderr, "shutdown: sending all processes the KILL signal.\r\n"); -- (void) kill(-1, SIGKILL); -+ /* Kill all processes. */ -+ fprintf(stderr, "shutdown: sending all processes the TERM signal...\r\n"); -+ kill(-1, SIGTERM); -+ sleep(sltime ? atoi(sltime) : 3); -+ fprintf(stderr, "shutdown: sending all processes the KILL signal.\r\n"); -+ (void) kill(-1, SIGKILL); - - #if 0 -- /* See if we can run /etc/init.d/halt */ -- if (access(script, X_OK) == 0) { -- spawn(1, cmd, "fast", NULL); -- fprintf(stderr, "shutdown: %s returned - falling back on default routines\r\n", script); -- } -+ /* See if we can run /etc/init.d/halt */ -+ if (access(script, X_OK) == 0) { -+ spawn(1, cmd, "fast", NULL); -+ fprintf(stderr, "shutdown: %s returned - falling back " -+ "on default routines\r\n", script); -+ } - #endif - -- /* script failed or not present: do it ourself. */ -- sleep(1); /* Give init the chance to collect zombies. */ -+ /* script failed or not present: do it ourself. */ -+ sleep(1); /* Give init the chance to collect zombies. */ - -- /* Record the fact that we're going down */ -- write_wtmp("shutdown", "~~", 0, RUN_LVL, "~~"); -+ /* Record the fact that we're going down */ -+ write_wtmp("shutdown", "~~", 0, RUN_LVL, "~~"); - -- /* This is for those who have quota installed. */ -- spawn(1, "accton", NULL); -- spawn(1, "quotaoff", "-a", NULL); -+ /* This is for those who have quota installed. */ -+ spawn(1, "accton", NULL); -+ spawn(1, "quotaoff", "-a", NULL); - -- sync(); -- fprintf(stderr, "shutdown: turning off swap\r\n"); -- spawn(0, "swapoff", "-a", NULL); -- fprintf(stderr, "shutdown: unmounting all file systems\r\n"); -- spawn(0, "umount", "-a", NULL); -+ sync(); -+ fprintf(stderr, "shutdown: turning off swap\r\n"); -+ spawn(0, "swapoff", "-a", NULL); -+ fprintf(stderr, "shutdown: unmounting all file systems\r\n"); -+ spawn(0, "umount", "-a", NULL); - -- /* We're done, halt or reboot now. */ -- if (do_halt) { -- fprintf(stderr, "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n"); -- init_reboot(BMAGIC_HALT); -+ /* We're done, halt or reboot now. */ -+ if (do_halt) { -+ fprintf(stderr, "The system is halted. Press CTRL-ALT-DEL " -+ "or turn off power\r\n"); -+ init_reboot(BMAGIC_HALT); -+ exit(0); -+ } -+ -+ fprintf(stderr, "Please stand by while rebooting the system.\r\n"); -+ init_reboot(BMAGIC_REBOOT); - exit(0); -- } -- fprintf(stderr, "Please stand by while rebooting the system.\r\n"); -- init_reboot(BMAGIC_REBOOT); -- exit(0); - } - - /* -- * Go to runlevel 0, 1 or 6. -+ * Go to runlevel 0, 1 or 6. - */ --void shutdown() -+void shutdown(char *halttype) - { -- char *args[8]; -- int argp = 0; -+ char *args[8]; -+ int argp = 0; -+ int do_halt = (down_level[0] == '0'); - -- /* Warn for the last time (hehe) */ -- warn(0); -- if (dontshut) { -- hardsleep(1); -- stopit(); -- } -+ /* Warn for the last time */ -+ warn(0); -+ if (dontshut) { -+ hardsleep(1); -+ stopit(0); -+ } -+ openlog("shutdown", LOG_PID, LOG_USER); -+ if (do_halt) -+ syslog(LOG_NOTICE, "shutting down for system halt"); -+ else -+ syslog(LOG_NOTICE, "shutting down for system reboot"); -+ closelog(); - -- /* See if we have to do it ourself. */ -- if (doself) fastdown(); -+ /* See if we have to do it ourself. */ -+ if (doself) fastdown(); - -- /* Create the arguments for init. */ -- args[argp++] = INIT; -- if (sltime) { -- args[argp++] = "-t"; -- args[argp++] = sltime; -- } -- args[argp++] = down_level; -- args[argp] = (char *)NULL; -+ /* Create the arguments for init. */ -+ args[argp++] = INIT; -+ if (sltime) { -+ args[argp++] = "-t"; -+ args[argp++] = sltime; -+ } -+ args[argp++] = down_level; -+ args[argp] = (char *)NULL; - -- unlink(SDPID); -- unlink(NOLOGIN); -+ unlink(SDPID); -+ unlink(NOLOGIN); - -- /* Now execute init to change runlevel. */ -- sync(); -- execv(INIT, args); -+ /* Now execute init to change runlevel. */ -+ sync(); -+ init_setenv("INIT_HALT", halttype); -+ execv(INIT, args); - -- /* Oops - failed. */ -- fprintf(stderr, "\rshutdown: cannot execute %s\r\n", INIT); -- unlink(FASTBOOT); -- unlink(FORCEFSCK); -- exit(1); -+ /* Oops - failed. */ -+ fprintf(stderr, "\rshutdown: cannot execute %s\r\n", INIT); -+ unlink(FASTBOOT); -+ unlink(FORCEFSCK); -+ init_setenv("INIT_HALT", NULL); -+ openlog("shutdown", LOG_PID, LOG_USER); -+ syslog(LOG_NOTICE, "shutdown failed"); -+ closelog(); -+ exit(1); - } - - /* -@@ -349,274 +426,287 @@ - } - - /* -- * Main program. -- * Process the options and do the final countdown. -+ * Main program. -+ * Process the options and do the final countdown. - */ --int main(argc, argv) --int argc; --char **argv; -+int main(int argc, char **argv) - { -- extern int getopt(); -- extern int optind; -- int c, i, wt, hours, mins; -- struct tm *lt; -- time_t t; -- char *sp; -- char *when = NULL; -- int didnolog = 0; -- int cancel = 0; -- int useacl = 0; -- int pid = 0; -- uid_t realuid; -- FILE *fp; -- char *downusers[32]; -- char buf[128]; -- char term[UT_LINESIZE + 6]; -- struct stat st; -- struct utmp *ut; -- int user_ok = 0; -- struct sigaction sa; -+ FILE *fp; -+ extern int getopt(); -+ extern int optind; -+ struct sigaction sa; -+ struct tm *lt; -+ struct stat st; -+ struct utmp *ut; -+ time_t t; -+ uid_t realuid; -+ char *halttype; -+ char *downusers[32]; -+ char buf[128]; -+ char term[UT_LINESIZE + 6]; -+ char *sp; -+ char *when = NULL; -+ int c, i, wt; -+ int hours, mins; -+ int didnolog = 0; -+ int cancel = 0; -+ int useacl = 0; -+ int pid = 0; -+ int user_ok = 0; - -- /* We can be installed setuid root (executable for a special group) */ -- realuid = getuid(); -- setuid(geteuid()); -+ /* We can be installed setuid root (executable for a special group) */ -+ realuid = getuid(); -+ setuid(geteuid()); - -- if (getuid() != 0) { -- fprintf(stderr, "shutdown: you must be root to do that!\n"); -- exit(1); -- } -- strcpy(down_level, "1"); -+ if (getuid() != 0) { -+ fprintf(stderr, "shutdown: you must be root to do that!\n"); -+ exit(1); -+ } -+ strcpy(down_level, "1"); -+ halttype = NULL; - -- /* Process the options. */ -- while((c = getopt(argc, argv, "acqkrhnfFyt:g:i:")) != EOF) { -- switch(c) { -- case 'a': /* Access control. */ -- useacl = 1; -- break; -- case 'c': /* Cancel an already running shutdown. */ -- cancel = 1; -- break; -- case 'k': /* Don't really shutdown, only warn.*/ -- dontshut = 1; -- break; -- case 'r': /* Automatic reboot */ -- down_level[0] = '6'; -- break; -- case 'h': /* Halt after shutdown */ -- down_level[0] = '0'; -- break; -- case 'f': /* Don't perform fsck after next boot */ -- fastboot = 1; -- break; -- case 'F': /* Force fsck after next boot */ -- forcefsck = 1; -- break; -- case 'n': /* Don't switch runlevels. */ -- doself = 1; -- break; -- case 't': /* Delay between TERM and KILL */ -- sltime = optarg; -- break; -- case 'y': /* Ignored for sysV compatibility */ -- break; -- case 'g': /* sysv style to specify time. */ -- when = optarg; -- down_level[0] = '0'; -- break; -- case 'i': /* Level to go to. */ -- if (!strchr("0156aAbBcCsS", optarg[0])) { -- fprintf(stderr, "shutdown: `%s': bad runlevel\n", -+ /* Process the options. */ -+ while((c = getopt(argc, argv, "HPacqkrhnfFyt:g:i:")) != EOF) { -+ switch(c) { -+ case 'H': -+ halttype = "HALT"; -+ break; -+ case 'P': -+ halttype = "POWERDOWN"; -+ break; -+ case 'a': /* Access control. */ -+ useacl = 1; -+ break; -+ case 'c': /* Cancel an already running shutdown. */ -+ cancel = 1; -+ break; -+ case 'k': /* Don't really shutdown, only warn.*/ -+ dontshut = 1; -+ break; -+ case 'r': /* Automatic reboot */ -+ down_level[0] = '6'; -+ break; -+ case 'h': /* Halt after shutdown */ -+ down_level[0] = '0'; -+ break; -+ case 'f': /* Don't perform fsck after next boot */ -+ fastboot = 1; -+ break; -+ case 'F': /* Force fsck after next boot */ -+ forcefsck = 1; -+ break; -+ case 'n': /* Don't switch runlevels. */ -+ doself = 1; -+ break; -+ case 't': /* Delay between TERM and KILL */ -+ sltime = optarg; -+ break; -+ case 'y': /* Ignored for sysV compatibility */ -+ break; -+ case 'g': /* sysv style to specify time. */ -+ when = optarg; -+ break; -+ case 'i': /* Level to go to. */ -+ if (!strchr("0156aAbBcCsS", optarg[0])) { -+ fprintf(stderr, -+ "shutdown: `%s': bad runlevel\n", - optarg); -- exit(1); -- } -- down_level[0] = optarg[0]; -- break; -- default: -- usage(); -- break; -- } -- } -+ exit(1); -+ } -+ down_level[0] = optarg[0]; -+ break; -+ default: -+ usage(); -+ break; -+ } -+ } - -- /* Do we need to use the shutdown.allow file ? */ -- if (useacl && (fp = fopen(SDALLOW, "r")) != NULL) { -+ /* Do we need to use the shutdown.allow file ? */ -+ if (useacl && (fp = fopen(SDALLOW, "r")) != NULL) { - -- /* Read /etc/shutdown.allow. */ -- i = 0; -- while(fgets(buf, 128, fp)) { -- if (buf[0] == '#' || buf[0] == '\n') continue; -- if (i > 31) continue; -- for(sp = buf; *sp; sp++) if (*sp == '\n') *sp = 0; -- downusers[i++] = strdup(buf); -- } -- if (i < 32) downusers[i] = 0; -- fclose(fp); -+ /* Read /etc/shutdown.allow. */ -+ i = 0; -+ while(fgets(buf, 128, fp)) { -+ if (buf[0] == '#' || buf[0] == '\n') continue; -+ if (i > 31) continue; -+ for(sp = buf; *sp; sp++) if (*sp == '\n') *sp = 0; -+ downusers[i++] = strdup(buf); -+ } -+ if (i < 32) downusers[i] = 0; -+ fclose(fp); - -- /* Now walk through /var/run/utmp to find logged in users. */ -- while(!user_ok && (ut = getutent()) != NULL) { -+ /* Now walk through /var/run/utmp to find logged in users. */ -+ while(!user_ok && (ut = getutent()) != NULL) { - -- /* See if this is a user process on a VC. */ -- if (ut->ut_type != USER_PROCESS) continue; -- sprintf(term, "/dev/%.*s", UT_LINESIZE, ut->ut_line); -- if (stat(term, &st) < 0) continue; -+ /* See if this is a user process on a VC. */ -+ if (ut->ut_type != USER_PROCESS) continue; -+ sprintf(term, "/dev/%.*s", UT_LINESIZE, ut->ut_line); -+ if (stat(term, &st) < 0) continue; - #ifdef major /* glibc */ -- if (major(st.st_rdev) != 4 || -- minor(st.st_rdev) > 63) continue; -+ if (major(st.st_rdev) != 4 || -+ minor(st.st_rdev) > 63) continue; - #else -- if ((st.st_rdev & 0xFFC0) != 0x0400) continue; -+ if ((st.st_rdev & 0xFFC0) != 0x0400) continue; - #endif -- /* Root is always OK. */ -- if (strcmp(ut->ut_user, "root") == 0) { -- user_ok++; -- break; -- } -- -- /* See if this is an allowed user. */ -- for(i = 0; i < 32 && downusers[i]; i++) -- if (!strncmp(downusers[i], ut->ut_user, UT_NAMESIZE)) { -+ /* Root is always OK. */ -+ if (strcmp(ut->ut_user, "root") == 0) { - user_ok++; - break; - } -- } -- endutent(); - -- /* See if user was allowed. */ -- if (!user_ok) { -- if ((fp = fopen(CONSOLE, "w")) != NULL) { -- fprintf(fp, "\rshutdown: no authorized users logged in.\r\n"); -- fclose(fp); -+ /* See if this is an allowed user. */ -+ for(i = 0; i < 32 && downusers[i]; i++) -+ if (!strncmp(downusers[i], ut->ut_user, -+ UT_NAMESIZE)) { -+ user_ok++; -+ break; -+ } - } -- exit(1); -- } -- } -+ endutent(); - -- /* Read pid of running shutdown from a file */ -- if ((fp = fopen(SDPID, "r")) != NULL) { -- fscanf(fp, "%d", &pid); -- fclose(fp); -- } -+ /* See if user was allowed. */ -+ if (!user_ok) { -+ if ((fp = fopen(CONSOLE, "w")) != NULL) { -+ fprintf(fp, "\rshutdown: no authorized users " -+ "logged in.\r\n"); -+ fclose(fp); -+ } -+ exit(1); -+ } -+ } - -- /* Read remaining words, skip time if needed. */ -- message[0] = 0; -- for(c = optind + (!cancel && !when); c < argc; c++) { -- if (strlen(message) + strlen(argv[c]) + 4 > MESSAGELEN) -- break; -- strcat(message, argv[c]); -- strcat(message, " "); -- } -- if (message[0]) strcat(message, "\r\n"); -+ /* Read pid of running shutdown from a file */ -+ if ((fp = fopen(SDPID, "r")) != NULL) { -+ fscanf(fp, "%d", &pid); -+ fclose(fp); -+ } - -- /* See if we want to run or cancel. */ -- if (cancel) { -- if (pid <= 0) { -- fprintf(stderr, "shutdown: cannot find pid of running shutdown.\n"); -- exit(1); -+ /* Read remaining words, skip time if needed. */ -+ message[0] = 0; -+ for(c = optind + (!cancel && !when); c < argc; c++) { -+ if (strlen(message) + strlen(argv[c]) + 4 > MESSAGELEN) -+ break; -+ strcat(message, argv[c]); -+ strcat(message, " "); - } -- if (kill(pid, SIGINT) < 0) { -- fprintf(stderr, "shutdown: not running.\n"); -- exit(1); -+ if (message[0]) strcat(message, "\r\n"); -+ -+ /* See if we want to run or cancel. */ -+ if (cancel) { -+ if (pid <= 0) { -+ fprintf(stderr, "shutdown: cannot find pid " -+ "of running shutdown.\n"); -+ exit(1); -+ } -+ init_setenv("INIT_HALT", NULL); -+ if (kill(pid, SIGINT) < 0) { -+ fprintf(stderr, "shutdown: not running.\n"); -+ exit(1); -+ } -+ if (message[0]) wall(message, 1, 0); -+ exit(0); - } -- if (message[0]) wall(message, 1, 0); -- exit(0); -- } - -- /* Check syntax. */ -- if (when == NULL) { -- if (optind == argc) usage(); -- when = argv[optind++]; -- } -+ /* Check syntax. */ -+ if (when == NULL) { -+ if (optind == argc) usage(); -+ when = argv[optind++]; -+ } - -- /* See if we are already running. */ -- if (pid > 0 && kill(pid, 0) == 0) { -- fprintf(stderr, "\rshutdown: already running.\r\n"); -- exit(1); -- } -+ /* See if we are already running. */ -+ if (pid > 0 && kill(pid, 0) == 0) { -+ fprintf(stderr, "\rshutdown: already running.\r\n"); -+ exit(1); -+ } - -- /* Extra check. */ -- if (doself && down_level[0] != '0' && down_level[0] != '6') { -- fprintf(stderr, "shutdown: can use \"-n\" for halt or reboot only.\r\n"); -- exit(1); -- } -+ /* Extra check. */ -+ if (doself && down_level[0] != '0' && down_level[0] != '6') { -+ fprintf(stderr, -+ "shutdown: can use \"-n\" for halt or reboot only.\r\n"); -+ exit(1); -+ } - -- /* Tell users what we're gonna do. */ -- switch(down_level[0]) { -- case '0': -- strcpy(newstate, "for system halt"); -- break; -- case '6': -- strcpy(newstate, "for reboot"); -- break; -- case '1': -- strcpy(newstate, "to maintenance mode"); -- break; -- default: -- sprintf(newstate, "to runlevel %s", down_level); -- break; -- } -+ /* Tell users what we're gonna do. */ -+ switch(down_level[0]) { -+ case '0': -+ strcpy(newstate, "for system halt"); -+ break; -+ case '6': -+ strcpy(newstate, "for reboot"); -+ break; -+ case '1': -+ strcpy(newstate, "to maintenance mode"); -+ break; -+ default: -+ sprintf(newstate, "to runlevel %s", down_level); -+ break; -+ } - -- /* Create a new PID file. */ -- unlink(SDPID); -- umask(022); -- if ((fp = fopen(SDPID, "w")) != NULL) { -- fprintf(fp, "%d\n", getpid()); -- fclose(fp); -- } else if (errno != EROFS) -- fprintf(stderr, "shutdown: warning: cannot open %s\n", SDPID); -+ /* Create a new PID file. */ -+ unlink(SDPID); -+ umask(022); -+ if ((fp = fopen(SDPID, "w")) != NULL) { -+ fprintf(fp, "%d\n", getpid()); -+ fclose(fp); -+ } else if (errno != EROFS) -+ fprintf(stderr, "shutdown: warning: cannot open %s\n", SDPID); - -- /* -- * Catch some common signals. -- */ -- signal(SIGQUIT, SIG_IGN); -- signal(SIGCHLD, SIG_IGN); -- signal(SIGHUP, SIG_IGN); -- signal(SIGTSTP, SIG_IGN); -- signal(SIGTTIN, SIG_IGN); -- signal(SIGTTOU, SIG_IGN); -+ /* -+ * Catch some common signals. -+ */ -+ signal(SIGQUIT, SIG_IGN); -+ signal(SIGCHLD, SIG_IGN); -+ signal(SIGHUP, SIG_IGN); -+ signal(SIGTSTP, SIG_IGN); -+ signal(SIGTTIN, SIG_IGN); -+ signal(SIGTTOU, SIG_IGN); - -- sa.sa_handler = stopit; -- sa.sa_flags = SA_RESTART; -- sigaction(SIGINT, &sa, NULL); -+ memset(&sa, 0, sizeof(sa)); -+ sa.sa_handler = stopit; -+ sigaction(SIGINT, &sa, NULL); - -- /* Go to the root directory */ -- chdir("/"); -- if (fastboot) close(open(FASTBOOT, O_CREAT | O_RDWR, 0644)); -- if (forcefsck) close(open(FORCEFSCK, O_CREAT | O_RDWR, 0644)); -+ /* Go to the root directory */ -+ chdir("/"); -+ if (fastboot) close(open(FASTBOOT, O_CREAT | O_RDWR, 0644)); -+ if (forcefsck) close(open(FORCEFSCK, O_CREAT | O_RDWR, 0644)); - -- /* Alias now and take care of old '+mins' notation. */ -- if (!strcmp(when, "now")) strcpy(when, "0"); -- if (when[0] == '+') when++; -+ /* Alias now and take care of old '+mins' notation. */ -+ if (!strcmp(when, "now")) strcpy(when, "0"); -+ if (when[0] == '+') when++; - -- /* Decode shutdown time. */ -- for (sp = when; *sp; sp++) { -- if (*sp != ':' && (*sp < '0' || *sp > '9')) -- usage(); -- } -- if (strchr(when, ':') == NULL) { -- /* Time in minutes. */ -- wt = atoi(when); -- if (wt == 0 && when[0] != '0') usage(); -- } else { -- /* Time in hh:mm format. */ -- if (sscanf(when, "%d:%2d", &hours, &mins) != 2) usage(); -- if (hours > 23 || mins > 59) usage(); -- time(&t); -- lt = localtime(&t); -- wt = (60*hours + mins) - (60*lt->tm_hour + lt->tm_min); -- if (wt < 0) wt += 1440; -- } -- /* Shutdown NOW if time == 0 */ -- if (wt == 0) shutdown(); -+ /* Decode shutdown time. */ -+ for (sp = when; *sp; sp++) { -+ if (*sp != ':' && (*sp < '0' || *sp > '9')) -+ usage(); -+ } -+ if (strchr(when, ':') == NULL) { -+ /* Time in minutes. */ -+ wt = atoi(when); -+ if (wt == 0 && when[0] != '0') usage(); -+ } else { -+ /* Time in hh:mm format. */ -+ if (sscanf(when, "%d:%2d", &hours, &mins) != 2) usage(); -+ if (hours > 23 || mins > 59) usage(); -+ time(&t); -+ lt = localtime(&t); -+ wt = (60*hours + mins) - (60*lt->tm_hour + lt->tm_min); -+ if (wt < 0) wt += 1440; -+ } -+ /* Shutdown NOW if time == 0 */ -+ if (wt == 0) shutdown(halttype); - -- /* Give warnings on regular intervals and finally shutdown. */ -- if (wt < 15 && !needwarning(wt)) warn(wt); -- while(wt) { -- if (wt <= 5 && !didnolog) { -- donologin(wt); -- didnolog++; -+ /* Give warnings on regular intervals and finally shutdown. */ -+ if (wt < 15 && !needwarning(wt)) warn(wt); -+ while(wt) { -+ if (wt <= 5 && !didnolog) { -+ donologin(wt); -+ didnolog++; -+ } -+ if (needwarning(wt)) warn(wt); -+ hardsleep(60); -+ wt--; - } -- if (needwarning(wt)) warn(wt); -- hardsleep(60); -- wt--; -- } -- shutdown(); -- return(0); /* Never happens */ -+ shutdown(halttype); -+ -+ return 0; /* Never happens */ - } -Binary files sysvinit-2.85/src/shutdown.o and sysvinit-2.86/src/shutdown.o differ -Binary files sysvinit-2.85/src/sulogin and sysvinit-2.86/src/sulogin differ -diff -urNd -urNd sysvinit-2.85/src/sulogin.c sysvinit-2.86/src/sulogin.c ---- sysvinit-2.85/src/sulogin.c 2003-04-14 04:53:49.000000000 -0500 -+++ sysvinit-2.86/src/sulogin.c 2004-07-30 06:40:28.000000000 -0500 -@@ -8,7 +8,7 @@ - * encrypted root password is "x" the shadow - * password will be used. - * -- * Version: @(#)sulogin 2.85 14-Apr-2003 miquels@cistron.nl -+ * Version: @(#)sulogin 2.85-3 23-Apr-2003 miquels@cistron.nl - * - */ - -@@ -35,11 +35,15 @@ - #define F_SHADOW "/etc/shadow" - #define BINSH "/bin/sh" - --char *Version = "@(#)sulogin 2.85 14-Apr-2003 miquels@cistron.nl"; -+char *Version = "@(#)sulogin 2.85-3 23-Apr-2003 miquels@cistron.nl"; - - int timeout = 0; - int profile = 0; - -+#ifndef IUCLC -+# define IUCLC 0 -+#endif -+ - #if 0 - /* - * Fix the tty modes and set reasonable defaults. -@@ -252,7 +256,7 @@ - printf("Give root password for maintenance\n"); - else - printf("Press enter for maintenance\n"); -- printf("(or type Control-D for normal startup): "); -+ printf("(or type Control-D to continue): "); - fflush(stdout); - - tcgetattr(0, &old); -Binary files sysvinit-2.85/src/sulogin.o and sysvinit-2.86/src/sulogin.o differ -Binary files sysvinit-2.85/src/utmp.o and sysvinit-2.86/src/utmp.o differ |