#!/bin/sh -e # # 2016 Daniel Heule (hda at sfs.biz) # Copyright 2017, Philippe Gregoire # 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # # cdist is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # cdist is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # # # Returns the name of the init system (PID 1) # # Expected values: # Linux: # Adélie Linux: # sysvinit+openrc # Alpine Linux: # busybox-init+openrc # ArchLinux: # systemd, sysvinit # CRUX: # sysvinit # Debian: # systemd, upstart, sysvinit, openrc, ??? # Devuan: # sysvinit, ??? # Gentoo: # sysvinit+openrc, openrc-init, systemd # OpenBMC: # systemd # OpenWrt: # procd, init?? # RedHat (RHEL, CentOS, Fedora, RedHat Linux, ...): # systemd, upstart, sysvinit # Slackware: # sysvinit # SuSE: # systemd, sysvinit # Ubuntu: # systemd, upstart, sysvinit # # GNU: # Debian: # hurd-init, sysvinit # # BSD: # {Free,Open,Net}BSD: # init # # Mac OS X: # launchd, init # # Solaris/Illumos: # smf, init # [root@fedora-12 ~]# readlink /proc/1/exe # /sbin/init (deleted) # [root@fedora-12 ~]# ls -l /proc/1/exe # lrwxrwxrwx. 1 root root 0 2020-01-30 23:00 /proc/1/exe -> /sbin/init (deleted) set -e #set -x # DEBUG validate_busybox_init() { # It is quite common to use SysVinit to stack other init systemd # (like OpenRC) on top of it. So we check for that, too. if stacked=$(validate_openrc) then echo "busybox-init+${stacked}" else echo busybox-init fi } validate_hurd_init() { # FIXME: Test me! test -x /hurd/init || return 1 grep -q 'GNU Hurd' /hurd/init || return 1 echo hurd-init } validate_openrc() { test -f /run/openrc/softlevel || return 1 echo openrc } validate_procd() { grep -q 'procd' /sbin/procd || return 1 echo procd } validate_runit() { test -d /run/runit || return 1 echo runit } validate_smf() { # XXX: Is this the correct way?? test -f /etc/svc/volatile/svc_nonpersist.db || return 1 echo smf } validate_systemd() { # NOTE: sd_booted(3) test -d /run/systemd/system/ || return 1 # systemctl --version | sed -e '/^systemd/!d;s/^systemd //' echo systemd } validate_sysvinit() { test -x /sbin/init \ && grep -q 'INIT_VERSION=sysvinit-[0-9.]*' /sbin/init \ || return 1 # It is quite common to use SysVinit to stack other init systemd # (like OpenRC) on top of it. So we check for that, too. if stacked=$(validate_openrc) then echo "sysvinit+${stacked}" else echo sysvinit fi unset stacked } validate_upstart() { test -x "$(command -v initctl)" || return 1 case $(initctl version) in *'(upstart '*')') # if type -d /etc/init # then # # modern (DBus-based?) upstart >= 0.5 # : # elif type -d /etc/events.d # then # # ancient upstart # : # fi echo upstart ;; *) return 1 ;; esac } find_init_procfs() ( # First, check if the required file in procfs exists... test -h /proc/1/exe || return 1 # Find init executable init_exe=$(ls -l /proc/1/exe 2>/dev/null) init_exe=${init_exe#* -> } if ! test -x "$init_exe" then # On some rare occasions it can happen that the # running init's binary has been replaced. In this # case Linux adjusts the symlink to "X (deleted)" case $init_exe in *' (deleted)') init_exe=${init_exe% (deleted)} test -x "$init_exe" || exit 1 ;; *) exit 1 ;; esac fi echo "${init_exe}" ) # BusyBox's versions of ps and pgrep do not support some options # depending on which compile-time options have been used. find_init_pgrep() { pgrep -P0 -fl 2>/dev/null | awk -F '[[:blank:]]' '$1 == 1 { print $2 }' } find_init_ps() { case $(uname -s) in Darwin|NetBSD) ps -o ucomm= -p 1 2>/dev/null ;; FreeBSD) ps -o command= -p 1 2>/dev/null | cut -d ' ' -f 1 ;; OpenBSD) ps -o command -p 1 2>/dev/null | tail -n +2 | cut -d ' ' -f 1 ;; *) ps -o comm= -p 1 2>/dev/null ;; esac } find_init() { case $(uname -s) in Linux|GNU|NetBSD) find_init_procfs || find_init_pgrep || find_init_ps ;; FreeBSD) find_init_procfs || find_init_ps ;; OpenBSD) find_init_pgrep || find_init_ps ;; Darwin|FreeBSD|SunOS) find_init_ps ;; *) echo "Don't know how to determine init." >&2 echo 'Please send a patch.' >&2 exit 1 esac } validate_by_comm_name() { case $1 in busybox) validate_busybox_init ;; init) # FIXME: Do some more magic here! echo init ;; openrc-init) validate_openrc >/dev/null && echo openrc-init ;; runit) validate_runit ;; systemd) validate_systemd ;; *) # Run validate function by comm name if available. # Fall back to comm name if either it does not exist or # returns non-zero. type "validate_$1" >/dev/null && "validate_$1" || echo $1 esac } try_all() { # init: it could be anything... # We try some approaches to gather more information about init without # calling it! On some init systemd this triggers a reinitialisation of # the system which we don't want (e.g. embedded systems). validate_sysvinit || \ validate_openrc || \ validate_runit || \ validate_smf || \ validate_upstart || \ validate_hurd_init || \ echo init # fallback } init=$(find_init) if test -x "${init}" then case $init in /hurd/init) # FIXME: Create validate function echo hurd-init ;; */init) try_all ;; *) validate_by_comm_name "$(basename "${init}")" ;; esac else validate_by_comm_name "${init}" fi