summaryrefslogtreecommitdiffstats
path: root/meta/packages/sysvinit/sysvinit-2.86/sysvinit-2.86.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/packages/sysvinit/sysvinit-2.86/sysvinit-2.86.patch')
-rw-r--r--meta/packages/sysvinit/sysvinit-2.86/sysvinit-2.86.patch4880
1 files changed, 4880 insertions, 0 deletions
diff --git a/meta/packages/sysvinit/sysvinit-2.86/sysvinit-2.86.patch b/meta/packages/sysvinit/sysvinit-2.86/sysvinit-2.86.patch
new file mode 100644
index 0000000000..b83f525c3e
--- /dev/null
+++ b/meta/packages/sysvinit/sysvinit-2.86/sysvinit-2.86.patch
@@ -0,0 +1,4880 @@
1diff -urNd -urNd sysvinit-2.85/COPYRIGHT sysvinit-2.86/COPYRIGHT
2--- sysvinit-2.85/COPYRIGHT 2003-04-15 03:45:44.000000000 -0500
3+++ sysvinit-2.86/COPYRIGHT 2004-07-30 07:12:12.000000000 -0500
4@@ -1,4 +1,4 @@
5-Sysvinit is Copyright (C) 1991-2003 Miquel van Smoorenburg
6+Sysvinit is Copyright (C) 1991-2004 Miquel van Smoorenburg
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10diff -urNd -urNd sysvinit-2.85/doc/Changelog sysvinit-2.86/doc/Changelog
11--- sysvinit-2.85/doc/Changelog 2003-04-15 09:37:58.000000000 -0500
12+++ sysvinit-2.86/doc/Changelog 2004-07-30 07:15:06.000000000 -0500
13@@ -1,3 +1,29 @@
14+sysvinit (2.86) cistron; urgency=low
15+
16+ * Fixed up bootlogd to read /proc/cmdline. Also keep an internal
17+ linebuffer to process \r, \t and ^H. It is becoming useable.
18+ * Applied trivial OWL patches
19+ * Block signals in syslog(), since syslog() is not re-entrant
20+ (James Olin Oden <joden@malachi.lee.k12.nc.us>, redhat bug #97534)
21+ * Minor adjustements so that sysvinit compiles on the Hurd
22+ * killall5 now skips kernel threads
23+ * Inittab entries with both 'S' and other runlevels were broken.
24+ Fix by Bryan Kadzban <bryan@kadzban.is-a-geek.net>
25+ * Changed initreq.h to be more flexible and forwards-compatible.
26+ * You can now through /dev/initctl set environment variables in
27+ init that will be inherited by its children. For now, only
28+ variables prefixed with INIT_ can be set and the maximum is
29+ 16 variables. There's also a length limit due to the size
30+ of struct init_request, so it should be safe from abuse.
31+ * Option -P and -H to shutdown set INIT_HALT=POWERDOWN and
32+ INIT_HALT=HALT as environment variables as described above
33+ * Add "mountpoint" utility.
34+ * Slightly better algorithm in killall5.c:pidof()
35+ * Added some patches from fedora-core (halt-usage, last -t,
36+ sulogin-message, user-console)
37+
38+ -- Miquel van Smoorenburg <miquels@cistron.nl> Fri, 30 Jul 2004 14:14:58 +0200
39+
40 sysvinit (2.85) cistron; urgency=low
41
42 * Add IPv6 support in last(1)
43diff -urNd -urNd sysvinit-2.85/doc/Install sysvinit-2.86/doc/Install
44--- sysvinit-2.85/doc/Install 2003-04-15 03:46:49.000000000 -0500
45+++ sysvinit-2.86/doc/Install 2004-07-30 07:15:40.000000000 -0500
46@@ -1,5 +1,5 @@
47
48- README for the System V style init, version 2.85
49+ README for the System V style init, version 2.86
50
51 init, shutdown, halt, reboot, wall, last, mesg, runlevel,
52 killall5, pidof, sulogin.
53diff -urNd -urNd sysvinit-2.85/doc/bootlogd.README sysvinit-2.86/doc/bootlogd.README
54--- sysvinit-2.85/doc/bootlogd.README 2000-09-12 16:54:31.000000000 -0500
55+++ sysvinit-2.86/doc/bootlogd.README 2004-06-09 07:47:45.000000000 -0500
56@@ -1,10 +1,12 @@
57
58 bootlogd: a way to capture all console output during bootup
59- in a logfile. ** PROOF OF CONCEPT IMPLEMENTATION **
60+ in a logfile.
61
62-- bootlogd opens /dev/console
63-- finds out what the real console is with an ioctl()
64-- then opens the real console
65+- bootlogd opens /dev/console and finds out what the real console is
66+ with an ioctl() if TIOCCONS is available
67+- otherwise bootlogd tries to parse /proc/cmdline for console=
68+ kernel command line arguments
69+- then opens the (most probable) real console
70 - allocates a pty pair
71 - redirects console I/O to the pty pair
72 - then goes in a loop reading from the pty, writing to the real
73diff -urNd -urNd sysvinit-2.85/doc/sysvinit-2.85.lsm sysvinit-2.86/doc/sysvinit-2.85.lsm
74--- sysvinit-2.85/doc/sysvinit-2.85.lsm 2003-04-18 16:04:12.000000000 -0500
75+++ sysvinit-2.86/doc/sysvinit-2.85.lsm 2004-06-09 07:47:45.000000000 -0500
76@@ -1,7 +1,7 @@
77 Begin3
78 Title: sysvinit and utilities
79 Version: 2.85
80-Entered-Date: 18APR2003
81+Entered-Date: 15APR2003
82 Description: This is the Linux System V init.
83 This version can be compiled with glibc 2.0.6 and up.
84 Author: miquels@cistron.nl (Miquel van Smoorenburg)
85diff -urNd -urNd sysvinit-2.85/doc/sysvinit-2.86.lsm sysvinit-2.86/doc/sysvinit-2.86.lsm
86--- sysvinit-2.85/doc/sysvinit-2.86.lsm 1969-12-31 18:00:00.000000000 -0600
87+++ sysvinit-2.86/doc/sysvinit-2.86.lsm 2004-07-31 08:35:28.000000000 -0500
88@@ -0,0 +1,14 @@
89+Begin3
90+Title: sysvinit and utilities
91+Version: 2.86
92+Entered-Date: 30JUL2004
93+Description: This is the Linux System V init.
94+ This version can be compiled with glibc 2.0.6 and up.
95+Author: miquels@cistron.nl (Miquel van Smoorenburg)
96+Primary-Site: ftp.cistron.nl /pub/people/miquels/software
97+ 92K sysvinit-2.86.tar.gz
98+Alternate-Site: sunsite.unc.edu /pub/Linux/system/daemons/init
99+ 92K sysvinit-2.86.tar.gz
100+Copying-Policy: GPL
101+Keywords: init shutdown halt reboot
102+End
103diff -urNd -urNd sysvinit-2.85/man/bootlogd.8 sysvinit-2.86/man/bootlogd.8
104--- sysvinit-2.85/man/bootlogd.8 1969-12-31 18:00:00.000000000 -0600
105+++ sysvinit-2.86/man/bootlogd.8 2004-06-09 07:47:45.000000000 -0500
106@@ -0,0 +1,39 @@
107+.TH BOOTLOGD 8 "Jul 21, 2003" "" "Linux System Administrator's Manual"
108+.SH NAME
109+bootlogd \- record boot messages
110+.SH SYNOPSIS
111+.B /sbin/bootlogd
112+.RB [ \-d ]
113+.RB [ \-r ]
114+.RB [ \-v ]
115+.RB [ " -l logfile " ]
116+.RB [ " -p pidfile " ]
117+.SH DESCRIPTION
118+\fBBootlogd\fP runs in the background and copies all strings sent to the
119+\fI/dev/console\fP device to a logfile. If the logfile is not accessible,
120+the messages will be buffered in-memory until it is.
121+.SH OPTIONS
122+.IP \fB\-d\fP
123+Do not fork and run in the background.
124+.IP \fB\-r\fP
125+If there is an existing logfile called \fIlogfile\fP rename it to
126+\fIlogfile~\fP unless \fIlogfile~\fP already exists.
127+.IP \fB\-v\fP
128+Show version.
129+.IP \fB\-l logfile\fP
130+Log to this logfile. The default is \fI/var/log/boot\fP.
131+.IP \fB\-p pidfile\fP
132+Put process-id in this file. The default is no pidfile.
133+.SH BUGS
134+Bootlogd works by redirecting the console output from the console
135+device. It copies that output to the real console device and a
136+logfile. There is no standard way to find out the real console device
137+if you have a new-style \fI/dev/console\fP device (major 5, minor 1).
138+\fBBootlogd\fP tries to parse the kernel command line, looking for
139+console= lines and deducts the real console device from that. If that
140+syntax is ever changed by the kernel, or a console-type is used
141+bootlogd does not know about, bootlogd will not work.
142+.SH AUTHOR
143+Miquel van Smoorenburg, miquels@cistron.nl
144+.SH "SEE ALSO"
145+.BR dmesg (8)
146diff -urNd -urNd sysvinit-2.85/man/init.8 sysvinit-2.86/man/init.8
147--- sysvinit-2.85/man/init.8 2003-04-18 16:05:03.000000000 -0500
148+++ sysvinit-2.86/man/init.8 2004-07-29 06:21:31.000000000 -0500
149@@ -1,6 +1,6 @@
150 .\"{{{}}}
151 .\"{{{ Title
152-.TH INIT 8 "18 April 2003" "" "Linux System Administrator's Manual"
153+.TH INIT 8 "29 Jul 2004" "" "Linux System Administrator's Manual"
154 .\"}}}
155 .\"{{{ Name
156 .SH NAME
157@@ -160,7 +160,7 @@
158 .SH ENVIRONMENT
159 \fBInit\fP sets the following environment variables for all its children:
160 .IP \fBPATH\fP
161-\fI/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin\fP
162+\fI/bin:/usr/bin:/sbin:/usr/sbin\fP
163 .IP \fBINIT_VERSION\fP
164 As the name says. Useful to determine if a script runs directly from \fBinit\fP.
165 .IP \fBRUNLEVEL\fP
166diff -urNd -urNd sysvinit-2.85/man/initscript.5 sysvinit-2.86/man/initscript.5
167--- sysvinit-2.85/man/initscript.5 1999-12-24 16:31:21.000000000 -0600
168+++ sysvinit-2.86/man/initscript.5 2004-06-09 07:47:45.000000000 -0500
169@@ -1,4 +1,4 @@
170-.TH INITSCRIPT 5 "December 24, 1999" "" "Linux System Administrator's Manual"
171+.TH INITSCRIPT 5 "July 10, 2003" "" "Linux System Administrator's Manual"
172 .SH NAME
173 initscript \- script that executes inittab commands.
174 .SH SYNOPSIS
175@@ -40,6 +40,12 @@
176
177 .sp
178 .RE
179+.SH NOTES
180+This script is not meant as startup script for daemons or somesuch.
181+It has nothing to do with a \fIrc.local\fP style script. It's just
182+a handler for things executed from \fB/etc/inittab\fP. Experimenting
183+with this can make your system un(re)bootable.
184+.RE
185 .SH FILES
186 /etc/inittab,
187 /etc/initscript.
188diff -urNd -urNd sysvinit-2.85/man/killall5.8 sysvinit-2.86/man/killall5.8
189--- sysvinit-2.85/man/killall5.8 1997-05-27 05:34:21.000000000 -0500
190+++ sysvinit-2.86/man/killall5.8 2004-06-09 07:47:45.000000000 -0500
191@@ -1,4 +1,4 @@
192-.TH KILLALL5 8 "27 May 1997" "" "Linux System Administrator's Manual"
193+.TH KILLALL5 8 "04 Nov 2003" "" "Linux System Administrator's Manual"
194 .SH NAME
195 killall5 -- send a signal to all processes.
196 .SH SYNOPSIS
197@@ -7,9 +7,9 @@
198 .SH DESCRIPTION
199 .B killall5
200 is the SystemV killall command. It sends a signal to all processes except
201-the processes in its own session, so it won't kill the shell that is
202-running the script it was called from. Its primary (only) use is in the
203-\fBrc\fP scripts found in the /etc/init.d directory.
204+kernel threads and the processes in its own session, so it won't kill
205+the shell that is running the script it was called from. Its primary
206+(only) use is in the \fBrc\fP scripts found in the /etc/init.d directory.
207 .SH SEE ALSO
208 .BR halt (8),
209 .BR reboot (8)
210diff -urNd -urNd sysvinit-2.85/man/last.1 sysvinit-2.86/man/last.1
211--- sysvinit-2.85/man/last.1 1999-07-29 05:50:34.000000000 -0500
212+++ sysvinit-2.86/man/last.1 2004-07-30 06:39:18.000000000 -0500
213@@ -1,6 +1,6 @@
214 .\"{{{}}}
215 .\"{{{ Title
216-.TH LAST,LASTB 1 "Jul 29, 1999" "" "Linux System Administrator's Manual"
217+.TH LAST,LASTB 1 "Jul 31, 2004" "" "Linux System Administrator's Manual"
218 .\"}}}
219 .\"{{{ Name
220 .SH NAME
221@@ -14,6 +14,7 @@
222 .RB "[ \-\fBn\fP \fInum\fP ]"
223 .RB [ \-adiox ]
224 .RB "[ \-\fBf\fP \fIfile\fP ]"
225+.RB "[ \-\fBt\fP \fIYYYYMMDDHHMMSS\fP ]"
226 .RI [ name... ]
227 .RI [ tty... ]
228 .br
229@@ -54,6 +55,11 @@
230 This is a count telling \fBlast\fP how many lines to show.
231 .IP "\fB\-n\fP \fInum\fP"
232 The same.
233+.IP "\fB\-t\fP \fIYYYYMMDDHHMMSS\fP"
234+Display the state of logins as of the specified time. This is
235+useful, e.g., to determine easily who was logged in at a particular
236+time -- specify that time with \fB\-t\fP and look for "still logged
237+in".
238 .IP \fB\-R\fP
239 Suppresses the display of the hostname field.
240 .IP \fB\-a\fP
241diff -urNd -urNd sysvinit-2.85/man/mesg.1 sysvinit-2.86/man/mesg.1
242--- sysvinit-2.85/man/mesg.1 2001-02-26 06:01:10.000000000 -0600
243+++ sysvinit-2.86/man/mesg.1 2004-06-09 07:47:45.000000000 -0500
244@@ -27,7 +27,7 @@
245 If no option is given, \fBmesg\fP prints out the current access state of your
246 terminal.
247 .PP NOTES
248-\fBMesg\fP assumes that it's standard input is connected to your
249+\fBMesg\fP assumes that its standard input is connected to your
250 terminal. That also means that if you are logged in multiple times,
251 you can get/set the mesg status of other sessions by using redirection.
252 For example "mesg n < /dev/pts/46".
253diff -urNd -urNd sysvinit-2.85/man/mountpoint.1 sysvinit-2.86/man/mountpoint.1
254--- sysvinit-2.85/man/mountpoint.1 1969-12-31 18:00:00.000000000 -0600
255+++ sysvinit-2.86/man/mountpoint.1 2004-06-09 07:47:45.000000000 -0500
256@@ -0,0 +1,37 @@
257+.TH MOUNTPOINT 8 "Mar 15, 2004" "" "Linux System Administrator's Manual"
258+.SH NAME
259+mountpoint \- see if a directory is a mountpoint
260+.SH SYNOPSIS
261+.B /bin/mountpoint
262+.RB [ \-q ]
263+.RB [ \-d ]
264+.I /path/to/directory
265+.br
266+.B /bin/mountpoint
267+.RB \-x
268+.I /dev/device
269+.SH DESCRIPTION
270+\fBMountpoint\fP checks if the directory is a mountpoint.
271+
272+.SH OPTIONS
273+.IP \fB\-q\fP
274+Be quiet - don't print anything.
275+.IP \fB\-d\fP
276+Print major/minor device number of the filesystem on stdout.
277+.IP \fB\-x\fP
278+Print major/minor device number of the blockdevice on stdout.
279+.SH EXIT STATUS
280+Zero if the directory is a mountpoint, non-zero if not.
281+.SH NOTES
282+Symbolic links are not followed, except when the \fB-x\fP option is
283+used. To force following symlinks, add a trailing slash to the
284+path of the directory.
285+.PP
286+The name of the command is misleading when the -x option is used,
287+but the option is useful for comparing if a directory and a device
288+match up, and there is no other command that can print the info easily.
289+.PP
290+.SH AUTHOR
291+Miquel van Smoorenburg, miquels@cistron.nl
292+.SH "SEE ALSO"
293+.BR stat (1)
294diff -urNd -urNd sysvinit-2.85/man/shutdown.8 sysvinit-2.86/man/shutdown.8
295--- sysvinit-2.85/man/shutdown.8 2001-10-02 16:27:50.000000000 -0500
296+++ sysvinit-2.86/man/shutdown.8 2004-06-09 07:47:45.000000000 -0500
297@@ -1,6 +1,6 @@
298 .\"{{{}}}
299 .\"{{{ Title
300-.TH SHUTDOWN 8 "Juli 31, 2001" "" "Linux System Administrator's Manual"
301+.TH SHUTDOWN 8 "November 12, 2003" "" "Linux System Administrator's Manual"
302 .\"}}}
303 .\"{{{ Name
304 .SH NAME
305@@ -11,7 +11,7 @@
306 .B /sbin/shutdown
307 .RB [ \-t
308 .IR sec ]
309-.RB [ \-arkhncfF ]
310+.RB [ \-arkhncfFHP ]
311 .I time
312 .RI [ warning-message ]
313 .\"}}}
314@@ -54,7 +54,16 @@
315 .\"}}}
316 .\"{{{ -h
317 .IP \fB\-h\fP
318-Halt after shutdown.
319+Halt or poweroff after shutdown.
320+.\"}}}
321+.\"{{{ -H
322+.IP \fB\-H\fP
323+Halt action is to halt or drop into boot monitor on systems that
324+support it.
325+.\"}}}
326+.\"{{{ -P
327+.IP \fB\-P\fP
328+Halt action is to turn off the power.
329 .\"}}}
330 .\"{{{ -n
331 .IP \fB\-n\fP
332@@ -141,6 +150,14 @@
333 .sp 1
334 Note that if \fI/etc/shutdown.allow\fP is not present, the \fB-a\fP
335 argument is ignored.
336+.SH HALT OR POWEROFF
337+The \fB-H\fP option just sets the \fIinit\fP environment variable
338+\fIINIT_HALT\fP to \fIHALT\fP, and the \fB-P\fP option just sets
339+that variable to \fIPOWEROFF\fP. The shutdown script that calls
340+\fBhalt\fP(8) as the last thing in the shutdown sequence should
341+check these environment variables and call \fBhalt\fP(8) with
342+the right options for these options to actually have any effect.
343+Debian 3.1 (sarge) supports this.
344 .SH FILES
345 .nf
346 /fastboot
347diff -urNd -urNd sysvinit-2.85/man/sulogin.8 sysvinit-2.86/man/sulogin.8
348--- sysvinit-2.85/man/sulogin.8 2000-09-11 07:19:25.000000000 -0500
349+++ sysvinit-2.86/man/sulogin.8 2004-06-09 07:47:45.000000000 -0500
350@@ -1,4 +1,4 @@
351-.TH SULOGIN 8 "11 Sep 2000" "" "Linux System Administrator's Manual"
352+.TH SULOGIN 8 "04 Nov 2003" "" "Linux System Administrator's Manual"
353 .SH NAME
354 sulogin -- Single-user login
355 .SH SYNOPSIS
356@@ -20,7 +20,7 @@
357 .br
358 (or type Control-D for normal startup):
359 .PP
360-\fIsulogin\fP will connected to the current terminal, or to the
361+\fIsulogin\fP will be connected to the current terminal, or to the
362 optional device that can be specified on the command line
363 (typically \fB/dev/console\fP).
364 .PP
365@@ -45,16 +45,18 @@
366 .PP
367 boot: linux -b rw sushell=/sbin/sash
368 .SH FALLBACK METHODS
369-\fIsulogin\fP checks the root password using the standard methods first.
370-If the \fB-e\fP option was specified,
371-\fIsulogin\fP examines the next files to find the root password. If
372-they are damaged, or non-existant, it will use fallback methods that
373-even go so far as to provide you with a shell prompt without asking
374-for the root password if they are irrepairably damaged.
375+\fIsulogin\fP checks the root password using the standard method (getpwnam)
376+first.
377+Then, if the \fB-e\fP option was specified,
378+\fIsulogin\fP examines these files directly to find the root password:
379 .PP
380 /etc/passwd,
381 .br
382 /etc/shadow (if present)
383+.PP
384+If they are damaged or non-existant, sulogin will start a root shell
385+without asking for a password. Only use the \fB-e\fP option if you
386+are sure the console is physically protected against unauthorized access.
387 .SH AUTHOR
388 Miquel van Smoorenburg <miquels@cistron.nl>
389 .SH SEE ALSO
390diff -urNd -urNd sysvinit-2.85/man/wall.1 sysvinit-2.86/man/wall.1
391--- sysvinit-2.85/man/wall.1 2003-04-16 04:17:38.000000000 -0500
392+++ sysvinit-2.86/man/wall.1 2004-06-09 07:47:45.000000000 -0500
393@@ -47,7 +47,7 @@
394 .I Wall
395 ignores the
396 .B TZ
397-variable - the time printed in the banner is based on the systems
398+variable - the time printed in the banner is based on the system's
399 local time.
400
401 .SH SEE ALSO
402diff -urNd -urNd sysvinit-2.85/src/Makefile sysvinit-2.86/src/Makefile
403--- sysvinit-2.85/src/Makefile 2001-11-06 05:58:16.000000000 -0600
404+++ sysvinit-2.86/src/Makefile 2004-06-09 07:47:45.000000000 -0500
405@@ -5,34 +5,56 @@
406 # clean cleans up object files
407 # clobber really cleans up
408 #
409-# Version: @(#)Makefile 2.83-3 06-Nov-2001 miquels@cistron.nl
410+# Version: @(#)Makefile 2.85-13 23-Mar-2004 miquels@cistron.nl
411 #
412
413-CC = cc
414-CFLAGS = -Wall -O2 -D_GNU_SOURCE
415+CC = gcc
416+CFLAGS = -Wall -O2 -fomit-frame-pointer -D_GNU_SOURCE
417 LDFLAGS = -s
418 STATIC =
419
420-# For Debian we do not build all programs, otherwise we do.
421-ifeq ($(DEBIAN),)
422-PROGS = init halt shutdown killall5 runlevel sulogin utmpdump \
423- last mesg wall
424-else
425-PROGS = init halt shutdown killall5 runlevel sulogin last mesg
426+# For some known distributions we do not build all programs, otherwise we do.
427+BIN =
428+SBIN = init halt shutdown runlevel killall5
429+USRBIN = last mesg
430+
431+MAN1 = last.1 lastb.1 mesg.1
432+MAN5 = initscript.5 inittab.5
433+MAN8 = halt.8 init.8 killall5.8 pidof.8 poweroff.8 reboot.8 runlevel.8
434+MAN8 += shutdown.8 telinit.8
435+
436+ifeq ($(DISTRO),)
437+BIN += mountpoint
438+SBIN += sulogin bootlogd
439+USRBIN += utmpdump wall
440+MAN1 += mountpoint.1 wall.1
441+MAN8 += sulogin.8 bootlogd.8
442+endif
443+
444+ifeq ($(DISTRO),Debian)
445+BIN += mountpoint
446+SBIN += sulogin bootlogd
447+MAN1 += mountpoint.1
448+MAN8 += sulogin.8 bootlogd.8
449+endif
450+
451+ifeq ($(DISTRO),Owl)
452+USRBIN += wall
453+MAN1 += wall.1
454 endif
455
456 BIN_OWNER = root
457 BIN_GROUP = root
458-BIN_COMBO = $(BIN_OWNER).$(BIN_GROUP)
459+BIN_COMBO = $(BIN_OWNER):$(BIN_GROUP)
460 INSTALL = install -o $(BIN_OWNER) -g $(BIN_GROUP)
461 MANDIR = /usr/share/man
462
463-# Additional libs for Gnu Libc
464+# Additional libs for GNU libc.
465 ifneq ($(wildcard /usr/lib/libcrypt.a),)
466 LCRYPT = -lcrypt
467 endif
468
469-all: $(PROGS)
470+all: $(BIN) $(SBIN) $(USRBIN)
471
472 init: init.o init_utmp.o
473 $(CC) $(LDFLAGS) $(STATIC) -o $@ init.o init_utmp.o
474@@ -46,6 +68,9 @@
475 mesg: mesg.o
476 $(CC) $(LDFLAGS) -o $@ mesg.o
477
478+mountpoint: mountpoint.o
479+ $(CC) $(LDFLAGS) -o $@ mountpoint.o
480+
481 utmpdump: utmpdump.o
482 $(CC) $(LDFLAGS) -o $@ utmpdump.o
483
484@@ -62,9 +87,9 @@
485 $(CC) $(LDFLAGS) -o $@ dowall.o shutdown.o utmp.o
486
487 bootlogd: bootlogd.o
488- $(CC) $(LDFLAGS) -o $@ bootlogd.o
489+ $(CC) $(LDFLAGS) -o $@ bootlogd.o -lutil
490
491-init.o: init.c init.h set.h reboot.h
492+init.o: init.c init.h set.h reboot.h initreq.h
493 $(CC) -c $(CFLAGS) init.c
494
495 utmp.o: utmp.c init.h
496@@ -80,36 +105,44 @@
497 @echo Type \"make clobber\" to really clean up.
498
499 clobber: cleanobjs
500- rm -f $(PROGS)
501+ rm -f $(BIN) $(SBIN) $(USRBIN)
502
503 distclean: clobber
504
505 install:
506- $(INSTALL) -m 755 halt init killall5 sulogin \
507- runlevel shutdown $(ROOT)/sbin
508- # These are not installed by default
509-ifeq ($(DEBIAN),)
510- $(INSTALL) -m 555 utmpdump wall $(ROOT)/usr/bin
511-endif
512- # $(INSTALL) -m 755 etc/initscript.sample $(ROOT)/etc
513- $(INSTALL) -m 755 mesg last $(ROOT)/usr/bin
514- cd $(ROOT)/sbin; ln -sf halt reboot; chown $(BIN_COMBO) reboot
515- cd $(ROOT)/sbin; ln -sf halt poweroff; chown $(BIN_COMBO) poweroff
516- cd $(ROOT)/sbin; ln -sf init telinit; chown $(BIN_COMBO) telinit
517- cd $(ROOT)/bin; ln -sf ../sbin/killall5 pidof; chown $(BIN_COMBO) pidof
518- cd $(ROOT)/usr/bin; ln -sf last lastb; chown $(BIN_COMBO) lastb
519- $(INSTALL) -m 644 initreq.h $(ROOT)/usr/include
520- $(INSTALL) -m 644 ../man/*.8 $(ROOT)$(MANDIR)/man8
521- $(INSTALL) -m 644 ../man/*.5 $(ROOT)$(MANDIR)/man5
522-ifeq ($(DEBIAN),)
523- $(INSTALL) -m 644 ../man/wall.1 $(ROOT)$(MANDIR)/man1
524-endif
525- $(INSTALL) -m 644 ../man/last.1 ../man/lastb.1 ../man/mesg.1 \
526- $(ROOT)$(MANDIR)/man1
527+ for i in $(BIN); do \
528+ $(INSTALL) -m 755 $$i $(ROOT)/bin/; \
529+ done
530+ for i in $(SBIN); do \
531+ $(INSTALL) -m 755 $$i $(ROOT)/sbin/; \
532+ done
533+ for i in $(USRBIN); do \
534+ $(INSTALL) -m 755 $$i $(ROOT)/usr/bin/; \
535+ done
536+ # $(INSTALL) -m 755 etc/initscript.sample $(ROOT)/etc/
537+ ln -sf halt $(ROOT)/sbin/reboot
538+ ln -sf halt $(ROOT)/sbin/poweroff
539+ ln -sf init $(ROOT)/sbin/telinit
540+ ln -sf ../sbin/killall5 $(ROOT)/bin/pidof
541+ if [ ! -f $(ROOT)/usr/bin/lastb ]; then \
542+ ln -sf last $(ROOT)/usr/bin/lastb; \
543+ fi
544+ $(INSTALL) -m 644 initreq.h $(ROOT)/usr/include/
545+ for i in $(MAN1); do \
546+ $(INSTALL) -m 644 ../man/$$i $(ROOT)$(MANDIR)/man1/; \
547+ done
548+ for i in $(MAN5); do \
549+ $(INSTALL) -m 644 ../man/$$i $(ROOT)$(MANDIR)/man5/; \
550+ done
551+ for i in $(MAN8); do \
552+ $(INSTALL) -m 644 ../man/$$i $(ROOT)$(MANDIR)/man8/; \
553+ done
554+ifeq ($(ROOT),)
555 #
556- # This part is skipped on debian systems, the
557+ # This part is skipped on Debian systems, the
558 # debian.preinst script takes care of it.
559 @if [ ! -p /dev/initctl ]; then \
560 echo "Creating /dev/initctl"; \
561 rm -f /dev/initctl; \
562 mknod -m 600 /dev/initctl p; fi
563+endif
564Binary files sysvinit-2.85/src/bootlogd and sysvinit-2.86/src/bootlogd differ
565diff -urNd -urNd sysvinit-2.85/src/bootlogd.c sysvinit-2.86/src/bootlogd.c
566--- sysvinit-2.85/src/bootlogd.c 2001-12-09 08:01:28.000000000 -0600
567+++ sysvinit-2.86/src/bootlogd.c 2004-06-09 07:47:45.000000000 -0500
568@@ -3,12 +3,12 @@
569 * The file is usually located on the /var partition, and
570 * gets written (and fsynced) as soon as possible.
571 *
572- * Version: @(#)bootlogd 2.79 11-Sep-2000 miquels@cistron.nl
573+ * Version: @(#)bootlogd 2.86pre 12-Jan-2004 miquels@cistron.nl
574 *
575 * Bugs: Uses openpty(), only available in glibc. Sorry.
576 *
577 * This file is part of the sysvinit suite,
578- * Copyright 1991-2000 Miquel van Smoorenburg.
579+ * Copyright 1991-2004 Miquel van Smoorenburg.
580 *
581 * This program is free software; you can redistribute it and/or
582 * modify it under the terms of the GNU General Public License
583@@ -17,7 +17,9 @@
584 *
585 * *NOTE* *NOTE* *NOTE*
586 * This is a PROOF OF CONCEPT IMPLEMENTATION
587- * I do not recommend using this on production systems.
588+ *
589+ * I have bigger plans for Debian, but for now
590+ * this has to do ;)
591 *
592 */
593
594@@ -38,18 +40,14 @@
595 #include <dirent.h>
596 #include <fcntl.h>
597 #include <pty.h>
598-
599-char *Version = "@(#) bootlogd 2.79 11-Sep-2000 MvS";
600-
601-/*
602- * Until the kernel knows about TIOCGDEV, use a really ugly
603- * non-portable (not even between architectures) hack.
604- */
605-#ifndef TIOCGDEV
606-# define TIOCTTYGSTRUCT_HACK 1
607+#include <ctype.h>
608+#ifdef __linux__
609+#include <sys/mount.h>
610 #endif
611
612-#define LOGFILE "/var/log/boot.log"
613+char *Version = "@(#) bootlogd 2.86 03-Jun-2004 miquels@cistron.nl";
614+
615+#define LOGFILE "/var/log/boot"
616
617 char ringbuf[32768];
618 char *endptr = ringbuf + sizeof(ringbuf);
619@@ -59,29 +57,32 @@
620 int got_signal = 0;
621 int didnl = 1;
622
623+struct line {
624+ char buf[256];
625+ int pos;
626+} line;
627
628-#ifdef TIOCTTYGSTRUCT_HACK
629-struct tty_offsets {
630- char *kver;
631- int offset;
632-} tty_offsets[] = {
633-#if ((~0UL) == 0xffffffff) /* 32 bits */
634- { "2.0.", 236 },
635- { "2.1.", 268 },
636- { "2.2.", 272 },
637- { "2.3.", 272 },
638- { "2.4.", 272 },
639- { "2.5.", 272 },
640-#else /* 64 bits */
641- { "2.2.", 480 },
642- { "2.3.", 480 },
643- { "2.4.", 480 },
644- { "2.5.", 480 },
645-#endif
646- { NULL, 0 },
647+/*
648+ * Console devices as listed on the kernel command line and
649+ * the mapping to actual devices in /dev
650+ */
651+struct consdev {
652+ char *cmdline;
653+ char *dev1;
654+ char *dev2;
655+} consdev[] = {
656+ { "ttySC", "/dev/ttySC%s", "/dev/ttsc/%s" },
657+ { "ttyS", "/dev/ttyS%s", "/dev/tts/%s" },
658+ { "tty", "/dev/tty%s", "/dev/vc/%s" },
659+ { "hvc", "/dev/hvc%s", "/dev/hvc/%s" },
660+ { NULL, NULL, NULL },
661 };
662-#endif
663
664+/*
665+ * Devices to try as console if not found on kernel command line.
666+ * Tried from left to right (as opposed to kernel cmdline).
667+ */
668+char *defcons[] = { "tty0", "hvc0", "ttyS0", "ttySC0", NULL };
669
670 /*
671 * Catch signals.
672@@ -95,6 +96,8 @@
673 /*
674 * Scan /dev and find the device name.
675 * Side-effect: directory is changed to /dev
676+ *
677+ * FIXME: scan subdirectories for devfs support ?
678 */
679 int findtty(char *res, int rlen, dev_t dev)
680 {
681@@ -117,18 +120,88 @@
682 }
683 }
684 if (ent == NULL) {
685- fprintf(stderr, "bootlogd: cannot find console device\n");
686+ fprintf(stderr, "bootlogd: cannot find console device "
687+ "%d:%d in /dev\n", major(dev), minor(dev));
688 r = -1;
689- } else if (strlen(ent->d_name) >= rlen) {
690+ } else if (strlen(ent->d_name) + 5 >= rlen) {
691 fprintf(stderr, "bootlogd: console device name too long\n");
692 r = -1;
693 } else
694- strcpy(res, ent->d_name);
695+ snprintf(res, rlen, "/dev/%s", ent->d_name);
696 closedir(dir);
697
698 return r;
699 }
700
701+/*
702+ * For some reason, openpty() in glibc sometimes doesn't
703+ * work at boot-time. It must be a bug with old-style pty
704+ * names, as new-style (/dev/pts) is not available at that
705+ * point. So, we find a pty/tty pair ourself if openpty()
706+ * fails for whatever reason.
707+ */
708+int findpty(int *master, int *slave, char *name)
709+{
710+ char pty[16];
711+ char tty[16];
712+ int i, j;
713+ int found;
714+
715+ if (openpty(master, slave, name, NULL, NULL) >= 0)
716+ return 0;
717+
718+ found = 0;
719+
720+ for (i = 'p'; i <= 'z'; i++) {
721+ for (j = '0'; j <= 'f'; j++) {
722+ if (j == '9' + 1) j = 'a';
723+ sprintf(pty, "/dev/pty%c%c", i, j);
724+ sprintf(tty, "/dev/tty%c%c", i, j);
725+ if ((*master = open(pty, O_RDWR|O_NOCTTY)) >= 0) {
726+ *slave = open(tty, O_RDWR|O_NOCTTY);
727+ if (*slave >= 0) {
728+ found = 1;
729+ break;
730+ }
731+ }
732+ }
733+ if (found) break;
734+ }
735+ if (found < 0) return -1;
736+
737+ if (name) strcpy(name, tty);
738+
739+ return 0;
740+}
741+/*
742+ * See if a console taken from the kernel command line maps
743+ * to a character device we know about, and if we can open it.
744+ */
745+int isconsole(char *s, char *res, int rlen)
746+{
747+ struct consdev *c;
748+ int l, sl, i, fd;
749+ char *p, *q;
750+
751+ sl = strlen(s);
752+
753+ for (c = consdev; c->cmdline; c++) {
754+ l = strlen(c->cmdline);
755+ if (sl <= l) continue;
756+ p = s + l;
757+ if (strncmp(s, c->cmdline, l) != 0 || !isdigit(*p))
758+ continue;
759+ for (i = 0; i < 2; i++) {
760+ snprintf(res, rlen, i ? c->dev1 : c->dev2, p);
761+ if ((q = strchr(res, ',')) != NULL) *q = 0;
762+ if ((fd = open(res, O_RDONLY|O_NONBLOCK)) >= 0) {
763+ close(fd);
764+ return 1;
765+ }
766+ }
767+ }
768+ return 0;
769+}
770
771 /*
772 * Find out the _real_ console. Assume that stdin is connected to
773@@ -136,21 +209,18 @@
774 */
775 int consolename(char *res, int rlen)
776 {
777- struct stat st;
778-#if TIOCTTYGSTRUCT_HACK
779- struct utsname uts;
780- struct tty_offsets *tt;
781- dev_t dev;
782- unsigned short *kdev;
783- char buf[4096];
784- int offset = -1;
785-#endif
786 #ifdef TIOCGDEV
787- kdev_t kdev;
788+ unsigned int kdev;
789 #endif
790+ struct stat st, st2;
791+ char buf[256];
792+ char *p;
793+ int didmount = 0;
794+ int n, r;
795+ int fd;
796
797 fstat(0, &st);
798- if (st.st_rdev != 0x0501) {
799+ if (major(st.st_rdev) != 5 || minor(st.st_rdev) != 1) {
800 /*
801 * Old kernel, can find real device easily.
802 */
803@@ -160,33 +230,78 @@
804 #ifdef TIOCGDEV
805 if (ioctl(0, TIOCGDEV, &kdev) == 0)
806 return findtty(res, rlen, (dev_t)kdev);
807- return -1;
808+ if (errno != ENOIOCTLCMD) return -1;
809 #endif
810
811+#ifdef __linux__
812 /*
813- * New kernel and new console device - hard to find
814- * out what device the real console is ..
815+ * Read /proc/cmdline.
816 */
817-#if TIOCTTYGSTRUCT_HACK
818- if (ioctl(0, TIOCTTYGSTRUCT, buf) != 0) {
819- perror("bootlogd: TIOCTTYGSTRUCT");
820+ stat("/", &st);
821+ if (stat("/proc", &st2) < 0) {
822+ perror("bootlogd: /proc");
823 return -1;
824 }
825- uname(&uts);
826- for (tt = tty_offsets; tt->kver; tt++)
827- if (!strncmp(uts.release, tt->kver, strlen(tt->kver))) {
828- offset = tt->offset;
829+ if (st.st_dev == st2.st_dev) {
830+ if (mount("proc", "/proc", "proc", 0, NULL) < 0) {
831+ perror("bootlogd: mount /proc");
832+ return -1;
833+ }
834+ didmount = 1;
835+ }
836+
837+ n = 0;
838+ r = -1;
839+ if ((fd = open("/proc/cmdline", O_RDONLY)) < 0) {
840+ perror("bootlogd: /proc/cmdline");
841+ } else {
842+ buf[0] = 0;
843+ if ((n = read(fd, buf, sizeof(buf) - 1)) >= 0)
844+ r = 0;
845+ else
846+ perror("bootlogd: /proc/cmdline");
847+ close(fd);
848+ }
849+ if (didmount) umount("/proc");
850+
851+ if (r < 0) return r;
852+
853+ /*
854+ * OK, so find console= in /proc/cmdline.
855+ * Parse in reverse, opening as we go.
856+ *
857+ * Valid console devices: ttySC, ttyS, tty, hvc.
858+ */
859+ p = buf + n;
860+ *p-- = 0;
861+ r = -1;
862+ while (p >= buf) {
863+ if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {
864+ *p-- = 0;
865+ continue;
866+ }
867+ if (strncmp(p, "console=", 8) == 0 &&
868+ isconsole(p + 8, res, rlen)) {
869+ r = 0;
870 break;
871 }
872- if (offset < 0) {
873- fprintf(stderr, "bootlogd: don't know offsetof"
874- "(struct tty_struct, device) for kernel %s\n", uts.release);
875- return -1;
876+ p--;
877 }
878- kdev = (unsigned short *)(&buf[offset]);
879- dev = (dev_t)(*kdev);
880- return findtty(res, rlen, dev);
881+
882+ if (r == 0) return r;
883 #endif
884+
885+ /*
886+ * Okay, no console on the command line -
887+ * guess the default console.
888+ */
889+ for (n = 0; defcons[n]; n++)
890+ if (isconsole(defcons[n], res, rlen))
891+ return 0;
892+
893+ fprintf(stderr, "bootlogd: cannot deduce real console device\n");
894+
895+ return -1;
896 }
897
898
899@@ -197,9 +312,13 @@
900 {
901 time_t t;
902 char *s;
903+ char tmp[8];
904 int olen = len;
905+ int dosync = 0;
906+ int tlen;
907
908 while (len > 0) {
909+ tmp[0] = 0;
910 if (didnl) {
911 time(&t);
912 s = ctime(&t);
913@@ -207,24 +326,51 @@
914 didnl = 0;
915 }
916 switch (*ptr) {
917+ case 27: /* ESC */
918+ strcpy(tmp, "^[");
919+ break;
920 case '\r':
921+ line.pos = 0;
922+ break;
923+ case 8: /* ^H */
924+ if (line.pos > 0) line.pos--;
925 break;
926 case '\n':
927 didnl = 1;
928+ dosync = 1;
929+ break;
930 case '\t':
931+ line.pos += (line.pos / 8 + 1) * 8;
932+ if (line.pos >= sizeof(line.buf))
933+ line.pos = sizeof(line.buf) - 1;
934+ break;
935 case 32 ... 127:
936 case 161 ... 255:
937- fputc(*ptr, fp);
938+ tmp[0] = *ptr;
939+ tmp[1] = 0;
940 break;
941 default:
942- fprintf(fp, "\\%03o", *ptr);
943+ sprintf(tmp, "\\%03o", *ptr);
944 break;
945 }
946 ptr++;
947 len--;
948+
949+ tlen = strlen(tmp);
950+ if (tlen && (line.pos + tlen < sizeof(line.buf))) {
951+ memcpy(line.buf + line.pos, tmp, tlen);
952+ line.pos += tlen;
953+ }
954+ if (didnl) {
955+ fprintf(fp, "%s\n", line.buf);
956+ memset(&line, 0, sizeof(line));
957+ }
958+ }
959+
960+ if (dosync) {
961+ fflush(fp);
962+ fdatasync(fileno(fp));
963 }
964- fflush(fp);
965- fdatasync(fileno(fp));
966
967 outptr += olen;
968 if (outptr >= endptr)
969@@ -242,6 +388,40 @@
970 exit(1);
971 }
972
973+int open_nb(char *buf)
974+{
975+ int fd, n;
976+
977+ if ((fd = open(buf, O_WRONLY|O_NONBLOCK|O_NOCTTY)) < 0)
978+ return -1;
979+ n = fcntl(fd, F_GETFL);
980+ n &= ~(O_NONBLOCK);
981+ fcntl(fd, F_SETFL, n);
982+
983+ return fd;
984+}
985+
986+/*
987+ * We got a write error on the real console. If its an EIO,
988+ * somebody hung up our filedescriptor, so try to re-open it.
989+ */
990+int write_err(int pts, int realfd, char *realcons, int e)
991+{
992+ int fd;
993+
994+ if (e != EIO) {
995+werr:
996+ close(pts);
997+ fprintf(stderr, "bootlogd: writing to console: %s\n",
998+ strerror(e));
999+ return -1;
1000+ }
1001+ close(realfd);
1002+ if ((fd = open_nb(realcons)) < 0)
1003+ goto werr;
1004+
1005+ return fd;
1006+}
1007
1008 int main(int argc, char **argv)
1009 {
1010@@ -249,6 +429,7 @@
1011 struct timeval tv;
1012 fd_set fds;
1013 char buf[1024];
1014+ char realcons[1024];
1015 char *p;
1016 char *logfile;
1017 char *pidfile;
1018@@ -298,23 +479,32 @@
1019 /*
1020 * Open console device directly.
1021 */
1022- if (consolename(buf, sizeof(buf)) < 0)
1023+ if (consolename(realcons, sizeof(realcons)) < 0)
1024 return 1;
1025- if ((realfd = open(buf, O_WRONLY|O_NONBLOCK)) < 0) {
1026+
1027+ if (strcmp(realcons, "/dev/tty0") == 0)
1028+ strcpy(realcons, "/dev/tty1");
1029+ if (strcmp(realcons, "/dev/vc/0") == 0)
1030+ strcpy(realcons, "/dev/vc/1");
1031+
1032+ if ((realfd = open_nb(realcons)) < 0) {
1033 fprintf(stderr, "bootlogd: %s: %s\n", buf, strerror(errno));
1034 return 1;
1035 }
1036- n = fcntl(realfd, F_GETFL);
1037- n &= ~(O_NONBLOCK);
1038- fcntl(realfd, F_SETFL, n);
1039
1040 /*
1041 * Grab a pty, and redirect console messages to it.
1042 */
1043- if (openpty(&ptm, &pts, buf, NULL, NULL) < 0) {
1044- fprintf(stderr, "bootlogd: cannot allocate pseudo tty\n");
1045+ ptm = -1;
1046+ pts = -1;
1047+ buf[0] = 0;
1048+ if (findpty(&ptm, &pts, buf) < 0) {
1049+ fprintf(stderr,
1050+ "bootlogd: cannot allocate pseudo tty: %s\n",
1051+ strerror(errno));
1052 return 1;
1053 }
1054+
1055 (void)ioctl(0, TIOCCONS, NULL);
1056 #if 1
1057 /* Work around bug in 2.1/2.2 kernels. Fixed in 2.2.13 and 2.3.18 */
1058@@ -357,8 +547,8 @@
1059 * open the logfile. There might be buffered messages
1060 * we want to write.
1061 */
1062- tv.tv_sec = fp ? 86400 : 5;
1063- tv.tv_usec = 0;
1064+ tv.tv_sec = 0;
1065+ tv.tv_usec = 500000;
1066 FD_ZERO(&fds);
1067 FD_SET(ptm, &fds);
1068 if (select(ptm + 1, &fds, NULL, NULL, &tv) == 1) {
1069@@ -374,10 +564,22 @@
1070 p = inptr;
1071 while (m > 0) {
1072 i = write(realfd, p, m);
1073- if (i <= 0) break;
1074- m -= i;
1075- p += i;
1076+ if (i >= 0) {
1077+ m -= i;
1078+ p += i;
1079+ continue;
1080+ }
1081+ /*
1082+ * Handle EIO (somebody hung
1083+ * up our filedescriptor)
1084+ */
1085+ realfd = write_err(pts, realfd,
1086+ realcons, errno);
1087+ if (realfd >= 0) continue;
1088+ got_signal = 1; /* Not really */
1089+ break;
1090 }
1091+
1092 /*
1093 * Increment buffer position. Handle
1094 * wraps, and also drag output pointer
1095@@ -410,8 +612,8 @@
1096 writelog(fp, outptr, todo);
1097 }
1098
1099- if (fp && !didnl) {
1100- fputc('\n', fp);
1101+ if (fp) {
1102+ if (!didnl) fputc('\n', fp);
1103 fclose(fp);
1104 }
1105
1106Binary files sysvinit-2.85/src/bootlogd.o and sysvinit-2.86/src/bootlogd.o differ
1107diff -urNd -urNd sysvinit-2.85/src/dowall.c sysvinit-2.86/src/dowall.c
1108--- sysvinit-2.85/src/dowall.c 2003-04-17 06:32:01.000000000 -0500
1109+++ sysvinit-2.86/src/dowall.c 2004-06-09 07:47:45.000000000 -0500
1110@@ -3,7 +3,7 @@
1111 *
1112 * Author: Miquel van Smoorenburg, miquels@cistron.nl
1113 *
1114- * Version: @(#)dowall.c 2.85-1 15-Apr-2003 miquels@cistron.nl
1115+ * Version: @(#)dowall.c 2.85-5 02-Jul-2003 miquels@cistron.nl
1116 *
1117 * This file is part of the sysvinit suite,
1118 * Copyright 1991-2003 Miquel van Smoorenburg.
1119@@ -135,6 +135,13 @@
1120 char *user, *tty;
1121 int fd, flags;
1122
1123+ /*
1124+ * Make sure tp and fd aren't in a register. Some versions
1125+ * of gcc clobber those after longjmp (or so I understand).
1126+ */
1127+ (void) &tp;
1128+ (void) &fd;
1129+
1130 getuidtty(&user, &tty);
1131
1132 /* Get the time */
1133Binary files sysvinit-2.85/src/dowall.o and sysvinit-2.86/src/dowall.o differ
1134Binary files sysvinit-2.85/src/halt and sysvinit-2.86/src/halt differ
1135diff -urNd -urNd sysvinit-2.85/src/halt.c sysvinit-2.86/src/halt.c
1136--- sysvinit-2.85/src/halt.c 2001-11-27 06:12:03.000000000 -0600
1137+++ sysvinit-2.86/src/halt.c 2004-07-30 07:16:18.000000000 -0500
1138@@ -8,12 +8,14 @@
1139 * execute an "shutdown -r". This is for compatibility with
1140 * sysvinit 2.4.
1141 *
1142- * Usage: halt [-n] [-w] [-d] [-f] [-p]
1143+ * Usage: halt [-n] [-w] [-d] [-f] [-h] [-i] [-p]
1144 * -n: don't sync before halting the system
1145 * -w: only write a wtmp reboot record and exit.
1146 * -d: don't write a wtmp record.
1147 * -f: force halt/reboot, don't call shutdown.
1148- * -p: power down the system (if possible, otherwise halt)
1149+ * -h: put harddisks in standby mode
1150+ * -i: shut down all network interfaces.
1151+ * -p: power down the system (if possible, otherwise halt).
1152 *
1153 * Reboot and halt are both this program. Reboot
1154 * is just a link to halt. Invoking the program
1155@@ -21,10 +23,10 @@
1156 *
1157 * Author: Miquel van Smoorenburg, miquels@cistron.nl
1158 *
1159- * Version: 2.84, 27-Nov-2001
1160+ * Version: 2.86, 30-Jul-2004
1161 *
1162 * This file is part of the sysvinit suite,
1163- * Copyright 1991-2001 Miquel van Smoorenburg.
1164+ * Copyright 1991-2004 Miquel van Smoorenburg.
1165 *
1166 * This program is free software; you can redistribute it and/or
1167 * modify it under the terms of the GNU General Public License
1168@@ -47,7 +49,7 @@
1169 #include <getopt.h>
1170 #include "reboot.h"
1171
1172-char *Version = "@(#)halt 2.84 27-Nov-2001 miquels@cistron.nl";
1173+char *Version = "@(#)halt 2.86 31-Jul-2004 miquels@cistron.nl";
1174 char *progname;
1175
1176 #define KERNEL_MONITOR 1 /* If halt() puts you into the kernel monitor. */
1177@@ -62,7 +64,16 @@
1178 */
1179 void usage(void)
1180 {
1181- fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f] [-i] [-p]\n", progname);
1182+ fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f] [-h] [-i]%s\n",
1183+ progname, strcmp(progname, "halt") ? "" : " [-p]");
1184+ fprintf(stderr, "\t-n: don't sync before halting the system\n");
1185+ fprintf(stderr, "\t-w: only write a wtmp reboot record and exit.\n");
1186+ fprintf(stderr, "\t-d: don't write a wtmp record.\n");
1187+ fprintf(stderr, "\t-f: force halt/reboot, don't call shutdown.\n");
1188+ fprintf(stderr, "\t-h: put harddisks in standby mode.\n");
1189+ fprintf(stderr, "\t-i: shut down all network interfaces.\n");
1190+ if (!strcmp(progname, "halt"))
1191+ fprintf(stderr, "\t-p: power down the system (if possible, otherwise halt).\n");
1192 exit(1);
1193 }
1194
1195@@ -172,11 +183,6 @@
1196 else
1197 progname = argv[0];
1198
1199- if (geteuid() != 0) {
1200- fprintf(stderr, "%s: must be superuser.\n", progname);
1201- exit(1);
1202- }
1203-
1204 if (!strcmp(progname, "reboot")) do_reboot = 1;
1205 if (!strcmp(progname, "poweroff")) do_poweroff = 1;
1206
1207@@ -216,6 +222,11 @@
1208 }
1209 if (argc != optind) usage();
1210
1211+ if (geteuid() != 0) {
1212+ fprintf(stderr, "%s: must be superuser.\n", progname);
1213+ exit(1);
1214+ }
1215+
1216 (void)chdir("/");
1217
1218 if (!do_hard && !do_nothing) {
1219@@ -236,7 +247,7 @@
1220 /*
1221 * Exit if all we wanted to do was write a wtmp record.
1222 */
1223- if (do_nothing) exit(0);
1224+ if (do_nothing && !do_hddown && !do_ifdown) exit(0);
1225
1226 if (do_sync) {
1227 sync();
1228@@ -249,13 +260,17 @@
1229 if (do_hddown)
1230 (void)hddown();
1231
1232+ if (do_nothing) exit(0);
1233+
1234 if (do_reboot) {
1235 init_reboot(BMAGIC_REBOOT);
1236 } else {
1237 /*
1238 * Turn on hard reboot, CTRL-ALT-DEL will reboot now
1239 */
1240+#ifdef BMAGIC_HARD
1241 init_reboot(BMAGIC_HARD);
1242+#endif
1243
1244 /*
1245 * Stop init; it is insensitive to the signals sent
1246@@ -277,7 +292,9 @@
1247 /*
1248 * If we return, we (c)ontinued from the kernel monitor.
1249 */
1250+#ifdef BMAGIC_SOFT
1251 init_reboot(BMAGIC_SOFT);
1252+#endif
1253 kill(1, SIGCONT);
1254
1255 exit(0);
1256Binary files sysvinit-2.85/src/halt.o and sysvinit-2.86/src/halt.o differ
1257diff -urNd -urNd sysvinit-2.85/src/hddown.c sysvinit-2.86/src/hddown.c
1258--- sysvinit-2.85/src/hddown.c 2001-11-07 09:11:21.000000000 -0600
1259+++ sysvinit-2.86/src/hddown.c 2004-06-09 07:47:45.000000000 -0500
1260@@ -3,7 +3,7 @@
1261 * shut them down.
1262 *
1263 */
1264-char *v_hddown = "@(#)hddown.c 1.01 07-Nov-2001 miquels@cistron.nl";
1265+char *v_hddown = "@(#)hddown.c 1.02 22-Apr-2003 miquels@cistron.nl";
1266
1267 #include <stdio.h>
1268 #include <stdlib.h>
1269@@ -13,8 +13,9 @@
1270 #include <fcntl.h>
1271 #include <dirent.h>
1272
1273-#include <sys/ioctl.h>
1274+#ifdef __linux__
1275
1276+#include <sys/ioctl.h>
1277 #include <linux/hdreg.h>
1278
1279 #define MAX_DISKS 64
1280@@ -104,6 +105,15 @@
1281 return 0;
1282 }
1283
1284+#else /* __linux__ */
1285+
1286+int hddown(void)
1287+{
1288+ return 0;
1289+}
1290+
1291+#endif /* __linux__ */
1292+
1293 #ifdef STANDALONE
1294 int main(int argc, char **argv)
1295 {
1296Binary files sysvinit-2.85/src/hddown.o and sysvinit-2.86/src/hddown.o differ
1297Binary files sysvinit-2.85/src/ifdown.o and sysvinit-2.86/src/ifdown.o differ
1298Binary files sysvinit-2.85/src/init and sysvinit-2.86/src/init differ
1299diff -urNd -urNd sysvinit-2.85/src/init.c sysvinit-2.86/src/init.c
1300--- sysvinit-2.85/src/init.c 2003-04-15 06:16:41.000000000 -0500
1301+++ sysvinit-2.86/src/init.c 2004-07-30 07:16:20.000000000 -0500
1302@@ -5,34 +5,28 @@
1303 * init [0123456SsQqAaBbCc]
1304 * telinit [0123456SsQqAaBbCc]
1305 *
1306- * Version: @(#)init.c 2.85 15-Apr-2003 miquels@cistron.nl
1307+ * Version: @(#)init.c 2.86 30-Jul-2004 miquels@cistron.nl
1308 */
1309-#define VERSION "2.85"
1310-#define DATE "15-Apr-2003"
1311+#define VERSION "2.86"
1312+#define DATE "31-Jul-2004"
1313 /*
1314 * This file is part of the sysvinit suite,
1315- * Copyright 1991-2003 Miquel van Smoorenburg.
1316+ * Copyright 1991-2004 Miquel van Smoorenburg.
1317 *
1318 * This program is free software; you can redistribute it and/or
1319 * modify it under the terms of the GNU General Public License
1320 * as published by the Free Software Foundation; either version
1321 * 2 of the License, or (at your option) any later version.
1322 *
1323- * Modified: 21 Feb 1998, Al Viro:
1324- * 'U' flag added to telinit. It forces init to re-exec itself
1325- * (passing its state through exec, certainly).
1326- * May be useful for smoother (heh) upgrades.
1327- * 24 Feb 1998, AV:
1328- * did_boot made global and added to state - thanks, Miquel.
1329- * Yet another file descriptors leak - close state pipe if
1330- * re_exec fails.
1331 */
1332
1333 #include <sys/types.h>
1334 #include <sys/stat.h>
1335 #include <sys/ioctl.h>
1336 #include <sys/wait.h>
1337+#ifdef __linux__
1338 #include <sys/kd.h>
1339+#endif
1340 #include <sys/resource.h>
1341 #include <stdlib.h>
1342 #include <unistd.h>
1343@@ -70,6 +64,13 @@
1344 # define SIGPWR SIGUSR2
1345 #endif
1346
1347+#ifndef CBAUD
1348+# define CBAUD 0
1349+#endif
1350+#ifndef CBAUDEX
1351+# define CBAUDEX 0
1352+#endif
1353+
1354 /* Set a signal handler. */
1355 #define SETSIG(sa, sig, fun, flags) \
1356 do { \
1357@@ -88,13 +89,13 @@
1358 CHILD *newFamily = NULL; /* The list after inittab re-read */
1359
1360 CHILD ch_emerg = { /* Emergency shell */
1361- 0, 0, 0, 0, 0,
1362- "~~",
1363- "S",
1364- 3,
1365- "/sbin/sulogin",
1366- NULL,
1367- NULL
1368+ 0, 0, 0, 0, 0,
1369+ "~~",
1370+ "S",
1371+ 3,
1372+ "/sbin/sulogin",
1373+ NULL,
1374+ NULL
1375 };
1376
1377 char runlevel = 'S'; /* The current run level */
1378@@ -108,8 +109,9 @@
1379 int wrote_utmp_reboot = 1; /* Set when we wrote the reboot record */
1380 int sltime = 5; /* Sleep time between TERM and KILL */
1381 char *argv0; /* First arguments; show up in ps listing */
1382-int maxproclen; /* Maximal length of argv[0] without \0 */
1383+int maxproclen; /* Maximal length of argv[0] with \0 */
1384 struct utmp utproto; /* Only used for sizeof(utproto.ut_id) */
1385+char *user_console = NULL; /* User console device */
1386 char *console_dev; /* Console device. */
1387 int pipe_fd = -1; /* /dev/initctl */
1388 int did_boot = 0; /* Did we already do BOOT* stuff? */
1389@@ -186,6 +188,10 @@
1390 {NULL,0}
1391 };
1392
1393+#define NR_EXTRA_ENV 16
1394+char *extra_env[NR_EXTRA_ENV];
1395+
1396+
1397 /*
1398 * Sleep a number of seconds.
1399 *
1400@@ -203,6 +209,35 @@
1401 ;
1402 }
1403
1404+
1405+/*
1406+ * Non-failing allocation routines (init cannot fail).
1407+ */
1408+void *imalloc(size_t size)
1409+{
1410+ void *m;
1411+
1412+ while ((m = malloc(size)) == NULL) {
1413+ initlog(L_VB, "out of memory");
1414+ do_sleep(5);
1415+ }
1416+ memset(m, 0, size);
1417+ return m;
1418+}
1419+
1420+
1421+char *istrdup(char *s)
1422+{
1423+ char *m;
1424+ int l;
1425+
1426+ l = strlen(s) + 1;
1427+ m = imalloc(l);
1428+ memcpy(m, s, l);
1429+ return m;
1430+}
1431+
1432+
1433 /*
1434 * Send the state info of the previous running init to
1435 * the new one, in a version-independant way.
1436@@ -344,12 +379,9 @@
1437 }
1438 } while (cmd != C_REC);
1439
1440- while ((p = (CHILD *)malloc(sizeof(CHILD))) == NULL ) {
1441- log(L_VB, "out of memory");
1442- do_sleep(5);
1443- }
1444- memset(p, 0, sizeof(CHILD));
1445+ p = imalloc(sizeof(CHILD));
1446 get_string(p->id, sizeof(p->id), f);
1447+
1448 do switch(cmd = get_cmd(f)) {
1449 case 0:
1450 case C_EOR:
1451@@ -420,7 +452,7 @@
1452 #ifdef __GNUC__
1453 __attribute__ ((format (printf, 1, 2)))
1454 #endif
1455-int setproctitle(char *fmt, ...)
1456+static int setproctitle(char *fmt, ...)
1457 {
1458 va_list ap;
1459 int len;
1460@@ -432,8 +464,10 @@
1461 len = vsnprintf(buf, sizeof(buf), fmt, ap);
1462 va_end(ap);
1463
1464- memset(argv0, 0, maxproclen + 1);
1465- strncpy(argv0, buf, maxproclen - 1);
1466+ if (maxproclen > 2) {
1467+ memset(argv0, 0, maxproclen);
1468+ strncpy(argv0, buf, maxproclen - 2);
1469+ }
1470
1471 return len;
1472 }
1473@@ -448,7 +482,9 @@
1474 int tried_vtmaster = 0;
1475 char *s;
1476
1477- if ((s = getenv("CONSOLE")) != NULL)
1478+ if (user_console) {
1479+ console_dev = user_console;
1480+ } else if ((s = getenv("CONSOLE")) != NULL)
1481 console_dev = s;
1482 else {
1483 console_dev = CONSOLE;
1484@@ -528,10 +564,9 @@
1485 if (errno == ECHILD) break;
1486 for( ch = family; ch; ch = ch->next )
1487 if ( ch->pid == pid && (ch->flags & RUNNING) ) {
1488-#if DEBUG
1489- log(L_VB, "chld_handler: marked %d as zombie",
1490+ INITDBG(L_VB,
1491+ "chld_handler: marked %d as zombie",
1492 ch->pid);
1493-#endif
1494 ADDSET(got_signals, SIGCHLD);
1495 ch->exstat = st;
1496 ch->flags |= ZOMBIE;
1497@@ -541,11 +576,9 @@
1498 }
1499 break;
1500 }
1501-#if DEBUG
1502 if (ch == NULL)
1503- log(L_VB, "chld_handler: unknown child %d exited.",
1504+ INITDBG(L_VB, "chld_handler: unknown child %d exited.",
1505 pid);
1506-#endif
1507 }
1508 errno = saved_errno;
1509 }
1510@@ -563,28 +596,34 @@
1511 }
1512
1513 /*
1514- * Dump core. Returns 0 if we are the child, so that the caller
1515- * can return if it is a signal handler - SIGSEGV is blocked in
1516- * the handler, so it will be raised when the handler returns.
1517+ * Fork and dump core in /.
1518 */
1519-int coredump(void)
1520+void coredump(void)
1521 {
1522- static int dumped = 0;
1523- struct rlimit rlim;
1524+ static int dumped = 0;
1525+ struct rlimit rlim;
1526+ sigset_t mask;
1527
1528- if (dumped) return 1;
1529+ if (dumped) return;
1530 dumped = 1;
1531
1532- if (fork() != 0) return 1;
1533+ if (fork() != 0) return;
1534+
1535+ sigfillset(&mask);
1536+ sigprocmask(SIG_SETMASK, &mask, NULL);
1537
1538 rlim.rlim_cur = RLIM_INFINITY;
1539 rlim.rlim_max = RLIM_INFINITY;
1540 setrlimit(RLIMIT_CORE, &rlim);
1541-
1542 chdir("/");
1543+
1544 signal(SIGSEGV, SIG_DFL);
1545 raise(SIGSEGV);
1546- return 0;
1547+ sigdelset(&mask, SIGSEGV);
1548+ sigprocmask(SIG_SETMASK, &mask, NULL);
1549+
1550+ do_sleep(5);
1551+ exit(0);
1552 }
1553
1554 /*
1555@@ -592,7 +631,7 @@
1556 * If we have the info, print where it occured.
1557 * Then sleep 30 seconds and try to continue.
1558 */
1559-#ifdef STACK_DEBUG
1560+#if defined(STACK_DEBUG) && defined(__linux__)
1561 void segv_handler(int sig, struct sigcontext ctx)
1562 {
1563 char *p = "";
1564@@ -601,10 +640,10 @@
1565 if ((void *)ctx.eip >= (void *)do_sleep &&
1566 (void *)ctx.eip < (void *)main)
1567 p = " (code)";
1568- log(L_VB, "PANIC: segmentation violation at %p%s! "
1569+ initlog(L_VB, "PANIC: segmentation violation at %p%s! "
1570 "sleeping for 30 seconds.", (void *)ctx.eip, p);
1571- if (coredump() != 0)
1572- do_sleep(30);
1573+ coredump();
1574+ do_sleep(30);
1575 errno = saved_errno;
1576 }
1577 #else
1578@@ -612,9 +651,10 @@
1579 {
1580 int saved_errno = errno;
1581
1582- log(L_VB, "PANIC: segmentation violation! sleeping for 30 seconds.");
1583- if (coredump() != 0)
1584- do_sleep(30);
1585+ initlog(L_VB,
1586+ "PANIC: segmentation violation! sleeping for 30 seconds.");
1587+ coredump();
1588+ do_sleep(30);
1589 errno = saved_errno;
1590 }
1591 #endif
1592@@ -641,7 +681,7 @@
1593 int fd;
1594
1595 if ((fd = console_open(O_RDWR|O_NOCTTY)) < 0) {
1596- log(L_VB, "can't open %s", console_dev);
1597+ initlog(L_VB, "can't open %s", console_dev);
1598 return;
1599 }
1600
1601@@ -697,10 +737,11 @@
1602 #ifdef __GNUC__
1603 __attribute__ ((format (printf, 2, 3)))
1604 #endif
1605-void log(int loglevel, char *s, ...)
1606+void initlog(int loglevel, char *s, ...)
1607 {
1608 va_list va_alist;
1609 char buf[256];
1610+ sigset_t nmask, omask;
1611
1612 va_start(va_alist, s);
1613 vsnprintf(buf, sizeof(buf), s, va_alist);
1614@@ -708,11 +749,15 @@
1615
1616 if (loglevel & L_SY) {
1617 /*
1618- * Re-etablish connection with syslogd every time.
1619+ * Re-establish connection with syslogd every time.
1620+ * Block signals while talking to syslog.
1621 */
1622+ sigfillset(&nmask);
1623+ sigprocmask(SIG_BLOCK, &nmask, &omask);
1624 openlog("init", 0, LOG_DAEMON);
1625 syslog(LOG_INFO, "%s", buf);
1626 closelog();
1627+ sigprocmask(SIG_SETMASK, &omask, NULL);
1628 }
1629
1630 /*
1631@@ -727,14 +772,51 @@
1632
1633
1634 /*
1635- * See if one character of s2 is in s1
1636+ * Build a new environment for execve().
1637 */
1638-int any(char *s1, char *s2)
1639+char **init_buildenv(int child)
1640 {
1641- while(*s2)
1642- if (strchr(s1, *s2++) != NULL)
1643- return(1);
1644- return(0);
1645+ char i_lvl[] = "RUNLEVEL=x";
1646+ char i_prev[] = "PREVLEVEL=x";
1647+ char i_cons[32];
1648+ char **e;
1649+ int n, i;
1650+
1651+ for (n = 0; environ[n]; n++)
1652+ ;
1653+ n += NR_EXTRA_ENV + 8;
1654+ e = calloc(n, sizeof(char *));
1655+
1656+ for (n = 0; environ[n]; n++)
1657+ e[n] = istrdup(environ[n]);
1658+
1659+ for (i = 0; i < NR_EXTRA_ENV; i++)
1660+ if (extra_env[i])
1661+ e[n++] = istrdup(extra_env[i]);
1662+
1663+ if (child) {
1664+ snprintf(i_cons, sizeof(i_cons), "CONSOLE=%s", console_dev);
1665+ i_lvl[9] = thislevel;
1666+ i_prev[10] = prevlevel;
1667+ e[n++] = istrdup(i_lvl);
1668+ e[n++] = istrdup(i_prev);
1669+ e[n++] = istrdup(i_cons);
1670+ e[n++] = istrdup(E_VERSION);
1671+ }
1672+
1673+ e[n++] = NULL;
1674+
1675+ return e;
1676+}
1677+
1678+
1679+void init_freeenv(char **e)
1680+{
1681+ int n;
1682+
1683+ for (n = 0; e[n]; n++)
1684+ free(e[n]);
1685+ free(e);
1686 }
1687
1688
1689@@ -753,9 +835,6 @@
1690 time_t t; /* System time */
1691 int oldAlarm; /* Previous alarm value */
1692 char *proc = ch->process; /* Command line */
1693- char i_lvl[] = "RUNLEVEL=x"; /* Runlevel in environment. */
1694- char i_prev[] = "PREVLEVEL=x";/* Previous runlevel. */
1695- char i_cons[32]; /* console device. */
1696 pid_t pid, pgrp; /* child, console process group. */
1697 sigset_t nmask, omask; /* For blocking SIGCHLD */
1698 struct sigaction sa;
1699@@ -781,8 +860,9 @@
1700 /* Do we try to respawn too fast? */
1701 if (ch->count >= MAXSPAWN) {
1702
1703- log(L_VB, "Id \"%s\" respawning too fast: disabled for %d minutes",
1704- ch->id, SLEEPTIME / 60);
1705+ initlog(L_VB,
1706+ "Id \"%s\" respawning too fast: disabled for %d minutes",
1707+ ch->id, SLEEPTIME / 60);
1708 ch->flags &= ~RUNNING;
1709 ch->flags |= FAILING;
1710
1711@@ -813,7 +893,7 @@
1712 }
1713 args[6] = proc;
1714 args[7] = NULL;
1715- } else if (any(proc, "~`!$^&*()=|\\{}[];\"'<>?")) {
1716+ } else if (strpbrk(proc, "~`!$^&*()=|\\{}[];\"'<>?")) {
1717 /* See if we need to fire off a shell for this command */
1718 /* Give command line to shell */
1719 args[1] = SHELL;
1720@@ -868,15 +948,6 @@
1721
1722 sigprocmask(SIG_SETMASK, &omask, NULL);
1723
1724- /* Now set RUNLEVEL and PREVLEVEL */
1725- snprintf(i_cons, sizeof(i_cons), "CONSOLE=%s", console_dev);
1726- i_lvl[9] = thislevel;
1727- i_prev[10] = prevlevel;
1728- putenv(i_lvl);
1729- putenv(i_prev);
1730- putenv(i_cons);
1731- putenv(E_VERSION);
1732-
1733 /*
1734 * In sysinit, boot, bootwait or single user mode:
1735 * for any wait-type subprocess we _force_ the console
1736@@ -896,7 +967,7 @@
1737 dup(f);
1738 }
1739 if ((pid = fork()) < 0) {
1740- log(L_VB, "cannot fork");
1741+ initlog(L_VB, "cannot fork");
1742 exit(1);
1743 }
1744 if (pid > 0) {
1745@@ -926,7 +997,7 @@
1746 * this with a temporary process.
1747 */
1748 if ((pid = fork()) < 0) {
1749- log(L_VB, "cannot fork");
1750+ initlog(L_VB, "cannot fork");
1751 exit(1);
1752 }
1753 if (pid == 0) {
1754@@ -946,7 +1017,7 @@
1755 } else {
1756 setsid();
1757 if ((f = console_open(O_RDWR|O_NOCTTY)) < 0) {
1758- log(L_VB, "open(%s): %s", console_dev,
1759+ initlog(L_VB, "open(%s): %s", console_dev,
1760 strerror(errno));
1761 f = open("/dev/null", O_RDWR);
1762 }
1763@@ -954,15 +1025,15 @@
1764 dup(f);
1765 }
1766
1767- /* Reset all the signals */
1768+ /* Reset all the signals, set up environment */
1769 for(f = 1; f < NSIG; f++) SETSIG(sa, f, SIG_DFL, SA_RESTART);
1770- execvp(args[1], args + 1);
1771+ environ = init_buildenv(1);
1772
1773 /*
1774- * Is this a bug in execvp? It does _not_ execute shell
1775- * scripts (/etc/rc !), so we try again with
1776- * 'sh -c exec ...'
1777+ * Execute prog. In case of ENOEXEC try again
1778+ * as a shell script.
1779 */
1780+ execvp(args[1], args + 1);
1781 if (errno == ENOEXEC) {
1782 args[1] = SHELL;
1783 args[2] = "-c";
1784@@ -972,18 +1043,16 @@
1785 args[4] = NULL;
1786 execvp(args[1], args + 1);
1787 }
1788- log(L_VB, "cannot execute \"%s\"", args[1]);
1789+ initlog(L_VB, "cannot execute \"%s\"", args[1]);
1790 exit(1);
1791 }
1792 *res = pid;
1793 sigprocmask(SIG_SETMASK, &omask, NULL);
1794
1795-#if DEBUG
1796- log(L_VB, "Started id %s (pid %d)", ch->id, pid);
1797-#endif
1798+ INITDBG(L_VB, "Started id %s (pid %d)", ch->id, pid);
1799
1800 if (pid == -1) {
1801- log(L_VB, "cannot fork, retry..");
1802+ initlog(L_VB, "cannot fork, retry..");
1803 do_sleep(5);
1804 continue;
1805 }
1806@@ -1032,66 +1101,45 @@
1807 }
1808 }
1809
1810-/*
1811- * My version of strtok(3).
1812- */
1813-char *get_part(char *str, int tok)
1814-{
1815- static char *s;
1816- char *p, *q;
1817-
1818- if (str != NULL)
1819- s = str;
1820- if (s == NULL || *s == 0)
1821- return(NULL);
1822- q = p = s;
1823- while(*p != tok && *p)
1824- p++;
1825- if (*p == tok)
1826- *p++ = 0;
1827- s = p;
1828-
1829- return q;
1830-}
1831
1832 /*
1833 * Read the inittab file.
1834 */
1835 void read_inittab(void)
1836 {
1837- FILE *fp; /* The INITTAB file */
1838- char buf[256]; /* Line buffer */
1839- char err[64]; /* Error message. */
1840- char *id, *rlevel,
1841- *action, *process; /* Fields of a line */
1842- char *p;
1843- CHILD *ch, *old, *i; /* Pointers to CHILD structure */
1844- CHILD *head = NULL; /* Head of linked list */
1845- int lineNo = 0; /* Line number in INITTAB file */
1846- int actionNo; /* Decoded action field */
1847- int f; /* Counter */
1848- int round; /* round 0 for SIGTERM, round 1 for SIGKILL */
1849- int foundOne = 0; /* No killing no sleep */
1850- int talk; /* Talk to the user */
1851- int done = 0; /* Ready yet? */
1852- sigset_t nmask, omask; /* For blocking SIGCHLD. */
1853+ FILE *fp; /* The INITTAB file */
1854+ CHILD *ch, *old, *i; /* Pointers to CHILD structure */
1855+ CHILD *head = NULL; /* Head of linked list */
1856 #ifdef INITLVL
1857- struct stat st; /* To stat INITLVL */
1858+ struct stat st; /* To stat INITLVL */
1859 #endif
1860+ sigset_t nmask, omask; /* For blocking SIGCHLD. */
1861+ char buf[256]; /* Line buffer */
1862+ char err[64]; /* Error message. */
1863+ char *id, *rlevel,
1864+ *action, *process; /* Fields of a line */
1865+ char *p;
1866+ int lineNo = 0; /* Line number in INITTAB file */
1867+ int actionNo; /* Decoded action field */
1868+ int f; /* Counter */
1869+ int round; /* round 0 for SIGTERM, 1 for SIGKILL */
1870+ int foundOne = 0; /* No killing no sleep */
1871+ int talk; /* Talk to the user */
1872+ int done = 0; /* Ready yet? */
1873
1874 #if DEBUG
1875 if (newFamily != NULL) {
1876- log(L_VB, "PANIC newFamily != NULL");
1877+ INITDBG(L_VB, "PANIC newFamily != NULL");
1878 exit(1);
1879 }
1880- log(L_VB, "Reading inittab");
1881+ INITDBG(L_VB, "Reading inittab");
1882 #endif
1883
1884 /*
1885 * Open INITTAB and real line by line.
1886 */
1887 if ((fp = fopen(INITTAB, "r")) == NULL)
1888- log(L_VB, "No inittab file found");
1889+ initlog(L_VB, "No inittab file found");
1890
1891 while(!done) {
1892 /*
1893@@ -1103,9 +1151,9 @@
1894 * See if we have a single user entry.
1895 */
1896 for(old = newFamily; old; old = old->next)
1897- if (strcmp(old->rlevel, "S") == 0) break;
1898+ if (strpbrk(old->rlevel, "S")) break;
1899 if (old == NULL)
1900- snprintf(buf, sizeof(buf), "~~:S:wait:%s\n", SHELL);
1901+ snprintf(buf, sizeof(buf), "~~:S:wait:%s\n", SULOGIN);
1902 else
1903 continue;
1904 }
1905@@ -1120,10 +1168,10 @@
1906 /*
1907 * Decode the fields
1908 */
1909- id = get_part(p, ':');
1910- rlevel = get_part(NULL, ':');
1911- action = get_part(NULL, ':');
1912- process = get_part(NULL, '\n');
1913+ id = strsep(&p, ":");
1914+ rlevel = strsep(&p, ":");
1915+ action = strsep(&p, ":");
1916+ process = strsep(&p, "\n");
1917
1918 /*
1919 * Check if syntax is OK. Be very verbose here, to
1920@@ -1145,10 +1193,8 @@
1921 if (action && strlen(action) > 32)
1922 strcpy(err, "action field too long");
1923 if (err[0] != 0) {
1924- log(L_VB, "%s[%d]: %s", INITTAB, lineNo, err);
1925-#if DEBUG
1926- log(L_VB, "%s:%s:%s:%s", id, rlevel, action, process);
1927-#endif
1928+ initlog(L_VB, "%s[%d]: %s", INITTAB, lineNo, err);
1929+ INITDBG(L_VB, "%s:%s:%s:%s", id, rlevel, action, process);
1930 continue;
1931 }
1932
1933@@ -1162,7 +1208,7 @@
1934 break;
1935 }
1936 if (actionNo == -1) {
1937- log(L_VB, "%s[%d]: %s: unknown action field",
1938+ initlog(L_VB, "%s[%d]: %s: unknown action field",
1939 INITTAB, lineNo, action);
1940 continue;
1941 }
1942@@ -1172,7 +1218,7 @@
1943 */
1944 for(old = newFamily; old; old = old->next) {
1945 if(strcmp(old->id, id) == 0 && strcmp(id, "~~")) {
1946- log(L_VB, "%s[%d]: duplicate ID field \"%s\"",
1947+ initlog(L_VB, "%s[%d]: duplicate ID field \"%s\"",
1948 INITTAB, lineNo, id);
1949 break;
1950 }
1951@@ -1182,11 +1228,7 @@
1952 /*
1953 * Allocate a CHILD structure
1954 */
1955- while ((ch = malloc(sizeof(CHILD))) == NULL) {
1956- log(L_VB, "out of memory");
1957- do_sleep(5);
1958- }
1959- memset(ch, 0, sizeof(CHILD));
1960+ ch = imalloc(sizeof(CHILD));
1961
1962 /*
1963 * And fill it in.
1964@@ -1275,9 +1317,7 @@
1965 * be killed.
1966 */
1967
1968-#if DEBUG
1969- log(L_VB, "Checking for children to kill");
1970-#endif
1971+ INITDBG(L_VB, "Checking for children to kill");
1972 for(round = 0; round < 2; round++) {
1973 talk = 1;
1974 for(ch = family; ch; ch = ch->next) {
1975@@ -1328,19 +1368,19 @@
1976 ch->flags &= ~KILLME;
1977 continue;
1978 }
1979-#if DEBUG
1980- log(L_VB, "Killing \"%s\"", ch->process);
1981-#endif
1982+ INITDBG(L_VB, "Killing \"%s\"", ch->process);
1983 switch(round) {
1984 case 0: /* Send TERM signal */
1985 if (talk)
1986- log(L_CO, "Sending processes the TERM signal");
1987+ initlog(L_CO,
1988+ "Sending processes the TERM signal");
1989 kill(-(ch->pid), SIGTERM);
1990 foundOne = 1;
1991 break;
1992 case 1: /* Send KILL signal and collect status */
1993 if (talk)
1994- log(L_CO, "Sending processes the KILL signal");
1995+ initlog(L_CO,
1996+ "Sending processes the KILL signal");
1997 kill(-(ch->pid), SIGKILL);
1998 break;
1999 }
2000@@ -1380,12 +1420,11 @@
2001 for(ch = family; ch; ch = ch->next)
2002 if (ch->flags & KILLME) {
2003 if (!(ch->flags & ZOMBIE))
2004- log(L_CO, "Pid %d [id %s] seems to hang", ch->pid,
2005+ initlog(L_CO, "Pid %d [id %s] seems to hang", ch->pid,
2006 ch->id);
2007 else {
2008-#if DEBUG
2009- log(L_VB, "Updating utmp for pid %d [id %s]", ch->pid, ch->id);
2010-#endif
2011+ INITDBG(L_VB, "Updating utmp for pid %d [id %s]",
2012+ ch->pid, ch->id);
2013 ch->flags &= ~RUNNING;
2014 if (ch->process[0] != '+')
2015 write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
2016@@ -1451,15 +1490,13 @@
2017 CHILD *ch; /* Pointer to child */
2018 int delete; /* Delete this entry from list? */
2019
2020-#if DEBUG
2021- log(L_VB, "Checking for children to start");
2022-#endif
2023+ INITDBG(L_VB, "Checking for children to start");
2024
2025 for(ch = family; ch; ch = ch->next) {
2026
2027 #if DEBUG
2028 if (ch->rlevel[0] == 'C') {
2029- log(L_VB, "%s: flags %d", ch->process, ch->flags);
2030+ INITDBG(L_VB, "%s: flags %d", ch->process, ch->flags);
2031 }
2032 #endif
2033
2034@@ -1545,7 +1582,8 @@
2035 if (lvl > 0) {
2036 if (islower(lvl)) lvl = toupper(lvl);
2037 if (strchr("0123456789S", lvl) == NULL) {
2038- log(L_VB, "Initdefault level '%c' is invalid", lvl);
2039+ initlog(L_VB,
2040+ "Initdefault level '%c' is invalid", lvl);
2041 lvl = 0;
2042 }
2043 }
2044@@ -1570,98 +1608,99 @@
2045 */
2046 int read_level(int arg)
2047 {
2048- unsigned char foo = 'X'; /* Contents of INITLVL */
2049- CHILD *ch; /* Walk through list */
2050- int ok = 1;
2051+ CHILD *ch; /* Walk through list */
2052+ unsigned char foo = 'X'; /* Contents of INITLVL */
2053+ int ok = 1;
2054 #ifdef INITLVL
2055- FILE *fp;
2056- int st;
2057- struct stat stt;
2058+ FILE *fp;
2059+ struct stat stt;
2060+ int st;
2061 #endif
2062
2063- if (arg) foo = arg;
2064+ if (arg) foo = arg;
2065
2066 #ifdef INITLVL
2067- ok = 0;
2068+ ok = 0;
2069
2070- if (arg == 0) {
2071- fp = NULL;
2072- if (stat(INITLVL, &stt) != 0 || stt.st_size != 0L)
2073- fp = fopen(INITLVL, "r");
2074+ if (arg == 0) {
2075+ fp = NULL;
2076+ if (stat(INITLVL, &stt) != 0 || stt.st_size != 0L)
2077+ fp = fopen(INITLVL, "r");
2078 #ifdef INITLVL2
2079- if (fp == NULL && (stat(INITLVL2, &stt) != 0 || stt.st_size != 0L))
2080- fp = fopen(INITLVL2, "r");
2081+ if (fp == NULL &&
2082+ (stat(INITLVL2, &stt) != 0 || stt.st_size != 0L))
2083+ fp = fopen(INITLVL2, "r");
2084 #endif
2085- if (fp == NULL) {
2086- /* INITLVL file is empty or not there - act as 'init q' */
2087- log(L_SY, "Re-reading inittab");
2088- return(runlevel);
2089+ if (fp == NULL) {
2090+ /* INITLVL file empty or not there - act as 'init q' */
2091+ initlog(L_SY, "Re-reading inittab");
2092+ return(runlevel);
2093+ }
2094+ ok = fscanf(fp, "%c %d", &foo, &st);
2095+ fclose(fp);
2096+ } else {
2097+ /* We go to the new runlevel passed as an argument. */
2098+ foo = arg;
2099+ ok = 1;
2100 }
2101- ok = fscanf(fp, "%c %d", &foo, &st);
2102- fclose(fp);
2103- } else {
2104- /* We go to the new runlevel passed as an argument. */
2105- foo = arg;
2106- ok = 1;
2107- }
2108- if (ok == 2) sltime = st;
2109+ if (ok == 2) sltime = st;
2110
2111 #endif /* INITLVL */
2112
2113- if (islower(foo)) foo = toupper(foo);
2114- if (ok < 1 || ok > 2 || strchr("QS0123456789ABCU", foo) == NULL) {
2115- log(L_VB, "bad runlevel: %c", foo);
2116- return(runlevel);
2117- }
2118+ if (islower(foo)) foo = toupper(foo);
2119+ if (ok < 1 || ok > 2 || strchr("QS0123456789ABCU", foo) == NULL) {
2120+ initlog(L_VB, "bad runlevel: %c", foo);
2121+ return runlevel;
2122+ }
2123
2124- /* Log this action */
2125- switch(foo) {
2126- case 'S':
2127- log(L_VB, "Going single user");
2128- break;
2129- case 'Q':
2130- log(L_SY, "Re-reading inittab");
2131- break;
2132- case 'A':
2133- case 'B':
2134- case 'C':
2135- log(L_SY, "Activating demand-procedures for '%c'", foo);
2136- break;
2137- case 'U':
2138- log(L_SY, "Trying to re-exec init");
2139- return 'U';
2140- default:
2141- log(L_VB, "Switching to runlevel: %c", foo);
2142- }
2143+ /* Log this action */
2144+ switch(foo) {
2145+ case 'S':
2146+ initlog(L_VB, "Going single user");
2147+ break;
2148+ case 'Q':
2149+ initlog(L_SY, "Re-reading inittab");
2150+ break;
2151+ case 'A':
2152+ case 'B':
2153+ case 'C':
2154+ initlog(L_SY,
2155+ "Activating demand-procedures for '%c'", foo);
2156+ break;
2157+ case 'U':
2158+ initlog(L_SY, "Trying to re-exec init");
2159+ return 'U';
2160+ default:
2161+ initlog(L_VB, "Switching to runlevel: %c", foo);
2162+ }
2163
2164- if (foo == 'Q') return(runlevel);
2165+ if (foo == 'Q') return runlevel;
2166
2167- /* Check if this is a runlevel a, b or c */
2168- if (strchr("ABC", foo)) {
2169- if (runlevel == 'S') return(runlevel);
2170+ /* Check if this is a runlevel a, b or c */
2171+ if (strchr("ABC", foo)) {
2172+ if (runlevel == 'S') return(runlevel);
2173
2174- /* Read inittab again first! */
2175- read_inittab();
2176+ /* Read inittab again first! */
2177+ read_inittab();
2178
2179- /* Mark those special tasks */
2180- for(ch = family; ch; ch = ch->next)
2181- if (strchr(ch->rlevel, foo) != NULL ||
2182- strchr(ch->rlevel, tolower(foo)) != NULL) {
2183- ch->flags |= DEMAND;
2184- ch->flags &= ~XECUTED;
2185-#if DEBUG
2186- log(L_VB, "Marking (%s) as ondemand, flags %d",
2187- ch->id, ch->flags);
2188-#endif
2189- }
2190- return(runlevel);
2191- }
2192+ /* Mark those special tasks */
2193+ for(ch = family; ch; ch = ch->next)
2194+ if (strchr(ch->rlevel, foo) != NULL ||
2195+ strchr(ch->rlevel, tolower(foo)) != NULL) {
2196+ ch->flags |= DEMAND;
2197+ ch->flags &= ~XECUTED;
2198+ INITDBG(L_VB,
2199+ "Marking (%s) as ondemand, flags %d",
2200+ ch->id, ch->flags);
2201+ }
2202+ return runlevel;
2203+ }
2204
2205- /* Store both the old and the new runlevel. */
2206- write_utmp_wtmp("runlevel", "~~", foo + 256*runlevel, RUN_LVL, "~");
2207- thislevel = foo;
2208- prevlevel = runlevel;
2209- return(foo);
2210+ /* Store both the old and the new runlevel. */
2211+ write_utmp_wtmp("runlevel", "~~", foo + 256*runlevel, RUN_LVL, "~");
2212+ thislevel = foo;
2213+ prevlevel = runlevel;
2214+ return foo;
2215 }
2216
2217
2218@@ -1674,32 +1713,33 @@
2219 */
2220 void fail_check(void)
2221 {
2222- time_t t; /* System time */
2223- CHILD *ch; /* Pointer to child structure */
2224- time_t next_alarm = 0; /* When to set next alarm */
2225+ CHILD *ch; /* Pointer to child structure */
2226+ time_t t; /* System time */
2227+ time_t next_alarm = 0; /* When to set next alarm */
2228
2229- time(&t);
2230+ time(&t);
2231
2232- for(ch = family; ch; ch = ch->next) {
2233+ for(ch = family; ch; ch = ch->next) {
2234
2235- if (ch->flags & FAILING) {
2236- /* Can we free this sucker? */
2237- if (ch->tm + SLEEPTIME < t) {
2238- ch->flags &= ~FAILING;
2239- ch->count = 0;
2240- ch->tm = 0;
2241- } else {
2242- /* No, we'll look again later */
2243- if (next_alarm == 0 || ch->tm + SLEEPTIME > next_alarm)
2244- next_alarm = ch->tm + SLEEPTIME;
2245+ if (ch->flags & FAILING) {
2246+ /* Can we free this sucker? */
2247+ if (ch->tm + SLEEPTIME < t) {
2248+ ch->flags &= ~FAILING;
2249+ ch->count = 0;
2250+ ch->tm = 0;
2251+ } else {
2252+ /* No, we'll look again later */
2253+ if (next_alarm == 0 ||
2254+ ch->tm + SLEEPTIME > next_alarm)
2255+ next_alarm = ch->tm + SLEEPTIME;
2256+ }
2257 }
2258 }
2259- }
2260- if (next_alarm) {
2261- next_alarm -= t;
2262- if (next_alarm < 1) next_alarm = 1;
2263- alarm(next_alarm);
2264- }
2265+ if (next_alarm) {
2266+ next_alarm -= t;
2267+ if (next_alarm < 1) next_alarm = 1;
2268+ alarm(next_alarm);
2269+ }
2270 }
2271
2272 /* Set all 'Fail' timers to 0 */
2273@@ -1752,9 +1792,9 @@
2274 */
2275 int check_pipe(int fd)
2276 {
2277- struct timeval t;
2278- fd_set s;
2279- char signature[8];
2280+ struct timeval t;
2281+ fd_set s;
2282+ char signature[8];
2283
2284 FD_ZERO(&s);
2285 FD_SET(fd, &s);
2286@@ -1789,10 +1829,11 @@
2287 */
2288 void re_exec(void)
2289 {
2290- sigset_t mask, oldset;
2291- pid_t pid;
2292- int fd;
2293- CHILD *ch;
2294+ CHILD *ch;
2295+ sigset_t mask, oldset;
2296+ pid_t pid;
2297+ char **env;
2298+ int fd;
2299
2300 if (strchr("S12345",runlevel) == NULL)
2301 return;
2302@@ -1825,27 +1866,26 @@
2303 */
2304 for(ch = family; ch; ch = ch->next)
2305 if (ch->flags & ZOMBIE) {
2306-#if DEBUG
2307- log(L_VB, "Child died, PID= %d", ch->pid);
2308-#endif
2309+ INITDBG(L_VB, "Child died, PID= %d", ch->pid);
2310 ch->flags &= ~(RUNNING|ZOMBIE|WAITING);
2311 if (ch->process[0] != '+')
2312 write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
2313 }
2314
2315- if ((pid = fork()) > 0) {
2316- /*
2317- * Yup. _Parent_ exec's ...
2318- */
2319- execl(myname, myname, "--init", NULL);
2320- } else if (pid == 0) {
2321+ if ((pid = fork()) == 0) {
2322 /*
2323- * ... while child sends her the
2324- * state information and dies
2325+ * Child sends state information to the parent.
2326 */
2327 send_state(fd);
2328 exit(0);
2329 }
2330+
2331+ /*
2332+ * The existing init process execs a new init binary.
2333+ */
2334+ env = init_buildenv(0);
2335+ execl(myname, myname, "--init", NULL, env);
2336+
2337 /*
2338 * We shouldn't be here, something failed.
2339 * Bitch, close the state pipe, unblock signals and return.
2340@@ -1853,7 +1893,8 @@
2341 close(fd);
2342 close(STATE_PIPE);
2343 sigprocmask(SIG_SETMASK, &oldset, NULL);
2344- log(L_CO, "Attempt to re-exec failed");
2345+ init_freeenv(env);
2346+ initlog(L_CO, "Attempt to re-exec failed");
2347 }
2348
2349
2350@@ -1863,10 +1904,10 @@
2351 */
2352 void fifo_new_level(int level)
2353 {
2354- int oldlevel;
2355 #if CHANGE_WAIT
2356- CHILD *ch;
2357+ CHILD *ch;
2358 #endif
2359+ int oldlevel;
2360
2361 if (level == runlevel) return;
2362
2363@@ -1894,6 +1935,59 @@
2364 }
2365 }
2366
2367+
2368+/*
2369+ * Set/unset environment variables. The variables are
2370+ * encoded as KEY=VAL\0KEY=VAL\0\0. With "=VAL" it means
2371+ * setenv, without it means unsetenv.
2372+ */
2373+void initcmd_setenv(char *data, int size)
2374+{
2375+ char *env, *p, *e, *eq;
2376+ int i, sz;
2377+
2378+ e = data + size;
2379+
2380+ while (*data && data < e) {
2381+ eq = NULL;
2382+ for (p = data; *p && p < e; p++)
2383+ if (*p == '=') eq = p;
2384+ if (*p) break;
2385+ env = data;
2386+ data = ++p;
2387+
2388+ sz = eq ? (eq - env) : (p - env);
2389+
2390+ /*initlog(L_SY, "init_setenv: %s, %s, %d", env, eq, sz);*/
2391+
2392+ /*
2393+ * We only allow INIT_* to be set.
2394+ */
2395+ if (strncmp(env, "INIT_", 5) != 0)
2396+ continue;
2397+
2398+ /* Free existing vars. */
2399+ for (i = 0; i < NR_EXTRA_ENV; i++) {
2400+ if (extra_env[i] == NULL) continue;
2401+ if (!strncmp(extra_env[i], env, sz) &&
2402+ extra_env[i][sz] == '=') {
2403+ free(extra_env[i]);
2404+ extra_env[i] = NULL;
2405+ }
2406+ }
2407+
2408+ /* Set new vars if needed. */
2409+ if (eq == NULL) continue;
2410+ for (i = 0; i < NR_EXTRA_ENV; i++) {
2411+ if (extra_env[i] == NULL) {
2412+ extra_env[i] = istrdup(env);
2413+ break;
2414+ }
2415+ }
2416+ }
2417+}
2418+
2419+
2420 /*
2421 * Read from the init FIFO. Processes like telnetd and rlogind can
2422 * ask us to create login processes on their behalf.
2423@@ -1906,12 +2000,12 @@
2424 */
2425 void check_init_fifo(void)
2426 {
2427- struct init_request request;
2428- int n;
2429- fd_set fds;
2430- int quit = 0;
2431- struct stat st, st2;
2432- struct timeval tv;
2433+ struct init_request request;
2434+ struct timeval tv;
2435+ struct stat st, st2;
2436+ fd_set fds;
2437+ int n;
2438+ int quit = 0;
2439
2440 /*
2441 * First, try to create /dev/initctl if not present.
2442@@ -1940,7 +2034,7 @@
2443 if ((pipe_fd = open(INIT_FIFO, O_RDWR|O_NONBLOCK)) >= 0) {
2444 fstat(pipe_fd, &st);
2445 if (!S_ISFIFO(st.st_mode)) {
2446- log(L_VB, "%s is not a fifo", INIT_FIFO);
2447+ initlog(L_VB, "%s is not a fifo", INIT_FIFO);
2448 close(pipe_fd);
2449 pipe_fd = -1;
2450 }
2451@@ -1987,7 +2081,7 @@
2452 }
2453 if (n <= 0) {
2454 if (errno == EINTR) return;
2455- log(L_VB, "error reading initrequest");
2456+ initlog(L_VB, "error reading initrequest");
2457 continue;
2458 }
2459
2460@@ -2001,7 +2095,7 @@
2461 * Process request.
2462 */
2463 if (request.magic != INIT_MAGIC || n != sizeof(request)) {
2464- log(L_VB, "got bogus initrequest");
2465+ initlog(L_VB, "got bogus initrequest");
2466 continue;
2467 }
2468 switch(request.cmd) {
2469@@ -2025,8 +2119,23 @@
2470 do_power_fail('O');
2471 quit = 1;
2472 break;
2473+ case INIT_CMD_SETENV:
2474+ initcmd_setenv(request.i.data, sizeof(request.i.data));
2475+ break;
2476+ case INIT_CMD_CHANGECONS:
2477+ if (user_console) {
2478+ free(user_console);
2479+ user_console = NULL;
2480+ }
2481+ if (!request.i.bsd.reserved[0])
2482+ user_console = NULL;
2483+ else
2484+ user_console = strdup(request.i.bsd.reserved);
2485+ console_init();
2486+ quit = 1;
2487+ break;
2488 default:
2489- log(L_VB, "got unimplemented initrequest.");
2490+ initlog(L_VB, "got unimplemented initrequest.");
2491 break;
2492 }
2493 }
2494@@ -2045,11 +2154,11 @@
2495 */
2496 void boot_transitions()
2497 {
2498- CHILD *ch;
2499- static int newlevel = 0;
2500- int loglevel;
2501- int oldlevel;
2502- static int warn = 1;
2503+ CHILD *ch;
2504+ static int newlevel = 0;
2505+ static int warn = 1;
2506+ int loglevel;
2507+ int oldlevel;
2508
2509 /* Check if there is something to wait for! */
2510 for( ch = family; ch; ch = ch->next )
2511@@ -2061,9 +2170,7 @@
2512 oldlevel = 'N';
2513 switch(runlevel) {
2514 case '#': /* SYSINIT -> BOOT */
2515-#if DEBUG
2516- log(L_VB, "SYSINIT -> BOOT");
2517-#endif
2518+ INITDBG(L_VB, "SYSINIT -> BOOT");
2519
2520 /* Write a boot record. */
2521 wrote_utmp_reboot = 0;
2522@@ -2080,9 +2187,7 @@
2523 runlevel = '*';
2524 break;
2525 case '*': /* BOOT -> NORMAL */
2526-#if DEBUG
2527- log(L_VB, "BOOT -> NORMAL");
2528-#endif
2529+ INITDBG(L_VB, "BOOT -> NORMAL");
2530 if (runlevel != newlevel)
2531 loglevel = newlevel;
2532 runlevel = newlevel;
2533@@ -2091,9 +2196,7 @@
2534 break;
2535 case 'S': /* Ended SU mode */
2536 case 's':
2537-#if DEBUG
2538- log(L_VB, "END SU MODE");
2539-#endif
2540+ INITDBG(L_VB, "END SU MODE");
2541 newlevel = get_init_default();
2542 if (!did_boot && newlevel != 'S')
2543 runlevel = '*';
2544@@ -2110,7 +2213,8 @@
2545 break;
2546 default:
2547 if (warn)
2548- log(L_VB, "no more processes left in this runlevel");
2549+ initlog(L_VB,
2550+ "no more processes left in this runlevel");
2551 warn = 0;
2552 loglevel = -1;
2553 if (got_signals == 0)
2554@@ -2118,7 +2222,7 @@
2555 break;
2556 }
2557 if (loglevel > 0) {
2558- log(L_VB, "Entering runlevel: %c", runlevel);
2559+ initlog(L_VB, "Entering runlevel: %c", runlevel);
2560 write_utmp_wtmp("runlevel", "~~", runlevel + 256 * oldlevel, RUN_LVL, "~");
2561 thislevel = runlevel;
2562 prevlevel = oldlevel;
2563@@ -2133,16 +2237,14 @@
2564 */
2565 void process_signals()
2566 {
2567- int pwrstat;
2568- int oldlevel;
2569- int fd;
2570- CHILD *ch;
2571- char c;
2572+ CHILD *ch;
2573+ int pwrstat;
2574+ int oldlevel;
2575+ int fd;
2576+ char c;
2577
2578 if (ISMEMBER(got_signals, SIGPWR)) {
2579-#if DEBUG
2580- log(L_VB, "got SIGPWR");
2581-#endif
2582+ INITDBG(L_VB, "got SIGPWR");
2583 /* See _what_ kind of SIGPWR this is. */
2584 pwrstat = 0;
2585 if ((fd = open(PWRSTAT, O_RDONLY)) >= 0) {
2586@@ -2157,9 +2259,7 @@
2587 }
2588
2589 if (ISMEMBER(got_signals, SIGINT)) {
2590-#if DEBUG
2591- log(L_VB, "got SIGINT");
2592-#endif
2593+ INITDBG(L_VB, "got SIGINT");
2594 /* Tell ctrlaltdel entry to start up */
2595 for(ch = family; ch; ch = ch->next)
2596 if (ch->action == CTRLALTDEL)
2597@@ -2168,9 +2268,7 @@
2598 }
2599
2600 if (ISMEMBER(got_signals, SIGWINCH)) {
2601-#if DEBUG
2602- log(L_VB, "got SIGWINCH");
2603-#endif
2604+ INITDBG(L_VB, "got SIGWINCH");
2605 /* Tell kbrequest entry to start up */
2606 for(ch = family; ch; ch = ch->next)
2607 if (ch->action == KBREQUEST)
2608@@ -2179,26 +2277,20 @@
2609 }
2610
2611 if (ISMEMBER(got_signals, SIGALRM)) {
2612-#if DEBUG
2613- log(L_VB, "got SIGALRM");
2614-#endif
2615+ INITDBG(L_VB, "got SIGALRM");
2616 /* The timer went off: check it out */
2617 DELSET(got_signals, SIGALRM);
2618 }
2619
2620 if (ISMEMBER(got_signals, SIGCHLD)) {
2621-#if DEBUG
2622- log(L_VB, "got SIGCHLD");
2623-#endif
2624+ INITDBG(L_VB, "got SIGCHLD");
2625 /* First set flag to 0 */
2626 DELSET(got_signals, SIGCHLD);
2627
2628 /* See which child this was */
2629 for(ch = family; ch; ch = ch->next)
2630 if (ch->flags & ZOMBIE) {
2631-#if DEBUG
2632- log(L_VB, "Child died, PID= %d", ch->pid);
2633-#endif
2634+ INITDBG(L_VB, "Child died, PID= %d", ch->pid);
2635 ch->flags &= ~(RUNNING|ZOMBIE|WAITING);
2636 if (ch->process[0] != '+')
2637 write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
2638@@ -2207,9 +2299,7 @@
2639 }
2640
2641 if (ISMEMBER(got_signals, SIGHUP)) {
2642-#if DEBUG
2643- log(L_VB, "got SIGHUP");
2644-#endif
2645+ INITDBG(L_VB, "got SIGHUP");
2646 #if CHANGE_WAIT
2647 /* Are we waiting for a child? */
2648 for(ch = family; ch; ch = ch->next)
2649@@ -2240,9 +2330,7 @@
2650 /*
2651 * SIGUSR1 means close and reopen /dev/initctl
2652 */
2653-#if DEBUG
2654- log(L_VB, "got SIGUSR1");
2655-#endif
2656+ INITDBG(L_VB, "got SIGUSR1");
2657 close(pipe_fd);
2658 pipe_fd = -1;
2659 DELSET(got_signals, SIGUSR1);
2660@@ -2254,11 +2342,11 @@
2661 */
2662 int init_main()
2663 {
2664- int f, st;
2665- pid_t rc;
2666- CHILD *ch;
2667- sigset_t sgt;
2668- struct sigaction sa;
2669+ CHILD *ch;
2670+ struct sigaction sa;
2671+ sigset_t sgt;
2672+ pid_t rc;
2673+ int f, st;
2674
2675 if (!reload) {
2676
2677@@ -2278,6 +2366,7 @@
2678 }
2679 #endif
2680
2681+#ifdef __linux__
2682 /*
2683 * Tell the kernel to send us SIGINT when CTRL-ALT-DEL
2684 * is pressed, and that we want to handle keyboard signals.
2685@@ -2288,6 +2377,7 @@
2686 close(f);
2687 } else
2688 (void) ioctl(0, KDSIGACCEPT, SIGWINCH);
2689+#endif
2690
2691 /*
2692 * Ignore all signals.
2693@@ -2320,9 +2410,9 @@
2694 setsid();
2695
2696 /*
2697- * Set default PATH variable (for ksh)
2698+ * Set default PATH variable.
2699 */
2700- if (getenv("PATH") == NULL) putenv(PATH_DFL);
2701+ putenv(PATH_DFL);
2702
2703 /*
2704 * Initialize /var/run/utmp (only works if /var is on
2705@@ -2333,7 +2423,7 @@
2706 /*
2707 * Say hello to the world
2708 */
2709- log(L_CO, bootmsg, "booting");
2710+ initlog(L_CO, bootmsg, "booting");
2711
2712 /*
2713 * See if we have to start an emergency shell.
2714@@ -2358,7 +2448,7 @@
2715 /*
2716 * Restart: unblock signals and let the show go on
2717 */
2718- log(L_CO, bootmsg, "reloading");
2719+ initlog(L_CO, bootmsg, "reloading");
2720 sigfillset(&sgt);
2721 sigprocmask(SIG_UNBLOCK, &sgt, NULL);
2722 }
2723@@ -2368,9 +2458,7 @@
2724
2725 /* See if we need to make the boot transitions. */
2726 boot_transitions();
2727-#if DEBUG
2728- log(L_VB, "init_main: waiting..");
2729-#endif
2730+ INITDBG(L_VB, "init_main: waiting..");
2731
2732 /* Check if there are processes to be waited on. */
2733 for(ch = family; ch; ch = ch->next)
2734@@ -2405,10 +2493,10 @@
2735 /*
2736 * Tell the user about the syntax we expect.
2737 */
2738-void Usage(char *s)
2739+void usage(char *s)
2740 {
2741- fprintf(stderr, "Usage: %s 0123456SsQqAaBbCcUu\n", s);
2742- exit(1);
2743+ fprintf(stderr, "Usage: %s 0123456SsQqAaBbCcUu\n", s);
2744+ exit(1);
2745 }
2746
2747 int telinit(char *progname, int argc, char **argv)
2748@@ -2418,28 +2506,51 @@
2749 #endif
2750 struct init_request request;
2751 struct sigaction sa;
2752- int f, fd;
2753+ int f, fd, l;
2754+ char *env = NULL;
2755
2756- while((f = getopt(argc, argv, "t:")) != EOF) switch(f) {
2757+ memset(&request, 0, sizeof(request));
2758+ request.magic = INIT_MAGIC;
2759+
2760+ while ((f = getopt(argc, argv, "t:e:")) != EOF) switch(f) {
2761 case 't':
2762 sltime = atoi(optarg);
2763 break;
2764+ case 'e':
2765+ if (env == NULL)
2766+ env = request.i.data;
2767+ l = strlen(optarg);
2768+ if (env + l + 2 > request.i.data + sizeof(request.i.data)) {
2769+ fprintf(stderr, "%s: -e option data "
2770+ "too large\n", progname);
2771+ exit(1);
2772+ }
2773+ memcpy(env, optarg, l);
2774+ env += l;
2775+ *env++ = 0;
2776+ break;
2777 default:
2778- Usage(progname);
2779+ usage(progname);
2780 break;
2781 }
2782
2783- /* Check syntax. */
2784- if (argc - optind != 1 || strlen(argv[optind]) != 1) Usage(progname);
2785- if (!strchr("0123456789SsQqAaBbCcUu", argv[optind][0])) Usage(progname);
2786+ if (env) *env++ = 0;
2787
2788- /* Open the fifo and write a command. */
2789- memset(&request, 0, sizeof(request));
2790- request.magic = INIT_MAGIC;
2791- request.cmd = INIT_CMD_RUNLVL;
2792- request.runlevel = argv[optind][0];
2793- request.sleeptime = sltime;
2794+ if (env) {
2795+ if (argc != optind)
2796+ usage(progname);
2797+ request.cmd = INIT_CMD_SETENV;
2798+ } else {
2799+ if (argc - optind != 1 || strlen(argv[optind]) != 1)
2800+ usage(progname);
2801+ if (!strchr("0123456789SsQqAaBbCcUu", argv[optind][0]))
2802+ usage(progname);
2803+ request.cmd = INIT_CMD_RUNLVL;
2804+ request.runlevel = env ? 0 : argv[optind][0];
2805+ request.sleeptime = sltime;
2806+ }
2807
2808+ /* Open the fifo and write a command. */
2809 /* Make sure we don't hang on opening /dev/initctl */
2810 SETSIG(sa, SIGALRM, signal_handler, 0);
2811 alarm(3);
2812@@ -2449,7 +2560,27 @@
2813 alarm(0);
2814 return 0;
2815 }
2816-#ifndef TELINIT_USES_INITLVL
2817+
2818+#ifdef TELINIT_USES_INITLVL
2819+ if (request.cmd == INIT_CMD_RUNLVL) {
2820+ /* Fallthrough to the old method. */
2821+
2822+ /* Now write the new runlevel. */
2823+ if ((fp = fopen(INITLVL, "w")) == NULL) {
2824+ fprintf(stderr, "%s: cannot create %s\n",
2825+ progname, INITLVL);
2826+ exit(1);
2827+ }
2828+ fprintf(fp, "%s %d", argv[optind], sltime);
2829+ fclose(fp);
2830+
2831+ /* And tell init about the pending runlevel change. */
2832+ if (kill(INITPID, SIGHUP) < 0) perror(progname);
2833+
2834+ return 0;
2835+ }
2836+#endif
2837+
2838 fprintf(stderr, "%s: ", progname);
2839 if (ISMEMBER(got_signals, SIGALRM)) {
2840 fprintf(stderr, "timeout opening/writing control channel %s\n",
2841@@ -2458,24 +2589,6 @@
2842 perror(INIT_FIFO);
2843 }
2844 return 1;
2845-#endif
2846-
2847- /* Fallthrough to the old method. */
2848-
2849-#ifdef TELINIT_USES_INITLVL
2850- /* Now write the new runlevel. */
2851- if ((fp = fopen(INITLVL, "w")) == NULL) {
2852- fprintf(stderr, "%s: cannot create %s\n", progname, INITLVL);
2853- exit(1);
2854- }
2855- fprintf(fp, "%s %d", argv[optind], sltime);
2856- fclose(fp);
2857-
2858- /* And tell init about the pending runlevel change. */
2859- if (kill(INITPID, SIGHUP) < 0) perror(progname);
2860-
2861- return 0;
2862-#endif
2863 }
2864
2865 /*
2866@@ -2518,7 +2631,7 @@
2867
2868 receive_state(STATE_PIPE);
2869
2870- myname = strdup(argv[0]);
2871+ myname = istrdup(argv[0]);
2872 argv0 = argv[0];
2873 maxproclen = 0;
2874 for (f = 0; f < argc; f++)
2875diff -urNd -urNd sysvinit-2.85/src/init.h sysvinit-2.86/src/init.h
2876--- sysvinit-2.85/src/init.h 1999-06-03 14:22:59.000000000 -0500
2877+++ sysvinit-2.86/src/init.h 2004-07-29 06:21:01.000000000 -0500
2878@@ -2,9 +2,8 @@
2879 * init.h Several defines and declarations to be
2880 * included by all modules of the init program.
2881 *
2882- * Version: @(#)init.h 2.74 09-Mar-1998 miquels@cistron.nl
2883+ * Version: @(#)init.h 2.85-5 02-Jul-2003 miquels@cistron.nl
2884 *
2885- * Modified: Re-exec patch; 24 Feb 1998, Al Viro.
2886 */
2887
2888 /* Standard configuration */
2889@@ -24,17 +23,26 @@
2890 #define TESTTIME 120 /* this much seconds */
2891 #define SLEEPTIME 300 /* Disable time */
2892
2893-/* Default path inherited by every child if it's not set. */
2894-#define PATH_DFL "PATH=/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin"
2895+/* Default path inherited by every child. */
2896+#define PATH_DFL "PATH=/bin:/usr/bin:/sbin:/usr/sbin"
2897
2898
2899 /* Prototypes. */
2900 void write_utmp_wtmp(char *user, char *id, int pid, int type, char *line);
2901 void write_wtmp(char *user, char *id, int pid, int type, char *line);
2902-void log(int loglevel, char *fmt, ...);
2903+#ifdef __GNUC__
2904+__attribute__ ((format (printf, 2, 3)))
2905+#endif
2906+void initlog(int loglevel, char *fmt, ...);
2907 void set_term(int how);
2908 void print(char *fmt);
2909
2910+#if DEBUG
2911+# define INITDBG(level, fmt, args...) initlog(level, fmt, ##args)
2912+#else
2913+# define INITDBG(level, fmt, args...)
2914+#endif
2915+
2916 /* Actions to be taken by init */
2917 #define RESPAWN 1
2918 #define WAIT 2
2919Binary files sysvinit-2.85/src/init.o and sysvinit-2.86/src/init.o differ
2920Binary files sysvinit-2.85/src/init_utmp.o and sysvinit-2.86/src/init_utmp.o differ
2921diff -urNd -urNd sysvinit-2.85/src/initreq.h sysvinit-2.86/src/initreq.h
2922--- sysvinit-2.85/src/initreq.h 1996-01-02 12:22:06.000000000 -0600
2923+++ sysvinit-2.86/src/initreq.h 2004-07-30 06:56:51.000000000 -0500
2924@@ -1,41 +1,77 @@
2925 /*
2926- * initreq.h Interface to let init spawn programs on behalf of
2927- * other programs/daemons.
2928- * Definitions based on sys_term.c from the BSD 4.4
2929- * telnetd source.
2930+ * initreq.h Interface to talk to init through /dev/initctl.
2931 *
2932- * Version: @(#)initreq.h 1.25 28-Dec-1995 MvS
2933+ * Copyright (C) 1995-2004 Miquel van Smoorenburg
2934+ *
2935+ * This library is free software; you can redistribute it and/or
2936+ * modify it under the terms of the GNU Lesser General Public
2937+ * License as published by the Free Software Foundation; either
2938+ * version 2 of the License, or (at your option) any later version.
2939+ *
2940+ * Version: @(#)initreq.h 1.28 31-Mar-2004 MvS
2941 *
2942- * Notes: Implemented in sysvinit-2.58 and up, but only
2943- * for "telinit". Support for rlogind, telnetd
2944- * and rxvt/xterm will follow shortly.
2945 */
2946 #ifndef _INITREQ_H
2947 #define _INITREQ_H
2948
2949 #include <sys/param.h>
2950
2951+#if defined(__FreeBSD_kernel__)
2952+# define INIT_FIFO "/etc/.initctl"
2953+#else
2954+# define INIT_FIFO "/dev/initctl"
2955+#endif
2956+
2957 #define INIT_MAGIC 0x03091969
2958-#define INIT_FIFO "/dev/initctl"
2959-#define INIT_CMD_START 0
2960-#define INIT_CMD_RUNLVL 1
2961-#define INIT_CMD_POWERFAIL 2
2962-#define INIT_CMD_POWERFAILNOW 3
2963-#define INIT_CMD_POWEROK 4
2964+#define INIT_CMD_START 0
2965+#define INIT_CMD_RUNLVL 1
2966+#define INIT_CMD_POWERFAIL 2
2967+#define INIT_CMD_POWERFAILNOW 3
2968+#define INIT_CMD_POWEROK 4
2969+#define INIT_CMD_BSD 5
2970+#define INIT_CMD_SETENV 6
2971+#define INIT_CMD_UNSETENV 7
2972+
2973+#define INIT_CMD_CHANGECONS 12345
2974+
2975+#ifdef MAXHOSTNAMELEN
2976+# define INITRQ_HLEN MAXHOSTNAMELEN
2977+#else
2978+# define INITRQ_HLEN 64
2979+#endif
2980+
2981+/*
2982+ * This is what BSD 4.4 uses when talking to init.
2983+ * Linux doesn't use this right now.
2984+ */
2985+struct init_request_bsd {
2986+ char gen_id[8]; /* Beats me.. telnetd uses "fe" */
2987+ char tty_id[16]; /* Tty name minus /dev/tty */
2988+ char host[INITRQ_HLEN]; /* Hostname */
2989+ char term_type[16]; /* Terminal type */
2990+ int signal; /* Signal to send */
2991+ int pid; /* Process to send to */
2992+ char exec_name[128]; /* Program to execute */
2993+ char reserved[128]; /* For future expansion. */
2994+};
2995+
2996
2997+/*
2998+ * Because of legacy interfaces, "runlevel" and "sleeptime"
2999+ * aren't in a seperate struct in the union.
3000+ *
3001+ * The weird sizes are because init expects the whole
3002+ * struct to be 384 bytes.
3003+ */
3004 struct init_request {
3005- int magic; /* Magic number */
3006- int cmd; /* What kind of request */
3007- int runlevel; /* Runlevel to change to */
3008- int sleeptime; /* Time between TERM and KILL */
3009- char gen_id[8]; /* Beats me.. telnetd uses "fe" */
3010- char tty_id[16]; /* Tty name minus /dev/tty */
3011- char host[MAXHOSTNAMELEN]; /* Hostname */
3012- char term_type[16]; /* Terminal type */
3013- int signal; /* Signal to send */
3014- int pid; /* Process to send to */
3015- char exec_name[128]; /* Program to execute */
3016- char reserved[128]; /* For future expansion. */
3017+ int magic; /* Magic number */
3018+ int cmd; /* What kind of request */
3019+ int runlevel; /* Runlevel to change to */
3020+ int sleeptime; /* Time between TERM and KILL */
3021+ union {
3022+ struct init_request_bsd bsd;
3023+ char data[368];
3024+ } i;
3025 };
3026
3027 #endif
3028Binary files sysvinit-2.85/src/killall5 and sysvinit-2.86/src/killall5 differ
3029diff -urNd -urNd sysvinit-2.85/src/killall5.c sysvinit-2.86/src/killall5.c
3030--- sysvinit-2.85/src/killall5.c 2003-04-14 04:59:11.000000000 -0500
3031+++ sysvinit-2.86/src/killall5.c 2004-07-30 07:16:23.000000000 -0500
3032@@ -5,7 +5,7 @@
3033 *
3034 * pidof.c Tries to get the pid of the process[es] named.
3035 *
3036- * Version: 2.85 14-Apr-2003 MvS
3037+ * Version: 2.86 30-Jul-2004 MvS
3038 *
3039 * Usage: killall5 [-][signal]
3040 * pidof [-s] [-o omitpid [-o omitpid]] program [program..]
3041@@ -20,7 +20,7 @@
3042 * - swapped out programs pids are caught now
3043 *
3044 * This file is part of the sysvinit suite,
3045- * Copyright 1991-2003 Miquel van Smoorenburg.
3046+ * Copyright 1991-2004 Miquel van Smoorenburg.
3047 *
3048 * This program is free software; you can redistribute it and/or
3049 * modify it under the terms of the GNU General Public License
3050@@ -41,34 +41,43 @@
3051 #include <getopt.h>
3052 #include <stdarg.h>
3053
3054-char *Version = "@(#)killall5 2.85 14-Apr-2003 miquels@cistron.nl";
3055+char *Version = "@(#)killall5 2.86 31-Jul-2004 miquels@cistron.nl";
3056+
3057+#define STATNAMELEN 15
3058
3059 /* Info about a process. */
3060-typedef struct _proc_
3061-{
3062- char *fullname; /* Name as found out from argv[0] */
3063- char *basename; /* Only the part after the last / */
3064- char *statname; /* the statname without braces */
3065- ino_t ino; /* Inode number */
3066- dev_t dev; /* Device it is on */
3067- pid_t pid; /* Process ID. */
3068- int sid; /* Session ID. */
3069- struct _proc_ *next; /* Pointer to next struct. */
3070+typedef struct proc {
3071+ char *argv0; /* Name as found out from argv[0] */
3072+ char *argv0base; /* `basename argv[1]` */
3073+ char *argv1; /* Name as found out from argv[1] */
3074+ char *argv1base; /* `basename argv[1]` */
3075+ char *statname; /* the statname without braces */
3076+ ino_t ino; /* Inode number */
3077+ dev_t dev; /* Device it is on */
3078+ pid_t pid; /* Process ID. */
3079+ int sid; /* Session ID. */
3080+ int kernel; /* Kernel thread or zombie. */
3081+ struct proc *next; /* Pointer to next struct. */
3082 } PROC;
3083
3084 /* pid queue */
3085-typedef struct _pidq_ {
3086- struct _pidq_ *front;
3087- struct _pidq_ *next;
3088- struct _pidq_ *rear;
3089- PROC *proc;
3090+
3091+typedef struct pidq {
3092+ PROC *proc;
3093+ struct pidq *next;
3094 } PIDQ;
3095
3096+typedef struct {
3097+ PIDQ *head;
3098+ PIDQ *tail;
3099+ PIDQ *next;
3100+} PIDQ_HEAD;
3101+
3102 /* List of processes. */
3103 PROC *plist;
3104
3105-/* Did we stop a number of processes? */
3106-int stopped;
3107+/* Did we stop all processes ? */
3108+int sent_sigstop;
3109
3110 int scripts_too = 0;
3111
3112@@ -86,7 +95,7 @@
3113 void *p;
3114
3115 if ((p = malloc(bytes)) == NULL) {
3116- if (stopped) kill(-1, SIGCONT);
3117+ if (sent_sigstop) kill(-1, SIGCONT);
3118 nsyslog(LOG_ERR, "out of memory");
3119 exit(1);
3120 }
3121@@ -98,14 +107,14 @@
3122 */
3123 int mount_proc(void)
3124 {
3125- struct stat st;
3126- pid_t pid, rc;
3127- int wst;
3128- char *args[] = { "mount", "-t", "proc", "none", "/proc", NULL };
3129- int did_mount = 0;
3130+ struct stat st;
3131+ char *args[] = { "mount", "-t", "proc", "proc", "/proc", 0 };
3132+ pid_t pid, rc;
3133+ int wst;
3134+ int did_mount = 0;
3135
3136 /* Stat /proc/version to see if /proc is mounted. */
3137- if (stat("/proc/version", &st) < 0) {
3138+ if (stat("/proc/version", &st) < 0 && errno == ENOENT) {
3139
3140 /* It's not there, so mount it. */
3141 if ((pid = fork()) < 0) {
3142@@ -115,7 +124,6 @@
3143 if (pid == 0) {
3144 /* Try a few mount binaries. */
3145 execv("/sbin/mount", args);
3146- execv("/etc/mount", args);
3147 execv("/bin/mount", args);
3148
3149 /* Okay, I give up. */
3150@@ -134,28 +142,42 @@
3151
3152 /* See if mount succeeded. */
3153 if (stat("/proc/version", &st) < 0) {
3154- nsyslog(LOG_ERR, "/proc not mounted, failed to mount.");
3155+ if (errno == ENOENT)
3156+ nsyslog(LOG_ERR, "/proc not mounted, failed to mount.");
3157+ else
3158+ nsyslog(LOG_ERR, "/proc unavailable.");
3159 exit(1);
3160 }
3161
3162 return did_mount;
3163 }
3164
3165+int readarg(FILE *fp, char *buf, int sz)
3166+{
3167+ int c = 0, f = 0;
3168+
3169+ while (f < (sz-1) && (c = fgetc(fp)) != EOF && c)
3170+ buf[f++] = c;
3171+ buf[f] = 0;
3172+
3173+ return (c == EOF && f == 0) ? c : f;
3174+}
3175+
3176 /*
3177 * Read the proc filesystem.
3178 */
3179 int readproc()
3180 {
3181- DIR *dir;
3182- struct dirent *d;
3183- char path[256];
3184- char buf[256];
3185- char *s, *q;
3186- FILE *fp;
3187- int pid, f;
3188- PROC *p, *n;
3189- struct stat st;
3190- int c;
3191+ DIR *dir;
3192+ FILE *fp;
3193+ PROC *p, *n;
3194+ struct dirent *d;
3195+ struct stat st;
3196+ char path[256];
3197+ char buf[256];
3198+ char *s, *q;
3199+ unsigned long startcode, endcode;
3200+ int pid, f;
3201
3202 /* Open the /proc directory. */
3203 if ((dir = opendir("/proc")) == NULL) {
3204@@ -167,7 +189,8 @@
3205 n = plist;
3206 for (p = plist; n; p = n) {
3207 n = p->next;
3208- if (p->fullname) free(p->fullname);
3209+ if (p->argv0) free(p->argv0);
3210+ if (p->argv1) free(p->argv1);
3211 free(p);
3212 }
3213 plist = NULL;
3214@@ -188,7 +211,7 @@
3215 /* Read SID & statname from it. */
3216 if ((fp = fopen(path, "r")) != NULL) {
3217 buf[0] = 0;
3218- fgets(buf, 256, fp);
3219+ fgets(buf, sizeof(buf), fp);
3220
3221 /* See if name starts with '(' */
3222 s = buf;
3223@@ -215,14 +238,21 @@
3224 p->statname = (char *)xmalloc(strlen(s)+1);
3225 strcpy(p->statname, s);
3226
3227- /* This could be replaced by getsid(pid) */
3228- if (sscanf(q, "%*c %*d %*d %d", &p->sid) != 1) {
3229+ /* Get session, startcode, endcode. */
3230+ startcode = endcode = 0;
3231+ if (sscanf(q, "%*c %*d %*d %d %*d %*d %*u %*u "
3232+ "%*u %*u %*u %*u %*u %*d %*d "
3233+ "%*d %*d %*d %*d %*u %*u %*d "
3234+ "%*u %lu %lu",
3235+ &p->sid, &startcode, &endcode) != 3) {
3236 p->sid = 0;
3237 nsyslog(LOG_ERR, "can't read sid from %s\n",
3238 path);
3239 free(p);
3240 continue;
3241 }
3242+ if (startcode == 0 && endcode == 0)
3243+ p->kernel = 1;
3244 fclose(fp);
3245 } else {
3246 /* Process disappeared.. */
3247@@ -230,24 +260,44 @@
3248 continue;
3249 }
3250
3251- /* Now read argv[0] */
3252 snprintf(path, sizeof(path), "/proc/%s/cmdline", d->d_name);
3253 if ((fp = fopen(path, "r")) != NULL) {
3254- f = 0;
3255- while(f < 127 && (c = fgetc(fp)) != EOF && c)
3256- buf[f++] = c;
3257- buf[f++] = 0;
3258- fclose(fp);
3259
3260- /* Store the name into malloced memory. */
3261- p->fullname = (char *)xmalloc(f);
3262- strcpy(p->fullname, buf);
3263+ /* Now read argv[0] */
3264+ f = readarg(fp, buf, sizeof(buf));
3265+
3266+ if (buf[0]) {
3267+ /* Store the name into malloced memory. */
3268+ p->argv0 = (char *)xmalloc(f + 1);
3269+ strcpy(p->argv0, buf);
3270+
3271+ /* Get a pointer to the basename. */
3272+ p->argv0base = strrchr(p->argv0, '/');
3273+ if (p->argv0base != NULL)
3274+ p->argv0base++;
3275+ else
3276+ p->argv0base = p->argv0;
3277+ }
3278+
3279+ /* And read argv[1] */
3280+ while ((f = readarg(fp, buf, sizeof(buf))) != EOF)
3281+ if (buf[0] != '-') break;
3282+
3283+ if (buf[0]) {
3284+ /* Store the name into malloced memory. */
3285+ p->argv1 = (char *)xmalloc(f + 1);
3286+ strcpy(p->argv1, buf);
3287+
3288+ /* Get a pointer to the basename. */
3289+ p->argv1base = strrchr(p->argv1, '/');
3290+ if (p->argv1base != NULL)
3291+ p->argv1base++;
3292+ else
3293+ p->argv1base = p->argv1;
3294+ }
3295+
3296+ fclose(fp);
3297
3298- /* Get a pointer to the basename. */
3299- if ((p->basename = strrchr(p->fullname, '/')) != NULL)
3300- p->basename++;
3301- else
3302- p->basename = p->fullname;
3303 } else {
3304 /* Process disappeared.. */
3305 free(p);
3306@@ -272,19 +322,18 @@
3307 return 0;
3308 }
3309
3310-PIDQ *init_pid_q(PIDQ *q)
3311+PIDQ_HEAD *init_pid_q(PIDQ_HEAD *q)
3312 {
3313- q->front = q->next = q->rear = NULL;
3314- q->proc = NULL;
3315+ q->head = q->next = q->tail = NULL;
3316 return q;
3317 }
3318
3319-int empty_q(PIDQ *q)
3320+int empty_q(PIDQ_HEAD *q)
3321 {
3322- return (q->front == NULL);
3323+ return (q->head == NULL);
3324 }
3325
3326-int add_pid_to_q(PIDQ *q, PROC *p)
3327+int add_pid_to_q(PIDQ_HEAD *q, PROC *p)
3328 {
3329 PIDQ *tmp;
3330
3331@@ -294,23 +343,23 @@
3332 tmp->next = NULL;
3333
3334 if (empty_q(q)) {
3335- q->front = tmp;
3336- q->rear = tmp;
3337+ q->head = tmp;
3338+ q->tail = tmp;
3339 } else {
3340- q->rear->next = tmp;
3341- q->rear = tmp;
3342+ q->tail->next = tmp;
3343+ q->tail = tmp;
3344 }
3345 return 0;
3346 }
3347
3348-PROC *get_next_from_pid_q(PIDQ *q)
3349+PROC *get_next_from_pid_q(PIDQ_HEAD *q)
3350 {
3351- PROC *p;
3352- PIDQ *tmp = q->front;
3353+ PROC *p;
3354+ PIDQ *tmp = q->head;
3355
3356 if (!empty_q(q)) {
3357- p = q->front->proc;
3358- q->front = tmp->next;
3359+ p = q->head->proc;
3360+ q->head = tmp->next;
3361 free(tmp);
3362 return p;
3363 }
3364@@ -319,15 +368,15 @@
3365 }
3366
3367 /* Try to get the process ID of a given process. */
3368-PIDQ *pidof(char *prog)
3369+PIDQ_HEAD *pidof(char *prog)
3370 {
3371- struct stat st;
3372- int dostat = 0;
3373- PROC *p;
3374- PIDQ *q;
3375- char *s;
3376- int foundone = 0;
3377- int ok = 0;
3378+ PROC *p;
3379+ PIDQ_HEAD *q;
3380+ struct stat st;
3381+ char *s;
3382+ int dostat = 0;
3383+ int foundone = 0;
3384+ int ok = 0;
3385
3386 /* Try to stat the executable. */
3387 if (prog[0] == '/' && stat(prog, &st) == 0) dostat++;
3388@@ -338,7 +387,7 @@
3389 else
3390 s++;
3391
3392- q = (PIDQ *)xmalloc(sizeof(PIDQ));
3393+ q = (PIDQ_HEAD *)xmalloc(sizeof(PIDQ_HEAD));
3394 q = init_pid_q(q);
3395
3396 /* First try to find a match based on dev/ino pair. */
3397@@ -352,20 +401,31 @@
3398 }
3399
3400 /* If we didn't find a match based on dev/ino, try the name. */
3401- if (!foundone) {
3402- for (p = plist; p; p = p->next) {
3403- ok = 0;
3404+ if (!foundone) for (p = plist; p; p = p->next) {
3405+ ok = 0;
3406
3407- ok += (strcmp(p->fullname, prog) == 0);
3408- ok += (strcmp(p->basename, s) == 0);
3409+ /* Compare name (both basename and full path) */
3410+ ok += (p->argv0 && strcmp(p->argv0, prog) == 0);
3411+ ok += (p->argv0 && strcmp(p->argv0base, s) == 0);
3412
3413- if (p->fullname[0] == 0 ||
3414- strchr(p->fullname, ' ') ||
3415- scripts_too)
3416- ok += (strcmp(p->statname, s) == 0);
3417+ /* For scripts, compare argv[1] as well. */
3418+ if (scripts_too && p->argv1 &&
3419+ !strncmp(p->statname, p->argv1base, STATNAMELEN)) {
3420+ ok += (strcmp(p->argv1, prog) == 0);
3421+ ok += (strcmp(p->argv1base, s) == 0);
3422+ }
3423
3424- if (ok) add_pid_to_q(q, p);
3425+ /*
3426+ * if we have a space in argv0, process probably
3427+ * used setproctitle so try statname.
3428+ */
3429+ if (strlen(s) <= STATNAMELEN &&
3430+ (p->argv0 == NULL ||
3431+ p->argv0[0] == 0 ||
3432+ strchr(p->argv0, ' '))) {
3433+ ok += (strcmp(p->statname, s) == 0);
3434 }
3435+ if (ok) add_pid_to_q(q, p);
3436 }
3437
3438 return q;
3439@@ -410,12 +470,12 @@
3440 */
3441 int main_pidof(int argc, char **argv)
3442 {
3443- PROC *p;
3444- PIDQ *q;
3445- int f;
3446- int first = 1;
3447- int i,oind, opt, flags = 0;
3448- pid_t opid[PIDOF_OMITSZ], spid;
3449+ PIDQ_HEAD *q;
3450+ PROC *p;
3451+ pid_t opid[PIDOF_OMITSZ], spid;
3452+ int f;
3453+ int first = 1;
3454+ int i, oind, opt, flags = 0;
3455
3456 for (oind = PIDOF_OMITSZ-1; oind > 0; oind--)
3457 opid[oind] = 0;
3458@@ -498,9 +558,9 @@
3459 /* Main for either killall or pidof. */
3460 int main(int argc, char **argv)
3461 {
3462- PROC *p;
3463- int pid, sid = -1;
3464- int sig = SIGKILL;
3465+ PROC *p;
3466+ int pid, sid = -1;
3467+ int sig = SIGKILL;
3468
3469 /* Get program name. */
3470 if ((progname = strrchr(argv[0], '/')) == NULL)
3471@@ -511,9 +571,6 @@
3472 /* Now connect to syslog. */
3473 openlog(progname, LOG_CONS|LOG_PID, LOG_DAEMON);
3474
3475- /* First get the /proc filesystem online. */
3476- mount_proc();
3477-
3478 /* Were we called as 'pidof' ? */
3479 if (strcmp(progname, "pidof") == 0)
3480 return main_pidof(argc, argv);
3481@@ -525,6 +582,9 @@
3482 if ((sig = atoi(argv[1])) <= 0 || sig > 31) usage();
3483 }
3484
3485+ /* First get the /proc filesystem online. */
3486+ mount_proc();
3487+
3488 /*
3489 * Ignoring SIGKILL and SIGSTOP do not make sense, but
3490 * someday kill(-1, sig) might kill ourself if we don't
3491@@ -537,24 +597,19 @@
3492
3493 /* Now stop all processes. */
3494 kill(-1, SIGSTOP);
3495- stopped = 1;
3496+ sent_sigstop = 1;
3497
3498- /* Find out our own 'sid'. */
3499+ /* Read /proc filesystem */
3500 if (readproc() < 0) {
3501 kill(-1, SIGCONT);
3502 exit(1);
3503 }
3504
3505- pid = getpid();
3506- for (p = plist; p; p = p->next)
3507- if (p->pid == pid) {
3508- sid = p->sid;
3509- break;
3510- }
3511-
3512 /* Now kill all processes except our session. */
3513+ sid = (int)getsid(0);
3514+ pid = (int)getpid();
3515 for (p = plist; p; p = p->next)
3516- if (p->pid != pid && p->sid != sid)
3517+ if (p->pid != pid && p->sid != sid && !p->kernel)
3518 kill(p->pid, sig);
3519
3520 /* And let them continue. */
3521Binary files sysvinit-2.85/src/last and sysvinit-2.86/src/last differ
3522diff -urNd -urNd sysvinit-2.85/src/last.c sysvinit-2.86/src/last.c
3523--- sysvinit-2.85/src/last.c 2003-04-17 06:38:56.000000000 -0500
3524+++ sysvinit-2.86/src/last.c 2004-07-30 07:16:26.000000000 -0500
3525@@ -6,10 +6,10 @@
3526 *
3527 * Author: Miquel van Smoorenburg, miquels@cistron.nl
3528 *
3529- * Version: @(#)last 2.85 16-Apr-2003 miquels@cistron.nl
3530+ * Version: @(#)last 2.85 30-Jul-2004 miquels@cistron.nl
3531 *
3532 * This file is part of the sysvinit suite,
3533- * Copyright 1991-2003 Miquel van Smoorenburg.
3534+ * Copyright 1991-2004 Miquel van Smoorenburg.
3535 *
3536 * This program is free software; you can redistribute it and/or
3537 * modify it under the terms of the GNU General Public License
3538@@ -40,7 +40,7 @@
3539 # define SHUTDOWN_TIME 254
3540 #endif
3541
3542-char *Version = "@(#) last 2.85 16-Apr-2003 miquels";
3543+char *Version = "@(#) last 2.85 31-Apr-2004 miquels";
3544
3545 #define CHOP_DOMAIN 0 /* Define to chop off local domainname. */
3546 #define NEW_UTMP 1 /* Fancy & fast utmp read code. */
3547@@ -491,10 +491,48 @@
3548 void usage(char *s)
3549 {
3550 fprintf(stderr, "Usage: %s [-num | -n num] [-f file] "
3551+ "[-t YYYYMMDDHHMMSS] "
3552 "[-R] [-x] [-o] [username..] [tty..]\n", s);
3553 exit(1);
3554 }
3555
3556+time_t parsetm(char *ts)
3557+{
3558+ struct tm u = {0}, origu;
3559+ time_t tm;
3560+
3561+ if (sscanf(ts, "%4d%2d%2d%2d%2d%2d", &u.tm_year,
3562+ &u.tm_mon, &u.tm_mday, &u.tm_hour, &u.tm_min,
3563+ &u.tm_sec) != 6)
3564+ return (time_t)-1;
3565+
3566+ u.tm_year -= 1900;
3567+ u.tm_mon -= 1;
3568+ u.tm_isdst = -1;
3569+
3570+ origu = u;
3571+
3572+ if ((tm = mktime(&u)) == (time_t)-1)
3573+ return tm;
3574+
3575+ /*
3576+ * Unfortunately mktime() is much more forgiving than
3577+ * it should be. For example, it'll gladly accept
3578+ * "30" as a valid month number. This behavior is by
3579+ * design, but we don't like it, so we want to detect
3580+ * it and complain.
3581+ */
3582+ if (u.tm_year != origu.tm_year ||
3583+ u.tm_mon != origu.tm_mon ||
3584+ u.tm_mday != origu.tm_mday ||
3585+ u.tm_hour != origu.tm_hour ||
3586+ u.tm_min != origu.tm_min ||
3587+ u.tm_sec != origu.tm_sec)
3588+ return (time_t)-1;
3589+
3590+ return tm;
3591+}
3592+
3593 int main(int argc, char **argv)
3594 {
3595 FILE *fp; /* Filepointer of wtmp file */
3596@@ -518,10 +556,12 @@
3597 int extended = 0; /* Lots of info. */
3598 char *altufile = NULL;/* Alternate wtmp */
3599
3600+ time_t until = 0; /* at what time to stop parsing the file */
3601+
3602 progname = mybasename(argv[0]);
3603
3604 /* Process the arguments. */
3605- while((c = getopt(argc, argv, "f:n:Rxadio0123456789")) != EOF)
3606+ while((c = getopt(argc, argv, "f:n:Rxadiot:0123456789")) != EOF)
3607 switch(c) {
3608 case 'R':
3609 showhost = 0;
3610@@ -552,6 +592,13 @@
3611 case 'a':
3612 altlist++;
3613 break;
3614+ case 't':
3615+ if ((until = parsetm(optarg)) == (time_t)-1) {
3616+ fprintf(stderr, "%s: Invalid time value \"%s\"\n",
3617+ progname, optarg);
3618+ usage(progname);
3619+ }
3620+ break;
3621 case '0': case '1': case '2': case '3': case '4':
3622 case '5': case '6': case '7': case '8': case '9':
3623 maxrecs = 10*maxrecs + c - '0';
3624@@ -650,6 +697,9 @@
3625 if (uread(fp, &ut, &quit) != 1)
3626 break;
3627
3628+ if (until && until < ut.ut_time)
3629+ continue;
3630+
3631 if (memcmp(&ut, &oldut, sizeof(struct utmp)) == 0) continue;
3632 memcpy(&oldut, &ut, sizeof(struct utmp));
3633 lastdate = ut.ut_time;
3634Binary files sysvinit-2.85/src/last.o and sysvinit-2.86/src/last.o differ
3635Binary files sysvinit-2.85/src/mesg and sysvinit-2.86/src/mesg differ
3636Binary files sysvinit-2.85/src/mesg.o and sysvinit-2.86/src/mesg.o differ
3637Binary files sysvinit-2.85/src/mountpoint and sysvinit-2.86/src/mountpoint differ
3638diff -urNd -urNd sysvinit-2.85/src/mountpoint.c sysvinit-2.86/src/mountpoint.c
3639--- sysvinit-2.85/src/mountpoint.c 1969-12-31 18:00:00.000000000 -0600
3640+++ sysvinit-2.86/src/mountpoint.c 2004-06-09 07:47:45.000000000 -0500
3641@@ -0,0 +1,119 @@
3642+/*
3643+ * mountpoint See if a directory is a mountpoint.
3644+ *
3645+ * Author: Miquel van Smoorenburg.
3646+ *
3647+ * Version: @(#)mountpoint 2.85-12 17-Mar-2004 miquels@cistron.nl
3648+ *
3649+ * This file is part of the sysvinit suite,
3650+ * Copyright 1991-2004 Miquel van Smoorenburg.
3651+ *
3652+ * This program is free software; you can redistribute it and/or
3653+ * modify it under the terms of the GNU General Public License
3654+ * as published by the Free Software Foundation; either version
3655+ * 2 of the License, or (at your option) any later version.
3656+ */
3657+
3658+#include <sys/stat.h>
3659+#include <unistd.h>
3660+#include <stdlib.h>
3661+#include <string.h>
3662+#include <errno.h>
3663+#include <stdarg.h>
3664+#include <getopt.h>
3665+#include <stdio.h>
3666+
3667+int dostat(char *path, struct stat *st, int do_lstat, int quiet)
3668+{
3669+ int n;
3670+
3671+ if (do_lstat)
3672+ n = lstat(path, st);
3673+ else
3674+ n = stat(path, st);
3675+
3676+ if (n != 0) {
3677+ if (!quiet)
3678+ fprintf(stderr, "mountpoint: %s: %s\n", path,
3679+ strerror(errno));
3680+ return -1;
3681+ }
3682+ return 0;
3683+}
3684+
3685+void usage(void) {
3686+ fprintf(stderr, "Usage: mountpoint [-q] [-d] [-x] path\n");
3687+ exit(1);
3688+}
3689+
3690+int main(int argc, char **argv)
3691+{
3692+ struct stat st, st2;
3693+ char buf[256];
3694+ char *path;
3695+ int quiet = 0;
3696+ int showdev = 0;
3697+ int xdev = 0;
3698+ int c, r;
3699+
3700+ while ((c = getopt(argc, argv, "dqx")) != EOF) switch(c) {
3701+ case 'd':
3702+ showdev = 1;
3703+ break;
3704+ case 'q':
3705+ quiet = 1;
3706+ break;
3707+ case 'x':
3708+ xdev = 1;
3709+ break;
3710+ default:
3711+ usage();
3712+ break;
3713+ }
3714+ if (optind != argc - 1) usage();
3715+ path = argv[optind];
3716+
3717+ if (dostat(path, &st, !xdev, quiet) < 0)
3718+ return 1;
3719+
3720+ if (xdev) {
3721+#ifdef __linux__
3722+ if (!S_ISBLK(st.st_mode))
3723+#else
3724+ if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
3725+#endif
3726+ {
3727+ if (quiet)
3728+ printf("\n");
3729+ else
3730+ fprintf(stderr, "mountpoint: %s: not a block device\n",
3731+ path);
3732+ return 1;
3733+ }
3734+ printf("%u:%u\n", major(st.st_rdev), minor(st.st_rdev));
3735+ return 0;
3736+ }
3737+
3738+ if (!S_ISDIR(st.st_mode)) {
3739+ if (!quiet)
3740+ fprintf(stderr, "mountpoint: %s: not a directory\n",
3741+ path);
3742+ return 1;
3743+ }
3744+
3745+ memset(buf, 0, sizeof(buf));
3746+ strncpy(buf, path, sizeof(buf) - 4);
3747+ strcat(buf, "/..");
3748+ if (dostat(buf, &st2, 0, quiet) < 0)
3749+ return 1;
3750+
3751+ r = (st.st_dev != st2.st_dev) ||
3752+ (st.st_dev == st2.st_dev && st.st_ino == st2.st_ino);
3753+
3754+ if (!quiet && !showdev)
3755+ printf("%s is %sa mountpoint\n", path, r ? "" : "not ");
3756+ if (showdev)
3757+ printf("%u:%u\n", major(st.st_dev), minor(st.st_dev));
3758+
3759+ return r ? 0 : 1;
3760+}
3761Binary files sysvinit-2.85/src/mountpoint.o and sysvinit-2.86/src/mountpoint.o differ
3762diff -urNd -urNd sysvinit-2.85/src/paths.h sysvinit-2.86/src/paths.h
3763--- sysvinit-2.85/src/paths.h 2003-04-14 06:37:01.000000000 -0500
3764+++ sysvinit-2.86/src/paths.h 2004-06-09 07:47:45.000000000 -0500
3765@@ -1,7 +1,7 @@
3766 /*
3767 * paths.h Paths of files that init and related utilities need.
3768 *
3769- * Version: @(#) paths.h 2.84 27-Nov-2001
3770+ * Version: @(#) paths.h 2.85-8 05-Nov-2003
3771 *
3772 * Author: Miquel van Smoorenburg, <miquels@cistron.nl>
3773 *
3774@@ -24,6 +24,7 @@
3775 #define FORCEFSCK "/forcefsck" /* Force fsck on boot */
3776 #define SDPID "/var/run/shutdown.pid" /* PID of shutdown program */
3777 #define SHELL "/bin/sh" /* Default shell */
3778+#define SULOGIN "/sbin/sulogin" /* Sulogin */
3779 #define INITSCRIPT "/etc/initscript" /* Initscript. */
3780 #define PWRSTAT "/etc/powerstatus" /* COMPAT: SIGPWR reason (OK/BAD) */
3781
3782diff -urNd -urNd sysvinit-2.85/src/reboot.h sysvinit-2.86/src/reboot.h
3783--- sysvinit-2.85/src/reboot.h 1997-09-24 03:55:52.000000000 -0500
3784+++ sysvinit-2.86/src/reboot.h 2004-06-09 07:47:45.000000000 -0500
3785@@ -2,22 +2,35 @@
3786 * reboot.h Headerfile that defines how to handle
3787 * the reboot() system call.
3788 *
3789- * Version: @(#)reboot.h 1.00 23-Jul-1996 miquels@cistron.nl
3790+ * Version: @(#)reboot.h 2.85-17 04-Jun-2004 miquels@cistron.nl
3791 *
3792 */
3793
3794-#if defined(__GLIBC__)
3795-# include <sys/reboot.h>
3796+#include <sys/reboot.h>
3797+
3798+#ifdef RB_ENABLE_CAD
3799+# define BMAGIC_HARD RB_ENABLE_CAD
3800 #endif
3801
3802-#define BMAGIC_HARD 0x89ABCDEF
3803-#define BMAGIC_SOFT 0
3804-#define BMAGIC_REBOOT 0x01234567
3805-#define BMAGIC_HALT 0xCDEF0123
3806-#define BMAGIC_POWEROFF 0x4321FEDC
3807+#ifdef RB_DISABLE_CAD
3808+# define BMAGIC_SOFT RB_DISABLE_CAD
3809+#endif
3810
3811-#if defined(__GLIBC__)
3812- #define init_reboot(magic) reboot(magic)
3813+#ifdef RB_HALT_SYSTEM
3814+# define BMAGIC_HALT RB_HALT_SYSTEM
3815 #else
3816- #define init_reboot(magic) reboot(0xfee1dead, 672274793, magic)
3817+# define BMAGIC_HALT RB_HALT
3818 #endif
3819+
3820+#define BMAGIC_REBOOT RB_AUTOBOOT
3821+
3822+#ifdef RB_POWER_OFF
3823+# define BMAGIC_POWEROFF RB_POWER_OFF
3824+#elif defined(RB_POWEROFF)
3825+# define BMAGIC_POWEROFF RB_POWEROFF
3826+#else
3827+# define BMAGIC_POWEROFF BMAGIC_HALT
3828+#endif
3829+
3830+#define init_reboot(magic) reboot(magic)
3831+
3832Binary files sysvinit-2.85/src/runlevel and sysvinit-2.86/src/runlevel differ
3833Binary files sysvinit-2.85/src/runlevel.o and sysvinit-2.86/src/runlevel.o differ
3834Binary files sysvinit-2.85/src/shutdown and sysvinit-2.86/src/shutdown differ
3835diff -urNd -urNd sysvinit-2.85/src/shutdown.c sysvinit-2.86/src/shutdown.c
3836--- sysvinit-2.85/src/shutdown.c 2003-04-14 06:35:51.000000000 -0500
3837+++ sysvinit-2.86/src/shutdown.c 2004-07-30 06:59:04.000000000 -0500
3838@@ -13,10 +13,10 @@
3839 *
3840 * Author: Miquel van Smoorenburg, miquels@cistron.nl
3841 *
3842- * Version: @(#)shutdown 2.85 14-Apr-2003 miquels@cistron.nl
3843+ * Version: @(#)shutdown 2.86-1 31-Jul-2004 miquels@cistron.nl
3844 *
3845 * This file is part of the sysvinit suite,
3846- * Copyright 1991-2003 Miquel van Smoorenburg.
3847+ * Copyright 1991-2004 Miquel van Smoorenburg.
3848 *
3849 * This program is free software; you can redistribute it and/or
3850 * modify it under the terms of the GNU General Public License
3851@@ -36,10 +36,12 @@
3852 #include <fcntl.h>
3853 #include <stdarg.h>
3854 #include <utmp.h>
3855+#include <syslog.h>
3856 #include "paths.h"
3857 #include "reboot.h"
3858+#include "initreq.h"
3859
3860-char *Version = "@(#) shutdown 2.85 14-Apr-2003 miquels@cistron.nl";
3861+char *Version = "@(#) shutdown 2.86-1 31-Jul-2004 miquels@cistron.nl";
3862
3863 #define MESSAGELEN 256
3864
3865@@ -52,6 +54,7 @@
3866 char *sltime = 0; /* Sleep time */
3867 char newstate[64]; /* What are we gonna do */
3868 int doself = 0; /* Don't use init */
3869+int got_alrm = 0;
3870
3871 char *clean_env[] = {
3872 "HOME=/",
3873@@ -67,93 +70,152 @@
3874 extern void write_wtmp(char *user, char *id, int pid, int type, char *line);
3875
3876 /*
3877- * Sleep without being interrupted.
3878+ * Sleep without being interrupted.
3879 */
3880 void hardsleep(int secs)
3881 {
3882- struct timespec ts, rem;
3883+ struct timespec ts, rem;
3884
3885- ts.tv_sec = secs;
3886- ts.tv_nsec = 0;
3887+ ts.tv_sec = secs;
3888+ ts.tv_nsec = 0;
3889
3890- while(nanosleep(&ts, &rem) < 0 && errno == EINTR)
3891+ while(nanosleep(&ts, &rem) < 0 && errno == EINTR)
3892 ts = rem;
3893 }
3894
3895 /*
3896- * Break off an already running shutdown.
3897+ * Break off an already running shutdown.
3898 */
3899-void stopit()
3900+void stopit(int sig)
3901 {
3902- unlink(NOLOGIN);
3903- unlink(FASTBOOT);
3904- unlink(FORCEFSCK);
3905- unlink(SDPID);
3906- printf("\r\nShutdown cancelled.\r\n");
3907- exit(0);
3908+ unlink(NOLOGIN);
3909+ unlink(FASTBOOT);
3910+ unlink(FORCEFSCK);
3911+ unlink(SDPID);
3912+ printf("\r\nShutdown cancelled.\r\n");
3913+ exit(0);
3914 }
3915
3916 /*
3917- * Show usage message.
3918+ * Show usage message.
3919 */
3920-void usage()
3921+void usage(void)
3922 {
3923- fprintf(stderr,
3924- "Usage:\t shutdown [-akrhfnc] [-t secs] time [warning message]\n"
3925+ fprintf(stderr,
3926+ "Usage:\t shutdown [-akrhHPfnc] [-t secs] time [warning message]\n"
3927 "\t\t -a: use /etc/shutdown.allow\n"
3928 "\t\t -k: don't really shutdown, only warn.\n"
3929 "\t\t -r: reboot after shutdown.\n"
3930 "\t\t -h: halt after shutdown.\n"
3931+ "\t\t -P: halt action is to turn off power.\n"
3932+ "\t\t -H: halt action is to just halt.\n"
3933 "\t\t -f: do a 'fast' reboot (skip fsck).\n"
3934 "\t\t -F: Force fsck on reboot.\n"
3935 "\t\t -n: do not go through \"init\" but go down real fast.\n"
3936 "\t\t -c: cancel a running shutdown.\n"
3937 "\t\t -t secs: delay between warning and kill signal.\n"
3938 "\t\t ** the \"time\" argument is mandatory! (try \"now\") **\n");
3939- exit(1);
3940+ exit(1);
3941 }
3942
3943+
3944+void alrm_handler(int sig)
3945+{
3946+ got_alrm = sig;
3947+}
3948+
3949+
3950 /*
3951- * Tell everyone the system is going down in 'mins' minutes.
3952+ * Set environment variables in the init process.
3953 */
3954-void warn(mins)
3955-int mins;
3956+int init_setenv(char *name, char *value)
3957 {
3958- char buf[MESSAGELEN + sizeof(newstate)];
3959- int len;
3960+ struct init_request request;
3961+ struct sigaction sa;
3962+ int fd;
3963+ int nl, vl;
3964
3965- buf[0] = 0;
3966- strncat(buf, message, sizeof(buf) - 1);
3967- len = strlen(buf);
3968+ memset(&request, 0, sizeof(request));
3969+ request.magic = INIT_MAGIC;
3970+ request.cmd = INIT_CMD_SETENV;
3971+ nl = strlen(name);
3972+ vl = value ? strlen(value) : 0;
3973
3974- if (mins == 0)
3975- snprintf(buf + len, sizeof(buf) - len,
3976- "\rThe system is going down %s NOW!\r\n",
3977- newstate);
3978- else
3979- snprintf(buf + len, sizeof(buf) - len,
3980- "\rThe system is going DOWN %s in %d minute%s!\r\n",
3981- newstate, mins, mins == 1 ? "" : "s");
3982- wall(buf, 1, 0);
3983+ if (nl + vl + 3 >= sizeof(request.i.data))
3984+ return -1;
3985+
3986+ memcpy(request.i.data, name, nl);
3987+ if (value) {
3988+ request.i.data[nl] = '=';
3989+ memcpy(request.i.data + nl + 1, value, vl);
3990+ }
3991+
3992+ /*
3993+ * Open the fifo and write the command.
3994+ * Make sure we don't hang on opening /dev/initctl
3995+ */
3996+ memset(&sa, 0, sizeof(sa));
3997+ sa.sa_handler = alrm_handler;
3998+ sigaction(SIGALRM, &sa, NULL);
3999+ got_alrm = 0;
4000+ alarm(3);
4001+ if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0 &&
4002+ write(fd, &request, sizeof(request)) == sizeof(request)) {
4003+ close(fd);
4004+ alarm(0);
4005+ return 0;
4006+ }
4007+
4008+ fprintf(stderr, "shutdown: ");
4009+ if (got_alrm) {
4010+ fprintf(stderr, "timeout opening/writing control channel %s\n",
4011+ INIT_FIFO);
4012+ } else {
4013+ perror(INIT_FIFO);
4014+ }
4015+ return -1;
4016 }
4017
4018+
4019 /*
4020- * Create the /etc/nologin file.
4021+ * Tell everyone the system is going down in 'mins' minutes.
4022+ */
4023+void warn(int mins)
4024+{
4025+ char buf[MESSAGELEN + sizeof(newstate)];
4026+ int len;
4027+
4028+ buf[0] = 0;
4029+ strncat(buf, message, sizeof(buf) - 1);
4030+ len = strlen(buf);
4031+
4032+ if (mins == 0)
4033+ snprintf(buf + len, sizeof(buf) - len,
4034+ "\rThe system is going down %s NOW!\r\n",
4035+ newstate);
4036+ else
4037+ snprintf(buf + len, sizeof(buf) - len,
4038+ "\rThe system is going DOWN %s in %d minute%s!\r\n",
4039+ newstate, mins, mins == 1 ? "" : "s");
4040+ wall(buf, 1, 0);
4041+}
4042+
4043+/*
4044+ * Create the /etc/nologin file.
4045 */
4046 void donologin(int min)
4047 {
4048- FILE *fp;
4049- time_t t;
4050+ FILE *fp;
4051+ time_t t;
4052
4053- time(&t);
4054- t += 60 * min;
4055+ time(&t);
4056+ t += 60 * min;
4057
4058- unlink(NOLOGIN);
4059- if ((fp = fopen(NOLOGIN, "w")) != NULL) {
4060- fprintf(fp, "\rThe system is going down on %s\r\n", ctime(&t));
4061- if (message[0]) fputs(message, fp);
4062- fclose(fp);
4063- }
4064+ if ((fp = fopen(NOLOGIN, "w")) != NULL) {
4065+ fprintf(fp, "\rThe system is going down on %s\r\n", ctime(&t));
4066+ if (message[0]) fputs(message, fp);
4067+ fclose(fp);
4068+ }
4069 }
4070
4071 /*
4072@@ -202,131 +264,146 @@
4073 return 0;
4074 }
4075
4076-/* Kill all processes, call /etc/init.d/halt (if present) */
4077+/*
4078+ * Kill all processes, call /etc/init.d/halt (if present)
4079+ */
4080 void fastdown()
4081 {
4082- int do_halt = (down_level[0] == '0');
4083- int i;
4084+ int do_halt = (down_level[0] == '0');
4085+ int i;
4086 #if 0
4087- char cmd[128];
4088- char *script;
4089+ char cmd[128];
4090+ char *script;
4091
4092- /* Currently, the halt script is either init.d/halt OR rc.d/rc.0,
4093- * likewise for the reboot script. Test for the presence
4094- * of either.
4095- */
4096- if (do_halt) {
4097- if (access(HALTSCRIPT1, X_OK) == 0)
4098- script = HALTSCRIPT1;
4099- else
4100- script = HALTSCRIPT2;
4101- } else {
4102- if (access(REBOOTSCRIPT1, X_OK) == 0)
4103- script = REBOOTSCRIPT1;
4104- else
4105- script = REBOOTSCRIPT2;
4106- }
4107+ /*
4108+ * Currently, the halt script is either init.d/halt OR rc.d/rc.0,
4109+ * likewise for the reboot script. Test for the presence
4110+ * of either.
4111+ */
4112+ if (do_halt) {
4113+ if (access(HALTSCRIPT1, X_OK) == 0)
4114+ script = HALTSCRIPT1;
4115+ else
4116+ script = HALTSCRIPT2;
4117+ } else {
4118+ if (access(REBOOTSCRIPT1, X_OK) == 0)
4119+ script = REBOOTSCRIPT1;
4120+ else
4121+ script = REBOOTSCRIPT2;
4122+ }
4123 #endif
4124
4125- /* First close all files. */
4126- for(i = 0; i < 3; i++)
4127- if (!isatty(i)) {
4128- close(i);
4129- open("/dev/null", O_RDWR);
4130- }
4131- for(i = 3; i < 20; i++) close(i);
4132- close(255);
4133+ /* First close all files. */
4134+ for(i = 0; i < 3; i++)
4135+ if (!isatty(i)) {
4136+ close(i);
4137+ open("/dev/null", O_RDWR);
4138+ }
4139+ for(i = 3; i < 20; i++) close(i);
4140+ close(255);
4141
4142- /* First idle init. */
4143- if (kill(1, SIGTSTP) < 0) {
4144- fprintf(stderr, "shutdown: can't idle init.\r\n");
4145- exit(1);
4146- }
4147+ /* First idle init. */
4148+ if (kill(1, SIGTSTP) < 0) {
4149+ fprintf(stderr, "shutdown: can't idle init.\r\n");
4150+ exit(1);
4151+ }
4152
4153- /* Kill all processes. */
4154- fprintf(stderr, "shutdown: sending all processes the TERM signal...\r\n");
4155- (void) kill(-1, SIGTERM);
4156- if (sltime)
4157- sleep(atoi(sltime));
4158- else
4159- sleep(3);
4160- fprintf(stderr, "shutdown: sending all processes the KILL signal.\r\n");
4161- (void) kill(-1, SIGKILL);
4162+ /* Kill all processes. */
4163+ fprintf(stderr, "shutdown: sending all processes the TERM signal...\r\n");
4164+ kill(-1, SIGTERM);
4165+ sleep(sltime ? atoi(sltime) : 3);
4166+ fprintf(stderr, "shutdown: sending all processes the KILL signal.\r\n");
4167+ (void) kill(-1, SIGKILL);
4168
4169 #if 0
4170- /* See if we can run /etc/init.d/halt */
4171- if (access(script, X_OK) == 0) {
4172- spawn(1, cmd, "fast", NULL);
4173- fprintf(stderr, "shutdown: %s returned - falling back on default routines\r\n", script);
4174- }
4175+ /* See if we can run /etc/init.d/halt */
4176+ if (access(script, X_OK) == 0) {
4177+ spawn(1, cmd, "fast", NULL);
4178+ fprintf(stderr, "shutdown: %s returned - falling back "
4179+ "on default routines\r\n", script);
4180+ }
4181 #endif
4182
4183- /* script failed or not present: do it ourself. */
4184- sleep(1); /* Give init the chance to collect zombies. */
4185+ /* script failed or not present: do it ourself. */
4186+ sleep(1); /* Give init the chance to collect zombies. */
4187
4188- /* Record the fact that we're going down */
4189- write_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");
4190+ /* Record the fact that we're going down */
4191+ write_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");
4192
4193- /* This is for those who have quota installed. */
4194- spawn(1, "accton", NULL);
4195- spawn(1, "quotaoff", "-a", NULL);
4196+ /* This is for those who have quota installed. */
4197+ spawn(1, "accton", NULL);
4198+ spawn(1, "quotaoff", "-a", NULL);
4199
4200- sync();
4201- fprintf(stderr, "shutdown: turning off swap\r\n");
4202- spawn(0, "swapoff", "-a", NULL);
4203- fprintf(stderr, "shutdown: unmounting all file systems\r\n");
4204- spawn(0, "umount", "-a", NULL);
4205+ sync();
4206+ fprintf(stderr, "shutdown: turning off swap\r\n");
4207+ spawn(0, "swapoff", "-a", NULL);
4208+ fprintf(stderr, "shutdown: unmounting all file systems\r\n");
4209+ spawn(0, "umount", "-a", NULL);
4210
4211- /* We're done, halt or reboot now. */
4212- if (do_halt) {
4213- fprintf(stderr, "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n");
4214- init_reboot(BMAGIC_HALT);
4215+ /* We're done, halt or reboot now. */
4216+ if (do_halt) {
4217+ fprintf(stderr, "The system is halted. Press CTRL-ALT-DEL "
4218+ "or turn off power\r\n");
4219+ init_reboot(BMAGIC_HALT);
4220+ exit(0);
4221+ }
4222+
4223+ fprintf(stderr, "Please stand by while rebooting the system.\r\n");
4224+ init_reboot(BMAGIC_REBOOT);
4225 exit(0);
4226- }
4227- fprintf(stderr, "Please stand by while rebooting the system.\r\n");
4228- init_reboot(BMAGIC_REBOOT);
4229- exit(0);
4230 }
4231
4232 /*
4233- * Go to runlevel 0, 1 or 6.
4234+ * Go to runlevel 0, 1 or 6.
4235 */
4236-void shutdown()
4237+void shutdown(char *halttype)
4238 {
4239- char *args[8];
4240- int argp = 0;
4241+ char *args[8];
4242+ int argp = 0;
4243+ int do_halt = (down_level[0] == '0');
4244
4245- /* Warn for the last time (hehe) */
4246- warn(0);
4247- if (dontshut) {
4248- hardsleep(1);
4249- stopit();
4250- }
4251+ /* Warn for the last time */
4252+ warn(0);
4253+ if (dontshut) {
4254+ hardsleep(1);
4255+ stopit(0);
4256+ }
4257+ openlog("shutdown", LOG_PID, LOG_USER);
4258+ if (do_halt)
4259+ syslog(LOG_NOTICE, "shutting down for system halt");
4260+ else
4261+ syslog(LOG_NOTICE, "shutting down for system reboot");
4262+ closelog();
4263
4264- /* See if we have to do it ourself. */
4265- if (doself) fastdown();
4266+ /* See if we have to do it ourself. */
4267+ if (doself) fastdown();
4268
4269- /* Create the arguments for init. */
4270- args[argp++] = INIT;
4271- if (sltime) {
4272- args[argp++] = "-t";
4273- args[argp++] = sltime;
4274- }
4275- args[argp++] = down_level;
4276- args[argp] = (char *)NULL;
4277+ /* Create the arguments for init. */
4278+ args[argp++] = INIT;
4279+ if (sltime) {
4280+ args[argp++] = "-t";
4281+ args[argp++] = sltime;
4282+ }
4283+ args[argp++] = down_level;
4284+ args[argp] = (char *)NULL;
4285
4286- unlink(SDPID);
4287- unlink(NOLOGIN);
4288+ unlink(SDPID);
4289+ unlink(NOLOGIN);
4290
4291- /* Now execute init to change runlevel. */
4292- sync();
4293- execv(INIT, args);
4294+ /* Now execute init to change runlevel. */
4295+ sync();
4296+ init_setenv("INIT_HALT", halttype);
4297+ execv(INIT, args);
4298
4299- /* Oops - failed. */
4300- fprintf(stderr, "\rshutdown: cannot execute %s\r\n", INIT);
4301- unlink(FASTBOOT);
4302- unlink(FORCEFSCK);
4303- exit(1);
4304+ /* Oops - failed. */
4305+ fprintf(stderr, "\rshutdown: cannot execute %s\r\n", INIT);
4306+ unlink(FASTBOOT);
4307+ unlink(FORCEFSCK);
4308+ init_setenv("INIT_HALT", NULL);
4309+ openlog("shutdown", LOG_PID, LOG_USER);
4310+ syslog(LOG_NOTICE, "shutdown failed");
4311+ closelog();
4312+ exit(1);
4313 }
4314
4315 /*
4316@@ -349,274 +426,287 @@
4317 }
4318
4319 /*
4320- * Main program.
4321- * Process the options and do the final countdown.
4322+ * Main program.
4323+ * Process the options and do the final countdown.
4324 */
4325-int main(argc, argv)
4326-int argc;
4327-char **argv;
4328+int main(int argc, char **argv)
4329 {
4330- extern int getopt();
4331- extern int optind;
4332- int c, i, wt, hours, mins;
4333- struct tm *lt;
4334- time_t t;
4335- char *sp;
4336- char *when = NULL;
4337- int didnolog = 0;
4338- int cancel = 0;
4339- int useacl = 0;
4340- int pid = 0;
4341- uid_t realuid;
4342- FILE *fp;
4343- char *downusers[32];
4344- char buf[128];
4345- char term[UT_LINESIZE + 6];
4346- struct stat st;
4347- struct utmp *ut;
4348- int user_ok = 0;
4349- struct sigaction sa;
4350+ FILE *fp;
4351+ extern int getopt();
4352+ extern int optind;
4353+ struct sigaction sa;
4354+ struct tm *lt;
4355+ struct stat st;
4356+ struct utmp *ut;
4357+ time_t t;
4358+ uid_t realuid;
4359+ char *halttype;
4360+ char *downusers[32];
4361+ char buf[128];
4362+ char term[UT_LINESIZE + 6];
4363+ char *sp;
4364+ char *when = NULL;
4365+ int c, i, wt;
4366+ int hours, mins;
4367+ int didnolog = 0;
4368+ int cancel = 0;
4369+ int useacl = 0;
4370+ int pid = 0;
4371+ int user_ok = 0;
4372
4373- /* We can be installed setuid root (executable for a special group) */
4374- realuid = getuid();
4375- setuid(geteuid());
4376+ /* We can be installed setuid root (executable for a special group) */
4377+ realuid = getuid();
4378+ setuid(geteuid());
4379
4380- if (getuid() != 0) {
4381- fprintf(stderr, "shutdown: you must be root to do that!\n");
4382- exit(1);
4383- }
4384- strcpy(down_level, "1");
4385+ if (getuid() != 0) {
4386+ fprintf(stderr, "shutdown: you must be root to do that!\n");
4387+ exit(1);
4388+ }
4389+ strcpy(down_level, "1");
4390+ halttype = NULL;
4391
4392- /* Process the options. */
4393- while((c = getopt(argc, argv, "acqkrhnfFyt:g:i:")) != EOF) {
4394- switch(c) {
4395- case 'a': /* Access control. */
4396- useacl = 1;
4397- break;
4398- case 'c': /* Cancel an already running shutdown. */
4399- cancel = 1;
4400- break;
4401- case 'k': /* Don't really shutdown, only warn.*/
4402- dontshut = 1;
4403- break;
4404- case 'r': /* Automatic reboot */
4405- down_level[0] = '6';
4406- break;
4407- case 'h': /* Halt after shutdown */
4408- down_level[0] = '0';
4409- break;
4410- case 'f': /* Don't perform fsck after next boot */
4411- fastboot = 1;
4412- break;
4413- case 'F': /* Force fsck after next boot */
4414- forcefsck = 1;
4415- break;
4416- case 'n': /* Don't switch runlevels. */
4417- doself = 1;
4418- break;
4419- case 't': /* Delay between TERM and KILL */
4420- sltime = optarg;
4421- break;
4422- case 'y': /* Ignored for sysV compatibility */
4423- break;
4424- case 'g': /* sysv style to specify time. */
4425- when = optarg;
4426- down_level[0] = '0';
4427- break;
4428- case 'i': /* Level to go to. */
4429- if (!strchr("0156aAbBcCsS", optarg[0])) {
4430- fprintf(stderr, "shutdown: `%s': bad runlevel\n",
4431+ /* Process the options. */
4432+ while((c = getopt(argc, argv, "HPacqkrhnfFyt:g:i:")) != EOF) {
4433+ switch(c) {
4434+ case 'H':
4435+ halttype = "HALT";
4436+ break;
4437+ case 'P':
4438+ halttype = "POWERDOWN";
4439+ break;
4440+ case 'a': /* Access control. */
4441+ useacl = 1;
4442+ break;
4443+ case 'c': /* Cancel an already running shutdown. */
4444+ cancel = 1;
4445+ break;
4446+ case 'k': /* Don't really shutdown, only warn.*/
4447+ dontshut = 1;
4448+ break;
4449+ case 'r': /* Automatic reboot */
4450+ down_level[0] = '6';
4451+ break;
4452+ case 'h': /* Halt after shutdown */
4453+ down_level[0] = '0';
4454+ break;
4455+ case 'f': /* Don't perform fsck after next boot */
4456+ fastboot = 1;
4457+ break;
4458+ case 'F': /* Force fsck after next boot */
4459+ forcefsck = 1;
4460+ break;
4461+ case 'n': /* Don't switch runlevels. */
4462+ doself = 1;
4463+ break;
4464+ case 't': /* Delay between TERM and KILL */
4465+ sltime = optarg;
4466+ break;
4467+ case 'y': /* Ignored for sysV compatibility */
4468+ break;
4469+ case 'g': /* sysv style to specify time. */
4470+ when = optarg;
4471+ break;
4472+ case 'i': /* Level to go to. */
4473+ if (!strchr("0156aAbBcCsS", optarg[0])) {
4474+ fprintf(stderr,
4475+ "shutdown: `%s': bad runlevel\n",
4476 optarg);
4477- exit(1);
4478- }
4479- down_level[0] = optarg[0];
4480- break;
4481- default:
4482- usage();
4483- break;
4484- }
4485- }
4486+ exit(1);
4487+ }
4488+ down_level[0] = optarg[0];
4489+ break;
4490+ default:
4491+ usage();
4492+ break;
4493+ }
4494+ }
4495
4496- /* Do we need to use the shutdown.allow file ? */
4497- if (useacl && (fp = fopen(SDALLOW, "r")) != NULL) {
4498+ /* Do we need to use the shutdown.allow file ? */
4499+ if (useacl && (fp = fopen(SDALLOW, "r")) != NULL) {
4500
4501- /* Read /etc/shutdown.allow. */
4502- i = 0;
4503- while(fgets(buf, 128, fp)) {
4504- if (buf[0] == '#' || buf[0] == '\n') continue;
4505- if (i > 31) continue;
4506- for(sp = buf; *sp; sp++) if (*sp == '\n') *sp = 0;
4507- downusers[i++] = strdup(buf);
4508- }
4509- if (i < 32) downusers[i] = 0;
4510- fclose(fp);
4511+ /* Read /etc/shutdown.allow. */
4512+ i = 0;
4513+ while(fgets(buf, 128, fp)) {
4514+ if (buf[0] == '#' || buf[0] == '\n') continue;
4515+ if (i > 31) continue;
4516+ for(sp = buf; *sp; sp++) if (*sp == '\n') *sp = 0;
4517+ downusers[i++] = strdup(buf);
4518+ }
4519+ if (i < 32) downusers[i] = 0;
4520+ fclose(fp);
4521
4522- /* Now walk through /var/run/utmp to find logged in users. */
4523- while(!user_ok && (ut = getutent()) != NULL) {
4524+ /* Now walk through /var/run/utmp to find logged in users. */
4525+ while(!user_ok && (ut = getutent()) != NULL) {
4526
4527- /* See if this is a user process on a VC. */
4528- if (ut->ut_type != USER_PROCESS) continue;
4529- sprintf(term, "/dev/%.*s", UT_LINESIZE, ut->ut_line);
4530- if (stat(term, &st) < 0) continue;
4531+ /* See if this is a user process on a VC. */
4532+ if (ut->ut_type != USER_PROCESS) continue;
4533+ sprintf(term, "/dev/%.*s", UT_LINESIZE, ut->ut_line);
4534+ if (stat(term, &st) < 0) continue;
4535 #ifdef major /* glibc */
4536- if (major(st.st_rdev) != 4 ||
4537- minor(st.st_rdev) > 63) continue;
4538+ if (major(st.st_rdev) != 4 ||
4539+ minor(st.st_rdev) > 63) continue;
4540 #else
4541- if ((st.st_rdev & 0xFFC0) != 0x0400) continue;
4542+ if ((st.st_rdev & 0xFFC0) != 0x0400) continue;
4543 #endif
4544- /* Root is always OK. */
4545- if (strcmp(ut->ut_user, "root") == 0) {
4546- user_ok++;
4547- break;
4548- }
4549-
4550- /* See if this is an allowed user. */
4551- for(i = 0; i < 32 && downusers[i]; i++)
4552- if (!strncmp(downusers[i], ut->ut_user, UT_NAMESIZE)) {
4553+ /* Root is always OK. */
4554+ if (strcmp(ut->ut_user, "root") == 0) {
4555 user_ok++;
4556 break;
4557 }
4558- }
4559- endutent();
4560
4561- /* See if user was allowed. */
4562- if (!user_ok) {
4563- if ((fp = fopen(CONSOLE, "w")) != NULL) {
4564- fprintf(fp, "\rshutdown: no authorized users logged in.\r\n");
4565- fclose(fp);
4566+ /* See if this is an allowed user. */
4567+ for(i = 0; i < 32 && downusers[i]; i++)
4568+ if (!strncmp(downusers[i], ut->ut_user,
4569+ UT_NAMESIZE)) {
4570+ user_ok++;
4571+ break;
4572+ }
4573 }
4574- exit(1);
4575- }
4576- }
4577+ endutent();
4578
4579- /* Read pid of running shutdown from a file */
4580- if ((fp = fopen(SDPID, "r")) != NULL) {
4581- fscanf(fp, "%d", &pid);
4582- fclose(fp);
4583- }
4584+ /* See if user was allowed. */
4585+ if (!user_ok) {
4586+ if ((fp = fopen(CONSOLE, "w")) != NULL) {
4587+ fprintf(fp, "\rshutdown: no authorized users "
4588+ "logged in.\r\n");
4589+ fclose(fp);
4590+ }
4591+ exit(1);
4592+ }
4593+ }
4594
4595- /* Read remaining words, skip time if needed. */
4596- message[0] = 0;
4597- for(c = optind + (!cancel && !when); c < argc; c++) {
4598- if (strlen(message) + strlen(argv[c]) + 4 > MESSAGELEN)
4599- break;
4600- strcat(message, argv[c]);
4601- strcat(message, " ");
4602- }
4603- if (message[0]) strcat(message, "\r\n");
4604+ /* Read pid of running shutdown from a file */
4605+ if ((fp = fopen(SDPID, "r")) != NULL) {
4606+ fscanf(fp, "%d", &pid);
4607+ fclose(fp);
4608+ }
4609
4610- /* See if we want to run or cancel. */
4611- if (cancel) {
4612- if (pid <= 0) {
4613- fprintf(stderr, "shutdown: cannot find pid of running shutdown.\n");
4614- exit(1);
4615+ /* Read remaining words, skip time if needed. */
4616+ message[0] = 0;
4617+ for(c = optind + (!cancel && !when); c < argc; c++) {
4618+ if (strlen(message) + strlen(argv[c]) + 4 > MESSAGELEN)
4619+ break;
4620+ strcat(message, argv[c]);
4621+ strcat(message, " ");
4622 }
4623- if (kill(pid, SIGINT) < 0) {
4624- fprintf(stderr, "shutdown: not running.\n");
4625- exit(1);
4626+ if (message[0]) strcat(message, "\r\n");
4627+
4628+ /* See if we want to run or cancel. */
4629+ if (cancel) {
4630+ if (pid <= 0) {
4631+ fprintf(stderr, "shutdown: cannot find pid "
4632+ "of running shutdown.\n");
4633+ exit(1);
4634+ }
4635+ init_setenv("INIT_HALT", NULL);
4636+ if (kill(pid, SIGINT) < 0) {
4637+ fprintf(stderr, "shutdown: not running.\n");
4638+ exit(1);
4639+ }
4640+ if (message[0]) wall(message, 1, 0);
4641+ exit(0);
4642 }
4643- if (message[0]) wall(message, 1, 0);
4644- exit(0);
4645- }
4646
4647- /* Check syntax. */
4648- if (when == NULL) {
4649- if (optind == argc) usage();
4650- when = argv[optind++];
4651- }
4652+ /* Check syntax. */
4653+ if (when == NULL) {
4654+ if (optind == argc) usage();
4655+ when = argv[optind++];
4656+ }
4657
4658- /* See if we are already running. */
4659- if (pid > 0 && kill(pid, 0) == 0) {
4660- fprintf(stderr, "\rshutdown: already running.\r\n");
4661- exit(1);
4662- }
4663+ /* See if we are already running. */
4664+ if (pid > 0 && kill(pid, 0) == 0) {
4665+ fprintf(stderr, "\rshutdown: already running.\r\n");
4666+ exit(1);
4667+ }
4668
4669- /* Extra check. */
4670- if (doself && down_level[0] != '0' && down_level[0] != '6') {
4671- fprintf(stderr, "shutdown: can use \"-n\" for halt or reboot only.\r\n");
4672- exit(1);
4673- }
4674+ /* Extra check. */
4675+ if (doself && down_level[0] != '0' && down_level[0] != '6') {
4676+ fprintf(stderr,
4677+ "shutdown: can use \"-n\" for halt or reboot only.\r\n");
4678+ exit(1);
4679+ }
4680
4681- /* Tell users what we're gonna do. */
4682- switch(down_level[0]) {
4683- case '0':
4684- strcpy(newstate, "for system halt");
4685- break;
4686- case '6':
4687- strcpy(newstate, "for reboot");
4688- break;
4689- case '1':
4690- strcpy(newstate, "to maintenance mode");
4691- break;
4692- default:
4693- sprintf(newstate, "to runlevel %s", down_level);
4694- break;
4695- }
4696+ /* Tell users what we're gonna do. */
4697+ switch(down_level[0]) {
4698+ case '0':
4699+ strcpy(newstate, "for system halt");
4700+ break;
4701+ case '6':
4702+ strcpy(newstate, "for reboot");
4703+ break;
4704+ case '1':
4705+ strcpy(newstate, "to maintenance mode");
4706+ break;
4707+ default:
4708+ sprintf(newstate, "to runlevel %s", down_level);
4709+ break;
4710+ }
4711
4712- /* Create a new PID file. */
4713- unlink(SDPID);
4714- umask(022);
4715- if ((fp = fopen(SDPID, "w")) != NULL) {
4716- fprintf(fp, "%d\n", getpid());
4717- fclose(fp);
4718- } else if (errno != EROFS)
4719- fprintf(stderr, "shutdown: warning: cannot open %s\n", SDPID);
4720+ /* Create a new PID file. */
4721+ unlink(SDPID);
4722+ umask(022);
4723+ if ((fp = fopen(SDPID, "w")) != NULL) {
4724+ fprintf(fp, "%d\n", getpid());
4725+ fclose(fp);
4726+ } else if (errno != EROFS)
4727+ fprintf(stderr, "shutdown: warning: cannot open %s\n", SDPID);
4728
4729- /*
4730- * Catch some common signals.
4731- */
4732- signal(SIGQUIT, SIG_IGN);
4733- signal(SIGCHLD, SIG_IGN);
4734- signal(SIGHUP, SIG_IGN);
4735- signal(SIGTSTP, SIG_IGN);
4736- signal(SIGTTIN, SIG_IGN);
4737- signal(SIGTTOU, SIG_IGN);
4738+ /*
4739+ * Catch some common signals.
4740+ */
4741+ signal(SIGQUIT, SIG_IGN);
4742+ signal(SIGCHLD, SIG_IGN);
4743+ signal(SIGHUP, SIG_IGN);
4744+ signal(SIGTSTP, SIG_IGN);
4745+ signal(SIGTTIN, SIG_IGN);
4746+ signal(SIGTTOU, SIG_IGN);
4747
4748- sa.sa_handler = stopit;
4749- sa.sa_flags = SA_RESTART;
4750- sigaction(SIGINT, &sa, NULL);
4751+ memset(&sa, 0, sizeof(sa));
4752+ sa.sa_handler = stopit;
4753+ sigaction(SIGINT, &sa, NULL);
4754
4755- /* Go to the root directory */
4756- chdir("/");
4757- if (fastboot) close(open(FASTBOOT, O_CREAT | O_RDWR, 0644));
4758- if (forcefsck) close(open(FORCEFSCK, O_CREAT | O_RDWR, 0644));
4759+ /* Go to the root directory */
4760+ chdir("/");
4761+ if (fastboot) close(open(FASTBOOT, O_CREAT | O_RDWR, 0644));
4762+ if (forcefsck) close(open(FORCEFSCK, O_CREAT | O_RDWR, 0644));
4763
4764- /* Alias now and take care of old '+mins' notation. */
4765- if (!strcmp(when, "now")) strcpy(when, "0");
4766- if (when[0] == '+') when++;
4767+ /* Alias now and take care of old '+mins' notation. */
4768+ if (!strcmp(when, "now")) strcpy(when, "0");
4769+ if (when[0] == '+') when++;
4770
4771- /* Decode shutdown time. */
4772- for (sp = when; *sp; sp++) {
4773- if (*sp != ':' && (*sp < '0' || *sp > '9'))
4774- usage();
4775- }
4776- if (strchr(when, ':') == NULL) {
4777- /* Time in minutes. */
4778- wt = atoi(when);
4779- if (wt == 0 && when[0] != '0') usage();
4780- } else {
4781- /* Time in hh:mm format. */
4782- if (sscanf(when, "%d:%2d", &hours, &mins) != 2) usage();
4783- if (hours > 23 || mins > 59) usage();
4784- time(&t);
4785- lt = localtime(&t);
4786- wt = (60*hours + mins) - (60*lt->tm_hour + lt->tm_min);
4787- if (wt < 0) wt += 1440;
4788- }
4789- /* Shutdown NOW if time == 0 */
4790- if (wt == 0) shutdown();
4791+ /* Decode shutdown time. */
4792+ for (sp = when; *sp; sp++) {
4793+ if (*sp != ':' && (*sp < '0' || *sp > '9'))
4794+ usage();
4795+ }
4796+ if (strchr(when, ':') == NULL) {
4797+ /* Time in minutes. */
4798+ wt = atoi(when);
4799+ if (wt == 0 && when[0] != '0') usage();
4800+ } else {
4801+ /* Time in hh:mm format. */
4802+ if (sscanf(when, "%d:%2d", &hours, &mins) != 2) usage();
4803+ if (hours > 23 || mins > 59) usage();
4804+ time(&t);
4805+ lt = localtime(&t);
4806+ wt = (60*hours + mins) - (60*lt->tm_hour + lt->tm_min);
4807+ if (wt < 0) wt += 1440;
4808+ }
4809+ /* Shutdown NOW if time == 0 */
4810+ if (wt == 0) shutdown(halttype);
4811
4812- /* Give warnings on regular intervals and finally shutdown. */
4813- if (wt < 15 && !needwarning(wt)) warn(wt);
4814- while(wt) {
4815- if (wt <= 5 && !didnolog) {
4816- donologin(wt);
4817- didnolog++;
4818+ /* Give warnings on regular intervals and finally shutdown. */
4819+ if (wt < 15 && !needwarning(wt)) warn(wt);
4820+ while(wt) {
4821+ if (wt <= 5 && !didnolog) {
4822+ donologin(wt);
4823+ didnolog++;
4824+ }
4825+ if (needwarning(wt)) warn(wt);
4826+ hardsleep(60);
4827+ wt--;
4828 }
4829- if (needwarning(wt)) warn(wt);
4830- hardsleep(60);
4831- wt--;
4832- }
4833- shutdown();
4834- return(0); /* Never happens */
4835+ shutdown(halttype);
4836+
4837+ return 0; /* Never happens */
4838 }
4839Binary files sysvinit-2.85/src/shutdown.o and sysvinit-2.86/src/shutdown.o differ
4840Binary files sysvinit-2.85/src/sulogin and sysvinit-2.86/src/sulogin differ
4841diff -urNd -urNd sysvinit-2.85/src/sulogin.c sysvinit-2.86/src/sulogin.c
4842--- sysvinit-2.85/src/sulogin.c 2003-04-14 04:53:49.000000000 -0500
4843+++ sysvinit-2.86/src/sulogin.c 2004-07-30 06:40:28.000000000 -0500
4844@@ -8,7 +8,7 @@
4845 * encrypted root password is "x" the shadow
4846 * password will be used.
4847 *
4848- * Version: @(#)sulogin 2.85 14-Apr-2003 miquels@cistron.nl
4849+ * Version: @(#)sulogin 2.85-3 23-Apr-2003 miquels@cistron.nl
4850 *
4851 */
4852
4853@@ -35,11 +35,15 @@
4854 #define F_SHADOW "/etc/shadow"
4855 #define BINSH "/bin/sh"
4856
4857-char *Version = "@(#)sulogin 2.85 14-Apr-2003 miquels@cistron.nl";
4858+char *Version = "@(#)sulogin 2.85-3 23-Apr-2003 miquels@cistron.nl";
4859
4860 int timeout = 0;
4861 int profile = 0;
4862
4863+#ifndef IUCLC
4864+# define IUCLC 0
4865+#endif
4866+
4867 #if 0
4868 /*
4869 * Fix the tty modes and set reasonable defaults.
4870@@ -252,7 +256,7 @@
4871 printf("Give root password for maintenance\n");
4872 else
4873 printf("Press enter for maintenance\n");
4874- printf("(or type Control-D for normal startup): ");
4875+ printf("(or type Control-D to continue): ");
4876 fflush(stdout);
4877
4878 tcgetattr(0, &old);
4879Binary files sysvinit-2.85/src/sulogin.o and sysvinit-2.86/src/sulogin.o differ
4880Binary files sysvinit-2.85/src/utmp.o and sysvinit-2.86/src/utmp.o differ