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