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
