Merge branch 'beta'
This commit is contained in:
commit
c0f5983562
8
Makefile
8
Makefile
@ -7,6 +7,7 @@ SVLOGIN=$(shell svn info | sed -rn '/Repository Root:/{ s|.*//(.*)\@.*|\1|p }')
|
||||
override TMP:=$(shell mktemp -d $(VERSION).XXXXXXXX)
|
||||
override TARBALL:=$(TMP)/$(PACKAGE)-$(VERSION).tar.bz2
|
||||
override SFTPBATCH:=$(TMP)/$(VERSION)-sftpbatch
|
||||
SOURCES=contrib COPYING COPYRIGHT doc Makefile man README src
|
||||
|
||||
dist: $(TARBALL)
|
||||
@cp $(TARBALL) .
|
||||
@ -31,9 +32,10 @@ $(TARBALL).sig: $(TARBALL)
|
||||
@gpg -q -ba --use-agent -o $@ $<
|
||||
|
||||
$(TARBALL): $(TMP)/$(PACKAGE)-$(VERSION)
|
||||
@tar --bzip2 --owner=nobody --group=nogroup -cf $@ -C $(TMP) $(PACKAGE)-$(VERSION)
|
||||
@tar --exclude=.git --bzip2 --owner=nobody --group=nogroup -cf $@ -C $(TMP) $(PACKAGE)-$(VERSION)
|
||||
|
||||
$(TMP)/$(PACKAGE)-$(VERSION): .svn
|
||||
svn export . $@
|
||||
$(TMP)/$(PACKAGE)-$(VERSION):
|
||||
@mkdir $(TMP)/$(PACKAGE)-$(VERSION)
|
||||
@cp -R $(SOURCES) $(TMP)/$(PACKAGE)-$(VERSION)/
|
||||
@chmod -R a+r,u+w,og-w $@
|
||||
@find $@ -type d | xargs -r chmod a+rx,u+w,og-w
|
||||
|
@ -1,5 +1,87 @@
|
||||
sysvinit (2.89) UNRELEASED; urgency=low
|
||||
|
||||
[ Jesse Smith ]
|
||||
* Fixed Clang compiler warning regarding variable data parameters to sprintf().
|
||||
* Updated top-level Makefile to work with git repo instead of old svn repo.
|
||||
* Removed unused variables and findtty() function in bootlogd
|
||||
* Add checks to return code for fscanf() called in init.c.
|
||||
This mostly just cleans up compiler warnings.
|
||||
* Perform error check on setuid() call as suggested in manual page.
|
||||
* Fix typo in killall5.c
|
||||
Move initscript sample file from "src" to "doc" directory and updated
|
||||
Makefile to match.
|
||||
* Allow multiple console output
|
||||
When booting a kernel with multiple serial console support, or multuiple
|
||||
console arguments ala "console=tty1 console=ttyS0,9600" the kernel will output
|
||||
messages to all consoles, init however will not. It will only send output to,
|
||||
and accept input from, the last of the consoles.
|
||||
This patch fixes it.
|
||||
(Patch provided by Martin Buck.)
|
||||
* Added Patch from Debian developer Mats Erik Andersson to make
|
||||
ioctl work on GNU/kFreeBSD. Patches bootlogd.
|
||||
* Added Robert Millan's Debian patch to set TERM variable to xterm (instead
|
||||
of cons25) when running on GNU/kFreeBSD.
|
||||
* Added Robert Millan's Debian patch to use /run/initctl as the named
|
||||
pipe for communicating. This works around a limitation on the kFreeBSD
|
||||
branch which prevents us from using /dev/initctl for pipes.
|
||||
* Confirmed we have applied Guillem Jover's patch to make
|
||||
ifdown work on FreeBSD.
|
||||
* Confirmed we have Debian patch to fix enabling SELinux.
|
||||
(Credit to Petter Reinholdtsen)
|
||||
* Confirmed we have Debian patch to make sure utf-8 flag is not cleared from tty.
|
||||
(Credit to Samuel Thibault)
|
||||
* Confirmed we have Roger Leigh's Makefile patch to allow building
|
||||
with multiarch libcrypt.
|
||||
* Applied Justus Winter's symlink patch to make sure killall5
|
||||
builds and runs on Hurd.
|
||||
* Confirmed we have Werner Fink's PATH_MAX patch for getting
|
||||
killall5 to build on Hurd.
|
||||
* Made sure we have Petter Reinholdtsen's patch to init.c which
|
||||
allows init to build on GNU/kFreeBSD despite missing VSWTC.
|
||||
* Dropping Debian patch to use /run/nologin instead of /etc/nologin in paths.h.
|
||||
Seems every distribution uses a different location. Oracle uses /etc/nologin,
|
||||
CentOS seems to use /var/run/nologin.
|
||||
We will use /etc/nologin and let distros patch to suit their own preference.
|
||||
* Updated halt.8 man page with corrections from
|
||||
Christoph Anton Mitterer.
|
||||
* Confirme we have applied patch from Bjarni Ingi Gislason
|
||||
which fixes typo in fstab-decode man page.
|
||||
* Applied Debian patch to allow init to build on GNU Hurd.
|
||||
(Credit: Roger Leigh)
|
||||
* Confirmed we have Debian patch from developer Johannes Truschnigg
|
||||
which informs the user of field size limit.
|
||||
* Applied patch from Debian to the init manual page (init.8)
|
||||
to better address runlevels. (Author unknown)
|
||||
* The pidof command used to discover the correct PID of
|
||||
a process even if the wrong path was given. For example
|
||||
pidof /wrongpath/sleep would find the PID of a command run as "sleep".
|
||||
This bug was reported on Launchpad for Ubuntu and on Savannah.
|
||||
https://bugs.launchpad.net/ubuntu/+source/sysvinit/+bug/1546126
|
||||
http://savannah.nongnu.org/bugs/?47196
|
||||
This bug appears to have been fixed in the development branch,
|
||||
allowing these bugs to be tested/closed.
|
||||
* Confirmed Savannah bug #37114 (mountpoint does not detect
|
||||
mount points using --bind on same file system) still exists,
|
||||
but fixed in Debian and Red Hat.
|
||||
Considering this bug closed since distributions are using
|
||||
util-linux's mountpoint program and ours is no longer
|
||||
built/used by default.
|
||||
Considered importing util-linux mountpoint but that would duplicate
|
||||
effort and pull in a new dependency on libmount.
|
||||
* Problem with pidof breaks after prelink (Savannah bug #34992)
|
||||
fixed. Patch supplied by Dave Dykstra.
|
||||
* Patch to automatically spawn agetty on kernel consoles
|
||||
The feature is useful for developers and admins that occasionally need
|
||||
to boot with e.g. console=ttyS0.
|
||||
The built in default can be overridden via inittab for each device. An
|
||||
entry like "S0::off:" turns off the getty on ttyS0.
|
||||
characters in log file. Also makes parsing easier.
|
||||
This should close Savannah bug report 36528.
|
||||
http://savannah.nongnu.org/bugs/?36528
|
||||
* Applied patches provided in Savannah bug report 49991. Fix tabs in
|
||||
bootlogd and avoid printing unitialized "buf" variable when
|
||||
consolename() fails.
|
||||
|
||||
[ Werner Fink ]
|
||||
* Do not forget room for last NULL of new environment (was
|
||||
local bug 35866)
|
||||
|
@ -66,7 +66,11 @@ You might want to create a file called "/etc/shutdown.allow". Read the
|
||||
manual page on shutdown to find out more about this.
|
||||
|
||||
Running from a read-only file system (CDROM?):
|
||||
<<<<<<< HEAD
|
||||
* All communication to init goes through the FIFO /run/initctl.
|
||||
=======
|
||||
o All communication to init goes through the FIFO /run/initctl.
|
||||
>>>>>>> beta
|
||||
There should be no problem using a read-only root file system
|
||||
IF you use a Linux kernel > 1.3.66. Older kernels don't allow
|
||||
writing to a FIFO on a read-only file system.
|
||||
|
@ -51,7 +51,7 @@ halt, reboot, poweroff \- stop the system.
|
||||
.\"}}}
|
||||
.\"{{{ Description
|
||||
.SH DESCRIPTION
|
||||
\fBHalt\fP notes that the system is being brought down in the file
|
||||
\fBhalt\fP notes that the system is being brought down in the file
|
||||
\fI/var/log/wtmp\fP, and then either tells the kernel to halt, reboot or
|
||||
power-off the system.
|
||||
.PP
|
||||
@ -68,12 +68,12 @@ and 6, that is when the systems shutdown scripts are being run.
|
||||
.SH OPTIONS
|
||||
.IP \fB\-n\fP
|
||||
Don't sync before reboot or halt. Note that the kernel and storage
|
||||
drivers may still sync.
|
||||
drivers may still sync. This implies \fB\-d\fP.
|
||||
.IP \fB\-w\fP
|
||||
Don't actually reboot or halt but only write the wtmp record
|
||||
(in the \fI/var/log/wtmp\fP file).
|
||||
.IP \fB\-d\fP
|
||||
Don't write the wtmp record. The \fB\-n\fP flag implies \fB\-d\fP.
|
||||
Don't write the wtmp record.
|
||||
.IP \fB\-f\fP
|
||||
Force halt or reboot, don't call \fBshutdown\fP(8).
|
||||
.IP \fB\-i\fP
|
||||
|
110
man/init.8
110
man/init.8
@ -56,21 +56,34 @@ A \fIrunlevel\fP is a software configuration of the system which allows
|
||||
only a selected group of processes to exist. The processes spawned by
|
||||
\fBinit\fP for each of these runlevels are defined in the
|
||||
\fB/etc/inittab\fP file. \fBInit\fP can be in one of eight runlevels:
|
||||
\fB0\(en6\fP and \fBS\fP or \fBs\fP. The runlevel is
|
||||
\fB0\(en6\fP and \fBS\fP (a.k.a. \fBs\fP). The runlevel is
|
||||
changed by having a privileged user run \fBtelinit\fP, which sends
|
||||
appropriate signals to \fBinit\fP, telling it which runlevel to change
|
||||
to.
|
||||
.PP
|
||||
Runlevels \fB0\fP, \fB1\fP, and \fB6\fP are reserved. Runlevel 0 is used to
|
||||
halt the system, runlevel 6 is used to reboot the system, and runlevel
|
||||
1 is used to get the system down into single user mode. Runlevel \fBS\fP
|
||||
is not really meant to be used directly, but more for the scripts that are
|
||||
executed when entering runlevel 1. For more information on this,
|
||||
Runlevels \fBS\fP, \fB0\fP, \fB1\fP, and \fB6\fP are reserved.
|
||||
Runlevel S is used to initialize the system on boot.
|
||||
When starting runlevel S (on boot)
|
||||
or runlevel 1 (switching from a multi-user runlevel)
|
||||
the system is entering ``single-user mode'', after which the
|
||||
current runlevel is S.
|
||||
Runlevel 0 is used to halt the system;
|
||||
runlevel 6 is used to reboot the system.
|
||||
.PP
|
||||
After booting through S the system automatically enters one of
|
||||
the multi-user runlevels 2 through 5, unless there was some
|
||||
problem that needs to be fixed by the administrator in
|
||||
single-user mode.
|
||||
Normally after entering single-user mode
|
||||
the administrator performs maintenance and then reboots the system.
|
||||
.PP
|
||||
For more information,
|
||||
see the manpages for \fBshutdown\fP(8) and \fBinittab\fP(5).
|
||||
.PP
|
||||
Runlevels 7\(en9 are also valid, though not really documented.
|
||||
This is because "traditional" Unix variants don't use them.
|
||||
In case you're curious, runlevels \fIS\fP and \fIs\fP are in fact the same.
|
||||
Runlevels 7-9 are also valid, though not really documented. This is
|
||||
because "traditional" Unix variants don't use them.
|
||||
.PP
|
||||
Runlevels \fIS\fP and \fIs\fP are the same.
|
||||
Internally they are aliases for the same runlevel.
|
||||
.\"}}}
|
||||
.PP
|
||||
@ -82,9 +95,10 @@ determines the initial runlevel of the system. If there is no such
|
||||
entry (or no \fB/etc/inittab\fP at all), a runlevel must be
|
||||
entered at the system console.
|
||||
.PP
|
||||
Runlevel \fBS\fP or \fBs\fP bring the system to single user mode
|
||||
and do not require an \fB/etc/inittab\fP file. In single user mode,
|
||||
\fB/sbin/sulogin\fP is invoked on \fB/dev/console\fP.
|
||||
Runlevel \fBS\fP or \fBs\fP initialize the system
|
||||
and do not require an \fB/etc/inittab\fP file.
|
||||
.PP
|
||||
In single user mode, \fB/sbin/sulogin\fP is invoked on \fB/dev/console\fP.
|
||||
.PP
|
||||
When entering single user mode, \fBinit\fP initializes the consoles
|
||||
\fBstty\fP settings to sane values. Clocal mode is set. Hardware
|
||||
@ -110,7 +124,7 @@ When one of the above three conditions occurs, it re-examines
|
||||
the \fB/etc/inittab\fP file. New entries can be added to this file at
|
||||
any time. However, \fBinit\fP still waits for one of the above three
|
||||
conditions to occur. To provide for an instantaneous response, the
|
||||
\fBtelinit Q\fP or \fBq\fP command can wake up \fBinit\fP to re-examine the
|
||||
\fBtelinit Q\fP or \fBq\fP command can wake up \fBinit\fP to re-examine (reload) the
|
||||
\fB/etc/inittab\fP file.
|
||||
.PP
|
||||
If \fBinit\fP is not in single user mode and receives a powerfail
|
||||
@ -130,7 +144,7 @@ letters \fBF\fP, \fBO\fP or \fBL\fP, init will behave as if it has read
|
||||
the letter \fBF\fP.
|
||||
.PP
|
||||
Usage of \fBSIGPWR\fP and \fB/etc/powerstatus\fP is discouraged. Someone
|
||||
wanting to interact with \fBinit\fP should use the \fB/dev/initctl\fP
|
||||
wanting to interact with \fBinit\fP should use the \fB/run/initctl\fP
|
||||
control channel - see the source code of the \fBsysvinit\fP package
|
||||
for more documentation about this.
|
||||
.PP
|
||||
@ -160,19 +174,18 @@ tell \fBinit\fP to re-examine the \fB/etc/inittab\fP file.
|
||||
.IP "\fBS\fP or \fBs\fP"
|
||||
tell \fBinit\fP to switch to single user mode.
|
||||
.IP "\fBU\fP or \fBu\fP"
|
||||
tell \fBinit\fP to re-execute itself (preserving the state).
|
||||
No re-examining of
|
||||
\fB/etc/inittab\fP file happens.
|
||||
Run level should be one of \fBSs0123456\fP otherwise request would be
|
||||
silently ignored.
|
||||
tell \fBinit\fP to re-execute itself (preserving the state). No re-examining of
|
||||
\fB/etc/inittab\fP file happens. Run level should be one of
|
||||
\fBSs0123456\fP
|
||||
otherwise request would be silently ignored.
|
||||
.PP
|
||||
\fBtelinit\fP can tell \fBinit\fP how long it should wait
|
||||
between sending processes the SIGTERM and SIGKILL signals. The default
|
||||
is 5 seconds, but this can be changed with the \fB\-t\fP option.
|
||||
is 5 seconds, but this can be changed with the \fB-t\fP option.
|
||||
.PP
|
||||
\fBtelinit \-e\fP tells \fBinit\fP to change the environment
|
||||
\fBtelinit -e\fP tells \fBinit\fP to change the environment
|
||||
for processes it spawns.
|
||||
The argument of \fB\-e\fP is either of the form \fIVAR\fP=\fIVAL\fP
|
||||
The argument of \fB-e\fP is either of the form \fIVAR\fP=\fIVAL\fP
|
||||
which sets variable \fIVAR\fP to value \fIVAL\fP,
|
||||
or of the form \fIVAR\fP
|
||||
(without an equality sign)
|
||||
@ -202,16 +215,15 @@ The system console. This is really inherited from the kernel; however
|
||||
if it is not set \fBinit\fP will set it to \fB/dev/console\fP by default.
|
||||
.SH BOOTFLAGS
|
||||
It is possible to pass a number of flags to \fBinit\fP from the
|
||||
boot monitor (eg.\& LILO).
|
||||
\fBInit\fP accepts the following flags:
|
||||
boot monitor (eg. LILO). \fBInit\fP accepts the following flags:
|
||||
.TP 0.5i
|
||||
.B -s, S, single
|
||||
Single user mode boot.
|
||||
In this mode \fI/etc/inittab\fP is examined and the bootup rc scripts
|
||||
are usually run before the single user mode shell is started.
|
||||
Single user mode boot. In this mode \fI/etc/inittab\fP is
|
||||
examined and the bootup rc scripts are usually run before
|
||||
the single user mode shell is started.
|
||||
.PP
|
||||
.TP 0.5i
|
||||
.B 1\(en5
|
||||
.B 1-5
|
||||
Runlevel to boot into.
|
||||
.PP
|
||||
.TP 0.5i
|
||||
@ -224,25 +236,23 @@ other startup scripts.
|
||||
The LILO boot loader adds the word "auto" to the command line if it
|
||||
booted the kernel with the default command line (without user intervention).
|
||||
If this is found \fBinit\fP sets the "AUTOBOOT" environment
|
||||
variable to "yes".
|
||||
Note that you cannot use this for any security measures - of course
|
||||
the user could specify "auto" or \-a on the command line manually.
|
||||
variable to "yes". Note that you cannot use this for any security
|
||||
measures - of course the user could specify "auto" or \-a on the
|
||||
command line manually.
|
||||
.PP
|
||||
.TP 0.5i
|
||||
.BI "\-z " xxx
|
||||
The argument to \fB\-z\fP is ignored.
|
||||
You can use this to expand the command line a bit, so that it takes
|
||||
some more space on the stack.
|
||||
\fBInit\fP can then manipulate the command line so that \fBps\fP(1)
|
||||
shows the current runlevel.
|
||||
|
||||
.BI "-z " xxx
|
||||
The argument to \fB-z\fP is ignored. You can use this to expand the command
|
||||
line a bit, so that it takes some more space on the stack. \fBInit\fP
|
||||
can then manipulate the command line so that \fBps\fP(1) shows
|
||||
the current runlevel.
|
||||
.PP
|
||||
.SH INTERFACE
|
||||
Init listens on a \fIfifo\fP in /dev, \fI/dev/initctl\fP, for messages.
|
||||
\fBTelinit\fP uses this to communicate with init.
|
||||
The interface is not very well documented or finished.
|
||||
Those interested should study the \fIinitreq.h\fP file in the
|
||||
\fIsrc/\fP subdirectory of the \fBinit\fP source code tar archive.
|
||||
Init listens on a \fIfifo\fP in /dev, \fI/run/initctl\fP, for messages.
|
||||
\fBTelinit\fP uses this to communicate with init. The interface is not
|
||||
very well documented or finished. Those interested should study the
|
||||
\fIinitreq.h\fP file in the \fIsrc/\fP subdirectory of the \fBinit\fP
|
||||
source code tar archive.
|
||||
.SH SIGNALS
|
||||
Init reacts to several signals:
|
||||
.TP 0.5i
|
||||
@ -252,7 +262,7 @@ Has the same effect as \fBtelinit q\fP.
|
||||
.TP 0.5i
|
||||
.B SIGUSR1
|
||||
On receipt of this signals, init closes and re-opens its control fifo,
|
||||
\fB/dev/initctl\fP. Useful for bootscripts when /dev is remounted.
|
||||
\fB/run/initctl\fP. Useful for bootscripts when /dev is remounted.
|
||||
.TP 0.5i
|
||||
.B SIGINT
|
||||
Normally the kernel sends this signal to init when CTRL-ALT-DEL is
|
||||
@ -277,7 +287,7 @@ file in the directory \fI/etc/init.d\fP explaining how these scripts work.
|
||||
/dev/console
|
||||
/var/run/utmp
|
||||
/var/log/wtmp
|
||||
/dev/initctl
|
||||
/run/initctl
|
||||
.fi
|
||||
.\"}}}
|
||||
.\"{{{ Warnings
|
||||
@ -287,6 +297,14 @@ remain in the same process group which was originally created
|
||||
for them. If the processes change their group, \fBinit\fP can't
|
||||
kill them and you may end up with two processes reading from one
|
||||
terminal line.
|
||||
.PP
|
||||
On a Debian system, entering runlevel 1 causes all processes
|
||||
to be killed except for kernel threads and the script that does
|
||||
the killing and other processes in its session.
|
||||
As a consequence of this, it isn't safe to return from runlevel 1
|
||||
to a multi-user runlevel: daemons that were started in runlevel S
|
||||
and are needed for normal operation are no longer running.
|
||||
The system should be rebooted.
|
||||
.\"}}}
|
||||
.\"{{{ Diagnostics
|
||||
.SH DIAGNOSTICS
|
||||
@ -309,7 +327,7 @@ page by Michael Haardt (u31b3hs@pool.informatik.rwth-aachen.de).
|
||||
.BR login (1),
|
||||
.BR sh (1),
|
||||
.BR runlevel (8),
|
||||
.BR shutdown (8),
|
||||
.BR shutdown(8),
|
||||
.BR kill (1),
|
||||
.BR inittab (5),
|
||||
.BR initscript (5),
|
||||
|
11
src/Makefile
11
src/Makefile
@ -11,6 +11,7 @@
|
||||
CPPFLAGS =
|
||||
CFLAGS ?= -ansi -O2 -fomit-frame-pointer -fstack-protector
|
||||
override CFLAGS += -W -Wall -Wunreachable-code -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -D_XOPEN_SOURCE -D_GNU_SOURCE
|
||||
override CFLAGS += $(shell getconf LFS_CFLAGS)
|
||||
STATIC =
|
||||
MANDB := s@^\('\\\\\"\)[^\*-]*-\*- coding: [^[:blank:]]\+ -\*-@\1@
|
||||
|
||||
@ -187,7 +188,7 @@ install:
|
||||
$(INSTALL_EXEC) $$i $(ROOT)/usr/bin/ ; \
|
||||
done
|
||||
# $(INSTALL_DIR) $(ROOT)/etc/
|
||||
# $(INSTALL_EXEC) initscript.sample $(ROOT)/etc/
|
||||
# $(INSTALL_EXEC) ../doc/initscript.sample $(ROOT)/etc/
|
||||
ln -sf halt $(ROOT)/sbin/reboot
|
||||
ln -sf halt $(ROOT)/sbin/poweroff
|
||||
ln -sf init $(ROOT)/sbin/telinit
|
||||
@ -216,8 +217,8 @@ ifeq ($(ROOT),)
|
||||
#
|
||||
# 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
|
||||
@if [ ! -p /run/initctl ]; then \
|
||||
echo "Creating /run/initctl"; \
|
||||
rm -f /run/initctl; \
|
||||
mknod -m 600 /run/initctl p; fi
|
||||
endif
|
||||
|
322
src/bootlogd.c
322
src/bootlogd.c
@ -57,6 +57,7 @@
|
||||
char *Version = "@(#) bootlogd 2.86 03-Jun-2004 miquels@cistron.nl";
|
||||
|
||||
#define LOGFILE "/var/log/boot"
|
||||
#define MAX_CONSOLES 16
|
||||
|
||||
char ringbuf[32768];
|
||||
char *endptr = ringbuf + sizeof(ringbuf);
|
||||
@ -68,10 +69,10 @@ int didnl = 1;
|
||||
int createlogfile = 0;
|
||||
int syncalot = 0;
|
||||
|
||||
struct line {
|
||||
char buf[256];
|
||||
int pos;
|
||||
} line;
|
||||
struct real_cons {
|
||||
char name[1024];
|
||||
int fd;
|
||||
};
|
||||
|
||||
/*
|
||||
* Console devices as listed on the kernel command line and
|
||||
@ -108,62 +109,68 @@ void handler(int sig)
|
||||
/*
|
||||
* Scan /dev and find the device name.
|
||||
*/
|
||||
static int findtty(char *res, const char *startdir, size_t rlen, dev_t dev)
|
||||
/*
|
||||
This function does not appear to be called anymore. Commenting it
|
||||
out for now, can probably be removed entirely in the future.
|
||||
|
||||
static int findtty(char *res, const char *startdir, int rlen, dev_t dev)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
struct stat st;
|
||||
int r = -1;
|
||||
char *olddir = getcwd(NULL, 0);
|
||||
|
||||
if ((dir = opendir(startdir)) == NULL) {
|
||||
if (chdir(startdir) < 0 || (dir = opendir(".")) == NULL) {
|
||||
int msglen = strlen(startdir) + 11;
|
||||
char *msg = malloc(msglen);
|
||||
snprintf(msg, msglen, "bootlogd: %s", startdir);
|
||||
perror(msg);
|
||||
free(msg);
|
||||
chdir(olddir);
|
||||
return -1;
|
||||
}
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
struct stat st;
|
||||
int pathlen = strlen(startdir) + strlen(ent->d_name) + 2;
|
||||
char *path = malloc(pathlen);
|
||||
snprintf(path, pathlen, "%s/%s", startdir, ent->d_name);
|
||||
|
||||
if (lstat(path, &st) != 0) {
|
||||
free(path);
|
||||
if (lstat(ent->d_name, &st) != 0)
|
||||
continue;
|
||||
}
|
||||
if (S_ISDIR(st.st_mode)
|
||||
&& 0 != strcmp(".", ent->d_name)
|
||||
&& 0 != strcmp("..", ent->d_name)) {
|
||||
char *path = malloc(rlen);
|
||||
snprintf(path, rlen, "%s/%s", startdir, ent->d_name);
|
||||
r = findtty(res, path, rlen, dev);
|
||||
if (0 == r) { /* device found, return */
|
||||
free(path);
|
||||
free(path);
|
||||
if (0 == r) {
|
||||
closedir(dir);
|
||||
chdir(olddir);
|
||||
return 0;
|
||||
}
|
||||
free(path);
|
||||
continue;
|
||||
}
|
||||
free(path);
|
||||
path = NULL;
|
||||
if (!S_ISCHR(st.st_mode))
|
||||
continue;
|
||||
if (st.st_rdev == dev) {
|
||||
if ( (strlen(ent->d_name) + strlen(startdir) + 1) >= rlen) {
|
||||
if ( (int) (strlen(ent->d_name) + strlen(startdir) + 1) >= rlen) {
|
||||
fprintf(stderr, "bootlogd: console device name too long\n");
|
||||
closedir(dir);
|
||||
chdir(olddir);
|
||||
return -1;
|
||||
} else {
|
||||
snprintf(res, rlen, "%s/%s", startdir, ent->d_name);
|
||||
closedir(dir);
|
||||
chdir(olddir);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
chdir(olddir);
|
||||
return r;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* For some reason, openpty() in glibc sometimes doesn't
|
||||
@ -209,7 +216,7 @@ int findpty(int *master, int *slave, char *name)
|
||||
* 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, size_t rlen)
|
||||
int isconsole(char *s, char *res, int rlen)
|
||||
{
|
||||
struct consdev *c;
|
||||
int l, sl, i, fd;
|
||||
@ -236,50 +243,21 @@ int isconsole(char *s, char *res, size_t rlen)
|
||||
}
|
||||
|
||||
/*
|
||||
* Find out the _real_ console. Assume that stdin is connected to
|
||||
* Find out the _real_ console(s). Assume that stdin is connected to
|
||||
* the console device (/dev/console).
|
||||
*/
|
||||
int consolename(char *res, size_t rlen)
|
||||
int consolenames(struct real_cons *cons, int max_consoles)
|
||||
{
|
||||
#ifdef TIOCGDEV
|
||||
unsigned int kdev;
|
||||
/* This appears to be unused. unsigned int kdev; */
|
||||
#endif
|
||||
struct stat st;
|
||||
int n;
|
||||
#ifdef __linux__
|
||||
struct stat st, st2;
|
||||
char buf[256];
|
||||
char *p;
|
||||
struct stat st2;
|
||||
int didmount = 0;
|
||||
int r;
|
||||
int n;
|
||||
int fd;
|
||||
#endif
|
||||
|
||||
fstat(0, &st);
|
||||
if (major(st.st_rdev) != 5 || minor(st.st_rdev) != 1) {
|
||||
/*
|
||||
* Old kernel, can find real device easily.
|
||||
*/
|
||||
int r = findtty(res, "/dev", rlen, st.st_rdev);
|
||||
if (0 != r)
|
||||
fprintf(stderr, "bootlogd: cannot find console device "
|
||||
"%d:%d under /dev\n", major(st.st_rdev), minor(st.st_rdev));
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef TIOCGDEV
|
||||
# ifndef ENOIOCTLCMD
|
||||
# define ENOIOCTLCMD 515
|
||||
# endif
|
||||
if (ioctl(0, TIOCGDEV, &kdev) == 0) {
|
||||
int r = findtty(res, "/dev", rlen, (dev_t)kdev);
|
||||
if (0 != r)
|
||||
fprintf(stderr, "bootlogd: cannot find console device "
|
||||
"%d:%d under /dev\n", major(kdev), minor(kdev));
|
||||
return r;
|
||||
}
|
||||
if (errno != ENOIOCTLCMD) return -1;
|
||||
#endif
|
||||
int considx, num_consoles = 0;
|
||||
|
||||
#ifdef __linux__
|
||||
/*
|
||||
@ -288,7 +266,7 @@ int consolename(char *res, size_t rlen)
|
||||
stat("/", &st);
|
||||
if (stat("/proc", &st2) < 0) {
|
||||
perror("bootlogd: /proc");
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
if (st.st_dev == st2.st_dev) {
|
||||
if (mount("proc", "/proc", "proc", 0, NULL) < 0) {
|
||||
@ -298,22 +276,21 @@ int consolename(char *res, size_t rlen)
|
||||
didmount = 1;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
r = -1;
|
||||
n = -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;
|
||||
buf[sizeof(buf)-1] = 0; /* enforce null termination */
|
||||
} else
|
||||
if ((n = read(fd, buf, sizeof(buf) - 1)) < 0)
|
||||
perror("bootlogd: /proc/cmdline");
|
||||
close(fd);
|
||||
}
|
||||
if (didmount) umount("/proc");
|
||||
|
||||
if (r < 0) return r;
|
||||
|
||||
if (n < 0) return 0;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* OK, so find console= in /proc/cmdline.
|
||||
@ -321,21 +298,32 @@ int consolename(char *res, size_t rlen)
|
||||
*/
|
||||
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;
|
||||
isconsole(p + 8, cons[num_consoles].name, sizeof(cons[num_consoles].name))) {
|
||||
/*
|
||||
* Suppress duplicates
|
||||
*/
|
||||
for (considx = 0; considx < num_consoles; considx++) {
|
||||
if (!strcmp(cons[num_consoles].name, cons[considx].name)) {
|
||||
goto dontuse;
|
||||
}
|
||||
}
|
||||
|
||||
num_consoles++;
|
||||
if (num_consoles >= max_consoles) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
dontuse:
|
||||
p--;
|
||||
}
|
||||
|
||||
if (r == 0) return r;
|
||||
if (num_consoles > 0) return num_consoles;
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -343,12 +331,12 @@ int consolename(char *res, size_t rlen)
|
||||
* guess the default console.
|
||||
*/
|
||||
for (n = 0; defcons[n]; n++)
|
||||
if (isconsole(defcons[n], res, rlen))
|
||||
return 0;
|
||||
if (isconsole(defcons[n], cons[0].name, sizeof(cons[0].name)))
|
||||
return 1;
|
||||
|
||||
fprintf(stderr, "bootlogd: cannot deduce real console device\n");
|
||||
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -357,63 +345,75 @@ int consolename(char *res, size_t rlen)
|
||||
*/
|
||||
void writelog(FILE *fp, unsigned char *ptr, int len)
|
||||
{
|
||||
time_t t;
|
||||
char *s;
|
||||
char tmp[8];
|
||||
int olen = len;
|
||||
int dosync = 0;
|
||||
int tlen;
|
||||
int dosync = 0;
|
||||
int i;
|
||||
static int first_run = 1;
|
||||
static int inside_esc = 0;
|
||||
|
||||
while (len > 0) {
|
||||
tmp[0] = 0;
|
||||
if (didnl) {
|
||||
for (i = 0; i < len; i++) {
|
||||
int ignore = 0;
|
||||
|
||||
/* prepend date to every line */
|
||||
if (*(ptr-1) == '\n' || first_run) {
|
||||
time_t t;
|
||||
char *s;
|
||||
time(&t);
|
||||
s = ctime(&t);
|
||||
fprintf(fp, "%.24s: ", s);
|
||||
didnl = 0;
|
||||
dosync = 1;
|
||||
first_run = 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 >= (int)sizeof(line.buf))
|
||||
line.pos = sizeof(line.buf) - 1;
|
||||
break;
|
||||
case 32 ... 127:
|
||||
case 161 ... 255:
|
||||
tmp[0] = *ptr;
|
||||
tmp[1] = 0;
|
||||
break;
|
||||
default:
|
||||
sprintf(tmp, "\\%03o", *ptr);
|
||||
break;
|
||||
|
||||
/* remove escape sequences, but do it in a way that allows us to stop
|
||||
* in the middle in case the string was cut off */
|
||||
if (inside_esc == 1) {
|
||||
/* first '[' is special because if we encounter it again, it should be considered the final byte */
|
||||
if (*ptr == '[') {
|
||||
/* multi char sequence */
|
||||
ignore = 1;
|
||||
inside_esc = 2;
|
||||
} else {
|
||||
/* single char sequence */
|
||||
if (*ptr >= 64 && *ptr <= 95) {
|
||||
ignore = 1;
|
||||
}
|
||||
inside_esc = 0;
|
||||
}
|
||||
} else if (inside_esc == 2) {
|
||||
switch (*ptr) {
|
||||
case '0' ... '9': /* intermediate chars of escape sequence */
|
||||
case ';':
|
||||
case 32 ... 47:
|
||||
if (inside_esc) {
|
||||
ignore = 1;
|
||||
}
|
||||
break;
|
||||
case 64 ... 126: /* final char of escape sequence */
|
||||
if (inside_esc) {
|
||||
ignore = 1;
|
||||
inside_esc = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (*ptr) {
|
||||
case '\r':
|
||||
ignore = 1;
|
||||
break;
|
||||
case 27: /* ESC */
|
||||
ignore = 1;
|
||||
inside_esc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!ignore) {
|
||||
fwrite(ptr, sizeof(char), 1, fp);
|
||||
}
|
||||
|
||||
ptr++;
|
||||
len--;
|
||||
|
||||
tlen = strlen(tmp);
|
||||
if (tlen && (line.pos + tlen < (int)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);
|
||||
if (syncalot) {
|
||||
@ -421,7 +421,7 @@ void writelog(FILE *fp, unsigned char *ptr, int len)
|
||||
}
|
||||
}
|
||||
|
||||
outptr += olen;
|
||||
outptr += len;
|
||||
if (outptr >= endptr)
|
||||
outptr = ringbuf;
|
||||
|
||||
@ -478,19 +478,21 @@ int main(int argc, char **argv)
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
char buf[1024];
|
||||
char realcons[1024];
|
||||
char *p;
|
||||
char *logfile;
|
||||
char *pidfile;
|
||||
int rotate;
|
||||
int dontfork;
|
||||
int ptm, pts;
|
||||
int realfd;
|
||||
/* int realfd; -- this is now unused */
|
||||
int n, m, i;
|
||||
int todo;
|
||||
#ifndef __linux__ /* BSD-style ioctl needs an argument. */
|
||||
int on = 1;
|
||||
#endif
|
||||
int considx;
|
||||
struct real_cons cons[MAX_CONSOLES];
|
||||
int num_consoles, consoles_left;
|
||||
|
||||
fp = NULL;
|
||||
logfile = LOGFILE;
|
||||
@ -537,6 +539,7 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Open console device directly.
|
||||
*/
|
||||
/*
|
||||
if (consolename(realcons, sizeof(realcons)) < 0)
|
||||
return 1;
|
||||
|
||||
@ -546,9 +549,28 @@ int main(int argc, char **argv)
|
||||
strcpy(realcons, "/dev/vc/1");
|
||||
|
||||
if ((realfd = open_nb(realcons)) < 0) {
|
||||
fprintf(stderr, "bootlogd: %s: %s\n", buf, strerror(errno));
|
||||
fprintf(stderr, "bootlogd: %s: %s\n", realcons, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
if ((num_consoles = consolenames(cons, MAX_CONSOLES)) <= 0)
|
||||
return 1;
|
||||
consoles_left = num_consoles;
|
||||
for (considx = 0; considx < num_consoles; considx++) {
|
||||
if (strcmp(cons[considx].name, "/dev/tty0") == 0)
|
||||
strcpy(cons[considx].name, "/dev/tty1");
|
||||
if (strcmp(cons[considx].name, "/dev/vc/0") == 0)
|
||||
strcpy(cons[considx].name, "/dev/vc/1");
|
||||
|
||||
if ((cons[considx].fd = open_nb(cons[considx].name)) < 0) {
|
||||
fprintf(stderr, "bootlogd: %s: %s\n",
|
||||
cons[considx].name, strerror(errno));
|
||||
consoles_left--;
|
||||
}
|
||||
}
|
||||
if (!consoles_left)
|
||||
return 1;
|
||||
|
||||
|
||||
/*
|
||||
* Grab a pty, and redirect console messages to it.
|
||||
@ -632,26 +654,34 @@ int main(int argc, char **argv)
|
||||
if ((n = read(ptm, inptr, endptr - inptr)) >= 0) {
|
||||
/*
|
||||
* Write data (in chunks if needed)
|
||||
* to the real output device.
|
||||
* to the real output devices.
|
||||
*/
|
||||
m = n;
|
||||
p = inptr;
|
||||
while (m > 0) {
|
||||
i = write(realfd, p, m);
|
||||
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;
|
||||
for (considx = 0; considx < num_consoles; considx++) {
|
||||
if (cons[considx].fd < 0) continue;
|
||||
m = n;
|
||||
p = inptr;
|
||||
while (m > 0) {
|
||||
i = write(cons[considx].fd, p, m);
|
||||
if (i >= 0) {
|
||||
m -= i;
|
||||
p += i;
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Handle EIO (somebody hung
|
||||
* up our filedescriptor)
|
||||
*/
|
||||
cons[considx].fd = write_err(pts,
|
||||
cons[considx].fd,
|
||||
cons[considx].name, errno);
|
||||
if (cons[considx].fd >= 0) continue;
|
||||
/*
|
||||
* If this was the last console,
|
||||
* generate a fake signal
|
||||
*/
|
||||
if (--consoles_left <= 0) got_signal = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -697,7 +727,9 @@ int main(int argc, char **argv)
|
||||
|
||||
close(pts);
|
||||
close(ptm);
|
||||
close(realfd);
|
||||
for (considx = 0; considx < num_consoles; considx++) {
|
||||
close(cons[considx].fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -96,7 +96,14 @@ static void getuidtty(char **userp, char **ttyp)
|
||||
uidbuf[0] = 0;
|
||||
strncat(uidbuf, pwd->pw_name, sizeof(uidbuf) - 1);
|
||||
} else {
|
||||
/* Using variable number of data parameters in one
|
||||
function makes the Clang compiler cry. -- Jesse
|
||||
sprintf(uidbuf, uid ? "uid %d" : "root", (int)uid);
|
||||
*/
|
||||
if (uid)
|
||||
sprintf(uidbuf, "uid %d", (int) uid);
|
||||
else
|
||||
sprintf(uidbuf, "root");
|
||||
}
|
||||
|
||||
if ((tty = ttyname(0)) != NULL) {
|
||||
|
139
src/init.c
139
src/init.c
@ -131,7 +131,7 @@ char *argv0; /* First arguments; show up in ps listing */
|
||||
int maxproclen; /* Maximal length of argv[0] with \0 */
|
||||
struct utmp utproto; /* Only used for sizeof(utproto.ut_id) */
|
||||
char *console_dev; /* Console device. */
|
||||
int pipe_fd = -1; /* /dev/initctl */
|
||||
int pipe_fd = -1; /* /run/initctl */
|
||||
int did_boot = 0; /* Did we already do BOOT* stuff? */
|
||||
int main(int, char **);
|
||||
|
||||
@ -362,6 +362,7 @@ static CHILD *get_record(FILE *f)
|
||||
CHILD *p;
|
||||
|
||||
do {
|
||||
errno = 0;
|
||||
switch (cmd = get_cmd(f)) {
|
||||
case C_END:
|
||||
get_void(f);
|
||||
@ -372,34 +373,54 @@ static CHILD *get_record(FILE *f)
|
||||
case C_REC:
|
||||
break;
|
||||
case D_RUNLEVEL:
|
||||
fscanf(f, "%c\n", &runlevel);
|
||||
if (fscanf(f, "%c\n", &runlevel) == EOF && errno != 0) {
|
||||
fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
}
|
||||
break;
|
||||
case D_THISLEVEL:
|
||||
fscanf(f, "%c\n", &thislevel);
|
||||
if (fscanf(f, "%c\n", &thislevel) == EOF && errno != 0) {
|
||||
fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
}
|
||||
break;
|
||||
case D_PREVLEVEL:
|
||||
fscanf(f, "%c\n", &prevlevel);
|
||||
if (fscanf(f, "%c\n", &prevlevel) == EOF && errno != 0) {
|
||||
fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
}
|
||||
break;
|
||||
case D_GOTSIGN:
|
||||
fscanf(f, "%u\n", &got_signals);
|
||||
if (fscanf(f, "%u\n", &got_signals) == EOF && errno != 0) {
|
||||
fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
}
|
||||
break;
|
||||
case D_WROTE_WTMP_REBOOT:
|
||||
fscanf(f, "%d\n", &wrote_wtmp_reboot);
|
||||
if (fscanf(f, "%d\n", &wrote_wtmp_reboot) == EOF && errno != 0) {
|
||||
fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
}
|
||||
break;
|
||||
case D_WROTE_UTMP_REBOOT:
|
||||
fscanf(f, "%d\n", &wrote_utmp_reboot);
|
||||
if (fscanf(f, "%d\n", &wrote_utmp_reboot) == EOF && errno != 0) {
|
||||
fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
}
|
||||
break;
|
||||
case D_SLTIME:
|
||||
fscanf(f, "%d\n", &sltime);
|
||||
if (fscanf(f, "%d\n", &sltime) == EOF && errno != 0) {
|
||||
fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
}
|
||||
break;
|
||||
case D_DIDBOOT:
|
||||
fscanf(f, "%d\n", &did_boot);
|
||||
if (fscanf(f, "%d\n", &did_boot) == EOF && errno != 0) {
|
||||
fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
}
|
||||
break;
|
||||
case D_WROTE_WTMP_RLEVEL:
|
||||
fscanf(f, "%d\n", &wrote_wtmp_rlevel);
|
||||
if (fscanf(f, "%d\n", &wrote_wtmp_rlevel) == EOF && errno != 0) {
|
||||
fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
}
|
||||
break;
|
||||
case D_WROTE_UTMP_RLEVEL:
|
||||
fscanf(f, "%d\n", &wrote_utmp_rlevel);
|
||||
if (fscanf(f, "%d\n", &wrote_utmp_rlevel) == EOF && errno != 0) {
|
||||
fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (cmd > 0 || cmd == C_EOF) {
|
||||
@ -418,10 +439,14 @@ static CHILD *get_record(FILE *f)
|
||||
get_void(f);
|
||||
break;
|
||||
case C_PID:
|
||||
fscanf(f, "%d\n", &(p->pid));
|
||||
if (fscanf(f, "%d\n", &(p->pid)) == EOF && errno != 0) {
|
||||
fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
}
|
||||
break;
|
||||
case C_EXS:
|
||||
fscanf(f, "%u\n", &(p->exstat));
|
||||
if (fscanf(f, "%u\n", &(p->exstat)) == EOF && errno != 0) {
|
||||
fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
}
|
||||
break;
|
||||
case C_LEV:
|
||||
get_string(p->rlevel, sizeof(p->rlevel), f);
|
||||
@ -753,11 +778,11 @@ void console_stty(void)
|
||||
#ifdef __FreeBSD_kernel__
|
||||
/*
|
||||
* The kernel of FreeBSD expects userland to set TERM. Usually, we want
|
||||
* "cons25". Later, gettys might disagree on this (i.e. we're not using
|
||||
* "xterm". Later, gettys might disagree on this (i.e. we're not using
|
||||
* syscons) but some boot scripts, like /etc/init.d/xserver-xorg, still
|
||||
* need a non-dumb terminal.
|
||||
*/
|
||||
putenv ("TERM=cons25");
|
||||
putenv ("TERM=xterm");
|
||||
#endif
|
||||
|
||||
(void) tcgetattr(fd, &tty);
|
||||
@ -1291,6 +1316,76 @@ void startup(CHILD *ch)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static
|
||||
void check_kernel_console()
|
||||
{
|
||||
FILE* fp;
|
||||
char buf[4096];
|
||||
if ((fp = fopen("/proc/cmdline", "r")) == 0) {
|
||||
return;
|
||||
}
|
||||
if (fgets(buf, sizeof(buf), fp)) {
|
||||
char* p = buf;
|
||||
while ((p = strstr(p, "console="))) {
|
||||
char* e;
|
||||
p += strlen("console=");
|
||||
for (e = p; *e; ++e) {
|
||||
switch (*e) {
|
||||
case '-' ... '9':
|
||||
case 'A' ... 'Z':
|
||||
case '_':
|
||||
case 'a' ... 'z':
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (p != e) {
|
||||
CHILD* old;
|
||||
int dup = 0;
|
||||
char id[8] = {0};
|
||||
char dev[32] = {0};
|
||||
strncpy(dev, p, MIN(sizeof(dev), (unsigned)(e-p)));
|
||||
if (!strncmp(dev, "tty", 3))
|
||||
strncpy(id, dev+3, sizeof(id));
|
||||
else
|
||||
strncpy(id, dev, sizeof(id));
|
||||
|
||||
for(old = newFamily; old; old = old->next) {
|
||||
if (!strcmp(old->id, id)) {
|
||||
dup = 1;
|
||||
}
|
||||
}
|
||||
if (!dup) {
|
||||
CHILD* ch = imalloc(sizeof(CHILD));
|
||||
ch->action = RESPAWN;
|
||||
strcpy(ch->id, id);
|
||||
strcpy(ch->rlevel, "2345");
|
||||
sprintf(ch->process, "/sbin/agetty -L -s 115200,38400,9600 %s vt102", dev);
|
||||
ch->next = NULL;
|
||||
for(old = family; old; old = old->next) {
|
||||
if (strcmp(old->id, ch->id) == 0) {
|
||||
old->new = ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* add to end */
|
||||
for(old = newFamily; old; old = old->next) {
|
||||
if (!old->next) {
|
||||
old->next = ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
initlog(L_VB, "added agetty on %s with id %s", dev, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Read the inittab file.
|
||||
@ -1503,6 +1598,10 @@ void read_inittab(void)
|
||||
*/
|
||||
if (fp) fclose(fp);
|
||||
|
||||
#ifdef __linux__
|
||||
check_kernel_console();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Loop through the list of children, and see if they need to
|
||||
* be killed.
|
||||
@ -2252,13 +2351,13 @@ void check_init_fifo(void)
|
||||
int quit = 0;
|
||||
|
||||
/*
|
||||
* First, try to create /dev/initctl if not present.
|
||||
* First, try to create /run/initctl if not present.
|
||||
*/
|
||||
if (stat(INIT_FIFO, &st2) < 0 && errno == ENOENT)
|
||||
(void)mkfifo(INIT_FIFO, 0600);
|
||||
|
||||
/*
|
||||
* If /dev/initctl is open, stat the file to see if it
|
||||
* If /run/initctl is open, stat the file to see if it
|
||||
* is still the _same_ inode.
|
||||
*/
|
||||
if (pipe_fd >= 0) {
|
||||
@ -2272,7 +2371,7 @@ void check_init_fifo(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Now finally try to open /dev/initctl
|
||||
* Now finally try to open /run/initctl
|
||||
*/
|
||||
if (pipe_fd < 0) {
|
||||
if ((pipe_fd = open(INIT_FIFO, O_RDWR|O_NONBLOCK)) >= 0) {
|
||||
@ -2578,7 +2677,7 @@ void process_signals()
|
||||
}
|
||||
if (ISMEMBER(got_signals, SIGUSR1)) {
|
||||
/*
|
||||
* SIGUSR1 means close and reopen /dev/initctl
|
||||
* SIGUSR1 means close and reopen /run/initctl
|
||||
*/
|
||||
INITDBG(L_VB, "got SIGUSR1");
|
||||
close(pipe_fd);
|
||||
@ -2816,7 +2915,7 @@ int telinit(char *progname, int argc, char **argv)
|
||||
strerror(errno));
|
||||
|
||||
/* Open the fifo and write a command. */
|
||||
/* Make sure we don't hang on opening /dev/initctl */
|
||||
/* Make sure we don't hang on opening /run/initctl */
|
||||
SETSIG(sa, SIGALRM, signal_handler, 0);
|
||||
alarm(3);
|
||||
if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* initreq.h Interface to talk to init through /dev/initctl.
|
||||
* initreq.h Interface to talk to init through /run/initctl.
|
||||
*
|
||||
* Copyright (C) 1995-2004 Miquel van Smoorenburg
|
||||
*
|
||||
@ -26,11 +26,7 @@
|
||||
#include <sys/param.h>
|
||||
|
||||
#ifndef INIT_FIFO
|
||||
# if defined(__FreeBSD_kernel__)
|
||||
# define INIT_FIFO "/etc/.initctl"
|
||||
# else
|
||||
# define INIT_FIFO "/dev/initctl"
|
||||
# endif
|
||||
#define INIT_FIFO "/run/initctl"
|
||||
#endif
|
||||
|
||||
#define INIT_MAGIC 0x03091969
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* kilall5.c Kill all processes except processes that have the
|
||||
* killall5.c Kill all processes except processes that have the
|
||||
* same session id, so that the shell that called us
|
||||
* won't be killed. Typically used in shutdown scripts.
|
||||
*
|
||||
|
@ -173,7 +173,7 @@ int init_setenv(char *name, char *value)
|
||||
|
||||
/*
|
||||
* Open the fifo and write the command.
|
||||
* Make sure we don't hang on opening /dev/initctl
|
||||
* Make sure we don't hang on opening /run/initctl
|
||||
*/
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = alrm_handler;
|
||||
@ -498,7 +498,15 @@ int main(int argc, char **argv)
|
||||
int user_ok = 0;
|
||||
|
||||
/* We can be installed setuid root (executable for a special group) */
|
||||
setuid(geteuid());
|
||||
/*
|
||||
This way is risky, do error check on setuid call.
|
||||
setuid(geteuid());
|
||||
*/
|
||||
errno = 0;
|
||||
if (setuid(geteuid()) == -1) {
|
||||
fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
abort();
|
||||
}
|
||||
|
||||
if (getuid() != 0) {
|
||||
fprintf(stderr, "shutdown: you must be root to do that!\n");
|
||||
|
Loading…
Reference in New Issue
Block a user