generic-poky/meta/packages/sysvinit/sysvinit-2.86/sysvinit-2.86.patch

4881 lines
126 KiB
Diff

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