admin/0001755000000000000000000000000014675400254010654 5ustar rootrootadmin/runit-2.2.0/0000755000000000000000000000000014675400254012451 5ustar rootrootadmin/runit-2.2.0/doc/0000755000000000000000000000000014675400254013216 5ustar rootrootadmin/runit-2.2.0/doc/runsvchdir.8.html0000644000000000000000000000350014675400254016437 0ustar rootroot runsvchdir(8) manual page G. Pape
runit

Name

runsvchdir - change services directory of runsvdir(8)

Synopsis

runsvchdir dir

Description

dir is a services directory for the use with runsvdir(8). If dir does not start with a slash, it is searched in /etc/runit/runsvdir/. dir must not start with a dot.

runsvchdir switches to the directory /etc/runit/runsvdir/, copies current to previous, and replaces current with a symlink pointing to dir.

Normally /service is a symlink to current, and runsvdir(8) is running /service/.

Exit Codes

runsvchdir prints an error message and exits 111 on error. runsvchdir exits 0 on success.

Files

/etc/runit/runsvdir/previous
/etc/runit/runsvdir/current
/etc/runit/runsvdir/current.new

See Also

runsvdir(8), runit(8), runit-init(8), sv(8), runsv(8)

http://smarden.org/runit/

Author

Gerrit Pape <pape@smarden.org>


Table of Contents

admin/runit-2.2.0/doc/runsv.8.html0000644000000000000000000001605714675400254015440 0ustar rootroot runsv(8) manual page G. Pape
runit

Name

runsv - starts and monitors a service and optionally an appendant log service

Synopsis

runsv service

Description

service must be a directory.

runsv switches to the directory service and starts ./run. If ./run exits and ./finish exists, runsv starts ./finish. If ./finish doesn’t exist or ./finish exits, runsv restarts ./run.

If ./run or ./finish exit immediately, runsv waits a second before starting ./finish or restarting ./run.

Two arguments are given to ./finish. The first one is ./run’s exit code, or -1 if ./run didn’t exit normally. The second one is the least significant byte of the exit status as determined by waitpid(2); for instance it is 0 if ./run exited normally, and the signal number if ./run was terminated by a signal. If runsv cannot start ./run for some reason, the exit code is 111 and the status is 0.

If the file service/down exists, runsv does not start ./run immediately. The control interface (see below) can be used to start the service and to give other commands to runsv.

If the directory service/log exists, runsv creates a pipe, redirects service/run’s and service/finish’s standard output to the pipe, switches to the directory service/log and starts ./run (and ./finish) exactly as described above for the service directory. The standard input of the log service is redirected to read from the pipe.

runsv maintains status information in a binary format (compatible to the daemontools’ supervise program) in service/supervise/status and service/log/supervise/status, and in a human-readable format in service/supervise/stat, service/log/supervise/stat, service/supervise/pid, service/log/supervise/pid.

Control

The named pipes service/supervise/control, and (optionally) service/log/supervise/control are provided to give commands to runsv. You can use sv(8) to control the service or just write one of the following characters to the named pipe:
u
Up. If the service is not running, start it. If the service stops, restart it.
d
Down. If the service is running, send it a TERM signal, and then a CONT signal. If ./run exits, start ./finish if it exists. After it stops, do not restart service.
o
Once. If the service is not running, start it. Do not restart it if it stops.
p
Pause. If the service is running, send it a STOP signal.
c
Continue. If the service is running, send it a CONT signal.
h
Hangup. If the service is running, send it a HUP signal.
a
Alarm. If the service is running, send it a ALRM signal.
i
Interrupt. If the service is running, send it a INT signal.
q
Quit. If the service is running, send it a QUIT signal.
1
User-defined 1. If the service is running, send it a USR1 signal.
2
User-defined 2. If the service is running, send it a USR2 signal.
t
Terminate. If the service is running, send it a TERM signal.
k
Kill. If the service is running, send it a KILL signal.
x
Exit. If the service is running, send it a TERM signal, and then a CONT signal. Do not restart the service. If the service is down, and no log service exists, runsv exits. If the service is down and a log service exists, runsv closes the standard input of the log service, and waits for it to terminate. If the log service is down, runsv exits. This command is ignored if it is given to service/log/supervise/control.

Example: to send a TERM signal to the socklog-unix service, either do # sv term /service/socklog-unix
or
# printf t >/service/socklog-unix/supervise/control

printf(1) usually blocks if no runsv process is running in the service directory.

Customize Control

For each control character c except "d" and "x" sent to the control pipe, runsv first checks if service/control/c exists and is executable. If so, it starts service/control/c and waits for it to terminate, before interpreting the command. If the program exits with return code 0, runsv refrains from sending the service the corresponding signal. The command o is always considered as command u. On command d first service/control/t is checked, and then service/control/d. On command x first service/control/t is checked, and then service/control/x. Specifically:

1.
runsv checks whether service/control/t exists and is executable and runs it if yes.
2.
If service/control/t exits nonzero, or is not executable or doesn't exist, runsv sends the service a TERM signal.
3.
runsv sends the service a CONT signal, disregarding service/control/c even if it exists and is executable.
4.
runsv checks whether service/control/d (or control/x) exists and is executable and runs it if yes. Its exit status is ignored.

The control of the optional log service cannot be customized.

Signals

If runsv receives a TERM signal, it acts as if the character x was written to the control pipe.

Exit Codes

runsv exits 111 on an error on startup or if another runsv is running in service.

runsv exits 0 if it was told to exit.

See Also

sv(8), chpst(8), svlogd(8), runit(8), runit-init(8), runsvdir(8), runsvchdir(8), utmpset(8)

http://smarden.org/runit/

Author

Gerrit Pape <pape@smarden.org>


Table of Contents

admin/runit-2.2.0/doc/runscripts.html0000644000000000000000000006247714675400254016340 0ustar rootroot runit - collection of run scripts G. Pape
runit
How to replace init

runit - collection of run scripts


This is a collection of run scripts for popular services to have them monitored by the daemontools or runit package. If you have additional run scripts or one of these run scripts works for you on an operating system not stated here, please let me know.

Thanks go to the following people for contributing run scripts: Alessandro Bono, Robin S. Socha, Claus Alboege, Paul Jarc, clemens fischer, Jesse Cablek, Lukas Beeler, Thomas Baden, Ralf Hildebrandt, Antonio Dias, Erich Schubert, Lang Martin, Tomasz Nidecki, Marek Bartnikowski, Thomas Schwinge, Gael Canal, Woon Wai Keen, Richard A Downing, Phil Genera, Stefan Karrmann, Kevin Berry, Karl Chen, Sascha Huedepohl, Jason Smith, Kevin, marlowe, ed neville, xavier dutoit.

See also here for some more run scripts.


atftpd
apache
apache2
atd
bind9
boa
cfengine
cfsd
chrony
clamav
clamsmtpd
courier-imap
cron
cups
dhclient
dhcpcd
dhcpd
dictd
dropbear
exim
expireproctitle
fam
fcron
fetchmail
gdm
getty
gpm
hotwayd
identd
inn
jabberd
junkbuster
kdm
keepalived
klogd
leafnode
logging Linux kernel messages
logging console messages
mdadm
minidentd
mpd
nscd
ntpd
nullidentd
polipo
pop3-ssl
pop3vscan
portmap
postfix
postgresql
powernowd
ppp
privoxy
proftpd
pure-ftpd
radiusd
rmrtg
rsyncd
samba (smbd, nmbd)
shoutcast
spamd
squid
sshd
sshd under tcpserver
statd, mountd
stunnel
subversion
swat
syslogd
taiclockd
tmda-ofmipd
tomcat
tor
vsftpd
wvdial
xdm
xfs

An atftpd run script

(Debian)
 #!/bin/sh
 exec in.tftpd --daemon --no-fork --tftpd-timeout 30 \
   --retry-timeout 5 --no-tsize --no-blksize --no-multicast \
   --maxthread 1000 --verbose=7 /var/atfpd 2>&1

An apache run script

(SunOS, Apache 1.*, patched to run under supervise)
 #!/bin/sh
 exec 2>&1
 exec env -i \
 /pack/apache/1.3.27-1/sbin/httpd -F 2>&1
(Debian woody)
 #!/bin/sh
 exec 1>&2
 exec apache-ssl -F

An apache2 run script

(SunOS)
 #!/bin/sh
 exec 2>&1
 exec env -i /command/pgrphack \
 /pack/apache/2.0.43-1/sbin/httpd -DFOREGROUND 2>&1
(HP-UX/GNU, Linux)
 #!/bin/sh
 TZ=MET-1METDST
 export TZ
 exec /usr/local/apache2/bin/httpd -DNO_DETACH

An atd run script

(Debian sarge)
 #!/bin/sh
 exec 2>&1
 exec atd -d

A bind9 run script

(Linux)
 #!/bin/sh
 MEM="`head -1 ./env/MEM`"
 CHROOT="`head -1 ./env/CHROOT`"
 exec softlimit -m "${MEM}" \
   named -u bind -t "${CHROOT}" -g 2>&1
(HP-UX/GNU, Linux)
 #!/bin/sh
 exec named -f -t /var/spool/named/ -u named

A boa run script

(SunOS)
 #!/bin/sh
 exec 2>&1
 ulimit -n 1024
 exec /pack/boa/current/boa -c /pack/boa/current -d 2>&1

A cfengine run script

(SunOS)
 #!/bin/sh
 /pack/cfengine/sbin/cfagent --file /pack/cfengine/etc/cfagent.conf \
   -L -v -q exec sleep 3600

A cfsd run script

(Debian sarge)
 #!/bin/sh
 exec 2>&1
 
 set -e
 
 PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
 DAEMON=cfsd
 CONFIG_FILE=/etc/cfs.conf
 
 # source config file
 test ! -r "$CONFIG_FILE" || . "$CONFIG_FILE"
 
 test -n "$CRYPT_ROOT" || exit 0
 test -n "$NULL_EXPORT" || exit 0
 test -n "$CFS_MOUNT" || exit 0
 test -n "$CFS_UMOUNT" || exit 0
 
 sv start portmap || exit 1
 
 exec env \
    NODAEMON=1 CFS_MOUNT="$CFS_MOUNT" CFS_UMOUNT="$CFS_UMOUNT" $DAEMON

A chrony run script

(LFS)
 #!/bin/sh
 exec 2>&1
 exec chronyd -d -r -s
This service needs a log service to be set up.

A clamd run script

(RedHat 7)
 #!/bin/sh
 exec 2>&1
 exec setuidgid clamav softlimit -a 40000000 clamd
This service needs a log service to be set up.

A clamsmtpd run script

(Debian sarge)
 #!/bin/sh
 exec 2>&1
 exec chpst -uclamav clamsmtpd -d 3
This service needs a log service to be set up.

A courier-imap run script

(SunOS)
 #!/bin/sh
 exec 2>&1
 PREFIX="/usr/lib/courier-imap"
 exec envdir ./env \
   tcpserver -v -R 0 143 \
   $PREFIX/sbin/imaplogin \
   $PREFIX/libexec/authlib/authshadow \
   $PREFIX/libexec/authlib/authvchkpw \
   $PREFIX/bin/imapd Maildir
See also this page.

A cron run script

(Debian sarge)
 #!/bin/sh
 exec 2>&1
 exec cron -f -l

A cups run script

(Debian woody)
 #!/bin/sh
 exec 2>&1
 exec cupsd -f

A dhclient run script

(Debian woody)
 #!/bin/sh
 exec dhclient -e -d -cf ./config -lf ./leases -pf ./pid eth1

A dhcpcd run script

(Linux, DHCP Client Daemon v.scriptconfig-0.1)
 #!/bin/sh
 exec dhcpcd -a -d -D -H eth0

A dhcpd run script

(Debian woody)
 #!/bin/sh
 exec 2>&1
 exec dhcpd-2.2.x -f -d -cf ./config eth0
This service needs a log service to be set up.

(Solaris 8, uses additional dsvclockd service, would get fired off automatically, but then it's not supervised)

 #!/bin/sh
 exec 2>&1
 exec envdir ./env /usr/lib/inet/dsvclockd -f
 #!/bin/sh
 if svok /service/dsvclockd; then
   sleep 2 # wait to make sure dsvclockd is initialized
   exec 2>&1
   exec envdir ./env /usr/lib/inet/in.dhcpd -b manual -d # -v
 fi
 echo dsvclockd is not running - aborting
 exec /usr/bin/sleep 5
The in.dhcpd service needs a log service to be set up.

A dictd run script

(Debian sarge)
 #!/bin/sh
 exec 2>&1
 exec dictd -d nodetach

A dropbear run script

(Linux)
 #!/bin/sh
 exec 2>&1
 exec dropbear -F -E -p 22
This service needs a log service to be set up.

(Linux, running under tcpsvd)

 #!/bin/sh
 exec 2>&1
 exec tcpsvd -v -i./peers 0 22 dropbear -i -E
This service needs a log service to be set up.

An exim run script

(Linux, FreeBSD)
 #!/bin/sh
 exec /usr/local/sbin/exim -bdf -q30m

expireproctitle run script examples

(Linux)
 #!/bin/sh
 echo -n .
 exec sleep 300

A fam run script

(Slackware Linux 9.0)
 #!/bin/sh
 exec 2>&1
 exec fam -L -f -v
This service needs a log service to be set up.

(Debian sarge)

 #!/bin/sh
 exec 2>&1
 sv start /service/portmap || exit 1
 exec famd -T 0 -f

A postfix master run script

(Debian etch)
 #!/bin/sh
 exec 1>&2
 
 daemon_directory=/usr/lib/postfix \
 command_directory=/usr/sbin \
 config_directory=/etc/postfix \
 queue_directory=/var/spool/postfix \
 mail_owner=postfix \
 setgid_group=postdrop \
   /etc/postfix/postfix-script check || exit 1
 
 exec /usr/lib/postfix/master

A fcron run script

(LFS)
 #!/bin/sh
 exec 2>&1
 exec fcron -f -y
This service needs a log service to be set up.

A fetchmail run script

(Linux)
 #!/bin/sh
 INTERVAL=551
 exec 2>&1
 echo "*** Starting fetchmail service..."
 exec env FETCHMAILHOME="./pid" \
   chpst -u fetchmail fetchmail -v \
     -f ./fetchmail.conf \
     --nodetach \
     --daemon ${INTERVAL}

A gdm run script

(Debian woody)
 #!/bin/sh
 exec gdm -nodaemon

A mingetty run script

(Debian)
 #!/bin/sh
 exec mingetty tty5
The runit package does not care about utmp records for getties. You should choose a getty that handles its own utmp and wtmp records. Debian's mingetty creates its own utmp record.

An agetty run script

(Slackware Linux 9.0)
 #!/bin/sh
 exec agetty 38400 tty1 linux

A fgetty run script

(Linux)
 #!/bin/sh
 exec chpst -P fgetty tty4
The runsv program does not automatically create a new session and separate process group for run scripts, which can cause some getties to fail due to limited permissions. The chpst program can be used to alter the process state for those getties.

A gpm run script

(LFS)
 #!/bin/sh
 exec 2>&1
 . /etc/sysconfig/mouse
 exec gpm -D -m $MDEVICE -t $PROTOCOL

A hotwayd run script

(LFS)
 #!/bin/sh
 exec 2>&1
 exec tcpsvd -l0 -u nobody 127.0.0.1 110 hotwayd

An oidentd run script

(Linux, oidentd version 2.0.6)
 #!/bin/sh
 exec 2>&1
 exec oidentd -i -S -t 10 -u daemon -g daemon
This service needs a log service to be set up.

(Debian)

 #!/bin/sh
 exec /usr/local/sbin/oidentd --nosyslog -i -u ident -g ident -l 15 -m \
   -C /etc/oidentd/oidentd.conf 2>&1
This service needs a log service to be set up.

An innd run script

(Linux)
 #!/bin/sh
 MEM="`head -1 ./env/MEM`"
 exec softlimit -m "${MEM}" \
   setuidgid news \
   /usr/sw/bin/news/inndstart -f -r

jabberd run scripts

(RedHat 7)
 #!/bin/sh
 exec 2>&1
 if [ -f /usr/local/jabber/jabber.pid ]; then
   rm /usr/local/jabber/jabber.pid
 fi
 exec setuidgid jabberd \
   /usr/local/jabber/jabberd/jabberd -D -c /etc/jabber.xml
This service needs a log service to be set up.
 #!/bin/sh
 exec 2>&1
 sleep 5 # so that jit starts after jabberd is up
 exec setuidgid jabberd \
   /usr/local/jabber/jit/jabberd/jabberd -c /etc/jit.xml
This service needs a log service to be set up.

A junkbuster run script

(Debian sarge)
 #!/bin/sh
 exec 2>&1
 DAEMON=junkbuster
 exec "$DAEMON" /etc/junkbuster/config

A kdm run script

(Debian sid, FreeBSD 5.3-REL)
 #!/bin/sh
 sv start /service/getty-* || exit 1
 exec kdm -nodaemon

A keepalived run script

(Linux)
 #!/bin/sh
 exec 2>&1
 exec keepalived -n

A klogd run script

(Debian woody)
 #!/bin/sh
 exec klogd -n

A leafnode run script

(Linux)
 #!/bin/sh
 exec 2>&1
 exec envuidgid news \
   tcpserver -v -x rules.cdb -c 10 -U 0 119 \
   leafnode
This service needs a log service to be set up.

A run script for logging Linux kernel messages with multilog

(Linux)
 #!/bin/sh -e
 exec < /proc/kmsg \
 setuidgid loguser \
 multilog t n64 ./main

A mdadm run script

(Debian sarge)
 #!/bin/sh
 DEBIANCONFIG=/etc/default/mdadm
 MAIL_TO=root
 test -f $DEBIANCONFIG && . $DEBIANCONFIG
 exec mdadm --monitor --scan --mail $MAIL_TO

A minidentd run script

(Linux)
 #!/bin/sh
 exec 2>&1
 exec envuidgid nobody \
   tcpserver -vUR 0 113 \
   timeoutafter 60 \
   minidentd -v
This service needs a log service to be set up.

A mpd run script

(Debian sid, FreeBSD 5.3-REL)
 #!/bin/sh
 MPDCONF=/etc/mpd.conf
 exec mpd --stdout --no-daemon $MPDCONF
This service needs a log service to be set up.

A nscd run script

(Debian sarge)
 #!/bin/sh
 secure=""
 for table in passwd group
   do
     if egrep '^'$table':.*nisplus' /etc/nsswitch.conf >/dev/null
       then
         nscd_nischeck $table || secure="$secure -S $table,yes"
     fi
 done
 exec nscd -d -- $secure

A ntpd run script

(Linux)
 #!/bin/sh
 MEM=`head -1 ./env/MEM`
 exec softlimit -m "${MEM}" \
   ntpd -n
(OpenNTPD on OpenBSD/Linux)
 #!/bin/sh
 exec /usr/sbin/ntpd -s -d 2>&1
This service needs a log service to be set up.

A nullidentd run script

(Debian sarge)
 #!/bin/sh
 exec 2>&1
 exec tcpsvd -u nobody -x nullidentd-cdb -t 60 0 113 nullidentd
This service needs a log service to be set up.

A polipo run script

(Linux)
 #!/bin/sh
 exec 2>&1
 exec setuidgid polipo \
   polipo -c config forbiddenFile="`pwd`"/forbidden diskCacheRoot="`pwd`"/cache
This service needs a log service to be set up.

A pop3-ssl run script

(BSD)
 #!/bin/sh
 exec tcpserver -R -v -c 50 0 995 /usr/local/sbin/stunnel
 -f  -p /etc/ssl/stunnel.pem \
 -l /var/qmail/bin/qmail-popup -- /var/qmail/bin/qmail-popup
 "`cat /var/qmail/control/me`" vchkpw /var/qmail/bin/qmail-pop3d Maildir 2>&1
This service needs a log service to be set up.

A pop3vscan run script

(RedHat 7)
 #!/bin/sh
 exec 2>&1
 exec setuidgid pop3vscan pop3vscan -d
This service needs a log service to be set up.

A portmap run script

(LFS, Debian sarge)
 #!/bin/sh
 exec 2>&1
 exec portmap -d

A postgresql run script

(Debian, SunOS)
 #!/bin/sh
 exec setuidgid postgres /usr/lib/postgresql/bin/postmaster \
   -D /var/lib/postgres/data 2>&1
This service needs a log service to be set up.

A powernowd run script

(Debian)
 #!/bin/sh
 set -e  # barf if modprobe fails
 modprobe cpufreq-userspace
 test ! -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ||
   exec /usr/sbin/powernowd -d
 
 echo "required sysfs objects not found!"
 echo "Read /usr/share/doc/powernowd/README.Debian for more information."
 sv down "$(pwd)"

A ppp run script

(FreeBSD)
 #!/bin/sh
 exec 2>&1
 echo "ppp -ddial dsl "
 exec ppp -unit0 -foreground dsl

A pppd run script

(Linux)
 #!/bin/sh
 exec 2>&1
 exec chpst -P pppd call isp nodetach

A privoxy run script

(Debian sarge)
 #!/bin/sh
 exec 2>&1
 exec chpst -u privoxy:nogroup privoxy --no-daemon /etc/privoxy/config
This service needs a log service to be set up.

A proftpd run script

(Linux, ProFTPD Version 1.2.8rc1, configure it to use 'ErrorLog "/dev/stdout"')
 #!/bin/sh
 exec 2>&1
 exec proftpd -n -d 1
This service needs a log service to be set up.

A pure-ftpd run script

(Debian woody)
 #!/bin/sh
 exec 2>&1
 exec pure-ftpd -a 50 -E -l pam -u 100

A radiusd run script

(Slackware Linux 9.0, cistron radius 1.6.1)
 #!/bin/sh
 exec 2>&1
 exec radiusd -f -y -z -lstdout
This service needs a log service to be set up.

A rmrtg run script

()
 #!/bin/sh
 MRTGUID=`id -u mrtg`
 MRTGGID=`id -g mrtg`
 exec 2>&1
 exec tcpserver -l 0 -R -H -q \
   -u"${MRTGUID}" -g"${MRTGGID}" 0 5660 /home/mrtg/ext/rmrtg

A rsyncd run script

(SunOS)
 #!/bin/sh
 exec 2>&1
 exec softlimit -d 100000000 tcpserver \
   -x /pack/rsync/rsync.service/tcp.rsync.cdb -v -c 100 -U -H -l 0 -R \
   1.2.3.4 873 nice -2 /pack/rsync/bin/rsync --daemon --no-detach \
   --config /pack/rsync/etc/rsyncd.conf
This service needs a log service to be set up.

A smbd run script

(Linux)
 #!/bin/sh
 PATH="/usr/local/samba/bin"
 exec 2>&1
 exec smbd -F -S -d3
This service needs a log service to be set up.

A nmbd run script

(Linux)
 #!/bin/sh
 PATH="/usr/local/samba/bin"
 exec 2>&1
 exec nmbd -F -S -d1
This service needs a log service to be set up.

A shoutcast run script

(RedHat 7)
 #!/bin/sh
 exec 2>&1
 exec setuidgid sc_serv \
   /usr/local/sc_serv/bin/sc_serv /etc/sc_serv.conf
This service needs a log service to be set up.

A spamd run script

(Debian woody)
 #!/bin/sh
 exec spamd -m 20 -a -H -s stderr 2>&1
This service needs a log service to be set up.

A squid run script

(Debian woody)
 #!/bin/sh
 exec squid -f ./config -sN

A sshd run script

(Debian)
 #!/bin/sh
 exec 2>&1
 exec /usr/sbin/sshd -D -e
This service needs a log service to be set up.

A sshd (under tcpserver) run script

(Linux, sshd version OpenSSH_3.4p1)
 #!/bin/sh -e
 exec 2>&1
 exec \
 tcpserver -1vpdl0 -Xxtcp.cdb 0 ssh \
 sshd -ief config
This service needs a log service to be set up.

A statd run script

(Debian woody)
 #!/bin/sh
 exec 2>&1
 NEED_LOCKD=yes
 if test -f /proc/ksyms; then
   # We need to be conservative and run lockd,
   # unless we can prove that it isn't required.
   grep -q lockdctl /proc/ksyms || NEED_LOCKD=no
 fi
 if [ "$NEED_LOCKD" = yes ]; then
   rpc.lockd
 fi
 exec rpc.statd -F -d
This service needs a log service to be set up.

A mountd run script

(Debian)
 #!/bin/sh
 sv start portmap statd || exit 1
 RPCNFSDCOUNT=8  # Number of servers to be started up by default
 RPCMOUNTDOPTS=
 
 trap '/usr/bin/killall -2 nfsd' 0
 trap 'exit 2' 1 2 3 15
 
 exportfs -r
 rpc.nfsd -- $RPCNFSDCOUNT
 rpcinfo -u localhost nfs 3 >/dev/null 2>&1 ||
   RPCMOUNTDOPTS="$RPCMOUNTDOPTS --no-nfs-version 3"
 exec rpc.mountd -F $RPCMOUNTDOPTS

A stunnel run script

(BSD)
 #!/bin/sh
 exec /usr/local/sbin/stunnel -f -d 1234 -r 25 -v3 -a /etc/ssl/mailcerts 2>&1

A svnserve run script

(Debian)
 #!/bin/sh
 exec 2>&1
 exec /usr/bin/svnserve -d --foreground

A swat run script

 #!/bin/sh
 exec 2>&1
 exec tcpsvd -l0 127.0.0.1 901 swat

A syslogd run script

(Debian sarge)
 #!/bin/sh
 exec syslogd -n

A taiclockd run script

 #!/bin/sh
 exec 2>&1
 exec setuidgid taiclock /usr/local/clockspeed/bin/taiclockd

A tmda-ofmipd run script

(RedHat 7)
 #!/bin/sh
 exec /usr/local/tmda/bin/tmda-ofmipd -f -d -R pop3 -p my.host.name:8025 2>&1
This service needs a log service to be set up.

A tomcat run script

(SunOS)
 #!/bin/sh
 exec 2>&1
 exec \
 setuidgid apache \
 /pack/tomcat/current/bin/catalina.sh run

A tor run script

(Debian sarge)
 #!/bin/sh
 exec 2>&1
 exec chpst -P -u debian-tor:debian-tor tor

A vsftpd run script

(RedHat 7)
 #!/bin/sh
 exec 2>&1
 exec tcpserver -c30 -Xv -llocalhost \
   -x/etc/tcp.ftp.cdb -uvsftpd -gvsftpd 0 ftp \
     softlimit -d300000 /var/vsftpd/bin/vsftpd
This service needs a log service to be set up.

A wvdial run script

(Slackware Linux 9.0, the service should have a down file, use svc -o /service/wvdial to bring up a ppp connection)
 #!/bin/sh
 exec 2>&1
 exec wvdial ISP
This service needs a log service to be set up.

A xdm run script

(Linux)
 #!/bin/sh
 sv start /service/vc-* || exit 1
 exec xdm -nodaemon

A xfs run script

(Debian sarge)
 #!/bin/sh
 SOCKET_DIR=/tmp/.font-unix
 mkdir -p $SOCKET_DIR
 chown 0:0 $SOCKET_DIR
 chmod 1777 $SOCKET_DIR
 exec /usr/bin/X11/xfs -nodaemon

Gerrit Pape <pape@smarden.org>
admin/runit-2.2.0/doc/runsvdir.8.html0000644000000000000000000000606414675400254016134 0ustar rootroot runsvdir(8) manual page G. Pape
runit

Name

runsvdir - starts and monitors a collection of runsv(8) processes

Synopsis

runsvdir [-P] dir [ log ]

Description

dir must be a directory. log is a space holder for a readproctitle log, and must be at least seven characters long or absent.

runsvdir starts a runsv(8) process for each subdirectory, or symlink to a directory, in the services directory dir, up to a limit of 1000 subdirectories, and restarts a runsv(8) process if it terminates. runsvdir skips subdirectory names starting with dots. runsv(8) must be in runsvdir’s PATH.

At least every five seconds runsvdir checks whether the time of last modification, the inode, or the device, of the services directory dir has changed. If so, it re-scans the service directory, and if it sees a new subdirectory, or new symlink to a directory, in dir, it starts a new runsv(8) process; if runsvdir sees a subdirectory being removed that was previously there, it sends the corresponding runsv(8) process a TERM signal, stops monitoring this process, and so does not restart the runsv(8) process if it exits.

If the log argument is given to runsvdir, all output to standard error is redirected to this log, which is similar to the daemontools’ readproctitle log. To see the most recent error messages, use a process-listing tool such as ps(1). runsvdir writes a dot to the readproctitle log every 15 minutes so that old error messages expire.

Options

-P
use setsid(2) to run each runsv(8) process in a new session and separate process group.

Signals

If runsvdir receives a TERM signal, it exits with 0 immediately.

If runsvdir receives a HUP signal, it sends a TERM signal to each runsv(8) process it is monitoring and then exits with 111.

See Also

sv(8), runsv(8), runsvchdir(8), runit(8), runit-init(8), chpst(8), svlogd(8), utmpset(8), setsid(2)

http://smarden.org/runit/

Author

Gerrit Pape <pape@smarden.org>


Table of Contents

admin/runit-2.2.0/doc/benefits.html0000644000000000000000000001774414675400254015720 0ustar rootroot runit - benefits G. Pape
runit

runit - benefits


Service supervision
Clean process state
Reliable logging facility
Fast system boot up and shutdown
Portability
Packaging friendly
Small code size

Service supervision

Each service is associated with a service directory, and each service daemon runs as a child process of a supervising runsv process running in this directory. The runsv program provides a reliable interface for signalling the service daemon and controlling the service and supervisor. Normally the sv program is used to send commands through this interface, and to query status informations about the service.

The runsv program supervises the corresponding service daemon. By default a service is defined to be up, that means, if the service daemon dies, it will be restarted. Of course you can tell runsv otherwise.

This reliable interface to control daemons and supervisors obsoletes pid-guessing programs, such as pidof, killall, start-stop-daemon, which, due to guessing, are prone to failures by design. It also obsoletes so called pid-files, no need for each and every service daemon to include code to daemonize, to write the new process id into a file, and to take care that the file is removed properly on shutdown, which might be very difficult in case of a crash.


Clean process state

runit guarantees each service a clean process state, no matter if the service is activated for the first time or automatically at boot time, reactivated, or simply restarted. This means that the service always is started with the same environment, resource limits, open file descriptors, and controlling terminals.

You don't necessarily have that with sysv init scripts for example. It requires a carefully written init script that reliably cleans up and sets the process state before starting the service daemon. This adds even more complexity to the init script in comparison with a run script used by runit. Many of today's init scripts don't provide a clean process state, here is an example on what could happen:

 # /etc/init.d/foo-daemon start
 Starting foo daemon: food.
 #
Fine. Everything works, nothing to worry about. After rebooting the system this shows up on the screen:
 ...
 Starting foo daemon: food: command not found
 failed.
 ...
The food program is installed in /opt/foo/bin/. When starting the service for the first time using the init script, the PATH environment variable contained /opt/foo/bin. After reboot init started the service using the init script, but with a different value for the PATH variable, not containing /opt/foo/bin. Of course the init script should have set PATH before starting the daemon; the problem is that it worked in the first place, and that the error didn't show up until system reboot.

With bad init scripts miraculous things could also happen when just doing

 # /etc/init.d/foo-daemon restart
at the command line.

The clean process state includes open file descriptors, obsoleting the widely used hack in many service daemons to force-close all file descriptors that might be open, up to the limit of available file descriptors for the daemon process (often results in 1024 unnecessary close() system calls in a great number of service daemon implementations).


Reliable logging facility

The runsv program provides a reliable logging facility for the service daemon. If configured, runsv creates a pipe, starts and supervises an additional log service, redirects the log daemon's standard input to read from the pipe, and redirects the service daemon's standard output to write to the pipe. Restarting the service does not require restarting the log service, and vice versa. A good choice for a log daemon is runit's service logging daemon svlogd.

The service daemon and the log daemon can run with different process states, and under different user id's. runit supports easy and reliable logging for service daemons running chroot'ed.

If runsv is told to shutdown a service, e.g. at system shutdown, it ensures that the log service stays up as long as the corresponding service daemon is running and possibly writing to the log.


Fast system boot up and shutdown

After the system's one time tasks (stage 1) are done, the system services are started up in parallel. The operating system's process scheduler takes care of having the services available as soon as possible.

On system shutdown, stage 3 uses runsv's control interface to wait until each service daemon is terminated and all logs are written. Again, services are taken down in parallel. As soon as all services are down, system halt or system reboot is initiated.


Portability

runit comes ready-to-run for Debian GNU/Linux and BSD systems, and can easily be configured to run on other UNIX systems. The UNIX system's one time initialization tasks and tasks to shutdown the system must be identified and runit's stages 1 and 3 configured accordingly.

Stages 1 and 3 handle one time tasks. They only run for short and exit soon. Stage 2 handles the system's uptime tasks (via the runsvdir program) and is running the whole system's uptime.

runit's stage 2 is portable across UNIX systems. runit is well suited for server systems and embedded systems, and also does its job well on desktop systems.


Packaging friendly

runit's stages 1 and 3 are distribution specific. They normally are shell scripts, and an operating system distribution with software package management should adapt these scripts if they need support for their package management. The runit-run Debian package is an attempt to integrate runit into Debian GNU/Linux as an alternative to the default sysvinit.

Stage 2 is packaging friendly: all a software package that provides a service needs to do is to include a service directory in the package, and to provide a symbolic link to this directory in /service/. The service will be started within five seconds, and automatically at boot time. The package's install and update scripts can use the reliable control interface to stop, start, restart, or send signals to the service. On package removal, the symbolic link simply is removed. The service will be taken down automatically.


Small code size

One of the runit project's principles is to keep the code size small. As of version 1.0.0 of runit, the runit.c source contains 330 lines of code; the runsvdir.c source is 274 lines of code, the runsv.c source 509. This minimizes the possibility of bugs introduced by programmer's fault, and makes it more easy for security related people to proofread the source code.

The runit core programs have a very small memory footprint and do not allocate memory dynamically.


Gerrit Pape <pape@smarden.org>
admin/runit-2.2.0/doc/upgrade.html0000644000000000000000000001254314675400254015540 0ustar rootroot runit - upgrading from previous versions G. Pape
runit

runit - upgrading from previous versions


2.1.x to 2.2.0

The chpst program learned a new option -C to run a program in a sepcific working directory, and the runit program now respects the magic file /etc/runit/nosync to make sync (commit filesystem caches to disk) on shutdown and reboot optional.

2.0.0 to 2.1.2

The chpst program learned a new option -b to run a program with a different name as the 0th argument.

1.9.0 to 2.0.0

No further action from you is required.

1.8.0 to 1.9.0

The default directory for services is now /service/, and no longer /var/service/. To be consistent with the new default location, create a symlink when upgrading
 # ln -s /var/service /
When installing runit on a system that should comply with the Filesystem Hierarchy Standard (FHS), neither /service/ nor /var/service/ should be chosen, but /etc/service/. It is recommended to create a compatibility symlink /service pointing to /etc/service in this case.

1.7.x to 1.8.0

The runit program, the process no 1, has been fixed to reap dead processes that re-parented to process no 1 (zombies) more thoroughly. Instructions on how to run runit with upstart as init scheme have been added, svlogd has been changed to use a new source port for each log message sent through udp, and this release includes a build fix for AIX.

1.6.0 to 1.7.x

With this version the runsv program starts to run the ./finish script with two arguments, the exit code and the exit status of the just finished ./run script. The timestamp svlogd optionally prepends to log messages can be specified to be in iso 8601 alike format. See the man pages for details.

1.5.x to 1.6.0

svlogd has been changed to prepend the optional timestamp also to log messages sent to the network through UDP, just as it does for log messages written to a log directory or standard error.

1.4.0 or 1.4.1 to 1.5.x

The svlogd program supports a new configuration option p to optionally prefix each line written to logs, standard error, or through UDP with a string, and no longer strips empty lines from the logs.

1.3.x to 1.4.0 or 1.4.1

With this version the runsvctrl, runsvstat, svwaitdown, and svwaitup programs no longer are being installed, the functionality of these programs has been incorporated into the sv program. The documentation now suggest to put service directories by default into the /etc/sv/ directory, and a list of frequently asked questions with answers has been added. The chpst program understands a new option -d to limit memory of the data segment per process.

1.2.x to 1.3.x

This release introduces a first test version of the sv program, which can be used to control the state and query the status of services monitored by runsv. Optionally it can be sym-linked into /etc/init.d/ to provide an interface to LSB init script actions for services controlled by runit. See the man page for details. Thanks to Lars Uffmann, instructions on how to run runit under launchd on MacOSX 10.4 have been added.

1.1.0 to 1.2.x

With this version the runsv program makes controlling the service through commands normally sent by runsvctrl configurable; arbitrary actions through external programs can optionally be specified, and signalling of the service disabled if desired. See the man page for details.

runsv now reports the seconds since ./run has been started when running the ./finish script, instead of the seconds since ./finish has been started. It no longer reports immediately failing ./run scripts as ``running'' for up to one second, but as ``down, normally up, want up''.

1.0.x to 1.1.0

The svlogd program now interprets the ``e'' and ``E'' configuration options so that they can be combined to select or deselect log messages to be written to standard error, similar to the ``+'' and ``-'' options for the rotated log. It also provides the new ``t'' and ``N'' configuration options, see the man page for details. The chpst program supports adjusting the nice level through the new -n command line option.

Starting with this version, /etc/runit/2 by default runs the runsvdir program with the -P option. To adapt edit /etc/runit/2 and change the invocation of runsvdir accordingly, see here.


Gerrit Pape <pape@smarden.org>
admin/runit-2.2.0/doc/runit-init.8.html0000644000000000000000000000416114675400254016356 0ustar rootroot runit-init(8) manual page G. Pape
runit

Name

init - a UNIX process no 1

Synopsis

init [ 0 | 6 ]

Description

runit-init is the first process the kernel starts. If runit-init is started as process no 1, it runs and replaces itself with runit(8).

If runit-init is started while the system is up, it must be either called as init 0 or init 6:

init 0
tells the Unix process no 1 to shutdown and halt the system. To signal runit(8) the system halt request, runit-init removes all permissions of the file /etc/runit/reboot (chmod 0), and sets the execute by owner permission of the file /etc/runit/stopit (chmod 100). Then a CONT signal is sent to runit(8).
init 6
tells the Unix process no 1 to shutdown and reboot the system. To signal runit(8) the system reboot request, runit-init sets the execute by owner permission of the files /etc/runit/reboot and /etc/runit/stopit (chmod 100). Then a CONT signal is sent to runit(8).

Exit Codes

runit-init returns 111 on error, 0 in all other cases.

See Also

runit(8), runsvdir(8), runsvchdir(8), sv(8), runsv(8), chpst(8), utmpset(8), svlogd(8)

http://smarden.org/runit/

Author

Gerrit Pape <pape@smarden.org>


Table of Contents

admin/runit-2.2.0/doc/debian0000777000000000000000000000000014675400254016513 2../etc/debianustar rootrootadmin/runit-2.2.0/doc/chpst.8.html0000644000000000000000000001445314675400254015402 0ustar rootroot chpst(8) manual page G. Pape
runit

Name

chpst - runs a program with a changed process state

Synopsis

chpst [-vVP012] [-u user] [-U user] [-b argv0] [-e dir] [-/ root] [-C pwd] [-n inc] [-l|-L lock] [-m bytes] [-d bytes] [-o n] [-p n] [-f bytes] [-c bytes] [-t seconds] prog

Description

prog consists of one or more arguments.

chpst changes the process state according to the given options, and runs prog.

Options

-u [:]user[:group]
setuidgid. Set uid and gid to the user’s uid and gid, as found in /etc/passwd. If user is followed by a colon and a group, set the gid to group’s gid, as found in /etc/group, instead of user’s gid. If group consists of a colon-separated list of group names, chpst sets the group ids of all listed groups. If user is prefixed with a colon, the user and all group arguments are interpreted as uid and gids respectively, and not looked up in the password or group file. All initial supplementary groups are removed.
-U [:]user[:group]
envuidgid. Set the environment variables $UID and $GID to the user’s uid and gid, as found in /etc/passwd. If user is followed by a colon and a group, set $GID to the group’s gid, as found in /etc/group, instead of user’s gid. If user is prefixed with a colon, the user and group arguments are interpreted as uid and gid respectively, and not looked up in the password or group file.
-b argv0
argv0. Run prog with argv0 as the 0th argument.
-e dir
envdir. Set various environment variables as specified by files in the directory dir: If dir contains a file named k whose first line is v, chpst removes the environment variable k if it exists, and then adds the environment variable k with the value v. The name k must not contain =. Spaces and tabs at the end of v are removed, and nulls in v are changed to newlines. If the file k is empty (0 bytes long), chpst removes the environment variable k if it exists, without adding a new variable.
-/ root
chroot. Change the root directory to root before starting prog.
-C pwd
chdir. Change the working directory to pwd before starting prog. When combined with -/, the working directory is changed after the chroot.
-n inc
nice. Add inc to the nice(2) value before starting prog. inc must be an integer, and may start with a minus or plus.
-l lock
lock. Open the file lock for writing, and obtain an exclusive lock on it. lock will be created if it does not exist. If lock is locked by another process, wait until a new lock can be obtained.
-L lock
The same as -l, but fail immediately if lock is locked by another process.
-m bytes
limit memory. Limit the data segment, stack segment, locked physical pages, and total of all segment per process to bytes bytes each.
-d bytes
limit data segment. Limit the data segment per process to bytes bytes.
-o n
limit open files. Limit the number of open file descriptors per process to n.
-p n
limit processes. Limit the number of processes per uid to n.
-f bytes
limit output size. Limit the output file size to bytes bytes.
-c bytes
limit core size. Limit the core file size to bytes bytes.
-t seconds
limit CPU time. Limit CPU time to seconds seconds, delivering a SIGXCPU thereafter.
-v
verbose. Print verbose messages to standard error. This includes warnings about limits unsupported by the system.
-V
version string. Print a version string to standard error.
-P
pgrphack. Run prog in a new process group.
-0
Close standard input before starting prog.
-1
Close standard output before starting prog.
-2
Close standard error before starting prog.

Exit Codes

chpst exits 100 when called with wrong options. It prints an error message and exits 111 if it has trouble changing the process state. Otherwise its exit code is the same as that of prog.

Emulation

If chpst is called as envdir, envuidgid, pgrphack, setlock, setuidgid, or softlimit, it emulates the functionality of these programs from the daemontools package respectively.

See Also

sv(8), runsv(8), setsid(2), runit(8), runit-init(8), runsvdir(8), runsvchdir(8)

http://smarden.org/runit/
http://cr.yp.to/daemontools.html

Author

Gerrit Pape <pape@smarden.org>


Table of Contents

admin/runit-2.2.0/doc/faq.html0000644000000000000000000003045214675400254014657 0ustar rootroot runit - Frequently asked questions G. Pape
runit

runit - Frequently asked questions


What's runit, why is it that different
I need some help with runit, what should I do
What's the license, is runit free software

How do I run a service under runit service supervision
How do I create a new service directory
How do I create a new service directory with an appendant log service
How do I tell runit about a new service
How do I start, stop, or restart a service
How can I send signals to a service daemon
How can I query the status of a service
How do I remove a service

How do I make a service depend on another service

What about runlevels
What about LSB init scripts compliance

Is it possible to allow a user other than root to control a service
Does runit support user-specific services?
Does runit work on a read-only filesystem


What's runit, why is it that different

What is this runit init scheme about? Why is it that different from sysvinit and other init schemes?

Answer: Please see the introduction, and web page about runit's benefits.


I need some help with runit, what should I do

I have a question, runit is doing something wrong, or I'm doing something wrong, what should I do?

Answer: First see the documentation, especially this list of frequently asked questions, and the man pages if you have a question about a specific runit program. If that still doesn't answer your question, try to search the supervision mailing list archive. Finally, if this fails, feel free to post your question to the supervision mailing list.


What's the license, is runit free software

I would like to distribute runit, in source and binary form. Am I allowed to do so?

Answer: runit is free software, it's licensed under a three-clause BSD alike license. See the file package/COPYING in the runit tarball.


How do I run a service under runit service supervision

I want a service to be run under runit service supervision, so that it's automatically started on system boot, and supervised while system uptime. How does that work?

Answer: runit doesn't use the usual /etc/init.d/ init script interface, but uses a directory per service. To integrate a service into the runit init scheme, create a service directory for the service, and tell runit about it.


How do I create a new service directory

How do I create a service directory for the use with runit?

Answer: Service directories usually are placed into the /etc/sv/ directory. Create a new directory for your service in /etc/sv/, put a ./run script into it, and make the script executable. Note that for the use with runit, service daemons must not put themself into the background, but must run in the foreground. Here's a simple example for a getty service:

 $ cat /etc/sv/getty-2/run
 #!/bin/sh
 exec getty 38400 tty2 linux
 $ 
Note the exec in the last line, it tells the shell that interprets the script to replace itself with the service daemon getty; this is necessary to make controlling the service work properly.

How do I create a new service directory with an appendant log service

How do I create a service directory with an appendant log service for the use with runit?

Answer: First create the service directory for the service. Then create a subdirectory ./log in the service directory, again put a ./run script into it, and make the script executable. The ./run script must run a service logging daemon, normally this is the svlogd program. See the runsv man page for details. Here's an example of a ./log/run script:

 $ cat /etc/sv/socklog-klog/log/run
 #!/bin/sh
 exec chpst -ulog svlogd -tt ./main
 $ 

How do I tell runit about a new service

I created a service directory for a service that should run under runit service supervision. How do I tell runit about the new service directory, so that it picks up and runs the service by default?

Answer: Create a symbolic link in /service/ pointing to the service directory, runit will pick up the service within the next five seconds, and automatically start it on system boot. E.g.:

 # ln -s /etc/sv/getty-2 /service/

How do I start, stop, or restart a service

I want to stop a service temporarily, and probably restart is later, or I want to have it restarted immediately. How can I control a service running under runit service supervision?

Answer: Use the sv program. E.g., to restart the socklog-unix service, do:

 # sv restart socklog-unix

How can I send signals to a service daemon

I want to send a service daemon the HUP signal, to have it re-read its configuration, or I want to send it the INT signal. How can a send signals to a service daemon?

Answer: Use the sv program. E.g., to send the dhcp service the HUP signal, do:

 # sv hup dhcp

How can I query the status of a service

I want to now the status of a service, whether it is up and available, or down as requested, or so. How can I find out this information?

Answer: User the sv program. E.g., to query or check the status of the socklog-unix service, do:

 # sv status socklog-unix
or
 # sv check socklog-unix

How do I remove a service

I want to remove a service that currently runs under runit service supervision. How do I tell runit?

Answer: Remove the symbolic link in /service/ pointing to the service directory, runit recognizes the removed service within the next five seconds, then stops the service, the optional log service, and finally the supervisor process. E.g.:

 # rm /service/getty-2

How do I make a service depend on another service

I have a service that needs another service to be available before it can start. How can I tell runit about this dependency?

Answer: Make sure in the ./run script of the dependant service that the service it depends on is available before the service daemon starts. The sv program can be used for that. E.g. the cron service wants the socklog-unix system logging service to be available before starting the cron service daemon, so no logs get lost:

 $ cat /etc/sv/cron/run
 #!/bin/sh
 sv start socklog-unix || exit 1
 exec cron -f
 $ 
See also the documentation.

What about runlevels

Other init schemes support runlevels, what about runit?

Answer: runit supports runlevels, even more flexible than traditional init schemes. See the documentation.


What about LSB init scripts compliance

I know about the sv program to control a service, but have applications that rely on the /etc/init.d/ scripts interface as defined through LSB. Do I need to change the application to work with runit?

Answer: You don't need to change the application. The sv program supports the /etc/init.d/ script interface as defined through LSB. To make this script interface work for a service, create a symbolic link in /etc/init.d/, named as the service daemon, pointing to the sv program, e.g. for the cron service:

 # ln -s /bin/sv /etc/init.d/cron
 # /etc/init.d/cron restart
 ok: run: cron: (pid 5869) 0s
 # 

Is it possible to allow a user other than root to control a service

Using the sv program to control a service, or query its status informations, only works as root. Is it possible to allow non-root users to control a service too?

Answer: Yes, you simply need to adjust file system permissions for the ./supervise/ subdirectory in the service directory. E.g.: to allow the user burdon to control the service dhcp, change to the dhcp service directory, and do

 # chmod 755 ./supervise
 # chown burdon ./supervise/ok ./supervise/control ./supervise/status
This works similarly with groups, of course.

Does runit support user-specific services?

It's very nice to simply create symbolic links to add system-wide services. Does this work for user-specific services too?

Answer: Yes. E.g.: to provide the user floyd with facility to manage services through ~/service/, create a service runsvdir-floyd with the following run script and a usual log/run script, and tell runit about the service

 #!/bin/sh
 exec 2>&1
 exec chpst -ufloyd runsvdir /home/floyd/service
Now floyd can create services on his own, and manage them through symbolic links in ~/service/ to have them run under his user id.

Does runit work on a read-only filesystem

On my system /etc/ is mounted read-only by default. runit uses many files in /etc/ it needs to write to, like /etc/runit/stopit, and the ./supervise/ subdirectories in the service directories. How can I make runit work on my system?

Answer: Use symbolic links, runit deals with them well, even with dangling symlinks. E.g., make a ramdisk available at a moint point, say /var/run/, and create symbolic links for the files and directories that runit needs to write access to pointing into /var/run/:

 # ln -s /var/run/runit.stopit /etc/runit/stopit
 # ln -s /var/run/sv.getty-2 /etc/sv/getty-2/supervise

Gerrit Pape <pape@smarden.org>
admin/runit-2.2.0/doc/sv.8.html0000644000000000000000000002034114675400254014702 0ustar rootroot sv(8) manual page G. Pape
runit

Name

sv - control and manage services monitored by runsv(8)

Synopsis

sv [-v] [-w sec] command services

/etc/init.d/service [-w sec] command

Description

The sv program reports the current status and controls the state of services monitored by the runsv(8) supervisor.

services consists of one or more arguments, each argument naming a directory service used by runsv(8). If service doesn’t start with a dot or slash and doesn’t end with a slash, it is searched in the default services directory /service/, otherwise relative to the current directory.

command is one of up, down, status, once, pause, cont, hup, alarm, interrupt, 1, 2, term, kill, or exit, or start, stop, restart, shutdown, force-stop, force-reload, force-restart, force-shutdown.

The sv program can be sym-linked to /etc/init.d/ to provide an LSB init script interface. The service to be controlled then is specified by the base name of the ‘‘init script’’.

Commands

status
Report the current status of the service, and the appendant log service if available, to standard output.
up
If the service is not running, start it. If the service stops, restart it.
down
If the service is running, send it the TERM signal, and the CONT signal. If ./run exits, start ./finish if it exists. After it stops, do not restart service.
once
If the service is not running, start it. Do not restart it if it stops.
pause cont hup alarm interrupt quit 1 2 term kill
If the service is running, send it the STOP, CONT, HUP, ALRM, INT, QUIT, USR1, USR2, TERM, or KILL signal respectively.
exit
If the service is running, send it the TERM signal, and the CONT signal. Do not restart the service. If the service is down, and no log service exists, runsv(8) exits. If the service is down and a log service exists, runsv(8) closes the standard input of the log service and waits for it to terminate. If the log service is down, runsv(8) exits. This command is ignored if it is given to an appendant log service.

sv actually looks only at the first character of these commands.

Commands compatible to LSB init script actions

status
Same as status.
start
Same as up, but wait up to 7 seconds for the command to take effect. Then report the status or timeout. If the script ./check exists in the service directory, sv runs this script to check whether the service is up and available; it’s considered to be available if ./check exits with 0.
stop
Same as down, but wait up to 7 seconds for the service to become down. Then report the status or timeout.
reload
Same as hup, and additionally report the status afterwards.
restart
Send the commands term, cont, and up to the service, and wait up to 7 seconds for the service to restart. Then report the status or timeout. If the script ./check exists in the service directory, sv runs this script to check whether the service is up and available again; it’s considered to be available if ./check exits with 0.
shutdown
Same as exit, but wait up to 7 seconds for the runsv(8) process to terminate. Then report the status or timeout.
force-stop
Same as down, but wait up to 7 seconds for the service to become down. Then report the status, and on timeout send the service the kill command.
force-reload
Send the service the term and cont commands, and wait up to 7 seconds for the service to restart. Then report the status, and on timeout send the service the kill command.
force-restart
Send the service the term, cont and up commands, and wait up to 7 seconds for the service to restart. Then report the status, and on timeout send the service the kill command. If the script ./check exists in the service directory, sv runs this script to check whether the service is up and available again; it’s considered to be available if ./check exits with 0.
force-shutdown
Same as exit, but wait up to 7 seconds for the runsv(8) process to terminate. Then report the status, and on timeout send the service the kill command.
try-restart
if the service is running, send it the term and cont commands, and wait up to 7 seconds for the service to restart. Then report the status or timeout.

Additional Commands

check
Check for the service to be in the state that’s been requested. Wait up to 7 seconds for the service to reach the requested state, then report the status or timeout. If the requested state of the service is up, and the script ./check exists in the service directory, sv runs this script to check whether the service is up and running; it’s considered to be up if ./check exits with 0.

Options

-v
If the command is up, down, term, once, cont, or exit, then wait up to 7 seconds for the command to take effect. Then report the status or timeout.
-w sec
Override the default timeout of 7 seconds with sec seconds. This option implies -v.

Environment

SVDIR
The environment variable $SVDIR overrides the default services directory /service/.
SVWAIT
The environment variable $SVWAIT overrides the default 7 seconds to wait for a command to take effect. It is overridden by the -w option.

Exit Codes

sv exits 0, if the command was successfully sent to all services, and, if it was told to wait, the command has taken effect to all services.

For each service that caused an error (e.g. the directory is not controlled by a runsv(8) process, or sv timed out while waiting), sv increases the exit code by one and exits non zero. The maximum is 99. sv exits 100 on error.

If sv is called with a base name other than sv: it exits 1 on timeout or trouble sending the command; if the command is status, it exits 3 if the service is down, and 4 if the status is unknown; it exits 2 on wrong usage, and 151 on error.

See Also

runsv(8), chpst(8), svlogd(8), runsvdir(8), runsvchdir(8), runit(8), runit-init(8)

http://smarden.org/runit/

Author

Gerrit Pape <pape@smarden.org>


Table of Contents

admin/runit-2.2.0/doc/install.html0000644000000000000000000000325614675400254015560 0ustar rootroot runit - installation G. Pape
runit

runit - installation


runit installs into /package. If you don't have a /package directory, create it now:
 # mkdir -p /package
 # chmod 1755 /package
Download runit-2.2.0.tar.gz into /package (sha256sum) and unpack the archive
 # cd /package
 # gunzip runit-2.2.0.tar
 # tar -xpf runit-2.2.0.tar
 # rm runit-2.2.0.tar
 # cd admin/runit-2.2.0
On MacOSX, do
 # echo 'cc -Xlinker -x' >src/conf-ld
 # cp src/Makefile src/Makefile.old
 # sed -e 's/ -static//' <src/Makefile.old >src/Makefile
Now compile and install the runit programs
 # package/install
If you want to make the man pages available in the /usr/local/man/ hierarchy, do:
 # package/install-man
To report success:
 # mail pape-runit-2.2.0@xxiv.smarden.org <compile/sysdeps
If you use runit regularly, please contribute to the project.

Refer to replacing init for replacing init with runit, or to use with traditional init for running runit's service supervision with your system's current init scheme.


Gerrit Pape <pape@smarden.org>
admin/runit-2.2.0/doc/utmpset.8.html0000644000000000000000000000405314675400254015755 0ustar rootroot utmpset(8) manual page G. Pape
runit

Name

utmpset - logout a line from utmp and wtmp file

Synopsis

utmpset [ -w ] line

Description

The utmpset program modifies the user accounting database utmp(5) and optionally wtmp(5) to indicate that the user on the terminal line has logged out.

Ordinary init(8) processes handle utmp file records for local login accounting. The runit(8) program doesn’t include code to update the utmp file, the getty(8) processes are handled the same as all other services.

To enable local login accounting, add utmpset to the getty(8) finish scripts, e.g.:

$ cat /service/getty-5/finish
#!/bin/sh
exec utmpset -w tty5
$

Options

-w
wtmp. Additionally to the utmp file, write an empty record for line to the wtmp file.

Exit Codes

utmpset returns 111 on error, 1 on wrong usage, 0 in all other cases.

See Also

sv(8), runsv(8), runit(8), runit-init(8) runsvdir(8), runsvchdir(8), chpst(8), svlogd(8), getty(8)

http://smarden.org/runit/

Author

Gerrit Pape <pape@smarden.org>


Table of Contents

admin/runit-2.2.0/doc/index.html0000644000000000000000000002624014675400254015217 0ustar rootroot runit - a UNIX init scheme with service supervision G. Pape

runit - a UNIX init scheme with service supervision


How to install runit
Upgrading from previous versions of runit

Benefits
How to replace init
How to use runit with current init
How to use dietlibc
Frequently asked questions

Runlevels
Service dependencies
A collection of run scripts

The runit program
The runit-init program

The sv program

The runsvdir program
The runsvchdir program
The runsv program

The svlogd program

The chpst program
The utmpset program


runit is a cross-platform Unix init scheme with service supervision, a replacement for sysvinit, and other init schemes. It runs on GNU/Linux, *BSD, MacOSX, Solaris, and can easily be adapted to other Unix operating systems. If runit runs for you on any other operating system, please let me know.
runit is discussed on the <supervision@list.skarnet.org> mailing list. Please contact this list and not me privately.

To subscribe send an empty email to <supervision-subscribe@list.skarnet.org>.

Mailing list archives are available at skarnet.org, and gmane.org.


The program runit is intended to run as Unix process no 1, it is automatically started by the runit-init /sbin/init-replacement if this is started by the kernel.

runit performs the system's booting, running and shutting down in three stages:

These are working examples for Debian sarge: /etc/runit/1, /etc/runit/2, /etc/runit/3.

The program runit-init is intended to replace /sbin/init. The command init 0 tells runit to halt the system, and init 6 to reboot. Runlevels are handled through the runsvdir and runsvchdir programs. Service dependencies are resolved automatically.

runit is optimized for reliability and small size. The amount of code in process no 1 should be minimal.


See How to install runit for installing runit, and How to replace init for configuring runit to run as process no 1. See How to use with current init if you want to use runit without replacing the current init scheme. Please read the list of Frequently asked questions with answers.
If runit on Linux is compiled and linked with the dietlibc, it yields in a statically linked runit binary of 8.5k size and this ps axuw output on my system:
 USER       PID %CPU %MEM   VSZ  RSS TTY      STAT START   TIME COMMAND
 root         1  0.0  0.0    20   16 ?        S     2002   0:02 runit
I recommend doing this; for instructions, see How to use dietlibc.
The following distributions are known to include or package runit: If you know of more distributions, please let me know.
runit in use: I replaced sysvinit successfully with runit on several server systems and a laptop running Debian/GNU Linux sarge, woody, and potato. Here is an example:
 # strings /proc/1/exe |grep Id
 $Id: runit.c,v 1.7 2002/02/13 09:59:52 pape Exp $
 # uptime
  11:59:13 up 365 days, 23:22,  3 users,  load average: 0.01, 0.02, 0.00
 # ps axuw |head -n20
 USER       PID %CPU %MEM   VSZ  RSS TTY      STAT START   TIME COMMAND
 root         1  0.0  0.0    20   16 ?        S     2002   0:07 runit
 root         2  0.0  0.0     0    0 ?        SW    2002   0:00 [keventd]
 root         3  0.0  0.0     0    0 ?        SWN   2002   0:51 [ksoftirqd_CPU0]
 root         4  0.0  0.0     0    0 ?        SW    2002 144:38 [kswapd]
 root         5  0.0  0.0     0    0 ?        SW    2002   0:08 [bdflush]
 root         6  0.0  0.0     0    0 ?        SW    2002   7:24 [kupdated]
 root       168  0.0  0.0  1652  168 ?        S     2002   0:27 /usr/sbin/cron
 root       174  0.0  0.0    36   24 ?        S     2002   1:06 runsvdir /var/service log: ...............................................................................................
 root       176  0.0  0.0    20   20 ?        S     2002   0:00 runsv qmail-send
 root       177  0.0  0.0    20   20 ?        S     2002   0:00 runsv getty-5
 root       178  0.0  0.0    20   20 ?        S     2002   0:00 runsv getty-4
 root       179  0.0  0.0    20   20 ?        S     2002   0:00 runsv getty-3
 root       180  0.0  0.0    20   20 ?        S     2002   0:00 runsv getty-2
 root       182  0.0  0.0    20   20 ?        S     2002   0:00 runsv socklog-unix
 root       183  0.0  0.0  1256    4 tty5     S     2002   0:00 /sbin/getty 38400 tty5 linux
 root       184  0.0  0.0  1256    4 tty3     S     2002   0:00 getty 38400 tty3 linux
 root       185  0.0  0.0    20   20 ?        S     2002   0:00 runsv socklog-klog
 root       186  0.0  0.0    20   20 ?        S     2002   0:00 runsv ssh
 root       187  0.0  0.0  1256    4 tty4     S     2002   0:00 getty 38400 tty4 linux
 # pstree
 runit-+-bdflush
       |-cron
       |-gcache
       |-keventd
       |-ksoftirqd_CPU0
       |-kswapd
       |-kupdated
       `-runsvdir-+-runsv-+-multilog
                  |       `-qmail-send-+-qmail-clean
                  |                    |-qmail-lspawn
                  |                    `-qmail-rspawn---qmail-remote
                  |-4*[runsv---getty]
                  |-2*[runsv-+-multilog]
                  |          `-socklog]
                  |-runsv-+-multilog
                  |       `-sshd-+-sshd---sshd---bash---bash---pstree
                  |              `-sshd---sshd---rsync
                  |-runsv---clockspeed
                  |-runsv-+-dnscache
                  |       `-multilog
                  |-runsv---apache-ssl-+-9*[apache-ssl]
                  |                    |-gcache
                  |                    `-4*[multilog]
                  |-7*[runsv-+-multilog]
                  |          `-tcpserver]
                  |-4*[runsv-+-multilog]
                  |          `-tinydns]
                  |-runsv---uncat
                  |-2*[runsv-+-multilog]
                  |          `-tcpsvd]
                  |-runsv-+-svlogd
                  |       `-tcpsvd-+-smtpfront-qmail
                  |                `-smtpfront-qmail---qmail-queue
                  `-runsv-+-svlogd
                          `-tcpsvd---bincimap-up---bincimapd

See http://smarden.org/runit/ for recent informations.
Related links:
Gerrit Pape <pape@smarden.org>
admin/runit-2.2.0/doc/svlogd.8.html0000644000000000000000000002731514675400254015560 0ustar rootroot svlogd(8) manual page G. Pape
runit

Name

svlogd - runit’s service logging daemon

Synopsis

svlogd [-tttv] [-r c] [-R xyz] [-l len] [-b buflen] logs

Description

logs consists of one or more arguments, each specifying a directory.

svlogd continuously reads log data from its standard input, optionally filters log messages, and writes the data to one or more automatically rotated logs.

Recent log files can automatically be processed by an arbitrary processor program when they are rotated, and svlogd can be told to alert selected log messages to standard error, and through udp.

svlogd runs until it sees end-of-file on standard input or is sent a TERM signal, see below.

Log Directory

A log directory log contains some number of old log files, and the current log file current. Old log files have a file name starting with @ followed by a precise timestamp (see the daemontools’ tai64n program), indicating when current was rotated and renamed to this file.

A log directory additionally contains the lock file lock, maybe state and newstate, and optionally the file config. svlogd creates necessary files if they don’t exist.

If svlogd has trouble opening a log directory, it prints a warning, and ignores this log directory. If svlogd is unable to open all log directories given at the command line, it exits with an error. This can happen on start-up or after receiving a HUP signal.

Log File Rotation

svlogd appends selected log messages to the current log file. If current has size bytes or more (or there is a new-line within the last len of size bytes), or is older than a specified amount of time, current is rotated:

svlogd closes current, changes permission of current to 0755, renames current to @timestamp.s, and starts with a new empty current. If svlogd sees num or more old log files in the log directory, it removes the oldest one. Note that this doesn’t decrease the number of log files if there are already more than num log files, this must be done manually, e.g. for keeping 10 log files:

ls -1 \@* |sort |sed -ne ’10,$p’ |xargs rm

Processor

If svlogd is told to process recent log files, it saves current to @timestamp.u, feeds @timestamp.u through ‘‘sh -c "processor"’’ and writes the output to @timestamp.t. If the processor finishes successfully, @timestamp.t is renamed to @timestamp.s, and @timestamp.u is deleted; otherwise @timestamp.t is deleted and the processor is started again. svlogd also saves any output that the processor writes to file descriptor 5, and makes that output available on file descriptor 4 when running processor on the next log file rotation.

A processor is run in the background. If svlogd sees a previously started processor still running when trying to start a new one for the same log, it blocks until the currently running processor has finished successfully. Only the HUP signal works in that situation. Note that this may block any program feeding its log data to svlogd.

Config

On startup, and after receiving a HUP signal, svlogd checks for each log directory log if the configuration file log/config exists, and if so, reads the file line by line and adjusts configuration for log as follows:

If the line is empty, or starts with a ‘‘#’’, it is ignored. A line of the form

ssize
sets the maximum file size of current when svlogd should rotate the current log file to size bytes. Default is 1000000. If size is zero, svlogd doesn’t rotate log files. You should set size to at least (2 * len).
nnum
sets the number of old log files svlogd should maintain to num. If svlogd sees more that num old log files in log after log file rotation, it deletes the oldest one. Default is 10. If num is zero, svlogd doesn’t remove old log files.
Nmin
sets the minimum number of old log files svlogd should maintain to min. min must be less than num. If min is set, and svlogd cannot write to current because the filesystem is full, and it sees more than min old log files, it deletes the oldest one.
ttimeout
sets the maximum age of the current log file when svlogd should rotate the current log file to timeout seconds. If current is timeout seconds old, and is not empty, svlogd forces log file rotation.
!processor
tells svlogd to feed each recent log file through processor (see above) on log file rotation. By default log files are not processed.
ua.b.c.d[:port]
tells svlogd to transmit the first len characters of selected log messages to the IP address a.b.c.d, port number port. If port isn’t set, the default port for syslog is used (514). len can be set through the -l option, see below. If svlogd has trouble sending udp packets, it writes error messages to the log directory. Attention: logging through udp is unreliable, and should be used in private networks only.
Ua.b.c.d[:port]
is the same as the u line above, but the log messages are no longer written to the log directory, but transmitted through udp only. Error messages from svlogd concerning sending udp packages still go to the log directory.
pprefix
tells svlogd to prefix each line to be written to the log directory, to standard error, or through UDP, with prefix.

If a line starts with a -, +, e, or E, svlogd matches the first len characters of each log message against pattern and acts accordingly:

-pattern
the log message is deselected.
+pattern
the log message is selected.
epattern
the log message is selected to be printed to standard error.
Epattern
the log message is deselected to be printed to standard error.

Initially each line is selected to be written to log/current. Deselected log messages are discarded from log. Initially each line is deselected to be written to standard err. Log messages selected for standard error are written to standard error.

Pattern Matching

svlogd matches a log message against the string pattern as follows:

pattern is applied to the log message one character by one, starting with the first. A character not a star (‘‘*’’) and not a plus (‘‘+’’) matches itself. A plus matches the next character in pattern in the log message one or more times. A star before the end of pattern matches any string in the log message that does not include the next character in pattern. A star at the end of pattern matches any string.

Timestamps optionally added by svlogd are not considered part of the log message.

An svlogd pattern is not a regular expression. For example consider a log message like this

2005-12-18_09:13:50.97618 tcpsvd: info: pid 1977 from 10.4.1.14

The following pattern doesn’t match

-*pid*

because the first star matches up to the first p in tcpsvd, and then the match fails because i is not s. To match this log message, you can use a pattern like this instead

-*: *: pid *

Options

-t
timestamp. Prefix each selected line with a precise timestamp (see the daemontools’ tai64n program) when writing to log or to standard error.
-tt
timestamp. Prefix each selected line with a human readable, sortable UTC timestamp of the form YYYY-MM-DD_HH:MM:SS.xxxxx when writing to log or to standard error.
-ttt
timestamp. Prefix each selected line with a human readable, sortable UTC timestamp of the form YYYY-MM-DDTHH:MM:SS.xxxxx when writing to log or to standard error.
-r c
replace. c must be a single character. Replace non-printable characters in log messages with c. Characters are replaced before pattern matching is applied.
-R xyz
replace charset. Additionally to non-printable characters, replace all characters found in xyz with c (default ‘‘_’’).
-l len
line length. Pattern matching applies to the first len characters of a log message only. Default is 1000.
-b buflen
buffer size. Set the size of the buffer svlogd uses when reading from standard input and writing to logs to buflen. Default is 1024. buflen must be greater than len. For svlogd instances that process a lot of data in short time, the buffer size should be increased to improve performance.
-v
verbose. Print verbose messages to standard error.

Signals

If svlogd is sent a HUP signal, it closes and reopens all logs, and updates their configuration according to log/config. If svlogd has trouble opening a log directory, it prints a warning, and discards this log directory. If svlogd is unable to open all log directories given at the command line, it exits with an error.

If svlogd is sent a TERM signal, or if it sees end-of-file on standard input, it stops reading standard input, processes the data in the buffer, waits for all processor subprocesses to finish if any, and exits 0 as soon as possible.

If svlogd is sent an ALRM signal, it forces log file rotation for all logs with a non empty current log file.

See Also

sv(8), runsv(8), chpst(8), runit(8), runit-init(8), runsvdir(8), runsvchdir(8)

http://smarden.org/runit/

Author

Gerrit Pape <pape@smarden.org>


Table of Contents

admin/runit-2.2.0/doc/replaceinit.html0000644000000000000000000002223414675400254016406 0ustar rootroot runit - replacing init G. Pape
runit

runit - replacing init


How to replace sysvinit on GNU/Linux
How to replace init on *BSD
How to replace init on MacOSX
How to replace init on Solaris

Replacing sysvinit (GNU/Linux)

Follow these steps to migrate from sysvinit to runit on Debian GNU/Linux (woody). The /sbin/init binary is not replaced until step 6, runit is the default Unix process no 1 after step 7.

If you have installed the precompiled Debian package, start at step 3.

Step 1: The three stages

runit looks for the three stages implementing the system's booting, running and shutdown in /etc/runit/1, /etc/runit/2 and /etc/runit/3, create the files now:
 # mkdir -p /etc/runit
 # cp -p /package/admin/runit/etc/debian/[123] /etc/runit/
Create also a getty service directory:
 # mkdir -p /etc/sv/getty-5
 # cp -p /package/admin/runit/etc/debian/getty-tty5/run /etc/sv/getty-5/
 # cp -p /package/admin/runit/etc/debian/getty-tty5/finish /etc/sv/getty-5/
If you want runit to handle the ctrl-alt-del keyboard request, do:
 # cp -p /package/admin/runit/etc/debian/ctrlaltdel /etc/runit/

Step 2: The runit programs

The runit programs must reside on the root partition, copy them to /sbin:
 # cp -p /package/admin/runit/command/runit* /sbin/

Step 3: The getties

At least one getty must run in stage 2 so that you are able to login. Choose a free tty, say tty5, where sysvinit is not running any getty (edit /etc/inittab and kill -HUP 1 if needed), and tell runsvdir about the getty-5 service:
 # mkdir -p /service
 # ln -s /etc/sv/getty-5 /service/
Start runit's stage 2 for testing:
 # /etc/runit/2 &
And check that the getty is running.

Step 4: Reboot into runit for testing

Boot your system with runit for the first time. This does not change the default boot behavior of your system, lilo will be told to use runit just once: If you are not using lilo as boot loader, refer to the documentation of your boot loader on how to pass init=/sbin/runit-init to the kernel.

Step 5: Service migration

The goal is to migrate all services from sysvinit scheme to the runit service supervision design; take a look at these run scripts for popular services. The migration can be done smoothly. For those services that are not migrated to use run scripts yet, add the corresponding init-script startup to /etc/runit/1, e.g.:
 #!/bin/sh
 # one time tasks

 /etc/init.d/kerneld start
 /etc/init.d/rmnologin

 touch /etc/runit/stopit
 chmod 0 /etc/runit/stopit
It is possible to just add /etc/init.d/rc 2 for having all services from the former runlevel 2 started as one time tasks, but keep the goal above in mind, supervising services has great advantages.

To migrate a service, create a service directory, disable the service if it is running, disable the service in /etc/rc.conf or remove the service startup from the /etc/rc.* scripts and tell runsvdir about the new service.

Repeat step 4 and 5, using /sbin/runit-init 6 to reboot the system, until you are satisfied with your services startup. If anything goes wrong, reboot the system into the default sysvinit /sbin/init and repair the runit stages, then start again at step 4.

Step 6: Replace /sbin/init

Now it is time to replace the sysvinit /sbin/init binary:
 # mv /sbin/init /sbin/init.sysv
 # ln -s runit-init /sbin/init

Step 7: Final reboot

The last step is to do the final reboot to boot the system with the new default Unix process no 1 runit.
 # init 6
To report success:
 # ( uname -a ; cat /etc/runit/[123] ) |mail pape-runit-2.2.0@xxiv.smarden.org

Replacing init (*BSD)

Follow these steps to migrate from init to runit on OpenBSD 2.9 or FreeBSD 4.4. The /sbin/init binary is not replaced until step 4.

Step 1: The three stages

runit looks for the three stages implementing the system's booting, running and shutdown in /etc/runit/1, /etc/runit/2 and /etc/runit/3 respectively. Create the scripts now:
 # mkdir -p /etc/runit

OpenBSD 2.9:
 # cp -p /package/admin/runit/etc/openbsd/[123] /etc/runit/

FreeBSD 4.4:
 # cp -p /package/admin/runit/etc/freebsd/[123] /etc/runit/
Remove the svscanboot startup from /etc/rc.local by deleting the line csh -cf '/command/svscanboot &' (this normally is the last one); runit will start runsvdir in stage 2 after running rc.local in stage 1.
 # vi /etc/rc.local

Step 2: The runit programs

The runit programs must reside on the root partition, install them into /sbin:
 # install -m0500 /package/admin/runit/command/runit* /sbin/

Step 3: The getties

At least one getty must run in stage 2 so that you are able to login. To have it run on the virtual console no 5, create the getty-5 service directory:
 # mkdir -p /etc/sv/getty-5

OpenBSD 2.9:
 # cp -p /package/admin/runit/etc/openbsd/getty-ttyC4/run /etc/sv/getty-5/
 # cp -p /package/admin/runit/etc/openbsd/getty-ttyC4/finish /etc/sv/getty-5/

FreeBSD 4.4:
 # cp -p /package/admin/runit/etc/freebsd/getty-ttyv4/run /etc/sv/getty-5/
 # cp -p /package/admin/runit/etc/freebsd/getty-ttyv4/finish /etc/sv/getty-5/
and tell runsvdir about the getty-5 service:
 # mkdir -p /service
 # ln -s /etc/sv/getty-5 /service/
Start runit's stage 2 for testing:
 # /etc/runit/2 &
And check that the getty is running.

Step 4: Replace the /sbin/init binary

Before replacing the init binary, make sure that you are able to boot your system alternatively, e.g. with a boot floppy, to restore the former /sbin/init if anything goes wrong.

Make a backup copy of the current /sbin/init program and replace it with /sbin/runit-init:

 # cp -p /sbin/init /sbin/init.bsd
 # install /sbin/runit-init /sbin/init
Boot your system with runit for the first time:
 # reboot
Watch the console output while runit boots up the system. Switch to the virtual console 5 (CTRL-ALT-F5) when stage 2 is reached, a getty should run there, you are able to login.

Use init 6 to reboot and init 0 to halt a system that runs runit. This will cause runit to enter stage 3 which runs /sbin/reboot or /sbin/halt as last command.

To report success:

 # ( uname -a ; cat /etc/runit/[123] ) |mail pape-runit-2.2.0@xxiv.smarden.org

Step 5: Service migration

The goal is to migrate all services from /etc/rc.* scheme to the runit service supervision design; take a look at these run scripts for popular services. The migration can be done smoothly. By default runit runs the /etc/rc scripts in stage 1 as a one time task, so the services are started automatically:
 #!/bin/sh
 # system one time tasks

 /bin/sh /etc/rc autoboot

 touch /etc/runit/stopit
 chmod 0 /etc/runit/stopit
To migrate a service, create a service directory, disable the service if it is running, disable the service in /etc/rc.conf or remove the service startup from the /etc/rc.* scripts and tell runsvdir about the new service.

Replacing init on MacOSX

Replacing init on MacOSX is not yet supported. Please refer to the instructions on how to use runit service supervision with the MacOSX init scheme.

Replacing init on Solaris

Replacing init on Solaris is not yet supported. Please refer to the instructions on how to use runit service supervision with the Solaris sysvinit scheme.
Gerrit Pape <pape@smarden.org>
admin/runit-2.2.0/doc/runlevels.html0000644000000000000000000000737514675400254016137 0ustar rootroot runit - runlevels G. Pape
runit

runit - runlevels


Prepare runit for using runlevels
Switching runlevels
Creating runlevels

Prepare runit

If not yet done, configure your system to use runit as process no 1 by following the instructions.

Create the following directories and symbolic links:

 # mkdir -p /etc/runit/runsvdir/default
 # mkdir -p /etc/runit/runsvdir/single
 # ln -s /etc/sv/getty-5 /etc/runit/runsvdir/single/
 # ln -s default /etc/runit/runsvdir/current
Copy the contents of /service/ to /etc/runit/runsvdir/current/ and replace /service/ with a symbolic link:
 # cp -pR /service/* /etc/runit/runsvdir/current/
 # mv -f /service /service.old && \
     ln -s /etc/runit/runsvdir/current /service
You have now created two runlevels: default and single. The current runlevel is default. It is safe to remove /service.old/ if you don't need it anymore.

Finally edit /etc/runit/2 to set the default runlevel when stage 2 starts:

 $ cat /etc/runit/2 
 #!/bin/sh
 PATH=/command:/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin
 
 runsvchdir default >/dev/null
 
 exec env - PATH=$PATH \
 runsvdir /service 'log: ...........................................................................................................................................................................................................................................................................................................................................................................................................'

Switching runlevels

Switching runlevels with runit is done by switching the directory the runsvdir program is running in. This is done by the runsvchdir program, e.g. to switch to the single user runlevel, do:
 # runsvchdir single
To switch back to the default runlevel, do:
 # runsvchdir default
See the runsvdir program for a description of what happens when runsvdir sees the directory changed. Note that there is no guarantee that all services from the previous runlevel will stop, the runsv processes have sent the service daemons a SIGTERM and wait for them to terminate. You can check the status of the previous runlevel through /etc/runit/runsvdir/previous/.

Creating new runlevels

To create a new runlevel, simply create a new directory in /etc/runit/runsvdir/. The name of the directory is the name of the new runlevel. The name must not start with a dot and must not be current, current.new, or previous, e.g.:
 # mkdir /etc/runit/runsvdir/maintenance
Add the services you want to run in the runlevel maintenance to the newly created directory, e.g.:
 # ln -s /etc/sv/getty-5 /etc/runit/runsvdir/maintenance/
 # ln -s /etc/sv/ssh /etc/runit/runsvdir/maintenance/
 # ln -s /etc/sv/dnscache /etc/runit/runsvdir/maintenance/
If you want to switch to the runlevel maintenance, do:
 # runsvchdir maintenance

Gerrit Pape <pape@smarden.org>
admin/runit-2.2.0/doc/useinit.html0000644000000000000000000000603514675400254015570 0ustar rootroot runit - use with traditional init G. Pape
runit

runit - use with traditional init


It's possible to use runit's service supervision without replacing the init scheme of the system. Simply run the stage 2 of runit as a service with your current init.

Normally this is done by either adding an entry for /sbin/runsvdir-start to /etc/inittab, or by adding /sbin/runsvdir-start as command to /etc/rc.local, or by adding /sbin/runsvdir-start to the system's StartupItems.

In any case, you first need to copy the stage 2 script to /sbin/runsvdir-start, and create the services directory /service/:

 # install -m0750 /package/admin/runit/etc/2 /sbin/runsvdir-start
 # mkdir -p /service

How to use with sysvinit and inittab
How to use with sysvinit and upstart
How to use with *BSD init
How to use with MacOSX init

Using with sysvinit and inittab

If your system uses a sysvinit alike init scheme with a /etc/inittab file, do:
 # cat >>/etc/inittab <<EOT
 SV:123456:respawn:/sbin/runsvdir-start
 EOT
and tell init to re-read its configuration, e.g.:
 # init q

Using with sysvinit and upstart

If your system uses a sysvinit alike init scheme that utilizes upstart instead of inittab, and which has start and stop scripts located in /etc/init/, do:
 # cat >/etc/init/runsvdir.conf <<\EOT
 # for runit - manage /usr/sbin/runsvdir-start
 start on runlevel 2
 start on runlevel 3
 start on runlevel 4
 start on runlevel 5
 stop on shutdown
 respawn
 exec /usr/sbin/runsvdir-start
 EOT
and tell init to start the new service, e.g.:
 # start runsvdir

Using with *BSD init

If your system uses a BSD alike init scheme with a /etc/rc.local script, do:
 # cat >>/etc/rc.local <<EOT
 csh -cf '/sbin/runsvdir-start &'
 EOT
and reboot your system.

Using with MacOSX init

On MacOSX 10.2 create an entry for runit in /System/Library/StartupItems/:
 # cd /System/Library/StartupItems
 # mkdir -p runit
 # cp -p /package/admin/runit/etc/macosx/StartupItems/* runit/
and reboot your system.

On MacOSX 10.4 create an entry for runit in /Library/LaunchDaemons/, and tell launchd to start the new service:

 # cp /package/admin/runit/etc/macosx/org.smarden.runit.plist \
     /Library/LaunchDaemons/
 # launchctl load /Library/LaunchDaemons/org.smarden.runit.plist

Gerrit Pape <pape@smarden.org>
admin/runit-2.2.0/doc/runit.8.html0000644000000000000000000000632114675400254015415 0ustar rootroot runit(8) manual page G. Pape
runit

Name

runit - a UNIX process no 1

Synopsis

runit

Description

runit must be run as Unix process no 1. It performs the system’s booting, running, and shutdown in three stages:

Stage 1

runit runs /etc/runit/1 and waits for it to terminate. The system’s one time tasks are done here. /etc/runit/1 has full control of /dev/console to be able to start an emergency shell if the one time initialization tasks fail. If /etc/runit/1 crashes, or exits 100, runit will skip stage 2 and enter stage 3.

Stage 2

runit runs /etc/runit/2, which should not return until system shutdown; if it crashes, or exits 111, it will be restarted. Normally /etc/runit/2 starts runsvdir(8). runit is able to handle the ctrl-alt-del keyboard request in stage 2, see below.

Stage 3

If runit is told to shutdown the system, or stage 2 returns, it terminates stage 2 if it is running, and runs /etc/runit/3. The systems tasks to shutdown and possibly halt or reboot the system are done here. If stage 3 returns, runit checks if the file /etc/runit/reboot exists and has the execute by owner permission set. If so, the system is rebooted, it’s halted otherwise. If /etc/runit/nosync exists, runit doesn’t invoke sync(). This is useful in vservers.

Ctrl-alt-del

If runit receives the ctrl-alt-del keyboard request and the file /etc/runit/ctrlaltdel exists and has the execute by owner permission set, runit runs /etc/runit/ctrlaltdel, waits for it to terminate, and then sends itself a CONT signal.

Signals

runit only accepts signals in stage 2.

If runit receives a CONT signal and the file /etc/runit/stopit exists and has the execute by owner permission set, runit is told to shutdown the system.

if runit receives an INT signal, a ctrl-alt-del keyboard request is triggered.

See Also

runit-init(8), runsvdir(8), runsvchdir(8), sv(8), runsv(8), chpst(8), utmpset(8), svlogd(8)

http://smarden.org/runit/

Author

Gerrit Pape <pape@smarden.org>


Table of Contents

admin/runit-2.2.0/doc/dependencies.html0000644000000000000000000000254614675400254016541 0ustar rootroot runit -service dependencies G. Pape
runit

runit - service dependencies


runit's service supervision resolves dependencies for service daemons designed to be run by a supervisor process automatically. The service daemon (or the corresponding run scripts) should behave as follows: If you want to run service daemons that do not support service supervision as described above, please refer to this page about service dependencies I wrote some time ago.
Gerrit Pape <pape@smarden.org>
admin/runit-2.2.0/doc/usedietlibc.html0000644000000000000000000000162514675400254016404 0ustar rootroot runit - use dietlibc G. Pape
runit

runit - use dietlibc


To recompile the runit programs with the diet libc, check that you have the recent version of dietlibc installed.

Change to the package directory of runit

 # cd /package/admin/runit/
Change the conf-cc and conf-ld to use diet
 # echo 'diet -Os gcc -O2 -Wall' >src/conf-cc
 # echo 'diet -Os gcc -s -Os -pipe' >src/conf-ld
Rebuild and install the runit programs
 # package/install

Gerrit Pape <pape@smarden.org>
admin/runit-2.2.0/package/0000755000000000000000000000000014675400254014044 5ustar rootrootadmin/runit-2.2.0/package/THANKS0000644000000000000000000000017414675400254014761 0ustar rootrootThanks to D. J. Bernstein for his daemontools package and for putting the daemontools' library code into the public domain. admin/runit-2.2.0/package/versions0000644000000000000000000000052214675400254015636 0ustar rootroot0.4.0 0.4.1 0.5.0 0.5.3 0.6.0 0.7.0 0.7.1 0.7.2 0.8.0 0.8.1 0.8.4 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5 0.10.0 0.11.0 0.11.1 0.11.2 0.12.0 0.12.1 0.13.0 0.13.1 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.5.0 1.5.1 1.6.0 1.7.0 1.7.1 1.7.2 1.8.0 1.9.0 2.0.0 2.1.0 2.1.1 2.1.2 2.2.0 admin/runit-2.2.0/package/upgrade0000755000000000000000000000137014675400254015422 0ustar rootroot#!/bin/sh set -e umask 022 test -d package || sh -cx '! : Wrong working directory.' test -d src || sh -cx '! : Wrong working directory.' here=`env - PATH=$PATH pwd` parent=`dirname $here` echo 'Creating symlink runit -> runit-2.2.0...' rm -f runit ln -s runit-2.2.0 runit mv -f runit .. echo 'Making command links in /command...' mkdir -p /command for i in `cat package/commands`; do rm -f /command/$i'{new}' ln -s $parent/runit/command/$i /command/$i'{new}' mv -f /command/$i'{new}' /command/$i done echo 'Making compatibility links in /usr/local/bin...' mkdir -p /usr/local/bin for i in `cat package/commands`; do rm -f /usr/local/bin/$i'{new}' ln -s /command/$i /usr/local/bin/$i'{new}' mv -f /usr/local/bin/$i'{new}' /usr/local/bin/$i done admin/runit-2.2.0/package/CHANGES0000644000000000000000000007417714675400254015057 0ustar rootroot2.2.0 Fri, 27 Sep 2024 00:38:25 +0000 * chpst.dist, sv.dist, svlogd.dist, utmpset.dist: adapt. * chpst.c, man/chpst.8: add -C option to change working directory (thx Andrew J. Hesford, void linux). * doc/install.html: add link to sha256sum. * doc/install.html, doc/replaceinit.html: change mail address. * package/TODO: remove. * package/README,COPYING: Copyright date. * chpst.c: fix compilation warning(s): -Wunsequenced (thx Dmitry Bogatov, Z. Liu). * svlogd.c: Initialize all fields of sockaddr_in (thx Érico Rolim). * sv.c: add sleep_microseconds to encapsulate (u|nano)sleep (thx Z. Liu). * chpst.c, chpst.dist, man/chpst.8: add options -t and -V to chpst man page and usage (thx Lorenzo Puliti, Z. Liu). * man/runsv.8: log service's ./finish script is actually not invoked (thx Jamie Heilman, Dmitry Bogatov, Z. Liu). * man/runsv.8: clarify how signal override works with control/d and x (thx Andras Korn, Lorenzo Puliti, Z. Liu). * runit.c, runit.h, man/runit.8: support /etc/runit/nosync file to make sync on shutdown/reboot optional (thx Andras Korn). * prot.c, prot.h, chkshsgr.c, tryshsgr.c: remove; obsolete. * Makefile, TARGETS: no longer check for "shortsetgroups" (thx Leah Neukirchen). * chpst.c: replace prot_uid() with setuid(). * utmpset.c: don't pass int32_t to time() (thx Lorenzo Beretta). * chpst.c, pathexec.h, pathexec_env.c, pathexec_run.c, runsvdir.c, sgetopt.c, sgetopt.h, subgetopt.c, subgetopt.h, sv.c, svlogd.c, utmpset.c: fix compilation warning(s): -Wincompatible-pointer-types- discards-qualifiers (thx Z. Liu, Debian, and others). * x86cpuid.c: fix error: call to undeclared library function '...'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] (thx Z. Liu, Debian, and others). * chpst.c, pathexec_run.c, prot.c, seek_set.c: fix error: call to undeclared function '...'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] (thx Z. Liu). * tryflock.c, trysgact.c, trysgprm.c, trywaitp.c: fix error: type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int [-Wimplicit-int] (thx Z. Liu and others). * chkshsgr.c, trycpp.c, trypoll.c, tryshsgr.c, tryulong64.c: fix error: call to undeclared function '...'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] (thx Z. Liu and others). 2.1.2 Sun, 10 Aug 2014 18:01:54 +0000 * doc/index.html: reorder, cleanup links to distributions; add Linux from Scratch, Finnix, VServer. * sv.c: properly format status command's output on failure cases. * sv.c: support optional LSB init script actions reload and try-restart. * man/sv.8: "sv exit" does not send a TERM signal to the log service (thx Jonathan Nieder). * fmt_ptime.c: 64 bits time_t fix for svlogd (tnx Jérémie Courrèges-Anglas). * sv.c: fix typo that may lead to wrong output from sv when reporting status of multiple service directories. * doc/index.html: add deepOfix Mail Server to list of distributions that include runit (thx Debayan Banerjee). * doc/useinit.html: update description on how to use with upstart (thx Gabriel de Perthuis). * doc/index.html: add Dragora GNU/Linux to list of distributions that use runit as default init scheme (thx Matias A. Fonzo). * doc/index.html: add ArchLinux to list of distributions that include runit (thx Kevin Berry). 2.1.1 Sun, 04 Oct 2009 20:28:38 +0000 * doc/upgrade.html: fix typo. * sv.c: on 'down', send runsv the 'down' command properly if not yet done (e.g. when taken up with 'once'). 2.1.0 Thu, 24 Sep 2009 22:49:33 +0000 * pathexec_env.c, pathexec.h: add function pathexec_env_run(). * chpst.c, man/chpst.8: new option -b argv0: run prog with different 0th argument. * sv.c: fix exit code of status command in lsb mode (thx Mathieu Poumeyrol) * chpst.c, svwaitdown.c, svwaitup.c: fix checks for return value of open_* functions (thx David Reiss). * runsv.c: exit with error if [log/]supervise/control exists, but is not a fifo (thx Charlie Brady). * man/sv.8: clarify which return values apply to the LSB init script interface. 2.0.0 Sun, 15 Jun 2008 15:31:05 +0000 1.9.0 Mon, 05 May 2008 22:00:13 +0000 * doc/upgrade.html: typo. * sv.c: service name is also relative to the current directory if it ends with a slash. * change default directory for services from /var/service/ to /service/. * runsv.c: create temporary new status files for log/supervise/ actually in log/supervise/. * doc/benefits.html: minor additions. 1.8.0 Fri, 21 Sep 2007 00:33:56 +0000 * man/svlogd.8: add hint on how to manually remove log files after the number of log files svlogd should maintain has been reduced; add hint about increasing the buffer size if lots of data is to be processed in short time. * chpst.c, uidgid.c: improve error reporting if getpwnam() or getgrnam() fails; cleanup. * svlogd.c: don't statically bind local udp socket, but request new source port for each log message sent through udp. * runit.c: fix typo in error messages (thx Matthew R. Dempsky); minor rewording. * doc/useinit.html: add instructions on how to use with upstart (thx Lloyd Zusman). * chpst.c: add explicit braces to avoid ambiguous 'else'. * uw_tmp.h1: fallback to UTMP_FILE if _PATH_UTMP is not defined as seen on AIX 5.2 ML1, AIX 5.3 ML5 (thx Daniel Clark). * sv.c: fix race on check for down if pid is 0 and state is run or finish. * runit.c: speed up collecting zombies. * runit.c: force check for zombies after a 14 second timeout without signals (CHLD, CONT, INT). * doc/index.html: typo. * doc/*.html: remove $Id$. 1.7.2 Tue, 21 Nov 2006 15:13:47 +0000 * doc/index.html: add list of distributions that are known to include or package runit; some reordering. * doc/replaceinit.html: point to faq.html#create, faq.html#tell (thx David Kaufman). * doc/runscripts.html: point to faq.html#createlog. * runit.c: fix arguments to wait_pid() after fork for reboot_system() (thx Jan Kampe). * man/runsv.8: suggest printf t instead of echo -n t. * runsv.c: really don't act on commands in state finish; minor. 1.7.1 Sat, 04 Nov 2006 19:23:29 +0000 * chpst.c, uidgid.c, uidgid.h: support numerical uid gid through chpst -[u|U] :uid:gid... * man/chpst.8: adapt; clarify that users and groups are looked up in /etc/passwd and /etc/group only. * sv.c: properly wait for a service to be restarted on 'restart'; support checks through -v for pause, cont, kill. * doc/runscripts.html: add contributed run scripts (thx Kevin, marlowe, ed neville, xavier dutoit). 1.7.0 Sat, 07 Oct 2006 18:24:17 +0000 * svlogd.c, fmt_ptime.*, man/svlogd.8: new option -ttt: prefix log messages with sortable UTC timestamp YYYY-MM-DDTHH:MM:SS.xxxxx. * runsv.c, runsv.8: give two arguments to ./finish: exit code and exit status of ./run (mostly copied from pipe-tools' npt-supervise, thx Laurent Bercot). * runit.c: don't make console the controlling terminal for process 1, but for stage 1 only; fork before initiating system halt or reboot, the linux kernel calls do_exit(0) in kernel/sys.c (thx Jan Kampe). 1.6.0 Thu, 29 Jun 2006 07:52:35 +0000 * svlogd.c: cleanup *.t files possibly leftover by processor when interrupted by signal, also on startup (thx Andras Korn, http://bugs.debian.org/369840); 1st rename .t to .s, then remove .u. * man/svlogd.8: adapt. * svlogd.c: prepend optional timestamp to log messages sent through UDP, as done for messages written to dir and to stderr. * uidgid.c: properly fixup user/group argument on getpwnam() error. * doc/benefits.html: typo; wording. 1.5.1 Wed, 10 May 2006 20:55:35 +0000 * runsv.c: delay restart of log service at least 1 sec, just as the main service. * runsvdir.c: don't double-copy filedescriptor. * package/README, package/COPYING: 2006. * man/runsvctrl.8, man/runsvstat.8, man/svwaitup.8, man/svwaitdown.8, doc/runsvctrl.html, doc/runsvstat.html, doc/svwaitdown.html, doc/svwaitup.html: remove; obsolete. 1.5.0 Sun, 16 Apr 2006 12:26:50 +0000 * man/runsvdir.8: document that the services directory is re-scanned if the time of last modification, the inode, or the device has changed. * sv.c: don't report success on 'sv start' if the service is in state finish (thx Matthew R. Dempsky). * svlogd.c: new config line p: optionally prefix each line written to logs, stderr, or through udp; no longer skip empty lines (just containing '\n'), old behavior can be restored with '-' in config. * man/svlogd.8: document new p config line; adapt. 1.4.1 Mon, 20 Mar 2006 18:54:41 +0000 * doc/faq.html: typos; add usercontrol, userservices; minor. * src/uidgid.h: use uid_t, git_t (fix setting of multiple groups with dietlibc, thx Tino Keitel, http://bugs.debian.org/356016) runit 1.4.0 Mon, 06 Mar 2006 12:45:08 +0000 * doc/faq.html: new. * doc/benefits.html: use sv program instead of runsvstat, runsvctrl; minor. * doc/replaceinit.html, doc/runlevels.html: put getty service directory into /etc/sv/. * doc/runscripts.html: use sv program instead of svwaitup. * etc/*/3, etc/macosx/StartupItems/runit: use sv program instead of svwaitdown. * man/runsv.8: use sv program instead of runsvctrl. * man/sv.8: minor. * Makefile, package/commands: no longer build/install runsvctrl, runsvstat, svwaitdown, svwaitup. * man/runsvctrl.8, man/runsvstat.8, man/svwaitdown.8, man/svwaitup.8: remove; obsolete. * doc/index.html: add faq; remove runsvctrl, runsvstat, svwaitdown, svwaitup. * sv: fix usage output. * chpst: new option -d, limit data segment per process; don't use nested functions. runit 1.3.3 Mon, 02 Jan 2006 20:35:34 +0000 * chpst.c: adjust nice value and set limits before dropping permissions. * sv.c: new additional command 'check'; with -v check for CONT through ./check if service is up. * man/sv.8: adapt. runit 1.3.2 Sun, 18 Dec 2005 11:22:04 +0000 * svlogd.c: don't print extra newlines to the log if additionally writing to the network through udp (thx Andras Korn, http://bugs.debian.org/339030). * runsvdir.c: also process svdir changes if mtime of svdir has changed into the past (thx Martin Dickopp). * doc/index.html: update description; Please contact this list and not me privately. * doc/replaceinit.html, doc/runscripts.html: minor. * man/chpst.8: -U doesn't support a list of groups. * man/svlogd.8: update PATTERN MATCHING section, add example (based on sugesstions from Joshua N Pritikin). * man/*8: update SEE ALSO sections: runsvctrl, runsvstat, svwaitdown, svwaitup will become obsolete; remove references to man pages for programs from the daemontools package. runit 1.3.1 Wed, 24 Aug 2005 20:14:17 +0000 * doc/runscripts.html: typo; openssh needs absolute path (thx Kevin Berry); exec into dhcpcd. * uidgid.c, uidgid.h, chpst.c: support colon-separated list of groups. * sv.c: utilize optional ./check script in service directory to check for availablity of service. * runsv.c: wait_pid() might be interupted. * man/chpst.8, man/sv.8: adapt. runit 1.3.0 Sun, 24 Jul 2005 16:50:55 +0000 * man/runsv.8: typo; no longer document the e control character; clarify custom control on d and x. * doc/useinit.html: how to use runit with macosx 10.4 (thx Lars Uffmann). * etc/macosx/org.smarden.runit.plist: new; launchd plist file for runsvdir-start (thx Lars Uffmann). * doc/runscripts.html: don't use absolute pathnames for programs in $PATH; add contributed run scripts (thx Sascha Huedepohl); typos. * runsvchdir.c, runsvstat.c: optimize output buffer handling. * runsvctrl.c: write x control character to runsv on e. * svlogd.c: write to log dir after possibly writing through udp (fixes line break issue). * runsv.c, runsv.check: optimize output buffer handling; porperly run custom t, d, x, k, when stopping service; no longer support e control character. * sv.c: new sv program to control services, optionally can be linked to /etc/init.d/ as lsb "init script" command line interface. * Makefile, TARGETS: adapt. * chpst.c: fix pointer types. * man/sv.8: new. * package/TODO: new. runit 1.2.3 Mon, 18 Apr 2005 17:08:35 +0000 * doc/runscripts.html: add contributed run scripts (thx Kevin Berry); remove mysql run scripts. * svlogd.dist, svwaitdown.dist, svwaitup.dist: fix program selftest's false alarms (thx Ian Stokes-Rees). runit 1.2.2 Sun, 03 Apr 2005 09:21:52 +0000 * doc/index.html, doc/replaceinit.html: no longer refer to sysvinit's shutdown program. * man/svlogd.8: svlogd doesn't decrease the number of log files in a log directory; with n0 don't remove any log files. * svlogd.c: properly prefix log messages written to standard error with optional timestamp. * runsvctrl.c, svwaitdown.c, svwaitup.c: supervise not running -> runsv not running. * package/README: 2005. runit 1.2.1 Sat, 15 Jan 2005 11:57:46 +0000 * chpst.c: typo. * svwaitdown.c: minimum timeout is 1 second; service directories no longer must start with /. * svwaitup.c: minimum uptime of services is 1 second; service directories no longer must start with /; print number of seconds a service is up if verbose. * man/svwaitdown.8, man/svwaitup.8: adapt. * doc/runscripts.html: add contributed run scripts (thx Stefan Karrmann, Kevin Berry, Karl Chen). * runsv.c: typos; bugfix: run optional control/x when receiving SIGTERM (thx Vladimir Smelhaus); minor. * man/runsvctrl.8: minor. * package/COPYING: adapt, 2005. runit 1.2.0 Fri, 17 Dec 2004 21:08:50 +0000 * doc/upgrade.html: typo. * runsv.c: support custom control commands through control/ directory, optionally switch off sending signal; don't update timestamp in status when running ./finish; only sleep for a second if ./run has been restarted within a second, and after updating status to down, normally up, want up. * man/runsv.8: document custom control commands. * runsv.check, runsv.dist: check custom control commands. * doc/runscripts.html: add contributed run scripts (thx Stefan Karrmann, Kevin Berry). runit 1.1.0 Sat, 06 Nov 2004 17:21:11 +0000 * svlogd.c: new config option t timeout (thx Enrico Scholz); config options e and E select and deselect lines for stderr respectively (thx Vladimir Smelhaus); new config option N. * man/svlogd.8: adapt. * runsv.c: on commands down and exit send CONT after TERM. * man/runsv.8: adapt. * etc/2: use -P option to runsvdir. * src/svlogd.check: add check for t config option. * chpst.c: new option -n: adjust nice level. * man/chpst.8: adapt. runit 1.0.5 Tue, 21 Sep 2004 18:18:14 +0000 * svlogd.c: fix line buffer handling for pattern matching (thx Enrico Scholz); properly retry writing to current on error; minor. * doc/index.html: wording; add link to useinit.html; remove link to runit on linuxfromscratch. * doc/runscripts.html: add hint, some getties need to be run in a new session/process group (thx Dan Melomedman). * man/svlogd.8: minor fixes. * man/svwaitdown.8: remove hint about -x option. * package/check, package/compile, package/install, package/install-man, package/upgrade: use set -e instead of #!/bin/sh -e. * runsvdir.c: new option -P, run each runsv process in a new session and process group (thx Charlie Brady). * man/runsvdir.8: adapt; typo. runit 1.0.4 Sun, 01 Aug 2004 18:29:36 +0000 * doc/runlevels.html, doc/upgrade.html, doc/useinit.html, man/runsvdir.8, man/runsvchdir.8: minor changes in wording, notations. * runsvdir.c: check services dir again after one second until it's unchanged (thx Eric Lammerts); sleep one second before scanning if services dir mtime is now; loop while chdir to starting dir fails; rename log, loglen to rplog, rploglen. * etc/macosx/StartupItems/runit: use -x option to svwaitdown; timeout 14. runit 1.0.3 Sat, 26 Jun 2004 14:50:41 +0000 * chpst.c, man/chpst.8: new option -/ chroot. * runit.c, man/runit.8: if stage 1 crashes or exits 100, stage 2 will be skipped; if stage 2 crashes or exits 111, it will be restarted. * package/check, package/compile, package/install-man, package/upgrade: minor cleanup. * doc/runscripts.html: add, adapt various run scripts (thx). runit 1.0.2 Mon, 29 Mar 2004 17:52:50 +0000 * man/svlogd.8: timestamps are not considered when matching patterns (thx Andras KORN). * runsv.c: on exit run the finish scripts when taking the service down (thx X.). * runsv.c, runsvctrl.c: handle sig_quit (thx Wayne Marshall). * svlogd.c: don't crash on zero byte long config file (thx Alex Efros). * man/*: minor cleanup. * doc/index.html: add link to runit on linuxfromscratch doc (thx Richard A Downing FBCS). runit 1.0.1 Sun, 07 Mar 2004 10:40:40 +0000 * doc/usedietlibc.html: minor. * fmt_ptime.c: create timestamps in UTC, not localtime. * chpst.c: -e dir: silently ignore directories, print warning if verbose. * runsv.c: allow also log/supervise to be a dangling symlink; more meaningful error message if opening lock or locking fails. * check-diff, check-dist, check-local, package/check: new; run checks on programs. * package/install: run package/check. * chpst.check, runit-init.check, runit.check, runsv.check, runsvchdir.check, runsvctrl.check, runsvdir.check, runsvstat.check, svlogd.check, svwaitdown.check, svwaitup.check, utmpset.check: new; check program. * chpst.dist, runit-init.dist, runit.dist, runsv.dist, runsvchdir.dist, runsvctrl.dist, runsvdir.dist, runsvstat.dist, svlogd.dist, svwaitdown.dist, svwaitup.dist, utmpset.dist: new; dist check program output. runit 1.0.0 Tue, 10 Feb 2004 13:37:28 +0000 * doc/benefits.html, doc/dependencies.html, doc/index.html, doc/replaceinit.html, doc/runlevels.html, doc/upgrade.html, doc/useinit.html: cleanup; minor. * man/utmpset.8: run utmpset in finish script, not run script. * man/runsvdir.8: minor. runit 0.13.1 Mon, 19 Jan 2004 18:32:58 +0000 * doc/upgrade.html: typo. * svlogd.c: bugfix: properly print new-line character to the log on end of line (thx Pawel Chmielowski). * trysocketlib.c: new; check for libraries needed for socket() on some systems (fixes link failure on solaris, thx Uffe Jakobsen). * Makefile: adapt. * print-cc.sh, print-ld.sh: head -1 -> head -n1. runit 0.13.0 Mon, 12 Jan 2004 14:39:38 +0000 * doc/runscripts.html: use html named entities (thx Taj Khattra); add more contributed run scripts (thx Marek Bartnikowski, Thomas Schwinge). * svlogd.c: support sending log entries to remote host through udp, configurable through u and U lines in log dir config file; minor. * man/svlogd.8: adapt; document -tt option. * package/compile, package/install-man, package/upgrade: exit 1 on sub-shell failures. * man/runsv.8: fix typos (thx Christian Hammers). runit 0.12.1 Tue, 18 Nov 2003 15:42:44 +0000 * doc/runscripts: add pppd run script (with chpst) next to the ppp one. * man/chpst.8: typo. * etc/debian/3: test -r -> test -x (thx Alejandro Mery). * runsv.c: don't start new processes while collecting children. runit 0.12.0 Wed, 29 Oct 2003 18:27:48 +0000 * runsv.c: don't use EOVERFLOW as it is not standard (thx Christoph Scheurer). * reboot_system.h1, reboot_system.h2, tryreboot.c: new; test if reboot() function takes one or two arguments (solaris). * runit.c: fallthrough stage 3: re-get stderr; sync() before reboot(). * uw_tmp.h1, uw_tmp.h2, tryuwtmp.c, tryuwtmpx.c: new; test for utmpx or utmp support. * utmpset.c: support systems with utmp or utmpx (solaris). * Makefile: adapt. * supports the solaris platform (thx Uffe Jakobsen). * doc/benefits.html, doc/index.html, doc/replaceinit.html, doc/runlevels.html, doc/useinit.html: default service directory is /var/service; minor. * etc/2, etc/debian/3, etc/freebsd/3, etc/macosx/StartupItems/runit, etc/openbsd/3, man/runsv.8, man/runsvchdir.8, man/runsvdir.8: default service directory is /var/service. * doc/runscripts.html: add more contributed run scripts (thx Tomasz Nidecki). runit 0.11.2 Tue, 23 Sep 2003 10:15:32 +0200 * doc/useinit.html, etc/macosx/StartupItems/runit: don't use /etc/runit/2 when using runit service supervision with traditional init, use /sbin/runsvdir-start instead. * fmt_ptime.c: calculate UTC localtime correctly. * runsv.c: support ./supervise as symbolic link, on dangling symlink create link target. runit 0.11.1 Thu, 4 Sep 2003 11:51:02 +0200 * src/Makefile: add dependency to sysdeps to target fmt_ptime.o (thx Thomas Schwinge). * svlogd.c: barf if all log directories given at the command line fail. * man/svlogd.8: adapt. * doc/runscripts.html: adaptions (thx Erich Schubert, Lang Martin). runit 0.11.0 Fri, 08 Aug 2003 12:37:14 +0200 * uidgid.c, uidgid.h: new; get uid/gid by name. * chpst: new; run program with a changed process state (includes envdir, envuidgid, pgrphack, setlock, setuidgid, softlimit functionality). * setuidgid.c: remove; obsolete (replaced by chpst). runit 0.10.0 Sun, 22 Jun 2003 20:44:58 +0200 * doc/index.html, doc/install.html, doc/replaceinit.html, doc/useinit.html: how to install and configure runit on MacOSX. * svlogd.c: typo; fix incorrect handling of processor's state file; minor code cleanup; correctly calculate size for all types of timestamps. * runit-init.c: exit 0 on wrong usage. * package/versions: new. runit 0.9.5 Tue, 17 Jun 2003 10:48:10 +0200 * runit.c: use select() on systems that don't provide poll(). * svlogd.c: reset match flag in lineflush() in all cases. * Makefile: build setuidgid in default target. * doc/useinit.html: add instruction to create /etc/runit/2 first. * doc/install.html: minor. runit 0.9.4 Wed, 04 Jun 2003 13:56:33 +0200 * svlogd.c: default log file size is 1M; print verbose message only if -v is set. * man/svlogd.8: document -v option; minor. * etc/freebsd/3, etc/openbsd/3: check if magic files in /etc/runit/ are executable, not readable. * etc/*/getty-tty*/run: remove utmpset from script. * etc/*/getty-tty*/finish: new: run utmpset. * doc/replaceinit.html: adapt. * setuidgid.c: new: daemontools' setuidgid drop in replacement (not installed by default). * Makefile: build setuidgid. * doc/index.html: update. runit 0.9.3 Sun, 04 May 2003 11:30:58 +0200 * Makefile: actually build runsvstat, runsvctrl before installing them, fixes build failure (thx Lukas Beeler). * runsvctrl.c, runsvstat.c: use _exit(). runit 0.9.2 Sat, 03 May 2003 17:40:23 +0200 * doc/runscripts.html: changes from Jesse Cablek. * doc/dependencies.html, doc/useinit.html: new. * doc/index.html: adapt; reorder programs; runsvstat, runsvctrl installed by default. * doc/install.html: remove dependency on daemontools; create /package. * doc/replaceinit.html, man/runsv.8: typos. * man/svwaitdown.8, man/svwaitup.8: refer to runit and supervise. * svlogd.c: fix counter var namespace. * package/commands: add runsvctrl, runsvstat. runit 0.9.1 Wed, 30 Apr 2003 22:10:57 +0200 * svlogd.c: reset match flag on deselection, fixes pattern matching. runit 0.9.0 Fri, 25 Apr 2003 09:22:03 +0200 * runsvdir.c: don't propagate sig_term to runsv processes when receiving sig_term; send sig_term to all runsv processes and exit 111 when receiving sig_hangup. * runit.c: print warning for each state that exits non-zero; restart stage 2 if it exits non-zero. * svlogd.c: code cleanup. * svwaitdown.c: send command 'd' (and 'x' if -x is set) to each service if it's not in state 'want down'. * svwaitup.c: minor code cleanup. * man/runsvdir.8, man/svwaitdown.8: adapt. * doc/runscripts.html: add contributed run scripts (thx!). * doc/upgrade.html, doc/index.html: adapt. runit 0.8.4 Sun, 20 Apr 2003 19:31:24 +0200 * svlogd.c: new; runit's service logging daemon. * fmt_ptime.h, fmt_ptime.c, pmatch.h, pmatch.c: new. * man/svlogd.8, doc/svlogd.8.html: new. * man/runsv.8, man/runsvstat.8, man/utmpset.8: minor cleanup. runit 0.8.1 Wed, 12 Mar 2003 15:10:04 +0100 * runsvdir.c, runsv.c: close-on-exec file descriptors of current dir and lock files (thx Lukas Beeler). * doc/runscripts.html: add contributed run scripts (thx Robin S. Socha, Claus Alboege, Paul Jarc, clemens fischer, Jesse Cablek). runit 0.8.0 Tue, 25 Feb 2003 16:17:34 +0100 * doc/benefits.html: new. * doc/index.html, doc/upgrade.html: adapt. * etc/*/1, etc/*/3, etc/*/ctrlaltdel: set permissions on the magic files instead of creating and removing them (can make them symbolic links now); set PATH. * runit.h: new; centralize runit's compiled in magic file names. * runit.c: check permissions of magic files instead of sole existence; conditionally call reboot(RB_AUTOBOOT), reboot(RB_POWER_OFF), reboot(RB_HALT_SYSTEM) if possible; code cleanup. * runit-init.c: set permissions on magic files instead of creating or removing them; code cleanup. * runsvdir.c: detect and tolerate system time warp; code cleanup. * runsv.c, runsvchdir.c, runsvctrl.c, runsvstat.c, svwaitdown.c, svwaitup.c, utmpset.c: code cleanup. * man/runit.8, man/runit-init.8: adapt. runit 0.7.2 Fri, 10 Jan 2003 21:34:13 +0100 * runsv.c: close finish script file descriptor. * runsv.c: close logpipe[] instead of sending sigterm to logservice when told to exit, loggers should exit when they see EOF on stdin (thx Paul Jarc). * etc/*/1, etc/*/3: remove explicit 'exit'. * error.h: include (upcoming glibc changes). runit 0.7.1 Wed, 23 Oct 2002 11:40:24 +0200 * man/runsv.8, doc/runlevels.html: typos. * runsvctrl.c, runsvstat.c: exit 111 on error. * runsvdir.c: continue reading directory when stat() on entry fails. * doc/runsvstat.8.html,doc/runsvctrl.8.html: new. * runsvstat, runsvctrl: new; optional svc, svstat replacements. * doc/index.html: adapt; new example. runit 0.7.0 Mon, 07 Oct 2002 11:26:27 +0200 * runsvdir.c: check service directory's inode and device in addition to mtime; sleep at least 1 second before restarting runsv processes. * runsv.c: use status[19] for state information; control pipe supports e. * runsvstat.c: new option -l: only show log service if -l is given; use status[19] for state. * runsvchdir: new; change directory runsvdir is running in (switch runlevels). * man/runsvchdir.8, doc/runsvchdir.8.html: new. * svwaitdown.c: -k option: only kill service that still are up on timeout. runit 0.6.0 Fri, 27 Sep 2002 16:34:57 +0200 * man/runsv.8, man/runsvdir.8: new. * doc: use runsvdir/runsv instead of svscanboot/supervise. * svwaitdown.c, svwaitup.c, man/svwaitdown.8, man/svwaitup.8: services must start with slash. * svwaitdown: new option -x: wait for runsv to exit instead for the service to be down; new option -k: SIGKILL still running services if timeout is reached. * stage 3: use new svwaitdown options. runit 0.5.3 Mon, 23 Sep 2002 16:25:07 +0200 * runsv, runsvdir: new; svscan/supervise replacement. * etc/runit/2: use runsvdir instead of svscanboot. * runsvstat.c: new; svstat for runsv. * runsvctrl.c: new; svc for runsv. * runsvdir.c, runsv.c: code cleanup. * utmpset.c: setlock utmp and wtmp file. runit 0.5.0 Wed, 28 Aug 2002 11:18:28 +0200 * utmpset: avoids libutil; compiles with dietlibc; built by default. * doc/usedietlibc.html: fix description. * getty-*/run: add utmpset. runit 0.4.1 Mon, 24 Jun 2002 15:53:11 +0200 * utmpset.c: new option -w: additionally write wtmp record. runit 0.4.0 Sun, 19 May 2002 12:28:29 +0200 * src/: include public domain sources to build byte.a, unix.a, time.a: runit builds without having daemontools' sources installed. * utmpset.c: new utmpset program. * doc/utmpset.html: new. runit 0.3.2 Wed, 13 Feb 2002 10:56:17 +0100 * runit.c: support ctrl-alt-del also on Linux/i386, dietlibc. * runscripts.html: more samples. (thx Alessandro Bono) runit 0.3.1 Sun, 3 Feb 2002 16:30:55 +0100 * src: cleanup. runit 0.3.0 Tue, 29 Jan 2002 19:38:33 +0100 * doc: adapted. * runit.8: changes documented. * runscripts.html: more examples. runit 0.2.9 Thu, 17 Jan 2002 19:00:44 +0100 * reportedly runs on FreeBSD 4.3 (thx clemensF) * svwaitdown: max timeout is 6000, really. (thx ska) * runit.c: stage 1 gets no new session and full control of console; an emergency shell or login program (if present) can be executed. * openbsd, freebsd: support for 'single user' emergency shell in stage 1 * runit.c: skip stage 2 if stage 1 crashes. runit 0.2.7 Tue, 1 Jan 2002 16:20:14 +0100 * tested on fresh freebsd 4.4 installation in vmware * new etc/freebsd: stages and getty service * doc: replaceinit: how to replace bsd init (freebsd) * svwaitup: minor code cleanup * doc: /service/getty-5/ as default getty service. * doc: index: related links added. * package: install-man added for installing manpages in /usr/local/man/ runit 0.2.6 Sun, 30 Dec 2001 17:29:29 +0100 * runs on openbsd 2.9 * runit: console init and reinit * runit: sig_pause() on end. * new: etc/openbsd: stages and getty service * doc: replaceinit: how to replace bsd init runit 0.2.3 Thu, 27 Dec 2001 14:41:56 +0100 * doc: runscripts.html integrated runit 0.2.2 Sun, 23 Dec 2001 18:12:29 +0100 * runit: checks for pid == 1 * new: svwaitdown, svwaitup, svwaitdown.8, svwaitup.8 * stage3: uses svwaitdown * doc: runscripts.html added runit 0.2.0 Mon, 26 Nov 2001 12:29:44 +0100 * runit-halt, runit-reboot removed, integrated into runit-init * tested with dietlibc * doc: usedietlibs.html added. * BSD license. runit 0.1.2 Thu, 22 Nov 2001 18:29:05 +0100 * collects all terminated children in all stages * sends sigkill to whole process group if stage2 crashes and waits 5 seconds before restarting * ctraltdel not automatically shuts down, now respects /etc/runit/stopit * /etc/runit/ctrlaltdel touches /etc/runit/stopit * on shutdown request: send sigterm to stage 2, wait max 5 second, send sigkill if still running, leave stage 2, enter stage 3 runit 0.1.1 Tue, 20 Nov 2001 11:56:58 +0100 * package moved to smarden.org runit 0.1.0 Fri, 16 Nov 2001 14:01:27 +0100 * documention * debian package runit 0.0.4 Sun, 11 Nov 2001 19:07:49 +0100 * initial release admin/runit-2.2.0/package/sharing0000644000000000000000000000004314675400254015417 0ustar rootrootcommand:syst package:dist src:dist admin/runit-2.2.0/package/compile0000755000000000000000000000123714675400254015425 0ustar rootroot#!/bin/sh set -e umask 022 test -d package || sh -cx '! : Wrong working directory.' test -d src || sh -cx '! : Wrong working directory.' here=`env - PATH=$PATH pwd` mkdir -p compile command test -r compile/home || echo $here >compile/home test -h compile/src || ln -s $here/src compile/src echo 'Linking ./src/* into ./compile...' for i in `ls src`; do test -h compile/$i || ln -s src/$i compile/$i done echo 'Compiling everything in ./compile...' sh -cxe 'cd compile; exec make' echo 'Copying commands into ./command...' for i in `cat package/commands`; do rm -f command/$i'{new}' cp -p compile/$i command/$i'{new}' mv -f command/$i'{new}' command/$i done admin/runit-2.2.0/package/install0000755000000000000000000000010014675400254015427 0ustar rootroot#!/bin/sh set -e package/compile package/check package/upgrade admin/runit-2.2.0/package/README0000644000000000000000000000006614675400254014726 0ustar rootrootCopyright 2001-2024 G. Pape http://smarden.org/runit/ admin/runit-2.2.0/package/check0000755000000000000000000000033614675400254015051 0ustar rootroot#!/bin/sh set -e umask 022 test -d package || sh -cx '! : Wrong working directory.' test -d compile || sh -cx '! : Wrong working directory.' echo 'Checking commands in ./command...' sh -cxe 'cd compile; exec make check' admin/runit-2.2.0/package/COPYING0000644000000000000000000000261214675400254015100 0ustar rootrootCopyright (c) 2001-2024, Gerrit Pape All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. admin/runit-2.2.0/package/commands0000644000000000000000000000010314675400254015562 0ustar rootrootchpst runit runit-init runsv runsvchdir runsvdir sv svlogd utmpset admin/runit-2.2.0/package/install-man0000755000000000000000000000112714675400254016212 0ustar rootroot#!/bin/sh set -e umask 022 test -d package || sh -cx '! : Wrong working directory.' test -d man || sh -cx '! : Wrong working directory.' here=`env - PATH=$PATH pwd` parent=`dirname $here` echo 'Compressing manpages...' for i in man/*.[1-8]; do gzip -c $i >${i}.gz done echo 'Making manpage links in /usr/local/man...' cd man for i in 8; do mkdir -p /usr/local/man/man$i for j in *.$i; do rm -f /usr/local/man/man$i/$j.gz'{new}' ln -s $parent/runit/man/$j.gz /usr/local/man/man$i/$j.gz'{new}' mv -f /usr/local/man/man$i/$j.gz'{new}' /usr/local/man/man$i/$j.gz done done cd .. admin/runit-2.2.0/src/0000755000000000000000000000000014675400254013240 5ustar rootrootadmin/runit-2.2.0/src/svlogd.check0000755000000000000000000000063614675400254015545 0ustar rootroot#!/bin/sh rm -rf "${ctmp}" svlogd echo $? svlogd -V echo $? mkdir "${ctmp}" echo foo |svlogd "${ctmp}" echo $? cat "${ctmp}"/current ( echo bar; echo baz ) |svlogd "${ctmp}" echo $? cat "${ctmp}"/current ( echo foo; echo bar; echo baz ) |svlogd -r: -R fb "${ctmp}" echo $? cat "${ctmp}"/current echo t2 >"${ctmp}"/config ( echo foo; sleep 3 ) |svlogd "${ctmp}" echo $? cat "${ctmp}"/current rm -rf "${ctmp}" admin/runit-2.2.0/src/tryreboot.c0000644000000000000000000000012514675400254015433 0ustar rootroot#include #include int main(void) { return(reboot(0)); } admin/runit-2.2.0/src/taia_less.c0000644000000000000000000000046714675400254015357 0ustar rootroot/* Public domain. */ #include "taia.h" /* XXX: breaks tai encapsulation */ int taia_less(const struct taia *t,const struct taia *u) { if (t->sec.x < u->sec.x) return 1; if (t->sec.x > u->sec.x) return 0; if (t->nano < u->nano) return 1; if (t->nano > u->nano) return 0; return t->atto < u->atto; } admin/runit-2.2.0/src/runsvctrl.check0000755000000000000000000000061414675400254016305 0ustar rootroot#!/bin/sh rm -rf "${ctmp}" runsvctrl echo $? mkdir "${ctmp}" echo '#!/bin/sh' >"${ctmp}"/run echo 'echo starting' >>"${ctmp}"/run echo 'exec sleep 14' >>"${ctmp}"/run chmod 700 "${ctmp}"/run runsv "${ctmp}" & sleep 1 test -r "${ctmp}"/supervise/stat || sleep 2 runsvctrl down "${ctmp}" echo $? sleep 1 cat "${ctmp}"/supervise/stat runsvctrl exit "${ctmp}" echo $? wait echo $? rm -rf "${ctmp}" admin/runit-2.2.0/src/Makefile0000644000000000000000000003037314675400254014706 0ustar rootrootIT=chpst runit runit-init runsv runsvchdir runsvdir sv svlogd utmpset default: sysdeps $(IT) check: $(IT) ./check-local $(IT) runit: load runit.o unix.a byte.a ./load runit unix.a byte.a -static runit-init: load runit-init.o unix.a byte.a ./load runit-init unix.a byte.a -static runsv: load runsv.o unix.a byte.a time.a ./load runsv unix.a byte.a time.a runsvdir: load runsvdir.o unix.a byte.a time.a ./load runsvdir unix.a byte.a time.a runsvstat: load runsvstat.o unix.a byte.a time.a ./load runsvstat unix.a byte.a time.a runsvctrl: load runsvctrl.o unix.a byte.a ./load runsvctrl unix.a byte.a sv: load sv.o unix.a byte.a time.a ./load sv unix.a byte.a time.a svwaitup: load svwaitup.o unix.a byte.a time.a ./load svwaitup unix.a byte.a time.a svwaitdown: load svwaitdown.o unix.a byte.a time.a ./load svwaitdown unix.a byte.a time.a utmpset: load utmpset.o unix.a byte.a ./load utmpset unix.a byte.a runsvchdir: load runsvchdir.o unix.a byte.a ./load runsvchdir unix.a byte.a svlogd: load svlogd.o pmatch.o fmt_ptime.o unix.a byte.a time.a socket.lib ./load svlogd pmatch.o fmt_ptime.o unix.a byte.a time.a \ `cat socket.lib` chpst: load chpst.o uidgid.o unix.a byte.a ./load chpst uidgid.o unix.a byte.a runit.o: compile sysdeps runit.c ./compile runit.c runit-init.o: compile runit-init.c ./compile runit-init.c runsv.o: compile sysdeps runsv.c ./compile runsv.c runsvdir.o: compile sysdeps runsvdir.c ./compile runsvdir.c runsvstat.o: compile sysdeps runsvstat.c ./compile runsvstat.c runsvctrl.o: compile runsvctrl.c ./compile runsvctrl.c sv.o: compile sysdeps sv.c ./compile sv.c svwaitup.o: compile sysdeps svwaitup.c ./compile svwaitup.c svwaitdown.o: compile sysdeps svwaitdown.c ./compile svwaitdown.c utmpset.o: compile sysdeps utmpset.c ./compile utmpset.c runsvchdir.o: compile runsvchdir.c ./compile runsvchdir.c svlogd.o: compile sysdeps svlogd.c ./compile svlogd.c chpst.o: compile sysdeps chpst.c ./compile chpst.c uidgid.o: compile uidgid.c uidgid.h ./compile uidgid.c pmatch.o: compile pmatch.c ./compile pmatch.c fmt_ptime.o: compile sysdeps fmt_ptime.c ./compile fmt_ptime.c reboot_system.h: choose compile reboot_system.h1 reboot_system.h2 ./choose c tryreboot reboot_system.h1 reboot_system.h2 > \ reboot_system.h uw_tmp.h: compile uw_tmp.h1 uw_tmp.h2 ( ./compile tryuwtmpx.c 2>/dev/null && cat uw_tmp.h2 >uw_tmp.h ) || \ ( ./compile tryuwtmp.c 2>/dev/null && cat uw_tmp.h1 >uw_tmp.h ) rm -f tryuwtmp.o tryuwtmpx.o socket.lib: compile load trysocketlib.c ./compile trysocketlib.c ( ./load trysocketlib >/dev/null 2>&1 || \ ( ./load trysocketlib -lxnet >/dev/null 2>&1 && echo '-lxnet' ) || \ ( ./load trysocketlib -lsocket -lnsl >/dev/null 2>&1 && \ echo '-lsocket -lnsl' ) \ ) >socket.lib rm -f trysocketlib.o trysocketlib clean: find . -name \*~ -exec rm -f {} \; find . -name .??*~ -exec rm -f {} \; find . -name \#?* -exec rm -f {} \; rm -f `cat TARGETS` alloc.o: alloc.c alloc.h compile error.h ./compile alloc.c alloc_re.o: alloc.h alloc_re.c byte.h compile ./compile alloc_re.c buffer.o: buffer.c buffer.h compile ./compile buffer.c buffer_0.o: buffer.h buffer_0.c compile ./compile buffer_0.c buffer_1.o: buffer.h buffer_1.c compile ./compile buffer_1.c buffer_2.o: buffer.h buffer_2.c compile ./compile buffer_2.c buffer_get.o: buffer.h buffer_get.c byte.h compile error.h ./compile buffer_get.c buffer_put.o: buffer.h buffer_put.c byte.h compile error.h str.h ./compile buffer_put.c buffer_read.o: buffer.h buffer_read.c compile ./compile buffer_read.c buffer_write.o: buffer.h buffer_write.c compile ./compile buffer_write.c byte.a: byte_chr.o byte_copy.o byte_cr.o byte_diff.o byte_rchr.o \ fmt_uint.o fmt_uint0.o fmt_ulong.o makelib scan_ulong.o str_chr.o \ str_diff.o str_len.o str_start.o ./makelib byte.a byte_chr.o byte_copy.o byte_cr.o byte_diff.o \ byte_rchr.o fmt_uint.o fmt_uint0.o fmt_ulong.o scan_ulong.o str_chr.o \ str_diff.o str_len.o str_start.o byte_chr.o: byte.h byte_chr.c compile ./compile byte_chr.c byte_copy.o: byte.h byte_copy.c compile ./compile byte_copy.c byte_cr.o: byte.h byte_cr.c compile ./compile byte_cr.c byte_diff.o: byte.h byte_diff.c compile ./compile byte_diff.c byte_rchr.o: byte.h byte_rchr.c compile ./compile byte_rchr.c choose: choose.sh warn-auto.sh rm -f choose cat warn-auto.sh choose.sh \ > choose chmod 555 choose coe.o: coe.c coe.h compile ./compile coe.c compile: conf-cc print-cc.sh systype warn-auto.sh rm -f compile sh print-cc.sh > compile chmod 555 compile direntry.h: choose compile direntry.h1 direntry.h2 trydrent.c ./choose c trydrent direntry.h1 direntry.h2 > direntry.h env.o: compile env.c env.h str.h ./compile env.c error.o: compile error.c error.h ./compile error.c error_str.o: compile error.h error_str.c ./compile error_str.c fd_copy.o: compile fd.h fd_copy.c ./compile fd_copy.c fd_move.o: compile fd.h fd_move.c ./compile fd_move.c fifo.o: compile fifo.c fifo.h hasmkffo.h ./compile fifo.c fmt_uint.o: compile fmt.h fmt_uint.c ./compile fmt_uint.c fmt_uint0.o: compile fmt.h fmt_uint0.c ./compile fmt_uint0.c fmt_ulong.o: compile fmt.h fmt_ulong.c ./compile fmt_ulong.c hasflock.h: choose compile hasflock.h1 hasflock.h2 load tryflock.c ./choose cl tryflock hasflock.h1 hasflock.h2 > hasflock.h hasmkffo.h: choose compile hasmkffo.h1 hasmkffo.h2 load trymkffo.c ./choose cl trymkffo hasmkffo.h1 hasmkffo.h2 > hasmkffo.h hassgact.h: choose compile hassgact.h1 hassgact.h2 load trysgact.c ./choose cl trysgact hassgact.h1 hassgact.h2 > hassgact.h hassgprm.h: choose compile hassgprm.h1 hassgprm.h2 load trysgprm.c ./choose cl trysgprm hassgprm.h1 hassgprm.h2 > hassgprm.h haswaitp.h: choose compile haswaitp.h1 haswaitp.h2 load trywaitp.c ./choose cl trywaitp haswaitp.h1 haswaitp.h2 > haswaitp.h iopause.h: choose compile iopause.h1 iopause.h2 load trypoll.c ./choose clr trypoll iopause.h1 iopause.h2 > iopause.h iopause.o: compile iopause.c iopause.h select.h tai.h taia.h uint64.h ./compile iopause.c load: conf-ld print-ld.sh systype warn-auto.sh rm -f load sh print-ld.sh > load chmod 555 load lock_ex.o: compile hasflock.h lock.h lock_ex.c ./compile lock_ex.c lock_exnb.o: compile hasflock.h lock.h lock_exnb.c ./compile lock_exnb.c makelib: print-ar.sh systype warn-auto.sh rm -f makelib sh print-ar.sh > makelib chmod 555 makelib ndelay_off.o: compile ndelay.h ndelay_off.c ./compile ndelay_off.c ndelay_on.o: compile ndelay.h ndelay_on.c ./compile ndelay_on.c open_append.o: compile open.h open_append.c ./compile open_append.c open_read.o: compile open.h open_read.c ./compile open_read.c open_trunc.o: compile open.h open_trunc.c ./compile open_trunc.c open_write.o: compile open.h open_write.c ./compile open_write.c openreadclose.o: compile error.h gen_alloc.h open.h openreadclose.c \ openreadclose.h readclose.h stralloc.h ./compile openreadclose.c pathexec_env.o: alloc.h byte.h compile env.h gen_alloc.h pathexec.h \ pathexec_env.c str.h stralloc.h ./compile pathexec_env.c pathexec_run.o: compile env.h error.h gen_alloc.h pathexec.h \ pathexec_run.c str.h stralloc.h ./compile pathexec_run.c readclose.o: compile error.h gen_alloc.h readclose.c readclose.h \ stralloc.h ./compile readclose.c scan_ulong.o: compile scan.h scan_ulong.c ./compile scan_ulong.c seek_set.o: compile seek.h seek_set.c ./compile seek_set.c select.h: choose compile select.h1 select.h2 trysysel.c ./choose c trysysel select.h1 select.h2 > select.h sgetopt.o: buffer.h compile sgetopt.c sgetopt.h subgetopt.h ./compile sgetopt.c sig.o: compile sig.c sig.h ./compile sig.c sig_block.o: compile hassgprm.h sig.h sig_block.c ./compile sig_block.c sig_catch.o: compile hassgact.h sig.h sig_catch.c ./compile sig_catch.c sig_pause.o: compile hassgprm.h sig.h sig_pause.c ./compile sig_pause.c str_chr.o: compile str.h str_chr.c ./compile str_chr.c str_diff.o: compile str.h str_diff.c ./compile str_diff.c str_len.o: compile str.h str_len.c ./compile str_len.c str_start.o: compile str.h str_start.c ./compile str_start.c stralloc_cat.o: byte.h compile gen_alloc.h stralloc.h stralloc_cat.c ./compile stralloc_cat.c stralloc_catb.o: byte.h compile gen_alloc.h stralloc.h \ stralloc_catb.c ./compile stralloc_catb.c stralloc_cats.o: byte.h compile gen_alloc.h str.h stralloc.h \ stralloc_cats.c ./compile stralloc_cats.c stralloc_eady.o: alloc.h compile gen_alloc.h gen_allocdefs.h \ stralloc.h stralloc_eady.c ./compile stralloc_eady.c stralloc_opyb.o: byte.h compile gen_alloc.h stralloc.h \ stralloc_opyb.c ./compile stralloc_opyb.c stralloc_opys.o: byte.h compile gen_alloc.h str.h stralloc.h \ stralloc_opys.c ./compile stralloc_opys.c stralloc_pend.o: alloc.h compile gen_alloc.h gen_allocdefs.h \ stralloc.h stralloc_pend.c ./compile stralloc_pend.c strerr_die.o: buffer.h compile strerr.h strerr_die.c ./compile strerr_die.c strerr_sys.o: compile error.h strerr.h strerr_sys.c ./compile strerr_sys.c subgetopt.o: compile subgetopt.c subgetopt.h ./compile subgetopt.c sysdeps: compile direntry.h hasflock.h hasmkffo.h hassgact.h \ hassgprm.h haswaitp.h iopause.h load select.h systype \ uint64.h reboot_system.h uw_tmp.h socket.lib rm -f sysdeps cat systype compile load socket.lib >>sysdeps grep sysdep direntry.h >>sysdeps grep sysdep haswaitp.h >>sysdeps grep sysdep hassgact.h >>sysdeps grep sysdep hassgprm.h >>sysdeps grep sysdep select.h >>sysdeps grep sysdep uint64.h >>sysdeps grep sysdep iopause.h >>sysdeps grep sysdep hasmkffo.h >>sysdeps grep sysdep hasflock.h >>sysdeps grep sysdep reboot_system.h >>sysdeps grep sysdep uw_tmp.h >>sysdeps cat sysdeps systype: find-systype.sh trycpp.c x86cpuid.c sh find-systype.sh > systype tai_now.o: compile tai.h tai_now.c uint64.h ./compile tai_now.c tai_pack.o: compile tai.h tai_pack.c uint64.h ./compile tai_pack.c tai_sub.o: compile tai.h tai_sub.c uint64.h ./compile tai_sub.c tai_unpack.o: compile tai.h tai_unpack.c uint64.h ./compile tai_unpack.c taia_add.o: compile tai.h taia.h taia_add.c uint64.h ./compile taia_add.c taia_approx.o: compile tai.h taia.h taia_approx.c uint64.h ./compile taia_approx.c taia_frac.o: compile tai.h taia.h taia_frac.c uint64.h ./compile taia_frac.c taia_less.o: compile tai.h taia.h taia_less.c uint64.h ./compile taia_less.c taia_now.o: compile tai.h taia.h taia_now.c uint64.h ./compile taia_now.c taia_pack.o: compile tai.h taia.h taia_pack.c uint64.h ./compile taia_pack.c taia_sub.o: compile tai.h taia.h taia_sub.c uint64.h ./compile taia_sub.c taia_uint.o: compile tai.h taia.h taia_uint.c uint64.h ./compile taia_uint.c time.a: iopause.o makelib tai_now.o tai_pack.o tai_sub.o tai_unpack.o \ taia_add.o taia_approx.o taia_frac.o taia_less.o taia_now.o \ taia_pack.o taia_sub.o taia_uint.o ./makelib time.a iopause.o tai_now.o tai_pack.o tai_sub.o \ tai_unpack.o taia_add.o taia_approx.o taia_frac.o taia_less.o \ taia_now.o taia_pack.o taia_sub.o taia_uint.o uint64.h: choose compile load tryulong64.c uint64.h1 uint64.h2 ./choose clr tryulong64 uint64.h1 uint64.h2 > uint64.h unix.a: alloc.o alloc_re.o buffer.o buffer_0.o buffer_1.o buffer_2.o \ buffer_get.o buffer_put.o buffer_read.o buffer_write.o coe.o env.o \ error.o error_str.o fd_copy.o fd_move.o fifo.o lock_ex.o lock_exnb.o \ makelib ndelay_off.o ndelay_on.o open_append.o open_read.o \ open_trunc.o open_write.o openreadclose.o pathexec_env.o \ pathexec_run.o readclose.o seek_set.o sgetopt.o sig.o \ sig_block.o sig_catch.o sig_pause.o stralloc_cat.o stralloc_catb.o \ stralloc_cats.o stralloc_eady.o stralloc_opyb.o stralloc_opys.o \ stralloc_pend.o strerr_die.o strerr_sys.o subgetopt.o wait_nohang.o \ wait_pid.o ./makelib unix.a alloc.o alloc_re.o buffer.o buffer_0.o buffer_1.o \ buffer_2.o buffer_get.o buffer_put.o buffer_read.o buffer_write.o \ coe.o env.o error.o error_str.o fd_copy.o fd_move.o fifo.o lock_ex.o \ lock_exnb.o ndelay_off.o ndelay_on.o open_append.o open_read.o \ open_trunc.o open_write.o openreadclose.o pathexec_env.o \ pathexec_run.o readclose.o seek_set.o sgetopt.o sig.o \ sig_block.o sig_catch.o sig_pause.o stralloc_cat.o stralloc_catb.o \ stralloc_cats.o stralloc_eady.o stralloc_opyb.o stralloc_opys.o \ stralloc_pend.o strerr_die.o strerr_sys.o subgetopt.o wait_nohang.o \ wait_pid.o wait_nohang.o: compile haswaitp.h wait_nohang.c ./compile wait_nohang.c wait_pid.o: compile error.h haswaitp.h wait_pid.c ./compile wait_pid.c admin/runit-2.2.0/src/byte_rchr.c0000644000000000000000000000070714675400254015371 0ustar rootroot/* Public domain. */ #include "byte.h" unsigned int byte_rchr(s,n,c) char *s; register unsigned int n; int c; { register char ch; register char *t; register char *u; ch = c; t = s; u = 0; for (;;) { if (!n) break; if (*t == ch) u = t; ++t; --n; if (!n) break; if (*t == ch) u = t; ++t; --n; if (!n) break; if (*t == ch) u = t; ++t; --n; if (!n) break; if (*t == ch) u = t; ++t; --n; } if (!u) u = t; return u - s; } admin/runit-2.2.0/src/taia_approx.c0000644000000000000000000000020314675400254015706 0ustar rootroot/* Public domain. */ #include "taia.h" double taia_approx(const struct taia *t) { return tai_approx(&t->sec) + taia_frac(t); } admin/runit-2.2.0/src/str_len.c0000644000000000000000000000040514675400254015051 0ustar rootroot/* Public domain. */ #include "str.h" unsigned int str_len(const char *s) { register const char *t; t = s; for (;;) { if (!*t) return t - s; ++t; if (!*t) return t - s; ++t; if (!*t) return t - s; ++t; if (!*t) return t - s; ++t; } } admin/runit-2.2.0/src/stralloc_opys.c0000644000000000000000000000025514675400254016303 0ustar rootroot/* Public domain. */ #include "byte.h" #include "str.h" #include "stralloc.h" int stralloc_copys(stralloc *sa,const char *s) { return stralloc_copyb(sa,s,str_len(s)); } admin/runit-2.2.0/src/sig_block.c0000644000000000000000000000122314675400254015336 0ustar rootroot/* Public domain. */ #include #include "sig.h" #include "hassgprm.h" void sig_block(int sig) { #ifdef HASSIGPROCMASK sigset_t ss; sigemptyset(&ss); sigaddset(&ss,sig); sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0); #else sigblock(1 << (sig - 1)); #endif } void sig_unblock(int sig) { #ifdef HASSIGPROCMASK sigset_t ss; sigemptyset(&ss); sigaddset(&ss,sig); sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0); #else sigsetmask(sigsetmask(~0) & ~(1 << (sig - 1))); #endif } void sig_blocknone(void) { #ifdef HASSIGPROCMASK sigset_t ss; sigemptyset(&ss); sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); #else sigsetmask(0); #endif } admin/runit-2.2.0/src/open.h0000644000000000000000000000036514675400254014356 0ustar rootroot/* Public domain. */ #ifndef OPEN_H #define OPEN_H extern int open_read(const char *); extern int open_excl(const char *); extern int open_append(const char *); extern int open_trunc(const char *); extern int open_write(const char *); #endif admin/runit-2.2.0/src/hasmkffo.h20000644000000000000000000000010014675400254015260 0ustar rootroot/* Public domain. */ /* sysdep: +mkfifo */ #define HASMKFIFO 1 admin/runit-2.2.0/src/conf-ld0000644000000000000000000000007714675400254014511 0ustar rootrootgcc -s This will be used to link .o files into an executable. admin/runit-2.2.0/src/runit.c0000644000000000000000000002153314675400254014551 0ustar rootroot#include #include #include #include #include #include #include #include "runit.h" #include "sig.h" #include "strerr.h" #include "error.h" #include "iopause.h" #include "coe.h" #include "ndelay.h" #include "wait.h" #include "open.h" #include "reboot_system.h" /* #define DEBUG */ #define INFO "- runit: " #define WARNING "- runit: warning: " #define FATAL "- runit: fatal: " const char * const stage[3] ={ "/etc/runit/1", "/etc/runit/2", "/etc/runit/3" }; int selfpipe[2]; int sigc =0; int sigi =0; void sig_cont_handler (void) { sigc++; write(selfpipe[1], "", 1); } void sig_int_handler (void) { sigi++; write(selfpipe[1], "", 1); } void sig_child_handler (void) { write(selfpipe[1], "", 1); } void sync_if_needed() { struct stat s; if (stat(NOSYNC, &s) == -1) sync(); } int main (int argc, const char * const *argv, char * const *envp) { const char * prog[2]; int pid, pid2; int wstat; int st; iopause_fd x; #ifndef IOPAUSE_POLL fd_set rfds; struct timeval t; #endif char ch; int ttyfd; struct stat s; if (getpid() != 1) strerr_die2x(111, FATAL, "must be run as process no 1."); setsid(); sig_block(sig_alarm); sig_block(sig_child); sig_catch(sig_child, sig_child_handler); sig_block(sig_cont); sig_catch(sig_cont, sig_cont_handler); sig_block(sig_hangup); sig_block(sig_int); sig_catch(sig_int, sig_int_handler); sig_block(sig_pipe); sig_block(sig_term); /* console */ if ((ttyfd =open_write("/dev/console")) != -1) { dup2(ttyfd, 0); dup2(ttyfd, 1); dup2(ttyfd, 2); if (ttyfd > 2) close(ttyfd); } /* create selfpipe */ while (pipe(selfpipe) == -1) { strerr_warn2(FATAL, "unable to create selfpipe, pausing: ", &strerr_sys); sleep(5); } coe(selfpipe[0]); coe(selfpipe[1]); ndelay_on(selfpipe[0]); ndelay_on(selfpipe[1]); #ifdef RB_DISABLE_CAD /* activate ctrlaltdel handling, glibc, dietlibc */ if (RB_DISABLE_CAD == 0) reboot_system(0); #endif strerr_warn3(INFO, "$Id: c6c9cea989d36a913fe8ed121272c01625813eb4 $", ": booting.", 0); /* runit */ for (st =0; st < 3; st++) { /* if (st == 2) logwtmp("~", "reboot", ""); */ while ((pid =fork()) == -1) { strerr_warn4(FATAL, "unable to fork for \"", stage[st], "\" pausing: ", &strerr_sys); sleep(5); } if (!pid) { /* child */ prog[0] =stage[st]; prog[1] =0; /* stage 1 gets full control of console */ if (st == 0) { if ((ttyfd =open("/dev/console", O_RDWR)) != -1) { #ifdef TIOCSCTTY ioctl(ttyfd, TIOCSCTTY, (char *)0); #endif dup2(ttyfd, 0); if (ttyfd > 2) close(ttyfd); } else strerr_warn2(WARNING, "unable to open /dev/console: ", &strerr_sys); } else setsid(); sig_unblock(sig_alarm); sig_unblock(sig_child); sig_uncatch(sig_child); sig_unblock(sig_cont); sig_ignore(sig_cont); sig_unblock(sig_hangup); sig_unblock(sig_int); sig_uncatch(sig_int); sig_unblock(sig_pipe); sig_unblock(sig_term); strerr_warn3(INFO, "enter stage: ", stage[st], 0); execve(*prog, (char *const *)prog, envp); strerr_die4sys(0, FATAL, "unable to start child: ", stage[st], ": "); } x.fd =selfpipe[0]; x.events =IOPAUSE_READ; for (;;) { int child; sig_unblock(sig_child); sig_unblock(sig_cont); sig_unblock(sig_int); #ifdef IOPAUSE_POLL poll(&x, 1, 14000); #else t.tv_sec =14; t.tv_usec =0; FD_ZERO(&rfds); FD_SET(x.fd, &rfds); select(x.fd +1, &rfds, (fd_set*)0, (fd_set*)0, &t); #endif sig_block(sig_cont); sig_block(sig_child); sig_block(sig_int); while (read(selfpipe[0], &ch, 1) == 1) {} while ((child =wait_nohang(&wstat)) > 0) if (child == pid) break; if (child == -1) { strerr_warn2(WARNING, "wait_nohang, pausing: ", &strerr_sys); sleep(5); } /* reget stderr */ if ((ttyfd =open_write("/dev/console")) != -1) { dup2(ttyfd, 2); if (ttyfd > 2) close(ttyfd); } if (child == pid) { if (wait_exitcode(wstat) != 0) { if (wait_crashed(wstat)) strerr_warn3(WARNING, "child crashed: ", stage[st], 0); else strerr_warn3(WARNING, "child failed: ", stage[st], 0); if (st == 0) /* this is stage 1 */ if (wait_crashed(wstat) || (wait_exitcode(wstat) == 100)) { strerr_warn3(INFO, "leave stage: ", stage[st], 0); strerr_warn2(WARNING, "skipping stage 2...", 0); st++; break; } if (st == 1) /* this is stage 2 */ if (wait_crashed(wstat) || (wait_exitcode(wstat) == 111)) { strerr_warn2(WARNING, "killing all processes in stage 2...", 0); kill(-pid, 9); sleep(5); strerr_warn2(WARNING, "restarting.", 0); st--; break; } } strerr_warn3(INFO, "leave stage: ", stage[st], 0); break; } if (child != 0) { /* collect terminated children */ write(selfpipe[1], "", 1); continue; } /* sig? */ if (!sigc && !sigi) { #ifdef DEBUG strerr_warn2(WARNING, "poll: ", &strerr_sys); #endif continue; } if (st != 1) { strerr_warn2(WARNING, "signals only work in stage 2.", 0); sigc =sigi =0; continue; } if (sigi && (stat(CTRLALTDEL, &s) != -1) && (s.st_mode & S_IXUSR)) { strerr_warn2(INFO, "ctrl-alt-del request...", 0); prog[0] =CTRLALTDEL; prog[1] =0; while ((pid2 =fork()) == -1) { strerr_warn4(FATAL, "unable to fork for \"", CTRLALTDEL, "\" pausing: ", &strerr_sys); sleep(5); } if (!pid2) { /* child */ strerr_warn3(INFO, "enter stage: ", prog[0], 0); execve(*prog, (char *const *) prog, envp); strerr_die4sys(0, FATAL, "unable to start child: ", prog[0], ": "); } if (wait_pid(&wstat, pid2) == -1) strerr_warn2(FATAL, "wait_pid: ", &strerr_sys); if (wait_crashed(wstat)) strerr_warn3(WARNING, "child crashed: ", CTRLALTDEL, 0); strerr_warn3(INFO, "leave stage: ", prog[0], 0); sigi =0; sigc++; } if (sigc && (stat(STOPIT, &s) != -1) && (s.st_mode & S_IXUSR)) { int i; /* unlink(STOPIT); */ chmod(STOPIT, 0); /* kill stage 2 */ #ifdef DEBUG strerr_warn2(WARNING, "sending sigterm...", 0); #endif kill(pid, sig_term); i =0; while (i < 5) { if ((child =wait_nohang(&wstat)) == pid) { #ifdef DEBUG strerr_warn2(WARNING, "stage 2 terminated.", 0); #endif pid =0; break; } if (child) continue; if (child == -1) strerr_warn2(WARNING, "wait_nohang: ", &strerr_sys); #ifdef DEBUG strerr_warn2(WARNING, "waiting...", 0); #endif sleep(1); i++; } if (pid) { /* still there */ strerr_warn2(WARNING, "stage 2 not terminated, sending sigkill...", 0); kill(pid, 9); if (wait_pid(&wstat, pid) == -1) strerr_warn2(WARNING, "wait_pid: ", &strerr_sys); } sigc =0; strerr_warn3(INFO, "leave stage: ", stage[st], 0); /* enter stage 3 */ break; } sigc =sigi =0; #ifdef DEBUG strerr_warn2(WARNING, "no request.", 0); #endif } } /* reget stderr */ if ((ttyfd =open_write("/dev/console")) != -1) { dup2(ttyfd, 2); if (ttyfd > 2) close(ttyfd); } #ifdef RB_AUTOBOOT /* fallthrough stage 3 */ strerr_warn2(INFO, "sending KILL signal to all processes...", 0); kill(-1, SIGKILL); pid =fork(); switch (pid) { case 0: case -1: if ((stat(REBOOT, &s) != -1) && (s.st_mode & S_IXUSR)) { strerr_warn2(INFO, "system reboot.", 0); sync_if_needed(); reboot_system(RB_AUTOBOOT); } else { #ifdef RB_POWER_OFF strerr_warn2(INFO, "power off...", 0); sync_if_needed(); reboot_system(RB_POWER_OFF); sleep(2); #endif #ifdef RB_HALT_SYSTEM strerr_warn2(INFO, "system halt.", 0); sync_if_needed(); reboot_system(RB_HALT_SYSTEM); #else #ifdef RB_HALT strerr_warn2(INFO, "system halt.", 0); sync_if_needed(); reboot_system(RB_HALT); #else strerr_warn2(INFO, "system reboot.", 0); sync_if_needed(); reboot_system(RB_AUTOBOOT); #endif #endif } if (pid == 0) _exit(0); break; default: sig_unblock(sig_child); while (wait_pid(0, pid) == -1); } #endif for (;;) sig_pause(); /* not reached */ strerr_die2x(0, INFO, "exit."); return(0); } admin/runit-2.2.0/src/trymkffo.c0000644000000000000000000000016114675400254015243 0ustar rootroot/* Public domain. */ #include #include void main() { mkfifo("temp-trymkffo",0); } admin/runit-2.2.0/src/select.h20000644000000000000000000000026514675400254014755 0ustar rootroot/* Public domain. */ #ifndef SELECT_H #define SELECT_H /* sysdep: +sysselect */ #include #include #include extern int select(); #endif admin/runit-2.2.0/src/ndelay_off.c0000644000000000000000000000034514675400254015514 0ustar rootroot/* Public domain. */ #include #include #include "ndelay.h" #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif int ndelay_off(int fd) { return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK); } admin/runit-2.2.0/src/sv.check0000755000000000000000000000056014675400254014673 0ustar rootroot#!/bin/sh rm -rf "${ctmp}" trap 'rm -rf "${ctmp}"' EXIT sv echo $? sv -V echo $? mkdir "${ctmp}" cat >"${ctmp}"/run <<-\EOT #!/bin/sh echo starting exec sleep 14 EOT chmod 700 "${ctmp}"/run runsv "${ctmp}" & sleep 1 test -r "${ctmp}"/supervise/stat || sleep 2 sv down "${ctmp}" echo $? sleep 1 cat "${ctmp}"/supervise/stat sv exit "${ctmp}" echo $? wait echo $? admin/runit-2.2.0/src/hassgact.h20000644000000000000000000000010614675400254015265 0ustar rootroot/* Public domain. */ /* sysdep: +sigaction */ #define HASSIGACTION 1 admin/runit-2.2.0/src/runsvchdir.c0000644000000000000000000000423514675400254015577 0ustar rootroot#include #include #include #include #include "strerr.h" #include "error.h" #include "buffer.h" #define USAGE " dir" #define SVDIR "/etc/runit/runsvdir" #define VERSION "$Id: 9bf17f77e33c6b961e060aacffa3c8abd38fc64a $" char *progname; char *new; void usage () { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } void fatal(char *m1, char *m2) { strerr_die5sys(111, progname, ": fatal: ", m1, m2, ": "); } void fatalx(char *m1, char *m2) { strerr_die4x(111, progname, ": fatal: ", m1, m2); } void warn(char *m1, char *m2) { strerr_warn5(progname, ": fatal: ", m1, m2, ": ", &strerr_sys); } int main (int argc, char **argv) { struct stat s; int dev; int ino; progname =*argv++; if (! argv || ! *argv) usage(); new =*argv; if (new[0] == '.') fatalx(new, ": must not start with a dot."); if (chdir(SVDIR) == -1) fatal("unable to chdir: ", SVDIR); if (stat(new, &s) == -1) { if (errno == error_noent) fatal(new, 0); fatal("unable to stat: ", new); } if (! S_ISDIR(s.st_mode)) fatalx(new, "not a directory."); ino =s.st_ino; dev =s.st_dev; if (stat("current", &s) == -1) fatal("unable to stat: ", "current"); if ((s.st_ino == ino) && (s.st_dev == dev)) { buffer_puts(buffer_1, "runsvchdir: "); buffer_puts(buffer_1, new); buffer_puts(buffer_1, ": current.\n"); buffer_flush(buffer_1); _exit(0); } if (unlink("current.new") == -1) if (errno != error_noent) fatal("unable to unlink: ", "current.new"); if (symlink(new, "current.new") == -1) fatal("unable to create: current.new -> ", new); if (unlink("previous") == -1) if (errno != error_noent) fatal("unable to unlink: ", "previous"); if (rename("current", "previous") == -1) fatal("unable to copy: current to ", "previous"); if (rename("current.new", "current") == -1) { warn("unable to move: current.new to ", "current"); if (rename("previous", "current") == -1) fatal("unable to move previous back to ", "current"); _exit(111); } buffer_puts(buffer_1, "runsvchdir: "); buffer_puts(buffer_1, new); buffer_puts(buffer_1, ": now current.\n"); buffer_flush(buffer_1); _exit(0); } admin/runit-2.2.0/src/trysgprm.c0000644000000000000000000000025014675400254015270 0ustar rootroot/* Public domain. */ #include int main() { sigset_t ss; sigemptyset(&ss); sigaddset(&ss,SIGCHLD); sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); } admin/runit-2.2.0/src/taia_now.c0000644000000000000000000000044114675400254015204 0ustar rootroot/* Public domain. */ #include #include #include #include "taia.h" void taia_now(struct taia *t) { struct timeval now; gettimeofday(&now,(struct timezone *) 0); tai_unix(&t->sec,now.tv_sec); t->nano = 1000 * now.tv_usec + 500; t->atto = 0; } admin/runit-2.2.0/src/haswaitp.h20000644000000000000000000000010214675400254015304 0ustar rootroot/* Public domain. */ /* sysdep: +waitpid */ #define HASWAITPID 1 admin/runit-2.2.0/src/lock_ex.c0000644000000000000000000000037414675400254015034 0ustar rootroot/* Public domain. */ #include #include #include #include "hasflock.h" #include "lock.h" #ifdef HASFLOCK int lock_ex(int fd) { return flock(fd,LOCK_EX); } #else int lock_ex(int fd) { return lockf(fd,1,0); } #endif admin/runit-2.2.0/src/scan.h0000644000000000000000000000260514675400254014340 0ustar rootroot/* Public domain. */ #ifndef SCAN_H #define SCAN_H extern unsigned int scan_uint(const char *,unsigned int *); extern unsigned int scan_xint(const char *,unsigned int *); extern unsigned int scan_nbbint(const char *,unsigned int,unsigned int,unsigned int,unsigned int *); extern unsigned int scan_ushort(const char *,unsigned short *); extern unsigned int scan_xshort(const char *,unsigned short *); extern unsigned int scan_nbbshort(const char *,unsigned int,unsigned int,unsigned int,unsigned short *); extern unsigned int scan_ulong(const char *,unsigned long *); extern unsigned int scan_xlong(const char *,unsigned long *); extern unsigned int scan_nbblong(const char *,unsigned int,unsigned int,unsigned int,unsigned long *); extern unsigned int scan_plusminus(const char *,int *); extern unsigned int scan_0x(const char *,unsigned int *); extern unsigned int scan_whitenskip(const char *,unsigned int); extern unsigned int scan_nonwhitenskip(const char *,unsigned int); extern unsigned int scan_charsetnskip(const char *,const char *,unsigned int); extern unsigned int scan_noncharsetnskip(const char *,const char *,unsigned int); extern unsigned int scan_strncmp(const char *,const char *,unsigned int); extern unsigned int scan_memcmp(const char *,const char *,unsigned int); extern unsigned int scan_long(const char *,long *); extern unsigned int scan_8long(const char *,unsigned long *); #endif admin/runit-2.2.0/src/fmt_ulong.c0000644000000000000000000000052014675400254015373 0ustar rootroot/* Public domain. */ #include "fmt.h" unsigned int fmt_ulong(register char *s,register unsigned long u) { register unsigned int len; register unsigned long q; len = 1; q = u; while (q > 9) { ++len; q /= 10; } if (s) { s += len; do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */ } return len; } admin/runit-2.2.0/src/seek_set.c0000644000000000000000000000031614675400254015206 0ustar rootroot/* Public domain. */ #include #include #include "seek.h" #define SET 0 /* sigh */ int seek_set(int fd,seek_pos pos) { if (lseek(fd,(off_t) pos,SET) == -1) return -1; return 0; } admin/runit-2.2.0/src/runsvctrl.dist0000644000000000000000000000012214675400254016162 0ustar rootrootusage: runsvctrl u|d|o|p|c|h|a|i|q|1|2|t|k|x|e service ... 1 starting 0 down 0 0 admin/runit-2.2.0/src/open_trunc.c0000644000000000000000000000026414675400254015562 0ustar rootroot/* Public domain. */ #include #include #include "open.h" int open_trunc(const char *fn) { return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); } admin/runit-2.2.0/src/wait_pid.c0000644000000000000000000000133314675400254015204 0ustar rootroot/* Public domain. */ #include #include #include "error.h" #include "haswaitp.h" #ifdef HASWAITPID int wait_pid(wstat,pid) int *wstat; int pid; { int r; do r = waitpid(pid,wstat,0); while ((r == -1) && (errno == error_intr)); return r; } #else /* XXX untested */ /* XXX breaks down with more than two children */ static int oldpid = 0; static int oldwstat; /* defined if(oldpid) */ int wait_pid(wstat,pid) int *wstat; int pid; { int r; if (pid == oldpid) { *wstat = oldwstat; oldpid = 0; return pid; } do { r = wait(wstat); if ((r != pid) && (r != -1)) { oldwstat = *wstat; oldpid = r; continue; } } while ((r == -1) && (errno == error_intr)); return r; } #endif admin/runit-2.2.0/src/trysocketlib.c0000644000000000000000000000031214675400254016116 0ustar rootroot#include #include #include #include #include int main(void) { int s; s =socket(AF_INET, SOCK_STREAM, 0); return(close(s)); } admin/runit-2.2.0/src/TARGETS0000644000000000000000000000304014675400254014271 0ustar rootrootrunit runit.o runit-init runit-init.o runsv runsv.o runsvdir runsvdir.o runsvstat runsvstat.o runsvctrl runsvctrl.o sv sv.o svwaitdown svwaitdown.o svwaitup svwaitup.o utmpset utmpset.o runsvchdir runsvchdir.o svlogd svlogd.o chpst chpst.o pmatch.o fmt_ptime.o uidgid.o reboot_system.h uw_tmp.h socket.lib trysocketlib trysocketlib.o check alloc.o alloc_re.o buffer.o buffer_0.o buffer_1.o buffer_2.o buffer_get.o buffer_put.o buffer_read.o buffer_write.o byte.a byte_chr.o byte_copy.o byte_cr.o byte_diff.o byte_rchr.o choose coe.o compile direntry.h env.o error.o error_str.o fd_copy.o fd_move.o fifo.o fmt_uint.o fmt_uint0.o fmt_ulong.o hasflock.h hasmkffo.h hassgact.h hassgprm.h hasshsgr.h haswaitp.h iopause.h iopause.o load lock_ex.o lock_exnb.o makelib ndelay_off.o ndelay_on.o open_append.o open_read.o open_trunc.o open_write.o openreadclose.o pathexec_env.o pathexec_run.o prot.o readclose.o scan_ulong.o seek_set.o select.h sgetopt.o sig.o sig_block.o sig_catch.o sig_pause.o str_chr.o str_diff.o str_len.o str_start.o stralloc_cat.o stralloc_catb.o stralloc_cats.o stralloc_eady.o stralloc_opyb.o stralloc_opys.o stralloc_pend.o strerr_die.o strerr_sys.o subgetopt.o sysdeps systype tai_now.o tai_pack.o tai_sub.o tai_unpack.o taia_add.o taia_approx.o taia_frac.o taia_less.o taia_now.o taia_pack.o taia_sub.o taia_uint.o time.a uint64.h unix.a wait_nohang.o wait_pid.o chpst.local runit-init.local runit.local runsv.local runsvchdir.local runsvctrl.local runsvdir.local runsvstat.local sv.local svlogd.local svwaitdown.local svwaitup.local utmpset.local admin/runit-2.2.0/src/fd_move.c0000644000000000000000000000027414675400254015026 0ustar rootroot/* Public domain. */ #include #include "fd.h" int fd_move(int to,int from) { if (to == from) return 0; if (fd_copy(to,from) == -1) return -1; close(from); return 0; } admin/runit-2.2.0/src/buffer_read.c0000644000000000000000000000022514675400254015647 0ustar rootroot/* Public domain. */ #include #include "buffer.h" int buffer_unixread(int fd,char *buf,unsigned int len) { return read(fd,buf,len); } admin/runit-2.2.0/src/ndelay.h0000644000000000000000000000017014675400254014663 0ustar rootroot/* Public domain. */ #ifndef NDELAY_H #define NDELAY_H extern int ndelay_on(int); extern int ndelay_off(int); #endif admin/runit-2.2.0/src/pmatch.c0000644000000000000000000000135314675400254014662 0ustar rootroot int pmatch(const char *p, const char *s, unsigned int len) { for (;;) { char c =*p++; if (! c) return(! len); switch(c) { case '*': if (! (c =*p)) return(1); for (;;) { if (! len) return(0); if (*s == c) break; ++s; --len; } continue; case '+': if ((c =*p++) != *s) return(0); for (;;) { if (! len) return(1); if (*s != c) break; ++s; --len; } continue; /* case '?': if (*p == '?') { if (*s != '?') return(0); ++p; } ++s; --len; continue; */ default: if (! len) return(0); if (*s != c) return(0); ++s; --len; continue; } } return(0); } admin/runit-2.2.0/src/svwaitdown.c0000644000000000000000000001123514675400254015613 0ustar rootroot#include #include "strerr.h" #include "error.h" #include "sgetopt.h" #include "scan.h" #include "open.h" #include "tai.h" #include "buffer.h" #define FATAL "svwaitdown: fatal: " #define WARN "svwaitdown: warning: " #define INFO "svwaitdown: " #define USAGE " [-v] [-t 1..6000] service ..." #define VERSION "$Id: 6cd3efc2e15e5e3d2fa60cd0c028e60958676ec7 $" const char *progname; const char * const *dir; unsigned int rc =0; void fatal(const char *m) { strerr_die3sys(111, FATAL, m, ": "); } void warn(const char *s1, const char *s2, struct strerr *e) { dir++; rc++; strerr_warn3(WARN, s1, s2, e); } void usage() { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } int main(int argc, const char * const *argv) { int opt; unsigned long sec =600; int verbose =0; int doexit =0; int dokill =0; int wdir; int fd; char status[20]; int r; unsigned long pid; struct tai start; struct tai now; progname =*argv; while ((opt =getopt(argc, argv, "t:xkvV")) != opteof) { switch(opt) { case 't': scan_ulong(optarg, &sec); if ((sec < 1) || (sec > 6000)) usage(); break; case 'x': doexit =1; break; case 'k': dokill =1; break; case 'v': verbose =1; break; case 'V': strerr_warn1(VERSION, 0); case '?': usage(); } } argv +=optind; if (! argv || ! *argv) usage(); if ((wdir =open_read(".")) == -1) fatal("unable to open current working directory"); for (dir =argv; *dir; ++dir) { if (dir != argv) if (fchdir(wdir) == -1) fatal("unable to switch to starting directory"); if (chdir(*dir) == -1) continue; /* bummer */ if ((fd =open_write("supervise/control")) == -1) continue; /* bummer */ if (write(fd, "dx", 1 +doexit) != (1 +doexit)) { close(fd); continue; /* bummer */ } close(fd); } dir =argv; tai_now(&start); while (*dir) { if (fchdir(wdir) == -1) fatal("unable to switch to starting directory"); if (chdir(*dir) == -1) { warn(*dir, ": unable to change directory: ", &strerr_sys); continue; } if ((fd =open_write("supervise/ok")) == -1) { if (errno == error_nodevice) { if (verbose) strerr_warn3(INFO, *dir, ": runsv not running.", 0); dir++; } else warn(*dir, ": unable to open supervise/ok: ", &strerr_sys); continue; } close(fd); if ((fd =open_read("supervise/status")) == -1) { warn(*dir, "unable to open supervise/status: ", &strerr_sys); continue; } r =buffer_unixread(fd, status, 20); close(fd); if ((r < 18) || (r == 19)) { /* supervise compatibility */ if (r == -1) warn(*dir, "unable to read supervise/status: ", &strerr_sys); else warn(*dir, ": unable to read supervise/status: bad format.", 0); continue; } pid =(unsigned char)status[15]; pid <<=8; pid +=(unsigned char)status[14]; pid <<=8; pid +=(unsigned char)status[13]; pid <<=8; pid +=(unsigned char)status[12]; if (! doexit && ! pid) { /* ok, service is down */ if (verbose) strerr_warn3(INFO, *dir, ": down.", 0); dir++; continue; } if (status[17] != 'd') { /* catch previous failures */ if ((fd =open_write("supervise/control")) == -1) { warn(*dir, ": unable to open supervise/control: ", &strerr_sys); continue; } if (write(fd, "dx", 1 +doexit) != (1 +doexit)) { warn(*dir, ": unable to write to supervise/control: ", &strerr_sys); close(fd); continue; } close(fd); } tai_now(&now); tai_sub(&now, &now, &start); if (tai_approx(&now) >= sec) { /* timeout */ if (verbose) strerr_warn2(INFO, "timeout.", 0); if (dokill) { if (chdir(*dir) == -1) { warn(*dir, ": unable to change directory: ", &strerr_sys); continue; } if ((fd =open_write("supervise/control")) == -1) { if (errno == error_nodevice) { if (verbose) strerr_warn3(INFO, *dir, ": runsv not running.", 0); dir++; } else warn(*argv, ": unable to open supervise/control: ", &strerr_sys); continue; } if (write(fd, "k", 1) != 1) warn(*argv, ": unable to write to supervise/control: ", &strerr_sys); else strerr_warn3(INFO, *dir, ": killed.", 0); close(fd); dir++; if (! *dir) _exit(111); continue; } _exit(111); } sleep(1); } if (fchdir(wdir) == -1) strerr_warn2(WARN, "unable to switch to starting directory: ", &strerr_sys); close(wdir); if (rc > 100) rc =100; _exit(rc); } admin/runit-2.2.0/src/ndelay_on.c0000644000000000000000000000034314675400254015354 0ustar rootroot/* Public domain. */ #include #include #include "ndelay.h" #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif int ndelay_on(int fd) { return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK); } admin/runit-2.2.0/src/sig_pause.c0000644000000000000000000000032314675400254015361 0ustar rootroot/* Public domain. */ #include #include "sig.h" #include "hassgprm.h" void sig_pause(void) { #ifdef HASSIGPROCMASK sigset_t ss; sigemptyset(&ss); sigsuspend(&ss); #else sigpause(0); #endif } admin/runit-2.2.0/src/uidgid.h0000644000000000000000000000044114675400254014655 0ustar rootroot#ifndef UIDGID_H #define UIDGID_H #include struct uidgid { uid_t uid; gid_t gid[61]; int gids; }; /* user */ extern unsigned int uidgid_get(struct uidgid *, char *); /* [:]user[:group[:group]...] */ extern unsigned int uidgids_get(struct uidgid *, char *); #endif admin/runit-2.2.0/src/haswaitp.h10000644000000000000000000000005514675400254015312 0ustar rootroot/* Public domain. */ /* sysdep: -waitpid */ admin/runit-2.2.0/src/error_str.c0000644000000000000000000001257614675400254015440 0ustar rootroot/* Public domain. */ #include #include "error.h" #define X(e,s) if (i == e) return s; const char *error_str(int i) { X(0,"no error") X(error_intr,"interrupted system call") X(error_nomem,"out of memory") X(error_noent,"file does not exist") X(error_txtbsy,"text busy") X(error_io,"input/output error") X(error_exist,"file already exists") X(error_timeout,"timed out") X(error_inprogress,"operation in progress") X(error_again,"temporary failure") X(error_wouldblock,"input/output would block") X(error_pipe,"broken pipe") X(error_perm,"permission denied") X(error_acces,"access denied") X(error_nodevice,"device not configured") X(error_proto,"protocol error") X(error_isdir,"is a directory") X(error_connrefused,"connection refused") X(error_notdir,"not a directory") #ifdef ESRCH X(ESRCH,"no such process") #endif #ifdef E2BIG X(E2BIG,"argument list too long") #endif #ifdef ENOEXEC X(ENOEXEC,"exec format error") #endif #ifdef EBADF X(EBADF,"file descriptor not open") #endif #ifdef ECHILD X(ECHILD,"no child processes") #endif #ifdef EDEADLK X(EDEADLK,"operation would cause deadlock") #endif #ifdef EFAULT X(EFAULT,"bad address") #endif #ifdef ENOTBLK X(ENOTBLK,"not a block device") #endif #ifdef EBUSY X(EBUSY,"device busy") #endif #ifdef EXDEV X(EXDEV,"cross-device link") #endif #ifdef ENODEV X(ENODEV,"device does not support operation") #endif #ifdef EINVAL X(EINVAL,"invalid argument") #endif #ifdef ENFILE X(ENFILE,"system cannot open more files") #endif #ifdef EMFILE X(EMFILE,"process cannot open more files") #endif #ifdef ENOTTY X(ENOTTY,"not a tty") #endif #ifdef EFBIG X(EFBIG,"file too big") #endif #ifdef ENOSPC X(ENOSPC,"out of disk space") #endif #ifdef ESPIPE X(ESPIPE,"unseekable descriptor") #endif #ifdef EROFS X(EROFS,"read-only file system") #endif #ifdef EMLINK X(EMLINK,"too many links") #endif #ifdef EDOM X(EDOM,"input out of range") #endif #ifdef ERANGE X(ERANGE,"output out of range") #endif #ifdef EALREADY X(EALREADY,"operation already in progress") #endif #ifdef ENOTSOCK X(ENOTSOCK,"not a socket") #endif #ifdef EDESTADDRREQ X(EDESTADDRREQ,"destination address required") #endif #ifdef EMSGSIZE X(EMSGSIZE,"message too long") #endif #ifdef EPROTOTYPE X(EPROTOTYPE,"incorrect protocol type") #endif #ifdef ENOPROTOOPT X(ENOPROTOOPT,"protocol not available") #endif #ifdef EPROTONOSUPPORT X(EPROTONOSUPPORT,"protocol not supported") #endif #ifdef ESOCKTNOSUPPORT X(ESOCKTNOSUPPORT,"socket type not supported") #endif #ifdef EOPNOTSUPP X(EOPNOTSUPP,"operation not supported") #endif #ifdef EPFNOSUPPORT X(EPFNOSUPPORT,"protocol family not supported") #endif #ifdef EAFNOSUPPORT X(EAFNOSUPPORT,"address family not supported") #endif #ifdef EADDRINUSE X(EADDRINUSE,"address already used") #endif #ifdef EADDRNOTAVAIL X(EADDRNOTAVAIL,"address not available") #endif #ifdef ENETDOWN X(ENETDOWN,"network down") #endif #ifdef ENETUNREACH X(ENETUNREACH,"network unreachable") #endif #ifdef ENETRESET X(ENETRESET,"network reset") #endif #ifdef ECONNABORTED X(ECONNABORTED,"connection aborted") #endif #ifdef ECONNRESET X(ECONNRESET,"connection reset") #endif #ifdef ENOBUFS X(ENOBUFS,"out of buffer space") #endif #ifdef EISCONN X(EISCONN,"already connected") #endif #ifdef ENOTCONN X(ENOTCONN,"not connected") #endif #ifdef ESHUTDOWN X(ESHUTDOWN,"socket shut down") #endif #ifdef ETOOMANYREFS X(ETOOMANYREFS,"too many references") #endif #ifdef ELOOP X(ELOOP,"symbolic link loop") #endif #ifdef ENAMETOOLONG X(ENAMETOOLONG,"file name too long") #endif #ifdef EHOSTDOWN X(EHOSTDOWN,"host down") #endif #ifdef EHOSTUNREACH X(EHOSTUNREACH,"host unreachable") #endif #ifdef ENOTEMPTY X(ENOTEMPTY,"directory not empty") #endif #ifdef EPROCLIM X(EPROCLIM,"too many processes") #endif #ifdef EUSERS X(EUSERS,"too many users") #endif #ifdef EDQUOT X(EDQUOT,"disk quota exceeded") #endif #ifdef ESTALE X(ESTALE,"stale NFS file handle") #endif #ifdef EREMOTE X(EREMOTE,"too many levels of remote in path") #endif #ifdef EBADRPC X(EBADRPC,"RPC structure is bad") #endif #ifdef ERPCMISMATCH X(ERPCMISMATCH,"RPC version mismatch") #endif #ifdef EPROGUNAVAIL X(EPROGUNAVAIL,"RPC program unavailable") #endif #ifdef EPROGMISMATCH X(EPROGMISMATCH,"program version mismatch") #endif #ifdef EPROCUNAVAIL X(EPROCUNAVAIL,"bad procedure for program") #endif #ifdef ENOLCK X(ENOLCK,"no locks available") #endif #ifdef ENOSYS X(ENOSYS,"system call not available") #endif #ifdef EFTYPE X(EFTYPE,"bad file type") #endif #ifdef EAUTH X(EAUTH,"authentication error") #endif #ifdef ENEEDAUTH X(ENEEDAUTH,"not authenticated") #endif #ifdef ENOSTR X(ENOSTR,"not a stream device") #endif #ifdef ETIME X(ETIME,"timer expired") #endif #ifdef ENOSR X(ENOSR,"out of stream resources") #endif #ifdef ENOMSG X(ENOMSG,"no message of desired type") #endif #ifdef EBADMSG X(EBADMSG,"bad message type") #endif #ifdef EIDRM X(EIDRM,"identifier removed") #endif #ifdef ENONET X(ENONET,"machine not on network") #endif #ifdef ERREMOTE X(ERREMOTE,"object not local") #endif #ifdef ENOLINK X(ENOLINK,"link severed") #endif #ifdef EADV X(EADV,"advertise error") #endif #ifdef ESRMNT X(ESRMNT,"srmount error") #endif #ifdef ECOMM X(ECOMM,"communication error") #endif #ifdef EMULTIHOP X(EMULTIHOP,"multihop attempted") #endif #ifdef EREMCHG X(EREMCHG,"remote address changed") #endif return "unknown error"; } admin/runit-2.2.0/src/stralloc_cat.c0000644000000000000000000000025714675400254016062 0ustar rootroot/* Public domain. */ #include "byte.h" #include "stralloc.h" int stralloc_cat(stralloc *sato,const stralloc *safrom) { return stralloc_catb(sato,safrom->s,safrom->len); } admin/runit-2.2.0/src/tai_sub.c0000644000000000000000000000020614675400254015030 0ustar rootroot/* Public domain. */ #include "tai.h" void tai_sub(struct tai *t,const struct tai *u,const struct tai *v) { t->x = u->x - v->x; } admin/runit-2.2.0/src/iopause.h10000644000000000000000000000046214675400254015141 0ustar rootroot/* Public domain. */ #ifndef IOPAUSE_H #define IOPAUSE_H /* sysdep: -poll */ typedef struct { int fd; short events; short revents; } iopause_fd; #define IOPAUSE_READ 1 #define IOPAUSE_WRITE 4 #include "taia.h" extern void iopause(iopause_fd *,unsigned int,struct taia *,struct taia *); #endif admin/runit-2.2.0/src/pmatch.h0000644000000000000000000000016114675400254014663 0ustar rootroot#ifndef PMATCH_H #define PMATCH_H extern unsigned int pmatch(const char *, const char *, unsigned int); #endif admin/runit-2.2.0/src/runsvchdir.dist0000644000000000000000000000003114675400254016306 0ustar rootrootusage: runsvchdir dir 1 admin/runit-2.2.0/src/strerr_die.c0000644000000000000000000000155414675400254015553 0ustar rootroot/* Public domain. */ #include #include "buffer.h" #include "strerr.h" void strerr_warn(const char *x1,const char *x2,const char *x3,const char *x4,const char *x5,const char *x6,const struct strerr *se) { strerr_sysinit(); if (x1) buffer_puts(buffer_2,x1); if (x2) buffer_puts(buffer_2,x2); if (x3) buffer_puts(buffer_2,x3); if (x4) buffer_puts(buffer_2,x4); if (x5) buffer_puts(buffer_2,x5); if (x6) buffer_puts(buffer_2,x6); while(se) { if (se->x) buffer_puts(buffer_2,se->x); if (se->y) buffer_puts(buffer_2,se->y); if (se->z) buffer_puts(buffer_2,se->z); se = se->who; } buffer_puts(buffer_2,"\n"); buffer_flush(buffer_2); } void strerr_die(int e,const char *x1,const char *x2,const char *x3,const char *x4,const char *x5,const char *x6,const struct strerr *se) { strerr_warn(x1,x2,x3,x4,x5,x6,se); _exit(e); } admin/runit-2.2.0/src/trypoll.c0000644000000000000000000000057214675400254015115 0ustar rootroot/* Public domain. */ #include #include #include #include int main() { struct pollfd x; x.fd = open("trypoll.c",O_RDONLY); if (x.fd == -1) _exit(111); x.events = POLLIN; if (poll(&x,1,10) == -1) _exit(1); if (x.revents != POLLIN) _exit(1); /* XXX: try to detect and avoid poll() imitation libraries */ _exit(0); } admin/runit-2.2.0/src/runsv.dist0000644000000000000000000000014314675400254015300 0ustar rootrootusage: runsv dir 1 starting run term starting term 0 0 starting no interrupt term 0 starting term admin/runit-2.2.0/src/iopause.c0000644000000000000000000000321414675400254015051 0ustar rootroot/* Public domain. */ #include "taia.h" #include "select.h" #include "iopause.h" void iopause(iopause_fd *x,unsigned int len,struct taia *deadline,struct taia *stamp) { struct taia t; int millisecs; double d; int i; if (taia_less(deadline,stamp)) millisecs = 0; else { t = *stamp; taia_sub(&t,deadline,&t); d = taia_approx(&t); if (d > 1000.0) d = 1000.0; millisecs = d * 1000.0 + 20.0; } for (i = 0;i < len;++i) x[i].revents = 0; #ifdef IOPAUSE_POLL poll(x,len,millisecs); /* XXX: some kernels apparently need x[0] even if len is 0 */ /* XXX: how to handle EAGAIN? are kernels really this dumb? */ /* XXX: how to handle EINVAL? when exactly can this happen? */ #else { struct timeval tv; fd_set rfds; fd_set wfds; int nfds; int fd; FD_ZERO(&rfds); FD_ZERO(&wfds); nfds = 1; for (i = 0;i < len;++i) { fd = x[i].fd; if (fd < 0) continue; if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/ if (fd >= nfds) nfds = fd + 1; if (x[i].events & IOPAUSE_READ) FD_SET(fd,&rfds); if (x[i].events & IOPAUSE_WRITE) FD_SET(fd,&wfds); } tv.tv_sec = millisecs / 1000; tv.tv_usec = 1000 * (millisecs % 1000); if (select(nfds,&rfds,&wfds,(fd_set *) 0,&tv) <= 0) return; /* XXX: for EBADF, could seek out and destroy the bad descriptor */ for (i = 0;i < len;++i) { fd = x[i].fd; if (fd < 0) continue; if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/ if (x[i].events & IOPAUSE_READ) if (FD_ISSET(fd,&rfds)) x[i].revents |= IOPAUSE_READ; if (x[i].events & IOPAUSE_WRITE) if (FD_ISSET(fd,&wfds)) x[i].revents |= IOPAUSE_WRITE; } } #endif } admin/runit-2.2.0/src/choose.sh0000644000000000000000000000040214675400254015050 0ustar rootroot result="$4" case "$1" in *c*) ./compile $2.c >/dev/null 2>&1 || result="$3" ;; esac case "$1" in *l*) ./load $2 >/dev/null 2>&1 || result="$3" ;; esac case "$1" in *r*) ./$2 >/dev/null 2>&1 || result="$3" ;; esac rm -f $2.o $2 exec cat "$result" admin/runit-2.2.0/src/subgetopt.h0000644000000000000000000000111014675400254015416 0ustar rootroot/* Public domain. */ #ifndef SUBGETOPT_H #define SUBGETOPT_H #ifndef SUBGETOPTNOSHORT #define sgopt subgetopt #define sgoptarg subgetoptarg #define sgoptind subgetoptind #define sgoptpos subgetoptpos #define sgoptproblem subgetoptproblem #define sgoptprogname subgetoptprogname #define sgoptdone subgetoptdone #endif #define SUBGETOPTDONE -1 extern int subgetopt(int,char *const *,const char *); extern const char *subgetoptarg; extern int subgetoptind; extern int subgetoptpos; extern int subgetoptproblem; extern const char *subgetoptprogname; extern int subgetoptdone; #endif admin/runit-2.2.0/src/check-local0000755000000000000000000000035014675400254015331 0ustar rootroot#!/bin/sh PATH=`pwd`:$PATH for i in ${1+"$@"}; do echo "Checking $i..." env - PATH="$PATH" ctmp="`pwd`/check-tmp" $i.check 2>&1 |cat -v >$i.local ./check-diff $i || ( cat $i.local; echo "$i failed."; exit 1 ) || exit 1 done admin/runit-2.2.0/src/sv.c0000644000000000000000000002721414675400254014042 0ustar rootroot#include #include #include #include #include "str.h" #include "strerr.h" #include "error.h" #include "sgetopt.h" #include "open.h" #include "env.h" #include "buffer.h" #include "fmt.h" #include "scan.h" #include "tai.h" #include "taia.h" #include "wait.h" #define USAGE " [-v] [-w sec] command service ..." #define USAGELSB " [-w sec] command" #define VERSION "$Id: bccdf71babe2596029c67cd0f6cec89bd05844a2 $" #define FATAL "fatal: " #define FAIL "fail: " #define WARN "warning: " #define OK "ok: " #define RUN "run: " #define FINISH "finish: " #define DOWN "down: " #define TIMEOUT "timeout: " #define KILL "kill: " char *progname; char *action; char *acts; char *varservice ="/service/"; char **service; char **servicex; unsigned int services; unsigned int rc =0; unsigned int lsb; unsigned int verbose =0; unsigned long wait =7; unsigned int kll =0; unsigned int islog =0; struct taia tstart, tnow, tdiff; struct tai tstatus; int (*act)(char*) =0; int (*cbk)(char*) =0; int curdir, fd, r; char svstatus[20]; char sulong[FMT_ULONG]; void usage() { if (!lsb) strerr_die4x(100, "usage: ", progname, USAGE, "\n"); strerr_die4x(2, "usage: ", progname, USAGELSB, "\n"); } void done(unsigned int e) { if (curdir != -1) fchdir(curdir); _exit(e); } void fatal(char *m1) { strerr_warn3(FATAL, m1, ": ", &strerr_sys); done(lsb ? 151 : 100); } void fatal2(char *m1, char *m2) { strerr_warn4(FATAL, m1, m2, ": ", &strerr_sys); done(lsb ? 151 : 100); } void out(char *p, char *m1) { buffer_puts(buffer_1, p); buffer_puts(buffer_1, *service); if (islog) buffer_puts(buffer_1, "/log"); buffer_puts(buffer_1, ": "); buffer_puts(buffer_1, m1); if (errno) { buffer_puts(buffer_1, ": "); buffer_puts(buffer_1, error_str(errno)); } buffer_puts(buffer_1, "\n"); buffer_flush(buffer_1); } void fail(char *m1) { ++rc; out(FAIL, m1); } void failx(char *m1) { errno =0; fail(m1); } void warn(char *m1) { ++rc; out(WARN, m1); } void warnx(char *m1) { errno =0; warn(m1); } void ok(char *m1) { errno =0; out(OK, m1); } void outs(const char *s) { buffer_puts(buffer_1, s); } void flush(const char *s) { outs(s); buffer_flush(buffer_1); } void outs2(const char *s) { buffer_puts(buffer_2, s); } void flush2(const char *s) { outs2(s); buffer_flush(buffer_2); } int svstatus_get() { if ((fd =open_write("supervise/ok")) == -1) { if (errno == error_nodevice) { *acts == 'x' ? ok("runsv not running") : failx("runsv not running"); return(0); } warn("unable to open supervise/ok"); return(-1); } close(fd); if ((fd =open_read("supervise/status")) == -1) { warn("unable to open supervise/status"); return(-1); } r =read(fd, svstatus, 20); close(fd); switch(r) { case 20: break; case -1: warn("unable to read supervise/status"); return(-1); default: warnx("unable to read supervise/status: bad format"); return(-1); } return(1); } unsigned int svstatus_print(char *m) { int pid; int normallyup =0; struct stat s; if (stat("down", &s) == -1) { if (errno != error_noent) { outs2(WARN); outs2("unable to stat "); outs2(*service); outs2("/down: "); outs2(error_str(errno)); flush2("\n"); return(0); } normallyup =1; } pid =(unsigned char) svstatus[15]; pid <<=8; pid +=(unsigned char)svstatus[14]; pid <<=8; pid +=(unsigned char)svstatus[13]; pid <<=8; pid +=(unsigned char)svstatus[12]; tai_unpack(svstatus, &tstatus); switch (svstatus[19]) { case 0: outs(DOWN); break; case 1: outs(RUN); break; case 2: outs(FINISH); break; } outs(m); outs(": "); if (svstatus[19]) { outs("(pid "); sulong[fmt_ulong(sulong, pid)] =0; outs(sulong); outs(") "); } buffer_put(buffer_1, sulong, fmt_ulong(sulong, tnow.sec.x < tstatus.x ? 0 : tnow.sec.x -tstatus.x)); outs("s"); if (pid && !normallyup) outs(", normally down"); if (!pid && normallyup) outs(", normally up"); if (pid && svstatus[16]) outs(", paused"); if (!pid && (svstatus[17] == 'u')) outs(", want up"); if (pid && (svstatus[17] == 'd')) outs(", want down"); if (pid && svstatus[18]) outs(", got TERM"); return(pid ? 1 : 2); } int status(char *unused) { int rc; rc =svstatus_get(); switch(rc) { case -1: if (lsb) done(4); case 0: return(0); } rc =svstatus_print(*service); islog =1; if (chdir("log") == -1) { if (errno != error_noent) { outs("; "); warn("unable to change directory"); } else outs("\n"); } else { outs("; "); if (svstatus_get()) { rc =svstatus_print("log"); outs("\n"); } } islog =0; flush(""); if (lsb) switch(rc) { case 1: done(0); case 2: done(3); case 0: done(4); } return(rc); } int checkscript() { char *prog[2]; struct stat s; int pid, w; if (stat("check", &s) == -1) { if (errno == error_noent) return(1); outs2(WARN); outs2("unable to stat "); outs2(*service); outs2("/check: "); outs2(error_str(errno)); flush2("\n"); return(0); } /* if (!(s.st_mode & S_IXUSR)) return(1); */ if ((pid =fork()) == -1) { outs2(WARN); outs2("unable to fork for "); outs2(*service); outs2("/check: "); outs2(error_str(errno)); flush2("\n"); return(0); } if (!pid) { prog[0] ="./check"; prog[1] =0; close(1); execve("check", prog, environ); outs2(WARN); outs2("unable to run "); outs2(*service); outs2("/check: "); outs2(error_str(errno)); flush2("\n"); _exit(0); } while (wait_pid(&w, pid) == -1) { if (errno == error_intr) continue; outs2(WARN); outs2("unable to wait for child "); outs2(*service); outs2("/check: "); outs2(error_str(errno)); flush2("\n"); return(0); } return(!wait_exitcode(w)); } int check(char *a) { unsigned int pid; if ((r =svstatus_get()) == -1) return(-1); while (*a) { if (r == 0) { if (*a == 'x') return(1); return(-1); } pid =(unsigned char)svstatus[15]; pid <<=8; pid +=(unsigned char)svstatus[14]; pid <<=8; pid +=(unsigned char)svstatus[13]; pid <<=8; pid +=(unsigned char)svstatus[12]; switch (*a) { case 'x': return(0); case 'u': if (!pid || svstatus[19] != 1) return(0); if (!checkscript()) return(0); break; case 'd': if (pid || svstatus[19] != 0) return(0); break; case 'C': if (pid) if (!checkscript()) return(0); break; case 't': case 'k': if (!pid && svstatus[17] == 'd') break; tai_unpack(svstatus, &tstatus); if ((tstart.sec.x > tstatus.x) || !pid || svstatus[18] || !checkscript()) return(0); break; case 'o': tai_unpack(svstatus, &tstatus); if ((!pid && tstart.sec.x > tstatus.x) || (pid && svstatus[17] != 'd')) return(0); break; case 'p': if (pid && !svstatus[16]) return(0); break; case 'c': if (pid && svstatus[16]) return(0); break; } ++a; } outs(OK); svstatus_print(*service); flush("\n"); return(1); } int control(char *a) { if (svstatus_get() <= 0) return(-1); if (svstatus[17] == *a) if (*a != 'd' || svstatus[18] == 1) return(0); /* once w/o term */ if ((fd =open_write("supervise/control")) == -1) { if (errno != error_nodevice) warn("unable to open supervise/control"); else *a == 'x' ? ok("runsv not running") : failx("runsv not running"); return(-1); } r =write(fd, a, str_len(a)); close(fd); if (r != str_len(a)) { warn("unable to write to supervise/control"); return(-1); } return(1); } void sleep_microseconds(unsigned int microseconds) { #if _POSIX_C_SOURCE >= 199309L struct timespec sleeptime; sleeptime.tv_sec = microseconds / 1000000; sleeptime.tv_nsec = (microseconds % 1000000) * 1000L; nanosleep(&sleeptime, NULL); #else usleep(microseconds); #endif } int main(int argc, char **argv) { unsigned int i, done; char *x; progname =*argv; for (i =str_len(*argv); i; --i) if ((*argv)[i -1] == '/') break; *argv +=i; optprogname =progname =*argv; service =argv; services =1; lsb =(str_diff(progname, "sv")); if ((x =env_get("SVDIR"))) varservice =x; if ((x =env_get("SVWAIT"))) scan_ulong(x, &wait); while ((i =getopt(argc, (char* const*)argv, "w:vV")) != opteof) { switch(i) { case 'w': scan_ulong(optarg, &wait); case 'v': verbose =1; break; case 'V': strerr_warn1(VERSION, 0); case '?': usage(); } } argv +=optind; argc -=optind; if (!(action =*argv++)) usage(); --argc; if (!lsb) { service =argv; services =argc; } if (!*service) usage(); taia_now(&tnow); tstart =tnow; if ((curdir =open_read(".")) == -1) fatal("unable to open current directory"); act =&control; acts ="s"; if (verbose) cbk =✓ switch (*action) { case 'x': case 'e': acts ="x"; break; case 'X': case 'E': acts ="x"; kll =1; cbk =✓ break; case 'D': acts ="d"; kll =1; cbk =✓ break; case 'T': acts ="tc"; kll =1; cbk =✓ break; case 't': if (!str_diff(action, "try-restart")) { acts ="tc"; cbk =✓ break; } case 'c': if (!str_diff(action, "check")) { act =0; acts ="C"; cbk =✓ break; } case 'u': case 'd': case 'o': case 'p': case 'h': case 'a': case 'i': case 'k': case 'q': case '1': case '2': action[1] =0; acts =action; break; case 's': if (!str_diff(action, "shutdown")) { acts ="x"; cbk =✓ break; } if (!str_diff(action, "start")) { acts ="u"; cbk =✓ break; } if (!str_diff(action, "stop")) { acts ="d"; cbk =✓ break; } if (lsb && str_diff(action, "status")) usage(); act =&status; cbk =0; break; case 'r': if (!str_diff(action, "restart")) { acts ="tcu"; cbk =✓ break; } if (!str_diff(action, "reload")) { acts ="h"; cbk =✓ break; } usage(); case 'f': if (!str_diff(action, "force-reload")) { acts ="tc"; kll =1; cbk =✓ break; } if (!str_diff(action, "force-restart")) { acts ="tcu"; kll =1; cbk =✓ break; } if (!str_diff(action, "force-shutdown")) { acts ="x"; kll =1; cbk =✓ break; } if (!str_diff(action, "force-stop")) { acts ="d"; kll =1; cbk =✓ break; } default: usage(); } servicex =service; for (i =0; i < services; ++i) { if ((**service != '/') && (**service != '.') && **service && ((*service)[str_len(*service) -1] != '/')) { if ((chdir(varservice) == -1) || (chdir(*service) == -1)) { fail("unable to change to service directory"); *service =0; } } else if (chdir(*service) == -1) { fail("unable to change to service directory"); *service =0; } if (*service) if (act && (act(acts) == -1)) *service =0; if (fchdir(curdir) == -1) fatal("unable to change to original directory"); service++; } if (*cbk) for (;;) { taia_sub(&tdiff, &tnow, &tstart); service =servicex; done =1; for (i =0; i < services; ++i, ++service) { if (!*service) continue; if ((**service != '/') && (**service != '.')) { if ((chdir(varservice) == -1) || (chdir(*service) == -1)) { fail("unable to change to service directory"); *service =0; } } else if (chdir(*service) == -1) { fail("unable to change to service directory"); *service =0; } if (*service) { if (cbk(acts) != 0) *service =0; else done =0; } if (*service && taia_approx(&tdiff) > wait) { kll ? outs(KILL) : outs(TIMEOUT); if (svstatus_get() > 0) { svstatus_print(*service); ++rc; } flush("\n"); if (kll) control("k"); *service =0; } if (fchdir(curdir) == -1) fatal("unable to change to original directory"); } if (done) break; sleep_microseconds(420000); taia_now(&tnow); } return(rc > 99 ? 99 : rc); } admin/runit-2.2.0/src/fd.h0000644000000000000000000000016314675400254014002 0ustar rootroot/* Public domain. */ #ifndef FD_H #define FD_H extern int fd_copy(int,int); extern int fd_move(int,int); #endif admin/runit-2.2.0/src/print-ar.sh0000644000000000000000000000037114675400254015331 0ustar rootrootcat warn-auto.sh echo 'main="$1"; shift' echo 'rm -f "$main"' echo 'ar cr "$main" ${1+"$@"}' case "`cat systype`" in sunos-5.*) ;; unix_sv*) ;; irix64-*) ;; irix-*) ;; dgux-*) ;; hp-ux-*) ;; sco*) ;; *) echo 'ranlib "$main"' ;; esac admin/runit-2.2.0/src/fmt.h0000644000000000000000000000212414675400254014176 0ustar rootroot/* Public domain. */ #ifndef FMT_H #define FMT_H #define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */ #define FMT_LEN ((char *) 0) /* convenient abbreviation */ extern unsigned int fmt_uint(char *,unsigned int); extern unsigned int fmt_uint0(char *,unsigned int,unsigned int); extern unsigned int fmt_xint(char *,unsigned int); extern unsigned int fmt_nbbint(char *,unsigned int,unsigned int,unsigned int,unsigned int); extern unsigned int fmt_ushort(char *,unsigned short); extern unsigned int fmt_xshort(char *,unsigned short); extern unsigned int fmt_nbbshort(char *,unsigned int,unsigned int,unsigned int,unsigned short); extern unsigned int fmt_ulong(char *,unsigned long); extern unsigned int fmt_xlong(char *,unsigned long); extern unsigned int fmt_nbblong(char *,unsigned int,unsigned int,unsigned int,unsigned long); extern unsigned int fmt_plusminus(char *,int); extern unsigned int fmt_minus(char *,int); extern unsigned int fmt_0x(char *,int); extern unsigned int fmt_str(char *,const char *); extern unsigned int fmt_strn(char *,const char *,unsigned int); #endif admin/runit-2.2.0/src/strerr_sys.c0000644000000000000000000000033214675400254015621 0ustar rootroot/* Public domain. */ #include "error.h" #include "strerr.h" struct strerr strerr_sys; void strerr_sysinit(void) { strerr_sys.who = 0; strerr_sys.x = error_str(errno); strerr_sys.y = ""; strerr_sys.z = ""; } admin/runit-2.2.0/src/runsvdir.check0000755000000000000000000000003314675400254016112 0ustar rootroot#!/bin/sh runsvdir echo $? admin/runit-2.2.0/src/runsvdir.dist0000644000000000000000000000003414675400254015776 0ustar rootrootusage: runsvdir [-P] dir 1 admin/runit-2.2.0/src/env.c0000644000000000000000000000047214675400254014177 0ustar rootroot/* Public domain. */ #include "str.h" #include "env.h" extern /*@null@*/char *env_get(const char *s) { int i; unsigned int len; if (!s) return 0; len = str_len(s); for (i = 0;environ[i];++i) if (str_start(environ[i],s) && (environ[i][len] == '=')) return environ[i] + len + 1; return 0; } admin/runit-2.2.0/src/subgetopt.c0000644000000000000000000000260514675400254015423 0ustar rootroot/* Public domain. */ #define SUBGETOPTNOSHORT #include "subgetopt.h" #define sgopt subgetopt #define optind subgetoptind #define optpos subgetoptpos #define optarg subgetoptarg #define optproblem subgetoptproblem #define optdone subgetoptdone int optind = 1; int optpos = 0; const char *optarg = 0; int optproblem = 0; int optdone = SUBGETOPTDONE; int sgopt(int argc,char *const *argv,const char *opts) { int c; const char *s; optarg = 0; if (!argv || (optind >= argc) || !argv[optind]) return optdone; if (optpos && !argv[optind][optpos]) { ++optind; optpos = 0; if ((optind >= argc) || !argv[optind]) return optdone; } if (!optpos) { if (argv[optind][0] != '-') return optdone; ++optpos; c = argv[optind][1]; if ((c == '-') || (c == 0)) { if (c) ++optind; optpos = 0; return optdone; } /* otherwise c is reassigned below */ } c = argv[optind][optpos]; ++optpos; s = opts; while (*s) { if (c == *s) { if (s[1] == ':') { optarg = argv[optind] + optpos; ++optind; optpos = 0; if (!*optarg) { optarg = argv[optind]; if ((optind >= argc) || !optarg) { /* argument past end */ optproblem = c; return '?'; } ++optind; } } return c; } ++s; if (*s == ':') ++s; } optproblem = c; return '?'; } admin/runit-2.2.0/src/chpst.c0000644000000000000000000003240114675400254014525 0ustar rootroot#include #include #include #include #include #include #include "sgetopt.h" #include "error.h" #include "strerr.h" #include "str.h" #include "uidgid.h" #include "strerr.h" #include "scan.h" #include "fmt.h" #include "lock.h" #include "pathexec.h" #include "stralloc.h" #include "byte.h" #include "open.h" #include "openreadclose.h" #include "direntry.h" #define USAGE_MAIN " [-vVP012] [-u user[:group]] [-U user[:group]] [-b argv0] [-e dir] [-/ root] [-C pwd] [-n nice] [-l|-L lock] [-m n] [-d n] [-o n] [-p n] [-f n] [-c n] [-t n] prog" #define FATAL "chpst: fatal: " #define WARNING "chpst: warning: " const char *progname; static stralloc sa; void fatal(const char *m) { strerr_die3sys(111, FATAL, m, ": "); } void fatal2(const char *m0, const char *m1) { strerr_die5sys(111, FATAL, m0, ": ", m1, ": "); } void fatalx(const char *m0, const char *m1) { strerr_die4x(111, FATAL, m0, ": ", m1); } void warn(const char *m) { strerr_warn2(WARNING, m, 0); } void die_nomem() { strerr_die2x(111, FATAL, "out of memory."); } void usage() { strerr_die4x(100, "usage: ", progname, USAGE_MAIN, "\n"); } char *set_user =0; char *env_user =0; char *argv0 =0; const char *env_dir =0; unsigned int verbose =0; unsigned int pgrp =0; unsigned int nostdin =0; unsigned int nostdout =0; unsigned int nostderr =0; long limitd =-2; long limits =-2; long limitl =-2; long limita =-2; long limito =-2; long limitp =-2; long limitf =-2; long limitc =-2; long limitr =-2; long limitt =-2; long nicelvl =0; const char *lock =0; const char *root =0; const char *pwd =0; unsigned int lockdelay; void suidgid(char *user, unsigned int ext) { struct uidgid ugid; if (ext) { if (! uidgids_get(&ugid, user)) { if (*user == ':') fatalx("invalid uid/gids", user +1); if (errno) fatal("unable to get password/group file entry"); fatalx("unknown user/group", user); } } else if (! uidgid_get(&ugid, user)) { if (errno) fatal("unable to get password file entry"); fatalx("unknown account", user); } if (setgroups(ugid.gids, ugid.gid) == -1) fatal("unable to setgroups"); if (setgid(*ugid.gid) == -1) fatal("unable to setgid"); if (setuid(ugid.uid) == -1) fatal("unable to setuid"); } void euidgid(char *user, unsigned int ext) { struct uidgid ugid; char bufnum[FMT_ULONG]; if (ext) { if (! uidgids_get(&ugid, user)) { if (*user == ':') fatalx("invalid uid/gids", user +1); if (errno) fatal("unable to get password/group file entry"); fatalx("unknown user/group", user); } } else if (! uidgid_get(&ugid, user)) { if (errno) fatal("unable to get password file entry"); fatalx("unknown account", user); } bufnum[fmt_ulong(bufnum, *ugid.gid)] =0; if (! pathexec_env("GID", bufnum)) die_nomem(); bufnum[fmt_ulong(bufnum, ugid.uid)] =0; if (! pathexec_env("UID", bufnum)) die_nomem(); } void edir(const char *dirname) { int wdir; DIR *dir; direntry *d; int i; if ((wdir =open_read(".")) == -1) fatal("unable to open current working directory"); if (chdir(dirname)) fatal2("unable to switch to directory", dirname); if (! (dir =opendir("."))) fatal2("unable to open directory", dirname); for (;;) { errno =0; d =readdir(dir); if (! d) { if (errno) fatal2("unable to read directory", dirname); break; } if (d->d_name[0] == '.') continue; if (openreadclose(d->d_name, &sa, 256) == -1) { if ((errno == error_isdir) && env_dir) { if (verbose) strerr_warn6(WARNING, "unable to read ", dirname, "/", d->d_name, ": ", &strerr_sys); continue; } else strerr_die6sys(111, FATAL, "unable to read ", dirname, "/", d->d_name, ": "); } if (sa.len) { sa.len =byte_chr(sa.s, sa.len, '\n'); while (sa.len && (sa.s[sa.len -1] == ' ' || sa.s[sa.len -1] == '\t')) --sa.len; for (i =0; i < sa.len; ++i) if (! sa.s[i]) sa.s[i] ='\n'; if (! stralloc_0(&sa)) die_nomem(); if (! pathexec_env(d->d_name, sa.s)) die_nomem(); } else if (! pathexec_env(d->d_name, 0)) die_nomem(); } closedir(dir); if (fchdir(wdir) == -1) fatal("unable to switch to starting directory"); close(wdir); } void slock_die(const char *m, const char *f, unsigned int x) { if (! x) fatal2(m, f); _exit(0); } void slock(const char *f, unsigned int d, unsigned int x) { int fd; if ((fd =open_append(f)) == -1) slock_die("unable to open lock", f, x); if (d) { if (lock_ex(fd) == -1) slock_die("unable to lock", f, x); return; } if (lock_exnb(fd) == -1) slock_die("unable to lock", f, x); } void limit(int what, long l) { struct rlimit r; if (getrlimit(what, &r) == -1) fatal("unable to getrlimit()"); if ((l < 0) || (l > r.rlim_max)) r.rlim_cur =r.rlim_max; else r.rlim_cur =l; if (setrlimit(what, &r) == -1) fatal("unable to setrlimit()"); } void slimit() { if (limitd >= -1) { #ifdef RLIMIT_DATA limit(RLIMIT_DATA, limitd); #else if (verbose) warn("system does not support RLIMIT_DATA"); #endif } if (limits >= -1) { #ifdef RLIMIT_STACK limit(RLIMIT_STACK, limits); #else if (verbose) warn("system does not support RLIMIT_STACK"); #endif } if (limitl >= -1) { #ifdef RLIMIT_MEMLOCK limit(RLIMIT_MEMLOCK, limitl); #else if (verbose) warn("system does not support RLIMIT_MEMLOCK"); #endif } if (limita >= -1) { #ifdef RLIMIT_VMEM limit(RLIMIT_VMEM, limita); #else #ifdef RLIMIT_AS limit(RLIMIT_AS, limita); #else if (verbose) warn("system does neither support RLIMIT_VMEM nor RLIMIT_AS"); #endif #endif } if (limito >= -1) { #ifdef RLIMIT_NOFILE limit(RLIMIT_NOFILE, limito); #else #ifdef RLIMIT_OFILE limit(RLIMIT_OFILE, limito); #else if (verbose) warn("system does neither support RLIMIT_NOFILE nor RLIMIT_OFILE"); #endif #endif } if (limitp >= -1) { #ifdef RLIMIT_NPROC limit(RLIMIT_NPROC, limitp); #else if (verbose) warn("system does not support RLIMIT_NPROC"); #endif } if (limitf >= -1) { #ifdef RLIMIT_FSIZE limit(RLIMIT_FSIZE, limitf); #else if (verbose) warn("system does not support RLIMIT_FSIZE"); #endif } if (limitc >= -1) { #ifdef RLIMIT_CORE limit(RLIMIT_CORE, limitc); #else if (verbose) warn("system does not support RLIMIT_CORE"); #endif } if (limitr >= -1) { #ifdef RLIMIT_RSS limit(RLIMIT_RSS, limitr); #else if (verbose) warn("system does not support RLIMIT_RSS"); #endif } if (limitt >= -1) { #ifdef RLIMIT_CPU limit(RLIMIT_CPU, limitt); #else if (verbose) warn("system does not support RLIMIT_CPU"); #endif } } /* argv[0] */ void setuidgid(int, char *const *); void envuidgid(int, char *const *); void envdir(int, char *const *); void pgrphack(int, char *const *); void setlock(int, char *const *); void softlimit(int, char *const *); int main(int argc, char **argv) { int opt; int i; unsigned long ul; progname =argv[0]; for (i =str_len(progname); i; --i) if (progname[i -1] == '/') { progname +=i; break; } if (progname[0] == 'd') ++progname; /* argv[0] */ if (str_equal(progname, "setuidgid")) setuidgid(argc, argv); if (str_equal(progname, "envuidgid")) envuidgid(argc, argv); if (str_equal(progname, "envdir")) envdir(argc, argv); if (str_equal(progname, "pgrphack")) pgrphack(argc, argv); if (str_equal(progname, "setlock")) setlock(argc, argv); if (str_equal(progname, "softlimit")) softlimit(argc, argv); while ((opt =getopt(argc, argv, "u:U:b:e:m:d:o:p:f:c:r:t:/:C:n:l:L:vP012V")) != opteof) switch(opt) { case 'u': set_user =(char*)optarg; break; case 'U': env_user =(char*)optarg; break; case 'b': argv0 =(char*)optarg; break; case 'e': env_dir =optarg; break; case 'm': if (optarg[scan_ulong(optarg, &ul)]) usage(); limits =limitl =limita =limitd =ul; break; case 'd': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitd =ul; break; case 'o': if (optarg[scan_ulong(optarg, &ul)]) usage(); limito =ul; break; case 'p': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitp =ul; break; case 'f': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitf =ul; break; case 'c': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitc =ul; break; case 'r': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitr =ul; break; case 't': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitt =ul; break; case '/': root =optarg; break; case 'C': pwd =optarg; break; case 'n': switch (*optarg) { case '-': ++optarg; if (optarg[scan_ulong(optarg, &ul)]) usage(); nicelvl =ul; nicelvl *=-1; break; case '+': ++optarg; default: if (optarg[scan_ulong(optarg, &ul)]) usage(); nicelvl =ul; break; } break; case 'l': if (lock) usage(); lock =optarg; lockdelay =1; break; case 'L': if (lock) usage(); lock =optarg; lockdelay =0; break; case 'v': verbose =1; break; case 'P': pgrp =1; break; case '0': nostdin =1; break; case '1': nostdout =1; break; case '2': nostderr =1; break; case 'V': strerr_warn1("$Id: e46a05449578fd7b8ee604f3ea6e81cd77d7d6f8 $", 0); case '?': usage(); } argv +=optind; if (! argv || ! *argv) usage(); if (pgrp) setsid(); if (env_dir) edir(env_dir); if (root) { if (chdir(root) == -1) fatal2("unable to change directory", root); if (chroot(".") == -1) fatal("unable to change root directory"); } if (pwd) { if (chdir(pwd) == -1) fatal2("unable to change directory", pwd); } if (nicelvl) { errno =0; if (nice(nicelvl) == -1) if (errno) fatal("unable to set nice level"); } if (env_user) euidgid(env_user, 1); if (set_user) suidgid(set_user, 1); if (lock) slock(lock, lockdelay, 0); if (nostdin) if (close(0) == -1) fatal("unable to close stdin"); if (nostdout) if (close(1) == -1) fatal("unable to close stdout"); if (nostderr) if (close(2) == -1) fatal("unable to close stderr"); slimit(); progname =*argv; if (argv0) *argv =argv0; pathexec_env_run(progname, argv); fatal2("unable to run", *argv); return(0); } /* argv[0] */ #define USAGE_SETUIDGID " account child" #define USAGE_ENVUIDGID " account child" #define USAGE_ENVDIR " dir child" #define USAGE_PGRPHACK " child" #define USAGE_SETLOCK " [ -nNxX ] file program [ arg ... ]" #define USAGE_SOFTLIMIT " [-a allbytes] [-c corebytes] [-d databytes] [-f filebytes] [-l lockbytes] [-m membytes] [-o openfiles] [-p processes] [-r residentbytes] [-s stackbytes] [-t cpusecs] child" void setuidgid_usage() { strerr_die4x(100, "usage: ", progname, USAGE_SETUIDGID, "\n"); } void setuidgid(int argc, char *const *argv) { const char *account; if (! (account =*++argv)) setuidgid_usage(); if (! *++argv) setuidgid_usage(); suidgid((char*)account, 0); pathexec(argv); fatal2("unable to run", *argv); } void envuidgid_usage() { strerr_die4x(100, "usage: ", progname, USAGE_ENVUIDGID, "\n"); } void envuidgid(int argc, char *const *argv) { const char *account; if (! (account =*++argv)) envuidgid_usage(); if (! *++argv) envuidgid_usage(); euidgid((char*)account, 0); pathexec(argv); fatal2("unable to run", *argv); } void envdir_usage() { strerr_die4x(100, "usage: ", progname, USAGE_ENVDIR, "\n"); } void envdir(int argc, char *const *argv) { const char *dir; if (! (dir =*++argv)) envdir_usage(); if (! *++argv) envdir_usage(); edir(dir); pathexec(argv); fatal2("unable to run", *argv); } void pgrphack_usage() { strerr_die4x(100, "usage: ", progname, USAGE_PGRPHACK, "\n"); } void pgrphack(int argc, char *const *argv) { if (! *++argv) pgrphack_usage(); setsid(); pathexec(argv); fatal2("unable to run", *argv); } void setlock_usage() { strerr_die4x(100, "usage: ", progname, USAGE_SETLOCK, "\n"); } void setlock(int argc, char *const *argv) { int opt; unsigned int delay =0; unsigned int x =0; const char *fn; while ((opt =getopt(argc, argv, "nNxX")) != opteof) switch(opt) { case 'n': delay =1; break; case 'N': delay =0; break; case 'x': x =1; break; case 'X': x =0; break; default: setlock_usage(); } argv +=optind; if (! (fn =*argv)) setlock_usage(); if (! *++argv) setlock_usage(); slock(fn, delay, x); pathexec(argv); if (! x) fatal2("unable to run", *argv); _exit(0); } void softlimit_usage() { strerr_die4x(100, "usage: ", progname, USAGE_SOFTLIMIT, "\n"); } void getlarg(long *l) { unsigned long ul; if (str_equal(optarg, "=")) { *l =-1; return; } if (optarg[scan_ulong(optarg, &ul)]) usage(); *l =ul; } void softlimit(int argc, char *const *argv) { int opt; while ((opt =getopt(argc,argv,"a:c:d:f:l:m:o:p:r:s:t:")) != opteof) switch(opt) { case '?': softlimit_usage(); case 'a': getlarg(&limita); break; case 'c': getlarg(&limitc); break; case 'd': getlarg(&limitd); break; case 'f': getlarg(&limitf); break; case 'l': getlarg(&limitl); break; case 'm': getlarg(&limitd); limits =limitl =limita =limitd; break; case 'o': getlarg(&limito); break; case 'p': getlarg(&limitp); break; case 'r': getlarg(&limitr); break; case 's': getlarg(&limits); break; case 't': getlarg(&limitt); break; } argv +=optind; if (!*argv) softlimit_usage(); slimit(); pathexec(argv); fatal2("unable to run", *argv); } admin/runit-2.2.0/src/reboot_system.h10000644000000000000000000000021314675400254016364 0ustar rootroot#include #include /* sysdep: -std reboot */ int reboot_system(int what) { return(reboot(what, (char *)0)); } admin/runit-2.2.0/src/tai_now.c0000644000000000000000000000017414675400254015046 0ustar rootroot/* Public domain. */ #include #include "tai.h" void tai_now(struct tai *t) { tai_unix(t,time((time_t *) 0)); } admin/runit-2.2.0/src/tai_unpack.c0000644000000000000000000000063014675400254015521 0ustar rootroot/* Public domain. */ #include "tai.h" void tai_unpack(const char *s,struct tai *t) { uint64 x; x = (unsigned char) s[0]; x <<= 8; x += (unsigned char) s[1]; x <<= 8; x += (unsigned char) s[2]; x <<= 8; x += (unsigned char) s[3]; x <<= 8; x += (unsigned char) s[4]; x <<= 8; x += (unsigned char) s[5]; x <<= 8; x += (unsigned char) s[6]; x <<= 8; x += (unsigned char) s[7]; t->x = x; } admin/runit-2.2.0/src/uint64.h10000644000000000000000000000017414675400254014625 0ustar rootroot/* Public domain. */ #ifndef UINT64_H #define UINT64_H /* sysdep: -ulong64 */ typedef unsigned long long uint64; #endif admin/runit-2.2.0/src/conf-cc0000644000000000000000000000026114675400254014472 0ustar rootrootgcc -O2 -Wall gcc -O2 -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings This will be used to compile .c files. admin/runit-2.2.0/src/taia_sub.c0000644000000000000000000000071614675400254015177 0ustar rootroot/* Public domain. */ #include "taia.h" /* XXX: breaks tai encapsulation */ void taia_sub(struct taia *t,const struct taia *u,const struct taia *v) { unsigned long unano = u->nano; unsigned long uatto = u->atto; t->sec.x = u->sec.x - v->sec.x; t->nano = unano - v->nano; t->atto = uatto - v->atto; if (t->atto > uatto) { t->atto += 1000000000UL; --t->nano; } if (t->nano > unano) { t->nano += 1000000000UL; --t->sec.x; } } admin/runit-2.2.0/src/svwaitdown.check0000755000000000000000000000062614675400254016453 0ustar rootroot#!/bin/sh rm -rf "${ctmp}" svwaitdown echo $? svwaitdown -V echo $? mkdir "${ctmp}" echo '#!/bin/sh' >"${ctmp}"/run echo 'echo starting' >>"${ctmp}"/run echo 'exec sleep 14' >>"${ctmp}"/run chmod 700 "${ctmp}"/run runsv "${ctmp}" & sleep 1 test -r "${ctmp}"/supervise/stat || sleep 2 svwaitdown "${ctmp}" echo $? svwaitdown -x "${ctmp}" echo $? cat "${ctmp}"/supervise/stat wait echo $? rm -rf "${ctmp}" admin/runit-2.2.0/src/strerr.h0000644000000000000000000000532214675400254014734 0ustar rootroot/* Public domain. */ #ifndef STRERR_H #define STRERR_H struct strerr { struct strerr *who; const char *x; const char *y; const char *z; } ; extern struct strerr strerr_sys; extern void strerr_sysinit(void); extern const char *strerr(const struct strerr *); extern void strerr_warn(const char *,const char *,const char *,const char *,const char *,const char *,const struct strerr *); extern void strerr_die(int,const char *,const char *,const char *,const char *,const char *,const char *,const struct strerr *); #define STRERR(r,se,a) \ { se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; } #define STRERR_SYS(r,se,a) \ { se.who = &strerr_sys; se.x = a; se.y = 0; se.z = 0; return r; } #define STRERR_SYS3(r,se,a,b,c) \ { se.who = &strerr_sys; se.x = a; se.y = b; se.z = c; return r; } #define strerr_warn6(x1,x2,x3,x4,x5,x6,se) \ strerr_warn((x1),(x2),(x3),(x4),(x5),(x6),(se)) #define strerr_warn5(x1,x2,x3,x4,x5,se) \ strerr_warn((x1),(x2),(x3),(x4),(x5),0,(se)) #define strerr_warn4(x1,x2,x3,x4,se) \ strerr_warn((x1),(x2),(x3),(x4),0,0,(se)) #define strerr_warn3(x1,x2,x3,se) \ strerr_warn((x1),(x2),(x3),0,0,0,(se)) #define strerr_warn2(x1,x2,se) \ strerr_warn((x1),(x2),0,0,0,0,(se)) #define strerr_warn1(x1,se) \ strerr_warn((x1),0,0,0,0,0,(se)) #define strerr_die6(e,x1,x2,x3,x4,x5,x6,se) \ strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(se)) #define strerr_die5(e,x1,x2,x3,x4,x5,se) \ strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,(se)) #define strerr_die4(e,x1,x2,x3,x4,se) \ strerr_die((e),(x1),(x2),(x3),(x4),0,0,(se)) #define strerr_die3(e,x1,x2,x3,se) \ strerr_die((e),(x1),(x2),(x3),0,0,0,(se)) #define strerr_die2(e,x1,x2,se) \ strerr_die((e),(x1),(x2),0,0,0,0,(se)) #define strerr_die1(e,x1,se) \ strerr_die((e),(x1),0,0,0,0,0,(se)) #define strerr_die6sys(e,x1,x2,x3,x4,x5,x6) \ strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),&strerr_sys) #define strerr_die5sys(e,x1,x2,x3,x4,x5) \ strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,&strerr_sys) #define strerr_die4sys(e,x1,x2,x3,x4) \ strerr_die((e),(x1),(x2),(x3),(x4),0,0,&strerr_sys) #define strerr_die3sys(e,x1,x2,x3) \ strerr_die((e),(x1),(x2),(x3),0,0,0,&strerr_sys) #define strerr_die2sys(e,x1,x2) \ strerr_die((e),(x1),(x2),0,0,0,0,&strerr_sys) #define strerr_die1sys(e,x1) \ strerr_die((e),(x1),0,0,0,0,0,&strerr_sys) #define strerr_die6x(e,x1,x2,x3,x4,x5,x6) \ strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),0) #define strerr_die5x(e,x1,x2,x3,x4,x5) \ strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,0) #define strerr_die4x(e,x1,x2,x3,x4) \ strerr_die((e),(x1),(x2),(x3),(x4),0,0,0) #define strerr_die3x(e,x1,x2,x3) \ strerr_die((e),(x1),(x2),(x3),0,0,0,0) #define strerr_die2x(e,x1,x2) \ strerr_die((e),(x1),(x2),0,0,0,0,0) #define strerr_die1x(e,x1) \ strerr_die((e),(x1),0,0,0,0,0,0) #endif admin/runit-2.2.0/src/lock_exnb.c0000644000000000000000000000041214675400254015345 0ustar rootroot/* Public domain. */ #include #include #include #include "hasflock.h" #include "lock.h" #ifdef HASFLOCK int lock_exnb(int fd) { return flock(fd,LOCK_EX | LOCK_NB); } #else int lock_exnb(int fd) { return lockf(fd,2,0); } #endif admin/runit-2.2.0/src/str.h0000644000000000000000000000070414675400254014222 0ustar rootroot/* Public domain. */ #ifndef STR_H #define STR_H extern unsigned int str_copy(char *,const char *); extern int str_diff(const char *,const char *); extern int str_diffn(const char *,const char *,unsigned int); extern unsigned int str_len(const char *); extern unsigned int str_chr(const char *,int); extern unsigned int str_rchr(const char *,int); extern int str_start(const char *,const char *); #define str_equal(s,t) (!str_diff((s),(t))) #endif admin/runit-2.2.0/src/error.c0000644000000000000000000000232114675400254014533 0ustar rootroot/* Public domain. */ #include #include "error.h" /* warning: as coverage improves here, should update error_{str,temp} */ int error_intr = #ifdef EINTR EINTR; #else -1; #endif int error_nomem = #ifdef ENOMEM ENOMEM; #else -2; #endif int error_noent = #ifdef ENOENT ENOENT; #else -3; #endif int error_txtbsy = #ifdef ETXTBSY ETXTBSY; #else -4; #endif int error_io = #ifdef EIO EIO; #else -5; #endif int error_exist = #ifdef EEXIST EEXIST; #else -6; #endif int error_timeout = #ifdef ETIMEDOUT ETIMEDOUT; #else -7; #endif int error_inprogress = #ifdef EINPROGRESS EINPROGRESS; #else -8; #endif int error_wouldblock = #ifdef EWOULDBLOCK EWOULDBLOCK; #else -9; #endif int error_again = #ifdef EAGAIN EAGAIN; #else -10; #endif int error_pipe = #ifdef EPIPE EPIPE; #else -11; #endif int error_perm = #ifdef EPERM EPERM; #else -12; #endif int error_acces = #ifdef EACCES EACCES; #else -13; #endif int error_nodevice = #ifdef ENXIO ENXIO; #else -14; #endif int error_proto = #ifdef EPROTO EPROTO; #else -15; #endif int error_isdir = #ifdef EISDIR EISDIR; #else -16; #endif int error_connrefused = #ifdef ECONNREFUSED ECONNREFUSED; #else -17; #endif int error_notdir = #ifdef ENOTDIR ENOTDIR; #else -18; #endif admin/runit-2.2.0/src/svwaitup.check0000755000000000000000000000075514675400254016133 0ustar rootroot#!/bin/sh rm -rf "${ctmp}" svwaitup echo $? svwaitup -V echo $? mkdir "${ctmp}" echo '#!/bin/sh' >"${ctmp}"/run echo 'echo starting' >>"${ctmp}"/run echo 'exec sleep 14' >>"${ctmp}"/run chmod 700 "${ctmp}"/run runsv "${ctmp}" & sleep 1 test -r "${ctmp}"/supervise/stat || sleep 2 svwaitup "${ctmp}" echo $? cat "${ctmp}"/supervise/stat svwaitup -s2 "${ctmp}" echo $? cat "${ctmp}"/supervise/stat runsvctrl exit "${ctmp}" wait echo $? chpst -2 svwaitup -s2 "${ctmp}" echo $? rm -rf "${ctmp}" admin/runit-2.2.0/src/str_start.c0000644000000000000000000000056214675400254015434 0ustar rootroot/* Public domain. */ #include "str.h" int str_start(register const char *s,register const char *t) { register char x; for (;;) { x = *t++; if (!x) return 1; if (x != *s++) return 0; x = *t++; if (!x) return 1; if (x != *s++) return 0; x = *t++; if (!x) return 1; if (x != *s++) return 0; x = *t++; if (!x) return 1; if (x != *s++) return 0; } } admin/runit-2.2.0/src/trysgact.c0000644000000000000000000000030014675400254015235 0ustar rootroot/* Public domain. */ #include int main() { struct sigaction sa; sa.sa_handler = 0; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(0,&sa,(struct sigaction *) 0); } admin/runit-2.2.0/src/svwaitup.dist0000644000000000000000000000017614675400254016013 0ustar rootrootusage: svwaitup [-v] [-s 1..600] service ... 1 $Id$ usage: svwaitup [-v] [-s 1..600] service ... 1 starting 0 run 0 run 0 1 admin/runit-2.2.0/src/fmt_uint.c0000644000000000000000000000020514675400254015226 0ustar rootroot/* Public domain. */ #include "fmt.h" unsigned int fmt_uint(register char *s,register unsigned int u) { return fmt_ulong(s,u); } admin/runit-2.2.0/src/hasflock.h20000644000000000000000000000007614675400254015270 0ustar rootroot/* Public domain. */ /* sysdep: +flock */ #define HASFLOCK 1 admin/runit-2.2.0/src/readclose.h0000644000000000000000000000031314675400254015347 0ustar rootroot/* Public domain. */ #ifndef READCLOSE_H #define READCLOSE_H #include "stralloc.h" extern int readclose_append(int,stralloc *,unsigned int); extern int readclose(int,stralloc *,unsigned int); #endif admin/runit-2.2.0/src/runsvctrl.c0000644000000000000000000000342114675400254015446 0ustar rootroot#include #include "strerr.h" #include "error.h" #include "open.h" #define USAGE " u|d|o|p|c|h|a|i|q|1|2|t|k|x|e service ..." #define VERSION "$Id: ccf8fc8ee3c340d8de97b5ddd9270b55e0f437cb $" #define FATAL "runsvctrl: fatal: " #define WARNING "runsvctrl: warning: " char *progname; unsigned int rc =0; void usage() { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } void fatal(char *m1) { strerr_die3sys(111, FATAL, m1, ": "); } void warn(char *m1, char *m2) { rc++; strerr_warn5(WARNING, m1, ": ", m2, ": ", &strerr_sys); } void warnx(char *m1, char *m2) { rc++; strerr_warn4(WARNING, m1, ": ", m2, 0); } int ctrl(char *name, char c) { int fd; if ((fd =open_write("supervise/control")) == -1) { if (errno == error_nodevice) warnx(name, "runsv not running."); else warn(name, "unable to open supervise/control"); return(-1); } if (write(fd, &c, 1) != 1) { warn(name, "unable to write to supervise/control"); return(-1); } return(1); } int main(int argc, char **argv) { char **dir; int curdir; char c; progname =*argv++; if (! argv || ! *argv) usage(); switch ((c =**argv)) { case 'e': c ='x'; case 'u': case 'd': case 'o': case 'x': case 'p': case 'c': case 'h': case 'a': case 'i': case 't': case 'k': case 'q': case '1': case '2': break; default: usage(); } dir =++argv; if (! dir || ! *dir) usage(); if ((curdir =open_read(".")) == -1) { rc =100; fatal("unable to open current directory"); } for (; dir && *dir; dir++) { if (chdir(*dir) == -1) { warn(*dir, "unable to change directory"); continue; } ctrl(*dir, c); if (fchdir(curdir) == -1) { rc =100; fatal("unable to change directory"); } } if (rc > 100) rc =100; _exit(rc); } admin/runit-2.2.0/src/tryulong64.c0000644000000000000000000000057614675400254015451 0ustar rootroot/* Public domain. */ #include int main() { unsigned long u; u = 1; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; if (!u) _exit(1); _exit(0); } admin/runit-2.2.0/src/buffer_2.c0000644000000000000000000000026614675400254015102 0ustar rootroot/* Public domain. */ #include "buffer.h" char buffer_2_space[256]; static buffer it = BUFFER_INIT(buffer_unixwrite,2,buffer_2_space,sizeof buffer_2_space); buffer *buffer_2 = ⁢ admin/runit-2.2.0/src/check-dist0000755000000000000000000000026514675400254015207 0ustar rootroot#!/bin/sh PATH=`pwd`:$PATH for i in `cat ../package/commands`; do echo "Creating new $i.dist..." env - PATH="$PATH" ctmp="`pwd`/check-tmp" $i.check 2>&1 |cat -v >$i.dist done admin/runit-2.2.0/src/coe.h0000644000000000000000000000012014675400254014150 0ustar rootroot/* Public domain. */ #ifndef COE_H #define COE_H extern int coe(int); #endif admin/runit-2.2.0/src/tai.h0000644000000000000000000000116214675400254014166 0ustar rootroot/* Public domain. */ #ifndef TAI_H #define TAI_H #include "uint64.h" struct tai { uint64 x; } ; #define tai_unix(t,u) ((void) ((t)->x = 4611686018427387914ULL + (uint64) (u))) extern void tai_now(struct tai *); #define tai_approx(t) ((double) ((t)->x)) extern void tai_add(struct tai *,const struct tai *,const struct tai *); extern void tai_sub(struct tai *,const struct tai *,const struct tai *); #define tai_less(t,u) ((t)->x < (u)->x) #define TAI_PACK 8 extern void tai_pack(char *,const struct tai *); extern void tai_unpack(const char *,struct tai *); extern void tai_uint(struct tai *,unsigned int); #endif admin/runit-2.2.0/src/stralloc.h0000644000000000000000000000222714675400254015237 0ustar rootroot/* Public domain. */ #ifndef STRALLOC_H #define STRALLOC_H #include "gen_alloc.h" GEN_ALLOC_typedef(stralloc,char,s,len,a) extern int stralloc_ready(stralloc *,unsigned int); extern int stralloc_readyplus(stralloc *,unsigned int); extern int stralloc_copy(stralloc *,const stralloc *); extern int stralloc_cat(stralloc *,const stralloc *); extern int stralloc_copys(stralloc *,const char *); extern int stralloc_cats(stralloc *,const char *); extern int stralloc_copyb(stralloc *,const char *,unsigned int); extern int stralloc_catb(stralloc *,const char *,unsigned int); extern int stralloc_append(stralloc *,const char *); /* beware: this takes a pointer to 1 char */ extern int stralloc_starts(stralloc *,const char *); #define stralloc_0(sa) stralloc_append(sa,"") extern int stralloc_catulong0(stralloc *,unsigned long,unsigned int); extern int stralloc_catlong0(stralloc *,long,unsigned int); #define stralloc_catlong(sa,l) (stralloc_catlong0((sa),(l),0)) #define stralloc_catuint0(sa,i,n) (stralloc_catulong0((sa),(i),(n))) #define stralloc_catint0(sa,i,n) (stralloc_catlong0((sa),(i),(n))) #define stralloc_catint(sa,i) (stralloc_catlong0((sa),(i),0)) #endif admin/runit-2.2.0/src/env.h0000644000000000000000000000020114675400254014172 0ustar rootroot/* Public domain. */ #ifndef ENV_H #define ENV_H extern char **environ; extern /*@null@*/char *env_get(const char *); #endif admin/runit-2.2.0/src/trydrent.c0000644000000000000000000000016114675400254015255 0ustar rootroot/* Public domain. */ #include #include void foo() { DIR *dir; struct dirent *d; } admin/runit-2.2.0/src/open_append.c0000644000000000000000000000026614675400254015700 0ustar rootroot/* Public domain. */ #include #include #include "open.h" int open_append(const char *fn) { return open(fn,O_WRONLY | O_NDELAY | O_APPEND | O_CREAT,0600); } admin/runit-2.2.0/src/sgetopt.c0000644000000000000000000000241714675400254015075 0ustar rootroot/* Public domain. */ /* sgetopt.c, sgetopt.h: (yet another) improved getopt clone, outer layer D. J. Bernstein, djb@pobox.com. Depends on subgetopt.h, buffer.h. No system requirements. 19991219: Switched to buffer.h. 19970208: Cleanups. 931201: Baseline. No known patent problems. Documentation in sgetopt.3. */ #include "buffer.h" #define SGETOPTNOSHORT #include "sgetopt.h" #define SUBGETOPTNOSHORT #include "subgetopt.h" #define getopt sgetoptmine #define optind subgetoptind #define opterr sgetopterr #define optproblem subgetoptproblem #define optprogname sgetoptprogname int opterr = 1; const char *optprogname = 0; int getopt(int argc,char *const *argv,const char *opts) { int c; const char *s; if (!optprogname) { optprogname = *argv; if (!optprogname) optprogname = ""; for (s = optprogname;*s;++s) if (*s == '/') optprogname = s + 1; } c = subgetopt(argc,argv,opts); if (opterr) if (c == '?') { char chp[2]; chp[0] = optproblem; chp[1] = '\n'; buffer_puts(buffer_2,optprogname); if (argv[optind] && (optind < argc)) buffer_puts(buffer_2,": illegal option -- "); else buffer_puts(buffer_2,": option requires an argument -- "); buffer_put(buffer_2,chp,2); buffer_flush(buffer_2); } return c; } admin/runit-2.2.0/src/error.h0000644000000000000000000000125014675400254014540 0ustar rootroot/* Public domain. */ #ifndef ERROR_H #define ERROR_H /* 20030124: include -upcoming glibc changes */ #include /* extern int errno; */ extern int error_intr; extern int error_nomem; extern int error_noent; extern int error_txtbsy; extern int error_io; extern int error_exist; extern int error_timeout; extern int error_inprogress; extern int error_wouldblock; extern int error_again; extern int error_pipe; extern int error_perm; extern int error_acces; extern int error_nodevice; extern int error_proto; extern int error_isdir; extern int error_connrefused; extern int error_notdir; extern const char *error_str(int); extern int error_temp(int); #endif admin/runit-2.2.0/src/runsvchdir.check0000755000000000000000000000003514675400254016427 0ustar rootroot#!/bin/sh runsvchdir echo $? admin/runit-2.2.0/src/hassgprm.h20000644000000000000000000000011214675400254015311 0ustar rootroot/* Public domain. */ /* sysdep: +sigprocmask */ #define HASSIGPROCMASK 1 admin/runit-2.2.0/src/tryuwtmpx.c0000644000000000000000000000016514675400254015511 0ustar rootroot#include #include struct futmpx ut; int main(void) { char *s =ut.ut_name; return(0); } admin/runit-2.2.0/src/str_diff.c0000644000000000000000000000072314675400254015206 0ustar rootroot/* Public domain. */ #include "str.h" int str_diff(register const char *s,register const char *t) { register char x; for (;;) { x = *s; if (x != *t) break; if (!x) break; ++s; ++t; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; } return ((int)(unsigned int)(unsigned char) x) - ((int)(unsigned int)(unsigned char) *t); } admin/runit-2.2.0/src/sig_catch.c0000644000000000000000000000055314675400254015333 0ustar rootroot/* Public domain. */ #include #include "sig.h" #include "hassgact.h" void sig_catch(int sig,void (*f)()) { #ifdef HASSIGACTION struct sigaction sa; sa.sa_handler = f; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(sig,&sa,(struct sigaction *) 0); #else signal(sig,f); /* won't work under System V, even nowadays---dorks */ #endif } admin/runit-2.2.0/src/stralloc_opyb.c0000644000000000000000000000042114675400254016255 0ustar rootroot/* Public domain. */ #include "stralloc.h" #include "byte.h" int stralloc_copyb(stralloc *sa,const char *s,unsigned int n) { if (!stralloc_ready(sa,n + 1)) return 0; byte_copy(sa->s,n,s); sa->len = n; sa->s[n] = 'Z'; /* ``offensive programming'' */ return 1; } admin/runit-2.2.0/src/uint64.h20000644000000000000000000000016714675400254014630 0ustar rootroot/* Public domain. */ #ifndef UINT64_H #define UINT64_H /* sysdep: +ulong64 */ typedef unsigned long uint64; #endif admin/runit-2.2.0/src/uidgid.c0000644000000000000000000000301114675400254014644 0ustar rootroot#include #include #include #include "uidgid.h" #include "str.h" #include "scan.h" /* user */ unsigned int uidgid_get(struct uidgid *u, char *ug) { struct passwd *pwd =0; if (! (pwd =getpwnam(ug))) return(0); u->gid[0] =pwd->pw_gid; u->gids =1; u->uid =pwd->pw_uid; return(1); } /* uid:gid[:gid[:gid]...] */ unsigned int uidgids_set(struct uidgid *u, char *ug) { unsigned long id; int i; if (*(ug +=scan_ulong(ug, &id)) != ':') return(0); u->uid =(uid_t)id; ++ug; for (i =0; i < 60; ++i, ++ug) { ug +=scan_ulong(ug, &id); u->gid[i] =(gid_t)id; if (*ug != ':') { ++i; break; } } u->gid[i] =0; u->gids =i; if (*ug) return(0); return(1); } /* [:]user[:group[:group]...] */ unsigned int uidgids_get(struct uidgid *u, char *ug) { char *g =0; struct passwd *pwd =0; struct group *gr =0; int i, d =0; if (*ug == ':') return(uidgids_set(u, ug +1)); if (ug[(d =str_chr(ug, ':'))] == ':') { ug[d] =0; g =ug +d +1; } if (! (pwd =getpwnam(ug))) { if (g) ug[d] =':'; return(0); } u->uid =pwd->pw_uid; if (! g) { u->gid[0] =pwd->pw_gid; u->gids =1; return(1); } ug[d] =':'; for (i =0; i < 60; ++i) { if (g[(d =str_chr(g, ':'))] == ':') { g[d] =0; if (! (gr =getgrnam(g))) { g[d] =':'; return(0); } g[d] =':'; u->gid[i] =gr->gr_gid; g +=d +1; } else { if (! (gr =getgrnam(g))) return(0); u->gid[i++] =gr->gr_gid; break; } } u->gid[i] =0; u->gids =i; return(1); } admin/runit-2.2.0/src/fmt_ptime.h0000644000000000000000000000045314675400254015377 0ustar rootroot#ifndef FMT_PTIME_H #define FMT_PTIME_H #define FMT_PTIME 30 #include #include #include "taia.h" extern unsigned int fmt_ptime(char *, struct taia *); extern unsigned int fmt_ptime_iso8601(char *, struct taia *); extern unsigned int fmt_taia(char *, struct taia *); #endif admin/runit-2.2.0/src/open_write.c0000644000000000000000000000023314675400254015555 0ustar rootroot/* Public domain. */ #include #include #include "open.h" int open_write(const char *fn) { return open(fn,O_WRONLY | O_NDELAY); } admin/runit-2.2.0/src/direntry.h10000644000000000000000000000024714675400254015335 0ustar rootroot/* Public domain. */ #ifndef DIRENTRY_H #define DIRENTRY_H /* sysdep: -dirent */ #include #include #define direntry struct direct #endif admin/runit-2.2.0/src/pathexec.h0000644000000000000000000000044114675400254015211 0ustar rootroot/* Public domain. */ #ifndef PATHEXEC_H #define PATHEXEC_H extern void pathexec_run(const char *,char * const *,char * const *); extern int pathexec_env(const char *,const char *); extern void pathexec_env_run(const char *, char * const *); extern void pathexec(char * const *); #endif admin/runit-2.2.0/src/sig.c0000644000000000000000000000046514675400254014173 0ustar rootroot/* Public domain. */ #include #include "sig.h" int sig_alarm = SIGALRM; int sig_child = SIGCHLD; int sig_cont = SIGCONT; int sig_hangup = SIGHUP; int sig_int = SIGINT; int sig_pipe = SIGPIPE; int sig_term = SIGTERM; void (*sig_defaulthandler)() = SIG_DFL; void (*sig_ignorehandler)() = SIG_IGN; admin/runit-2.2.0/src/iopause.h20000644000000000000000000000052314675400254015140 0ustar rootroot/* Public domain. */ #ifndef IOPAUSE_H #define IOPAUSE_H /* sysdep: +poll */ #define IOPAUSE_POLL #include #include typedef struct pollfd iopause_fd; #define IOPAUSE_READ POLLIN #define IOPAUSE_WRITE POLLOUT #include "taia.h" extern void iopause(iopause_fd *,unsigned int,struct taia *,struct taia *); #endif admin/runit-2.2.0/src/buffer_1.c0000644000000000000000000000030114675400254015067 0ustar rootroot/* Public domain. */ #include "buffer.h" char buffer_1_space[BUFFER_OUTSIZE]; static buffer it = BUFFER_INIT(buffer_unixwrite,1,buffer_1_space,sizeof buffer_1_space); buffer *buffer_1 = ⁢ admin/runit-2.2.0/src/coe.c0000644000000000000000000000015514675400254014153 0ustar rootroot/* Public domain. */ #include #include "coe.h" int coe(int fd) { return fcntl(fd,F_SETFD,1); } admin/runit-2.2.0/src/x86cpuid.c0000644000000000000000000000132014675400254015052 0ustar rootroot/* Public domain. */ #include #include #include void nope() { exit(1); } int main() { unsigned long x[4]; unsigned long y[4]; int i; int j; char c; signal(SIGILL,nope); x[0] = y[0] = 0; x[1] = y[1] = 0; x[2] = y[2] = 0; x[3] = y[3] = 0; asm volatile(".byte 15;.byte 162" : "=a"(x[0]),"=b"(x[1]),"=c"(x[3]),"=d"(x[2]) : "0"(0) ); if (!x[0]) return 0; asm volatile(".byte 15;.byte 162" : "=a"(y[0]),"=b"(y[1]),"=c"(y[2]),"=d"(y[3]) : "0"(1) ); for (i = 1;i < 4;++i) for (j = 0;j < 4;++j) { c = x[i] >> (8 * j); if (c < 32) c = 32; if (c > 126) c = 126; putchar(c); } printf("-%08lx-%08lx\n",y[0],y[3]); return 0; } admin/runit-2.2.0/src/chpst.dist0000644000000000000000000000065114675400254015250 0ustar rootrootusage: chpst [-vVP012] [-u user[:group]] [-U user[:group]] [-b argv0] [-e dir] [-/ root] [-C pwd] [-n nice] [-l|-L lock] [-m n] [-d n] [-o n] [-p n] [-f n] [-c n] [-t n] prog 100 $Id: e46a05449578fd7b8ee604f3ea6e81cd77d7d6f8 $ usage: chpst [-vVP012] [-u user[:group]] [-U user[:group]] [-b argv0] [-e dir] [-/ root] [-C pwd] [-n nice] [-l|-L lock] [-m n] [-d n] [-o n] [-p n] [-f n] [-c n] [-t n] prog 100 test=1 0 0 0 0 0 admin/runit-2.2.0/src/runsvdir.c0000644000000000000000000001461214675400254015264 0ustar rootroot#include #include #include #include #include "direntry.h" #include "strerr.h" #include "error.h" #include "wait.h" #include "env.h" #include "open.h" #include "pathexec.h" #include "fd.h" #include "str.h" #include "coe.h" #include "iopause.h" #include "sig.h" #include "ndelay.h" #define USAGE " [-P] dir" #define VERSION "$Id: 28cb04495cffccf27650de3cf2981942679781cd $" #define MAXSERVICES 1000 char *progname; char *svdir; unsigned long dev =0; unsigned long ino =0; struct { unsigned long dev; unsigned long ino; int pid; int isgone; } sv[MAXSERVICES]; int svnum =0; int check =1; char *rplog =0; int rploglen; int logpipe[2]; iopause_fd io[1]; struct taia stamplog; int exitsoon =0; int pgrp =0; void usage () { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } void fatal(char *m1, char *m2) { strerr_die6sys(100, "runsvdir ", svdir, ": fatal: ", m1, m2, ": "); } void warn(char *m1, char *m2) { strerr_warn6("runsvdir ", svdir, ": warning: ", m1, m2, ": ", &strerr_sys); } void warn3x(char *m1, char *m2, char *m3) { strerr_warn6("runsvdir ", svdir, ": warning: ", m1, m2, m3, 0); } void s_term() { exitsoon =1; } void s_hangup() { exitsoon =2; } void runsv(int no, char *name) { int pid; if ((pid =fork()) == -1) { warn("unable to fork for ", name); return; } if (pid == 0) { /* child */ char *prog[3]; prog[0] ="runsv"; prog[1] =name; prog[2] =0; sig_uncatch(sig_hangup); sig_uncatch(sig_term); if (pgrp) setsid(); pathexec_run(*prog, prog, (char* const*)environ); fatal("unable to start runsv ", name); } sv[no].pid =pid; } void runsvdir() { DIR *dir; direntry *d; int i; struct stat s; if (! (dir =opendir("."))) { warn("unable to open directory ", svdir); return; } for (i =0; i < svnum; i++) sv[i].isgone =1; errno =0; while ((d =readdir(dir))) { if (d->d_name[0] == '.') continue; if (stat(d->d_name, &s) == -1) { warn("unable to stat ", d->d_name); errno =0; continue; } if (! S_ISDIR(s.st_mode)) continue; for (i =0; i < svnum; i++) { if ((sv[i].ino == s.st_ino) && (sv[i].dev == s.st_dev)) { sv[i].isgone =0; if (! sv[i].pid) runsv(i, d->d_name); break; } } if (i == svnum) { /* new service */ if (svnum >= MAXSERVICES) { warn3x("unable to start runsv ", d->d_name, ": too many services."); continue; } sv[i].ino =s.st_ino; sv[i].dev =s.st_dev; sv[i].pid =0; sv[i].isgone =0; svnum++; runsv(i, d->d_name); check =1; } } if (errno) { warn("unable to read directory ", svdir); closedir(dir); check =1; return; } closedir(dir); /* SIGTERM removed runsv's */ for (i =0; i < svnum; i++) { if (! sv[i].isgone) continue; if (sv[i].pid) kill(sv[i].pid, SIGTERM); sv[i] =sv[--svnum]; check =1; } } int setup_log() { if ((rploglen =str_len(rplog)) < 7) { warn3x("log must have at least seven characters.", 0, 0); return(0); } if (pipe(logpipe) == -1) { warn3x("unable to create pipe for log.", 0, 0); return(-1); } coe(logpipe[1]); coe(logpipe[0]); ndelay_on(logpipe[0]); ndelay_on(logpipe[1]); if (fd_copy(2, logpipe[1]) == -1) { warn3x("unable to set filedescriptor for log.", 0, 0); return(-1); } io[0].fd =logpipe[0]; io[0].events =IOPAUSE_READ; taia_now(&stamplog); return(1); } int main(int argc, char **argv) { struct stat s; time_t mtime =0; int wstat; int curdir; int pid; struct taia deadline; struct taia now; struct taia stampcheck; char ch; int i; progname =*argv++; if (! argv || ! *argv) usage(); if (**argv == '-') { switch (*(*argv +1)) { case 'P': pgrp =1; case '-': ++argv; } if (! argv || ! *argv) usage(); } sig_catch(sig_term, s_term); sig_catch(sig_hangup, s_hangup); svdir =*argv++; if (argv && *argv) { rplog =*argv; if (setup_log() != 1) { rplog =0; warn3x("log service disabled.", 0, 0); } } if ((curdir =open_read(".")) == -1) fatal("unable to open current directory", 0); coe(curdir); taia_now(&stampcheck); for (;;) { /* collect children */ for (;;) { if ((pid =wait_nohang(&wstat)) <= 0) break; for (i =0; i < svnum; i++) { if (pid == sv[i].pid) { /* runsv has gone */ sv[i].pid =0; check =1; break; } } } taia_now(&now); if (now.sec.x < (stampcheck.sec.x -3)) { /* time warp */ warn3x("time warp: resetting time stamp.", 0, 0); taia_now(&stampcheck); taia_now(&now); if (rplog) taia_now(&stamplog); } if (taia_less(&now, &stampcheck) == 0) { /* wait at least a second */ taia_uint(&deadline, 1); taia_add(&stampcheck, &now, &deadline); if (stat(svdir, &s) != -1) { if (check || \ s.st_mtime != mtime || s.st_ino != ino || s.st_dev != dev) { /* svdir modified */ if (chdir(svdir) != -1) { mtime =s.st_mtime; dev =s.st_dev; ino =s.st_ino; check =0; if (now.sec.x <= (4611686018427387914ULL +(uint64)mtime)) sleep(1); runsvdir(); while (fchdir(curdir) == -1) { warn("unable to change directory, pausing", 0); sleep(5); } } else warn("unable to change directory to ", svdir); } } else warn("unable to stat ", svdir); } if (rplog) if (taia_less(&now, &stamplog) == 0) { write(logpipe[1], ".", 1); taia_uint(&deadline, 900); taia_add(&stamplog, &now, &deadline); } taia_uint(&deadline, check ? 1 : 5); taia_add(&deadline, &now, &deadline); sig_block(sig_child); if (rplog) iopause(io, 1, &deadline, &now); else iopause(0, 0, &deadline, &now); sig_unblock(sig_child); if (rplog && (io[0].revents | IOPAUSE_READ)) while (read(logpipe[0], &ch, 1) > 0) if (ch) { for (i =6; i < rploglen; i++) rplog[i -1] =rplog[i]; rplog[rploglen -1] =ch; } switch(exitsoon) { case 1: _exit(0); case 2: for (i =0; i < svnum; i++) if (sv[i].pid) kill(sv[i].pid, SIGTERM); _exit(111); } } /* not reached */ _exit(0); } admin/runit-2.2.0/src/byte_copy.c0000644000000000000000000000050114675400254015375 0ustar rootroot/* Public domain. */ #include "byte.h" void byte_copy(to,n,from) register char *to; register unsigned int n; register char *from; { for (;;) { if (!n) return; *to++ = *from++; --n; if (!n) return; *to++ = *from++; --n; if (!n) return; *to++ = *from++; --n; if (!n) return; *to++ = *from++; --n; } } admin/runit-2.2.0/src/stralloc_cats.c0000644000000000000000000000025314675400254016241 0ustar rootroot/* Public domain. */ #include "byte.h" #include "str.h" #include "stralloc.h" int stralloc_cats(stralloc *sa,const char *s) { return stralloc_catb(sa,s,str_len(s)); } admin/runit-2.2.0/src/sig.h0000644000000000000000000000111314675400254014167 0ustar rootroot/* Public domain. */ #ifndef SIG_H #define SIG_H extern int sig_alarm; extern int sig_child; extern int sig_cont; extern int sig_hangup; extern int sig_int; extern int sig_pipe; extern int sig_term; extern void (*sig_defaulthandler)(); extern void (*sig_ignorehandler)(); extern void sig_catch(int,void (*)()); #define sig_ignore(s) (sig_catch((s),sig_ignorehandler)) #define sig_uncatch(s) (sig_catch((s),sig_defaulthandler)) extern void sig_block(int); extern void sig_unblock(int); extern void sig_blocknone(void); extern void sig_pause(void); extern void sig_dfl(int); #endif admin/runit-2.2.0/src/stralloc_eady.c0000644000000000000000000000034114675400254016227 0ustar rootroot/* Public domain. */ #include "alloc.h" #include "stralloc.h" #include "gen_allocdefs.h" GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready) GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus) admin/runit-2.2.0/src/scan_ulong.c0000644000000000000000000000055114675400254015535 0ustar rootroot/* Public domain. */ #include "scan.h" unsigned int scan_ulong(register const char *s,register unsigned long *u) { register unsigned int pos = 0; register unsigned long result = 0; register unsigned long c; while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) { result = result * 10 + c; ++pos; } *u = result; return pos; } admin/runit-2.2.0/src/runsvstat.c0000644000000000000000000001013114675400254015451 0ustar rootroot#include #include #include #include "strerr.h" #include "error.h" #include "sgetopt.h" #include "open.h" #include "buffer.h" #include "tai.h" #include "fmt.h" #define USAGE " [ -l ] service ..." #define VERSION "$Id: c17bbd3eda6f3c57027dfb47ff676bdd3fefff9f $" #define FATAL "runsvstat: fatal: " #define WARNING "runsvstat: warning: " const char *progname; unsigned int rc =0; struct stat s; int showlog =0; void usage() { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } void fatal(char *m1) { strerr_die3sys(111, FATAL, m1, ": "); } void warn(char *m1, char *m2) { rc++; strerr_warn5(WARNING, m1, ": ", m2, ": ", &strerr_sys); } void warnx(char *m1, char *m2) { rc++; strerr_warn4(WARNING, m1, ": ", m2, 0); } int show_status(char *name) { char status[20]; int pid; int fd; int normallyup =0; char sulong[FMT_ULONG]; struct tai when; struct tai now; if (stat("down", &s) == -1) { if (errno != error_noent) { warn(name, "unable to stat down"); return(-1); } normallyup = 1; } if ((fd =open_write("supervise/ok")) == -1) { if (errno == error_nodevice) warnx(name, "runsv not running."); else warn(name, "unable to open supervise/ok"); return(-1); } close(fd); if ((fd =open_read("supervise/status")) == -1) { warn(name, "unable to open supervise/status"); return(-1); } switch(read(fd, status, 20)) { case 20: break; case -1: warn(name, "unable to read supervise/status"); return(-1); default: warnx(name, "unable to read supervise/status: bad format."); return(-1); } pid =(unsigned char) status[15]; pid <<=8; pid +=(unsigned char)status[14]; pid <<=8; pid +=(unsigned char)status[13]; pid <<=8; pid +=(unsigned char)status[12]; tai_unpack(status,&when); tai_now(&now); if (tai_less(&now,&when)) when =now; tai_sub(&when,&now,&when); buffer_puts(buffer_1, name); buffer_puts(buffer_1, ": "); if (pid) { switch (status[19]) { case 1: buffer_puts(buffer_1, "run "); break; case 2: buffer_puts(buffer_1, "finish "); break; } buffer_puts(buffer_1, "(pid "); buffer_put(buffer_1, sulong, fmt_ulong(sulong, pid)); buffer_puts(buffer_1, ") "); } else buffer_puts(buffer_1, "down "); buffer_put(buffer_1, sulong, fmt_ulong(sulong, tai_approx(&when))); buffer_puts(buffer_1, " seconds"); if (pid && !normallyup) buffer_puts(buffer_1,", normally down"); if (!pid && normallyup) buffer_puts(buffer_1,", normally up"); if (pid && status[16]) buffer_puts(buffer_1,", paused"); if (!pid && (status[17] == 'u')) buffer_puts(buffer_1,", want up"); if (pid && (status[17] == 'd')) buffer_puts(buffer_1,", want down"); if (pid && status[18]) buffer_puts(buffer_1, ", got TERM"); /* buffer_putsflush(buffer_1, "\n"); */ return(1); } int main(int argc, char **argv) { int opt; int curdir; char **dir; progname =*argv; while ((opt =getopt(argc, (const char * const *)argv, "lV")) != opteof) { switch(opt) { case 'l': showlog =1; break; case 'V': strerr_warn1(VERSION, 0); case '?': usage(); } } argv +=optind; dir =argv; if (! dir || ! *dir) usage(); if ((curdir =open_read(".")) == -1) { rc =100; fatal("unable to open current directory"); } for (; dir && *dir; dir++) { if (chdir(*dir) == -1) { warn(*dir, "unable to change directory"); continue; } if (show_status(*dir) == 1) { if (showlog) { if (stat("log", &s) == -1) { if (errno != error_noent) warn("unable to stat()", "./log"); } else { if (! S_ISDIR(s.st_mode)) warnx("./log", "not a directory."); else { if (chdir("log") == -1) { warn(*dir, "unable to change directory"); continue; } show_status("\n log"); } } } buffer_puts(buffer_1, "\n"); buffer_flush(buffer_1); } if (fchdir(curdir) == -1) { rc =100; fatal("unable to change directory"); } } if (rc > 100) rc =100; _exit(rc); } admin/runit-2.2.0/src/sgetopt.h0000644000000000000000000000073314675400254015101 0ustar rootroot/* Public domain. */ #ifndef SGETOPT_H #define SGETOPT_H #ifndef SGETOPTNOSHORT #define getopt sgetoptmine #define optarg subgetoptarg #define optind subgetoptind #define optpos subgetoptpos #define opterr sgetopterr #define optproblem subgetoptproblem #define optprogname sgetoptprogname #define opteof subgetoptdone #endif #include "subgetopt.h" extern int sgetoptmine(int,char *const *,const char *); extern int sgetopterr; extern const char *sgetoptprogname; #endif admin/runit-2.2.0/src/hasshsgr.h20000644000000000000000000000012014675400254015306 0ustar rootroot/* Public domain. */ /* sysdep: +shortsetgroups */ #define HASSHORTSETGROUPS 1 admin/runit-2.2.0/src/buffer_0.c0000644000000000000000000000052114675400254015072 0ustar rootroot/* Public domain. */ #include "buffer.h" int buffer_0_read(fd,buf,len) int fd; char *buf; int len; { if (buffer_flush(buffer_1) == -1) return -1; return buffer_unixread(fd,buf,len); } char buffer_0_space[BUFFER_INSIZE]; static buffer it = BUFFER_INIT(buffer_0_read,0,buffer_0_space,sizeof buffer_0_space); buffer *buffer_0 = ⁢ admin/runit-2.2.0/src/str_chr.c0000644000000000000000000000057214675400254015054 0ustar rootroot/* Public domain. */ #include "str.h" unsigned int str_chr(register const char *s,int c) { register char ch; register const char *t; ch = c; t = s; for (;;) { if (!*t) break; if (*t == ch) break; ++t; if (!*t) break; if (*t == ch) break; ++t; if (!*t) break; if (*t == ch) break; ++t; if (!*t) break; if (*t == ch) break; ++t; } return t - s; } admin/runit-2.2.0/src/taia_add.c0000644000000000000000000000063114675400254015132 0ustar rootroot/* Public domain. */ #include "taia.h" /* XXX: breaks tai encapsulation */ void taia_add(struct taia *t,const struct taia *u,const struct taia *v) { t->sec.x = u->sec.x + v->sec.x; t->nano = u->nano + v->nano; t->atto = u->atto + v->atto; if (t->atto > 999999999UL) { t->atto -= 1000000000UL; ++t->nano; } if (t->nano > 999999999UL) { t->nano -= 1000000000UL; ++t->sec.x; } } admin/runit-2.2.0/src/runit-init.c0000644000000000000000000000355014675400254015511 0ustar rootroot#include #include #include #include #include "runit.h" #include "strerr.h" #include "sig.h" #include "open.h" #include "error.h" #define USAGE " 0|6" #define FATAL "init: fatal: " /* #define WARNING "init: warning: " */ const char *progname; void usage(void) { strerr_die4x(0, "usage: ", progname, USAGE, "\n"); } void runit_halt () { if (open_trunc(STOPIT) == -1) strerr_die4sys(111, FATAL, "unable to create ", STOPIT, ": "); if (chmod(STOPIT, 0100) == -1) strerr_die4sys(111, FATAL, "unable to chmod ", STOPIT, ": "); if (chmod(REBOOT, 0) == -1) if (errno != error_noent) strerr_die4sys(111, FATAL, "unable to chmod ", REBOOT, ": "); kill(1, sig_cont); _exit(0); } void runit_reboot () { if (open_trunc(STOPIT) == -1) strerr_die4sys(111, FATAL, "unable to create ", STOPIT, ": "); if (chmod(STOPIT, 0100) == -1) strerr_die4sys(111, FATAL, "unable to chmod ", STOPIT, ": "); if (open_trunc(REBOOT) == -1) strerr_die4sys(111, FATAL, "unable to create ", REBOOT, ": "); if (chmod(REBOOT, 0100) == -1) strerr_die4sys(111, FATAL, "unable to chmod ", REBOOT, ": "); kill(1, sig_cont); _exit(0); } int main (int argc, const char * const *argv, char * const *envp) { const char *prog[2]; progname =*argv++; if (getpid() == 1) { prog[1] =0; prog[0] ="runit"; /* kernel is starting init, runit does the job. */ execve(RUNIT, (char *const *)prog, envp); /* serious error */ strerr_die4sys(111, FATAL, "unable to start ", prog[0], ": "); } if (! *argv || ! **argv) usage(); switch (**argv) { case '0': runit_halt(); break; case '6': runit_reboot(); break; case '-': if ((*argv)[1] == 'V') strerr_warn1("$Id: f075d98bf7dd17c893021f9572cbb970cdad8dcf $\n", 0); default: usage(); } /* not reached */ _exit(0); } admin/runit-2.2.0/src/sv.dist0000644000000000000000000000024614675400254014557 0ustar rootrootusage: sv [-v] [-w sec] command service ... 100 $Id: bccdf71babe2596029c67cd0f6cec89bd05844a2 $ usage: sv [-v] [-w sec] command service ... 100 starting 0 down 0 0 admin/runit-2.2.0/src/trycpp.c0000644000000000000000000000024114675400254014722 0ustar rootroot/* Public domain. */ #include #include int main() { #ifdef NeXT printf("nextstep\n"); exit(0); #endif printf("unknown\n"); exit(0); } admin/runit-2.2.0/src/buffer_put.c0000644000000000000000000000341514675400254015550 0ustar rootroot/* Public domain. */ #include "buffer.h" #include "str.h" #include "byte.h" #include "error.h" static int allwrite(int (*op)(),int fd,const char *buf,unsigned int len) { int w; while (len) { w = op(fd,buf,len); if (w == -1) { if (errno == error_intr) continue; return -1; /* note that some data may have been written */ } if (w == 0) ; /* luser's fault */ buf += w; len -= w; } return 0; } int buffer_flush(buffer *s) { int p; p = s->p; if (!p) return 0; s->p = 0; return allwrite(s->op,s->fd,s->x,p); } int buffer_putalign(buffer *s,const char *buf,unsigned int len) { unsigned int n; while (len > (n = s->n - s->p)) { byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n; if (buffer_flush(s) == -1) return -1; } /* now len <= s->n - s->p */ byte_copy(s->x + s->p,len,buf); s->p += len; return 0; } int buffer_put(buffer *s,const char *buf,unsigned int len) { unsigned int n; n = s->n; if (len > n - s->p) { if (buffer_flush(s) == -1) return -1; /* now s->p == 0 */ if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE; while (len > s->n) { if (n > len) n = len; if (allwrite(s->op,s->fd,buf,n) == -1) return -1; buf += n; len -= n; } } /* now len <= s->n - s->p */ byte_copy(s->x + s->p,len,buf); s->p += len; return 0; } int buffer_putflush(buffer *s,const char *buf,unsigned int len) { if (buffer_flush(s) == -1) return -1; return allwrite(s->op,s->fd,buf,len); } int buffer_putsalign(buffer *s,const char *buf) { return buffer_putalign(s,buf,str_len(buf)); } int buffer_puts(buffer *s,const char *buf) { return buffer_put(s,buf,str_len(buf)); } int buffer_putsflush(buffer *s,const char *buf) { return buffer_putflush(s,buf,str_len(buf)); } admin/runit-2.2.0/src/hasflock.h10000644000000000000000000000005314675400254015262 0ustar rootroot/* Public domain. */ /* sysdep: -flock */ admin/runit-2.2.0/src/alloc.c0000644000000000000000000000150014675400254014472 0ustar rootroot/* Public domain. */ #include #include "alloc.h" #include "error.h" #define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */ #define SPACE 2048 /* must be multiple of ALIGNMENT */ typedef union { char irrelevant[ALIGNMENT]; double d; } aligned; static aligned realspace[SPACE / ALIGNMENT]; #define space ((char *) realspace) static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */ /*@null@*//*@out@*/char *alloc(n) unsigned int n; { char *x; n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ if (n <= avail) { avail -= n; return space + avail; } x = malloc(n); if (!x) errno = error_nomem; return x; } void alloc_free(x) char *x; { if (x >= space) if (x < space + SPACE) return; /* XXX: assuming that pointers are flat */ free(x); } admin/runit-2.2.0/src/tryuwtmp.c0000644000000000000000000000016214675400254015316 0ustar rootroot#include #include struct utmp ut; int main(void) { char *s =ut.ut_name; return(0); } admin/runit-2.2.0/src/byte_cr.c0000644000000000000000000000053214675400254015033 0ustar rootroot/* Public domain. */ #include "byte.h" void byte_copyr(to,n,from) register char *to; register unsigned int n; register char *from; { to += n; from += n; for (;;) { if (!n) return; *--to = *--from; --n; if (!n) return; *--to = *--from; --n; if (!n) return; *--to = *--from; --n; if (!n) return; *--to = *--from; --n; } } admin/runit-2.2.0/src/alloc.h0000644000000000000000000000023114675400254014477 0ustar rootroot/* Public domain. */ #ifndef ALLOC_H #define ALLOC_H extern /*@null@*//*@out@*/char *alloc(); extern void alloc_free(); extern int alloc_re(); #endif admin/runit-2.2.0/src/print-ld.sh0000644000000000000000000000021314675400254015321 0ustar rootrootld="`head -n1 conf-ld`" systype="`cat systype`" cat warn-auto.sh echo 'main="$1"; shift' echo exec "$ld" '-o "$main" "$main".o ${1+"$@"}' admin/runit-2.2.0/src/pathexec_env.c0000644000000000000000000000266114675400254016062 0ustar rootroot/* Public domain. */ #include "stralloc.h" #include "alloc.h" #include "str.h" #include "byte.h" #include "env.h" #include "pathexec.h" static stralloc plus; static stralloc tmp; int pathexec_env(const char *s,const char *t) { if (!s) return 1; if (!stralloc_copys(&tmp,s)) return 0; if (t) { if (!stralloc_cats(&tmp,"=")) return 0; if (!stralloc_cats(&tmp,t)) return 0; } if (!stralloc_0(&tmp)) return 0; return stralloc_cat(&plus,&tmp); } void pathexec_env_run(const char *file, char *const *argv) { char **e; unsigned int elen; unsigned int i; unsigned int j; unsigned int split; unsigned int t; if (!stralloc_cats(&plus,"")) return; elen = 0; for (i = 0;environ[i];++i) ++elen; for (i = 0;i < plus.len;++i) if (!plus.s[i]) ++elen; e = (char **) alloc((elen + 1) * sizeof(char *)); if (!e) return; elen = 0; for (i = 0;environ[i];++i) e[elen++] = environ[i]; j = 0; for (i = 0;i < plus.len;++i) if (!plus.s[i]) { split = str_chr(plus.s + j,'='); for (t = 0;t < elen;++t) if (byte_equal(plus.s + j,split,e[t])) if (e[t][split] == '=') { --elen; e[t] = e[elen]; break; } if (plus.s[j + split]) e[elen++] = plus.s + j; j = i + 1; } e[elen] = 0; pathexec_run(file,argv,e); alloc_free(e); } void pathexec(char *const *argv) { return pathexec_env_run(*argv, argv); } admin/runit-2.2.0/src/fmt_uint0.c0000644000000000000000000000036114675400254015311 0ustar rootroot/* Public domain. */ #include "fmt.h" unsigned int fmt_uint0(char *s,unsigned int u,unsigned int n) { unsigned int len; len = fmt_uint(FMT_LEN,u); while (len < n) { if (s) *s++ = '0'; ++len; } if (s) fmt_uint(s,u); return len; } admin/runit-2.2.0/src/print-cc.sh0000644000000000000000000000014114675400254015307 0ustar rootrootcc="`head -n1 conf-cc`" systype="`cat systype`" cat warn-auto.sh echo exec "$cc" '-c ${1+"$@"}' admin/runit-2.2.0/src/hasmkffo.h10000644000000000000000000000005414675400254015267 0ustar rootroot/* Public domain. */ /* sysdep: -mkfifo */ admin/runit-2.2.0/src/tai_pack.c0000644000000000000000000000047114675400254015161 0ustar rootroot/* Public domain. */ #include "tai.h" void tai_pack(char *s,const struct tai *t) { uint64 x; x = t->x; s[7] = x & 255; x >>= 8; s[6] = x & 255; x >>= 8; s[5] = x & 255; x >>= 8; s[4] = x & 255; x >>= 8; s[3] = x & 255; x >>= 8; s[2] = x & 255; x >>= 8; s[1] = x & 255; x >>= 8; s[0] = x; } admin/runit-2.2.0/src/byte_diff.c0000644000000000000000000000073314675400254015342 0ustar rootroot/* Public domain. */ #include "byte.h" int byte_diff(s,n,t) register char *s; register unsigned int n; register char *t; { for (;;) { if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; } return ((int)(unsigned int)(unsigned char) *s) - ((int)(unsigned int)(unsigned char) *t); } admin/runit-2.2.0/src/pathexec_run.c0000644000000000000000000000203014675400254016064 0ustar rootroot/* Public domain. */ #include #include "error.h" #include "stralloc.h" #include "str.h" #include "env.h" #include "pathexec.h" static stralloc tmp; void pathexec_run(const char *file,char * const *argv,char * const *envp) { const char *path; unsigned int split; int savederrno; if (file[str_chr(file,'/')]) { execve(file,argv,envp); return; } path = env_get("PATH"); if (!path) path = "/bin:/usr/bin"; savederrno = 0; for (;;) { split = str_chr(path,':'); if (!stralloc_copyb(&tmp,path,split)) return; if (!split) if (!stralloc_cats(&tmp,".")) return; if (!stralloc_cats(&tmp,"/")) return; if (!stralloc_cats(&tmp,file)) return; if (!stralloc_0(&tmp)) return; execve(tmp.s,argv,envp); if (errno != error_noent) { savederrno = errno; if ((errno != error_acces) && (errno != error_perm) && (errno != error_isdir)) return; } if (!path[split]) { if (savederrno) errno = savederrno; return; } path += split; path += 1; } } admin/runit-2.2.0/src/gen_allocdefs.h0000644000000000000000000000227414675400254016203 0ustar rootroot/* Public domain. */ #ifndef GEN_ALLOC_DEFS_H #define GEN_ALLOC_DEFS_H #define GEN_ALLOC_ready(ta,type,field,len,a,i,n,x,base,ta_ready) \ int ta_ready(register ta *x,register unsigned int n) \ { register unsigned int i; \ if (x->field) { \ i = x->a; \ if (n > i) { \ x->a = base + n + (n >> 3); \ if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ x->a = i; return 0; } \ return 1; } \ x->len = 0; \ return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } #define GEN_ALLOC_readyplus(ta,type,field,len,a,i,n,x,base,ta_rplus) \ int ta_rplus(register ta *x,register unsigned int n) \ { register unsigned int i; \ if (x->field) { \ i = x->a; n += x->len; \ if (n > i) { \ x->a = base + n + (n >> 3); \ if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ x->a = i; return 0; } \ return 1; } \ x->len = 0; \ return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } #define GEN_ALLOC_append(ta,type,field,len,a,i,n,x,base,ta_rplus,ta_append) \ int ta_append(register ta *x,register const type *i) \ { if (!ta_rplus(x,1)) return 0; x->field[x->len++] = *i; return 1; } #endif admin/runit-2.2.0/src/select.h10000644000000000000000000000023514675400254014751 0ustar rootroot/* Public domain. */ #ifndef SELECT_H #define SELECT_H /* sysdep: -sysselect */ #include #include extern int select(); #endif admin/runit-2.2.0/src/svlogd.c0000644000000000000000000005773114675400254014717 0ustar rootroot#include #include #include #include #include #include #include #include #include #include #include "pmatch.h" #include "fmt_ptime.h" #include "alloc.h" #include "stralloc.h" #include "strerr.h" #include "buffer.h" #include "sig.h" #include "env.h" #include "fd.h" #include "wait.h" #include "error.h" #include "sgetopt.h" #include "open.h" #include "openreadclose.h" #include "coe.h" #include "lock.h" #include "str.h" #include "byte.h" #include "scan.h" #include "direntry.h" #include "taia.h" #include "fmt.h" #include "ndelay.h" #include "iopause.h" #define USAGE " [-ttv] [-r c] [-R abc] [-l len] [-b buflen] dir ..." #define VERSION "$Id: 66d40067fb843ee6cde160e47c9dee5c73986f6d $" #define FATAL "svlogd: fatal: " #define WARNING "svlogd: warning: " #define PAUSE "svlogd: pausing: " #define INFO "svlogd: info: " const char *progname; unsigned int verbose =0; unsigned int timestamp =0; unsigned long linemax =1000; unsigned long buflen =1024; unsigned long linelen; const char *replace =""; char repl =0; char **fndir; int fdwdir; struct stat st; stralloc sa; int wstat; struct taia now; struct taia trotate; char *databuf; buffer data; char *line; char stamp[FMT_PTIME]; unsigned int exitasap =0; unsigned int rotateasap =0; unsigned int reopenasap =0; unsigned int linecomplete =1; unsigned int tmaxflag =0; int fdudp =-1; iopause_fd in; struct logdir { int fddir; char *btmp; buffer b; stralloc inst; unsigned long size; unsigned long sizemax; unsigned long nmax; unsigned long nmin; unsigned long tmax; struct taia trotate; stralloc processor; int ppid; char fnsave[FMT_PTIME]; char *name; int fdcur; int fdlock; char match; char matcherr; struct sockaddr_in udpaddr; unsigned int udponly; stralloc prefix; } *dir; unsigned int dirn =0; void usage() { strerr_die4x(111, "usage: ", progname, USAGE, "\n"); } void die_nomem() { strerr_die2x(111, FATAL, "out of memory."); } void fatal(char *m0) { strerr_die3sys(111, FATAL, m0, ": "); } void fatalx(char *m0) { strerr_die2x(111, FATAL, m0); } void fatal2(char *m0, char *m1) { strerr_die5sys(111, FATAL, m0, ": ", m1, ": "); } void warn(char *m0) { strerr_warn3(WARNING, m0, ": ", &strerr_sys); } void warn2(char *m0, char *m1) { strerr_warn5(WARNING, m0, ": ", m1, ": ", &strerr_sys); } void warnx(char *m0, char *m1) { strerr_warn4(WARNING, m0, ": ", m1, 0); } void pause_nomem() { strerr_warn2(PAUSE, "out of memory.", 0); sleep(3); } void pause1(char *m0) { strerr_warn3(PAUSE, m0, ": ", &strerr_sys); sleep(3); } void pause2(char *m0, char *m1) { strerr_warn5(PAUSE, m0, ": ", m1, ": ", &strerr_sys); sleep(3); } unsigned int processorstart(struct logdir *ld) { int pid; if (! ld->processor.len) return(0); if (ld->ppid) { warnx("processor already running", ld->name); return(0); } while ((pid =fork()) == -1) pause2("unable to fork for processor", ld->name); if (! pid) { char *prog[4]; int fd; /* child */ sig_uncatch(sig_term); sig_uncatch(sig_alarm); sig_uncatch(sig_hangup); sig_unblock(sig_term); sig_unblock(sig_alarm); sig_unblock(sig_hangup); if (verbose) strerr_warn5(INFO, "processing: ", ld->name, "/", ld->fnsave, 0); if ((fd =open_read(ld->fnsave)) == -1) fatal2("unable to open input for processor", ld->name); if (fd_move(0, fd) == -1) fatal2("unable to move filedescriptor for processor", ld->name); ld->fnsave[26] ='t'; if ((fd =open_trunc(ld->fnsave)) == -1) fatal2("unable to open output for processor", ld->name); if (fd_move(1, fd) == -1) fatal2("unable to move filedescriptor for processor", ld->name); if ((fd =open_read("state")) == -1) { if (errno == error_noent) { if ((fd =open_trunc("state")) == -1) fatal2("unable to create empty state for processor", ld->name); close(fd); if ((fd =open_read("state")) == -1) fatal2("unable to open state for processor", ld->name); } else fatal2("unable to open state for processor", ld->name); } if (fd_move(4, fd) == -1) fatal2("unable to move filedescriptor for processor", ld->name); if ((fd =open_trunc("newstate")) == -1) fatal2("unable to open newstate for processor", ld->name); if (fd_move(5, fd) == -1) fatal2("unable to move filedescriptor for processor", ld->name); prog[0] = "sh"; prog[1] = "-c"; prog[2] = ld->processor.s; prog[3] = 0; execve("/bin/sh", prog, environ); fatal2("unable to run processor", ld->name); } ld->ppid =pid; return(1); } unsigned int processorstop(struct logdir *ld) { char f[28]; if (ld->ppid) { sig_unblock(sig_hangup); while (wait_pid(&wstat, ld->ppid) == -1) pause2("error waiting for processor", ld->name); sig_block(sig_hangup); ld->ppid =0; } if (ld->fddir == -1) return(1); while (fchdir(ld->fddir) == -1) pause2("unable to change directory, want processor", ld->name); if (wait_exitcode(wstat) != 0) { warnx("processor failed, restart", ld->name); ld->fnsave[26] ='t'; unlink(ld->fnsave); ld->fnsave[26] ='u'; processorstart(ld); while (fchdir(fdwdir) == -1) pause1("unable to change to initial working directory"); return(ld->processor.len ? 0 : 1); } ld->fnsave[26] ='t'; byte_copy(f, 26, ld->fnsave); f[26] ='s'; f[27] =0; while (rename(ld->fnsave, f) == -1) pause2("unable to rename processed", ld->name); while (chmod(f, 0744) == -1) pause2("unable to set mode of processed", ld->name); ld->fnsave[26] ='u'; if (unlink(ld->fnsave) == -1) strerr_warn5(WARNING, "unable to unlink: ", ld->name, "/", ld->fnsave, 0); while (rename("newstate", "state") == -1) pause2("unable to rename state", ld->name); if (verbose) strerr_warn5(INFO, "processed: ", ld->name, "/", f, 0); while (fchdir(fdwdir) == -1) pause1("unable to change to initial working directory"); return(1); } void rmoldest(struct logdir *ld) { DIR *d; direntry *f; char oldest[FMT_PTIME]; int n =0; oldest[0] ='A'; oldest[1] =oldest[27] =0; while (! (d =opendir("."))) pause2("unable to open directory, want rotate", ld->name); errno =0; while ((f =readdir(d))) if ((f->d_name[0] == '@') && (str_len(f->d_name) == 27)) { if (f->d_name[26] == 't') { if (unlink(f->d_name) == -1) warn2("unable to unlink processor leftover", f->d_name); } else { ++n; if (str_diff(f->d_name, oldest) < 0) byte_copy(oldest, 27, f->d_name); } errno =0; } if (errno) warn2("unable to read directory", ld->name); closedir(d); if (ld->nmax && (n > ld->nmax)) { if (verbose) strerr_warn5(INFO, "delete: ", ld->name, "/", oldest, 0); if ((*oldest == '@') && (unlink(oldest) == -1)) warn2("unable to unlink oldest logfile", ld->name); } } unsigned int rotate(struct logdir *ld) { char tmp[FMT_ULONG +1]; if (ld->fddir == -1) { ld->tmax =0; return(0); } if (ld->ppid) while(! processorstop(ld)); while (fchdir(ld->fddir) == -1) pause2("unable to change directory, want rotate", ld->name); /* create new filename */ ld->fnsave[25] ='.'; if (ld->processor.len) ld->fnsave[26] ='u'; else ld->fnsave[26] ='s'; ld->fnsave[27] =0; do { taia_now(&now); fmt_taia(ld->fnsave, &now); errno =0; } while ((stat(ld->fnsave, &st) != -1) || (errno != error_noent)); if (ld->tmax && taia_less(&ld->trotate, &now)) { taia_uint(&ld->trotate, ld->tmax); taia_add(&ld->trotate, &now, &ld->trotate); if (taia_less(&ld->trotate, &trotate)) trotate =ld->trotate; } if (ld->size > 0) { buffer_flush(&ld->b); while (fsync(ld->fdcur) == -1) pause2("unable to fsync current logfile", ld->name); while (fchmod(ld->fdcur, 0744) == -1) pause2("unable to set mode of current", ld->name); close(ld->fdcur); if (verbose) { tmp[0] =' '; tmp[fmt_ulong(tmp +1, ld->size) +1] =0; strerr_warn6(INFO, "rename: ", ld->name, "/current ", ld->fnsave, tmp, 0); } while (rename("current", ld->fnsave) == -1) pause2("unable to rename current", ld->name); while ((ld->fdcur =open_append("current")) == -1) pause2("unable to create new current", ld->name); coe(ld->fdcur); ld->size =0; while (fchmod(ld->fdcur, 0644) == -1) pause2("unable to set mode of current", ld->name); rmoldest(ld); processorstart(ld); } while (fchdir(fdwdir) == -1) pause1("unable to change to initial working directory"); return(1); } int buffer_pwrite(int n, char *s, unsigned int len) { int i; if ((dir +n)->sizemax) { if ((dir +n)->size >= (dir +n)->sizemax) rotate(dir +n); if (len > ((dir +n)->sizemax -(dir +n)->size)) len =(dir +n)->sizemax -(dir +n)->size; } while ((i =write((dir +n)->fdcur, s, len)) == -1) { if ((errno == ENOSPC) && ((dir +n)->nmin < (dir +n)->nmax)) { DIR *d; direntry *f; char oldest[FMT_PTIME]; int j =0; while (fchdir((dir +n)->fddir) == -1) pause2("unable to change directory, want remove old logfile", (dir +n)->name); oldest[0] ='A'; oldest[1] =oldest[27] =0; while (! (d =opendir("."))) pause2("unable to open directory, want remove old logfile", (dir +n)->name); errno =0; while ((f =readdir(d))) if ((f->d_name[0] == '@') && (str_len(f->d_name) == 27)) { ++j; if (str_diff(f->d_name, oldest) < 0) byte_copy(oldest, 27, f->d_name); } if (errno) warn2("unable to read directory, want remove old logfile", (dir +n)->name); closedir(d); errno =ENOSPC; if (j > (dir +n)->nmin) if (*oldest == '@') { strerr_warn5(WARNING, "out of disk space, delete: ", (dir +n)->name, "/", oldest, 0); errno =0; if (unlink(oldest) == -1) { warn2("unable to unlink oldest logfile", (dir +n)->name); errno =ENOSPC; } while (fchdir(fdwdir) == -1) pause1("unable to change to initial working directory"); } } if (errno) pause2("unable to write to current", (dir +n)->name); } (dir +n)->size +=i; if ((dir +n)->sizemax) if (s[i -1] == '\n') if ((dir +n)->size >= ((dir +n)->sizemax -linemax)) rotate(dir +n); return(i); } void logdir_close(struct logdir *ld) { if (ld->fddir == -1) return; if (verbose) strerr_warn3(INFO, "close: ", ld->name, 0); close(ld->fddir); ld->fddir =-1; if (ld->fdcur == -1) return; /* impossible */ buffer_flush(&ld->b); while (fsync(ld->fdcur) == -1) pause2("unable to fsync current logfile", ld->name); while (fchmod(ld->fdcur, 0744) == -1) pause2("unable to set mode of current", ld->name); close(ld->fdcur); ld->fdcur =-1; if (ld->fdlock == -1) return; /* impossible */ close(ld->fdlock); ld->fdlock =-1; while (! stralloc_copys(&ld->processor, "")) pause_nomem(); } /* taken from libdjbdns */ unsigned int ip4_scan(const char *s,char ip[4]) { unsigned int i; unsigned int len; unsigned long u; len = 0; i = scan_ulong(s,&u); if (!i) return 0; ip[0] = u; s += i; len += i; if (*s != '.') return 0; ++s; ++len; i = scan_ulong(s,&u); if (!i) return 0; ip[1] = u; s += i; len += i; if (*s != '.') return 0; ++s; ++len; i = scan_ulong(s,&u); if (!i) return 0; ip[2] = u; s += i; len += i; if (*s != '.') return 0; ++s; ++len; i = scan_ulong(s,&u); if (!i) return 0; ip[3] = u; s += i; len += i; return len; } unsigned int logdir_open(struct logdir *ld, const char *fn) { int i; if ((ld->fddir =open_read(fn)) == -1) { warn2("unable to open log directory", (char*)fn); return(0); } coe(ld->fddir); if (fchdir(ld->fddir) == -1) { logdir_close(ld); warn2("unable to change directory", (char*)fn); return(0); } ld->fdlock =open_append("lock"); if ((ld->fdlock == -1) || (lock_exnb(ld->fdlock) == -1)) { logdir_close(ld); warn2("unable to lock directory", (char*)fn); while (fchdir(fdwdir) == -1) pause1("unable to change to initial working directory"); return(0); } coe(ld->fdlock); ld->size =0; ld->sizemax =1000000; ld->nmax =ld->nmin =10; ld->tmax =0; ld->name =(char*)fn; ld->ppid =0; ld->match ='+'; ld->udpaddr.sin_family =AF_INET; ld->udpaddr.sin_port =0; ld->udponly =0; while (! stralloc_copys(&ld->prefix, "")) pause_nomem(); while (! stralloc_copys(&ld->inst, "")) pause_nomem(); while (! stralloc_copys(&ld->processor, "")) pause_nomem(); /* read config */ if ((i =openreadclose("config", &sa, 128)) == -1) warn2("unable to read config", ld->name); if (i != 0) { int len, c; unsigned long port; if (verbose) strerr_warn4(INFO, "read: ", ld->name, "/config", 0); for (i =0; i +1 < sa.len; ++i) { len =byte_chr(&sa.s[i], sa.len -i, '\n'); sa.s[len +i] =0; switch(sa.s[i]) { case '\n': case '#': break; case '+': case '-': case 'e': case 'E': while (! stralloc_catb(&ld->inst, &sa.s[i], len)) pause_nomem(); while (! stralloc_0(&ld->inst)) pause_nomem(); break; case 's': switch (sa.s[scan_ulong(&sa.s[i +1], &ld->sizemax) +i +1]) { case 'm': ld->sizemax *=1024; case 'k': ld->sizemax *=1024; } break; case 'n': scan_ulong(&sa.s[i +1], &ld->nmax); break; case 'N': scan_ulong(&sa.s[i +1], &ld->nmin); break; case 't': switch (sa.s[scan_ulong(&sa.s[i +1], &ld->tmax) +i +1]) { /* case 'd': ld->tmax *=24; */ case 'h': ld->tmax *=60; case 'm': ld->tmax *=60; } if (ld->tmax) { taia_uint(&ld->trotate, ld->tmax); taia_add(&ld->trotate, &now, &ld->trotate); if (! tmaxflag || taia_less(&ld->trotate, &trotate)) trotate =ld->trotate; tmaxflag =1; } break; case '!': if (len > 1) { while (! stralloc_copys(&ld->processor, &sa.s[i +1])) pause_nomem(); while (! stralloc_0(&ld->processor)) pause_nomem(); } break; case 'U': ld->udponly =1; case 'u': if (! (c =ip4_scan(sa.s +i +1, (char *)&ld->udpaddr.sin_addr))) { warnx("unable to scan ip address", sa.s +i +1); break; } if (sa.s[i +1 +c] == ':') { scan_ulong(sa.s +i +c +2, &port); if (port == 0) { warnx("unable to scan port number", sa.s +i +c +2); break; } } else port =514; ld->udpaddr.sin_port =htons(port); break; case 'p': if (len > 1) { while (! stralloc_copys(&ld->prefix, &sa.s[i +1])) pause_nomem(); while (! stralloc_0(&ld->prefix)) pause_nomem(); } break; } i +=len; } } /* open current */ if ((i =stat("current", &st)) != -1) { if (st.st_size && ! (st.st_mode & S_IXUSR)) { ld->fnsave[25] ='.'; ld->fnsave[26] ='u'; ld->fnsave[27] =0; do { taia_now(&now); fmt_taia(ld->fnsave, &now); errno =0; } while ((stat(ld->fnsave, &st) != -1) || (errno != error_noent)); while (rename("current", ld->fnsave) == -1) pause2("unable to rename current", ld->name); rmoldest(ld); i =-1; } else ld->size =st.st_size; } else if (errno != error_noent) { logdir_close(ld); warn2("unable to stat current", ld->name); while (fchdir(fdwdir) == -1) pause1("unable to change to initial working directory"); return(0); } while ((ld->fdcur =open_append("current")) == -1) pause2("unable to open current", ld->name); coe(ld->fdcur); while (fchmod(ld->fdcur, 0644) == -1) pause2("unable to set mode of current", ld->name); buffer_init(&ld->b, buffer_pwrite, ld -dir, ld->btmp, buflen); if (verbose) { if (i == 0) strerr_warn4(INFO, "append: ", ld->name, "/current", 0); else strerr_warn4(INFO, "new: ", ld->name, "/current", 0); } while (fchdir(fdwdir) == -1) pause1("unable to change to initial working directory"); return(1); } void logdirs_reopen(void) { int l; int ok =0; tmaxflag =0; taia_now(&now); for (l =0; l < dirn; ++l) { logdir_close(&dir[l]); if (logdir_open(&dir[l], fndir[l])) ok =1; } if (! ok) fatalx("no functional log directories."); } int buffer_pread(int fd, char *s, unsigned int len) { int i; for (i =0; i < dirn; ++i) buffer_flush(&dir[i].b); if (rotateasap) { for (i =0; i < dirn; ++i) rotate(dir +i); rotateasap =0; } if (exitasap) { if (linecomplete) return(0); len =1; } if (reopenasap) { logdirs_reopen(); reopenasap =0; } taia_now(&now); taia_uint(&trotate, 2744); taia_add(&trotate, &now, &trotate); for (i =0; i < dirn; ++i) if ((dir +i)->tmax) { if (taia_less(&dir[i].trotate, &now)) rotate(dir +i); if (taia_less(&dir[i].trotate, &trotate)) trotate =dir[i].trotate; } sig_unblock(sig_term); sig_unblock(sig_child); sig_unblock(sig_alarm); sig_unblock(sig_hangup); iopause(&in, 1, &trotate, &now); sig_block(sig_term); sig_block(sig_child); sig_block(sig_alarm); sig_block(sig_hangup); i =read(fd, s, len); if (i == -1) { if (errno == error_again) errno =error_intr; if (errno != error_intr) warn("unable to read standard input"); } if (i > 0) linecomplete =(s[i -1] == '\n'); return(i); } void sig_term_handler(void) { if (verbose) strerr_warn2(INFO, "sigterm received.", 0); exitasap =1; } void sig_child_handler(void) { int pid, l; if (verbose) strerr_warn2(INFO, "sigchild received.", 0); while ((pid =wait_nohang(&wstat)) > 0) for (l =0; l < dirn; ++l) if (dir[l].ppid == pid) { dir[l].ppid =0; processorstop(&dir[l]); break; } } void sig_alarm_handler(void) { if (verbose) strerr_warn2(INFO, "sigalarm received.", 0); rotateasap =1; } void sig_hangup_handler(void) { if (verbose) strerr_warn2(INFO, "sighangup received.", 0); reopenasap =1; } void logmatch(struct logdir *ld) { int i; ld->match ='+'; ld->matcherr ='E'; for (i =0; i < ld->inst.len; ++i) { switch(ld->inst.s[i]) { case '+': case '-': if (pmatch(&ld->inst.s[i +1], line, linelen)) ld->match =ld->inst.s[i]; break; case 'e': case 'E': if (pmatch(&ld->inst.s[i +1], line, linelen)) ld->matcherr =ld->inst.s[i]; break; } i +=byte_chr(&ld->inst.s[i], ld->inst.len -i, 0); } } int main(int argc, char **argv) { int i; int opt; progname =*argv; while ((opt =getopt(argc, argv, "R:r:l:b:tvV")) != opteof) { switch(opt) { case 'R': replace =optarg; if (! repl) repl ='_'; break; case 'r': repl =*optarg; if (! repl || *(optarg +1)) usage(); break; case 'l': scan_ulong(optarg, &linemax); if (linemax == 0) linemax =1000; break; case 'b': scan_ulong(optarg, &buflen); if (buflen == 0) buflen =1024; break; case 't': if (++timestamp > 3) timestamp =3; break; case 'v': ++verbose; break; case 'V': strerr_warn1(VERSION, 0); case '?': usage(); } } argv +=optind; dirn =argc -optind; if (dirn <= 0) usage(); if (buflen <= linemax) usage(); if ((fdwdir =open_read(".")) == -1) fatal("unable to open current working directory"); coe(fdwdir); dir =(struct logdir*)alloc(dirn *sizeof(struct logdir)); if (! dir) die_nomem(); for (i =0; i < dirn; ++i) { dir[i].fddir =-1; dir[i].fdcur =-1; dir[i].btmp =(char*)alloc(buflen *sizeof(char)); if (! dir[i].btmp) die_nomem(); dir[i].ppid =0; } databuf =(char*)alloc(buflen *sizeof(char)); if (! databuf) die_nomem(); buffer_init(&data, buffer_pread, 0, databuf, buflen); line =(char*)alloc(linemax *sizeof(char)); if (! line) die_nomem(); fndir =argv; in.fd =0; in.events =IOPAUSE_READ; ndelay_on(in.fd); sig_block(sig_term); sig_block(sig_child); sig_block(sig_alarm); sig_block(sig_hangup); sig_catch(sig_term, sig_term_handler); sig_catch(sig_child, sig_child_handler); sig_catch(sig_alarm, sig_alarm_handler); sig_catch(sig_hangup, sig_hangup_handler); logdirs_reopen(); for(;;) { char ch; linelen =0; for (linelen =0; linelen < linemax; ++linelen) { if (buffer_GETC(&data, &ch) <= 0) { exitasap =1; break; } if (! linelen && timestamp) { taia_now(&now); switch (timestamp) { case 1: fmt_taia(stamp, &now); break; case 2: fmt_ptime(stamp, &now); break; case 3: fmt_ptime_iso8601(stamp, &now); break; } stamp[25] =' '; stamp[26] =0; } if (ch == '\n') break; if (repl) { if ((ch < 32) || (ch > 126)) ch =repl; else for (i =0; replace[i]; ++i) if (ch == replace[i]) { ch =repl; break; } } line[linelen] =ch; } if (exitasap && ! data.p) break; /* data buffer is empty */ for (i =0; i < dirn; ++i) if (dir[i].fddir != -1) { if (dir[i].inst.len) logmatch(&dir[i]); if (dir[i].matcherr == 'e') { if (timestamp) buffer_puts(buffer_2, stamp); if (dir[i].prefix.len) buffer_puts(buffer_2, dir[i].prefix.s); buffer_put(buffer_2, line, linelen); if (linelen == linemax) buffer_puts(buffer_2, "..."); buffer_put(buffer_2, "\n", 1); buffer_flush(buffer_2); } if (dir[i].match != '+') continue; if (dir[i].udpaddr.sin_port != 0) { fdudp =socket(AF_INET, SOCK_DGRAM, 0); if (fdudp) if (ndelay_on(fdudp) == -1) { close(fdudp); fdudp =-1; } if (fdudp == -1) { buffer_puts(&dir[i].b, "warning: no udp socket available: "); if (timestamp) buffer_puts(&dir[i].b, stamp); if (dir[i].prefix.len) buffer_puts(&dir[i].b, dir[i].prefix.s); buffer_put(&dir[i].b, line, linelen); buffer_put(&dir[i].b, "\n", 1); buffer_flush(&dir[i].b); } else { while (! stralloc_copys(&sa, "")) pause_nomem(); if (timestamp) while (! stralloc_cats(&sa, stamp)) pause_nomem(); if (dir[i].prefix.len) while (! stralloc_cats(&sa, dir[i].prefix.s)) pause_nomem(); while (! stralloc_catb(&sa, line, linelen)) pause_nomem(); if (linelen == linemax) while (! stralloc_cats(&sa, "...")) pause_nomem(); while (! stralloc_append(&sa, "\n")) pause_nomem(); if (sendto(fdudp, sa.s, sa.len, 0, (struct sockaddr *)&dir[i].udpaddr, sizeof(dir[i].udpaddr)) != sa.len) { buffer_puts(&dir[i].b, "warning: failure sending through udp: "); buffer_put(&dir[i].b, sa.s, sa.len); buffer_flush(&dir[i].b); } close(fdudp); } } if (! dir[i].udponly) { if (timestamp) buffer_puts(&dir[i].b, stamp); if (dir[i].prefix.len) buffer_puts(&dir[i].b, dir[i].prefix.s); buffer_put(&dir[i].b, line, linelen); } } if (linelen == linemax) for (;;) { if (buffer_GETC(&data, &ch) <= 0) { exitasap =1; break; } if (ch == '\n') break; for (i =0; i < dirn; ++i) if (dir[i].fddir != -1) { if (dir[i].match != '+') continue; if (! dir[i].udponly) buffer_PUTC(&dir[i].b, ch); } } for (i =0; i < dirn; ++i) if (dir[i].fddir != -1) { if (dir[i].match != '+') continue; if (! dir[i].udponly) { ch ='\n'; buffer_PUTC(&dir[i].b, ch); buffer_flush(&dir[i].b); } } } for (i =0; i < dirn; ++i) { if (dir[i].ppid) while (! processorstop(&dir[i])); logdir_close(&dir[i]); } _exit(0); } admin/runit-2.2.0/src/wait_nohang.c0000644000000000000000000000036714675400254015710 0ustar rootroot/* Public domain. */ #include #include #include "haswaitp.h" int wait_nohang(wstat) int *wstat; { #ifdef HASWAITPID return waitpid(-1,wstat,WNOHANG); #else return wait3(wstat,WNOHANG,(struct rusage *) 0); #endif } admin/runit-2.2.0/src/wait.h0000644000000000000000000000047514675400254014363 0ustar rootroot/* Public domain. */ #ifndef WAIT_H #define WAIT_H extern int wait_pid(); extern int wait_nohang(); extern int wait_stop(); extern int wait_stopnohang(); #define wait_crashed(w) ((w) & 127) #define wait_exitcode(w) ((w) >> 8) #define wait_stopsig(w) ((w) >> 8) #define wait_stopped(w) (((w) & 127) == 127) #endif admin/runit-2.2.0/src/buffer_write.c0000644000000000000000000000023514675400254016067 0ustar rootroot/* Public domain. */ #include #include "buffer.h" int buffer_unixwrite(int fd,const char *buf,unsigned int len) { return write(fd,buf,len); } admin/runit-2.2.0/src/svwaitup.c0000644000000000000000000000610314675400254015266 0ustar rootroot#include #include "strerr.h" #include "error.h" #include "sgetopt.h" #include "scan.h" #include "open.h" #include "tai.h" #include "buffer.h" #include "fmt.h" #define FATAL "svwaitup: fatal: " #define WARN "svwaitup: warning: " #define INFO "svwaitup: " #define USAGE " [-v] [-s 1..600] service ..." const char *progname; unsigned long sec =2; unsigned int rc =0; const char * const *dir; void fatal(const char *m) { strerr_die3sys(111, FATAL, m, ": "); } void warn(const char *s1, const char *s2, struct strerr *e) { dir++; rc++; strerr_warn3(WARN, s1, s2, e); } void usage() { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } int main(int argc, const char * const *argv) { int opt; int verbose =0; char status[18]; int fd; int is; int r; int wdir; unsigned long pid; struct tai when; struct tai now; char sulong[FMT_ULONG]; progname =*argv; while ((opt =getopt(argc, argv, "s:vV")) != opteof) { switch(opt) { case 's': scan_ulong(optarg, &sec); if ((sec < 1) || (sec > 600)) usage(); break; case 'v': verbose =1; break; case 'V': strerr_warn1("$Id: e2d6c574c5e56f9931323fbc0e539c7f9b829b73 $", 0); case '?': usage(); } } argv +=optind; if (! argv || ! *argv) usage(); if ((wdir =open_read(".")) == -1) fatal("unable to open current working directory"); dir =argv; while (*dir) { if (dir != argv) if (fchdir(wdir) == -1) fatal("unable to switch to starting directory"); if (chdir(*dir) == -1) { warn(*dir, ": unable to change directory: ", &strerr_sys); continue; } if ((fd =open_write("supervise/ok")) == -1) { if (errno == error_nodevice) warn(*dir, ": runsv not running.", 0); else warn(*dir, ": unable to open supervise/ok: ", &strerr_sys); continue; } close(fd); if ((fd =open_read("supervise/status")) == -1) { warn(*dir, "unable to open supervise/status: ", &strerr_sys); continue; } r =buffer_unixread(fd, status, sizeof status); close(fd); if (r < sizeof status) { if (r == -1) warn(*dir, "unable to read supervise/status: ", &strerr_sys); else warn(*dir, ": unable to read supervise/status: bad format.", 0); continue; } pid =(unsigned char)status[15]; pid <<=8; pid +=(unsigned char)status[14]; pid <<=8; pid +=(unsigned char)status[13]; pid <<=8; pid +=(unsigned char)status[12]; if (! pid) { warn(*dir, ": is down.", 0); continue; } tai_unpack(status, &when); tai_now(&now); if (tai_less(&now, &when)) when =now; tai_sub(&when, &now, &when); is =tai_approx(&when); if (is >= sec) { /* ok */ if (verbose) { sulong[fmt_ulong(sulong, is)] =0; strerr_warn5(INFO, *dir, ": is up (", sulong, " seconds)", 0); } dir++; continue; } sleep(sec -is); } if (fchdir(wdir) == -1) strerr_warn2(WARN, "unable to switch to starting directory: ", &strerr_sys); close(wdir); if (rc > 100) rc =100; _exit(rc); } admin/runit-2.2.0/src/open_read.c0000644000000000000000000000023214675400254015335 0ustar rootroot/* Public domain. */ #include #include #include "open.h" int open_read(const char *fn) { return open(fn,O_RDONLY | O_NDELAY); } admin/runit-2.2.0/src/taia_pack.c0000644000000000000000000000055014675400254015320 0ustar rootroot/* Public domain. */ #include "taia.h" void taia_pack(char *s,const struct taia *t) { unsigned long x; tai_pack(s,&t->sec); s += 8; x = t->atto; s[7] = x & 255; x >>= 8; s[6] = x & 255; x >>= 8; s[5] = x & 255; x >>= 8; s[4] = x; x = t->nano; s[3] = x & 255; x >>= 8; s[2] = x & 255; x >>= 8; s[1] = x & 255; x >>= 8; s[0] = x; } admin/runit-2.2.0/src/fifo.c0000644000000000000000000000043314675400254014327 0ustar rootroot/* Public domain. */ #include #include #include "hasmkffo.h" #include "fifo.h" #ifdef HASMKFIFO int fifo_make(const char *fn,int mode) { return mkfifo(fn,mode); } #else int fifo_make(const char *fn,int mode) { return mknod(fn,S_IFIFO | mode,0); } #endif admin/runit-2.2.0/src/runit.check0000755000000000000000000000003014675400254015374 0ustar rootroot#!/bin/sh runit echo $? admin/runit-2.2.0/src/fmt_ptime.c0000644000000000000000000000213114675400254015365 0ustar rootroot#include #include "fmt_ptime.h" #include "fmt.h" unsigned int fmt_ptime2(char *s, struct taia *ta, char sep) { struct tm *t; time_t u; if (ta->sec.x < 4611686018427387914ULL) return(0); /* impossible? */ u =ta->sec.x -4611686018427387914ULL; if (! (t =gmtime((time_t*)&u))) return(0); fmt_ulong(s, 1900 +t->tm_year); s[4] ='-'; fmt_uint0(&s[5], t->tm_mon +1, 2); s[7] ='-'; fmt_uint0(&s[8], t->tm_mday, 2); s[10] =sep; fmt_uint0(&s[11], t->tm_hour, 2); s[13] =':'; fmt_uint0(&s[14], t->tm_min, 2); s[16] =':'; fmt_uint0(&s[17], t->tm_sec, 2); s[19] ='.'; fmt_uint0(&s[20], ta->nano, 9); return(25); } unsigned int fmt_ptime(char *s, struct taia *ta) { return(fmt_ptime2(s, ta, '_')); } unsigned int fmt_ptime_iso8601(char *s, struct taia *ta) { return(fmt_ptime2(s, ta, 'T')); } unsigned int fmt_taia(char *s, struct taia *t) { static char hex[16] ="0123456789abcdef"; static char pack[TAIA_PACK]; int i; taia_pack(pack, t); s[0] ='@'; for (i =0; i < 12; ++i) { s[i *2 +1] =hex[(pack[i] >>4) &15]; s[i *2 +2] =hex[pack[i] &15]; } return(25); } admin/runit-2.2.0/src/gen_alloc.h0000644000000000000000000000030314675400254015330 0ustar rootroot/* Public domain. */ #ifndef GEN_ALLOC_H #define GEN_ALLOC_H #define GEN_ALLOC_typedef(ta,type,field,len,a) \ typedef struct ta { type *field; unsigned int len; unsigned int a; } ta; #endif admin/runit-2.2.0/src/taia_frac.c0000644000000000000000000000021614675400254015314 0ustar rootroot/* Public domain. */ #include "taia.h" double taia_frac(const struct taia *t) { return (t->atto * 0.000000001 + t->nano) * 0.000000001; } admin/runit-2.2.0/src/buffer.h0000644000000000000000000000315014675400254014661 0ustar rootroot/* Public domain. */ #ifndef BUFFER_H #define BUFFER_H typedef struct buffer { char *x; unsigned int p; unsigned int n; int fd; int (*op)(); } buffer; #define BUFFER_INIT(op,fd,buf,len) { (buf), 0, (len), (fd), (op) } #define BUFFER_INSIZE 8192 #define BUFFER_OUTSIZE 8192 extern void buffer_init(buffer *,int (*)(),int,char *,unsigned int); extern int buffer_flush(buffer *); extern int buffer_put(buffer *,const char *,unsigned int); extern int buffer_putalign(buffer *,const char *,unsigned int); extern int buffer_putflush(buffer *,const char *,unsigned int); extern int buffer_puts(buffer *,const char *); extern int buffer_putsalign(buffer *,const char *); extern int buffer_putsflush(buffer *,const char *); #define buffer_PUTC(s,c) \ ( ((s)->n != (s)->p) \ ? ( (s)->x[(s)->p++] = (c), 0 ) \ : buffer_put((s),&(c),1) \ ) extern int buffer_get(buffer *,char *,unsigned int); extern int buffer_bget(buffer *,char *,unsigned int); extern int buffer_feed(buffer *); extern char *buffer_peek(buffer *); extern void buffer_seek(buffer *,unsigned int); #define buffer_PEEK(s) ( (s)->x + (s)->n ) #define buffer_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) ) #define buffer_GETC(s,c) \ ( ((s)->p > 0) \ ? ( *(c) = (s)->x[(s)->n], buffer_SEEK((s),1), 1 ) \ : buffer_get((s),(c),1) \ ) extern int buffer_copy(buffer *,buffer *); extern int buffer_unixread(int,char *,unsigned int); extern int buffer_unixwrite(int,const char *,unsigned int); extern buffer *buffer_0; extern buffer *buffer_0small; extern buffer *buffer_1; extern buffer *buffer_1small; extern buffer *buffer_2; #endif admin/runit-2.2.0/src/warn-shsgr0000644000000000000000000000031314675400254015253 0ustar rootrootOops. Your getgroups() returned 0, and setgroups() failed; this means that I can't reliably do my shsgr test. Please either ``make'' as root or ``make'' while you're in one or more supplementary groups. admin/runit-2.2.0/src/hasshsgr.h10000644000000000000000000000006414675400254015314 0ustar rootroot/* Public domain. */ /* sysdep: -shortsetgroups */ admin/runit-2.2.0/src/utmpset.dist0000644000000000000000000000015014675400254015622 0ustar rootrootusage: utmpset [-w] line 1 $Id: 6ced914b40d54fdfee353c5b5fdaf297031295e9 $ usage: utmpset [-w] line 1 admin/runit-2.2.0/src/buffer.c0000644000000000000000000000027514675400254014661 0ustar rootroot/* Public domain. */ #include "buffer.h" void buffer_init(buffer *s,int (*op)(),int fd,char *buf,unsigned int len) { s->x = buf; s->fd = fd; s->op = op; s->p = 0; s->n = len; } admin/runit-2.2.0/src/tryflock.c0000644000000000000000000000021614675400254015240 0ustar rootroot/* Public domain. */ #include #include #include int main() { flock(0,LOCK_EX | LOCK_UN | LOCK_NB); } admin/runit-2.2.0/src/lock.h0000644000000000000000000000021214675400254014334 0ustar rootroot/* Public domain. */ #ifndef LOCK_H #define LOCK_H extern int lock_ex(int); extern int lock_un(int); extern int lock_exnb(int); #endif admin/runit-2.2.0/src/runit.h0000644000000000000000000000026014675400254014550 0ustar rootroot#define RUNIT "/sbin/runit" #define STOPIT "/etc/runit/stopit" #define REBOOT "/etc/runit/reboot" #define NOSYNC "/etc/runit/nosync" #define CTRLALTDEL "/etc/runit/ctrlaltdel" admin/runit-2.2.0/src/runit-init.dist0000644000000000000000000000003114675400254016221 0ustar rootrootusage: runit-init 0|6 0 admin/runit-2.2.0/src/warn-auto.sh0000644000000000000000000000010014675400254015500 0ustar rootroot#!/bin/sh # WARNING: This file was auto-generated. Do not edit! admin/runit-2.2.0/src/utmpset.c0000644000000000000000000000537114675400254015113 0ustar rootroot#include #include #include #include #include #include #include "uw_tmp.h" #include "strerr.h" #include "sgetopt.h" #include "seek.h" #include "str.h" #include "open.h" #include "byte.h" #include "lock.h" #define USAGE " [-w] line" #define FATAL "utmpset: fatal: " #define WARNING "utmpset: warning: " const char *progname; void usage(void) { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } int utmp_logout(const char *line) { int fd; uw_tmp ut; time_t t; int ok =-1; if ((fd =open(UW_TMP_UFILE, O_RDWR, 0)) < 0) strerr_die4sys(111, FATAL, "unable to open ", UW_TMP_UFILE, ": "); if (lock_ex(fd) == -1) strerr_die4sys(111, FATAL, "unable to lock: ", UW_TMP_UFILE, ": "); while (read(fd, &ut, sizeof(uw_tmp)) == sizeof(uw_tmp)) { if (!ut.ut_name[0] || (str_diff(ut.ut_line, line) != 0)) continue; memset(ut.ut_name, 0, sizeof ut.ut_name); memset(ut.ut_host, 0, sizeof ut.ut_host); if (time(&t) == -1) break; ut.ut_time = t; #ifdef DEAD_PROCESS ut.ut_type =DEAD_PROCESS; #endif if (lseek(fd, -(off_t)sizeof(uw_tmp), SEEK_CUR) == -1) break; if (write(fd, &ut, sizeof(uw_tmp)) != sizeof(uw_tmp)) break; ok =1; break; } close(fd); return(ok); } int wtmp_logout(const char *line) { int fd; int len; struct stat st; uw_tmp ut; time_t t; if ((fd = open_append(UW_TMP_WFILE)) == -1) strerr_die4sys(111, FATAL, "unable to open ", UW_TMP_WFILE, ": "); if (lock_ex(fd) == -1) strerr_die4sys(111, FATAL, "unable to lock ", UW_TMP_WFILE, ": "); if (fstat(fd, &st) == -1) { close(fd); return(-1); } memset(&ut, 0, sizeof(uw_tmp)); if ((len =str_len(line)) > sizeof ut.ut_line) len =sizeof ut.ut_line -2; byte_copy(ut.ut_line, len, line); if (time(&t) == -1) { close(fd); return(-1); } ut.ut_time = t; #ifdef DEAD_PROCESS ut.ut_type =DEAD_PROCESS; #endif if (write(fd, &ut, sizeof(uw_tmp)) != sizeof(uw_tmp)) { ftruncate(fd, st.st_size); close(fd); return(-1); } close(fd); return(1); } int main (int argc, char * const *argv, const char * const *envp) { int opt; int wtmp =0; progname =*argv; while ((opt =getopt(argc, argv, "wV")) != opteof) { switch(opt) { case 'w': wtmp =1; break; case 'V': strerr_warn1("$Id: 6ced914b40d54fdfee353c5b5fdaf297031295e9 $", 0); case '?': usage(); } } argv +=optind; if (! argv || ! *argv) usage(); if (utmp_logout(*argv) == -1) strerr_die4x(111, WARNING, "unable to logout line ", *argv, " in utmp: no such entry"); if (wtmp) if (wtmp_logout(*argv) == -1) strerr_die4sys(111, WARNING, "unable to logout line ", *argv, " in wtmp: "); _exit(0); } admin/runit-2.2.0/src/byte.h0000644000000000000000000000042714675400254014357 0ustar rootroot/* Public domain. */ #ifndef BYTE_H #define BYTE_H extern unsigned int byte_chr(); extern unsigned int byte_rchr(); extern void byte_copy(); extern void byte_copyr(); extern int byte_diff(); extern void byte_zero(); #define byte_equal(s,n,t) (!byte_diff((s),(n),(t))) #endif admin/runit-2.2.0/src/buffer_get.c0000644000000000000000000000236714675400254015524 0ustar rootroot/* Public domain. */ #include "buffer.h" #include "byte.h" #include "error.h" static int oneread(int (*op)(),int fd,char *buf,unsigned int len) { int r; for (;;) { r = op(fd,buf,len); if (r == -1) if (errno == error_intr) continue; return r; } } static int getthis(buffer *s,char *buf,unsigned int len) { if (len > s->p) len = s->p; s->p -= len; byte_copy(buf,len,s->x + s->n); s->n += len; return len; } int buffer_feed(buffer *s) { int r; if (s->p) return s->p; r = oneread(s->op,s->fd,s->x,s->n); if (r <= 0) return r; s->p = r; s->n -= r; if (s->n > 0) byte_copyr(s->x + s->n,r,s->x); return r; } int buffer_bget(buffer *s,char *buf,unsigned int len) { int r; if (s->p > 0) return getthis(s,buf,len); if (s->n <= len) return oneread(s->op,s->fd,buf,s->n); r = buffer_feed(s); if (r <= 0) return r; return getthis(s,buf,len); } int buffer_get(buffer *s,char *buf,unsigned int len) { int r; if (s->p > 0) return getthis(s,buf,len); if (s->n <= len) return oneread(s->op,s->fd,buf,len); r = buffer_feed(s); if (r <= 0) return r; return getthis(s,buf,len); } char *buffer_peek(buffer *s) { return s->x + s->n; } void buffer_seek(buffer *s,unsigned int len) { s->n += len; s->p -= len; } admin/runit-2.2.0/src/chpst.check0000755000000000000000000000053614675400254015367 0ustar rootroot#!/bin/sh rm -rf "${ctmp}" chpst echo $? chpst -V echo $? # -u # -U mkdir "${ctmp}" echo 1 >"${ctmp}"/test chpst -e"${ctmp}" env |sed -ne '/^test=1$/p' echo $? rm -rf "${ctmp}" chpst -l"${ctmp}" true echo $? rm -f "${ctmp}" chpst -L"${ctmp}" true echo $? rm -f "${ctmp}" # -m # -o # -p # -f # -c chpst -P true echo $? chpst -012 true echo $? admin/runit-2.2.0/src/alloc_re.c0000644000000000000000000000035414675400254015166 0ustar rootroot/* Public domain. */ #include "alloc.h" #include "byte.h" int alloc_re(x,m,n) char **x; unsigned int m; unsigned int n; { char *y; y = alloc(n); if (!y) return 0; byte_copy(y,m,*x); alloc_free(*x); *x = y; return 1; } admin/runit-2.2.0/src/openreadclose.c0000644000000000000000000000054014675400254016226 0ustar rootroot/* Public domain. */ #include "error.h" #include "open.h" #include "readclose.h" #include "openreadclose.h" int openreadclose(const char *fn,stralloc *sa,unsigned int bufsize) { int fd; fd = open_read(fn); if (fd == -1) { if (errno == error_noent) return 0; return -1; } if (readclose(fd,sa,bufsize) == -1) return -1; return 1; } admin/runit-2.2.0/src/svlogd.dist0000644000000000000000000000035614675400254015427 0ustar rootrootusage: svlogd [-ttv] [-r c] [-R abc] [-l len] [-b buflen] dir ... 111 $Id: 66d40067fb843ee6cde160e47c9dee5c73986f6d $ usage: svlogd [-ttv] [-r c] [-R abc] [-l len] [-b buflen] dir ... 111 0 foo 0 foo bar baz 0 foo bar baz :oo :ar :az 0 admin/runit-2.2.0/src/utmpset.check0000755000000000000000000000005514675400254015743 0ustar rootroot#!/bin/sh utmpset echo $? utmpset -V echo $? admin/runit-2.2.0/src/uw_tmp.h10000644000000000000000000000054614675400254015012 0ustar rootroot#include #include /* sysdep: -utmpx */ #ifdef _PATH_UTMP #define UW_TMP_UFILE _PATH_UTMP #define UW_TMP_WFILE _PATH_WTMP #else /* AIX only has UTMP_FILE */ #ifdef UTMP_FILE #define UW_TMP_UFILE UTMP_FILE #define UW_TMP_WFILE WTMP_FILE #else #error neither _PATH_UTMP nor UTMP_FILE defined. #endif #endif typedef struct utmp uw_tmp; admin/runit-2.2.0/src/readclose.c0000644000000000000000000000105514675400254015346 0ustar rootroot/* Public domain. */ #include #include "error.h" #include "readclose.h" int readclose_append(int fd,stralloc *sa,unsigned int bufsize) { int r; for (;;) { if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; } r = read(fd,sa->s + sa->len,bufsize); if (r == -1) if (errno == error_intr) continue; if (r <= 0) { close(fd); return r; } sa->len += r; } } int readclose(int fd,stralloc *sa,unsigned int bufsize) { if (!stralloc_copys(sa,"")) { close(fd); return -1; } return readclose_append(fd,sa,bufsize); } admin/runit-2.2.0/src/runsvstat.check0000755000000000000000000000070214675400254016312 0ustar rootroot#!/bin/sh rm -rf "${ctmp}" runsvstat echo $? runsvstat -V echo $? mkdir "${ctmp}" echo '#!/bin/sh' >"${ctmp}"/run echo 'echo starting' >>"${ctmp}"/run echo 'exec sleep 14' >>"${ctmp}"/run chmod 700 "${ctmp}"/run chpst -2 runsvstat "${ctmp}" echo $? runsv "${ctmp}" & sleep 1 test -r "${ctmp}"/supervise/stat || sleep 2 chpst -1 runsvstat "${ctmp}" echo $? runsvctrl exit "${ctmp}" wait echo $? chpst -2 runsvstat "${ctmp}" echo $? rm -rf "${ctmp}" admin/runit-2.2.0/src/fifo.h0000644000000000000000000000014514675400254014334 0ustar rootroot/* Public domain. */ #ifndef FIFO_H #define FIFO_H extern int fifo_make(const char *,int); #endif admin/runit-2.2.0/src/runit.dist0000644000000000000000000000006114675400254015263 0ustar rootroot- runit: fatal: must be run as process no 1. 111 admin/runit-2.2.0/src/uw_tmp.h20000644000000000000000000000032714675400254015010 0ustar rootroot#include #include /* sysdep: +utmpx */ #define UW_TMP_UFILE _UTMPX_FILE #define UW_TMP_WFILE _WTMPX_FILE #ifndef ut_time #define ut_time ut_tv.tv_sec #endif typedef struct futmpx uw_tmp; admin/runit-2.2.0/src/runsv.check0000755000000000000000000000255714675400254015430 0ustar rootroot#!/bin/sh rm -rf "${ctmp}" runsv echo $? mkdir "${ctmp}" echo '#!/bin/sh' >"${ctmp}"/run echo 'echo starting' >>"${ctmp}"/run echo 'exec sleep 14' >>"${ctmp}"/run chmod 700 "${ctmp}"/run runsv "${ctmp}" & sleep 1 test -r "${ctmp}"/supervise/stat || sleep 2 cat "${ctmp}"/supervise/stat mkdir -p "${ctmp}"/control echo '#!/bin/sh' >"${ctmp}"/control/t echo 'echo term' >>"${ctmp}"/control/t echo 'exit 1' >>"${ctmp}"/control/t chmod 700 "${ctmp}"/control/t echo t >"${ctmp}"/supervise/control sleep 2 echo x >"${ctmp}"/supervise/control wait echo $? mkdir "${ctmp}"/log echo '#!/bin/sh' >"${ctmp}"/log/run echo 'exec cat >foo' >>"${ctmp}"/log/run chmod 700 "${ctmp}"/log/run runsv "${ctmp}" & sleep 1 test -r "${ctmp}"/log/supervise/stat || sleep 2 mkdir -p "${ctmp}"/control echo '#!/bin/sh' >"${ctmp}"/control/i echo 'echo no interrupt' >>"${ctmp}"/control/i echo 'exit 0' >>"${ctmp}"/control/i chmod 700 "${ctmp}"/control/i echo i >"${ctmp}"/supervise/control sleep 1 echo x >"${ctmp}"/supervise/control wait echo $? cat "${ctmp}"/log/foo rm -rf "${ctmp}"/supervise rm -rf "${ctmp}"/log/supervise rm -f "${ctmp}"/log/foo ln -s foo "${ctmp}"/supervise ln -s bar "${ctmp}"/log/supervise runsv "${ctmp}" & sleep 1 test -r "${ctmp}"/supervise/stat || sleep 2 test -r "${ctmp}"/log/supervise/stat || sleep 2 echo x >"${ctmp}"/foo/control wait echo $? cat "${ctmp}"/log/foo rm -rf "${ctmp}" admin/runit-2.2.0/src/check-diff0000755000000000000000000000015114675400254015146 0ustar rootroot#!/bin/sh while read i; do read j 0<&7 || exit 1 test "$i" = "$j" || exit 1 done 7<$1.dist <$1.local admin/runit-2.2.0/src/seek.h0000644000000000000000000000042714675400254014343 0ustar rootroot/* Public domain. */ #ifndef SEEK_H #define SEEK_H typedef unsigned long seek_pos; extern seek_pos seek_cur(int); extern int seek_set(int,seek_pos); extern int seek_end(int); extern int seek_trunc(int,seek_pos); #define seek_begin(fd) (seek_set((fd),(seek_pos) 0)) #endif admin/runit-2.2.0/src/taia_uint.c0000644000000000000000000000025614675400254015364 0ustar rootroot/* Public domain. */ #include "taia.h" /* XXX: breaks tai encapsulation */ void taia_uint(struct taia *t,unsigned int s) { t->sec.x = s; t->nano = 0; t->atto = 0; } admin/runit-2.2.0/src/svwaitdown.dist0000644000000000000000000000017714675400254016337 0ustar rootrootusage: svwaitdown [-v] [-t 1..6000] service ... 1 $Id$ usage: svwaitdown [-v] [-t 1..6000] service ... 1 starting 0 0 down 0 admin/runit-2.2.0/src/trysysel.c0000644000000000000000000000022614675400254015302 0ustar rootroot/* Public domain. */ #include #include #include #include /* SVR4 silliness */ void foo() { ; } admin/runit-2.2.0/src/runsv.c0000644000000000000000000003670114675400254014570 0ustar rootroot#include #include #include #include #include #include "strerr.h" #include "error.h" #include "taia.h" #include "sig.h" #include "env.h" #include "coe.h" #include "ndelay.h" #include "fifo.h" #include "open.h" #include "lock.h" #include "iopause.h" #include "wait.h" #include "fd.h" #include "buffer.h" #include "fmt.h" #include "byte.h" #define USAGE " dir" #define VERSION "$Id: ecf467746d7b97ff0fddb88b9d44cca201c74160 $" char *progname; int selfpipe[2]; /* state */ #define S_DOWN 0 #define S_RUN 1 #define S_FINISH 2 /* ctrl */ #define C_NOOP 0 #define C_TERM 1 #define C_PAUSE 2 /* want */ #define W_UP 0 #define W_DOWN 1 #define W_EXIT 2 struct svdir { int pid; int state; int ctrl; int want; struct taia start; int wstat; int fdlock; int fdcontrol; int fdcontrolwrite; int islog; }; struct svdir svd[2]; int sigterm =0; int haslog =0; int pidchanged =1; int logpipe[2]; char *dir; void usage () { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } void fatal(char *m) { strerr_die5sys(111, "runsv ", dir, ": fatal: ", m, ": "); } void fatal2(char *m1, char *m2) { strerr_die6sys(111, "runsv ", dir, ": fatal: ", m1, m2, ": "); } void fatalx(char *m1, char *m2) { strerr_die5x(111, "runsv ", dir, ": fatal: ", m1, m2); } void warn(char *m) { strerr_warn5("runsv ", dir, ": warning: ", m, ": ", &strerr_sys); } void warn2(char *m1, char *m2) { strerr_warn6("runsv ", dir, ": warning: ", m1, m2, ": ", &strerr_sys); } void warnx(char *m1, char *m2, char *m3) { strerr_warn6("runsv ", dir, ": warning: ", m1, m2, m3, 0); } void stopservice(struct svdir *); void s_child() { write(selfpipe[1], "", 1); } void s_term() { sigterm =1; write(selfpipe[1], "", 1); /* XXX */ } void update_status(struct svdir *s) { unsigned long l; int fd; char status[20]; char bspace[64]; buffer b; char spid[FMT_ULONG]; char *fstatus ="supervise/status"; char *fstatusnew ="supervise/status.new"; char *fstat ="supervise/stat"; char *fstatnew ="supervise/stat.new"; char *fpid ="supervise/pid"; char *fpidnew ="supervise/pid.new"; if (s->islog) { fstatus ="log/supervise/status"; fstatusnew ="log/supervise/status.new"; fstat ="log/supervise/stat"; fstatnew ="log/supervise/stat.new"; fpid ="log/supervise/pid"; fpidnew ="log/supervise/pid.new"; } /* pid */ if (pidchanged) { if ((fd =open_trunc(fpidnew)) == -1) { warn2("unable to open ", fpidnew); return; } buffer_init(&b, buffer_unixwrite, fd, bspace, sizeof bspace); spid[fmt_ulong(spid, (unsigned long)s->pid)] =0; if (s->pid) { buffer_puts(&b, spid); buffer_puts(&b, "\n"); buffer_flush(&b); } close(fd); if (rename(fpidnew, fpid) == -1) { warn2("unable to rename pid.new to ", fpid); return; } pidchanged =0; } /* stat */ if ((fd =open_trunc(fstatnew)) == -1) { warn2("unable to open ", fstatnew); return; } buffer_init(&b, buffer_unixwrite, fd, bspace, sizeof bspace); switch (s->state) { case S_DOWN: buffer_puts(&b, "down"); break; case S_RUN: buffer_puts(&b, "run"); break; case S_FINISH: buffer_puts(&b, "finish"); break; } if (s->ctrl & C_PAUSE) buffer_puts(&b, ", paused"); if (s->ctrl & C_TERM) buffer_puts(&b, ", got TERM"); if (s->state != S_DOWN) switch(s->want) { case W_DOWN: buffer_puts(&b, ", want down"); break; case W_EXIT: buffer_puts(&b, ", want exit"); break; } buffer_puts(&b, "\n"); buffer_flush(&b); close(fd); if (rename(fstatnew, fstat) == -1) warn2("unable to rename stat.new to ", fstat); /* supervise compatibility */ taia_pack(status, &s->start); l =(unsigned long)s->pid; status[12] =l; l >>=8; status[13] =l; l >>=8; status[14] =l; l >>=8; status[15] =l; if (s->ctrl & C_PAUSE) status[16] =1; else status[16] =0; if (s->want == W_UP) status[17] ='u'; else status[17] ='d'; if (s->ctrl & C_TERM) status[18] =1; else status[18] =0; status[19] =s->state; if ((fd =open_trunc(fstatusnew)) == -1) { warn2("unable to open ", fstatusnew); return; } if ((l =write(fd, status, sizeof status)) == -1) { warn2("unable to write ", fstatusnew); close(fd); unlink(fstatusnew); return; } close(fd); if (l < sizeof status) { warnx("unable to write ", fstatusnew, ": partial write."); return; } if (rename(fstatusnew, fstatus) == -1) warn2("unable to rename status.new to ", fstatus); } unsigned int custom(struct svdir *s, char c) { int pid; int w; char a[10]; struct stat st; char *prog[2]; if (s->islog) return(0); byte_copy(a, 10, "control/?"); a[8] =c; if (stat(a, &st) == 0) { if (st.st_mode & S_IXUSR) { if ((pid =fork()) == -1) { warn2("unable to fork for ", a); return(0); } if (! pid) { if (haslog && fd_copy(1, logpipe[1]) == -1) warn2("unable to setup stdout for ", a); prog[0] =a; prog[1] =0; execve(a, prog, environ); fatal("unable to run control/?"); } while (wait_pid(&w, pid) == -1) { if (errno == error_intr) continue; warn2("unable to wait for child ", a); return(0); } return(! wait_exitcode(w)); } } else { if (errno == error_noent) return(0); warn2("unable to stat ", a); } return(0); } void stopservice(struct svdir *s) { if (s->pid && ! custom(s, 't')) { kill(s->pid, SIGTERM); s->ctrl |=C_TERM; update_status(s); } if (s->want == W_DOWN) { kill(s->pid, SIGCONT); custom(s, 'd'); return; } if (s->want == W_EXIT) { kill(s->pid, SIGCONT); custom(s, 'x'); } } void startservice(struct svdir *s) { int p; char *run[4]; char code[FMT_ULONG]; char stat[FMT_ULONG]; if (s->state == S_FINISH) { run[0] ="./finish"; code[fmt_ulong(code, wait_exitcode(s->wstat))] =0; run[1] =wait_crashed(s->wstat) ? "-1" : code; stat[fmt_ulong(stat, s->wstat & 0xff)] =0; run[2] =stat; run[3] =0; } else { run[0] ="./run"; custom(s, 'u'); run[1] =0; } if (s->pid != 0) stopservice(s); /* should never happen */ while ((p =fork()) == -1) { warn("unable to fork, sleeping"); sleep(5); } if (p == 0) { /* child */ if (haslog) { if (s->islog) { if (fd_copy(0, logpipe[0]) == -1) fatal("unable to setup filedescriptor for ./log/run"); close(logpipe[1]); if (chdir("./log") == -1) fatal("unable to change directory to ./log"); } else { if (fd_copy(1, logpipe[1]) == -1) fatal("unable to setup filedescriptor for ./run"); close(logpipe[0]); } } sig_uncatch(sig_child); sig_unblock(sig_child); sig_uncatch(sig_term); sig_unblock(sig_term); execve(*run, run, environ); if (s->islog) fatal2("unable to start log/", *run); else fatal2("unable to start ", *run); } if (s->state != S_FINISH) { taia_now(&s->start); s->state =S_RUN; } s->pid =p; pidchanged =1; s->ctrl =C_NOOP; update_status(s); } int ctrl(struct svdir *s, char c) { switch(c) { case 'd': /* down */ s->want =W_DOWN; update_status(s); if (s->state == S_RUN) stopservice(s); break; case 'u': /* up */ s->want =W_UP; update_status(s); if (s->state == S_DOWN) startservice(s); break; case 'x': /* exit */ if (s->islog) break; s->want =W_EXIT; update_status(s); if (s->state == S_RUN) stopservice(s); break; case 't': /* sig term */ if (s->state == S_RUN) stopservice(s); break; case 'k': /* sig kill */ if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGKILL); s->state =S_DOWN; break; case 'p': /* sig pause */ if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGSTOP); s->ctrl |=C_PAUSE; update_status(s); break; case 'c': /* sig cont */ if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGCONT); if (s->ctrl & C_PAUSE) s->ctrl &=~C_PAUSE; update_status(s); break; case 'o': /* once */ s->want =W_DOWN; update_status(s); if (s->state == S_DOWN) startservice(s); break; case 'a': /* sig alarm */ if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGALRM); break; case 'h': /* sig hup */ if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGHUP); break; case 'i': /* sig int */ if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGINT); break; case 'q': /* sig quit */ if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGQUIT); break; case '1': /* sig usr1 */ if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGUSR1); break; case '2': /* sig usr2 */ if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGUSR2); break; } return(1); } int main(int argc, char **argv) { struct stat s; int fd; int r; char buf[256]; progname =argv[0]; if (! argv[1] || argv[2]) usage(); dir =argv[1]; if (pipe(selfpipe) == -1) fatal("unable to create selfpipe"); coe(selfpipe[0]); coe(selfpipe[1]); ndelay_on(selfpipe[0]); ndelay_on(selfpipe[1]); sig_block(sig_child); sig_catch(sig_child, s_child); sig_block(sig_term); sig_catch(sig_term, s_term); if (chdir(dir) == -1) fatal("unable to change to directory"); svd[0].pid =0; svd[0].state =S_DOWN; svd[0].ctrl =C_NOOP; svd[0].want =W_UP; svd[0].islog =0; svd[1].pid =0; taia_now(&svd[0].start); if (stat("down", &s) != -1) svd[0].want =W_DOWN; if (stat("log", &s) == -1) { if (errno != error_noent) warn("unable to stat() ./log: "); } else { if (! S_ISDIR(s.st_mode)) warnx("./log", 0, ": not a directory."); else { haslog =1; svd[1].state =S_DOWN; svd[1].ctrl =C_NOOP; svd[1].want =W_UP; svd[1].islog =1; taia_now(&svd[1].start); if (stat("log/down", &s) != -1) svd[1].want =W_DOWN; if (pipe(logpipe) == -1) fatal("unable to create log pipe"); coe(logpipe[0]); coe(logpipe[1]); } } if (mkdir("supervise", 0700) == -1) { if ((r =readlink("supervise", buf, 256)) != -1) { if (r == 256) fatalx("unable to readlink ./supervise: ", "name too long"); buf[r] =0; mkdir(buf, 0700); } else { if ((errno != ENOENT) && (errno != EINVAL)) fatal("unable to readlink ./supervise"); } } if ((svd[0].fdlock =open_append("supervise/lock")) == -1) fatal("unable to open supervise/lock"); if (lock_exnb(svd[0].fdlock) == -1) fatal("unable to lock supervise/lock"); coe(svd[0].fdlock); if (haslog) { if (mkdir("log/supervise", 0700) == -1) { if ((r =readlink("log/supervise", buf, 256)) != -1) { if (r == 256) fatalx("unable to readlink ./log/supervise: ", "name too long"); buf[r] =0; if ((fd =open_read(".")) == -1) fatal("unable to open current directory"); if (chdir("./log") == -1) fatal("unable to change directory to ./log"); mkdir(buf, 0700); if (fchdir(fd) == -1) fatal("unable to change back to service directory"); close(fd); } else { if ((errno != ENOENT) && (errno != EINVAL)) fatal("unable to readlink ./log/supervise"); } } if ((svd[1].fdlock =open_append("log/supervise/lock")) == -1) fatal("unable to open log/supervise/lock"); if (lock_ex(svd[1].fdlock) == -1) fatal("unable to lock log/supervise/lock"); coe(svd[1].fdlock); } fifo_make("supervise/control", 0600); if (stat("supervise/control", &s) == -1) fatal("unable to stat supervise/control"); if (!S_ISFIFO(s.st_mode)) fatalx("supervise/control exists but is not a fifo", ""); if ((svd[0].fdcontrol =open_read("supervise/control")) == -1) fatal("unable to open supervise/control"); coe(svd[0].fdcontrol); if ((svd[0].fdcontrolwrite =open_write("supervise/control")) == -1) fatal("unable to open supervise/control"); coe(svd[0].fdcontrolwrite); update_status(&svd[0]); if (haslog) { fifo_make("log/supervise/control", 0600); if (stat("supervise/control", &s) == -1) fatal("unable to stat log/supervise/control"); if (!S_ISFIFO(s.st_mode)) fatalx("log/supervise/control exists but is not a fifo", ""); if ((svd[1].fdcontrol =open_read("log/supervise/control")) == -1) fatal("unable to open log/supervise/control"); coe(svd[1].fdcontrol); if ((svd[1].fdcontrolwrite =open_write("log/supervise/control")) == -1) fatal("unable to open log/supervise/control"); coe(svd[1].fdcontrolwrite); update_status(&svd[1]); } fifo_make("supervise/ok",0600); if ((fd =open_read("supervise/ok")) == -1) fatal("unable to read supervise/ok"); coe(fd); if (haslog) { fifo_make("log/supervise/ok",0600); if ((fd =open_read("log/supervise/ok")) == -1) fatal("unable to read log/supervise/ok"); coe(fd); } for (;;) { iopause_fd x[3]; struct taia deadline; struct taia now; char ch; if (haslog) if (! svd[1].pid && (svd[1].want == W_UP)) startservice(&svd[1]); if (! svd[0].pid) if ((svd[0].want == W_UP) || (svd[0].state == S_FINISH)) startservice(&svd[0]); x[0].fd =selfpipe[0]; x[0].events =IOPAUSE_READ; x[1].fd =svd[0].fdcontrol; x[1].events =IOPAUSE_READ; if (haslog) { x[2].fd =svd[1].fdcontrol; x[2].events =IOPAUSE_READ; } taia_now(&now); taia_uint(&deadline, 3600); taia_add(&deadline, &now, &deadline); sig_unblock(sig_term); sig_unblock(sig_child); iopause(x, 2 +haslog, &deadline, &now); sig_block(sig_term); sig_block(sig_child); while (read(selfpipe[0], &ch, 1) == 1) ; for (;;) { int child; int wstat; child =wait_nohang(&wstat); if (!child) break; if ((child == -1) && (errno != error_intr)) break; if (child == svd[0].pid) { svd[0].pid =0; pidchanged =1; svd[0].wstat =wstat; svd[0].ctrl &=~C_TERM; if (svd[0].state != S_FINISH) if ((fd =open_read("finish")) != -1) { close(fd); svd[0].state =S_FINISH; update_status(&svd[0]); continue; } svd[0].state =S_DOWN; taia_uint(&deadline, 1); taia_add(&deadline, &svd[0].start, &deadline); taia_now(&svd[0].start); update_status(&svd[0]); if (taia_less(&svd[0].start, &deadline)) sleep(1); } if (haslog) { if (child == svd[1].pid) { svd[1].pid =0; pidchanged =1; svd[1].state =S_DOWN; svd[1].ctrl &=~C_TERM; taia_uint(&deadline, 1); taia_add(&deadline, &svd[1].start, &deadline); taia_now(&svd[1].start); update_status(&svd[1]); if (taia_less(&svd[1].start, &deadline)) sleep(1); } } } if (read(svd[0].fdcontrol, &ch, 1) == 1) ctrl(&svd[0], ch); if (haslog) if (read(svd[1].fdcontrol, &ch, 1) == 1) ctrl(&svd[1], ch); if (sigterm) { ctrl(&svd[0], 'x'); sigterm =0; } if ((svd[0].want == W_EXIT) && (svd[0].state == S_DOWN)) { if (svd[1].pid == 0) _exit(0); if (svd[1].want != W_EXIT) { svd[1].want =W_EXIT; /* stopservice(&svd[1]); */ update_status(&svd[1]); if (close(logpipe[1]) == -1) warn("unable to close logpipe[1]"); if (close(logpipe[0]) == -1) warn("unable to close logpipe[0]"); } } } _exit(0); } admin/runit-2.2.0/src/stralloc_pend.c0000644000000000000000000000025714675400254016241 0ustar rootroot/* Public domain. */ #include "alloc.h" #include "stralloc.h" #include "gen_allocdefs.h" GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append) admin/runit-2.2.0/src/hassgact.h10000644000000000000000000000005714675400254015271 0ustar rootroot/* Public domain. */ /* sysdep: -sigaction */ admin/runit-2.2.0/src/trywaitp.c0000644000000000000000000000014514675400254015267 0ustar rootroot/* Public domain. */ #include #include int main() { waitpid(0,0,0); } admin/runit-2.2.0/src/fd_copy.c0000644000000000000000000000040114675400254015022 0ustar rootroot/* Public domain. */ #include #include #include "fd.h" int fd_copy(int to,int from) { if (to == from) return 0; if (fcntl(from,F_GETFL,0) == -1) return -1; close(to); if (fcntl(from,F_DUPFD,to) == -1) return -1; return 0; } admin/runit-2.2.0/src/openreadclose.h0000644000000000000000000000024614675400254016236 0ustar rootroot/* Public domain. */ #ifndef OPENREADCLOSE_H #define OPENREADCLOSE_H #include "stralloc.h" extern int openreadclose(const char *,stralloc *,unsigned int); #endif admin/runit-2.2.0/src/taia.h0000644000000000000000000000174214675400254014333 0ustar rootroot/* Public domain. */ #ifndef TAIA_H #define TAIA_H #include "tai.h" struct taia { struct tai sec; unsigned long nano; /* 0...999999999 */ unsigned long atto; /* 0...999999999 */ } ; extern void taia_tai(const struct taia *,struct tai *); extern void taia_now(struct taia *); extern double taia_approx(const struct taia *); extern double taia_frac(const struct taia *); extern void taia_add(struct taia *,const struct taia *,const struct taia *); extern void taia_addsec(struct taia *,const struct taia *,int); extern void taia_sub(struct taia *,const struct taia *,const struct taia *); extern void taia_half(struct taia *,const struct taia *); extern int taia_less(const struct taia *,const struct taia *); #define TAIA_PACK 16 extern void taia_pack(char *,const struct taia *); extern void taia_unpack(const char *,struct taia *); #define TAIA_FMTFRAC 19 extern unsigned int taia_fmtfrac(char *,const struct taia *); extern void taia_uint(struct taia *,unsigned int); #endif admin/runit-2.2.0/src/byte_chr.c0000644000000000000000000000063014675400254015202 0ustar rootroot/* Public domain. */ #include "byte.h" unsigned int byte_chr(s,n,c) char *s; register unsigned int n; int c; { register char ch; register char *t; ch = c; t = s; for (;;) { if (!n) break; if (*t == ch) break; ++t; --n; if (!n) break; if (*t == ch) break; ++t; --n; if (!n) break; if (*t == ch) break; ++t; --n; if (!n) break; if (*t == ch) break; ++t; --n; } return t - s; } admin/runit-2.2.0/src/runsvstat.dist0000644000000000000000000000014414675400254016175 0ustar rootrootusage: runsvstat [ -l ] service ... 1 $Id$ usage: runsvstat [ -l ] service ... 1 1 starting 0 0 1 admin/runit-2.2.0/src/stralloc_catb.c0000644000000000000000000000052214675400254016217 0ustar rootroot/* Public domain. */ #include "stralloc.h" #include "byte.h" int stralloc_catb(stralloc *sa,const char *s,unsigned int n) { if (!sa->s) return stralloc_copyb(sa,s,n); if (!stralloc_readyplus(sa,n + 1)) return 0; byte_copy(sa->s + sa->len,n,s); sa->len += n; sa->s[sa->len] = 'Z'; /* ``offensive programming'' */ return 1; } admin/runit-2.2.0/src/direntry.h20000644000000000000000000000024614675400254015335 0ustar rootroot/* Public domain. */ #ifndef DIRENTRY_H #define DIRENTRY_H /* sysdep: +dirent */ #include #include #define direntry struct dirent #endif admin/runit-2.2.0/src/find-systype.sh0000644000000000000000000000640414675400254016236 0ustar rootroot# oper-:arch-:syst-:chip-:kern- # oper = operating system type; e.g., sunos-4.1.4 # arch = machine language; e.g., sparc # syst = which binaries can run; e.g., sun4 # chip = chip model; e.g., micro-2-80 # kern = kernel version; e.g., sun4m # dependence: arch --- chip # \ \ # oper --- syst --- kern # so, for example, syst is interpreted in light of oper, but chip is not. # anyway, no slashes, no extra colons, no uppercase letters. # the point of the extra -'s is to ease parsing: can add hierarchies later. # e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium, # and i386-486 (486s do have more instructions, you know) as well as i386. # the idea here is to include ALL useful available information. exec 2>/dev/null sys="`uname -s | tr '/:[A-Z]' '..[a-z]'`" if [ x"$sys" != x ] then unamer="`uname -r | tr /: ..`" unamem="`uname -m | tr /: ..`" unamev="`uname -v | tr /: ..`" case "$sys" in bsd.os|freebsd|netbsd|openbsd) # in bsd 4.4, uname -v does not have useful info. # in bsd 4.4, uname -m is arch, not chip. oper="$sys-$unamer" arch="$unamem" syst="" chip="`sysctl -n hw.model`" # hopefully kern="" ;; linux) # as in bsd 4.4, uname -v does not have useful info. oper="$sys-$unamer" syst="" chip="$unamem" kern="" case "$chip" in i386|i486|i586|i686) arch="i386" ;; alpha) arch="alpha" ;; esac ;; aix) # naturally IBM has to get uname -r and uname -v backwards. dorks. oper="$sys-$unamev-$unamer" arch="`arch | tr /: ..`" syst="" chip="$unamem" kern="" ;; sunos) oper="$sys-$unamer-$unamev" arch="`(uname -p || mach) | tr /: ..`" syst="`arch | tr /: ..`" chip="$unamem" # this is wrong; is there any way to get the real info? kern="`arch -k | tr /: ..`" ;; unix_sv) oper="$sys-$unamer-$unamev" arch="`uname -m`" syst="" chip="$unamem" kern="" ;; *) oper="$sys-$unamer-$unamev" arch="`arch | tr /: ..`" syst="" chip="$unamem" kern="" ;; esac else gcc -c trycpp.c gcc -o trycpp trycpp.o case `./trycpp` in nextstep) oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`" arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`" syst="" chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`" kern="" ;; *) oper="unknown" arch="" syst="" chip="" kern="" ;; esac rm -f trycpp.o trycpp fi case "$chip" in 80486) # let's try to be consistent here. (BSD/OS) chip=i486 ;; i486DX) # respect the hyphen hierarchy. (FreeBSD) chip=i486-dx ;; i486.DX2) # respect the hyphen hierarchy. (FreeBSD) chip=i486-dx2 ;; Intel.586) # no, you nitwits, there is no such chip. (NeXTStep) chip=pentium ;; i586) # no, you nitwits, there is no such chip. (Linux) chip=pentium ;; i686) # STOP SAYING THAT! (Linux) chip=ppro esac if gcc -c x86cpuid.c then if gcc -o x86cpuid x86cpuid.o then x86cpuid="`./x86cpuid | tr /: ..`" case "$x86cpuid" in ?*) chip="$x86cpuid" ;; esac fi fi rm -f x86cpuid x86cpuid.o echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]' admin/runit-2.2.0/src/hassgprm.h10000644000000000000000000000006114675400254015313 0ustar rootroot/* Public domain. */ /* sysdep: -sigprocmask */ admin/runit-2.2.0/src/reboot_system.h20000644000000000000000000000020014675400254016361 0ustar rootroot#include #include /* sysdep: +std reboot */ int reboot_system(int what) { return(reboot(what)); } admin/runit-2.2.0/src/runit-init.check0000755000000000000000000000003514675400254016342 0ustar rootroot#!/bin/sh runit-init echo $? admin/runit-2.2.0/etc/0000755000000000000000000000000014675400254013224 5ustar rootrootadmin/runit-2.2.0/etc/debian/0000755000000000000000000000000014675400254014446 5ustar rootrootadmin/runit-2.2.0/etc/debian/30000755000000000000000000000036014675400254014535 0ustar rootroot#!/bin/sh exec 2>&1 PATH=/command:/sbin:/bin:/usr/sbin:/usr/bin LAST=0 test -x /etc/runit/reboot && LAST=6 echo 'Waiting for services to stop...' sv -w196 force-stop /service/* sv exit /service/* echo 'Shutdown...' /etc/init.d/rc $LAST admin/runit-2.2.0/etc/debian/10000755000000000000000000000025114675400254014532 0ustar rootroot#!/bin/sh # system one time tasks PATH=/command:/sbin:/bin:/usr/sbin:/usr/bin /etc/init.d/rcS /etc/init.d/rmnologin touch /etc/runit/stopit chmod 0 /etc/runit/stopit admin/runit-2.2.0/etc/debian/getty-tty5/0000755000000000000000000000000014675400254016505 5ustar rootrootadmin/runit-2.2.0/etc/debian/getty-tty5/finish0000755000000000000000000000003714675400254017713 0ustar rootroot#!/bin/sh exec utmpset -w tty5 admin/runit-2.2.0/etc/debian/getty-tty5/run0000755000000000000000000000005414675400254017236 0ustar rootroot#!/bin/sh exec /sbin/getty 38400 tty5 linux admin/runit-2.2.0/etc/debian/ctrlaltdel0000755000000000000000000000027514675400254016532 0ustar rootroot#!/bin/sh PATH=/bin:/usr/bin MSG="System is going down in 14 seconds..." # echo 'disabled.' ; exit touch /etc/runit/stopit chmod 100 /etc/runit/stopit && echo "$MSG" | wall /bin/sleep 14 admin/runit-2.2.0/etc/debian/20000777000000000000000000000000014675400254015026 2../2ustar rootrootadmin/runit-2.2.0/etc/20000755000000000000000000000104614675400254013314 0ustar rootroot#!/bin/sh PATH=/command:/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin exec env - PATH=$PATH \ runsvdir -P /service 'log: ...........................................................................................................................................................................................................................................................................................................................................................................................................' admin/runit-2.2.0/etc/openbsd/0000755000000000000000000000000014675400254014656 5ustar rootrootadmin/runit-2.2.0/etc/openbsd/30000755000000000000000000000036414675400254014751 0ustar rootroot#!/bin/sh exec 2>&1 PATH=/command:/sbin:/bin:/usr/sbin:/usr/bin echo 'Waiting for services to stop...' sv -w196 force-stop /service/* sv exit /service/* echo 'Shutdown...' if test -x /etc/runit/reboot; then exec reboot else exec halt fi admin/runit-2.2.0/etc/openbsd/10000755000000000000000000000051714675400254014747 0ustar rootroot#!/bin/sh # system one time tasks PATH=/command:/sbin:/bin:/usr/sbin:/usr/bin trap : 2 trap : 3 sh /etc/rc autoboot if test $? -ne 0; then # /etc/rc crashed, start emergency shell. echo '/etc/rc failed. Press for emergency shell...' read input sh -l exec reboot fi touch /etc/runit/stopit chmod 0 /etc/runit/stopit admin/runit-2.2.0/etc/openbsd/ctrlaltdel0000755000000000000000000000027514675400254016742 0ustar rootroot#!/bin/sh PATH=/bin:/usr/bin MSG="System is going down in 14 seconds..." # echo 'disabled.' ; exit touch /etc/runit/stopit chmod 100 /etc/runit/stopit && echo "$MSG" | wall /bin/sleep 14 admin/runit-2.2.0/etc/openbsd/20000777000000000000000000000000014675400254015236 2../2ustar rootrootadmin/runit-2.2.0/etc/openbsd/getty-ttyC4/0000755000000000000000000000000014675400254017017 5ustar rootrootadmin/runit-2.2.0/etc/openbsd/getty-ttyC4/finish0000755000000000000000000000004014675400254020217 0ustar rootroot#!/bin/sh exec utmpset -w ttyC4 admin/runit-2.2.0/etc/openbsd/getty-ttyC4/run0000755000000000000000000000005314675400254017547 0ustar rootroot#!/bin/sh exec /usr/libexec/getty Pc ttyC4 admin/runit-2.2.0/etc/freebsd/0000755000000000000000000000000014675400254014636 5ustar rootrootadmin/runit-2.2.0/etc/freebsd/30000755000000000000000000000036414675400254014731 0ustar rootroot#!/bin/sh exec 2>&1 PATH=/command:/sbin:/bin:/usr/sbin:/usr/bin echo 'Waiting for services to stop...' sv -w196 force-stop /service/* sv exit /service/* echo 'Shutdown...' if test -x /etc/runit/reboot; then exec reboot else exec halt fi admin/runit-2.2.0/etc/freebsd/10000755000000000000000000000051714675400254014727 0ustar rootroot#!/bin/sh # system one time tasks PATH=/command:/sbin:/bin:/usr/sbin:/usr/bin trap : 2 trap : 3 sh /etc/rc autoboot if test $? -ne 0; then # /etc/rc crashed, start emergency shell. echo '/etc/rc failed. Press for emergency shell...' read input sh -p exec reboot fi touch /etc/runit/stopit chmod 0 /etc/runit/stopit admin/runit-2.2.0/etc/freebsd/getty-ttyv4/0000755000000000000000000000000014675400254017062 5ustar rootrootadmin/runit-2.2.0/etc/freebsd/getty-ttyv4/finish0000755000000000000000000000004014675400254020262 0ustar rootroot#!/bin/sh exec utmpset -w ttyv4 admin/runit-2.2.0/etc/freebsd/getty-ttyv4/run0000755000000000000000000000005314675400254017612 0ustar rootroot#!/bin/sh exec /usr/libexec/getty Pc ttyv4 admin/runit-2.2.0/etc/freebsd/ctrlaltdel0000755000000000000000000000027514675400254016722 0ustar rootroot#!/bin/sh PATH=/bin:/usr/bin MSG="System is going down in 14 seconds..." # echo 'disabled.' ; exit touch /etc/runit/stopit chmod 100 /etc/runit/stopit && echo "$MSG" | wall /bin/sleep 14 admin/runit-2.2.0/etc/freebsd/20000777000000000000000000000000014675400254015216 2../2ustar rootrootadmin/runit-2.2.0/etc/macosx/0000755000000000000000000000000014675400254014516 5ustar rootrootadmin/runit-2.2.0/etc/macosx/org.smarden.runit.plist0000644000000000000000000000106114675400254021150 0ustar rootroot Label org.smarden.runit ServiceDescription runsvdir - starts and monitors a collection of runsv(8) processes QueueDirectories /service OnDemand ProgramArguments /sbin/runsvdir-start admin/runit-2.2.0/etc/macosx/20000777000000000000000000000000014675400254015076 2../2ustar rootrootadmin/runit-2.2.0/etc/macosx/StartupItems/0000755000000000000000000000000014675400254017162 5ustar rootrootadmin/runit-2.2.0/etc/macosx/StartupItems/StartupParameters.plist0000644000000000000000000000041114675400254023721 0ustar rootroot{ Description = "runit service supervision"; Provides = ("runit"); Requires = ("Disks"); OrderPreference = "None"; Messages = { start = "Starting runit service supervision"; stop = "Stopping runit service supervision"; }; } admin/runit-2.2.0/etc/macosx/StartupItems/runit0000755000000000000000000000051414675400254020251 0ustar rootroot#!/bin/sh ## # runit ## . /etc/rc.common StartService() { ConsoleMessage "Starting runit service supervision" /bin/csh -cf '/sbin/runsvdir-start &' } StopService() { ConsoleMessage "Stopping runit service supervision" sv -w196 force-stop /service/* sv exit /service/* } RestartService() { return 0 } RunService "$1" admin/runit-2.2.0/man/0000755000000000000000000000000014675400254013224 5ustar rootrootadmin/runit-2.2.0/man/utmpset.80000644000000000000000000000207314675400254015020 0ustar rootroot.TH utmpset 8 .SH NAME utmpset \- logout a line from utmp and wtmp file .SH SYNOPSIS .B utmpset [ .B \-w ] .I line .SH DESCRIPTION The .B utmpset program modifies the user accounting database .BR utmp (5) and optionally .BR wtmp (5) to indicate that the user on the terminal .I line has logged out. .P Ordinary .BR init (8) processes handle utmp file records for local login accounting. The .BR runit (8) program doesn't include code to update the utmp file, the .BR getty (8) processes are handled the same as all other services. .P To enable local login accounting, add .B utmpset to the .BR getty (8) .I finish scripts, e.g.: .P $ cat /service/getty-5/finish #!/bin/sh exec utmpset \-w tty5 $ .SH OPTIONS .TP .B \-w wtmp. Additionally to the utmp file, write an empty record for .I line to the wtmp file. .SH EXIT CODES .B utmpset returns 111 on error, 1 on wrong usage, 0 in all other cases. .SH SEE ALSO sv(8), runsv(8), runit(8), runit-init(8) runsvdir(8), runsvchdir(8), chpst(8), svlogd(8), getty(8) .P http://smarden.org/runit/ .SH AUTHOR Gerrit Pape admin/runit-2.2.0/man/runsvdir.80000644000000000000000000000400614675400254015171 0ustar rootroot.TH runsvdir 8 .SH NAME runsvdir \- starts and monitors a collection of runsv(8) processes .SH SYNOPSIS .B runsvdir [\-P] .I dir [ .I log ] .SH DESCRIPTION .I dir must be a directory. .I log is a space holder for a readproctitle log, and must be at least seven characters long or absent. .P .B runsvdir starts a .BR runsv (8) process for each subdirectory, or symlink to a directory, in the services directory .IR dir , up to a limit of 1000 subdirectories, and restarts a .BR runsv (8) process if it terminates. .B runsvdir skips subdirectory names starting with dots. .BR runsv (8) must be in .BR runsvdir 's PATH. .P At least every five seconds .B runsvdir checks whether the time of last modification, the inode, or the device, of the services directory .I dir has changed. If so, it re-scans the service directory, and if it sees a new subdirectory, or new symlink to a directory, in .IR dir , it starts a new .BR runsv (8) process; if .B runsvdir sees a subdirectory being removed that was previously there, it sends the corresponding .BR runsv (8) process a TERM signal, stops monitoring this process, and so does not restart the .BR runsv (8) process if it exits. .P If the .I log argument is given to .BR runsvdir , all output to standard error is redirected to this .IR log , which is similar to the daemontools' .B readproctitle log. To see the most recent error messages, use a process-listing tool such as .BR ps (1). .B runsvdir writes a dot to the readproctitle log every 15 minutes so that old error messages expire. .SH OPTIONS .TP .B \-P use .BR setsid (2) to run each .BR runsv (8) process in a new session and separate process group. .SH SIGNALS If .B runsvdir receives a TERM signal, it exits with 0 immediately. .P If .B runsvdir receives a HUP signal, it sends a TERM signal to each .BR runsv (8) process it is monitoring and then exits with 111. .SH SEE ALSO sv(8), runsv(8), runsvchdir(8), runit(8), runit-init(8), chpst(8), svlogd(8), utmpset(8), setsid(2) .P http://smarden.org/runit/ .SH AUTHOR Gerrit Pape admin/runit-2.2.0/man/runsv.80000644000000000000000000001256214675400254014500 0ustar rootroot.TH runsv 8 .SH NAME runsv \- starts and monitors a service and optionally an appendant log service .SH SYNOPSIS .B runsv .I service .SH DESCRIPTION .I service must be a directory. .P .B runsv switches to the directory .I service and starts ./run. If ./run exits and ./finish exists, .B runsv starts ./finish. If ./finish doesn't exist or ./finish exits, .B runsv restarts ./run. .P If ./run or ./finish exit immediately, .B runsv waits a second before starting ./finish or restarting ./run. .P Two arguments are given to ./finish. The first one is ./run's exit code, or -1 if ./run didn't exit normally. The second one is the least significant byte of the exit status as determined by .BR waitpid (2); for instance it is 0 if ./run exited normally, and the signal number if ./run was terminated by a signal. If .B runsv cannot start ./run for some reason, the exit code is 111 and the status is 0. .P If the file .IR service /down exists, .B runsv does not start ./run immediately. The control interface (see below) can be used to start the service and to give other commands to .BR runsv . .P If the directory .IR service /log exists, .B runsv creates a pipe, redirects .IR service /run's and .IR service /finish's standard output to the pipe, switches to the directory .IR service /log and starts ./run script. The standard input of the log service is redirected to read from the pipe. .P .B runsv maintains status information in a binary format (compatible to the daemontools' .B supervise program) in .IR service /supervise/status and .IR service /log/supervise/status, and in a human-readable format in .IR service /supervise/stat, .IR service /log/supervise/stat, .IR service /supervise/pid, .IR service /log/supervise/pid. .SH CONTROL The named pipes .IR service /supervise/control, and (optionally) .IR service /log/supervise/control are provided to give commands to .BR runsv . You can use .BR sv (8) to control the service or just write one of the following characters to the named pipe: .TP .B u Up. If the service is not running, start it. If the service stops, restart it. .TP .B d Down. If the service is running, send it a TERM signal, and then a CONT signal. If ./run exits, start ./finish if it exists. After it stops, do not restart service. .TP .B o Once. If the service is not running, start it. Do not restart it if it stops. .TP .B p Pause. If the service is running, send it a STOP signal. .TP .B c Continue. If the service is running, send it a CONT signal. .TP .B h Hangup. If the service is running, send it a HUP signal. .TP .B a Alarm. If the service is running, send it a ALRM signal. .TP .B i Interrupt. If the service is running, send it a INT signal. .TP .B q Quit. If the service is running, send it a QUIT signal. .TP .B 1 User-defined 1. If the service is running, send it a USR1 signal. .TP .B 2 User-defined 2. If the service is running, send it a USR2 signal. .TP .B t Terminate. If the service is running, send it a TERM signal. .TP .B k Kill. If the service is running, send it a KILL signal. .TP .B x Exit. If the service is running, send it a TERM signal, and then a CONT signal. Do not restart the service. If the service is down, and no log service exists, .B runsv exits. If the service is down and a log service exists, .B runsv closes the standard input of the log service, and waits for it to terminate. If the log service is down, .B runsv exits. This command is ignored if it is given to .IR service /log/supervise/control. .P Example: to send a TERM signal to the socklog-unix service, either do # sv term /service/socklog-unix or # printf t >/service/socklog-unix/supervise/control .P .BR printf (1) usually blocks if no .B runsv process is running in the service directory. .SH CUSTOMIZE CONTROL For each control character .I c except "d" and "x" sent to the control pipe, .B runsv first checks if .I service\fR/control/\fIc exists and is executable. If so, it starts .I service\fR/control/\fIc and waits for it to terminate, before interpreting the command. If the program exits with return code 0, .B runsv refrains from sending the service the corresponding signal. The command .I o is always considered as command .IR u . On command .I d first .I service\fR/control/t is checked, and then .I service\fR/control/d. On command .I x first .I service\fR/control/t is checked, and then .I service\fR/control/x. Specifically: .P If the service is running or paused, control characters "d" and "x" are handled as follows: .TP .B 1. .B runsv checks whether .I service\fR/control/t exists and is executable and runs it if yes. .TP .B 2. If .I service\fR/control/t exits nonzero, or is not executable or doesn't exist, .B runsv sends the service a TERM signal. .TP .B 3. .B runsv sends the service a CONT signal, disregarding .I service\fR/control/c even if it exists and is executable. .TP .B 4. .B runsv checks whether .I service\fR/control/d (or control/x) exists and is executable and runs it if yes. Its exit status is ignored. .P The control of the optional log service cannot be customized. .SH SIGNALS If .B runsv receives a TERM signal, it acts as if the character x was written to the control pipe. .SH EXIT CODES .B runsv exits 111 on an error on startup or if another .B runsv is running in .IR service . .P .B runsv exits 0 if it was told to exit. .SH SEE ALSO sv(8), chpst(8), svlogd(8), runit(8), runit-init(8), runsvdir(8), runsvchdir(8), utmpset(8) .P http://smarden.org/runit/ .SH AUTHOR Gerrit Pape admin/runit-2.2.0/man/sv.80000644000000000000000000001421714675400254013752 0ustar rootroot.TH sv 8 .SH NAME sv \- control and manage services monitored by .BR runsv (8) .SH SYNOPSIS .B sv [\-v] [\-w .I sec\fR] .I command .I services .P .BI /etc/init.d/ service [\-w .I sec\fR] .I command .SH DESCRIPTION The .B sv program reports the current status and controls the state of services monitored by the .BR runsv (8) supervisor. .P .I services consists of one or more arguments, each argument naming a directory .I service used by .BR runsv (8). If .I service doesn't start with a dot or slash and doesn't end with a slash, it is searched in the default services directory .IR /service/ , otherwise relative to the current directory. .P .I command is one of up, down, status, once, pause, cont, hup, alarm, interrupt, 1, 2, term, kill, or exit, or start, stop, restart, shutdown, force-stop, force-reload, force-restart, force-shutdown. .P The .B sv program can be sym-linked to .I /etc/init.d/ to provide an LSB init script interface. The .I service to be controlled then is specified by the base name of the ``init script''. .SH COMMANDS .TP .B status Report the current status of the service, and the appendant log service if available, to standard output. .TP .B up If the service is not running, start it. If the service stops, restart it. .TP .B down If the service is running, send it the TERM signal, and the CONT signal. If ./run exits, start ./finish if it exists. After it stops, do not restart service. .TP .B once If the service is not running, start it. Do not restart it if it stops. .TP .B pause cont hup alarm interrupt quit 1 2 term kill If the service is running, send it the STOP, CONT, HUP, ALRM, INT, QUIT, USR1, USR2, TERM, or KILL signal respectively. .TP .B exit If the service is running, send it the TERM signal, and the CONT signal. Do not restart the service. If the service is down, and no log service exists, .BR runsv (8) exits. If the service is down and a log service exists, .BR runsv (8) closes the standard input of the log service and waits for it to terminate. If the log service is down, .BR runsv (8) exits. This command is ignored if it is given to an appendant log service. .P .BR sv actually looks only at the first character of these .IR command s. .SS Commands compatible to LSB init script actions .TP .B status Same as .IR status . .TP .B start Same as .IR up , but wait up to 7 seconds for the command to take effect. Then report the status or timeout. If the script .I ./check exists in the service directory, .B sv runs this script to check whether the service is up and available; it's considered to be available if .I ./check exits with 0. .TP .B stop Same as .IR down , but wait up to 7 seconds for the service to become down. Then report the status or timeout. .TP .B reload Same as .IR hup , and additionally report the status afterwards. .TP .B restart Send the commands .IR term , .IR cont , and .I up to the service, and wait up to 7 seconds for the service to restart. Then report the status or timeout. If the script .I ./check exists in the service directory, .B sv runs this script to check whether the service is up and available again; it's considered to be available if .I ./check exits with 0. .TP .B shutdown Same as .IR exit , but wait up to 7 seconds for the .BR runsv (8) process to terminate. Then report the status or timeout. .TP .B force-stop Same as .IR down , but wait up to 7 seconds for the service to become down. Then report the status, and on timeout send the service the .I kill command. .TP .B force-reload Send the service the .I term and .I cont commands, and wait up to 7 seconds for the service to restart. Then report the status, and on timeout send the service the .I kill command. .TP .B force-restart Send the service the .IR term , .I cont and .I up commands, and wait up to 7 seconds for the service to restart. Then report the status, and on timeout send the service the .I kill command. If the script .I ./check exists in the service directory, .B sv runs this script to check whether the service is up and available again; it's considered to be available if .I ./check exits with 0. .TP .B force-shutdown Same as .IR exit , but wait up to 7 seconds for the .BR runsv (8) process to terminate. Then report the status, and on timeout send the service the .I kill command. .TP .B try-restart if the service is running, send it the .I term and .I cont commands, and wait up to 7 seconds for the service to restart. Then report the status or timeout. .SS Additional Commands .TP .B check Check for the service to be in the state that's been requested. Wait up to 7 seconds for the service to reach the requested state, then report the status or timeout. If the requested state of the service is .IR up , and the script .I ./check exists in the service directory, .B sv runs this script to check whether the service is up and running; it's considered to be up if .I ./check exits with 0. .SH OPTIONS .TP .B \-v If the .I command is up, down, term, once, cont, or exit, then wait up to 7 seconds for the command to take effect. Then report the status or timeout. .TP .B \-w \fIsec Override the default timeout of 7 seconds with .I sec seconds. This option implies .IR \-v . .SH ENVIRONMENT .TP .B SVDIR The environment variable $SVDIR overrides the default services directory .IR /service/ . .TP .B SVWAIT The environment variable $SVWAIT overrides the default 7 seconds to wait for a command to take effect. It is overridden by the \-w option. .SH EXIT CODES .B sv exits 0, if the .I command was successfully sent to all .IR services , and, if it was told to wait, the .I command has taken effect to all services. .P For each .I service that caused an error (e.g. the directory is not controlled by a .BR runsv (8) process, or .B sv timed out while waiting), .B sv increases the exit code by one and exits non zero. The maximum is 99. .B sv exits 100 on error. .P If .B sv is called with a base name other than .BR sv : it exits 1 on timeout or trouble sending the command; if the .I command is .BR status , it exits 3 if the service is down, and 4 if the status is unknown; it exits 2 on wrong usage, and 151 on error. .SH SEE ALSO runsv(8), chpst(8), svlogd(8), runsvdir(8), runsvchdir(8), runit(8), runit-init(8) .P http://smarden.org/runit/ .SH AUTHOR Gerrit Pape admin/runit-2.2.0/man/svlogd.80000644000000000000000000002254514675400254014623 0ustar rootroot.TH svlogd 8 .SH NAME svlogd \- runit's service logging daemon .SH SYNOPSIS .B svlogd [\-tttv] [\-r .I c\fR] [\-R .I xyz\fR] [\-l .I len\fR] [\-b .I buflen\fR] .I logs .SH DESCRIPTION .I logs consists of one or more arguments, each specifying a directory. .P .B svlogd continuously reads log data from its standard input, optionally filters log messages, and writes the data to one or more automatically rotated .IR logs . .P Recent log files can automatically be processed by an arbitrary processor program when they are rotated, and .B svlogd can be told to alert selected log messages to standard error, and through udp. .P .B svlogd runs until it sees end-of-file on standard input or is sent a TERM signal, see below. .SS LOG DIRECTORY A log directory .I log contains some number of old log files, and the current log file .IR current . Old log files have a file name starting with .I @ followed by a precise timestamp (see the daemontools' .B tai64n program), indicating when .I current was rotated and renamed to this file. .P A log directory additionally contains the lock file .IR lock , maybe .I state and .IR newstate , and optionally the file .IR config . .B svlogd creates necessary files if they don't exist. .P If .B svlogd has trouble opening a log directory, it prints a warning, and ignores this log directory. If .B svlogd is unable to open all log directories given at the command line, it exits with an error. This can happen on start-up or after receiving a HUP signal. .SS LOG FILE ROTATION .B svlogd appends selected log messages to the .I current log file. If .I current has .I size bytes or more (or there is a new-line within the last .I len of .I size bytes), or is older than a specified amount of .IR time , .I current is rotated: .P .B svlogd closes .IR current , changes permission of .I current to 0755, renames .I current to .RI @ timestamp\fR.s, and starts with a new empty .IR current . If .B svlogd sees .I num or more old log files in the log directory, it removes the oldest one. Note that this doesn't decrease the number of log files if there are already more than .I num log files, this must be done manually, e.g. for keeping 10 log files: .P ls \-1 \\@* |sort |sed \-ne '10,$p' |xargs rm .SS PROCESSOR If .B svlogd is told to process recent log files, it saves .I current to .RI @ timestamp\fR.u, feeds .RI @ timestamp\fR.u through ``sh \-c "\fIprocessor\fR"'' and writes the output to .RI @ timestamp\fR.t. If the .I processor finishes successfully, .RI @ timestamp\fR.t is renamed to .RI @ timestamp\fR.s, and .RI @ timestamp\fR.u is deleted; otherwise .RI @ timestamp\fR.t is deleted and the .I processor is started again. .B svlogd also saves any output that the .I processor writes to file descriptor 5, and makes that output available on file descriptor 4 when running .I processor on the next log file rotation. .P A .I processor is run in the background. If .B svlogd sees a previously started .I processor still running when trying to start a new one for the same .IR log , it blocks until the currently running .I processor has finished successfully. Only the HUP signal works in that situation. Note that this may block any program feeding its log data to .BR svlogd. .SS CONFIG On startup, and after receiving a HUP signal, .B svlogd checks for each log directory .I log if the configuration file .I log/config exists, and if so, reads the file line by line and adjusts configuration for .I log as follows: .P If the line is empty, or starts with a ``#'', it is ignored. A line of the form .TP .RI s size sets the maximum file size of .I current when .B svlogd should rotate the current log file to .I size bytes. Default is 1000000. If .I size is zero, .B svlogd doesn't rotate log files. You should set .I size to at least (2 * .IR len ). .TP .RI n num sets the number of old log files .B svlogd should maintain to .IR num . If .B svlogd sees more that .I num old log files in .I log after log file rotation, it deletes the oldest one. Default is 10. If .I num is zero, .B svlogd doesn't remove old log files. .TP .RI N min sets the minimum number of old log files .B svlogd should maintain to .IR min . .I min must be less than .IR num . If .I min is set, and .B svlogd cannot write to .I current because the filesystem is full, and it sees more than .I min old log files, it deletes the oldest one. .TP .RI t timeout sets the maximum age of the .I current log file when .B svlogd should rotate the current log file to .I timeout seconds. If .I current is .I timeout seconds old, and is not empty, .B svlogd forces log file rotation. .TP .RI ! processor tells .B svlogd to feed each recent log file through .I processor (see above) on log file rotation. By default log files are not processed. .TP .RI u a.b.c.d[:port] tells .B svlogd to transmit the first .I len characters of selected log messages to the IP address .IR a.b.c.d , port number .IR port . If .I port isn't set, the default port for syslog is used (514). .I len can be set through the \-l option, see below. If .B svlogd has trouble sending udp packets, it writes error messages to the log directory. Attention: logging through udp is unreliable, and should be used in private networks only. .TP .RI U a.b.c.d[:port] is the same as the .I u line above, but the log messages are no longer written to the log directory, but transmitted through udp only. Error messages from .B svlogd concerning sending udp packages still go to the log directory. .TP .RI p prefix tells .B svlogd to prefix each line to be written to the log directory, to standard error, or through UDP, with .IR prefix . .P If a line starts with a .IR \- , .IR + , .IR e , or .IR E , .B svlogd matches the first .I len characters of each log message against .I pattern and acts accordingly: .TP .RI \- pattern the log message is deselected. .TP .RI + pattern the log message is selected. .TP .RI e pattern the log message is selected to be printed to standard error. .TP .RI E pattern the log message is deselected to be printed to standard error. .P Initially each line is selected to be written to .IR log/current . Deselected log messages are discarded from .IR log . Initially each line is deselected to be written to standard err. Log messages selected for standard error are written to standard error. .SH PATTERN MATCHING .B svlogd matches a log message against the string .I pattern as follows: .P .I pattern is applied to the log message one character by one, starting with the first. A character not a star (``*'') and not a plus (``+'') matches itself. A plus matches the next character in .I pattern in the log message one or more times. A star before the end of .I pattern matches any string in the log message that does not include the next character in .IR pattern . A star at the end of .I pattern matches any string. .P Timestamps optionally added by .B svlogd are not considered part of the log message. .P An .B svlogd pattern is not a regular expression. For example consider a log message like this .P 2005-12-18_09:13:50.97618 tcpsvd: info: pid 1977 from 10.4.1.14 .P The following pattern doesn't match .P -*pid* .P because the first star matches up to the first p in tcpsvd, and then the match fails because i is not s. To match this log message, you can use a pattern like this instead .P -*: *: pid * .SH OPTIONS .TP .B \-t timestamp. Prefix each selected line with a precise timestamp (see the daemontools' .B tai64n program) when writing to .I log or to standard error. .TP .B \-tt timestamp. Prefix each selected line with a human readable, sortable UTC timestamp of the form YYYY-MM-DD_HH:MM:SS.xxxxx when writing to .I log or to standard error. .TP .B \-ttt timestamp. Prefix each selected line with a human readable, sortable UTC timestamp of the form YYYY-MM-DDTHH:MM:SS.xxxxx when writing to .I log or to standard error. .TP .B \-r \fIc replace. .I c must be a single character. Replace non-printable characters in log messages with .IR c . Characters are replaced before pattern matching is applied. .TP .B \-R \fIxyz replace charset. Additionally to non-printable characters, replace all characters found in .I xyz with .I c (default ``_''). .TP .B \-l \fIlen line length. Pattern matching applies to the first .I len characters of a log message only. Default is 1000. .TP .B \-b \fIbuflen buffer size. Set the size of the buffer .B svlogd uses when reading from standard input and writing to .I logs to .IR buflen . Default is 1024. .I buflen must be greater than .IR len . For .B svlogd instances that process a lot of data in short time, the buffer size should be increased to improve performance. .TP .B \-v verbose. Print verbose messages to standard error. .SH SIGNALS If .B svlogd is sent a HUP signal, it closes and reopens all .IR logs , and updates their configuration according to .IR log/config . If .B svlogd has trouble opening a log directory, it prints a warning, and discards this log directory. If .B svlogd is unable to open all log directories given at the command line, it exits with an error. .P If .B svlogd is sent a TERM signal, or if it sees end-of-file on standard input, it stops reading standard input, processes the data in the buffer, waits for all .I processor subprocesses to finish if any, and exits 0 as soon as possible. .P If .B svlogd is sent an ALRM signal, it forces log file rotation for all .I logs with a non empty .I current log file. .SH SEE ALSO sv(8), runsv(8), chpst(8), runit(8), runit-init(8), runsvdir(8), runsvchdir(8) .P http://smarden.org/runit/ .SH AUTHOR Gerrit Pape admin/runit-2.2.0/man/chpst.80000644000000000000000000001112014675400254014431 0ustar rootroot.TH chpst 8 .SH NAME chpst \- runs a program with a changed process state .SH SYNOPSIS .B chpst [\-vVP012] [\-u .IR user ] [\-U .IR user ] [\-b .IR argv0 ] [-e .IR dir ] [\-/ .IR root ] [\-C .IR pwd ] [\-n .IR inc ] [-l|-L .IR lock ] [-m .IR bytes ] [-d .IR bytes ] [-o .IR n ] [-p .IR n ] [-f .IR bytes ] [-c .IR bytes ] [-t .IR seconds ] .I prog .SH DESCRIPTION .I prog consists of one or more arguments. .P .B chpst changes the process state according to the given options, and runs .IR prog . .SH OPTIONS .TP .B \-u \fI[:]user[:group] setuidgid. Set uid and gid to the .IR user 's uid and gid, as found in .IR /etc/passwd . If .I user is followed by a colon and a .IR group , set the gid to .IR group 's gid, as found in .IR /etc/group , instead of .IR user 's gid. If .I group consists of a colon-separated list of group names, .B chpst sets the group ids of all listed groups. If .I user is prefixed with a colon, the .I user and all .I group arguments are interpreted as uid and gids respectively, and not looked up in the password or group file. All initial supplementary groups are removed. .TP .B \-U \fI[:]user[:group] envuidgid. Set the environment variables $UID and $GID to the .IR user 's uid and gid, as found in .IR /etc/passwd . If .I user is followed by a colon and a .IR group , set $GID to the .IR group 's gid, as found in .IR /etc/group , instead of .IR user 's gid. If .I user is prefixed with a colon, the .I user and .I group arguments are interpreted as uid and gid respectively, and not looked up in the password or group file. .TP .B \-b \fIargv0 argv0. Run .I prog with .I argv0 as the 0th argument. .TP .B \-e \fIdir envdir. Set various environment variables as specified by files in the directory .IR dir : If .I dir contains a file named .I k whose first line is .IR v , .B chpst removes the environment variable .I k if it exists, and then adds the environment variable .I k with the value .IR v . The name .I k must not contain =. Spaces and tabs at the end of .I v are removed, and nulls in .I v are changed to newlines. If the file .I k is empty (0 bytes long), .B chpst removes the environment variable .I k if it exists, without adding a new variable. .TP .B \-/ \fIroot chroot. Change the root directory to .I root before starting .IR prog . .TP .B \-C \fIpwd chdir. Change the working directory to .I pwd before starting .IR prog . When combined with \-/, the working directory is changed after the chroot. .TP .B \-n \fIinc nice. Add .I inc to the .BR nice (2) value before starting .IR prog . .I inc must be an integer, and may start with a minus or plus. .TP .B \-l \fIlock lock. Open the file .I lock for writing, and obtain an exclusive lock on it. .I lock will be created if it does not exist. If .I lock is locked by another process, wait until a new lock can be obtained. .TP .B \-L \fIlock The same as \-l, but fail immediately if .I lock is locked by another process. .TP .B \-m \fIbytes limit memory. Limit the data segment, stack segment, locked physical pages, and total of all segment per process to .I bytes bytes each. .TP .B \-d \fIbytes limit data segment. Limit the data segment per process to .I bytes bytes. .TP .B \-o \fIn limit open files. Limit the number of open file descriptors per process to .IR n . .TP .B \-p \fIn limit processes. Limit the number of processes per uid to .IR n . .TP .B \-f \fIbytes limit output size. Limit the output file size to .I bytes bytes. .TP .B \-c \fIbytes limit core size. Limit the core file size to .I bytes bytes. .TP .B \-t \fIseconds limit CPU time. Limit CPU time to .I seconds seconds, delivering a SIGXCPU thereafter. .TP .B \-v verbose. Print verbose messages to standard error. This includes warnings about limits unsupported by the system. .TP .B \-V version string. Print a version string to standard error. .TP .B \-P pgrphack. Run .I prog in a new process group. .TP .B \-0 Close standard input before starting .IR prog . .TP .B \-1 Close standard output before starting .IR prog . .TP .B \-2 Close standard error before starting .IR prog . .SH EXIT CODES .B chpst exits 100 when called with wrong options. It prints an error message and exits 111 if it has trouble changing the process state. Otherwise its exit code is the same as that of .IR prog . .SH EMULATION If .B chpst is called as .BR envdir , .BR envuidgid , .BR pgrphack , .BR setlock , .BR setuidgid , or .BR softlimit , it emulates the functionality of these programs from the daemontools package respectively. .SH SEE ALSO sv(8), runsv(8), setsid(2), runit(8), runit-init(8), runsvdir(8), runsvchdir(8) .P http://smarden.org/runit/ http://cr.yp.to/daemontools.html .SH AUTHOR Gerrit Pape admin/runit-2.2.0/man/runsvchdir.80000644000000000000000000000164314675400254015510 0ustar rootroot.TH runsvchdir 8 .SH NAME runsvchdir \- change services directory of runsvdir(8) .SH SYNOPSIS .B runsvchdir .I dir .SH DESCRIPTION .I dir is a services directory for the use with .BR runsvdir (8). If .I dir does not start with a slash, it is searched in /etc/runit/runsvdir/. .I dir must not start with a dot. .P .B runsvchdir switches to the directory .IR /etc/runit/runsvdir/ , copies .I current to .IR previous , and replaces .I current with a symlink pointing to .IR dir . .P Normally .I /service is a symlink to .IR current , and .BR runsvdir (8) is running .IR /service/ . .SH EXIT CODES .B runsvchdir prints an error message and exits 111 on error. .B runsvchdir exits 0 on success. .SH FILES /etc/runit/runsvdir/previous /etc/runit/runsvdir/current /etc/runit/runsvdir/current.new .SH SEE ALSO runsvdir(8), runit(8), runit-init(8), sv(8), runsv(8) .P http://smarden.org/runit/ .SH AUTHOR Gerrit Pape admin/runit-2.2.0/man/runit.80000644000000000000000000000401614675400254014457 0ustar rootroot.TH runit 8 .SH NAME runit \- a UNIX process no 1 .SH SYNOPSIS .B runit .SH DESCRIPTION .B runit must be run as Unix process no 1. It performs the system's booting, running, and shutdown in three stages: .SH STAGE 1 .B runit runs .I /etc/runit/1 and waits for it to terminate. The system's one time tasks are done here. .I /etc/runit/1 has full control of .I /dev/console to be able to start an emergency shell if the one time initialization tasks fail. If .I /etc/runit/1 crashes, or exits 100, .B runit will skip stage 2 and enter stage 3. .SH STAGE 2 .B runit runs .IR /etc/runit/2 , which should not return until system shutdown; if it crashes, or exits 111, it will be restarted. Normally .I /etc/runit/2 starts .BR runsvdir (8). .B runit is able to handle the ctrl-alt-del keyboard request in stage 2, see below. .SH STAGE 3 If .B runit is told to shutdown the system, or stage 2 returns, it terminates stage 2 if it is running, and runs .IR /etc/runit/3 . The systems tasks to shutdown and possibly halt or reboot the system are done here. If stage 3 returns, .B runit checks if the file .I /etc/runit/reboot exists and has the execute by owner permission set. If so, the system is rebooted, it's halted otherwise. If .I /etc/runit/nosync exists, .B runit doesn't invoke sync(). This is useful in vservers. .SH CTRL-ALT-DEL If .B runit receives the ctrl-alt-del keyboard request and the file .I /etc/runit/ctrlaltdel exists and has the execute by owner permission set, .B runit runs .IR /etc/runit/ctrlaltdel , waits for it to terminate, and then sends itself a CONT signal. .SH SIGNALS .B runit only accepts signals in stage 2. .P If .B runit receives a CONT signal and the file .I /etc/runit/stopit exists and has the execute by owner permission set, .B runit is told to shutdown the system. .P if .B runit receives an INT signal, a ctrl-alt-del keyboard request is triggered. .SH SEE ALSO runit-init(8), runsvdir(8), runsvchdir(8), sv(8), runsv(8), chpst(8), utmpset(8), svlogd(8) .P http://smarden.org/runit/ .SH AUTHOR Gerrit Pape admin/runit-2.2.0/man/runit-init.80000644000000000000000000000232414675400254015420 0ustar rootroot.TH runit-init 8 .SH NAME init \- a UNIX process no 1 .SH SYNOPSIS .B init [ 0 | 6 ] .SH DESCRIPTION .B runit-init is the first process the kernel starts. If .B runit-init is started as process no 1, it runs and replaces itself with .BR runit (8). .P If .B runit-init is started while the system is up, it must be either called as .B init 0 or .B init 6\fR: .TP .B init 0 tells the Unix process no 1 to shutdown and halt the system. To signal .BR runit (8) the system halt request, .B runit-init removes all permissions of the file .I /etc/runit/reboot (chmod 0), and sets the execute by owner permission of the file .I /etc/runit/stopit (chmod 100). Then a CONT signal is sent to .BR runit (8). .TP .B init 6 tells the Unix process no 1 to shutdown and reboot the system. To signal .BR runit (8) the system reboot request, .B runit-init sets the execute by owner permission of the files .I /etc/runit/reboot and .I /etc/runit/stopit (chmod 100). Then a CONT signal is sent to .BR runit (8). .SH EXIT CODES .B runit-init returns 111 on error, 0 in all other cases. .SH SEE ALSO runit(8), runsvdir(8), runsvchdir(8), sv(8), runsv(8), chpst(8), utmpset(8), svlogd(8) .P http://smarden.org/runit/ .SH AUTHOR Gerrit Pape