aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile10
-rw-r--r--initscripts.spec7
-rwxr-xr-xrc.d/init.d/functions120
-rwxr-xr-xrc.d/init.d/halt4
-rwxr-xr-xrc.d/init.d/network12
-rwxr-xr-xrc.d/rc26
-rwxr-xr-xrc.d/rc.sysinit96
-rw-r--r--src/Makefile31
-rw-r--r--src/initlog.148
-rw-r--r--src/initlog.c317
-rw-r--r--src/initlog.h16
-rw-r--r--src/minilogd.c164
-rw-r--r--src/process.c216
-rw-r--r--src/process.h9
-rw-r--r--sysconfig.txt8
15 files changed, 999 insertions, 85 deletions
diff --git a/Makefile b/Makefile
index bf58ff99..e83232b6 100644
--- a/Makefile
+++ b/Makefile
@@ -8,11 +8,11 @@ all:
install:
mkdir -p $(ROOT)/etc/profile.d $(ROOT)/sbin
- install -m644 -o root -g root inittab $(ROOT)/etc
- install -m644 -o root -g root adjtime $(ROOT)/etc
- install -m644 -o root -g root inputrc $(ROOT)/etc
- install -m755 -o root -g root setsysfont $(ROOT)/sbin
- install -m755 -o root -g root lang.sh $(ROOT)/etc/profile.d
+ install -m644 inittab $(ROOT)/etc
+ install -m644 adjtime $(ROOT)/etc
+ install -m644 inputrc $(ROOT)/etc
+ install -m755 setsysfont $(ROOT)/sbin
+ install -m755 lang.sh $(ROOT)/etc/profile.d
cp -af rc.d sysconfig ppp $(ROOT)/etc
mkdir -p $(ROOT)/sbin
mv $(ROOT)/etc/sysconfig/network-scripts/ifup $(ROOT)/sbin
diff --git a/initscripts.spec b/initscripts.spec
index 36eb84e0..d0cef8ae 100644
--- a/initscripts.spec
+++ b/initscripts.spec
@@ -1,6 +1,6 @@
Summary: inittab and /etc/rc.d scripts
Name: initscripts
-%define version 3.83
+%define version 3.84
Version: %{version}
Copyright: GPL
Group: Base
@@ -142,9 +142,12 @@ rm -rf $RPM_BUILD_ROOT
/bin/doexec
/bin/ipcalc
/bin/usleep
-/usr/sbin/usernetctl
+%attr(4755,root,root) /usr/sbin/usernetctl
/sbin/netreport
+/sbin/initlog
+/sbin/minilogd
/usr/man/man1/doexec.1
+/usr/man/man1/initlog.1
/usr/man/man1/ipcalc.1
/usr/man/man1/usleep.1
/usr/man/man1/usernetctl.1
diff --git a/rc.d/init.d/functions b/rc.d/init.d/functions
index a651d699..e69f27f4 100755
--- a/rc.d/init.d/functions
+++ b/rc.d/init.d/functions
@@ -1,4 +1,5 @@
-#! /bin/sh
+
+#!/bin/sh
#
# functions This file contains functions to be used by most or all
# shell scripts in the /etc/init.d directory.
@@ -12,6 +13,15 @@
# First set up a default search path.
export PATH="/sbin:/usr/sbin:/bin:/usr/bin"
+# Read in our configuration
+if [ -f /etc/sysconfig/init ]; then
+ . /etc/sysconfig/init
+else
+ BOOTUP=color
+fi
+
+
+
# A function to start a program.
daemon() {
# Test syntax.
@@ -30,15 +40,17 @@ daemon() {
pid=`pidofproc $base`
[ -n "$pid" ] && ps h $pid >/dev/null 2>&1 && return
- # echo basename of the program.
- echo -n "$base "
-
# make sure it doesn't core dump anywhere; while this could mask
# problems with the daemon, it also closes some security problems
ulimit -c 0
+
+ #
+ if [ $BOOTUP != "color" ]; then
+ echo -n $base
+ fi
# And start it up.
- nice -n $nicelevel "$@"
+ nice -n $nicelevel initlog -q -c "$*" && success -n "$base startup" || failure -n "$base startup"
}
# A function to stop a program.
@@ -150,3 +162,101 @@ status() {
echo "$1 is stopped"
return 3
}
+
+echo_success() {
+ echo $* "[ OK ]"
+ return 0
+}
+
+echo_failure() {
+ echo $* "[FAILED]"
+ return 0
+}
+
+success() {
+ if [ "$1" = "-n" ]; then
+ ECHOARGS="-n"
+ shift
+ else
+ ECHOARGS=""
+ fi
+ if [ -z "$IN_INITLOG" ]; then
+ initlog -n $0 -s "$1" -e 1
+ else
+ echo "-n $0 -s \"$1\" -e 1" >&21
+ fi
+ [ "$BOOTUP" = "color" ] && echo_success $ECHOARGS
+ return 0
+}
+
+failure() {
+ if [ "$1" = "-n" ]; then
+ ECHOARGS="-n"
+ shift
+ else
+ ECHOARGS=""
+ fi
+ if [ -z "$IN_INITLOG" ]; then
+ initlog -n $0 -s "$1" -e 2
+ else
+ echo "-n $0 -s \"$1\" -e 2" >&21
+ fi
+ [ "$BOOTUP" = "color" ] && echo_failure $ECHOARGS
+ return 0
+}
+
+action() {
+ if [ "$1" = "-n" ]; then
+ ECHOARGS="-n"
+ shift
+ else
+ ECHOARGS=""
+ fi
+ STRING=$1
+ echo $ECHOARGS "$STRING "
+ shift
+ if [ -z "$IN_INITLOG" ]; then
+ initlog -q -c "$*" && success "$STRING" || failure "$STRING"
+ else
+ # This sucks.
+ output=`$*`
+ rc=$?
+ if [ -n "$output" ]; then
+ cmdname=`basename $1`
+ initlogcmds=`echo $output | sed -e "s/^/ -n $cmdname -s \"/" | sed -e "s/$/\"/"`
+ echo "$initlogcmds" >&21
+ fi
+
+ if [ $rc ]; then
+ success "$STRING"
+ else
+ echo $output
+ failure "$STRING"
+ fi
+ fi
+ return 0
+}
+
+# Confirm whether we really want to run this service
+confirm() {
+ echo -n "Start service $1 (Y)es/(N)o/(C)ontinue? [Y] "
+ read answer
+ case $answer in
+ y|Y|"")
+ return 0
+ ;;
+ c|C)
+ return 2
+ ;;
+ n|N)
+ return 1
+ ;;
+ *)
+ confirm $1
+ return $?
+ ;;
+ esac
+}
+
+
+
diff --git a/rc.d/init.d/halt b/rc.d/init.d/halt
index 5134770b..552f8f16 100755
--- a/rc.d/init.d/halt
+++ b/rc.d/init.d/halt
@@ -15,7 +15,7 @@ PATH=/sbin:/bin:/usr/bin:/usr/sbin
case "$0" in
*halt)
message="The system is halted"
- command="halt"
+ command="halt -p"
;;
*reboot)
message="Please stand by while rebooting the system..."
@@ -44,7 +44,7 @@ echo "Turning off swap and accounting"
swapoff -a
[ -x /sbin/accton ] && /sbin/accton
echo "Unmounting file systems"
-umount -a
+umount -a -f
mount -n -o remount,ro /
# turn off raid
diff --git a/rc.d/init.d/network b/rc.d/init.d/network
index 425d6c38..f21de187 100755
--- a/rc.d/init.d/network
+++ b/rc.d/init.d/network
@@ -57,8 +57,7 @@ ipv4_forward_set ()
fi
if [ $value != `cat /proc/sys/net/ipv4/ip_forward` ]; then
- echo $message
- echo "$value" > /proc/sys/net/ipv4/ip_forward
+ action -n "$message" echo "$value" > /proc/sys/net/ipv4/ip_forward
fi
fi
fi
@@ -70,7 +69,7 @@ case "$1" in
start)
ipv4_forward_set
- ./ifup ifcfg-lo
+ action "Bringing up interface lo" ./ifup ifcfg-lo
case "$IPX" in
yes|true)
@@ -81,14 +80,14 @@ case "$1" in
esac
for i in $interfaces; do
- ./ifup $i boot
+ action "Bringing up interface $i" ./ifup $i boot
done
touch /var/lock/subsys/network
;;
stop)
for i in $interfaces; do
- ./ifdown $i boot
+ action "Shutting down interface $i" ./ifdown $i boot
done
case "$IPX" in
yes|true)
@@ -96,8 +95,7 @@ case "$1" in
;;
esac
./ifdown ifcfg-lo
- echo "Disabling IPv4 packet forwarding."
- echo 0 > /proc/sys/net/ipv4/ip_forward
+ action -n "Disabling IPv4 packet forwarding." echo 0 > /proc/sys/net/ipv4/ip_forward
rm -f /var/lock/subsys/network
;;
status)
diff --git a/rc.d/rc b/rc.d/rc
index aacd5f3f..05f63392 100755
--- a/rc.d/rc
+++ b/rc.d/rc
@@ -19,6 +19,15 @@ runlevel=$2
previous=$1
export runlevel previous
+# See if we want to be in user confirmation mode
+if [ "$previous" = "N" ]; then
+ if grep -i confirm /proc/cmdline >/dev/null ; then
+ CONFIRM=yes
+ else
+ CONFIRM=
+ fi
+fi
+
# Get first argument. Set new runlevel to this argument.
[ "$1" != "" ] && runlevel="$argv1"
@@ -58,6 +67,23 @@ if [ -d /etc/rc.d/rc$runlevel.d ]; then
subsys=${i#/etc/rc.d/rc$runlevel.d/S??}
[ -f /var/lock/subsys/$subsys ] || \
[ -f /var/lock/subsys/${subsys}.init ] && continue
+
+ # If we're in confirmation mode, get user confirmation
+ [ -n "$CONFIRM" ] &&
+ {
+ confirm $subsys
+ case $? in
+ 0)
+ :
+ ;;
+ 2)
+ CONFIRM=
+ ;;
+ *)
+ continue
+ ;;
+ esac
+ }
# Bring the subsystem up.
$i start
diff --git a/rc.d/rc.sysinit b/rc.d/rc.sysinit
index acd2b5fa..0b84f72f 100755
--- a/rc.d/rc.sysinit
+++ b/rc.d/rc.sysinit
@@ -1,10 +1,15 @@
-#! /bin/sh
+#!/bin/sh
#
# /etc/rc.d/rc.sysinit - run once at boot time
#
# Taken in part from Miquel van Smoorenburg's bcheckrc.
#
+# Rerun ourselves through initlog
+if [ -z "$IN_INITLOG" ]; then
+ [ -f /sbin/initlog ] && exec /sbin/initlog -r /etc/rc.d/rc.sysinit
+fi
+
# Set the path
PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PATH
@@ -17,17 +22,18 @@ else
HOSTNAME=localhost
fi
+# Source functions
+. /etc/rc.d/init.d/functions
+
# Start up swapping.
-echo "Activating swap partitions"
-swapon -a
+action -n "Activating swap partitions" swapon -a
# Set the hostname.
-hostname ${HOSTNAME}
-echo hostname: `hostname`
+action -n "Setting hostname ${HOSTNAME}" hostname ${HOSTNAME}
# Set the NIS domain name
if [ -n "$NISDOMAIN" ]; then
- domainname $NISDOMAIN
+ action -n "Setting NIS domain name $NISDOMAIN" domainname $NISDOMAIN
else
domainname ""
fi
@@ -39,12 +45,10 @@ if [ -f /fsckoptions ]; then
fi
if [ ! -f /fastboot ]; then
- echo "Checking root filesystems."
- fsck -V -a $fsckoptions /
-
+ action -n "Checking root filesystem" fsck -T -a $fsckoptions /
rc=$?
-
- # A return of 2 or higher means there were serious problems.
+
+ # A return of 2 or higher means there were serious problems.
if [ $rc -gt 1 ]; then
echo
echo
@@ -60,17 +64,19 @@ if [ ! -f /fastboot ]; then
mount -n -o remount,ro /
echo "Automatic reboot in progress."
reboot
+ elif [ "$rc" = "1" -a -x /sbin/quotacheck ]; then
+ action -n "Checking root filesystem quotas" /sbin/quotacheck -v /
fi
fi
if [ -x /sbin/quotaon ]; then
- echo "Turning on user and group quotas for root filesystem"
- /sbin/quotaon /
+ action -n "Turning on user and group quotas for root filesystem" /sbin/quotaon /
fi
# check for arguments
mount -t proc /proc /proc
+
if grep -i nopnp /proc/cmdline >/dev/null ; then
PNP=
else
@@ -80,23 +86,20 @@ fi
# set up pnp
if [ -x /sbin/isapnp -a -f /etc/isapnp.conf ]; then
if [ -n "$PNP" ]; then
- echo "Setting up ISA PNP devices"
- /sbin/isapnp /etc/isapnp.conf
+ action -n "Setting up ISA PNP devices" /sbin/isapnp /etc/isapnp.conf
else
- echo "Skipping ISA PNP configuration at users request"
+ action -n "Skipping ISA PNP configuration at users request" /bin/true
fi
fi
# Remount the root filesystem read-write.
-echo "Remounting root filesystem in read-write mode."
-mount -n -o remount,rw /
+action -n "Remounting root filesystem in read-write mode" mount -n -o remount,rw /
-# Check quotas if fsck fixed something.
-if [ "$rc" = "1" -a -x /sbin/quotacheck ]; then
- echo "Checking root filesystem quotas"
- /sbin/quotacheck -v /
+if [ -n "$IN_INITLOG" ]; then
+ IN_INITLOG=
fi
+
if [ ! -f /etc/HOSTNAME ]; then
echo ${HOSTNAME} > /etc/HOSTNAME
fi
@@ -129,22 +132,20 @@ fi
if [ -x /sbin/depmod -a -n "$USEMODULES" ]; then
# Get ready for kerneld if module support in the kernel
- echo -n "Finding module dependencies... "
if [ -e /lib/modules/preferred ]; then
- depmod -a preferred
+ action -n "Finding module dependencies" depmod -a preferred
else
- depmod -a
+ action -n "Finding module dependencies" depmod -a
fi
- echo "done"
fi
# load sound modules
if ! grep -i nomodules /proc/cmdline >/dev/null ; then
if [ -n "$USEMODULES" ]; then
if grep -s "alias sound" /etc/conf.modules > /dev/null ; then
- modprobe sound
+ action -n "Loading sound module" modprobe sound
if grep -s "alias midi" /etc/conf.modules > /dev/null ; then
- modprobe midi
+ action -n "Loading midi module" modprobe midi
fi
fi
fi
@@ -162,8 +163,7 @@ fi
# Add raid devices
if [ -f /proc/mdstat -a -f /etc/raidtab -a -x /sbin/raidadd ]; then
- echo "Starting up RAID devices."
- raidadd -a
+ action -n "Starting up RAID devices" raidadd -a
rc=$?
@@ -193,8 +193,7 @@ fi
# Check filesystems
if [ ! -f /fastboot ]; then
- echo "Checking filesystems."
- fsck -R -A -V -a $fsckoptions
+ action -n "Checking filesystems" fsck -T -R -A -a $fsckoptions
rc=$?
@@ -214,29 +213,23 @@ if [ ! -f /fastboot ]; then
mount -n -o remount,ro /
echo "Automatic reboot in progress."
reboot
+ elif [ "$rc" = "1" -a -x /sbin/quotacheck ]; then
+ action -n "Checking filesystem quotas" /sbin/quotacheck -v -R -a
fi
fi
# Mount all other filesystems (except for NFS and /proc, which is already
# mounted). Contrary to standard usage,
# filesystems are NOT unmounted in single user mode.
-echo "Mounting local filesystems."
-mount -a -t nonfs,proc
+action -n "Mounting local filesystems" mount -a -t nonfs,proc
# set the console font
if [ -x /sbin/setsysfont ]; then
/sbin/setsysfont
fi
-# Check quotas if fsck fixed something.
-if [ "$rc" = "1" -a -x /sbin/quotacheck ]; then
- echo "Checking filesystem quotas"
- /sbin/quotacheck -v -R -a
-fi
-
if [ -x /sbin/quotaon ]; then
- echo "Turning on user and group quotas for local filesystems"
- /sbin/quotaon -a
+ action -n "Turning on user and group quotas for local filesystems" /sbin/quotaon -a
fi
# Clean out /etc.
@@ -263,8 +256,6 @@ rm -f /tmp/.X*-lock
rm -f /tmp/.s.PGSQL.*
# Set the system clock.
-echo -n "Setting clock"
-
ARC=0
UTC=0
if [ -f /etc/sysconfig/clock ]; then
@@ -278,6 +269,7 @@ if [ -f /etc/sysconfig/clock ]; then
fi
fi
+CLOCKDEF=""
if [ -x /sbin/hwclock ]; then
CLOCKFLAGS="--hctosys"
CLOCK=/sbin/hwclock
@@ -289,25 +281,22 @@ fi
case "$UTC" in
yes|true)
CLOCKFLAGS="$CLOCKFLAGS -u";
- echo -n " (utc)"
+ CLOCKDEF="$CLOCKDEF (utc)";
;;
esac
case "$ARC" in
yes|true)
CLOCKFLAGS="$CLOCKFLAGS -A";
- echo -n " (arc)"
+ CLOCKDEF="$CLOCKDEF (arc)";
;;
esac
-echo -n ": "
$CLOCK $CLOCKFLAGS
-
-date
+action -n "Setting clock $CLOCKDEF: `date`" date
# Right, now turn on swap in case we swap to files.
-echo "Enabling swap space."
-swapon -a 2>&1 | grep -v "busy"
+action -n "Enabling swap space" swapon -a 2>&1 | grep -v "busy"
# Initialize the serial ports.
if [ -f /etc/rc.d/rc.serial ]; then
@@ -335,7 +324,6 @@ fi
dmesg > /var/log/dmesg
# Feed entropy into the entropy pool
-# XXX Random is also started as S20random but randomization may be needed
-# XXX for packet sequence numbers during network initialization so we'll
-# XXX add entropy here too.
/etc/rc.d/init.d/random start
+
+sleep 10
diff --git a/src/Makefile b/src/Makefile
index c0e3f573..c2751e9e 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,6 +1,6 @@
-CFLAGS+=-Wall
+CFLAGS+=-Wall -D_GNU_SOURCE
-PROGS=usernetctl doexec netreport testd usleep ipcalc
+PROGS=usernetctl doexec netreport testd usleep ipcalc initlog minilogd
all: $(PROGS)
@@ -9,11 +9,14 @@ clean:
install:
mkdir -p $(ROOT)/bin $(ROOT)/usr/sbin $(ROOT)/usr/man/man1
- install -o 0 -g 0 -s -m 755 doexec $(ROOT)/bin/doexec
- install -o 0 -g 0 -s -m 755 usleep $(ROOT)/bin/usleep
- install -o 0 -g 0 -s -m 4755 usernetctl $(ROOT)/usr/sbin/usernetctl
- install -o 0 -g 0 -s -m 2755 netreport $(ROOT)/sbin/netreport
- install -o 0 -g 0 -s -m 755 ipcalc $(ROOT)/bin/ipcalc
+ install -s -m 755 doexec $(ROOT)/bin/doexec
+ install -s -m 755 usleep $(ROOT)/bin/usleep
+ install -s -m 4755 usernetctl $(ROOT)/usr/sbin/usernetctl
+ install -s -m 2755 netreport $(ROOT)/sbin/netreport
+ install -s -m 755 ipcalc $(ROOT)/bin/ipcalc
+ install -s -m 755 initlog $(ROOT)/sbin/initlog
+ install -s -m 755 minilogd $(ROOT)/sbin/minilogd
+ install -m 644 initlog.1 $(ROOT)/usr/man/man1
install -m 644 doexec.1 $(ROOT)/usr/man/man1
install -m 644 netreport.1 $(ROOT)/usr/man/man1
install -m 644 usleep.1 $(ROOT)/usr/man/man1
@@ -23,8 +26,18 @@ install:
# this daemon and initscript are useful for testing the up/down/status stuff
# not installed by default, only comes from sources.
install-test:
- install -o 0 -g 0 -s -m 755 testd $(ROOT)/usr/sbin/testd
- install -o 0 -g 0 -m 755 testdinit $(ROOT)/etc/rc.d/init.d/testd
+ install -s -m 755 testd $(ROOT)/usr/sbin/testd
+ install -m 755 testdinit $(ROOT)/etc/rc.d/init.d/testd
ipcalc: ipcalc.o
$(CC) $(LDFLAGS) -o $@ $< -lpopt
+
+minilogd: minilogd.o
+ $(CC) $(LDFLAGS) -o $@ $<
+
+initlog: initlog.o process.o
+ $(CC) $(LDFLAGS) -o $@ $< -lpopt
+
+clean:
+ rm ipcalc initlog minilogd *.o core *~
+
diff --git a/src/initlog.1 b/src/initlog.1
new file mode 100644
index 00000000..103ef3fd
--- /dev/null
+++ b/src/initlog.1
@@ -0,0 +1,48 @@
+.TH initlog 8 "Sun Jan 24 1999"
+.SH NAME
+initlog \- log messages and events to the system logger
+.SH SYNOPSIS
+.B initlog
+[\-cefnprs] [\-\-cmd=ARG] [\-\-event=ARG] [\-\-facility=ARG]
+[\-\-name=ARG] [\-\-priority=ARG] [\-\-run=ARG] [\-\-string=ARG]
+.SH DESCRIPTION
+\fBinitlog\fR logs messages and events to the system logger.
+It is mainly designed for use in init scripts.
+
+.SS OPTIONS
+.TP
+.I "\-c, \-\-cmd=[program]"
+Execute the specified program, logging anything output to
+stdout or stderr.
+.TP
+.I "\-e, \-\-event=[number]"
+Logs that the specified event happened. Usually used in conjuction
+with \fB\-\-name\fR. Currently specified events are:
+.nf
+ \fB1\fR the action completed successfully
+ \fB2\fR the action failed
+ \fB3\fR the action was cancelled at user request
+ \fB4\fR the action failed due to the failure of a dependent action
+.TP
+.I "\-f, \-\-facility=[facility]"
+
+Log at the specified syslog facility. The default
+is \fBdaemon\fR (see syslog(3)).
+.TP
+.I "\-n, \-\-name=[string]"
+Log the event under the specified string, such as
+"inetd".
+.TP
+.I "\-p, \-\-priority=[priority]"
+Log at the specified syslog priority. The default
+is \fBnotice\fR (see syslog(3)).
+.TP
+.I "\-r, \-\-run=[program]"
+Execute the specified program, with an open file
+descriptor so that the program can pass back
+commands to initlog.
+.TP
+.I "\-s, \-\-string=[string]
+Log the specified string to the logger.
+.SH "SEE ALSO"
+syslog(3), logger(1)
diff --git a/src/initlog.c b/src/initlog.c
new file mode 100644
index 00000000..96b5af87
--- /dev/null
+++ b/src/initlog.c
@@ -0,0 +1,317 @@
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libintl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define SYSLOG_NAMES
+#include <syslog.h>
+
+#include <sys/wait.h>
+
+#define _(String) gettext((String))
+
+#include <popt.h>
+
+#include "initlog.h"
+#include "process.h"
+
+static int logfacility=LOG_DAEMON;
+static int logpriority=LOG_NOTICE;
+static int reexec=0;
+static int quiet=0;
+
+static int logEntries = 0;
+struct logInfo *logData = NULL;
+
+char *getLine(char **data) {
+ /* Get one line from data */
+ char *x, *y;
+
+ if (!*data) return NULL;
+
+ for (x = *data; *x && (*x != '\n'); x++);
+ if (*x) {
+ x++;
+ } else {
+ if (x-*data) {
+ y=malloc(x-*data+1);
+ y[x-*data] = 0;
+ y[x-*data-1] = '\n';
+ memcpy(y,*data,x-*data);
+ } else {
+ y=NULL;
+ }
+ *data = NULL;
+ return y;
+ }
+ y = malloc(x-*data);
+ y[x-*data-1] = 0;
+ memcpy(y,*data,x-*data-1);
+ *data = x;
+ return y;
+}
+
+char **toArray(char *line, int *num) {
+ /* Converts a long string into an array of lines. */
+ char **lines;
+ char *tmpline;
+
+ *num = 0;
+ lines = NULL;
+
+ while ((tmpline=getLine(&line))) {
+ if (!*num)
+ lines = (char **) malloc(sizeof(char *));
+ else
+ lines = (char **) realloc(lines, (*num+1)*sizeof(char *));
+ lines[*num] = tmpline;
+ (*num)++;
+ }
+ return lines;
+}
+
+int startDaemon() {
+ int pid;
+ int rc;
+
+ if ( (pid = fork()) == -1 ) {
+ perror("fork");
+ return -1;
+ }
+ if ( pid ) {
+ /* parent */
+ waitpid(pid,&rc,0);
+ if (rc)
+ return -1;
+ else
+ return 0;
+ } else {
+ int fd;
+
+ fd=open("/dev/null",O_RDWR);
+ dup2(fd,0);
+ dup2(fd,1);
+ dup2(fd,2);
+ /* kid */
+ execlp("minilogd","minilogd",NULL);
+ perror("exec");
+ exit(-1);
+ }
+}
+
+int logLine(struct logInfo *logEnt) {
+ /* Logs a line... somewhere. */
+ int x;
+
+ /* Don't log empty or null lines */
+ if (!logEnt->line || !strcmp(logEnt->line,"\n")) return 0;
+
+ if ((x=access(_PATH_LOG,W_OK))) {
+ /* syslog isn't running, so start something... */
+ if ( (x=startDaemon()) ==-1) {
+ logData=realloc(logData,(logEntries+1)*sizeof(struct logInfo));
+ logData[logEntries]= (*logEnt);
+ logEntries++;
+ } else {
+ if (logEntries>0) {
+ for (x=0;x<logEntries;x++) {
+ openlog(logData[x].cmd,0,logData[x].fac);
+ printf("flushing %s\n",logData[x].line);
+ syslog(logData[x].pri,"%s",logData[x].line);
+ closelog();
+ }
+ free(logData);
+ logEntries = 0;
+ }
+ openlog(logEnt->cmd,0,logEnt->fac);
+ syslog(logEnt->pri,"%s",logEnt->line);
+ closelog();
+ }
+ } else {
+ if (logEntries>0) {
+ for (x=0;x<logEntries;x++) {
+ openlog(logData[x].cmd,0,logData[x].fac);
+ printf("flushing %s\n",logData[x].line);
+ syslog(logData[x].pri,"%s",logData[x].line);
+ closelog();
+ }
+ free(logData);
+ logEntries = 0;
+ }
+ openlog(logEnt->cmd,0,logEnt->fac);
+ syslog(logEnt->pri,"%s",logEnt->line);
+ closelog();
+ }
+ return 0;
+}
+
+int logEvent(char *cmd, int eventtype,char *string) {
+ char *eventtable [] = {
+ _("%s babbles incoherently"),
+ _("%s succeeded"),
+ _("%s failed"),
+ _("%s cancelled at user request"),
+ _("%s failed due to a failed dependency"),
+ /* insert more here */
+ NULL
+ };
+ int x=0,len;
+ struct logInfo logentry;
+
+
+ if (cmd) {
+ logentry.cmd = strdup(basename(cmd));
+ if ((logentry.cmd[0] =='K' || logentry.cmd[0] == 'S') && ( 30 <= logentry.cmd[1] <= 39 )
+ && ( 30 <= logentry.cmd[2] <= 39 ) )
+ logentry.cmd+=3;
+ } else
+ logentry.cmd = strdup(_("(none)"));
+ if (!string)
+ string = strdup(cmd);
+
+ while (eventtable[x] && x<eventtype) x++;
+ if (!(eventtable[x])) x=0;
+
+ len=strlen(eventtable[x])+strlen(string);
+ logentry.line=malloc(len);
+ snprintf(logentry.line,len,eventtable[x],string);
+
+ logentry.pri = logpriority;
+ logentry.fac = logfacility;
+
+ return logLine(&logentry);
+}
+
+int logString(char *cmd, char *string) {
+ struct logInfo logentry;
+
+ if (cmd) {
+ logentry.cmd = strdup(basename(cmd));
+ if ((logentry.cmd[0] =='K' || logentry.cmd[0] == 'S') && ( 30 <= logentry.cmd[1] <= 39 )
+ && ( 30 <= logentry.cmd[2] <= 39 ) )
+ logentry.cmd+=3;
+ } else
+ logentry.cmd = strdup(_(""));
+ logentry.line = strdup(string);
+ logentry.pri = logpriority;
+ logentry.fac = logfacility;
+
+ return logLine(&logentry);
+}
+
+void processArgs(int argc, char **argv) {
+ char *cmdname=NULL;
+ int cmdevent=0;
+ char *cmd=NULL;
+ char *logstring=NULL;
+ char *fac=NULL,*pri=NULL;
+ poptContext context;
+ int rc;
+ struct poptOption optTable[] = {
+ POPT_AUTOHELP
+ { "name", 'n', POPT_ARG_STRING, &cmdname, 0,
+ "name of service being logged", NULL
+ },
+ { "event", 'e', POPT_ARG_INT, &cmdevent, 0,
+ "event being logged (see man page)", NULL
+ },
+ { "cmd", 'c', POPT_ARG_STRING, &cmd, 0,
+ "command to run, logging output", NULL
+ },
+ { "run", 'r', POPT_ARG_STRING, &cmd, 3,
+ "command to run, accepting input on open fd", NULL
+ },
+ { "string", 's', POPT_ARG_STRING, &logstring, 0,
+ "string to log", NULL
+ },
+ { "facility", 'f', POPT_ARG_STRING, &fac, 1,
+ "facility to log at (default: 'daemon')", NULL
+ },
+ { "priority", 'p', POPT_ARG_STRING, &pri, 2,
+ "priority to log at (default: 'notice')", NULL
+ },
+ { "quiet", 'q', POPT_ARG_NONE, &quiet, 0,
+ "suppress stdout/stderr", NULL
+ },
+ { 0, 0, 0, 0, 0, 0 }
+ };
+
+ context = poptGetContext("initlog", argc, argv, optTable, 0);
+
+ while ((rc = poptGetNextOpt(context)) > 0) {
+ switch (rc) {
+ case 1:
+ logfacility=atoi(fac);
+ if ((logfacility == 0) && strcmp(fac,"0")) {
+ int x =0;
+
+ logfacility = LOG_DAEMON;
+ for (x=0;facilitynames[x].c_name;x++) {
+ if (!strcmp(fac,facilitynames[x].c_name)) {
+ logfacility = facilitynames[x].c_val;
+ break;
+ }
+ }
+ }
+ break;
+ case 2:
+ logpriority = atoi(pri);
+ if ((logpriority == 0) && strcmp(pri,"0")) {
+ int x=0;
+
+ logpriority = LOG_NOTICE;
+ for (x=0;prioritynames[x].c_name;x++) {
+ if (!strcmp(pri,prioritynames[x].c_name)) {
+ logpriority = prioritynames[x].c_val;
+ break;
+ }
+ }
+ }
+ break;
+ case 3:
+ reexec = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if ((rc < -1)) {
+ fprintf(stderr, "%s: %s\n",
+ poptBadOption(context, POPT_BADOPTION_NOALIAS),
+ poptStrerror(rc));
+ exit(-1);
+ }
+ if ( (cmd && logstring) || (cmd && cmdname) ) {
+ fprintf(stderr, _("--cmd and --run are incompatible with --string or --name\n"));
+ exit(-1);
+ }
+ if ( cmdname && (!logstring && !cmdevent)) {
+ fprintf(stderr, _("--name requires one of --event or --string\n"));
+ exit(-1);
+ }
+ if (cmdevent) {
+ logEvent(cmdname,cmdevent,logstring);
+ } else if (logstring) {
+ logString(cmdname,logstring);
+ } else if ( cmd ) {
+ exit(runCommand(cmd,reexec,quiet));
+ } else {
+ fprintf(stderr,"nothing to do!\n");
+ exit(-1);
+ }
+}
+
+int main(int argc, char **argv) {
+
+ setlocale(LC_ALL,"");
+ bindtextdomain("initlog","/etc/locale");
+ textdomain("initlog");
+ processArgs(argc,argv);
+ exit (0);
+}
diff --git a/src/initlog.h b/src/initlog.h
new file mode 100644
index 00000000..244ff9a0
--- /dev/null
+++ b/src/initlog.h
@@ -0,0 +1,16 @@
+
+#ifndef INITLOG_H
+#define INITLOG_H
+
+struct logInfo {
+ char *cmd;
+ char *line;
+ int fac;
+ int pri;
+};
+
+char *getLine(char **data);
+int logString(char *cmd, char *string);
+void processArgs(int argc, char **argv);
+
+#endif
diff --git a/src/minilogd.c b/src/minilogd.c
new file mode 100644
index 00000000..d15b8d9a
--- /dev/null
+++ b/src/minilogd.c
@@ -0,0 +1,164 @@
+
+/* minilogd.c
+ *
+ * A pale imitation of syslogd. Most notably, doesn't write anything
+ * anywhere except possibly back to syslogd.
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+
+static int we_own_log=0;
+static char **buffer=NULL;
+static int buflines=0;
+
+void freeBuffer() {
+ struct sockaddr_un addr;
+ int sock;
+ int x=0,conn;
+
+ bzero(&addr,sizeof(addr));
+ addr.sun_family = AF_LOCAL;
+ strncpy(addr.sun_path,_PATH_LOG,sizeof(addr.sun_path)-1);
+ /* wait for klogd to hit syslog */
+ sleep(1);
+ sock = socket(AF_LOCAL, SOCK_STREAM,0);
+ conn=connect(sock,(struct sockaddr *) &addr,sizeof(addr));
+ while (x<buflines) {
+ if (!conn) write(sock,buffer[x],strlen(buffer[x])+1);
+ free(buffer[x]);
+ x++;
+ }
+}
+
+void cleanup(int exitcode) {
+ /* If we own the log, unlink it before trying to free our buffer.
+ * Otherwise, sending the buffer to /dev/log doesn't make much sense.... */
+ if (we_own_log) {
+ perror("wol");
+ unlink(_PATH_LOG);
+ }
+ /* Don't try to free buffer if we were called from a signal handler */
+ perror("foo");
+ if (exitcode<=0) {
+ if (buffer) freeBuffer();
+ exit(exitcode);
+ } else
+ exit(exitcode+128);
+}
+
+void runDaemon(int sock) {
+ struct sockaddr_un addr;
+ int x,len,addrlen,recvsock,done=0;
+ char *message;
+ struct stat s1,s2;
+ struct pollfd pfds;
+ FILE *foo;
+
+ foo=fopen("./foo","a");
+
+ daemon(0,-1);
+ /* try not to leave stale sockets lying around */
+ /* Hopefully, we won't actually get any of these */
+ signal(SIGHUP,cleanup);
+ signal(SIGINT,cleanup);
+ signal(SIGQUIT,cleanup);
+ signal(SIGILL,cleanup);
+ signal(SIGABRT,cleanup);
+ signal(SIGFPE,cleanup);
+ signal(SIGSEGV,cleanup);
+ signal(SIGPIPE,cleanup);
+ signal(SIGBUS,cleanup);
+ signal(SIGTERM,cleanup);
+ done = 0;
+ /* Get stat info on dev log so we can later check to make sure we
+ * still own it... */
+ stat(_PATH_LOG,&s1);
+ while (!done) {
+ pfds.fd = sock;
+ pfds.events = POLLIN|POLLPRI;
+ if ( ( (x=poll(&pfds,1,500))==-1) && errno !=EINTR) {
+ perror("poll");
+ cleanup(-1);
+ }
+ if ( (x>0) && pfds.revents & (POLLIN | POLLPRI)) {
+ printf("foo!\n");
+ message = calloc(8192,sizeof(char));
+ recvsock = accept(sock,(struct sockaddr *) &addr, &addrlen);
+ len = read(recvsock,message,8192);
+ if (buffer)
+ buffer = realloc(buffer,(buflines+1)*sizeof(char *));
+ else
+ buffer = malloc(sizeof(char *));
+ if (len>0) {
+ message[strlen(message)]='\n';
+ fprintf(foo,"%s",message);
+ buffer[buflines]=message;
+ buflines++;
+ close(recvsock);
+ }
+ else {
+ close(recvsock);
+ recvsock=-1;
+ }
+ }
+ if ( (x>0) && ( pfds.revents & (POLLHUP | POLLNVAL)) )
+ done = 1;
+ /* Check to see if syslogd's yanked our socket out from under us */
+ if ( (stat(_PATH_LOG,&s2)!=0) ||
+ (s1.st_ino != s2.st_ino ) || (s1.st_ctime != s2.st_ctime) ||
+ (s1.st_mtime != s2.st_mtime) || (s1.st_atime != s2.st_atime) ) {
+ done = 1;
+ we_own_log = 0;
+ }
+ }
+ fclose(foo);
+ cleanup(0);
+}
+
+int main() {
+ struct sockaddr_un addr;
+ int sock;
+ int pid;
+
+ /* just in case */
+ sock = open("/dev/null",O_RDWR);
+ dup2(sock,0);
+ dup2(sock,1);
+ dup2(sock,2);
+
+ bzero(&addr, sizeof(addr));
+ addr.sun_family = AF_LOCAL;
+ strncpy(addr.sun_path,_PATH_LOG,sizeof(addr.sun_path)-1);
+ sock = socket(AF_LOCAL, SOCK_STREAM,0);
+ unlink(_PATH_LOG);
+ /* Bind socket before forking, so we know if the server started */
+ if (!bind(sock,(struct sockaddr *) &addr, sizeof(addr))) {
+ we_own_log = 1;
+ listen(sock,5);
+ if ((pid=fork())==-1) {
+ perror("fork");
+ exit(-1);
+ }
+ if (pid) {
+ exit(0);
+ } else {
+ runDaemon(sock);
+ /* shouldn't get back here... */
+ exit(-1);
+ }
+ } else {
+ exit(-1);
+ }
+}
diff --git a/src/process.c b/src/process.c
new file mode 100644
index 00000000..48f3b314
--- /dev/null
+++ b/src/process.c
@@ -0,0 +1,216 @@
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/poll.h>
+#include <sys/wait.h>
+
+#include <popt.h>
+
+#include "initlog.h"
+#include "process.h"
+
+int forkCommand(char **args, int *outfd, int *errfd, int *cmdfd, int quiet) {
+ /* Fork command 'cmd', returning pid, and optionally pointer
+ * to open file descriptor fd */
+ int fdin, fdout, fderr, fdcmd, pid;
+ int outpipe[2], errpipe[2], fdpipe[2];
+
+ if ( (pipe(outpipe)==-1) || (pipe(errpipe)==-1) || (pipe(fdpipe)==-1) ) {
+ perror("pipe");
+ return -1;
+ }
+
+ dup2(0,fdin);
+ if (outfd) {
+ fdout = outpipe[1];
+ *outfd = outpipe[0];
+ } else {
+ if (!quiet)
+ dup2(1,fdout);
+ }
+ if (errfd) {
+ fderr = errpipe[1];
+ *errfd = errpipe[0];
+ } else {
+ if (!quiet)
+ dup2(2,fderr);
+ }
+ fdcmd = fdpipe[1];
+ if (cmdfd)
+ *cmdfd = fdpipe[0];
+ if ((pid = fork())==-1) {
+ perror("fork");
+ return -1;
+ }
+ if (pid) {
+ /* parent */
+ close(fdin);
+ close(fdout);
+ close(fderr);
+ close(fdcmd);
+ return pid;
+ } else {
+ /* kid */
+ if (outfd) {
+ if ( (dup2(fdout,1)==-1) ) {
+ perror("dup2");
+ exit(-1);
+ }
+ } else if (quiet)
+ if ((dup2(open("/dev/null",O_WRONLY),1))==-1) {
+ perror("dup2");
+ exit(-1);
+ }
+
+ if (errfd) {
+ if ((dup2(fderr,2)==-1)) {
+ perror("dup2");
+ exit(-1);
+ }
+ } else if (quiet)
+ if ((dup2(open("/dev/null",O_WRONLY),2))==-1) {
+ perror("dup2");
+ exit(-1);
+ }
+
+
+ if ((dup2(fdcmd,CMD_FD)==-1)) {
+ perror("dup2");
+ exit(-1);
+ }
+ close(fdout);
+ close(fderr);
+ close(fdcmd);
+ if (outfd)
+ close(*outfd);
+ if (errfd)
+ close(*errfd);
+ if (cmdfd)
+ close(*cmdfd);
+ execvp(args[0],args);
+ perror("execvp");
+ exit(-1);
+ }
+}
+
+int monitor(char *cmdname, int pid, int numfds, int *fds, int reexec, int quiet) {
+ struct pollfd *pfds;
+ char *buf=malloc(2048*sizeof(char));
+ int outpipe[2];
+ char *tmpstr=NULL;
+ int x,y,rc=-1;
+ int done=0;
+ int output=0;
+
+ pipe(outpipe);
+
+ pfds = malloc(numfds*sizeof(struct pollfd));
+ for (x=0;x<numfds;x++) {
+ pfds[x].fd = fds[x];
+ pfds[x].events = POLLIN | POLLPRI;
+ }
+
+ while (!done) {
+ if ((x=poll(pfds,numfds,500))==-1) {
+ perror("poll");
+ return -1;
+ }
+ if (waitpid(pid,&rc,WNOHANG))
+ done=1;
+ y=0;
+ while (y<numfds) {
+ if ( x && ((pfds[y].revents & (POLLIN | POLLPRI)) )) {
+ int bytesread = 0;
+
+ do {
+ buf=calloc(2048,sizeof(char));
+ bytesread = read(pfds[y].fd,buf,2048);
+ if (bytesread==-1) {
+ perror("read");
+ return -1;
+ }
+ if (bytesread) {
+ if (!quiet && !reexec)
+ write(1,buf,bytesread);
+ if (quiet) {
+ output = 1;
+ write(outpipe[1],buf,bytesread);
+ }
+ while ((tmpstr=getLine(&buf))) {
+ if (!reexec)
+ logString(cmdname,tmpstr);
+ else {
+ char **cmdargs=NULL;
+ char **tmpargs=NULL;
+ int cmdargc,x;
+
+ poptParseArgvString(tmpstr,&cmdargc,&tmpargs);
+ cmdargs=malloc( (cmdargc++) * sizeof(char *) );
+ cmdargs[0]=strdup("initlog");
+ for (x=0;x<(cmdargc-1);x++) {
+ cmdargs[x+1]=tmpargs[x];
+ }
+ processArgs(cmdargc,cmdargs);
+ }
+ }
+ }
+
+ } while ( bytesread==2048 );
+ }
+ y++;
+ }
+ }
+ rc = rc>>8;
+
+ if (!rc)
+ return 0;
+ else {
+ /* If there was an error and we're quiet, be loud */
+ int x;
+
+ if (quiet && output) {
+ buf=calloc(2048,sizeof(char));
+ do {
+ x=read(outpipe[0],buf,2048);
+ write(1,buf,x);
+ buf=calloc(2048,sizeof(char));
+ } while (x==2048);
+ }
+ return (rc);
+ }
+}
+
+int runCommand(char *cmd, int reexec, int quiet) {
+ int fds[2];
+ int pid,x;
+ char **args, **tmpargs;
+ char *cmdname;
+
+ poptParseArgvString(cmd,&x,&tmpargs);
+ args = malloc((x+1)*sizeof(char *));
+ for ( pid = 0; pid < x ; pid++) {
+ args[pid] = strdup(tmpargs[pid]);
+ }
+ args[pid] = NULL;
+ if (strcmp(args[0],"sh") && strcmp(args[0],"/bin/sh"))
+ cmdname = basename(args[0]);
+ else
+ cmdname = basename(args[1]);
+ if ((cmdname[0] =='K' || cmdname[0] == 'S') && ( 30 <= cmdname[1] <= 39 )
+ && ( 30 <= cmdname[2] <= 39 ) )
+ cmdname+=3;
+ if (!reexec) {
+ pid=forkCommand(args,&fds[0],&fds[1],NULL,quiet);
+ x=monitor(cmdname,pid,2,fds,reexec,quiet);
+ } else {
+ setenv("IN_INITLOG","yes",1);
+ pid=forkCommand(args,NULL,NULL,&fds[0],quiet);
+ unsetenv("IN_INITLOG");
+ x=monitor(cmdname,pid,1,&fds[0],reexec,quiet);
+ }
+ return x;
+}
diff --git a/src/process.h b/src/process.h
new file mode 100644
index 00000000..6c796cb2
--- /dev/null
+++ b/src/process.h
@@ -0,0 +1,9 @@
+#ifndef PROCESS_H
+#define PROCESS_H
+
+
+#define CMD_FD 21
+
+int runCommand(char *cmd, int reexec, int quiet);
+
+#endif
diff --git a/sysconfig.txt b/sysconfig.txt
index aa0b5650..b385eefa 100644
--- a/sysconfig.txt
+++ b/sysconfig.txt
@@ -18,6 +18,12 @@ Files in /etc/sysconfig
42-year time offset is in effect; otherwise the normal
Unix epoch is assumed
+/etc/sysconfig/init:
+
+ BOOTUP=<some bootup mode>
+ BOOTUP=color means new (as of RH6.0) boot display. Anything
+ else means old-style display
+
/etc/sysconfig/keyboard:
@@ -300,7 +306,7 @@ Files in /etc/sysconfig/network-scripts/
LINGUAS= can be a : separated list of language codes
SYSTERM= use to set default TERM environment variable
- The above three variables are used in rc.sysinit.
+ The above four variables are used in rc.sysinit.
SYSFONT= any font that is legal when used as
/usr/sbin/setfont $SYSFONT ...