1 diff -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
5 -Sysvinit is Copyright (C) 1991-2003 Miquel van Smoorenburg
6 +Sysvinit is Copyright (C) 1991-2004 Miquel van Smoorenburg
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
10 diff -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
14 +sysvinit (2.86) cistron; urgency=low
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)
38 + -- Miquel van Smoorenburg <miquels@cistron.nl> Fri, 30 Jul 2004 14:14:58 +0200
40 sysvinit (2.85) cistron; urgency=low
42 * Add IPv6 support in last(1)
43 diff -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
48 - README for the System V style init, version 2.85
49 + README for the System V style init, version 2.86
51 init, shutdown, halt, reboot, wall, last, mesg, runlevel,
52 killall5, pidof, sulogin.
53 diff -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
58 bootlogd: a way to capture all console output during bootup
59 - in a logfile. ** PROOF OF CONCEPT IMPLEMENTATION **
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
73 diff -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
78 Title: sysvinit and utilities
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)
85 diff -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
90 +Title: sysvinit and utilities
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
101 +Keywords: init shutdown halt reboot
103 diff -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
107 +.TH BOOTLOGD 8 "Jul 21, 2003" "" "Linux System Administrator's Manual"
109 +bootlogd \- record boot messages
115 +.RB [ " -l logfile " ]
116 +.RB [ " -p pidfile " ]
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.
123 +Do not fork and run in the background.
125 +If there is an existing logfile called \fIlogfile\fP rename it to
126 +\fIlogfile~\fP unless \fIlogfile~\fP already exists.
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.
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.
143 +Miquel van Smoorenburg, miquels@cistron.nl
146 diff -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
152 -.TH INIT 8 "18 April 2003" "" "Linux System Administrator's Manual"
153 +.TH INIT 8 "29 Jul 2004" "" "Linux System Administrator's Manual"
159 \fBInit\fP sets the following environment variables for all its children:
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.
166 diff -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
170 -.TH INITSCRIPT 5 "December 24, 1999" "" "Linux System Administrator's Manual"
171 +.TH INITSCRIPT 5 "July 10, 2003" "" "Linux System Administrator's Manual"
173 initscript \- script that executes inittab commands.
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.
188 diff -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
192 -.TH KILLALL5 8 "27 May 1997" "" "Linux System Administrator's Manual"
193 +.TH KILLALL5 8 "04 Nov 2003" "" "Linux System Administrator's Manual"
195 killall5 -- send a signal to all processes.
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.
210 diff -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
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"
222 .RB "[ \-\fBn\fP \fInum\fP ]"
224 .RB "[ \-\fBf\fP \fIfile\fP ]"
225 +.RB "[ \-\fBt\fP \fIYYYYMMDDHHMMSS\fP ]"
230 This is a count telling \fBlast\fP how many lines to show.
231 .IP "\fB\-n\fP \fInum\fP"
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
239 Suppresses the display of the hostname field.
241 diff -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
245 If no option is given, \fBmesg\fP prints out the current access state of your
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".
253 diff -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
257 +.TH MOUNTPOINT 8 "Mar 15, 2004" "" "Linux System Administrator's Manual"
259 +mountpoint \- see if a directory is a mountpoint
264 +.I /path/to/directory
270 +\fBMountpoint\fP checks if the directory is a mountpoint.
274 +Be quiet - don't print anything.
276 +Print major/minor device number of the filesystem on stdout.
278 +Print major/minor device number of the blockdevice on stdout.
280 +Zero if the directory is a mountpoint, non-zero if not.
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.
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.
291 +Miquel van Smoorenburg, miquels@cistron.nl
294 diff -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
300 -.TH SHUTDOWN 8 "Juli 31, 2001" "" "Linux System Administrator's Manual"
301 +.TH SHUTDOWN 8 "November 12, 2003" "" "Linux System Administrator's Manual"
310 +.RB [ \-arkhncfFHP ]
312 .RI [ warning-message ]
318 -Halt after shutdown.
319 +Halt or poweroff after shutdown.
323 +Halt action is to halt or drop into boot monitor on systems that
328 +Halt action is to turn off the power.
334 Note that if \fI/etc/shutdown.allow\fP is not present, the \fB-a\fP
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.
347 diff -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
351 -.TH SULOGIN 8 "11 Sep 2000" "" "Linux System Administrator's Manual"
352 +.TH SULOGIN 8 "04 Nov 2003" "" "Linux System Administrator's Manual"
354 sulogin -- Single-user login
358 (or type Control-D for normal startup):
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).
367 boot: linux -b rw sushell=/sbin/sash
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)
377 +Then, if the \fB-e\fP option was specified,
378 +\fIsulogin\fP examines these files directly to find the root password:
382 /etc/shadow (if present)
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.
388 Miquel van Smoorenburg <miquels@cistron.nl>
390 diff -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
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
402 diff -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
406 # clean cleans up object files
407 # clobber really cleans up
409 -# Version: @(#)Makefile 2.83-3 06-Nov-2001 miquels@cistron.nl
410 +# Version: @(#)Makefile 2.85-13 23-Mar-2004 miquels@cistron.nl
414 -CFLAGS = -Wall -O2 -D_GNU_SOURCE
416 +CFLAGS = -Wall -O2 -fomit-frame-pointer -D_GNU_SOURCE
420 -# For Debian we do not build all programs, otherwise we do.
422 -PROGS = init halt shutdown killall5 runlevel sulogin utmpdump \
425 -PROGS = init halt shutdown killall5 runlevel sulogin last mesg
426 +# For some known distributions we do not build all programs, otherwise we do.
428 +SBIN = init halt shutdown runlevel killall5
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
438 +SBIN += sulogin bootlogd
439 +USRBIN += utmpdump wall
440 +MAN1 += mountpoint.1 wall.1
441 +MAN8 += sulogin.8 bootlogd.8
444 +ifeq ($(DISTRO),Debian)
446 +SBIN += sulogin bootlogd
447 +MAN1 += mountpoint.1
448 +MAN8 += sulogin.8 bootlogd.8
451 +ifeq ($(DISTRO),Owl)
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
463 -# Additional libs for Gnu Libc
464 +# Additional libs for GNU libc.
465 ifneq ($(wildcard /usr/lib/libcrypt.a),)
470 +all: $(BIN) $(SBIN) $(USRBIN)
472 init: init.o init_utmp.o
473 $(CC) $(LDFLAGS) $(STATIC) -o $@ init.o init_utmp.o
476 $(CC) $(LDFLAGS) -o $@ mesg.o
478 +mountpoint: mountpoint.o
479 + $(CC) $(LDFLAGS) -o $@ mountpoint.o
482 $(CC) $(LDFLAGS) -o $@ utmpdump.o
485 $(CC) $(LDFLAGS) -o $@ dowall.o shutdown.o utmp.o
488 - $(CC) $(LDFLAGS) -o $@ bootlogd.o
489 + $(CC) $(LDFLAGS) -o $@ bootlogd.o -lutil
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
495 utmp.o: utmp.c init.h
497 @echo Type \"make clobber\" to really clean up.
501 + rm -f $(BIN) $(SBIN) $(USRBIN)
506 - $(INSTALL) -m 755 halt init killall5 sulogin \
507 - runlevel shutdown $(ROOT)/sbin
508 - # These are not installed by default
510 - $(INSTALL) -m 555 utmpdump wall $(ROOT)/usr/bin
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
523 - $(INSTALL) -m 644 ../man/wall.1 $(ROOT)$(MANDIR)/man1
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/; \
530 + for i in $(SBIN); do \
531 + $(INSTALL) -m 755 $$i $(ROOT)/sbin/; \
533 + for i in $(USRBIN); do \
534 + $(INSTALL) -m 755 $$i $(ROOT)/usr/bin/; \
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; \
544 + $(INSTALL) -m 644 initreq.h $(ROOT)/usr/include/
545 + for i in $(MAN1); do \
546 + $(INSTALL) -m 644 ../man/$$i $(ROOT)$(MANDIR)/man1/; \
548 + for i in $(MAN5); do \
549 + $(INSTALL) -m 644 ../man/$$i $(ROOT)$(MANDIR)/man5/; \
551 + for i in $(MAN8); do \
552 + $(INSTALL) -m 644 ../man/$$i $(ROOT)$(MANDIR)/man8/; \
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
564 Binary files sysvinit-2.85/src/bootlogd and sysvinit-2.86/src/bootlogd differ
565 diff -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
569 * The file is usually located on the /var partition, and
570 * gets written (and fsynced) as soon as possible.
572 - * Version: @(#)bootlogd 2.79 11-Sep-2000 miquels@cistron.nl
573 + * Version: @(#)bootlogd 2.86pre 12-Jan-2004 miquels@cistron.nl
575 * Bugs: Uses openpty(), only available in glibc. Sorry.
577 * This file is part of the sysvinit suite,
578 - * Copyright 1991-2000 Miquel van Smoorenburg.
579 + * Copyright 1991-2004 Miquel van Smoorenburg.
581 * This program is free software; you can redistribute it and/or
582 * modify it under the terms of the GNU General Public License
585 * *NOTE* *NOTE* *NOTE*
586 * This is a PROOF OF CONCEPT IMPLEMENTATION
587 - * I do not recommend using this on production systems.
589 + * I have bigger plans for Debian, but for now
590 + * this has to do ;)
599 -char *Version = "@(#) bootlogd 2.79 11-Sep-2000 MvS";
602 - * Until the kernel knows about TIOCGDEV, use a really ugly
603 - * non-portable (not even between architectures) hack.
606 -# define TIOCTTYGSTRUCT_HACK 1
609 +#include <sys/mount.h>
612 -#define LOGFILE "/var/log/boot.log"
613 +char *Version = "@(#) bootlogd 2.86 03-Jun-2004 miquels@cistron.nl";
615 +#define LOGFILE "/var/log/boot"
618 char *endptr = ringbuf + sizeof(ringbuf);
628 -#ifdef TIOCTTYGSTRUCT_HACK
629 -struct tty_offsets {
633 -#if ((~0UL) == 0xffffffff) /* 32 bits */
648 + * Console devices as listed on the kernel command line and
649 + * the mapping to actual devices in /dev
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 },
665 + * Devices to try as console if not found on kernel command line.
666 + * Tried from left to right (as opposed to kernel cmdline).
668 +char *defcons[] = { "tty0", "hvc0", "ttyS0", "ttySC0", NULL };
674 * Scan /dev and find the device name.
675 * Side-effect: directory is changed to /dev
677 + * FIXME: scan subdirectories for devfs support ?
679 int findtty(char *res, int rlen, dev_t dev)
681 @@ -117,18 +120,88 @@
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));
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");
694 - strcpy(res, ent->d_name);
695 + snprintf(res, rlen, "/dev/%s", ent->d_name);
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.
708 +int findpty(int *master, int *slave, char *name)
715 + if (openpty(master, slave, name, NULL, NULL) >= 0)
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);
735 + if (found < 0) return -1;
737 + if (name) strcpy(name, tty);
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.
745 +int isconsole(char *s, char *res, int rlen)
753 + for (c = consdev; c->cmdline; c++) {
754 + l = strlen(c->cmdline);
755 + if (sl <= l) continue;
757 + if (strncmp(s, c->cmdline, l) != 0 || !isdigit(*p))
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) {
772 * Find out the _real_ console. Assume that stdin is connected to
773 @@ -136,21 +209,18 @@
775 int consolename(char *res, int rlen)
778 -#if TIOCTTYGSTRUCT_HACK
779 - struct utsname uts;
780 - struct tty_offsets *tt;
782 - unsigned short *kdev;
790 + struct stat st, st2;
798 - if (st.st_rdev != 0x0501) {
799 + if (major(st.st_rdev) != 5 || minor(st.st_rdev) != 1) {
801 * Old kernel, can find real device easily.
803 @@ -160,33 +230,78 @@
805 if (ioctl(0, TIOCGDEV, &kdev) == 0)
806 return findtty(res, rlen, (dev_t)kdev);
808 + if (errno != ENOIOCTLCMD) return -1;
813 - * New kernel and new console device - hard to find
814 - * out what device the real console is ..
815 + * Read /proc/cmdline.
817 -#if TIOCTTYGSTRUCT_HACK
818 - if (ioctl(0, TIOCTTYGSTRUCT, buf) != 0) {
819 - perror("bootlogd: TIOCTTYGSTRUCT");
821 + if (stat("/proc", &st2) < 0) {
822 + perror("bootlogd: /proc");
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");
839 + if ((fd = open("/proc/cmdline", O_RDONLY)) < 0) {
840 + perror("bootlogd: /proc/cmdline");
843 + if ((n = read(fd, buf, sizeof(buf) - 1)) >= 0)
846 + perror("bootlogd: /proc/cmdline");
849 + if (didmount) umount("/proc");
851 + if (r < 0) return r;
854 + * OK, so find console= in /proc/cmdline.
855 + * Parse in reverse, opening as we go.
857 + * Valid console devices: ttySC, ttyS, tty, hvc.
863 + if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {
867 + if (strncmp(p, "console=", 8) == 0 &&
868 + isconsole(p + 8, res, rlen)) {
873 - fprintf(stderr, "bootlogd: don't know offsetof"
874 - "(struct tty_struct, device) for kernel %s\n", uts.release);
878 - kdev = (unsigned short *)(&buf[offset]);
879 - dev = (dev_t)(*kdev);
880 - return findtty(res, rlen, dev);
882 + if (r == 0) return r;
886 + * Okay, no console on the command line -
887 + * guess the default console.
889 + for (n = 0; defcons[n]; n++)
890 + if (isconsole(defcons[n], res, rlen))
893 + fprintf(stderr, "bootlogd: cannot deduce real console device\n");
913 @@ -207,24 +326,51 @@
924 + if (line.pos > 0) line.pos--;
931 + line.pos += (line.pos / 8 + 1) * 8;
932 + if (line.pos >= sizeof(line.buf))
933 + line.pos = sizeof(line.buf) - 1;
942 - fprintf(fp, "\\%03o", *ptr);
943 + sprintf(tmp, "\\%03o", *ptr);
949 + tlen = strlen(tmp);
950 + if (tlen && (line.pos + tlen < sizeof(line.buf))) {
951 + memcpy(line.buf + line.pos, tmp, tlen);
955 + fprintf(fp, "%s\n", line.buf);
956 + memset(&line, 0, sizeof(line));
962 + fdatasync(fileno(fp));
965 - fdatasync(fileno(fp));
968 if (outptr >= endptr)
973 +int open_nb(char *buf)
977 + if ((fd = open(buf, O_WRONLY|O_NONBLOCK|O_NOCTTY)) < 0)
979 + n = fcntl(fd, F_GETFL);
980 + n &= ~(O_NONBLOCK);
981 + fcntl(fd, F_SETFL, n);
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.
990 +int write_err(int pts, int realfd, char *realcons, int e)
997 + fprintf(stderr, "bootlogd: writing to console: %s\n",
1002 + if ((fd = open_nb(realcons)) < 0)
1008 int main(int argc, char **argv)
1014 + char realcons[1024];
1018 @@ -298,23 +479,32 @@
1020 * Open console device directly.
1022 - if (consolename(buf, sizeof(buf)) < 0)
1023 + if (consolename(realcons, sizeof(realcons)) < 0)
1025 - if ((realfd = open(buf, O_WRONLY|O_NONBLOCK)) < 0) {
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");
1032 + if ((realfd = open_nb(realcons)) < 0) {
1033 fprintf(stderr, "bootlogd: %s: %s\n", buf, strerror(errno));
1036 - n = fcntl(realfd, F_GETFL);
1037 - n &= ~(O_NONBLOCK);
1038 - fcntl(realfd, F_SETFL, n);
1041 * Grab a pty, and redirect console messages to it.
1043 - if (openpty(&ptm, &pts, buf, NULL, NULL) < 0) {
1044 - fprintf(stderr, "bootlogd: cannot allocate pseudo tty\n");
1048 + if (findpty(&ptm, &pts, buf) < 0) {
1050 + "bootlogd: cannot allocate pseudo tty: %s\n",
1055 (void)ioctl(0, TIOCCONS, NULL);
1057 /* Work around bug in 2.1/2.2 kernels. Fixed in 2.2.13 and 2.3.18 */
1059 * open the logfile. There might be buffered messages
1062 - tv.tv_sec = fp ? 86400 : 5;
1065 + tv.tv_usec = 500000;
1068 if (select(ptm + 1, &fds, NULL, NULL, &tv) == 1) {
1069 @@ -374,10 +564,22 @@
1072 i = write(realfd, p, m);
1073 - if (i <= 0) break;
1082 + * Handle EIO (somebody hung
1083 + * up our filedescriptor)
1085 + realfd = write_err(pts, realfd,
1087 + if (realfd >= 0) continue;
1088 + got_signal = 1; /* Not really */
1093 * Increment buffer position. Handle
1094 * wraps, and also drag output pointer
1096 writelog(fp, outptr, todo);
1099 - if (fp && !didnl) {
1102 + if (!didnl) fputc('\n', fp);
1106 Binary files sysvinit-2.85/src/bootlogd.o and sysvinit-2.86/src/bootlogd.o differ
1107 diff -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
1112 * Author: Miquel van Smoorenburg, miquels@cistron.nl
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
1117 * This file is part of the sysvinit suite,
1118 * Copyright 1991-2003 Miquel van Smoorenburg.
1119 @@ -135,6 +135,13 @@
1124 + * Make sure tp and fd aren't in a register. Some versions
1125 + * of gcc clobber those after longjmp (or so I understand).
1130 getuidtty(&user, &tty);
1133 Binary files sysvinit-2.85/src/dowall.o and sysvinit-2.86/src/dowall.o differ
1134 Binary files sysvinit-2.85/src/halt and sysvinit-2.86/src/halt differ
1135 diff -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
1139 * execute an "shutdown -r". This is for compatibility with
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).
1153 * Reboot and halt are both this program. Reboot
1154 * is just a link to halt. Invoking the program
1157 * Author: Miquel van Smoorenburg, miquels@cistron.nl
1159 - * Version: 2.84, 27-Nov-2001
1160 + * Version: 2.86, 30-Jul-2004
1162 * This file is part of the sysvinit suite,
1163 - * Copyright 1991-2001 Miquel van Smoorenburg.
1164 + * Copyright 1991-2004 Miquel van Smoorenburg.
1166 * This program is free software; you can redistribute it and/or
1167 * modify it under the terms of the GNU General Public License
1172 -char *Version = "@(#)halt 2.84 27-Nov-2001 miquels@cistron.nl";
1173 +char *Version = "@(#)halt 2.86 31-Jul-2004 miquels@cistron.nl";
1176 #define KERNEL_MONITOR 1 /* If halt() puts you into the kernel monitor. */
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");
1195 @@ -172,11 +183,6 @@
1199 - if (geteuid() != 0) {
1200 - fprintf(stderr, "%s: must be superuser.\n", progname);
1204 if (!strcmp(progname, "reboot")) do_reboot = 1;
1205 if (!strcmp(progname, "poweroff")) do_poweroff = 1;
1207 @@ -216,6 +222,11 @@
1209 if (argc != optind) usage();
1211 + if (geteuid() != 0) {
1212 + fprintf(stderr, "%s: must be superuser.\n", progname);
1218 if (!do_hard && !do_nothing) {
1221 * Exit if all we wanted to do was write a wtmp record.
1223 - if (do_nothing) exit(0);
1224 + if (do_nothing && !do_hddown && !do_ifdown) exit(0);
1228 @@ -249,13 +260,17 @@
1232 + if (do_nothing) exit(0);
1235 init_reboot(BMAGIC_REBOOT);
1238 * Turn on hard reboot, CTRL-ALT-DEL will reboot now
1241 init_reboot(BMAGIC_HARD);
1245 * Stop init; it is insensitive to the signals sent
1248 * If we return, we (c)ontinued from the kernel monitor.
1251 init_reboot(BMAGIC_SOFT);
1256 Binary files sysvinit-2.85/src/halt.o and sysvinit-2.86/src/halt.o differ
1257 diff -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
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";
1273 -#include <sys/ioctl.h>
1276 +#include <sys/ioctl.h>
1277 #include <linux/hdreg.h>
1279 #define MAX_DISKS 64
1280 @@ -104,6 +105,15 @@
1284 +#else /* __linux__ */
1291 +#endif /* __linux__ */
1294 int main(int argc, char **argv)
1296 Binary files sysvinit-2.85/src/hddown.o and sysvinit-2.86/src/hddown.o differ
1297 Binary files sysvinit-2.85/src/ifdown.o and sysvinit-2.86/src/ifdown.o differ
1298 Binary files sysvinit-2.85/src/init and sysvinit-2.86/src/init differ
1299 diff -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
1303 * init [0123456SsQqAaBbCc]
1304 * telinit [0123456SsQqAaBbCc]
1306 - * Version: @(#)init.c 2.85 15-Apr-2003 miquels@cistron.nl
1307 + * Version: @(#)init.c 2.86 30-Jul-2004 miquels@cistron.nl
1309 -#define VERSION "2.85"
1310 -#define DATE "15-Apr-2003"
1311 +#define VERSION "2.86"
1312 +#define DATE "31-Jul-2004"
1314 * This file is part of the sysvinit suite,
1315 - * Copyright 1991-2003 Miquel van Smoorenburg.
1316 + * Copyright 1991-2004 Miquel van Smoorenburg.
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.
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
1333 #include <sys/types.h>
1334 #include <sys/stat.h>
1335 #include <sys/ioctl.h>
1336 #include <sys/wait.h>
1340 #include <sys/resource.h>
1344 # define SIGPWR SIGUSR2
1354 /* Set a signal handler. */
1355 #define SETSIG(sa, sig, fun, flags) \
1358 CHILD *newFamily = NULL; /* The list after inittab re-read */
1360 CHILD ch_emerg = { /* Emergency shell */
1377 char runlevel = 'S'; /* The current run level */
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 @@
1393 +#define NR_EXTRA_ENV 16
1394 +char *extra_env[NR_EXTRA_ENV];
1398 * Sleep a number of seconds.
1400 @@ -203,6 +209,35 @@
1406 + * Non-failing allocation routines (init cannot fail).
1408 +void *imalloc(size_t size)
1412 + while ((m = malloc(size)) == NULL) {
1413 + initlog(L_VB, "out of memory");
1416 + memset(m, 0, size);
1421 +char *istrdup(char *s)
1426 + l = strlen(s) + 1;
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 @@
1438 } while (cmd != C_REC);
1440 - while ((p = (CHILD *)malloc(sizeof(CHILD))) == NULL ) {
1441 - log(L_VB, "out of memory");
1444 - memset(p, 0, sizeof(CHILD));
1445 + p = imalloc(sizeof(CHILD));
1446 get_string(p->id, sizeof(p->id), f);
1448 do switch(cmd = get_cmd(f)) {
1453 __attribute__ ((format (printf, 1, 2)))
1455 -int setproctitle(char *fmt, ...)
1456 +static int setproctitle(char *fmt, ...)
1460 @@ -432,8 +464,10 @@
1461 len = vsnprintf(buf, sizeof(buf), fmt, ap);
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);
1474 int tried_vtmaster = 0;
1477 - if ((s = getenv("CONSOLE")) != NULL)
1478 + if (user_console) {
1479 + console_dev = user_console;
1480 + } else if ((s = getenv("CONSOLE")) != NULL)
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) ) {
1489 - log(L_VB, "chld_handler: marked %d as zombie",
1491 + "chld_handler: marked %d as zombie",
1494 ADDSET(got_signals, SIGCHLD);
1496 ch->flags |= ZOMBIE;
1497 @@ -541,11 +576,9 @@
1503 - log(L_VB, "chld_handler: unknown child %d exited.",
1504 + INITDBG(L_VB, "chld_handler: unknown child %d exited.",
1508 errno = saved_errno;
1510 @@ -563,28 +596,34 @@
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 /.
1520 +void coredump(void)
1522 - static int dumped = 0;
1523 - struct rlimit rlim;
1524 + static int dumped = 0;
1525 + struct rlimit rlim;
1528 - if (dumped) return 1;
1529 + if (dumped) return;
1532 - if (fork() != 0) return 1;
1533 + if (fork() != 0) return;
1535 + sigfillset(&mask);
1536 + sigprocmask(SIG_SETMASK, &mask, NULL);
1538 rlim.rlim_cur = RLIM_INFINITY;
1539 rlim.rlim_max = RLIM_INFINITY;
1540 setrlimit(RLIMIT_CORE, &rlim);
1544 signal(SIGSEGV, SIG_DFL);
1547 + sigdelset(&mask, SIGSEGV);
1548 + sigprocmask(SIG_SETMASK, &mask, NULL);
1556 * If we have the info, print where it occured.
1557 * Then sleep 30 seconds and try to continue.
1560 +#if defined(STACK_DEBUG) && defined(__linux__)
1561 void segv_handler(int sig, struct sigcontext ctx)
1564 @@ -601,10 +640,10 @@
1565 if ((void *)ctx.eip >= (void *)do_sleep &&
1566 (void *)ctx.eip < (void *)main)
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)
1575 errno = saved_errno;
1578 @@ -612,9 +651,10 @@
1580 int saved_errno = errno;
1582 - log(L_VB, "PANIC: segmentation violation! sleeping for 30 seconds.");
1583 - if (coredump() != 0)
1586 + "PANIC: segmentation violation! sleeping for 30 seconds.");
1589 errno = saved_errno;
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);
1601 @@ -697,10 +737,11 @@
1603 __attribute__ ((format (printf, 2, 3)))
1605 -void log(int loglevel, char *s, ...)
1606 +void initlog(int loglevel, char *s, ...)
1610 + sigset_t nmask, omask;
1612 va_start(va_alist, s);
1613 vsnprintf(buf, sizeof(buf), s, va_alist);
1614 @@ -708,11 +749,15 @@
1616 if (loglevel & L_SY) {
1618 - * Re-etablish connection with syslogd every time.
1619 + * Re-establish connection with syslogd every time.
1620 + * Block signals while talking to syslog.
1622 + sigfillset(&nmask);
1623 + sigprocmask(SIG_BLOCK, &nmask, &omask);
1624 openlog("init", 0, LOG_DAEMON);
1625 syslog(LOG_INFO, "%s", buf);
1627 + sigprocmask(SIG_SETMASK, &omask, NULL);
1631 @@ -727,14 +772,51 @@
1635 - * See if one character of s2 is in s1
1636 + * Build a new environment for execve().
1638 -int any(char *s1, char *s2)
1639 +char **init_buildenv(int child)
1642 - if (strchr(s1, *s2++) != NULL)
1645 + char i_lvl[] = "RUNLEVEL=x";
1646 + char i_prev[] = "PREVLEVEL=x";
1651 + for (n = 0; environ[n]; n++)
1653 + n += NR_EXTRA_ENV + 8;
1654 + e = calloc(n, sizeof(char *));
1656 + for (n = 0; environ[n]; n++)
1657 + e[n] = istrdup(environ[n]);
1659 + for (i = 0; i < NR_EXTRA_ENV; i++)
1661 + e[n++] = istrdup(extra_env[i]);
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);
1679 +void init_freeenv(char **e)
1683 + for (n = 0; e[n]; n++)
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;
1700 /* Do we try to respawn too fast? */
1701 if (ch->count >= MAXSPAWN) {
1703 - log(L_VB, "Id \"%s\" respawning too fast: disabled for %d minutes",
1704 - ch->id, SLEEPTIME / 60);
1706 + "Id \"%s\" respawning too fast: disabled for %d minutes",
1707 + ch->id, SLEEPTIME / 60);
1708 ch->flags &= ~RUNNING;
1709 ch->flags |= FAILING;
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 */
1720 @@ -868,15 +948,6 @@
1722 sigprocmask(SIG_SETMASK, &omask, NULL);
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;
1731 - putenv(E_VERSION);
1734 * In sysinit, boot, bootwait or single user mode:
1735 * for any wait-type subprocess we _force_ the console
1739 if ((pid = fork()) < 0) {
1740 - log(L_VB, "cannot fork");
1741 + initlog(L_VB, "cannot fork");
1746 * this with a temporary process.
1748 if ((pid = fork()) < 0) {
1749 - log(L_VB, "cannot fork");
1750 + initlog(L_VB, "cannot fork");
1754 @@ -946,7 +1017,7 @@
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,
1761 f = open("/dev/null", O_RDWR);
1763 @@ -954,15 +1025,15 @@
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);
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.
1780 + execvp(args[1], args + 1);
1781 if (errno == ENOEXEC) {
1784 @@ -972,18 +1043,16 @@
1786 execvp(args[1], args + 1);
1788 - log(L_VB, "cannot execute \"%s\"", args[1]);
1789 + initlog(L_VB, "cannot execute \"%s\"", args[1]);
1793 sigprocmask(SIG_SETMASK, &omask, NULL);
1796 - log(L_VB, "Started id %s (pid %d)", ch->id, pid);
1798 + INITDBG(L_VB, "Started id %s (pid %d)", ch->id, pid);
1801 - log(L_VB, "cannot fork, retry..");
1802 + initlog(L_VB, "cannot fork, retry..");
1806 @@ -1032,66 +1101,45 @@
1811 - * My version of strtok(3).
1813 -char *get_part(char *str, int tok)
1820 - if (s == NULL || *s == 0)
1823 - while(*p != tok && *p)
1833 * Read the inittab file.
1835 void read_inittab(void)
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 */
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 */
1857 - struct stat st; /* To stat INITLVL */
1858 + struct stat st; /* To stat INITLVL */
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 */
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? */
1875 if (newFamily != NULL) {
1876 - log(L_VB, "PANIC newFamily != NULL");
1877 + INITDBG(L_VB, "PANIC newFamily != NULL");
1880 - log(L_VB, "Reading inittab");
1881 + INITDBG(L_VB, "Reading inittab");
1885 * Open INITTAB and real line by line.
1887 if ((fp = fopen(INITTAB, "r")) == NULL)
1888 - log(L_VB, "No inittab file found");
1889 + initlog(L_VB, "No inittab file found");
1893 @@ -1103,9 +1151,9 @@
1894 * See if we have a single user entry.
1896 for(old = newFamily; old; old = old->next)
1897 - if (strcmp(old->rlevel, "S") == 0) break;
1898 + if (strpbrk(old->rlevel, "S")) break;
1900 - snprintf(buf, sizeof(buf), "~~:S:wait:%s\n", SHELL);
1901 + snprintf(buf, sizeof(buf), "~~:S:wait:%s\n", SULOGIN);
1905 @@ -1120,10 +1168,10 @@
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");
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");
1924 - log(L_VB, "%s[%d]: %s", INITTAB, lineNo, err);
1926 - log(L_VB, "%s:%s:%s:%s", id, rlevel, action, process);
1928 + initlog(L_VB, "%s[%d]: %s", INITTAB, lineNo, err);
1929 + INITDBG(L_VB, "%s:%s:%s:%s", id, rlevel, action, process);
1933 @@ -1162,7 +1208,7 @@
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);
1942 @@ -1172,7 +1218,7 @@
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);
1951 @@ -1182,11 +1228,7 @@
1953 * Allocate a CHILD structure
1955 - while ((ch = malloc(sizeof(CHILD))) == NULL) {
1956 - log(L_VB, "out of memory");
1959 - memset(ch, 0, sizeof(CHILD));
1960 + ch = imalloc(sizeof(CHILD));
1964 @@ -1275,9 +1317,7 @@
1969 - log(L_VB, "Checking for children to kill");
1971 + INITDBG(L_VB, "Checking for children to kill");
1972 for(round = 0; round < 2; round++) {
1974 for(ch = family; ch; ch = ch->next) {
1975 @@ -1328,19 +1368,19 @@
1976 ch->flags &= ~KILLME;
1980 - log(L_VB, "Killing \"%s\"", ch->process);
1982 + INITDBG(L_VB, "Killing \"%s\"", ch->process);
1984 case 0: /* Send TERM signal */
1986 - log(L_CO, "Sending processes the TERM signal");
1988 + "Sending processes the TERM signal");
1989 kill(-(ch->pid), SIGTERM);
1992 case 1: /* Send KILL signal and collect status */
1994 - log(L_CO, "Sending processes the KILL signal");
1996 + "Sending processes the KILL signal");
1997 kill(-(ch->pid), SIGKILL);
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,
2009 - log(L_VB, "Updating utmp for pid %d [id %s]", ch->pid, ch->id);
2011 + INITDBG(L_VB, "Updating utmp for pid %d [id %s]",
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? */
2021 - log(L_VB, "Checking for children to start");
2023 + INITDBG(L_VB, "Checking for children to start");
2025 for(ch = family; ch; ch = ch->next) {
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);
2034 @@ -1545,7 +1582,8 @@
2036 if (islower(lvl)) lvl = toupper(lvl);
2037 if (strchr("0123456789S", lvl) == NULL) {
2038 - log(L_VB, "Initdefault level '%c' is invalid", lvl);
2040 + "Initdefault level '%c' is invalid", lvl);
2044 @@ -1570,98 +1608,99 @@
2046 int read_level(int arg)
2048 - unsigned char foo = 'X'; /* Contents of INITLVL */
2049 - CHILD *ch; /* Walk through list */
2051 + CHILD *ch; /* Walk through list */
2052 + unsigned char foo = 'X'; /* Contents of INITLVL */
2063 - if (arg) foo = arg;
2064 + if (arg) foo = arg;
2072 - if (stat(INITLVL, &stt) != 0 || stt.st_size != 0L)
2073 - fp = fopen(INITLVL, "r");
2076 + if (stat(INITLVL, &stt) != 0 || stt.st_size != 0L)
2077 + fp = fopen(INITLVL, "r");
2079 - if (fp == NULL && (stat(INITLVL2, &stt) != 0 || stt.st_size != 0L))
2080 - fp = fopen(INITLVL2, "r");
2082 + (stat(INITLVL2, &stt) != 0 || stt.st_size != 0L))
2083 + fp = fopen(INITLVL2, "r");
2086 - /* INITLVL file is empty or not there - act as 'init q' */
2087 - log(L_SY, "Re-reading inittab");
2090 + /* INITLVL file empty or not there - act as 'init q' */
2091 + initlog(L_SY, "Re-reading inittab");
2094 + ok = fscanf(fp, "%c %d", &foo, &st);
2097 + /* We go to the new runlevel passed as an argument. */
2101 - ok = fscanf(fp, "%c %d", &foo, &st);
2104 - /* We go to the new runlevel passed as an argument. */
2108 - if (ok == 2) sltime = st;
2109 + if (ok == 2) sltime = st;
2111 #endif /* INITLVL */
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);
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);
2124 - /* Log this action */
2127 - log(L_VB, "Going single user");
2130 - log(L_SY, "Re-reading inittab");
2135 - log(L_SY, "Activating demand-procedures for '%c'", foo);
2138 - log(L_SY, "Trying to re-exec init");
2141 - log(L_VB, "Switching to runlevel: %c", foo);
2143 + /* Log this action */
2146 + initlog(L_VB, "Going single user");
2149 + initlog(L_SY, "Re-reading inittab");
2155 + "Activating demand-procedures for '%c'", foo);
2158 + initlog(L_SY, "Trying to re-exec init");
2161 + initlog(L_VB, "Switching to runlevel: %c", foo);
2164 - if (foo == 'Q') return(runlevel);
2165 + if (foo == 'Q') return runlevel;
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);
2174 - /* Read inittab again first! */
2176 + /* Read inittab again first! */
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;
2186 - log(L_VB, "Marking (%s) as ondemand, flags %d",
2187 - ch->id, ch->flags);
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;
2199 + "Marking (%s) as ondemand, flags %d",
2200 + ch->id, ch->flags);
2205 - /* Store both the old and the new runlevel. */
2206 - write_utmp_wtmp("runlevel", "~~", foo + 256*runlevel, RUN_LVL, "~");
2208 - prevlevel = runlevel;
2210 + /* Store both the old and the new runlevel. */
2211 + write_utmp_wtmp("runlevel", "~~", foo + 256*runlevel, RUN_LVL, "~");
2213 + prevlevel = runlevel;
2218 @@ -1674,32 +1713,33 @@
2220 void fail_check(void)
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 */
2232 - for(ch = family; ch; ch = ch->next) {
2233 + for(ch = family; ch; ch = ch->next) {
2235 - if (ch->flags & FAILING) {
2236 - /* Can we free this sucker? */
2237 - if (ch->tm + SLEEPTIME < t) {
2238 - ch->flags &= ~FAILING;
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;
2252 + /* No, we'll look again later */
2253 + if (next_alarm == 0 ||
2254 + ch->tm + SLEEPTIME > next_alarm)
2255 + next_alarm = ch->tm + SLEEPTIME;
2262 - if (next_alarm < 1) next_alarm = 1;
2263 - alarm(next_alarm);
2267 + if (next_alarm < 1) next_alarm = 1;
2268 + alarm(next_alarm);
2272 /* Set all 'Fail' timers to 0 */
2273 @@ -1752,9 +1792,9 @@
2275 int check_pipe(int fd)
2279 - char signature[8];
2282 + char signature[8];
2286 @@ -1789,10 +1829,11 @@
2290 - sigset_t mask, oldset;
2295 + sigset_t mask, oldset;
2300 if (strchr("S12345",runlevel) == NULL)
2302 @@ -1825,27 +1866,26 @@
2304 for(ch = family; ch; ch = ch->next)
2305 if (ch->flags & ZOMBIE) {
2307 - log(L_VB, "Child died, PID= %d", ch->pid);
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);
2315 - if ((pid = fork()) > 0) {
2317 - * Yup. _Parent_ exec's ...
2319 - execl(myname, myname, "--init", NULL);
2320 - } else if (pid == 0) {
2321 + if ((pid = fork()) == 0) {
2323 - * ... while child sends her the
2324 - * state information and dies
2325 + * Child sends state information to the parent.
2332 + * The existing init process execs a new init binary.
2334 + env = init_buildenv(0);
2335 + execl(myname, myname, "--init", NULL, env);
2338 * We shouldn't be here, something failed.
2339 * Bitch, close the state pipe, unblock signals and return.
2340 @@ -1853,7 +1893,8 @@
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");
2350 @@ -1863,10 +1904,10 @@
2352 void fifo_new_level(int level)
2361 if (level == runlevel) return;
2363 @@ -1894,6 +1935,59 @@
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.
2373 +void initcmd_setenv(char *data, int size)
2375 + char *env, *p, *e, *eq;
2380 + while (*data && data < e) {
2382 + for (p = data; *p && p < e; p++)
2383 + if (*p == '=') eq = p;
2388 + sz = eq ? (eq - env) : (p - env);
2390 + /*initlog(L_SY, "init_setenv: %s, %s, %d", env, eq, sz);*/
2393 + * We only allow INIT_* to be set.
2395 + if (strncmp(env, "INIT_", 5) != 0)
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;
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);
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 @@
2425 void check_init_fifo(void)
2427 - struct init_request request;
2431 - struct stat st, st2;
2432 - struct timeval tv;
2433 + struct init_request request;
2434 + struct timeval tv;
2435 + struct stat st, st2;
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);
2451 @@ -1987,7 +2081,7 @@
2454 if (errno == EINTR) return;
2455 - log(L_VB, "error reading initrequest");
2456 + initlog(L_VB, "error reading initrequest");
2460 @@ -2001,7 +2095,7 @@
2463 if (request.magic != INIT_MAGIC || n != sizeof(request)) {
2464 - log(L_VB, "got bogus initrequest");
2465 + initlog(L_VB, "got bogus initrequest");
2468 switch(request.cmd) {
2469 @@ -2025,8 +2119,23 @@
2473 + case INIT_CMD_SETENV:
2474 + initcmd_setenv(request.i.data, sizeof(request.i.data));
2476 + case INIT_CMD_CHANGECONS:
2477 + if (user_console) {
2478 + free(user_console);
2479 + user_console = NULL;
2481 + if (!request.i.bsd.reserved[0])
2482 + user_console = NULL;
2484 + user_console = strdup(request.i.bsd.reserved);
2489 - log(L_VB, "got unimplemented initrequest.");
2490 + initlog(L_VB, "got unimplemented initrequest.");
2494 @@ -2045,11 +2154,11 @@
2496 void boot_transitions()
2499 - static int newlevel = 0;
2502 - static int warn = 1;
2504 + static int newlevel = 0;
2505 + static int warn = 1;
2509 /* Check if there is something to wait for! */
2510 for( ch = family; ch; ch = ch->next )
2511 @@ -2061,9 +2170,7 @@
2514 case '#': /* SYSINIT -> BOOT */
2516 - log(L_VB, "SYSINIT -> BOOT");
2518 + INITDBG(L_VB, "SYSINIT -> BOOT");
2520 /* Write a boot record. */
2521 wrote_utmp_reboot = 0;
2522 @@ -2080,9 +2187,7 @@
2525 case '*': /* BOOT -> NORMAL */
2527 - log(L_VB, "BOOT -> NORMAL");
2529 + INITDBG(L_VB, "BOOT -> NORMAL");
2530 if (runlevel != newlevel)
2531 loglevel = newlevel;
2532 runlevel = newlevel;
2533 @@ -2091,9 +2196,7 @@
2535 case 'S': /* Ended SU mode */
2538 - log(L_VB, "END SU MODE");
2540 + INITDBG(L_VB, "END SU MODE");
2541 newlevel = get_init_default();
2542 if (!did_boot && newlevel != 'S')
2544 @@ -2110,7 +2213,8 @@
2548 - log(L_VB, "no more processes left in this runlevel");
2550 + "no more processes left in this runlevel");
2553 if (got_signals == 0)
2554 @@ -2118,7 +2222,7 @@
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 @@
2565 void process_signals()
2578 if (ISMEMBER(got_signals, SIGPWR)) {
2580 - log(L_VB, "got SIGPWR");
2582 + INITDBG(L_VB, "got SIGPWR");
2583 /* See _what_ kind of SIGPWR this is. */
2585 if ((fd = open(PWRSTAT, O_RDONLY)) >= 0) {
2586 @@ -2157,9 +2259,7 @@
2589 if (ISMEMBER(got_signals, SIGINT)) {
2591 - log(L_VB, "got SIGINT");
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 @@
2600 if (ISMEMBER(got_signals, SIGWINCH)) {
2602 - log(L_VB, "got SIGWINCH");
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 @@
2611 if (ISMEMBER(got_signals, SIGALRM)) {
2613 - log(L_VB, "got SIGALRM");
2615 + INITDBG(L_VB, "got SIGALRM");
2616 /* The timer went off: check it out */
2617 DELSET(got_signals, SIGALRM);
2620 if (ISMEMBER(got_signals, SIGCHLD)) {
2622 - log(L_VB, "got SIGCHLD");
2624 + INITDBG(L_VB, "got SIGCHLD");
2625 /* First set flag to 0 */
2626 DELSET(got_signals, SIGCHLD);
2628 /* See which child this was */
2629 for(ch = family; ch; ch = ch->next)
2630 if (ch->flags & ZOMBIE) {
2632 - log(L_VB, "Child died, PID= %d", ch->pid);
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 @@
2641 if (ISMEMBER(got_signals, SIGHUP)) {
2643 - log(L_VB, "got SIGHUP");
2645 + INITDBG(L_VB, "got SIGHUP");
2647 /* Are we waiting for a child? */
2648 for(ch = family; ch; ch = ch->next)
2649 @@ -2240,9 +2330,7 @@
2651 * SIGUSR1 means close and reopen /dev/initctl
2654 - log(L_VB, "got SIGUSR1");
2656 + INITDBG(L_VB, "got SIGUSR1");
2659 DELSET(got_signals, SIGUSR1);
2660 @@ -2254,11 +2342,11 @@
2668 - struct sigaction sa;
2670 + struct sigaction sa;
2677 @@ -2278,6 +2366,7 @@
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 @@
2688 (void) ioctl(0, KDSIGACCEPT, SIGWINCH);
2692 * Ignore all signals.
2693 @@ -2320,9 +2410,9 @@
2697 - * Set default PATH variable (for ksh)
2698 + * Set default PATH variable.
2700 - if (getenv("PATH") == NULL) putenv(PATH_DFL);
2704 * Initialize /var/run/utmp (only works if /var is on
2705 @@ -2333,7 +2423,7 @@
2707 * Say hello to the world
2709 - log(L_CO, bootmsg, "booting");
2710 + initlog(L_CO, bootmsg, "booting");
2713 * See if we have to start an emergency shell.
2714 @@ -2358,7 +2448,7 @@
2716 * Restart: unblock signals and let the show go on
2718 - log(L_CO, bootmsg, "reloading");
2719 + initlog(L_CO, bootmsg, "reloading");
2721 sigprocmask(SIG_UNBLOCK, &sgt, NULL);
2723 @@ -2368,9 +2458,7 @@
2725 /* See if we need to make the boot transitions. */
2728 - log(L_VB, "init_main: waiting..");
2730 + INITDBG(L_VB, "init_main: waiting..");
2732 /* Check if there are processes to be waited on. */
2733 for(ch = family; ch; ch = ch->next)
2734 @@ -2405,10 +2493,10 @@
2736 * Tell the user about the syntax we expect.
2738 -void Usage(char *s)
2739 +void usage(char *s)
2741 - fprintf(stderr, "Usage: %s 0123456SsQqAaBbCcUu\n", s);
2743 + fprintf(stderr, "Usage: %s 0123456SsQqAaBbCcUu\n", s);
2747 int telinit(char *progname, int argc, char **argv)
2748 @@ -2418,28 +2506,51 @@
2750 struct init_request request;
2751 struct sigaction sa;
2756 - while((f = getopt(argc, argv, "t:")) != EOF) switch(f) {
2757 + memset(&request, 0, sizeof(request));
2758 + request.magic = INIT_MAGIC;
2760 + while ((f = getopt(argc, argv, "t:e:")) != EOF) switch(f) {
2762 sltime = atoi(optarg);
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);
2773 + memcpy(env, optarg, l);
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;
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;
2795 + if (argc != optind)
2797 + request.cmd = INIT_CMD_SETENV;
2799 + if (argc - optind != 1 || strlen(argv[optind]) != 1)
2801 + if (!strchr("0123456789SsQqAaBbCcUu", argv[optind][0]))
2803 + request.cmd = INIT_CMD_RUNLVL;
2804 + request.runlevel = env ? 0 : argv[optind][0];
2805 + request.sleeptime = sltime;
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);
2812 @@ -2449,7 +2560,27 @@
2816 -#ifndef TELINIT_USES_INITLVL
2818 +#ifdef TELINIT_USES_INITLVL
2819 + if (request.cmd == INIT_CMD_RUNLVL) {
2820 + /* Fallthrough to the old method. */
2822 + /* Now write the new runlevel. */
2823 + if ((fp = fopen(INITLVL, "w")) == NULL) {
2824 + fprintf(stderr, "%s: cannot create %s\n",
2825 + progname, INITLVL);
2828 + fprintf(fp, "%s %d", argv[optind], sltime);
2831 + /* And tell init about the pending runlevel change. */
2832 + if (kill(INITPID, SIGHUP) < 0) perror(progname);
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 @@
2847 - /* Fallthrough to the old method. */
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);
2855 - fprintf(fp, "%s %d", argv[optind], sltime);
2858 - /* And tell init about the pending runlevel change. */
2859 - if (kill(INITPID, SIGHUP) < 0) perror(progname);
2866 @@ -2518,7 +2631,7 @@
2868 receive_state(STATE_PIPE);
2870 - myname = strdup(argv[0]);
2871 + myname = istrdup(argv[0]);
2874 for (f = 0; f < argc; f++)
2875 diff -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
2879 * init.h Several defines and declarations to be
2880 * included by all modules of the init program.
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
2885 - * Modified: Re-exec patch; 24 Feb 1998, Al Viro.
2888 /* Standard configuration */
2890 #define TESTTIME 120 /* this much seconds */
2891 #define SLEEPTIME 300 /* Disable time */
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"
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, ...);
2904 +__attribute__ ((format (printf, 2, 3)))
2906 +void initlog(int loglevel, char *fmt, ...);
2907 void set_term(int how);
2908 void print(char *fmt);
2911 +# define INITDBG(level, fmt, args...) initlog(level, fmt, ##args)
2913 +# define INITDBG(level, fmt, args...)
2916 /* Actions to be taken by init */
2919 Binary files sysvinit-2.85/src/init.o and sysvinit-2.86/src/init.o differ
2920 Binary files sysvinit-2.85/src/init_utmp.o and sysvinit-2.86/src/init_utmp.o differ
2921 diff -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
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
2930 + * initreq.h Interface to talk to init through /dev/initctl.
2932 - * Version: @(#)initreq.h 1.25 28-Dec-1995 MvS
2933 + * Copyright (C) 1995-2004 Miquel van Smoorenburg
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.
2940 + * Version: @(#)initreq.h 1.28 31-Mar-2004 MvS
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.
2949 #include <sys/param.h>
2951 +#if defined(__FreeBSD_kernel__)
2952 +# define INIT_FIFO "/etc/.initctl"
2954 +# define INIT_FIFO "/dev/initctl"
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
2973 +#define INIT_CMD_CHANGECONS 12345
2975 +#ifdef MAXHOSTNAMELEN
2976 +# define INITRQ_HLEN MAXHOSTNAMELEN
2978 +# define INITRQ_HLEN 64
2982 + * This is what BSD 4.4 uses when talking to init.
2983 + * Linux doesn't use this right now.
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. */
2998 + * Because of legacy interfaces, "runlevel" and "sleeptime"
2999 + * aren't in a seperate struct in the union.
3001 + * The weird sizes are because init expects the whole
3002 + * struct to be 384 bytes.
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 */
3022 + struct init_request_bsd bsd;
3028 Binary files sysvinit-2.85/src/killall5 and sysvinit-2.86/src/killall5 differ
3029 diff -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
3034 * pidof.c Tries to get the pid of the process[es] named.
3036 - * Version: 2.85 14-Apr-2003 MvS
3037 + * Version: 2.86 30-Jul-2004 MvS
3039 * Usage: killall5 [-][signal]
3040 * pidof [-s] [-o omitpid [-o omitpid]] program [program..]
3042 * - swapped out programs pids are caught now
3044 * This file is part of the sysvinit suite,
3045 - * Copyright 1991-2003 Miquel van Smoorenburg.
3046 + * Copyright 1991-2004 Miquel van Smoorenburg.
3048 * This program is free software; you can redistribute it and/or
3049 * modify it under the terms of the GNU General Public License
3054 -char *Version = "@(#)killall5 2.85 14-Apr-2003 miquels@cistron.nl";
3055 +char *Version = "@(#)killall5 2.86 31-Jul-2004 miquels@cistron.nl";
3057 +#define STATNAMELEN 15
3059 /* Info about a process. */
3060 -typedef struct _proc_
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. */
3085 -typedef struct _pidq_ {
3086 - struct _pidq_ *front;
3087 - struct _pidq_ *next;
3088 - struct _pidq_ *rear;
3091 +typedef struct pidq {
3093 + struct pidq *next;
3102 /* List of processes. */
3105 -/* Did we stop a number of processes? */
3107 +/* Did we stop all processes ? */
3110 int scripts_too = 0;
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");
3121 @@ -98,14 +107,14 @@
3123 int mount_proc(void)
3128 - char *args[] = { "mount", "-t", "proc", "none", "/proc", NULL };
3129 - int did_mount = 0;
3131 + char *args[] = { "mount", "-t", "proc", "proc", "/proc", 0 };
3134 + int did_mount = 0;
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) {
3140 /* It's not there, so mount it. */
3141 if ((pid = fork()) < 0) {
3144 /* Try a few mount binaries. */
3145 execv("/sbin/mount", args);
3146 - execv("/etc/mount", args);
3147 execv("/bin/mount", args);
3149 /* Okay, I give up. */
3150 @@ -134,28 +142,42 @@
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.");
3158 + nsyslog(LOG_ERR, "/proc unavailable.");
3165 +int readarg(FILE *fp, char *buf, int sz)
3169 + while (f < (sz-1) && (c = fgetc(fp)) != EOF && c)
3173 + return (c == EOF && f == 0) ? c : f;
3177 * Read the proc filesystem.
3199 + unsigned long startcode, endcode;
3202 /* Open the /proc directory. */
3203 if ((dir = opendir("/proc")) == NULL) {
3206 for (p = plist; n; p = n) {
3208 - if (p->fullname) free(p->fullname);
3209 + if (p->argv0) free(p->argv0);
3210 + if (p->argv1) free(p->argv1);
3215 /* Read SID & statname from it. */
3216 if ((fp = fopen(path, "r")) != NULL) {
3218 - fgets(buf, 256, fp);
3219 + fgets(buf, sizeof(buf), fp);
3221 /* See if name starts with '(' */
3223 @@ -215,14 +238,21 @@
3224 p->statname = (char *)xmalloc(strlen(s)+1);
3225 strcpy(p->statname, s);
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 "
3235 + &p->sid, &startcode, &endcode) != 3) {
3237 nsyslog(LOG_ERR, "can't read sid from %s\n",
3242 + if (startcode == 0 && endcode == 0)
3246 /* Process disappeared.. */
3247 @@ -230,24 +260,44 @@
3251 - /* Now read argv[0] */
3252 snprintf(path, sizeof(path), "/proc/%s/cmdline", d->d_name);
3253 if ((fp = fopen(path, "r")) != NULL) {
3255 - while(f < 127 && (c = fgetc(fp)) != EOF && c)
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));
3267 + /* Store the name into malloced memory. */
3268 + p->argv0 = (char *)xmalloc(f + 1);
3269 + strcpy(p->argv0, buf);
3271 + /* Get a pointer to the basename. */
3272 + p->argv0base = strrchr(p->argv0, '/');
3273 + if (p->argv0base != NULL)
3276 + p->argv0base = p->argv0;
3279 + /* And read argv[1] */
3280 + while ((f = readarg(fp, buf, sizeof(buf))) != EOF)
3281 + if (buf[0] != '-') break;
3284 + /* Store the name into malloced memory. */
3285 + p->argv1 = (char *)xmalloc(f + 1);
3286 + strcpy(p->argv1, buf);
3288 + /* Get a pointer to the basename. */
3289 + p->argv1base = strrchr(p->argv1, '/');
3290 + if (p->argv1base != NULL)
3293 + p->argv1base = p->argv1;
3298 - /* Get a pointer to the basename. */
3299 - if ((p->basename = strrchr(p->fullname, '/')) != NULL)
3302 - p->basename = p->fullname;
3304 /* Process disappeared.. */
3306 @@ -272,19 +322,18 @@
3310 -PIDQ *init_pid_q(PIDQ *q)
3311 +PIDQ_HEAD *init_pid_q(PIDQ_HEAD *q)
3313 - q->front = q->next = q->rear = NULL;
3315 + q->head = q->next = q->tail = NULL;
3319 -int empty_q(PIDQ *q)
3320 +int empty_q(PIDQ_HEAD *q)
3322 - return (q->front == NULL);
3323 + return (q->head == NULL);
3326 -int add_pid_to_q(PIDQ *q, PROC *p)
3327 +int add_pid_to_q(PIDQ_HEAD *q, PROC *p)
3331 @@ -294,23 +343,23 @@
3340 - q->rear->next = tmp;
3342 + q->tail->next = tmp;
3348 -PROC *get_next_from_pid_q(PIDQ *q)
3349 +PROC *get_next_from_pid_q(PIDQ_HEAD *q)
3352 - PIDQ *tmp = q->front;
3354 + PIDQ *tmp = q->head;
3357 - p = q->front->proc;
3358 - q->front = tmp->next;
3359 + p = q->head->proc;
3360 + q->head = tmp->next;
3364 @@ -319,15 +368,15 @@
3367 /* Try to get the process ID of a given process. */
3368 -PIDQ *pidof(char *prog)
3369 +PIDQ_HEAD *pidof(char *prog)
3386 /* Try to stat the executable. */
3387 if (prog[0] == '/' && stat(prog, &st) == 0) dostat++;
3392 - q = (PIDQ *)xmalloc(sizeof(PIDQ));
3393 + q = (PIDQ_HEAD *)xmalloc(sizeof(PIDQ_HEAD));
3396 /* First try to find a match based on dev/ino pair. */
3397 @@ -352,20 +401,31 @@
3400 /* If we didn't find a match based on dev/ino, try the name. */
3402 - for (p = plist; p; p = p->next) {
3404 + if (!foundone) for (p = plist; p; p = p->next) {
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);
3413 - if (p->fullname[0] == 0 ||
3414 - strchr(p->fullname, ' ') ||
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);
3424 - if (ok) add_pid_to_q(q, p);
3426 + * if we have a space in argv0, process probably
3427 + * used setproctitle so try statname.
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);
3435 + if (ok) add_pid_to_q(q, p);
3439 @@ -410,12 +470,12 @@
3441 int main_pidof(int argc, char **argv)
3447 - int i,oind, opt, flags = 0;
3448 - pid_t opid[PIDOF_OMITSZ], spid;
3451 + pid_t opid[PIDOF_OMITSZ], spid;
3454 + int i, oind, opt, flags = 0;
3456 for (oind = PIDOF_OMITSZ-1; oind > 0; oind--)
3459 /* Main for either killall or pidof. */
3460 int main(int argc, char **argv)
3463 - int pid, sid = -1;
3464 - int sig = SIGKILL;
3466 + int pid, sid = -1;
3467 + int sig = SIGKILL;
3469 /* Get program name. */
3470 if ((progname = strrchr(argv[0], '/')) == NULL)
3472 /* Now connect to syslog. */
3473 openlog(progname, LOG_CONS|LOG_PID, LOG_DAEMON);
3475 - /* First get the /proc filesystem online. */
3478 /* Were we called as 'pidof' ? */
3479 if (strcmp(progname, "pidof") == 0)
3480 return main_pidof(argc, argv);
3482 if ((sig = atoi(argv[1])) <= 0 || sig > 31) usage();
3485 + /* First get the /proc filesystem online. */
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 @@
3493 /* Now stop all processes. */
3498 - /* Find out our own 'sid'. */
3499 + /* Read /proc filesystem */
3500 if (readproc() < 0) {
3506 - for (p = plist; p; p = p->next)
3507 - if (p->pid == pid) {
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)
3520 /* And let them continue. */
3521 Binary files sysvinit-2.85/src/last and sysvinit-2.86/src/last differ
3522 diff -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
3527 * Author: Miquel van Smoorenburg, miquels@cistron.nl
3529 - * Version: @(#)last 2.85 16-Apr-2003 miquels@cistron.nl
3530 + * Version: @(#)last 2.85 30-Jul-2004 miquels@cistron.nl
3532 * This file is part of the sysvinit suite,
3533 - * Copyright 1991-2003 Miquel van Smoorenburg.
3534 + * Copyright 1991-2004 Miquel van Smoorenburg.
3536 * This program is free software; you can redistribute it and/or
3537 * modify it under the terms of the GNU General Public License
3539 # define SHUTDOWN_TIME 254
3542 -char *Version = "@(#) last 2.85 16-Apr-2003 miquels";
3543 +char *Version = "@(#) last 2.85 31-Apr-2004 miquels";
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 @@
3550 fprintf(stderr, "Usage: %s [-num | -n num] [-f file] "
3551 + "[-t YYYYMMDDHHMMSS] "
3552 "[-R] [-x] [-o] [username..] [tty..]\n", s);
3556 +time_t parsetm(char *ts)
3558 + struct tm u = {0}, origu;
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,
3564 + return (time_t)-1;
3566 + u.tm_year -= 1900;
3572 + if ((tm = mktime(&u)) == (time_t)-1)
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.
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;
3593 int main(int argc, char **argv)
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 */
3600 + time_t until = 0; /* at what time to stop parsing the file */
3602 progname = mybasename(argv[0]);
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)
3610 @@ -552,6 +592,13 @@
3615 + if ((until = parsetm(optarg)) == (time_t)-1) {
3616 + fprintf(stderr, "%s: Invalid time value \"%s\"\n",
3617 + progname, optarg);
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';
3625 if (uread(fp, &ut, &quit) != 1)
3628 + if (until && until < ut.ut_time)
3631 if (memcmp(&ut, &oldut, sizeof(struct utmp)) == 0) continue;
3632 memcpy(&oldut, &ut, sizeof(struct utmp));
3633 lastdate = ut.ut_time;
3634 Binary files sysvinit-2.85/src/last.o and sysvinit-2.86/src/last.o differ
3635 Binary files sysvinit-2.85/src/mesg and sysvinit-2.86/src/mesg differ
3636 Binary files sysvinit-2.85/src/mesg.o and sysvinit-2.86/src/mesg.o differ
3637 Binary files sysvinit-2.85/src/mountpoint and sysvinit-2.86/src/mountpoint differ
3638 diff -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
3643 + * mountpoint See if a directory is a mountpoint.
3645 + * Author: Miquel van Smoorenburg.
3647 + * Version: @(#)mountpoint 2.85-12 17-Mar-2004 miquels@cistron.nl
3649 + * This file is part of the sysvinit suite,
3650 + * Copyright 1991-2004 Miquel van Smoorenburg.
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.
3658 +#include <sys/stat.h>
3659 +#include <unistd.h>
3660 +#include <stdlib.h>
3661 +#include <string.h>
3663 +#include <stdarg.h>
3664 +#include <getopt.h>
3667 +int dostat(char *path, struct stat *st, int do_lstat, int quiet)
3672 + n = lstat(path, st);
3674 + n = stat(path, st);
3678 + fprintf(stderr, "mountpoint: %s: %s\n", path,
3686 + fprintf(stderr, "Usage: mountpoint [-q] [-d] [-x] path\n");
3690 +int main(int argc, char **argv)
3692 + struct stat st, st2;
3700 + while ((c = getopt(argc, argv, "dqx")) != EOF) switch(c) {
3714 + if (optind != argc - 1) usage();
3715 + path = argv[optind];
3717 + if (dostat(path, &st, !xdev, quiet) < 0)
3722 + if (!S_ISBLK(st.st_mode))
3724 + if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
3730 + fprintf(stderr, "mountpoint: %s: not a block device\n",
3734 + printf("%u:%u\n", major(st.st_rdev), minor(st.st_rdev));
3738 + if (!S_ISDIR(st.st_mode)) {
3740 + fprintf(stderr, "mountpoint: %s: not a directory\n",
3745 + memset(buf, 0, sizeof(buf));
3746 + strncpy(buf, path, sizeof(buf) - 4);
3747 + strcat(buf, "/..");
3748 + if (dostat(buf, &st2, 0, quiet) < 0)
3751 + r = (st.st_dev != st2.st_dev) ||
3752 + (st.st_dev == st2.st_dev && st.st_ino == st2.st_ino);
3754 + if (!quiet && !showdev)
3755 + printf("%s is %sa mountpoint\n", path, r ? "" : "not ");
3757 + printf("%u:%u\n", major(st.st_dev), minor(st.st_dev));
3761 Binary files sysvinit-2.85/src/mountpoint.o and sysvinit-2.86/src/mountpoint.o differ
3762 diff -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
3767 * paths.h Paths of files that init and related utilities need.
3769 - * Version: @(#) paths.h 2.84 27-Nov-2001
3770 + * Version: @(#) paths.h 2.85-8 05-Nov-2003
3772 * Author: Miquel van Smoorenburg, <miquels@cistron.nl>
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) */
3782 diff -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
3786 * reboot.h Headerfile that defines how to handle
3787 * the reboot() system call.
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
3794 -#if defined(__GLIBC__)
3795 -# include <sys/reboot.h>
3796 +#include <sys/reboot.h>
3798 +#ifdef RB_ENABLE_CAD
3799 +# define BMAGIC_HARD RB_ENABLE_CAD
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
3811 -#if defined(__GLIBC__)
3812 - #define init_reboot(magic) reboot(magic)
3813 +#ifdef RB_HALT_SYSTEM
3814 +# define BMAGIC_HALT RB_HALT_SYSTEM
3816 - #define init_reboot(magic) reboot(0xfee1dead, 672274793, magic)
3817 +# define BMAGIC_HALT RB_HALT
3820 +#define BMAGIC_REBOOT RB_AUTOBOOT
3822 +#ifdef RB_POWER_OFF
3823 +# define BMAGIC_POWEROFF RB_POWER_OFF
3824 +#elif defined(RB_POWEROFF)
3825 +# define BMAGIC_POWEROFF RB_POWEROFF
3827 +# define BMAGIC_POWEROFF BMAGIC_HALT
3830 +#define init_reboot(magic) reboot(magic)
3832 Binary files sysvinit-2.85/src/runlevel and sysvinit-2.86/src/runlevel differ
3833 Binary files sysvinit-2.85/src/runlevel.o and sysvinit-2.86/src/runlevel.o differ
3834 Binary files sysvinit-2.85/src/shutdown and sysvinit-2.86/src/shutdown differ
3835 diff -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
3840 * Author: Miquel van Smoorenburg, miquels@cistron.nl
3842 - * Version: @(#)shutdown 2.85 14-Apr-2003 miquels@cistron.nl
3843 + * Version: @(#)shutdown 2.86-1 31-Jul-2004 miquels@cistron.nl
3845 * This file is part of the sysvinit suite,
3846 - * Copyright 1991-2003 Miquel van Smoorenburg.
3847 + * Copyright 1991-2004 Miquel van Smoorenburg.
3849 * This program is free software; you can redistribute it and/or
3850 * modify it under the terms of the GNU General Public License
3855 +#include <syslog.h>
3858 +#include "initreq.h"
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";
3863 #define MESSAGELEN 256
3866 char *sltime = 0; /* Sleep time */
3867 char newstate[64]; /* What are we gonna do */
3868 int doself = 0; /* Don't use init */
3871 char *clean_env[] = {
3873 @@ -67,93 +70,152 @@
3874 extern void write_wtmp(char *user, char *id, int pid, int type, char *line);
3877 - * Sleep without being interrupted.
3878 + * Sleep without being interrupted.
3880 void hardsleep(int secs)
3882 - struct timespec ts, rem;
3883 + struct timespec ts, rem;
3890 - while(nanosleep(&ts, &rem) < 0 && errno == EINTR)
3891 + while(nanosleep(&ts, &rem) < 0 && errno == EINTR)
3896 - * Break off an already running shutdown.
3897 + * Break off an already running shutdown.
3900 +void stopit(int sig)
3904 - unlink(FORCEFSCK);
3906 - printf("\r\nShutdown cancelled.\r\n");
3910 + unlink(FORCEFSCK);
3912 + printf("\r\nShutdown cancelled.\r\n");
3917 - * Show usage message.
3918 + * Show usage message.
3924 - "Usage:\t shutdown [-akrhfnc] [-t secs] time [warning message]\n"
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");
3944 +void alrm_handler(int sig)
3951 - * Tell everyone the system is going down in 'mins' minutes.
3952 + * Set environment variables in the init process.
3956 +int init_setenv(char *name, char *value)
3958 - char buf[MESSAGELEN + sizeof(newstate)];
3960 + struct init_request request;
3961 + struct sigaction sa;
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;
3975 - snprintf(buf + len, sizeof(buf) - len,
3976 - "\rThe system is going down %s NOW!\r\n",
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");
3983 + if (nl + vl + 3 >= sizeof(request.i.data))
3986 + memcpy(request.i.data, name, nl);
3988 + request.i.data[nl] = '=';
3989 + memcpy(request.i.data + nl + 1, value, vl);
3993 + * Open the fifo and write the command.
3994 + * Make sure we don't hang on opening /dev/initctl
3996 + memset(&sa, 0, sizeof(sa));
3997 + sa.sa_handler = alrm_handler;
3998 + sigaction(SIGALRM, &sa, NULL);
4001 + if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0 &&
4002 + write(fd, &request, sizeof(request)) == sizeof(request)) {
4008 + fprintf(stderr, "shutdown: ");
4010 + fprintf(stderr, "timeout opening/writing control channel %s\n",
4013 + perror(INIT_FIFO);
4020 - * Create the /etc/nologin file.
4021 + * Tell everyone the system is going down in 'mins' minutes.
4023 +void warn(int mins)
4025 + char buf[MESSAGELEN + sizeof(newstate)];
4029 + strncat(buf, message, sizeof(buf) - 1);
4030 + len = strlen(buf);
4033 + snprintf(buf + len, sizeof(buf) - len,
4034 + "\rThe system is going down %s NOW!\r\n",
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");
4044 + * Create the /etc/nologin file.
4046 void donologin(int min)
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);
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);
4072 @@ -202,131 +264,146 @@
4076 -/* Kill all processes, call /etc/init.d/halt (if present) */
4078 + * Kill all processes, call /etc/init.d/halt (if present)
4082 - int do_halt = (down_level[0] == '0');
4084 + int do_halt = (down_level[0] == '0');
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
4097 - if (access(HALTSCRIPT1, X_OK) == 0)
4098 - script = HALTSCRIPT1;
4100 - script = HALTSCRIPT2;
4102 - if (access(REBOOTSCRIPT1, X_OK) == 0)
4103 - script = REBOOTSCRIPT1;
4105 - script = REBOOTSCRIPT2;
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
4113 + if (access(HALTSCRIPT1, X_OK) == 0)
4114 + script = HALTSCRIPT1;
4116 + script = HALTSCRIPT2;
4118 + if (access(REBOOTSCRIPT1, X_OK) == 0)
4119 + script = REBOOTSCRIPT1;
4121 + script = REBOOTSCRIPT2;
4125 - /* First close all files. */
4126 - for(i = 0; i < 3; i++)
4129 - open("/dev/null", O_RDWR);
4131 - for(i = 3; i < 20; i++) close(i);
4133 + /* First close all files. */
4134 + for(i = 0; i < 3; i++)
4137 + open("/dev/null", O_RDWR);
4139 + for(i = 3; i < 20; i++) close(i);
4142 - /* First idle init. */
4143 - if (kill(1, SIGTSTP) < 0) {
4144 - fprintf(stderr, "shutdown: can't idle init.\r\n");
4147 + /* First idle init. */
4148 + if (kill(1, SIGTSTP) < 0) {
4149 + fprintf(stderr, "shutdown: can't idle init.\r\n");
4153 - /* Kill all processes. */
4154 - fprintf(stderr, "shutdown: sending all processes the TERM signal...\r\n");
4155 - (void) kill(-1, SIGTERM);
4157 - sleep(atoi(sltime));
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);
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);
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);
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. */
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, "~~");
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);
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);
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);
4211 - /* We're done, halt or reboot now. */
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. */
4217 + fprintf(stderr, "The system is halted. Press CTRL-ALT-DEL "
4218 + "or turn off power\r\n");
4219 + init_reboot(BMAGIC_HALT);
4223 + fprintf(stderr, "Please stand by while rebooting the system.\r\n");
4224 + init_reboot(BMAGIC_REBOOT);
4227 - fprintf(stderr, "Please stand by while rebooting the system.\r\n");
4228 - init_reboot(BMAGIC_REBOOT);
4233 - * Go to runlevel 0, 1 or 6.
4234 + * Go to runlevel 0, 1 or 6.
4237 +void shutdown(char *halttype)
4243 + int do_halt = (down_level[0] == '0');
4245 - /* Warn for the last time (hehe) */
4251 + /* Warn for the last time */
4257 + openlog("shutdown", LOG_PID, LOG_USER);
4259 + syslog(LOG_NOTICE, "shutting down for system halt");
4261 + syslog(LOG_NOTICE, "shutting down for system reboot");
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();
4269 - /* Create the arguments for init. */
4270 - args[argp++] = INIT;
4272 - args[argp++] = "-t";
4273 - args[argp++] = sltime;
4275 - args[argp++] = down_level;
4276 - args[argp] = (char *)NULL;
4277 + /* Create the arguments for init. */
4278 + args[argp++] = INIT;
4280 + args[argp++] = "-t";
4281 + args[argp++] = sltime;
4283 + args[argp++] = down_level;
4284 + args[argp] = (char *)NULL;
4291 - /* Now execute init to change runlevel. */
4293 - execv(INIT, args);
4294 + /* Now execute init to change runlevel. */
4296 + init_setenv("INIT_HALT", halttype);
4297 + execv(INIT, args);
4299 - /* Oops - failed. */
4300 - fprintf(stderr, "\rshutdown: cannot execute %s\r\n", INIT);
4302 - unlink(FORCEFSCK);
4304 + /* Oops - failed. */
4305 + fprintf(stderr, "\rshutdown: cannot execute %s\r\n", INIT);
4307 + unlink(FORCEFSCK);
4308 + init_setenv("INIT_HALT", NULL);
4309 + openlog("shutdown", LOG_PID, LOG_USER);
4310 + syslog(LOG_NOTICE, "shutdown failed");
4316 @@ -349,274 +426,287 @@
4321 - * Process the options and do the final countdown.
4323 + * Process the options and do the final countdown.
4325 -int main(argc, argv)
4328 +int main(int argc, char **argv)
4330 - extern int getopt();
4331 - extern int optind;
4332 - int c, i, wt, hours, mins;
4336 - char *when = NULL;
4343 - char *downusers[32];
4345 - char term[UT_LINESIZE + 6];
4349 - struct sigaction sa;
4351 + extern int getopt();
4352 + extern int optind;
4353 + struct sigaction sa;
4360 + char *downusers[32];
4362 + char term[UT_LINESIZE + 6];
4364 + char *when = NULL;
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());
4380 - if (getuid() != 0) {
4381 - fprintf(stderr, "shutdown: you must be root to do that!\n");
4384 - strcpy(down_level, "1");
4385 + if (getuid() != 0) {
4386 + fprintf(stderr, "shutdown: you must be root to do that!\n");
4389 + strcpy(down_level, "1");
4392 - /* Process the options. */
4393 - while((c = getopt(argc, argv, "acqkrhnfFyt:g:i:")) != EOF) {
4395 - case 'a': /* Access control. */
4398 - case 'c': /* Cancel an already running shutdown. */
4401 - case 'k': /* Don't really shutdown, only warn.*/
4404 - case 'r': /* Automatic reboot */
4405 - down_level[0] = '6';
4407 - case 'h': /* Halt after shutdown */
4408 - down_level[0] = '0';
4410 - case 'f': /* Don't perform fsck after next boot */
4413 - case 'F': /* Force fsck after next boot */
4416 - case 'n': /* Don't switch runlevels. */
4419 - case 't': /* Delay between TERM and KILL */
4422 - case 'y': /* Ignored for sysV compatibility */
4424 - case 'g': /* sysv style to specify time. */
4426 - down_level[0] = '0';
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) {
4435 + halttype = "HALT";
4438 + halttype = "POWERDOWN";
4440 + case 'a': /* Access control. */
4443 + case 'c': /* Cancel an already running shutdown. */
4446 + case 'k': /* Don't really shutdown, only warn.*/
4449 + case 'r': /* Automatic reboot */
4450 + down_level[0] = '6';
4452 + case 'h': /* Halt after shutdown */
4453 + down_level[0] = '0';
4455 + case 'f': /* Don't perform fsck after next boot */
4458 + case 'F': /* Force fsck after next boot */
4461 + case 'n': /* Don't switch runlevels. */
4464 + case 't': /* Delay between TERM and KILL */
4467 + case 'y': /* Ignored for sysV compatibility */
4469 + case 'g': /* sysv style to specify time. */
4472 + case 'i': /* Level to go to. */
4473 + if (!strchr("0156aAbBcCsS", optarg[0])) {
4475 + "shutdown: `%s': bad runlevel\n",
4479 - down_level[0] = optarg[0];
4488 + down_level[0] = optarg[0];
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) {
4501 - /* Read /etc/shutdown.allow. */
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);
4509 - if (i < 32) downusers[i] = 0;
4511 + /* Read /etc/shutdown.allow. */
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);
4519 + if (i < 32) downusers[i] = 0;
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) {
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;
4541 - if ((st.st_rdev & 0xFFC0) != 0x0400) continue;
4542 + if ((st.st_rdev & 0xFFC0) != 0x0400) continue;
4544 - /* Root is always OK. */
4545 - if (strcmp(ut->ut_user, "root") == 0) {
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) {
4561 - /* See if user was allowed. */
4563 - if ((fp = fopen(CONSOLE, "w")) != NULL) {
4564 - fprintf(fp, "\rshutdown: no authorized users logged in.\r\n");
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,
4579 - /* Read pid of running shutdown from a file */
4580 - if ((fp = fopen(SDPID, "r")) != NULL) {
4581 - fscanf(fp, "%d", &pid);
4584 + /* See if user was allowed. */
4586 + if ((fp = fopen(CONSOLE, "w")) != NULL) {
4587 + fprintf(fp, "\rshutdown: no authorized users "
4588 + "logged in.\r\n");
4595 - /* Read remaining words, skip time if needed. */
4597 - for(c = optind + (!cancel && !when); c < argc; c++) {
4598 - if (strlen(message) + strlen(argv[c]) + 4 > MESSAGELEN)
4600 - strcat(message, argv[c]);
4601 - strcat(message, " ");
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);
4610 - /* See if we want to run or cancel. */
4613 - fprintf(stderr, "shutdown: cannot find pid of running shutdown.\n");
4615 + /* Read remaining words, skip time if needed. */
4617 + for(c = optind + (!cancel && !when); c < argc; c++) {
4618 + if (strlen(message) + strlen(argv[c]) + 4 > MESSAGELEN)
4620 + strcat(message, argv[c]);
4621 + strcat(message, " ");
4623 - if (kill(pid, SIGINT) < 0) {
4624 - fprintf(stderr, "shutdown: not running.\n");
4626 + if (message[0]) strcat(message, "\r\n");
4628 + /* See if we want to run or cancel. */
4631 + fprintf(stderr, "shutdown: cannot find pid "
4632 + "of running shutdown.\n");
4635 + init_setenv("INIT_HALT", NULL);
4636 + if (kill(pid, SIGINT) < 0) {
4637 + fprintf(stderr, "shutdown: not running.\n");
4640 + if (message[0]) wall(message, 1, 0);
4643 - if (message[0]) wall(message, 1, 0);
4647 - /* Check syntax. */
4648 - if (when == NULL) {
4649 - if (optind == argc) usage();
4650 - when = argv[optind++];
4652 + /* Check syntax. */
4653 + if (when == NULL) {
4654 + if (optind == argc) usage();
4655 + when = argv[optind++];
4658 - /* See if we are already running. */
4659 - if (pid > 0 && kill(pid, 0) == 0) {
4660 - fprintf(stderr, "\rshutdown: already running.\r\n");
4663 + /* See if we are already running. */
4664 + if (pid > 0 && kill(pid, 0) == 0) {
4665 + fprintf(stderr, "\rshutdown: already running.\r\n");
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");
4674 + /* Extra check. */
4675 + if (doself && down_level[0] != '0' && down_level[0] != '6') {
4677 + "shutdown: can use \"-n\" for halt or reboot only.\r\n");
4681 - /* Tell users what we're gonna do. */
4682 - switch(down_level[0]) {
4684 - strcpy(newstate, "for system halt");
4687 - strcpy(newstate, "for reboot");
4690 - strcpy(newstate, "to maintenance mode");
4693 - sprintf(newstate, "to runlevel %s", down_level);
4696 + /* Tell users what we're gonna do. */
4697 + switch(down_level[0]) {
4699 + strcpy(newstate, "for system halt");
4702 + strcpy(newstate, "for reboot");
4705 + strcpy(newstate, "to maintenance mode");
4708 + sprintf(newstate, "to runlevel %s", down_level);
4712 - /* Create a new PID file. */
4715 - if ((fp = fopen(SDPID, "w")) != NULL) {
4716 - fprintf(fp, "%d\n", getpid());
4718 - } else if (errno != EROFS)
4719 - fprintf(stderr, "shutdown: warning: cannot open %s\n", SDPID);
4720 + /* Create a new PID file. */
4723 + if ((fp = fopen(SDPID, "w")) != NULL) {
4724 + fprintf(fp, "%d\n", getpid());
4726 + } else if (errno != EROFS)
4727 + fprintf(stderr, "shutdown: warning: cannot open %s\n", SDPID);
4730 - * Catch some common signals.
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);
4739 + * Catch some common signals.
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);
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);
4755 - /* Go to the root directory */
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 */
4761 + if (fastboot) close(open(FASTBOOT, O_CREAT | O_RDWR, 0644));
4762 + if (forcefsck) close(open(FORCEFSCK, O_CREAT | O_RDWR, 0644));
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++;
4771 - /* Decode shutdown time. */
4772 - for (sp = when; *sp; sp++) {
4773 - if (*sp != ':' && (*sp < '0' || *sp > '9'))
4776 - if (strchr(when, ':') == NULL) {
4777 - /* Time in minutes. */
4779 - if (wt == 0 && when[0] != '0') usage();
4781 - /* Time in hh:mm format. */
4782 - if (sscanf(when, "%d:%2d", &hours, &mins) != 2) usage();
4783 - if (hours > 23 || mins > 59) usage();
4785 - lt = localtime(&t);
4786 - wt = (60*hours + mins) - (60*lt->tm_hour + lt->tm_min);
4787 - if (wt < 0) wt += 1440;
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'))
4796 + if (strchr(when, ':') == NULL) {
4797 + /* Time in minutes. */
4799 + if (wt == 0 && when[0] != '0') usage();
4801 + /* Time in hh:mm format. */
4802 + if (sscanf(when, "%d:%2d", &hours, &mins) != 2) usage();
4803 + if (hours > 23 || mins > 59) usage();
4805 + lt = localtime(&t);
4806 + wt = (60*hours + mins) - (60*lt->tm_hour + lt->tm_min);
4807 + if (wt < 0) wt += 1440;
4809 + /* Shutdown NOW if time == 0 */
4810 + if (wt == 0) shutdown(halttype);
4812 - /* Give warnings on regular intervals and finally shutdown. */
4813 - if (wt < 15 && !needwarning(wt)) warn(wt);
4815 - if (wt <= 5 && !didnolog) {
4818 + /* Give warnings on regular intervals and finally shutdown. */
4819 + if (wt < 15 && !needwarning(wt)) warn(wt);
4821 + if (wt <= 5 && !didnolog) {
4825 + if (needwarning(wt)) warn(wt);
4829 - if (needwarning(wt)) warn(wt);
4834 - return(0); /* Never happens */
4835 + shutdown(halttype);
4837 + return 0; /* Never happens */
4839 Binary files sysvinit-2.85/src/shutdown.o and sysvinit-2.86/src/shutdown.o differ
4840 Binary files sysvinit-2.85/src/sulogin and sysvinit-2.86/src/sulogin differ
4841 diff -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
4845 * encrypted root password is "x" the shadow
4846 * password will be used.
4848 - * Version: @(#)sulogin 2.85 14-Apr-2003 miquels@cistron.nl
4849 + * Version: @(#)sulogin 2.85-3 23-Apr-2003 miquels@cistron.nl
4854 #define F_SHADOW "/etc/shadow"
4855 #define BINSH "/bin/sh"
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";
4869 * Fix the tty modes and set reasonable defaults.
4871 printf("Give root password for maintenance\n");
4873 printf("Press enter for maintenance\n");
4874 - printf("(or type Control-D for normal startup): ");
4875 + printf("(or type Control-D to continue): ");
4879 Binary files sysvinit-2.85/src/sulogin.o and sysvinit-2.86/src/sulogin.o differ
4880 Binary files sysvinit-2.85/src/utmp.o and sysvinit-2.86/src/utmp.o differ