├── 1 ├── 2 ├── 3 ├── .gitignore ├── Makefile ├── README.md ├── core-services ├── 00-pseudofs.sh ├── 01-static-devnodes.sh ├── 02-kmods.sh ├── 02-udev.sh ├── 03-console-setup.sh ├── 03-filesystems.sh ├── 04-swap.sh ├── 05-misc.sh ├── 08-sysctl.sh ├── 10-runit-control.sh ├── 97-dmesg.sh ├── 98-sbin-merge.sh └── 99-cleanup.sh ├── crypt.awk ├── ctrlaltdel ├── dracut └── 10-runit-void.conf ├── functions ├── halt.8 ├── halt.c ├── modules-load ├── modules-load.8 ├── pause.1 ├── pause.c ├── rc.conf ├── rc.local ├── rc.shutdown ├── runsvdir ├── current ├── default │ ├── agetty-tty1 │ ├── agetty-tty2 │ ├── agetty-tty3 │ ├── agetty-tty4 │ ├── agetty-tty5 │ └── agetty-tty6 └── single │ └── sulogin ├── seedrng.c ├── services ├── agetty-console │ ├── conf │ ├── finish │ ├── run │ └── supervise ├── agetty-generic │ ├── finish │ └── run ├── agetty-hvc0 │ ├── conf │ ├── finish │ ├── run │ └── supervise ├── agetty-hvsi0 │ ├── conf │ ├── finish │ ├── run │ └── supervise ├── agetty-serial │ ├── conf │ ├── finish │ └── run ├── agetty-tty1 │ ├── conf │ ├── finish │ ├── run │ └── supervise ├── agetty-tty2 │ ├── conf │ ├── finish │ ├── run │ └── supervise ├── agetty-tty3 │ ├── conf │ ├── finish │ ├── run │ └── supervise ├── agetty-tty4 │ ├── conf │ ├── finish │ ├── run │ └── supervise ├── agetty-tty5 │ ├── conf │ ├── finish │ ├── run │ └── supervise ├── agetty-tty6 │ ├── conf │ ├── finish │ ├── run │ └── supervise ├── agetty-ttyAMA0 │ ├── conf │ ├── finish │ ├── run │ └── supervise ├── agetty-ttyS0 │ ├── conf │ ├── finish │ ├── run │ └── supervise ├── agetty-ttyUSB0 │ ├── conf │ ├── finish │ ├── run │ └── supervise └── sulogin │ ├── run │ └── supervise ├── shutdown ├── shutdown.8 ├── shutdown.d ├── 10-sv-stop.sh ├── 20-rc-shutdown.sh ├── 30-seedrng.sh ├── 40-hwclock.sh ├── 50-wtmp.sh ├── 60-udev.sh ├── 70-pkill.sh ├── 80-filesystems.sh └── 90-kexec.sh ├── vlogger.8 ├── vlogger.c ├── zzz └── zzz.8 /1: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # vim: set ts=4 sw=4 et: 3 | 4 | PATH=/usr/bin:/usr/sbin 5 | 6 | . /etc/runit/functions 7 | 8 | msg "Welcome to Void!" 9 | 10 | [ -r /etc/rc.conf ] && . /etc/rc.conf 11 | 12 | # Start core services: one-time system tasks. 13 | detect_container 14 | for f in /etc/runit/core-services/*.sh; do 15 | [ -r $f ] && . $f 16 | done 17 | 18 | msg "Initialization complete, running stage 2..." 19 | -------------------------------------------------------------------------------- /2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # vim: set ts=4 sw=4 et: 3 | 4 | PATH=/usr/bin:/usr/sbin 5 | 6 | runlevel=default 7 | for arg in $(cat /proc/cmdline); do 8 | if [ -d /etc/runit/runsvdir/"$arg" ]; then 9 | echo "Runlevel detected: '$arg' (via kernel cmdline)" 10 | runlevel="$arg" 11 | fi 12 | done 13 | 14 | [ -x /etc/rc.local ] && /etc/rc.local 15 | 16 | runsvchdir "${runlevel}" 17 | mkdir -p /run/runit/runsvdir 18 | ln -s /etc/runit/runsvdir/current /run/runit/runsvdir/current 19 | 20 | exec env - PATH=$PATH \ 21 | runsvdir -P /run/runit/runsvdir/current 'log: ...........................................................................................................................................................................................................................................................................................................................................................................................................' 22 | -------------------------------------------------------------------------------- /3: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # vim: set ts=4 sw=4 et: 3 | 4 | PATH=/usr/bin:/usr/sbin 5 | 6 | . /etc/runit/functions 7 | detect_container 8 | [ -r /etc/rc.conf ] && . /etc/rc.conf 9 | echo 10 | for f in /etc/runit/shutdown.d/*.sh; do 11 | [ -r $f ] && . $f 12 | done 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | halt 2 | pause 3 | vlogger 4 | seedrng 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr/local 2 | SCRIPTS= 1 2 3 ctrlaltdel 3 | 4 | all: 5 | $(CC) $(CFLAGS) halt.c -o halt $(LDFLAGS) 6 | $(CC) $(CFLAGS) pause.c -o pause $(LDFLAGS) 7 | $(CC) $(CFLAGS) vlogger.c -o vlogger $(LDFLAGS) 8 | $(CC) $(CFLAGS) seedrng.c -o seedrng $(LDFLAGS) 9 | 10 | install: 11 | install -d ${DESTDIR}/${PREFIX}/sbin 12 | install -m755 halt ${DESTDIR}/${PREFIX}/sbin 13 | install -m755 pause ${DESTDIR}/${PREFIX}/sbin 14 | install -m755 vlogger ${DESTDIR}/${PREFIX}/sbin 15 | install -m755 shutdown ${DESTDIR}/${PREFIX}/sbin/shutdown 16 | install -m755 modules-load ${DESTDIR}/${PREFIX}/sbin/modules-load 17 | install -m755 seedrng ${DESTDIR}/${PREFIX}/sbin/seedrng 18 | install -m755 zzz ${DESTDIR}/${PREFIX}/sbin 19 | ln -sf zzz ${DESTDIR}/${PREFIX}/sbin/ZZZ 20 | ln -sf halt ${DESTDIR}/${PREFIX}/sbin/poweroff 21 | ln -sf halt ${DESTDIR}/${PREFIX}/sbin/reboot 22 | install -d ${DESTDIR}/${PREFIX}/share/man/man1 23 | install -m644 pause.1 ${DESTDIR}/${PREFIX}/share/man/man1 24 | install -d ${DESTDIR}/${PREFIX}/share/man/man8 25 | install -m644 zzz.8 ${DESTDIR}/${PREFIX}/share/man/man8 26 | install -m644 shutdown.8 ${DESTDIR}/${PREFIX}/share/man/man8 27 | install -m644 halt.8 ${DESTDIR}/${PREFIX}/share/man/man8 28 | install -m644 modules-load.8 ${DESTDIR}/${PREFIX}/share/man/man8 29 | install -m644 vlogger.8 ${DESTDIR}/${PREFIX}/share/man/man8 30 | ln -sf halt.8 ${DESTDIR}/${PREFIX}/share/man/man8/poweroff.8 31 | ln -sf halt.8 ${DESTDIR}/${PREFIX}/share/man/man8/reboot.8 32 | install -d ${DESTDIR}/etc/sv 33 | install -d ${DESTDIR}/etc/runit/runsvdir 34 | install -d ${DESTDIR}/etc/runit/core-services 35 | install -d ${DESTDIR}/etc/runit/shutdown.d 36 | install -m644 core-services/*.sh ${DESTDIR}/etc/runit/core-services 37 | install -m644 shutdown.d/*.sh ${DESTDIR}/etc/runit/shutdown.d 38 | install -m755 ${SCRIPTS} ${DESTDIR}/etc/runit 39 | install -m644 functions $(DESTDIR)/etc/runit 40 | install -m644 crypt.awk ${DESTDIR}/etc/runit 41 | install -m644 rc.conf ${DESTDIR}/etc 42 | install -m755 rc.local ${DESTDIR}/etc 43 | install -m755 rc.shutdown ${DESTDIR}/etc 44 | install -d ${DESTDIR}/${PREFIX}/lib/dracut/dracut.conf.d 45 | install -m644 dracut/*.conf ${DESTDIR}/${PREFIX}/lib/dracut/dracut.conf.d 46 | ln -sf /run/runit/reboot ${DESTDIR}/etc/runit/ 47 | ln -sf /run/runit/stopit ${DESTDIR}/etc/runit/ 48 | cp -R --no-dereference --preserve=mode,links -v runsvdir/* ${DESTDIR}/etc/runit/runsvdir/ 49 | cp -R --no-dereference --preserve=mode,links -v services/* ${DESTDIR}/etc/sv/ 50 | 51 | clean: 52 | -rm -f halt pause vlogger 53 | 54 | .PHONY: all install clean 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Runit init scripts for void 2 | 3 | This repository contains the runit init scripts for the Void Linux distribution. 4 | 5 | This is loosely based on https://github.com/chneukirchen/ignite but with the 6 | difference that I'm trying to avoid the bash dependency. 7 | 8 | ## Dependencies 9 | 10 | - A POSIX shell 11 | - A POSIX awk 12 | - procps-ng (needs pkill -s0,1) 13 | - runit 14 | 15 | ### How to use it 16 | 17 | runit is used by default in the Void distribution. 18 | 19 | To see enabled services for "current" runlevel: 20 | 21 | $ ls -l /var/service/ 22 | 23 | To see available runlevels (default and single, which just runs sulogin): 24 | 25 | $ ls -l /etc/runit/runsvdir 26 | 27 | To enable and start a service into the "current" runlevel: 28 | 29 | # ln -s /etc/sv/ /var/service 30 | 31 | To disable and remove a service: 32 | 33 | # rm -f /var/service/ 34 | 35 | To view status of all services for "current" runlevel: 36 | 37 | # sv status /var/service/* 38 | 39 | Feel free to send patches and contribute with improvements! 40 | 41 | ## Copyright 42 | 43 | void-runit is in the public domain. 44 | 45 | To the extent possible under law, the creator of this work has waived 46 | all copyright and related or neighboring rights to this work. 47 | 48 | http://creativecommons.org/publicdomain/zero/1.0/ 49 | -------------------------------------------------------------------------------- /core-services/00-pseudofs.sh: -------------------------------------------------------------------------------- 1 | # vim: set ts=4 sw=4 et: 2 | 3 | msg "Mounting pseudo-filesystems..." 4 | mountpoint -q /proc || mount -o nosuid,noexec,nodev -t proc proc /proc 5 | mountpoint -q /sys || mount -o nosuid,noexec,nodev -t sysfs sys /sys 6 | mountpoint -q /run || mount -o mode=0755,nosuid,nodev -t tmpfs run /run 7 | mountpoint -q /dev || mount -o mode=0755,nosuid -t devtmpfs dev /dev 8 | mkdir -p -m0755 /run/runit /run/lvm /run/user /run/lock /run/log /dev/pts /dev/shm 9 | mountpoint -q /dev/pts || mount -o mode=0620,gid=5,nosuid,noexec -n -t devpts devpts /dev/pts 10 | mountpoint -q /dev/shm || mount -o mode=1777,nosuid,nodev -n -t tmpfs shm /dev/shm 11 | mountpoint -q /sys/kernel/security || mount -n -t securityfs securityfs /sys/kernel/security 12 | 13 | if [ -d /sys/firmware/efi/efivars ]; then 14 | mountpoint -q /sys/firmware/efi/efivars || mount -o nosuid,noexec,nodev -t efivarfs efivarfs /sys/firmware/efi/efivars 15 | fi 16 | 17 | if [ -z "$IS_CONTAINER" ]; then 18 | _cgroupv1="" 19 | _cgroupv2="" 20 | 21 | case "${CGROUP_MODE:-unified}" in 22 | legacy) 23 | _cgroupv1="/sys/fs/cgroup" 24 | ;; 25 | hybrid) 26 | _cgroupv1="/sys/fs/cgroup" 27 | _cgroupv2="${_cgroupv1}/unified" 28 | ;; 29 | unified) 30 | _cgroupv2="/sys/fs/cgroup" 31 | ;; 32 | esac 33 | 34 | # cgroup v1 35 | if [ -n "$_cgroupv1" ]; then 36 | mountpoint -q "$_cgroupv1" || mount -o mode=0755 -t tmpfs cgroup "$_cgroupv1" 37 | while read -r _subsys_name _hierarchy _num_cgroups _enabled; do 38 | [ "$_enabled" = "1" ] || continue 39 | _controller="${_cgroupv1}/${_subsys_name}" 40 | mkdir -p "$_controller" 41 | mountpoint -q "$_controller" || mount -t cgroup -o "$_subsys_name" cgroup "$_controller" 42 | done < /proc/cgroups 43 | # always mount the systemd tracking cgroup, 44 | # to support containerized systemd instances 45 | mkdir -p /sys/fs/cgroup/systemd 46 | mountpoint -q /sys/fs/cgroup/systemd || \ 47 | mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd 48 | fi 49 | 50 | # cgroup v2 51 | if [ -n "$_cgroupv2" ]; then 52 | mkdir -p "$_cgroupv2" 53 | mountpoint -q "$_cgroupv2" || \ 54 | mount -t cgroup2 -o nsdelegate cgroup2 "$_cgroupv2" 55 | fi 56 | else 57 | # in containers, unless otherwise configured, 58 | # attempt to mount cgroup2 at the standard path, 59 | # but never fail 60 | if [ "${CGROUP_MODE:-unified}" = "unified" ]; then 61 | _cgroup2="/sys/fs/cgroup" 62 | mkdir -p "$_cgroup2" 63 | mountpoint -q "$_cgroup2" || \ 64 | mount -t cgroup2 -o nsdelegate cgroup2 "$_cgroup2" || true 65 | fi 66 | fi 67 | -------------------------------------------------------------------------------- /core-services/01-static-devnodes.sh: -------------------------------------------------------------------------------- 1 | # Some kernel modules must be loaded before starting udev(7). 2 | # Load them by looking at the output of `kmod static-nodes`. 3 | 4 | for f in $(kmod static-nodes -f devname 2>/dev/null|cut -d' ' -f1); do 5 | modprobe -bq $f 2>/dev/null 6 | done 7 | -------------------------------------------------------------------------------- /core-services/02-kmods.sh: -------------------------------------------------------------------------------- 1 | # vim: set ts=4 sw=4 et: 2 | 3 | [ -n "$IS_CONTAINER" ] && return 0 4 | 5 | # Do not try to load modules if kernel does not support them. 6 | [ ! -e /proc/modules ] && return 0 7 | 8 | msg "Loading kernel modules..." 9 | modules-load -v | tr '\n' ' ' | sed 's:insmod [^ ]*/::g; s:\.ko\(\.gz\)\? ::g' 10 | echo 11 | -------------------------------------------------------------------------------- /core-services/02-udev.sh: -------------------------------------------------------------------------------- 1 | # vim: set ts=4 sw=4 et: 2 | 3 | [ -n "$IS_CONTAINER" ] && return 0 4 | 5 | if [ -x /usr/lib/systemd/systemd-udevd ]; then 6 | _udevd=/usr/lib/systemd/systemd-udevd 7 | elif [ -x /sbin/udevd -o -x /bin/udevd ]; then 8 | _udevd=udevd 9 | else 10 | msg_warn "cannot find udevd!" 11 | fi 12 | 13 | if [ -n "${_udevd}" ]; then 14 | msg "Starting udev and waiting for devices to settle..." 15 | ${_udevd} --daemon 16 | udevadm trigger --action=add --type=subsystems 17 | udevadm trigger --action=add --type=devices 18 | udevadm settle 19 | fi 20 | -------------------------------------------------------------------------------- /core-services/03-console-setup.sh: -------------------------------------------------------------------------------- 1 | # vim: set ts=4 sw=4 et: 2 | 3 | [ -n "$IS_CONTAINER" ] && return 0 4 | 5 | TTYS=${TTYS:-12} 6 | if [ -n "$FONT" ]; then 7 | msg "Setting up TTYs font to '${FONT}'..." 8 | 9 | _index=0 10 | while [ ${_index} -le $TTYS ]; do 11 | setfont ${FONT_MAP:+-m $FONT_MAP} ${FONT_UNIMAP:+-u $FONT_UNIMAP} \ 12 | $FONT -C "/dev/tty${_index}" 13 | _index=$((_index + 1)) 14 | done 15 | fi 16 | 17 | if [ -n "$KEYMAP" ]; then 18 | msg "Setting up keymap to '${KEYMAP}'..." 19 | loadkeys -q -u ${KEYMAP} 20 | fi 21 | 22 | if [ -n "$HARDWARECLOCK" ]; then 23 | msg "Setting up RTC to '${HARDWARECLOCK}'..." 24 | TZ=$TIMEZONE hwclock --systz \ 25 | ${HARDWARECLOCK:+--$(echo $HARDWARECLOCK |tr A-Z a-z) --noadjfile} || emergency_shell 26 | fi 27 | -------------------------------------------------------------------------------- /core-services/03-filesystems.sh: -------------------------------------------------------------------------------- 1 | # vim: set ts=4 sw=4 et: 2 | 3 | [ -n "$IS_CONTAINER" ] && return 0 4 | 5 | msg "Remounting rootfs read-only..." 6 | LIBMOUNT_FORCE_MOUNT2=always mount -o remount,ro / || emergency_shell 7 | 8 | if [ -x /sbin/dmraid -o -x /bin/dmraid ]; then 9 | msg "Activating dmraid devices..." 10 | dmraid -i -ay 11 | fi 12 | 13 | if [ -x /bin/mdadm ]; then 14 | msg "Activating software RAID arrays..." 15 | mdadm -As 16 | fi 17 | 18 | if [ -x /bin/btrfs ]; then 19 | msg "Activating btrfs devices..." 20 | btrfs device scan || emergency_shell 21 | fi 22 | 23 | if [ -x /sbin/vgchange -o -x /bin/vgchange ]; then 24 | msg "Activating LVM devices..." 25 | vgchange --sysinit -a ay || emergency_shell 26 | fi 27 | 28 | if [ -e /etc/crypttab ]; then 29 | msg "Activating encrypted devices..." 30 | awk -f /etc/runit/crypt.awk /etc/crypttab 31 | 32 | if [ -x /sbin/vgchange -o -x /bin/vgchange ]; then 33 | msg "Activating LVM devices for dm-crypt..." 34 | vgchange --sysinit -a ay || emergency_shell 35 | fi 36 | fi 37 | 38 | if [ -x /usr/bin/zpool -a -x /usr/bin/zfs ]; then 39 | if [ -e /etc/zfs/zpool.cache ]; then 40 | msg "Importing cached ZFS pools..." 41 | zpool import -N -a -c /etc/zfs/zpool.cache 42 | else 43 | msg "Scanning for and importing ZFS pools..." 44 | zpool import -N -a -o cachefile=none 45 | fi 46 | 47 | msg "Mounting ZFS file systems..." 48 | zfs mount -a -l 49 | 50 | msg "Sharing ZFS file systems..." 51 | zfs share -a 52 | 53 | # NOTE(dh): ZFS has ZVOLs, block devices on top of storage pools. 54 | # In theory, it would be possible to use these as devices in 55 | # dmraid, btrfs, LVM and so on. In practice it's unlikely that 56 | # anybody is doing that, so we aren't supporting it for now. 57 | fi 58 | 59 | [ -f /fastboot ] && FASTBOOT=1 60 | [ -f /forcefsck ] && FORCEFSCK="-f" 61 | for arg in $(cat /proc/cmdline); do 62 | case $arg in 63 | fastboot) FASTBOOT=1;; 64 | forcefsck) FORCEFSCK="-f";; 65 | esac 66 | done 67 | 68 | if [ -z "$FASTBOOT" ]; then 69 | msg "Checking filesystems:" 70 | fsck -A -T -a -t noopts=_netdev $FORCEFSCK 71 | if [ $? -gt 1 ]; then 72 | emergency_shell 73 | fi 74 | fi 75 | 76 | msg "Mounting rootfs read-write..." 77 | LIBMOUNT_FORCE_MOUNT2=always mount -o remount,rw / || emergency_shell 78 | 79 | msg "Mounting all non-network filesystems..." 80 | mount -a -t "nosysfs,nonfs,nonfs4,nosmbfs,nocifs" -O no_netdev || emergency_shell 81 | -------------------------------------------------------------------------------- /core-services/04-swap.sh: -------------------------------------------------------------------------------- 1 | # vim: set ts=4 sw=4 et: 2 | 3 | [ -n "$IS_CONTAINER" ] && return 0 4 | 5 | msg "Initializing swap..." 6 | swapon -a || emergency_shell 7 | -------------------------------------------------------------------------------- /core-services/05-misc.sh: -------------------------------------------------------------------------------- 1 | # vim: set ts=4 sw=4 et: 2 | 3 | install -m0664 -o root -g utmp /dev/null /run/utmp 4 | halt -B # for wtmp 5 | 6 | if [ -z "$IS_CONTAINER" ]; then 7 | msg "Seeding random number generator..." 8 | seedrng || true 9 | fi 10 | 11 | msg "Setting up loopback interface..." 12 | ip link set up dev lo 13 | 14 | [ -r /etc/hostname ] && read -r HOSTNAME < /etc/hostname 15 | if [ -n "$HOSTNAME" ]; then 16 | msg "Setting up hostname to '${HOSTNAME}'..." 17 | printf "%s" "$HOSTNAME" > /proc/sys/kernel/hostname 18 | else 19 | msg_warn "Didn't setup a hostname!" 20 | fi 21 | 22 | if [ -n "$TIMEZONE" ]; then 23 | msg "Setting up timezone to '${TIMEZONE}'..." 24 | ln -sf "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime 25 | fi 26 | -------------------------------------------------------------------------------- /core-services/08-sysctl.sh: -------------------------------------------------------------------------------- 1 | # vim: set ts=4 sw=4 et: 2 | 3 | if [ -x /sbin/sysctl -o -x /bin/sysctl ]; then 4 | msg "Loading sysctl(8) settings..." 5 | mkdir -p /run/vsysctl.d 6 | for i in /run/sysctl.d/*.conf \ 7 | /etc/sysctl.d/*.conf \ 8 | /usr/local/lib/sysctl.d/*.conf \ 9 | /usr/lib/sysctl.d/*.conf; do 10 | 11 | if [ -e "$i" ] && [ ! -e "/run/vsysctl.d/${i##*/}" ]; then 12 | ln -s "$i" "/run/vsysctl.d/${i##*/}" 13 | fi 14 | done 15 | for i in /run/vsysctl.d/*.conf; do 16 | sysctl -p "$i" 17 | done 18 | rm -rf -- /run/vsysctl.d 19 | sysctl -p /etc/sysctl.conf 20 | fi 21 | -------------------------------------------------------------------------------- /core-services/10-runit-control.sh: -------------------------------------------------------------------------------- 1 | # vim: set ts=4 sw=4 et: 2 | 3 | # create files for controlling runit 4 | mkdir -p /run/runit 5 | install -m000 /dev/null /run/runit/stopit 6 | install -m000 /dev/null /run/runit/reboot 7 | -------------------------------------------------------------------------------- /core-services/97-dmesg.sh: -------------------------------------------------------------------------------- 1 | # vim: set ts=4 sw=4 et: 2 | 3 | dmesg >/var/log/dmesg.log 4 | if [ $(sysctl -n kernel.dmesg_restrict 2>/dev/null) -eq 1 ]; then 5 | chmod 0600 /var/log/dmesg.log 6 | else 7 | chmod 0644 /var/log/dmesg.log 8 | fi 9 | -------------------------------------------------------------------------------- /core-services/98-sbin-merge.sh: -------------------------------------------------------------------------------- 1 | if [ -d /usr/sbin -a ! -L /usr/sbin ]; then 2 | for f in /usr/sbin/*; do 3 | if [ -f $f -a ! -L $f ]; then 4 | msg "Detected $f file, can't create /usr/sbin symlink." 5 | return 0 6 | fi 7 | done 8 | msg "Creating /usr/sbin -> /usr/bin symlink, moving existing to /usr/sbin.old" 9 | mv /usr/sbin /usr/sbin.old 10 | ln -sf bin /usr/sbin 11 | fi 12 | -------------------------------------------------------------------------------- /core-services/99-cleanup.sh: -------------------------------------------------------------------------------- 1 | # vim: set ts=4 sw=4 et: 2 | 3 | if [ ! -e /var/log/wtmp ]; then 4 | install -m0664 -o root -g utmp /dev/null /var/log/wtmp 5 | fi 6 | if [ ! -e /var/log/btmp ]; then 7 | install -m0600 -o root -g utmp /dev/null /var/log/btmp 8 | fi 9 | if [ ! -e /var/log/lastlog ]; then 10 | install -m0600 -o root -g utmp /dev/null /var/log/lastlog 11 | fi 12 | install -dm1777 /tmp/.X11-unix /tmp/.ICE-unix 13 | rm -f /etc/nologin /forcefsck /forcequotacheck /fastboot 14 | -------------------------------------------------------------------------------- /crypt.awk: -------------------------------------------------------------------------------- 1 | /^#/ || /^$/ { next } 2 | NF>4 { print "a valid crypttab has max 4 cols not " NF >"/dev/stderr"; next } 3 | { 4 | # decode the src variants 5 | split($2, o_src, "=") 6 | if (o_src[1] == "UUID" || o_src[1] == "PARTUUID") ("blkid -l -o device -t " $2) | getline src; 7 | else src=o_src[1]; 8 | 9 | # no password or none is given, ask fo it 10 | if ( NF == 2 ) { 11 | ccmd="cryptsetup luksOpen " src " " $1; 12 | system(ccmd); 13 | ccmd=""; 14 | } 15 | else if (NF == 3 ) { 16 | dest=$1 17 | key=$3 18 | split($3, po, "="); 19 | if ( po[1] == "none") ccmd="cryptsetup luksOpen " src " " dest; 20 | else ccmd="cryptsetup luksOpen -d " key " " src" " dest; 21 | system(ccmd); 22 | ccmd=""; 23 | } 24 | else { 25 | # the option field is not empty parse the options 26 | dest=$1 27 | key=$3 28 | split($4, opts, ","); 29 | commonopts=""; 30 | swapopts=""; 31 | luksopts=""; 32 | for(i in opts) { 33 | split(opts[i], para, "="); 34 | par=para[1]; 35 | val=para[2]; 36 | if ( par == "readonly" || par == "read-only") commonopts=commonopts "-r "; 37 | else if ( par == "discard" ) commonopts=commonopts "--allow-discards "; 38 | else if ( par == "no-read-workqueue" ) commonopts=commonopts "--perf-no_read_workqueue "; 39 | else if ( par == "no-write-workqueue" ) commonopts=commonopts "--perf-no_write_workqueue "; 40 | else if ( par == "tries" ) commonopts=commonopts "-T " val " "; 41 | else if ( par == "swap" ) makeswap="y"; 42 | else if ( par == "cipher" ) swapopts=swapopts "-c " val " "; 43 | else if ( par == "size" ) swapopts=swapopts "-s " val " "; 44 | else if ( par == "hash" ) swapopts=swapopts "-h " val " "; 45 | else if ( par == "offset" ) swapopts=swapopts "-o " val " "; 46 | else if ( par == "skip" ) swapopts=swapopts "-p " val " "; 47 | else if ( par == "verify" ) swapopts=swapopts "-y "; 48 | #else if ( par == "noauto" ) 49 | #else if ( par == "nofail" ) 50 | #else if ( par == "plain" ) 51 | #else if ( par == "timeout" ) 52 | #else if ( par == "tmp" ) 53 | else if ( par == "luks" ) use_luks="y"; 54 | else if ( par == "keyscript" ) {use_keyscript="y"; keyscript=val;} 55 | else if ( par == "keyslot" || par == "key-slot" ) luksopts=luksopts "-S " val " "; 56 | else if ( par == "keyfile-size" ) luksopts=luksopts "-l " val " "; 57 | else if ( par == "keyfile-offset" ) luksopts=luksopts "--keyfile-offset=" val " "; 58 | else if ( par == "header" ) luksopts=luksopts "--header=" val " "; 59 | else if ( par == "perf-same_cpu_crypt" ) commonopts=commonopts "--perf-same_cpu_crypt "; 60 | else if ( par == "perf-submit_from_crypt_cpus" ) commonopts=commonopts "--perf-submit_from_crypt_cpus "; 61 | else if ( par == "perf-no_read_workqueue" ) commonopts=commonopts "--perf-no_read_workqueue "; 62 | else if ( par == "perf-no_write_workqueue" ) commonopts=commonopts "--perf-no_write_workqueue "; 63 | else { 64 | print "option: " par " not supported " >"/dev/stderr"; 65 | makeswap=""; 66 | use_luks=""; 67 | use_keyscript=""; 68 | next; 69 | } 70 | } 71 | if ( makeswap == "y" && use_luks != "y" ) { 72 | ccmd="cryptsetup " swapopts commonopts "-d " key " create " dest " " src; 73 | ccmd_2="mkswap /dev/mapper/" dest; 74 | makeswap=""; 75 | use_luks=""; 76 | use_keyscript=""; 77 | system(ccmd); 78 | system(ccmd_2); 79 | ccmd=""; 80 | ccmd_2=""; 81 | next; 82 | } 83 | if ( use_luks == "y" && makeswap != "y" ){ 84 | if ( use_keyscript == "y") { 85 | ccmd=keyscript " | cryptsetup " luksopts commonopts "luksOpen -d - " src " " dest; 86 | use_keyscript=""; 87 | } 88 | else { 89 | if ( key == "none" ){ 90 | ccmd="cryptsetup " luksopts commonopts "luksOpen " src " " dest; 91 | } 92 | else { 93 | ccmd="cryptsetup " luksopts commonopts "luksOpen -d " key " " src " " dest; 94 | } 95 | } 96 | } 97 | else { 98 | print "use swap OR luks as option" >"/dev/stderr"; 99 | ccmd=""; 100 | } 101 | makeswap=""; 102 | use_luks=""; 103 | use_keyscript=""; 104 | if ( ccmd != ""){ 105 | system(ccmd); 106 | ccmd="" 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /ctrlaltdel: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PATH=/usr/bin:/usr/sbin 4 | MSG="System is going down..." 5 | 6 | # We check for this file after receiving a SIGCONT to move to stage3 7 | chmod 100 /run/runit/stopit 8 | 9 | # We check for this file in stage3 to halt or reboot 10 | chmod 100 /run/runit/reboot 11 | 12 | # Proceed with shutdown process 13 | echo "$MSG" | wall 14 | -------------------------------------------------------------------------------- /dracut/10-runit-void.conf: -------------------------------------------------------------------------------- 1 | add_dracutmodules+=" resume " 2 | omit_dracutmodules+=" systemd " 3 | i18n_vars="/etc/rc.conf:KEYMAP,FONT,FONT_MAP,FONT_UNIMAP" 4 | -------------------------------------------------------------------------------- /functions: -------------------------------------------------------------------------------- 1 | # *-*-shell-*-* 2 | # vim: set ts=4 sw=4 et: 3 | 4 | msg() { 5 | # bold 6 | printf "\033[1m=> $@\033[m\n" 7 | } 8 | 9 | msg_ok() { 10 | # bold/green 11 | printf "\033[1m\033[32m OK\033[m\n" 12 | } 13 | 14 | msg_error() { 15 | # bold/red 16 | printf "\033[1m\033[31mERROR: $@\033[m\n" 17 | } 18 | 19 | msg_warn() { 20 | # bold/yellow 21 | printf "\033[1m\033[33mWARNING: $@\033[m\n" 22 | } 23 | 24 | emergency_shell() { 25 | echo 26 | echo "Cannot continue due to errors above, starting emergency shell." 27 | echo "When ready type exit to continue booting." 28 | /bin/sh -l 29 | } 30 | 31 | detect_container() { 32 | # LXC, podman 33 | [ -z "${container+x}" ] || export IS_CONTAINER=1 34 | [ -e /.dockerenv ] && export IS_CONTAINER=1 35 | 36 | # backcompat 37 | [ -n "$IS_CONTAINER" ] && export VIRTUALIZATION=1 38 | } 39 | 40 | deactivate_vgs() { 41 | _group=${1:-All} 42 | if [ -x /sbin/vgchange -o -x /bin/vgchange ]; then 43 | vgs=$(vgs|wc -l) 44 | if [ $vgs -gt 0 ]; then 45 | msg "Deactivating $_group LVM Volume Groups..." 46 | vgchange -an 47 | fi 48 | fi 49 | } 50 | 51 | deactivate_crypt() { 52 | if [ -x /sbin/dmsetup -o -x /bin/dmsetup ]; then 53 | msg "Deactivating Crypt Volumes" 54 | for v in $(dmsetup ls --target crypt --exec "dmsetup info -c --noheadings -o open,name"); do 55 | [ ${v%%:*} = "0" ] && cryptsetup close ${v##*:} && msg "[crypt] successfully closed: ${v##*:}" 56 | done 57 | deactivate_vgs "Crypt" 58 | fi 59 | } 60 | -------------------------------------------------------------------------------- /halt.8: -------------------------------------------------------------------------------- 1 | .Dd September 5, 2019 2 | .Dt HALT 8 3 | .Os Linux 4 | .Sh NAME 5 | .Nm halt , 6 | .Nm reboot , 7 | .Nm poweroff 8 | .Nd stop the system 9 | .Sh SYNOPSIS 10 | .Nm halt 11 | .Op Fl n 12 | .Op Fl f 13 | .Op Fl d 14 | .Op Fl w 15 | .Op Fl B 16 | .Nm reboot 17 | .Op Fl n 18 | .Op Fl f 19 | .Nm poweroff 20 | .Op Fl n 21 | .Op Fl f 22 | .Sh DESCRIPTION 23 | .Nm halt 24 | / 25 | .Nm reboot 26 | / 27 | .Nm poweroff 28 | tells 29 | .Xr init 8 30 | to bring down, reboot, or power off the system. 31 | Without 32 | .Fl f , 33 | it is a shortcut for 34 | .Nm init 0 35 | / 36 | .Nm init 6 . 37 | .Bl -tag -width indent 38 | .It Fl n 39 | Don't sync before reboot or halt. 40 | Note that the kernel and storage drivers may still sync. 41 | .It Fl f 42 | Force halt or reboot, don't call 43 | .Xr init 8 . 44 | This is 45 | .Sy dangerous ! 46 | .It Fl d 47 | Do not write the wtmp record. 48 | .It Fl w 49 | Just write the wtmp record. 50 | .It Fl B 51 | Just write the wtmp record, but for a boot. 52 | .El 53 | .Sh UNSUPPORTED OPTIONS 54 | This version of 55 | .Nm 56 | is based on 57 | .Xr runit 8 , 58 | the following features are 59 | .Sy not 60 | supported and silently ignored: 61 | .Bl -tag -width indent 62 | .It Fl h 63 | to put hard drives in standby mode. 64 | .It Fl i 65 | to shut down network interfaces. 66 | .El 67 | .Sh SEE ALSO 68 | .Xr init 8 , 69 | .Xr shutdown 8 70 | .Sh AUTHOR 71 | .An Leah Neukirchen , 72 | .Mt leah@vuxu.org . 73 | -------------------------------------------------------------------------------- /halt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | extern char *__progname; 15 | 16 | typedef enum {NOOP, HALT, REBOOT, POWEROFF} action_type; 17 | 18 | #ifndef OUR_WTMP 19 | #define OUR_WTMP "/var/log/wtmp" 20 | #endif 21 | 22 | #ifndef OUR_UTMP 23 | #define OUR_UTMP "/run/utmp" 24 | #endif 25 | 26 | void write_wtmp(int boot) { 27 | int fd; 28 | 29 | if ((fd = open(OUR_WTMP, O_WRONLY|O_APPEND)) < 0) 30 | return; 31 | 32 | struct utmp utmp = {0}; 33 | struct utsname uname_buf; 34 | struct timeval tv; 35 | 36 | gettimeofday(&tv, 0); 37 | utmp.ut_tv.tv_sec = tv.tv_sec; 38 | utmp.ut_tv.tv_usec = tv.tv_usec; 39 | 40 | utmp.ut_type = boot ? BOOT_TIME : RUN_LVL; 41 | 42 | strncpy(utmp.ut_name, boot ? "reboot" : "shutdown", sizeof utmp.ut_name); 43 | strncpy(utmp.ut_id , "~~", sizeof utmp.ut_id); 44 | strncpy(utmp.ut_line, boot ? "~" : "~~", sizeof utmp.ut_line); 45 | if (uname(&uname_buf) == 0) 46 | strncpy(utmp.ut_host, uname_buf.release, sizeof utmp.ut_host); 47 | 48 | write(fd, (char *)&utmp, sizeof utmp); 49 | close(fd); 50 | 51 | if (boot) { 52 | if ((fd = open(OUR_UTMP, O_WRONLY|O_APPEND)) < 0) 53 | return; 54 | write(fd, (char *)&utmp, sizeof utmp); 55 | close(fd); 56 | } 57 | } 58 | 59 | int main(int argc, char *argv[]) { 60 | int do_sync = 1; 61 | int do_force = 0; 62 | int do_wtmp = 1; 63 | int opt; 64 | action_type action = NOOP; 65 | 66 | if (strncmp(__progname, "halt", 4) == 0) 67 | action = HALT; 68 | else if (strncmp(__progname, "reboot", 6) == 0) 69 | action = REBOOT; 70 | else if (strncmp(__progname, "poweroff", 8) == 0) 71 | action = POWEROFF; 72 | else 73 | warnx("no default behavior, needs to be called as halt/reboot/poweroff."); 74 | 75 | while ((opt = getopt(argc, argv, "dfhinwB")) != -1) 76 | switch (opt) { 77 | case 'n': 78 | do_sync = 0; 79 | break; 80 | case 'w': 81 | action = NOOP; 82 | do_sync = 0; 83 | break; 84 | case 'd': 85 | do_wtmp = 0; 86 | break; 87 | case 'h': 88 | case 'i': 89 | /* silently ignored. */ 90 | break; 91 | case 'f': 92 | do_force = 1; 93 | break; 94 | case 'B': 95 | write_wtmp(1); 96 | return 0; 97 | default: 98 | errx(1, "Usage: %s [-n] [-f] [-d] [-w] [-B]", __progname); 99 | } 100 | 101 | if (do_wtmp) 102 | write_wtmp(0); 103 | 104 | if (do_sync) 105 | sync(); 106 | 107 | switch (action) { 108 | case HALT: 109 | if (do_force) 110 | reboot(RB_HALT_SYSTEM); 111 | else 112 | execl("/bin/runit-init", "init", "0", (char*)0); 113 | err(1, "halt failed"); 114 | break; 115 | case POWEROFF: 116 | if (do_force) 117 | reboot(RB_POWER_OFF); 118 | else 119 | execl("/bin/runit-init", "init", "0", (char*)0); 120 | err(1, "poweroff failed"); 121 | break; 122 | case REBOOT: 123 | if (do_force) 124 | reboot(RB_AUTOBOOT); 125 | else 126 | execl("/bin/runit-init", "init", "6", (char*)0); 127 | err(1, "reboot failed"); 128 | break; 129 | case NOOP: 130 | break; 131 | } 132 | 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /modules-load: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # modules-load [-n] [-v] - modules-load.d(5) compatible kernel module loader 3 | 4 | export PATH=/bin:/sbin 5 | 6 | { 7 | # Parameters passed as modules-load= or rd.modules-load= in kernel command line. 8 | sed -nr 's/,/\n/g;s/(.* |^)(rd\.)?modules-load=([^ ]*).*/\3/p' /proc/cmdline 9 | 10 | # Find files /{etc,run,usr/lib}/modules-load.d/*.conf in that order. 11 | find -L /etc/modules-load.d /run/modules-load.d /usr/lib/modules-load.d \ 12 | -maxdepth 1 -name '*.conf' -printf '%p %P\n' 2>/dev/null | 13 | # Load each basename only once. 14 | sort -k2 -s | uniq -f1 | cut -d' ' -f1 | 15 | # Read the files, output all non-empty, non-comment lines. 16 | tr '\012' '\0' | xargs -0 -r grep -h -v -e '^[#;]' -e '^$' 17 | } | 18 | # Call modprobe on the list of modules 19 | tr '\012' '\0' | xargs -0 -r modprobe -ab "$@" 20 | -------------------------------------------------------------------------------- /modules-load.8: -------------------------------------------------------------------------------- 1 | .Dd June 1, 2016 2 | .Dt MODULES-LOAD 8 3 | .Os Linux 4 | .Sh NAME 5 | .Nm modules-load 6 | .Nd Configure kernel modules to load at boot 7 | .Sh SYNOPSIS 8 | .Nm modules-load 9 | .Op Fl nv 10 | .Sh DESCRIPTION 11 | .Nm 12 | reads files which contain kernel modules to load during boot from the list of 13 | locations below. 14 | .Bl -tag -width indent 15 | .It Fl n 16 | dry-run mode. 17 | This option does everything but actually insert or delete the modules. 18 | .It Fl v 19 | verbose mode. 20 | Print messages about what the program is doing. 21 | .El 22 | .Sh FILES 23 | Configuration files are read from the following locations: 24 | .Bl -tag -width indent 25 | .It /etc/modules-load.d/*.conf 26 | .It /run/modules-load.d/*.conf 27 | .It /usr/lib/modules-load.d/*.conf 28 | .El 29 | .Pp 30 | The configuration files should simply contain a list of kernel module names 31 | to load, separated by newlines. 32 | Empty lines and lines whose first non-whitespace character is # or ; are 33 | ignored. 34 | .Sh EXAMPLES 35 | .Pa /etc/modules-load.d/virtio-net.conf : 36 | .Bd -literal -offset indent 37 | # Load virtio-net.ko at boot 38 | virtio-net 39 | .Ed 40 | .Sh SEE ALSO 41 | .Xr modprobe 8 42 | .Sh HISTORY 43 | This program is a replacement for the 44 | .Nm modules-load 45 | utility provided by 46 | .Nm systemd . 47 | .Sh AUTHOR 48 | .An Leah Neukirchen , 49 | .Mt leah@vuxu.org . 50 | .Sh LICENSE 51 | .Nm 52 | is in the public domain. 53 | -------------------------------------------------------------------------------- /pause.1: -------------------------------------------------------------------------------- 1 | .Dd September 27, 2012 2 | .Dt PAUSE 1 3 | .Os Linux 4 | .Sh NAME 5 | .Nm pause 6 | .Nd don't exit, efficiently 7 | .Sh SYNOPSIS 8 | .Nm pause 9 | .Sh DESCRIPTION 10 | .Nm pause 11 | waits to be terminated by a signal. 12 | It can be used when service supervision is used but there is no 13 | long-running program to supervise. 14 | .Nm pause 15 | uses minimal system resources. 16 | .Sh EXAMPLES 17 | Setting up a static IP address with 18 | .Xr plugsv 8 . 19 | .Pp 20 | .Pa /etc/netsv/eth0/run : 21 | .Bd -literal -offset indent 22 | #!/bin/sh 23 | ip link set eth0 up 24 | ip addr add 192.0.2.1/24 dev eth0 25 | exec pause 26 | .Ed 27 | .Pp 28 | .Pa /etc/netsv/eth0/finish : 29 | .Bd -literal -offset indent 30 | #!/bin/sh 31 | ip addr del 192.0.2.1/24 dev eth0 32 | ip link set eth0 down 33 | .Ed 34 | .Sh SEE ALSO 35 | .Xr sleep 1 , 36 | .Xr pause 2 37 | .Sh AUTHOR 38 | .An Leah Neukirchen , 39 | .Mt leah@vuxu.org . 40 | -------------------------------------------------------------------------------- /pause.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static void 5 | nop(int sig) 6 | { 7 | } 8 | 9 | int 10 | main() 11 | { 12 | signal(SIGTERM, nop); 13 | signal(SIGINT, nop); 14 | signal(SIGHUP, SIG_IGN); 15 | 16 | pause(); 17 | 18 | return 0; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /rc.conf: -------------------------------------------------------------------------------- 1 | # /etc/rc.conf - system configuration for void 2 | 3 | # Set the host name. 4 | # 5 | # NOTE: it's preferred to declare the hostname in /etc/hostname instead: 6 | # - echo myhost > /etc/hostname 7 | # 8 | #HOSTNAME="void-live" 9 | 10 | # Set RTC to UTC or localtime. 11 | #HARDWARECLOCK="UTC" 12 | 13 | # Set timezone, availables timezones can be found at /usr/share/zoneinfo. 14 | # 15 | # NOTE: it's preferred to set the timezone in /etc/localtime instead: 16 | # - ln -sf /usr/share/zoneinfo/ /etc/localtime 17 | # Setting the timezone here requires a reboot to apply any changes/fixes 18 | # and read-write access to the filesystem. 19 | # 20 | #TIMEZONE="Europe/Madrid" 21 | 22 | # Keymap to load, see loadkeys(8). 23 | #KEYMAP="es" 24 | 25 | # Console font to load, see setfont(8). 26 | #FONT="lat9w-16" 27 | 28 | # Console map to load, see setfont(8). 29 | #FONT_MAP= 30 | 31 | # Font unimap to load, see setfont(8). 32 | #FONT_UNIMAP= 33 | 34 | # Amount of ttys which should be setup. 35 | #TTYS= 36 | 37 | # Set the mode for cgroup mounts. 38 | # hybrid: mount cgroup v1 under /sys/fs/cgroup and 39 | # cgroup v2 under /sys/fs/cgroup/unified 40 | # legacy: mount cgroup v1 /sys/fs/cgroup 41 | # unified: mount cgroup v2 under /sys/fs/cgroup 42 | #CGROUP_MODE=unified 43 | 44 | # Set this to true only if you do not want seed files to actually credit the 45 | # RNG, for example if you plan to replicate this file system image and do not 46 | # have the wherewithal to first delete the contents of /var/lib/seedrng. 47 | #SEEDRNG_SKIP_CREDIT=false 48 | -------------------------------------------------------------------------------- /rc.local: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Default rc.local for void; add your custom commands here. 3 | # 4 | # This is run by runit in stage 2 before the services are executed 5 | # (see /etc/runit/2). 6 | -------------------------------------------------------------------------------- /rc.shutdown: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Default rc.shutdown for void; add your custom commands here. 3 | # 4 | # This is run by runit in stage 3 after the services are stopped 5 | # (see /etc/runit/3). 6 | -------------------------------------------------------------------------------- /runsvdir/current: -------------------------------------------------------------------------------- 1 | default -------------------------------------------------------------------------------- /runsvdir/default/agetty-tty1: -------------------------------------------------------------------------------- 1 | /etc/sv/agetty-tty1 -------------------------------------------------------------------------------- /runsvdir/default/agetty-tty2: -------------------------------------------------------------------------------- 1 | /etc/sv/agetty-tty2 -------------------------------------------------------------------------------- /runsvdir/default/agetty-tty3: -------------------------------------------------------------------------------- 1 | /etc/sv/agetty-tty3 -------------------------------------------------------------------------------- /runsvdir/default/agetty-tty4: -------------------------------------------------------------------------------- 1 | /etc/sv/agetty-tty4 -------------------------------------------------------------------------------- /runsvdir/default/agetty-tty5: -------------------------------------------------------------------------------- 1 | /etc/sv/agetty-tty5 -------------------------------------------------------------------------------- /runsvdir/default/agetty-tty6: -------------------------------------------------------------------------------- 1 | /etc/sv/agetty-tty6 -------------------------------------------------------------------------------- /runsvdir/single/sulogin: -------------------------------------------------------------------------------- 1 | /etc/sv/sulogin -------------------------------------------------------------------------------- /seedrng.c: -------------------------------------------------------------------------------- 1 | /* Based on code from . */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #ifndef LOCALSTATEDIR 22 | #define LOCALSTATEDIR "/var/lib" 23 | #endif 24 | 25 | #define SEED_DIR LOCALSTATEDIR "/seedrng" 26 | #define CREDITABLE_SEED "seed.credit" 27 | #define NON_CREDITABLE_SEED "seed.no-credit" 28 | 29 | enum blake2s_lengths { 30 | BLAKE2S_BLOCK_LEN = 64, 31 | BLAKE2S_HASH_LEN = 32, 32 | BLAKE2S_KEY_LEN = 32 33 | }; 34 | 35 | enum seedrng_lengths { 36 | MAX_SEED_LEN = 512, 37 | MIN_SEED_LEN = BLAKE2S_HASH_LEN 38 | }; 39 | 40 | struct blake2s_state { 41 | uint32_t h[8]; 42 | uint32_t t[2]; 43 | uint32_t f[2]; 44 | uint8_t buf[BLAKE2S_BLOCK_LEN]; 45 | unsigned int buflen; 46 | unsigned int outlen; 47 | }; 48 | 49 | #define le32_to_cpup(a) le32toh(*(a)) 50 | #define cpu_to_le32(a) htole32(a) 51 | #ifndef ARRAY_SIZE 52 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 53 | #endif 54 | #ifndef DIV_ROUND_UP 55 | #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) 56 | #endif 57 | 58 | static inline void cpu_to_le32_array(uint32_t *buf, unsigned int words) 59 | { 60 | while (words--) { 61 | *buf = cpu_to_le32(*buf); 62 | ++buf; 63 | } 64 | } 65 | 66 | static inline void le32_to_cpu_array(uint32_t *buf, unsigned int words) 67 | { 68 | while (words--) { 69 | *buf = le32_to_cpup(buf); 70 | ++buf; 71 | } 72 | } 73 | 74 | static inline uint32_t ror32(uint32_t word, unsigned int shift) 75 | { 76 | return (word >> (shift & 31)) | (word << ((-shift) & 31)); 77 | } 78 | 79 | static const uint32_t blake2s_iv[8] = { 80 | 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 81 | 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL 82 | }; 83 | 84 | static const uint8_t blake2s_sigma[10][16] = { 85 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, 86 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, 87 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, 88 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, 89 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, 90 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, 91 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, 92 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, 93 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, 94 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, 95 | }; 96 | 97 | static void blake2s_set_lastblock(struct blake2s_state *state) 98 | { 99 | state->f[0] = -1; 100 | } 101 | 102 | static void blake2s_increment_counter(struct blake2s_state *state, const uint32_t inc) 103 | { 104 | state->t[0] += inc; 105 | state->t[1] += (state->t[0] < inc); 106 | } 107 | 108 | static void blake2s_init_param(struct blake2s_state *state, const uint32_t param) 109 | { 110 | int i; 111 | 112 | memset(state, 0, sizeof(*state)); 113 | for (i = 0; i < 8; ++i) 114 | state->h[i] = blake2s_iv[i]; 115 | state->h[0] ^= param; 116 | } 117 | 118 | static void blake2s_init(struct blake2s_state *state, const size_t outlen) 119 | { 120 | blake2s_init_param(state, 0x01010000 | outlen); 121 | state->outlen = outlen; 122 | } 123 | 124 | static void blake2s_compress(struct blake2s_state *state, const uint8_t *block, size_t nblocks, const uint32_t inc) 125 | { 126 | uint32_t m[16]; 127 | uint32_t v[16]; 128 | int i; 129 | 130 | while (nblocks > 0) { 131 | blake2s_increment_counter(state, inc); 132 | memcpy(m, block, BLAKE2S_BLOCK_LEN); 133 | le32_to_cpu_array(m, ARRAY_SIZE(m)); 134 | memcpy(v, state->h, 32); 135 | v[ 8] = blake2s_iv[0]; 136 | v[ 9] = blake2s_iv[1]; 137 | v[10] = blake2s_iv[2]; 138 | v[11] = blake2s_iv[3]; 139 | v[12] = blake2s_iv[4] ^ state->t[0]; 140 | v[13] = blake2s_iv[5] ^ state->t[1]; 141 | v[14] = blake2s_iv[6] ^ state->f[0]; 142 | v[15] = blake2s_iv[7] ^ state->f[1]; 143 | 144 | #define G(r, i, a, b, c, d) do { \ 145 | a += b + m[blake2s_sigma[r][2 * i + 0]]; \ 146 | d = ror32(d ^ a, 16); \ 147 | c += d; \ 148 | b = ror32(b ^ c, 12); \ 149 | a += b + m[blake2s_sigma[r][2 * i + 1]]; \ 150 | d = ror32(d ^ a, 8); \ 151 | c += d; \ 152 | b = ror32(b ^ c, 7); \ 153 | } while (0) 154 | 155 | #define ROUND(r) do { \ 156 | G(r, 0, v[0], v[ 4], v[ 8], v[12]); \ 157 | G(r, 1, v[1], v[ 5], v[ 9], v[13]); \ 158 | G(r, 2, v[2], v[ 6], v[10], v[14]); \ 159 | G(r, 3, v[3], v[ 7], v[11], v[15]); \ 160 | G(r, 4, v[0], v[ 5], v[10], v[15]); \ 161 | G(r, 5, v[1], v[ 6], v[11], v[12]); \ 162 | G(r, 6, v[2], v[ 7], v[ 8], v[13]); \ 163 | G(r, 7, v[3], v[ 4], v[ 9], v[14]); \ 164 | } while (0) 165 | ROUND(0); 166 | ROUND(1); 167 | ROUND(2); 168 | ROUND(3); 169 | ROUND(4); 170 | ROUND(5); 171 | ROUND(6); 172 | ROUND(7); 173 | ROUND(8); 174 | ROUND(9); 175 | 176 | #undef G 177 | #undef ROUND 178 | 179 | for (i = 0; i < 8; ++i) 180 | state->h[i] ^= v[i] ^ v[i + 8]; 181 | 182 | block += BLAKE2S_BLOCK_LEN; 183 | --nblocks; 184 | } 185 | } 186 | 187 | static void blake2s_update(struct blake2s_state *state, const void *inp, size_t inlen) 188 | { 189 | const size_t fill = BLAKE2S_BLOCK_LEN - state->buflen; 190 | const uint8_t *in = inp; 191 | 192 | if (!inlen) 193 | return; 194 | if (inlen > fill) { 195 | memcpy(state->buf + state->buflen, in, fill); 196 | blake2s_compress(state, state->buf, 1, BLAKE2S_BLOCK_LEN); 197 | state->buflen = 0; 198 | in += fill; 199 | inlen -= fill; 200 | } 201 | if (inlen > BLAKE2S_BLOCK_LEN) { 202 | const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_LEN); 203 | blake2s_compress(state, in, nblocks - 1, BLAKE2S_BLOCK_LEN); 204 | in += BLAKE2S_BLOCK_LEN * (nblocks - 1); 205 | inlen -= BLAKE2S_BLOCK_LEN * (nblocks - 1); 206 | } 207 | memcpy(state->buf + state->buflen, in, inlen); 208 | state->buflen += inlen; 209 | } 210 | 211 | static void blake2s_final(struct blake2s_state *state, uint8_t *out) 212 | { 213 | blake2s_set_lastblock(state); 214 | memset(state->buf + state->buflen, 0, BLAKE2S_BLOCK_LEN - state->buflen); 215 | blake2s_compress(state, state->buf, 1, state->buflen); 216 | cpu_to_le32_array(state->h, ARRAY_SIZE(state->h)); 217 | memcpy(out, state->h, state->outlen); 218 | } 219 | 220 | static ssize_t getrandom_full(void *buf, size_t count, unsigned int flags) 221 | { 222 | ssize_t ret, total = 0; 223 | uint8_t *p = buf; 224 | 225 | do { 226 | ret = getrandom(p, count, flags); 227 | if (ret < 0 && errno == EINTR) 228 | continue; 229 | else if (ret < 0) 230 | return ret; 231 | total += ret; 232 | p += ret; 233 | count -= ret; 234 | } while (count); 235 | return total; 236 | } 237 | 238 | static ssize_t read_full(int fd, void *buf, size_t count) 239 | { 240 | ssize_t ret, total = 0; 241 | uint8_t *p = buf; 242 | 243 | do { 244 | ret = read(fd, p, count); 245 | if (ret < 0 && errno == EINTR) 246 | continue; 247 | else if (ret < 0) 248 | return ret; 249 | else if (ret == 0) 250 | break; 251 | total += ret; 252 | p += ret; 253 | count -= ret; 254 | } while (count); 255 | return total; 256 | } 257 | 258 | static ssize_t write_full(int fd, const void *buf, size_t count) 259 | { 260 | ssize_t ret, total = 0; 261 | const uint8_t *p = buf; 262 | 263 | do { 264 | ret = write(fd, p, count); 265 | if (ret < 0 && errno == EINTR) 266 | continue; 267 | else if (ret < 0) 268 | return ret; 269 | total += ret; 270 | p += ret; 271 | count -= ret; 272 | } while (count); 273 | return total; 274 | } 275 | 276 | static size_t determine_optimal_seed_len(void) 277 | { 278 | size_t ret = 0; 279 | char poolsize_str[11] = { 0 }; 280 | int fd = open("/proc/sys/kernel/random/poolsize", O_RDONLY); 281 | 282 | if (fd < 0 || read_full(fd, poolsize_str, sizeof(poolsize_str) - 1) < 0) { 283 | perror("Unable to determine pool size, falling back to 256 bits"); 284 | ret = MIN_SEED_LEN; 285 | } else 286 | ret = DIV_ROUND_UP(strtoul(poolsize_str, NULL, 10), 8); 287 | if (fd >= 0) 288 | close(fd); 289 | if (ret < MIN_SEED_LEN) 290 | ret = MIN_SEED_LEN; 291 | else if (ret > MAX_SEED_LEN) 292 | ret = MAX_SEED_LEN; 293 | return ret; 294 | } 295 | 296 | static int read_new_seed(uint8_t *seed, size_t len, bool *is_creditable) 297 | { 298 | ssize_t ret; 299 | int urandom_fd; 300 | 301 | *is_creditable = false; 302 | ret = getrandom_full(seed, len, GRND_NONBLOCK); 303 | if (ret == (ssize_t)len) { 304 | *is_creditable = true; 305 | return 0; 306 | } else if (ret < 0 && errno == ENOSYS) { 307 | struct pollfd random_fd = { 308 | .fd = open("/dev/random", O_RDONLY), 309 | .events = POLLIN 310 | }; 311 | if (random_fd.fd < 0) 312 | return -errno; 313 | *is_creditable = poll(&random_fd, 1, 0) == 1; 314 | close(random_fd.fd); 315 | } else if (getrandom_full(seed, len, GRND_INSECURE) == (ssize_t)len) 316 | return 0; 317 | urandom_fd = open("/dev/urandom", O_RDONLY); 318 | if (urandom_fd < 0) 319 | return -1; 320 | ret = read_full(urandom_fd, seed, len); 321 | if (ret == (ssize_t)len) 322 | ret = 0; 323 | else 324 | ret = -errno ? -errno : -EIO; 325 | close(urandom_fd); 326 | errno = -ret; 327 | return ret ? -1 : 0; 328 | } 329 | 330 | static int seed_rng(uint8_t *seed, size_t len, bool credit) 331 | { 332 | struct { 333 | int entropy_count; 334 | int buf_size; 335 | uint8_t buffer[MAX_SEED_LEN]; 336 | } req = { 337 | .entropy_count = credit ? len * 8 : 0, 338 | .buf_size = len 339 | }; 340 | int random_fd, ret; 341 | 342 | if (len > sizeof(req.buffer)) { 343 | errno = EFBIG; 344 | return -1; 345 | } 346 | memcpy(req.buffer, seed, len); 347 | 348 | random_fd = open("/dev/urandom", O_RDONLY); 349 | if (random_fd < 0) 350 | return -1; 351 | ret = ioctl(random_fd, RNDADDENTROPY, &req); 352 | if (ret) 353 | ret = -errno ? -errno : -EIO; 354 | close(random_fd); 355 | errno = -ret; 356 | return ret ? -1 : 0; 357 | } 358 | 359 | static int seed_from_file_if_exists(const char *filename, int dfd, bool credit, struct blake2s_state *hash) 360 | { 361 | uint8_t seed[MAX_SEED_LEN]; 362 | ssize_t seed_len; 363 | int fd = -1, ret = 0; 364 | 365 | fd = openat(dfd, filename, O_RDONLY); 366 | if (fd < 0 && errno == ENOENT) 367 | return 0; 368 | else if (fd < 0) { 369 | ret = -errno; 370 | perror("Unable to open seed file"); 371 | goto out; 372 | } 373 | seed_len = read_full(fd, seed, sizeof(seed)); 374 | if (seed_len < 0) { 375 | ret = -errno; 376 | perror("Unable to read seed file"); 377 | goto out; 378 | } 379 | if ((unlinkat(dfd, filename, 0) < 0 || fsync(dfd) < 0) && seed_len) { 380 | ret = -errno; 381 | perror("Unable to remove seed after reading, so not seeding"); 382 | goto out; 383 | } 384 | if (!seed_len) 385 | goto out; 386 | 387 | blake2s_update(hash, &seed_len, sizeof(seed_len)); 388 | blake2s_update(hash, seed, seed_len); 389 | 390 | printf("Seeding %zd bits %s crediting\n", seed_len * 8, credit ? "and" : "without"); 391 | if (seed_rng(seed, seed_len, credit) < 0) { 392 | ret = -errno; 393 | perror("Unable to seed"); 394 | } 395 | 396 | out: 397 | if (fd >= 0) 398 | close(fd); 399 | errno = -ret; 400 | return ret ? -1 : 0; 401 | } 402 | 403 | static bool skip_credit(void) 404 | { 405 | const char *skip = getenv("SEEDRNG_SKIP_CREDIT"); 406 | return skip && (!strcmp(skip, "1") || !strcasecmp(skip, "true") || 407 | !strcasecmp(skip, "yes") || !strcasecmp(skip, "y")); 408 | } 409 | 410 | int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) 411 | { 412 | static const char seedrng_prefix[] = "SeedRNG v1 Old+New Prefix"; 413 | static const char seedrng_failure[] = "SeedRNG v1 No New Seed Failure"; 414 | int fd = -1, dfd = -1, program_ret = 0; 415 | uint8_t new_seed[MAX_SEED_LEN]; 416 | size_t new_seed_len; 417 | bool new_seed_creditable; 418 | struct timespec realtime = { 0 }, boottime = { 0 }; 419 | struct blake2s_state hash; 420 | 421 | umask(0077); 422 | if (getuid()) { 423 | errno = EACCES; 424 | perror("This program requires root"); 425 | return 1; 426 | } 427 | 428 | blake2s_init(&hash, BLAKE2S_HASH_LEN); 429 | blake2s_update(&hash, seedrng_prefix, strlen(seedrng_prefix)); 430 | clock_gettime(CLOCK_REALTIME, &realtime); 431 | clock_gettime(CLOCK_BOOTTIME, &boottime); 432 | blake2s_update(&hash, &realtime, sizeof(realtime)); 433 | blake2s_update(&hash, &boottime, sizeof(boottime)); 434 | 435 | if (mkdir(SEED_DIR, 0700) < 0 && errno != EEXIST) { 436 | perror("Unable to create seed directory"); 437 | return 1; 438 | } 439 | 440 | dfd = open(SEED_DIR, O_DIRECTORY | O_RDONLY); 441 | if (dfd < 0 || flock(dfd, LOCK_EX) < 0) { 442 | perror("Unable to lock seed directory"); 443 | program_ret = 1; 444 | goto out; 445 | } 446 | 447 | if (seed_from_file_if_exists(NON_CREDITABLE_SEED, dfd, false, &hash) < 0) 448 | program_ret |= 1 << 1; 449 | if (seed_from_file_if_exists(CREDITABLE_SEED, dfd, !skip_credit(), &hash) < 0) 450 | program_ret |= 1 << 2; 451 | 452 | new_seed_len = determine_optimal_seed_len(); 453 | if (read_new_seed(new_seed, new_seed_len, &new_seed_creditable) < 0) { 454 | perror("Unable to read new seed"); 455 | new_seed_len = BLAKE2S_HASH_LEN; 456 | strncpy((char *)new_seed, seedrng_failure, new_seed_len); 457 | program_ret |= 1 << 3; 458 | } 459 | blake2s_update(&hash, &new_seed_len, sizeof(new_seed_len)); 460 | blake2s_update(&hash, new_seed, new_seed_len); 461 | blake2s_final(&hash, new_seed + new_seed_len - BLAKE2S_HASH_LEN); 462 | 463 | printf("Saving %zu bits of %s seed for next boot\n", new_seed_len * 8, new_seed_creditable ? "creditable" : "non-creditable"); 464 | fd = openat(dfd, NON_CREDITABLE_SEED, O_WRONLY | O_CREAT | O_TRUNC, 0400); 465 | if (fd < 0) { 466 | perror("Unable to open seed file for writing"); 467 | program_ret |= 1 << 4; 468 | goto out; 469 | } 470 | if (write_full(fd, new_seed, new_seed_len) != (ssize_t)new_seed_len || fsync(fd) < 0) { 471 | perror("Unable to write seed file"); 472 | program_ret |= 1 << 5; 473 | goto out; 474 | } 475 | if (new_seed_creditable && renameat(dfd, NON_CREDITABLE_SEED, dfd, CREDITABLE_SEED) < 0) { 476 | perror("Unable to make new seed creditable"); 477 | program_ret |= 1 << 6; 478 | } 479 | out: 480 | if (fd >= 0) 481 | close(fd); 482 | if (dfd >= 0) 483 | close(dfd); 484 | return program_ret; 485 | } 486 | -------------------------------------------------------------------------------- /services/agetty-console/conf: -------------------------------------------------------------------------------- 1 | BAUD_RATE=38400 2 | TERM_NAME=linux 3 | -------------------------------------------------------------------------------- /services/agetty-console/finish: -------------------------------------------------------------------------------- 1 | ../agetty-generic/finish -------------------------------------------------------------------------------- /services/agetty-console/run: -------------------------------------------------------------------------------- 1 | ../agetty-generic/run -------------------------------------------------------------------------------- /services/agetty-console/supervise: -------------------------------------------------------------------------------- 1 | /run/runit/supervise.agetty-console -------------------------------------------------------------------------------- /services/agetty-generic/finish: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | tty=${PWD##*-} 3 | exec utmpset -w $tty 4 | -------------------------------------------------------------------------------- /services/agetty-generic/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | tty=${PWD##*-} 4 | 5 | [ -r conf ] && . ./conf 6 | 7 | if [ -x /sbin/getty -o -x /bin/getty ]; then 8 | # busybox 9 | GETTY=getty 10 | elif [ -x /sbin/agetty -o -x /bin/agetty ]; then 11 | # util-linux 12 | GETTY=agetty 13 | fi 14 | 15 | exec chpst -P ${GETTY} ${GETTY_ARGS} \ 16 | "${tty}" "${BAUD_RATE}" "${TERM_NAME}" 17 | -------------------------------------------------------------------------------- /services/agetty-hvc0/conf: -------------------------------------------------------------------------------- 1 | GETTY_ARGS="-L" 2 | BAUD_RATE=9600 3 | TERM_NAME=vt100 4 | -------------------------------------------------------------------------------- /services/agetty-hvc0/finish: -------------------------------------------------------------------------------- 1 | ../agetty-generic/finish -------------------------------------------------------------------------------- /services/agetty-hvc0/run: -------------------------------------------------------------------------------- 1 | ../agetty-serial/run -------------------------------------------------------------------------------- /services/agetty-hvc0/supervise: -------------------------------------------------------------------------------- 1 | /run/runit/supervise.agetty-hvc0 -------------------------------------------------------------------------------- /services/agetty-hvsi0/conf: -------------------------------------------------------------------------------- 1 | GETTY_ARGS="-L" 2 | if [ -x /sbin/agetty -o -x /bin/agetty ]; then 3 | # util-linux specific settings 4 | GETTY_ARGS="${GETTY_ARGS} -8" 5 | fi 6 | 7 | BAUD_RATE=19200 8 | TERM_NAME=vt100 9 | -------------------------------------------------------------------------------- /services/agetty-hvsi0/finish: -------------------------------------------------------------------------------- 1 | ../agetty-generic/finish -------------------------------------------------------------------------------- /services/agetty-hvsi0/run: -------------------------------------------------------------------------------- 1 | ../agetty-serial/run -------------------------------------------------------------------------------- /services/agetty-hvsi0/supervise: -------------------------------------------------------------------------------- 1 | /run/runit/supervise.agetty-hvsi0 -------------------------------------------------------------------------------- /services/agetty-serial/conf: -------------------------------------------------------------------------------- 1 | GETTY_ARGS="-L" 2 | if [ -x /sbin/agetty -o -x /bin/agetty ]; then 3 | # util-linux specific settings 4 | GETTY_ARGS="${GETTY_ARGS} -8" 5 | fi 6 | 7 | BAUD_RATE=115200 8 | TERM_NAME=vt100 9 | -------------------------------------------------------------------------------- /services/agetty-serial/finish: -------------------------------------------------------------------------------- 1 | ../agetty-generic/finish -------------------------------------------------------------------------------- /services/agetty-serial/run: -------------------------------------------------------------------------------- 1 | ../agetty-generic/run -------------------------------------------------------------------------------- /services/agetty-tty1/conf: -------------------------------------------------------------------------------- 1 | if [ -x /sbin/agetty -o -x /bin/agetty ]; then 2 | # util-linux specific settings 3 | if [ "${tty}" = "tty1" ]; then 4 | GETTY_ARGS="--noclear" 5 | fi 6 | fi 7 | 8 | BAUD_RATE=38400 9 | TERM_NAME=linux 10 | -------------------------------------------------------------------------------- /services/agetty-tty1/finish: -------------------------------------------------------------------------------- 1 | ../agetty-generic/finish -------------------------------------------------------------------------------- /services/agetty-tty1/run: -------------------------------------------------------------------------------- 1 | ../agetty-generic/run -------------------------------------------------------------------------------- /services/agetty-tty1/supervise: -------------------------------------------------------------------------------- 1 | /run/runit/supervise.agetty-tty1 -------------------------------------------------------------------------------- /services/agetty-tty2/conf: -------------------------------------------------------------------------------- 1 | ../agetty-tty1/conf -------------------------------------------------------------------------------- /services/agetty-tty2/finish: -------------------------------------------------------------------------------- 1 | ../agetty-generic/finish -------------------------------------------------------------------------------- /services/agetty-tty2/run: -------------------------------------------------------------------------------- 1 | ../agetty-generic/run -------------------------------------------------------------------------------- /services/agetty-tty2/supervise: -------------------------------------------------------------------------------- 1 | /run/runit/supervise.agetty-tty2 -------------------------------------------------------------------------------- /services/agetty-tty3/conf: -------------------------------------------------------------------------------- 1 | ../agetty-tty1/conf -------------------------------------------------------------------------------- /services/agetty-tty3/finish: -------------------------------------------------------------------------------- 1 | ../agetty-generic/finish -------------------------------------------------------------------------------- /services/agetty-tty3/run: -------------------------------------------------------------------------------- 1 | ../agetty-generic/run -------------------------------------------------------------------------------- /services/agetty-tty3/supervise: -------------------------------------------------------------------------------- 1 | /run/runit/supervise.agetty-tty3 -------------------------------------------------------------------------------- /services/agetty-tty4/conf: -------------------------------------------------------------------------------- 1 | ../agetty-tty1/conf -------------------------------------------------------------------------------- /services/agetty-tty4/finish: -------------------------------------------------------------------------------- 1 | ../agetty-generic/finish -------------------------------------------------------------------------------- /services/agetty-tty4/run: -------------------------------------------------------------------------------- 1 | ../agetty-generic/run -------------------------------------------------------------------------------- /services/agetty-tty4/supervise: -------------------------------------------------------------------------------- 1 | /run/runit/supervise.agetty-tty4 -------------------------------------------------------------------------------- /services/agetty-tty5/conf: -------------------------------------------------------------------------------- 1 | ../agetty-tty1/conf -------------------------------------------------------------------------------- /services/agetty-tty5/finish: -------------------------------------------------------------------------------- 1 | ../agetty-generic/finish -------------------------------------------------------------------------------- /services/agetty-tty5/run: -------------------------------------------------------------------------------- 1 | ../agetty-generic/run -------------------------------------------------------------------------------- /services/agetty-tty5/supervise: -------------------------------------------------------------------------------- 1 | /run/runit/supervise.agetty-tty5 -------------------------------------------------------------------------------- /services/agetty-tty6/conf: -------------------------------------------------------------------------------- 1 | ../agetty-tty1/conf -------------------------------------------------------------------------------- /services/agetty-tty6/finish: -------------------------------------------------------------------------------- 1 | ../agetty-generic/finish -------------------------------------------------------------------------------- /services/agetty-tty6/run: -------------------------------------------------------------------------------- 1 | ../agetty-generic/run -------------------------------------------------------------------------------- /services/agetty-tty6/supervise: -------------------------------------------------------------------------------- 1 | /run/runit/supervise.agetty-tty6 -------------------------------------------------------------------------------- /services/agetty-ttyAMA0/conf: -------------------------------------------------------------------------------- 1 | ../agetty-serial/conf -------------------------------------------------------------------------------- /services/agetty-ttyAMA0/finish: -------------------------------------------------------------------------------- 1 | ../agetty-generic/finish -------------------------------------------------------------------------------- /services/agetty-ttyAMA0/run: -------------------------------------------------------------------------------- 1 | ../agetty-serial/run -------------------------------------------------------------------------------- /services/agetty-ttyAMA0/supervise: -------------------------------------------------------------------------------- 1 | /run/runit/supervise.agetty-ttyAMA0 -------------------------------------------------------------------------------- /services/agetty-ttyS0/conf: -------------------------------------------------------------------------------- 1 | ../agetty-serial/conf -------------------------------------------------------------------------------- /services/agetty-ttyS0/finish: -------------------------------------------------------------------------------- 1 | ../agetty-generic/finish -------------------------------------------------------------------------------- /services/agetty-ttyS0/run: -------------------------------------------------------------------------------- 1 | ../agetty-serial/run -------------------------------------------------------------------------------- /services/agetty-ttyS0/supervise: -------------------------------------------------------------------------------- 1 | /run/runit/supervise.agetty-ttyS0 -------------------------------------------------------------------------------- /services/agetty-ttyUSB0/conf: -------------------------------------------------------------------------------- 1 | ../agetty-serial/conf -------------------------------------------------------------------------------- /services/agetty-ttyUSB0/finish: -------------------------------------------------------------------------------- 1 | ../agetty-generic/finish -------------------------------------------------------------------------------- /services/agetty-ttyUSB0/run: -------------------------------------------------------------------------------- 1 | ../agetty-serial/run -------------------------------------------------------------------------------- /services/agetty-ttyUSB0/supervise: -------------------------------------------------------------------------------- 1 | /run/runit/supervise.agetty-ttyUSB0 -------------------------------------------------------------------------------- /services/sulogin/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -r conf ] && . ./conf 3 | read -r tty < /sys/class/tty/console/active 4 | tty=/dev/${tty##* } 5 | exec setsid sulogin ${OPTS:=-p} < $tty >$tty 2>&1 6 | -------------------------------------------------------------------------------- /services/sulogin/supervise: -------------------------------------------------------------------------------- 1 | /run/runit/supervise.sulogin -------------------------------------------------------------------------------- /shutdown: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shutdown - shutdown(8) lookalike for runit 3 | 4 | single() { 5 | runsvchdir single 6 | } 7 | 8 | abort() { 9 | printf '%s\n' "$1" >&2 10 | exit 1 11 | } 12 | 13 | usage() { 14 | abort "Usage: ${0##*/} [-fF] [-kchPr] time [warning message]" 15 | } 16 | 17 | action=single 18 | 19 | while getopts akrhPHfFnct: opt; do 20 | case "$opt" in 21 | a|n|H) abort "'-$opt' is not implemented";; 22 | t) ;; 23 | f) touch /fastboot;; 24 | F) touch /forcefsck;; 25 | k) action=true;; 26 | c) action=cancel;; 27 | h|P) action=halt;; 28 | r) action=reboot;; 29 | [?]) usage;; 30 | esac 31 | done 32 | shift $((OPTIND - 1)) 33 | 34 | [ $# -eq 0 ] && usage 35 | 36 | time=$1; shift 37 | message="${*:-system is going down}" 38 | 39 | if [ "$action" = "cancel" ]; then 40 | kill "$(cat /run/runit/shutdown.pid)" 41 | if [ -e /etc/nologin ] && ! [ -s /etc/nologin ]; then 42 | rm /etc/nologin 43 | fi 44 | echo "${*:-shutdown cancelled}" | wall 45 | exit 46 | fi 47 | 48 | touch /run/runit/shutdown.pid 2>/dev/null || abort "Not enough permissions to execute ${0#*/}" 49 | echo $$ >/run/runit/shutdown.pid 50 | 51 | case "$time" in 52 | now) time=0;; 53 | +*) time=${time#+};; 54 | *:*) abort "absolute time is not implemented";; 55 | *) abort "invalid time";; 56 | esac 57 | 58 | for break in 5 0; do 59 | [ "$time" -gt "$break" ] || continue 60 | [ "$break" = 0 ] && touch /etc/nologin 61 | 62 | printf '%s in %s minutes\n' "$message" "$time" | wall 63 | printf 'shutdown: sleeping for %s minutes... ' "$(( time - break ))" 64 | sleep $(( (time - break) * 60 )) 65 | time="$break" 66 | printf '\n' 67 | 68 | [ "$break" = 0 ] && rm /etc/nologin 69 | done 70 | 71 | printf '%s NOW\n' "$message" | wall 72 | 73 | $action 74 | -------------------------------------------------------------------------------- /shutdown.8: -------------------------------------------------------------------------------- 1 | .Dd July 29, 2014 2 | .Dt SHUTDOWN 8 3 | .Os Linux 4 | .Sh NAME 5 | .Nm shutdown 6 | .Nd bring down the system 7 | .Sh SYNOPSIS 8 | .Nm shutdown 9 | .Op Fl rhP 10 | .Op Fl fF 11 | .Op Cm now | Cm + Ns Ar mins 12 | .Op Ar message ... 13 | .Sh DESCRIPTION 14 | .Nm 15 | brings the system down in a secure way. 16 | All logged-in users 17 | are notified that the system is going down, and 18 | .Xr login 1 19 | is blocked. 20 | .Pp 21 | By default, 22 | .Nm 23 | puts the system into single user mode. 24 | Rebooting and halting the system can be done using the following options: 25 | .Bl -tag -width indent 26 | .It Fl c 27 | Cancel an ongoing shutdown. 28 | .It Fl f 29 | Enable fast booting; skip 30 | .Xr fsck 8 31 | on next boot. 32 | .It Fl F 33 | Force run of 34 | .Xr fsck 8 35 | on next boot. 36 | .It Fl h 37 | Halt the system. 38 | .It Fl k 39 | Don't really shutdown; only send the warning messages to everybody. 40 | .It Fl P 41 | Poweroff the system. 42 | .It Fl r 43 | Reboot the system. 44 | .It Cm now 45 | Shutdown without further waiting. 46 | .It Cm + Ns Ar mins 47 | Wait 48 | .Ar mins 49 | minutes before shutting down. 50 | .It Ar message 51 | Message displayed to all users, defaults to "system is going down". 52 | .El 53 | .Sh UNSUPPORTED OPTIONS 54 | This version of 55 | .Nm 56 | is based on 57 | .Xr runit 8 , 58 | the following features are 59 | .Sy not 60 | supported: 61 | .Bl -tag -width indent 62 | .It Fl t Ar secs 63 | to wait 64 | .Ar secs 65 | seconds between SIGKILL and SIGTERM on shutdown is silently ignored. 66 | .It Fl a 67 | Use 68 | .Pa /etc/shutdown.allow . 69 | .It Fl H 70 | Drop into boot monitor. 71 | .It Fl n 72 | Don't call 73 | .Xr init 8 . 74 | .It Ar hh Ns : Ns Ar mm 75 | Absolute time specification is not implemented. 76 | .El 77 | .Sh EXAMPLES 78 | Turn off the system: 79 | .Dl # shutdown -h now 80 | .Sh SEE ALSO 81 | .Xr fsck 8 , 82 | .Xr halt 8 , 83 | .Xr init 8 , 84 | .Xr poweroff 8 , 85 | .Xr reboot 8 , 86 | .Xr runit 8 , 87 | .Xr runsvchdir 8 88 | .Sh AUTHOR 89 | .An Leah Neukirchen , 90 | .Mt leah@vuxu.org . 91 | -------------------------------------------------------------------------------- /shutdown.d/10-sv-stop.sh: -------------------------------------------------------------------------------- 1 | msg "Waiting for services to stop..." 2 | sv force-stop /var/service/* 3 | sv exit /var/service/* 4 | -------------------------------------------------------------------------------- /shutdown.d/20-rc-shutdown.sh: -------------------------------------------------------------------------------- 1 | [ -x /etc/rc.shutdown ] && /etc/rc.shutdown 2 | -------------------------------------------------------------------------------- /shutdown.d/30-seedrng.sh: -------------------------------------------------------------------------------- 1 | if [ -z "$IS_CONTAINER" ]; then 2 | msg "Saving random number generator seed..." 3 | seedrng 4 | fi 5 | -------------------------------------------------------------------------------- /shutdown.d/40-hwclock.sh: -------------------------------------------------------------------------------- 1 | if [ -z "$IS_CONTAINER" ] && [ -n "$HARDWARECLOCK" ]; then 2 | hwclock --systohc ${HARDWARECLOCK:+--$(echo $HARDWARECLOCK |tr A-Z a-z)} 3 | fi 4 | -------------------------------------------------------------------------------- /shutdown.d/50-wtmp.sh: -------------------------------------------------------------------------------- 1 | halt -w 2 | -------------------------------------------------------------------------------- /shutdown.d/60-udev.sh: -------------------------------------------------------------------------------- 1 | if [ -z "$IS_CONTAINER" ]; then 2 | msg "Stopping udev..." 3 | udevadm control --exit 4 | fi 5 | -------------------------------------------------------------------------------- /shutdown.d/70-pkill.sh: -------------------------------------------------------------------------------- 1 | msg "Sending TERM signal to processes..." 2 | pkill --inverse -s0,1 -TERM 3 | sleep 1 4 | msg "Sending KILL signal to processes..." 5 | pkill --inverse -s0,1 -KILL 6 | -------------------------------------------------------------------------------- /shutdown.d/80-filesystems.sh: -------------------------------------------------------------------------------- 1 | if [ -z "$IS_CONTAINER" ]; then 2 | msg "Unmounting filesystems, disabling swap..." 3 | swapoff -a 4 | umount -r -a -t nosysfs,noproc,nodevtmpfs,notmpfs 5 | msg "Remounting rootfs read-only..." 6 | LIBMOUNT_FORCE_MOUNT2=always mount -o remount,ro / 7 | fi 8 | 9 | sync 10 | 11 | if [ -z "$IS_CONTAINER" ]; then 12 | deactivate_vgs 13 | deactivate_crypt 14 | fi 15 | -------------------------------------------------------------------------------- /shutdown.d/90-kexec.sh: -------------------------------------------------------------------------------- 1 | if [ -z "$IS_CONTAINER" ]; then 2 | # test -x returns false on a noexec mount, hence using find to detect x bit 3 | if [ -n "$(find /run/runit/reboot -perm -u+x 2>/dev/null)" ] && 4 | command -v kexec >/dev/null 5 | then 6 | msg "Triggering kexec..." 7 | kexec -e 2>/dev/null 8 | # not reached when kexec was successful. 9 | fi 10 | fi 11 | -------------------------------------------------------------------------------- /vlogger.8: -------------------------------------------------------------------------------- 1 | .Dd March 1, 2017 2 | .Dt VLOGGER 8 3 | .Os 4 | .Sh NAME 5 | .Nm vlogger 6 | .Nd log messages to syslog or an arbitrary executable 7 | .Sh SYNOPSIS 8 | .Nm vlogger 9 | .Op Fl isS 10 | .Op Fl f Ar file 11 | .Op Fl p Ar pri 12 | .Op Fl t Ar tag 13 | .Op Ar message ... 14 | .Sh DESCRIPTION 15 | The 16 | .Nm 17 | utility writes messages to the system log or an arbitrary executable. 18 | .Pp 19 | If 20 | .Nm 21 | is executed as 22 | .Nm logger 23 | it will always use the system log and behave like the regular 24 | .Xr logger 1 . 25 | .Pp 26 | Without 27 | .Ar message 28 | arguments 29 | .Nm 30 | reads messages from 31 | .Dv stdin 32 | or the file specified with the 33 | .Fl f 34 | flag. 35 | If the 36 | .Pa /etc/vlogger 37 | executable exists 38 | .Nm 39 | executes it with 40 | .Ar tag , 41 | .Ar level 42 | and 43 | .Ar facility 44 | as arguments, 45 | replacing the 46 | .Nm 47 | process. 48 | .Pp 49 | If 50 | .Nm 51 | is executed as a log service for 52 | .Xr runit 8 53 | or another daemontools like 54 | supervision suite it uses the service name as default 55 | .Ar tag . 56 | As example if 57 | .Nm 58 | is linked to 59 | .Pa /var/service/foo/log/run 60 | it uses 61 | .Dq foo 62 | as 63 | .Ar tag 64 | and 65 | .Dq daemon.notice 66 | as 67 | .Ar pri . 68 | .Pp 69 | The options are as follows: 70 | .Bl -tag -width "-f file" 71 | .It Fl f Ar file 72 | Read lines from the specified 73 | .Ar file . 74 | This option cannot be combine 75 | .Ar message 76 | arguments. 77 | .It Fl i 78 | Log the PID of the 79 | .Nm 80 | process. 81 | Only supported if 82 | .Xr syslog 3 83 | is used. 84 | .It Fl p Ar pri 85 | The. 86 | .Ar pri 87 | can be 88 | .Pa facility.level 89 | or just 90 | .Pa facility . 91 | See 92 | .Sx FACILITIES , 93 | .Sx LEVELS 94 | or 95 | .Xr syslog 3 . 96 | The default is 97 | .Dq user.notice . 98 | .It Fl S 99 | Force 100 | .Nm 101 | to use 102 | .Xr syslog 3 103 | even if 104 | .Pa /etc/vlogger 105 | exists. 106 | .It Fl s 107 | Output the message to standard error, as well as 108 | .Xr syslog 3 . 109 | Only supported if 110 | .Xr syslog 3 111 | is used. 112 | .It Fl t Ar tag 113 | Defines the 114 | .Xr openlog 3 115 | .Pa ident 116 | which is used as prefix for each log message or passed as first argument to 117 | .Pa /etc/vlogger . 118 | The default is the 119 | .Ev LOGNAME 120 | environment variable. 121 | .It Ar message 122 | Write the 123 | .Ar message 124 | to the system log. 125 | .El 126 | .Sh FACILITIES 127 | .Bl -tag -width 11n -compact 128 | .It auth 129 | .It authpriv 130 | .It cron 131 | .It daemon 132 | .It ftp 133 | .It kern 134 | can not be used from userspace replaced with 135 | .Pa daemon . 136 | .It lpr 137 | .It mail 138 | .It news 139 | .It syslog 140 | .It user 141 | .It uucp 142 | .It local[0-7] 143 | .It security 144 | deprecated synonym for 145 | .Pa auth . 146 | .El 147 | .Sh LEVELS 148 | .Bl -tag -width 11n -compact 149 | .It emerg 150 | .It alert 151 | .It crit 152 | .It err 153 | .It warning 154 | .It notice 155 | .It info 156 | .It debug 157 | .It panic 158 | deprecated synonym for 159 | .Pa emerg . 160 | .It error 161 | deprecated synonym for 162 | .Ar err . 163 | .It warn 164 | deprecated synonym for 165 | .Pa warning . 166 | .El 167 | .Sh FILES 168 | .Bl -tag -width indent 169 | .It /etc/vlogger 170 | An optional executable file that is used to handle the messages. 171 | It is executed with 172 | .Ar tag , 173 | .Ar level 174 | and 175 | .Ar facility 176 | as arguments 177 | and replaces the 178 | .Nm 179 | process. 180 | .El 181 | .Sh EXIT STATUS 182 | .Ex -std 183 | .Sh EXAMPLES 184 | .Pa /etc/vlogger : 185 | .Bd -literal -offset indent 186 | #!/bin/sh 187 | exec svlogd /var/log/$1 188 | .Ed 189 | .Sh SEE ALSO 190 | .Xr logger 1 , 191 | .Xr syslog 3 , 192 | .Xr svlogd 8 193 | .Sh HISTORY 194 | This program is a replacement for the 195 | .Nm logger 196 | utility provided by 197 | .Nm util-linux . 198 | .Sh AUTHORS 199 | .An Duncan Overbruck Aq Mt mail@duncano.de 200 | .Sh LICENSE 201 | .Nm 202 | is in the public domain. 203 | .Pp 204 | To the extent possible under law, 205 | the creator of this work 206 | has waived all copyright and related or 207 | neighboring rights to this work. 208 | .Pp 209 | .Lk http://creativecommons.org/publicdomain/zero/1.0/ 210 | -------------------------------------------------------------------------------- /vlogger.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | extern char *__progname; 10 | 11 | static char pwd[PATH_MAX]; 12 | 13 | typedef struct { 14 | const char *const c_name; 15 | int c_val; 16 | } CODE; 17 | 18 | CODE prioritynames[] = { 19 | { "alert", LOG_ALERT }, 20 | { "crit", LOG_CRIT }, 21 | { "debug", LOG_DEBUG }, 22 | { "emerg", LOG_EMERG }, 23 | { "err", LOG_ERR }, 24 | { "error", LOG_ERR }, 25 | { "info", LOG_INFO }, 26 | { "notice", LOG_NOTICE }, 27 | { "panic", LOG_EMERG }, 28 | { "warn", LOG_WARNING }, 29 | { "warning", LOG_WARNING }, 30 | { 0, -1 } 31 | }; 32 | 33 | CODE facilitynames[] = { 34 | { "auth", LOG_AUTH }, 35 | { "authpriv", LOG_AUTHPRIV }, 36 | { "cron", LOG_CRON }, 37 | { "daemon", LOG_DAEMON }, 38 | { "ftp", LOG_FTP }, 39 | { "kern", LOG_KERN }, 40 | { "lpr", LOG_LPR }, 41 | { "mail", LOG_MAIL }, 42 | { "news", LOG_NEWS }, 43 | { "security", LOG_AUTH }, 44 | { "syslog", LOG_SYSLOG }, 45 | { "user", LOG_USER }, 46 | { "uucp", LOG_UUCP }, 47 | { "local0", LOG_LOCAL0 }, 48 | { "local1", LOG_LOCAL1 }, 49 | { "local2", LOG_LOCAL2 }, 50 | { "local3", LOG_LOCAL3 }, 51 | { "local4", LOG_LOCAL4 }, 52 | { "local5", LOG_LOCAL5 }, 53 | { "local6", LOG_LOCAL6 }, 54 | { "local7", LOG_LOCAL7 }, 55 | { 0, -1 } 56 | }; 57 | 58 | static void 59 | strpriority(char *s, int *facility, int *level) 60 | { 61 | char *p; 62 | CODE *cp; 63 | 64 | if ((p = strchr(s, '.'))) { 65 | *p++ = 0; 66 | for (cp = prioritynames; cp->c_name; cp++) { 67 | if (strcmp(cp->c_name, p) == 0) 68 | *level = cp->c_val; 69 | } 70 | } 71 | if (*s) 72 | for (cp = facilitynames; cp->c_name; cp++) { 73 | if (strcmp(cp->c_name, s) == 0) 74 | *facility = cp->c_val; 75 | } 76 | } 77 | 78 | int 79 | main(int argc, char *argv[]) 80 | { 81 | char buf[1024]; 82 | char *p, *argv0; 83 | char *tag = NULL; 84 | int c; 85 | int Sflag = 0; 86 | int logflags = 0; 87 | int facility = LOG_USER; 88 | int level = LOG_NOTICE; 89 | 90 | argv0 = *argv; 91 | 92 | if (strcmp(argv0, "./run") == 0) { 93 | p = getcwd(pwd, sizeof (pwd)); 94 | if (p != NULL && *pwd == '/') { 95 | if (*(p = pwd+(strlen(pwd)-1)) == '/') 96 | *p = '\0'; 97 | if ((p = strrchr(pwd, '/')) && strncmp(p+1, "log", 3) == 0 && 98 | (*p = '\0', (p = strrchr(pwd, '/'))) && (*(p+1) != '\0')) { 99 | tag = p+1; 100 | facility = LOG_DAEMON; 101 | level = LOG_NOTICE; 102 | } 103 | } 104 | } else if (strcmp(__progname, "logger") == 0) { 105 | /* behave just like logger(1) and only use syslog */ 106 | Sflag++; 107 | } 108 | 109 | while ((c = getopt(argc, argv, "f:ip:Sst:")) != -1) 110 | switch (c) { 111 | case 'f': 112 | if (freopen(optarg, "r", stdin) == NULL) { 113 | fprintf(stderr, "vlogger: %s: %s\n", optarg, strerror(errno)); 114 | return 1; 115 | } 116 | break; 117 | case 'i': logflags |= LOG_PID; break; 118 | case 'p': strpriority(optarg, &facility, &level); break; 119 | case 'S': Sflag++; break; 120 | case 's': logflags |= LOG_PERROR; break; 121 | case 't': tag = optarg; break; 122 | default: 123 | fprintf(stderr, "usage: vlogger [-isS] [-f file] [-p pri] [-t tag] [message ...]\n"); 124 | exit(1); 125 | } 126 | argc -= optind; 127 | argv += optind; 128 | 129 | if (argc > 0) 130 | Sflag++; 131 | 132 | if (!Sflag && access("/etc/vlogger", X_OK) != -1) { 133 | CODE *cp; 134 | const char *sfacility = "", *slevel = ""; 135 | for (cp = prioritynames; cp->c_name; cp++) { 136 | if (cp->c_val == level) 137 | slevel = cp->c_name; 138 | } 139 | for (cp = facilitynames; cp->c_name; cp++) { 140 | if (cp->c_val == facility) 141 | sfacility = cp->c_name; 142 | } 143 | execl("/etc/vlogger", argv0, tag ? tag : "", slevel, sfacility, (char *)0); 144 | fprintf(stderr, "vlogger: exec: %s\n", strerror(errno)); 145 | exit(1); 146 | } 147 | 148 | openlog(tag ? tag : getlogin(), logflags, facility); 149 | 150 | if (argc > 0) { 151 | size_t len; 152 | char *p, *e; 153 | p = buf; 154 | *p = '\0'; 155 | e = buf + sizeof buf - 2; 156 | for (; *argv;) { 157 | len = strlen(*argv); 158 | if (p + len > e && p > buf) { 159 | syslog(level|facility, "%s", buf); 160 | p = buf; 161 | *p = '\0'; 162 | } 163 | if (len > sizeof buf - 1) { 164 | syslog(level|facility, "%s", *argv++); 165 | } else { 166 | if (p != buf) { 167 | *p++ = ' '; 168 | *p = '\0'; 169 | } 170 | strncat(p, *argv++, e-p); 171 | p += len; 172 | } 173 | } 174 | if (p != buf) 175 | syslog(level|facility, "%s", buf); 176 | return 0; 177 | } 178 | 179 | while (fgets(buf, sizeof buf, stdin) != NULL) 180 | syslog(level|facility, "%s", buf); 181 | 182 | return 0; 183 | } 184 | -------------------------------------------------------------------------------- /zzz: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # zzz - really simple suspend script 3 | 4 | USAGE="Usage: ${0##*/} [-nSzZR] 5 | -n dry run (sleep for 5s instead of suspend/hibernate) 6 | -S Low-power idle (ACPI S1) 7 | -z suspend to RAM (ACPI S3) [DEFAULT for zzz(8)] 8 | -Z hibernate to disk & power off (ACPI S4) [DEFAULT for ZZZ(8)] 9 | -R hibernate to disk & reboot 10 | -H hibernate to disk & suspend (aka suspend-hybrid)" 11 | 12 | fail() { echo ${0##*/}: 1>&2 "$*"; exit 1; } 13 | 14 | export ZZZ_MODE=suspend 15 | export ZZZ_HIBERNATE_MODE=platform 16 | 17 | case "$0" in 18 | *ZZZ) ZZZ_MODE=hibernate;; 19 | esac 20 | 21 | while getopts hnSzHRZ opt; do 22 | case "$opt" in 23 | n) ZZZ_MODE=noop;; 24 | S) ZZZ_MODE=standby;; 25 | z) ZZZ_MODE=suspend;; 26 | Z) ZZZ_MODE=hibernate;; 27 | R) ZZZ_MODE=hibernate; ZZZ_HIBERNATE_MODE=reboot;; 28 | H) ZZZ_MODE=hibernate; ZZZ_HIBERNATE_MODE=suspend;; 29 | [h?]) fail "$USAGE";; 30 | esac 31 | done 32 | shift $((OPTIND-1)) 33 | 34 | case "$ZZZ_MODE" in 35 | suspend) grep -q mem /sys/power/state || fail "suspend not supported";; 36 | hibernate) grep -q disk /sys/power/state || fail "hibernate not supported";; 37 | esac 38 | 39 | test -w /sys/power/state || fail "sleep permission denied" 40 | 41 | ( 42 | flock -n 9 || fail "another instance of zzz is running" 43 | 44 | printf "Zzzz... " 45 | 46 | for hook in /etc/zzz.d/suspend/*; do 47 | [ -x "$hook" ] && "$hook" 48 | done 49 | 50 | case "$ZZZ_MODE" in 51 | standby) printf freeze >/sys/power/state || fail "standby failed";; 52 | suspend) printf mem >/sys/power/state || fail "suspend failed";; 53 | hibernate) 54 | echo $ZZZ_HIBERNATE_MODE >/sys/power/disk 55 | printf disk >/sys/power/state || fail "hibernate failed";; 56 | noop) sleep 5;; 57 | esac 58 | 59 | for hook in /etc/zzz.d/resume/*; do 60 | [ -x "$hook" ] && "$hook" 61 | done 62 | 63 | echo "yawn." 64 | ) 9