aboutsummaryrefslogtreecommitdiff
path: root/systemctl
diff options
context:
space:
mode:
Diffstat (limited to 'systemctl')
-rwxr-xr-xsystemctl617
1 files changed, 617 insertions, 0 deletions
diff --git a/systemctl b/systemctl
new file mode 100755
index 0000000..eb4e6b6
--- /dev/null
+++ b/systemctl
@@ -0,0 +1,617 @@
+#!/bin/sh
+# Filename: systemctl
+# Location: /usr/bin/systemctl
+# /usr/bin/hostnamectl
+# /usr/bin/systemd-detect-virt
+# Author: bgstack15@gmail.com
+# Startdate: 2020-01-10 13:02:14
+# SPDX-License-Identifier: CC-BY-SA-4.0
+# Title:
+# Purpose:
+# Package: devuan-sanity
+# History:
+# 2020-05-14 place framework.sh contents inline so as not to depend on it.
+# 2021-01-08 adapted for inclusion in devuan-sanity
+# Usage:
+# Should be mostly like systemctl from systemd.
+# Reference: ftemplate.sh 2019-05-02a ; framework.sh 2018-05-02a
+# man 1 systemctl
+# Improve:
+# add preset
+# Documentation:
+# Be aware that real systemd systemctl is file /bin/systemctl but
+# this systemdtl is file /usr/bin/systemctl to prevent a recursive loop
+# in some service scripts that look for /bin/systemctl
+fiversion="2019-05-02a"
+systemctlversion="2021-01-08b"
+
+usage() {
+ ${PAGER:-/usr/bin/less -F} >&2 <<ENDUSAGE
+usage: systemctl [-duV] [-c conffile]
+Provides a systemctl-like interface to sysvinit. Simulates (poorly)
+various actions on services: start, stop, restart, enable, disable,
+status, mask, unmask, is-enabled, is-active, condrestart
+version ${systemctlversion}
+ -d debug Show debugging info, including parsed variables.
+ -u usage Show this usage block.
+ -V version Show script version number.
+ -c conf Read in this config file.
+Return values:
+ 0 Normal
+ 1 Queried service is disabled/inactive
+ 2 Count or type of flaglessvals is incorrect
+ 3 Incorrect OS type
+ 4 Unable to find dependency
+ 5 Not run as root or sudo
+ENDUSAGE
+}
+
+# DEFINE FUNCTIONS
+log_to_file() {
+ flecho "${@}" >> "${logfile}"
+}
+
+parseFlag() {
+ flag="$1"
+ hasval=0
+ case ${flag} in
+ # INSERT FLAGS HERE
+ "d" | "debug" | "DEBUG" | "dd" ) setdebug ; ferror "debug level ${debug}" ; __debug_set_by_param=1 ;;
+ "u" | "usage" | "help" | "h" ) usage ; exit 0 ;;
+ "V" | "fcheck" | "version" ) ferror "${scriptfile} version ${systemctlversion}" ; exit 0 ;;
+ #"i" | "infile" | "inputfile" ) getval ; infile1=${tempval} ;;
+ "c" | "conf" | "conffile" | "config" ) getval ; conffile="${tempval}" ;;
+ "now" ) export SYSTEMCTL_NOW=1 ;;
+ "full") export SYSTEMCTL_FULL=1 ;;
+ "system") export SYSTEMCTL_SYSTEM=1 ;;
+ esac
+
+ debuglev 10 && { test ${hasval} -eq 1 && ferror "flag: ${flag} = ${tempval}" || ferror "flag: ${flag}" ; }
+}
+
+# INITIALIZE VARIABLES
+# variables set in framework:
+# server scriptdir scriptfile scripttrim
+
+### BEGIN IMPORT OF FRAMEWORK.SH
+
+fversion="2020-04-24a"
+
+# DEFINE FUNCTIONS
+
+isflag() {
+ # input: $1=word to parse
+ case "$1" in
+ --*) retval=2 ;;
+ -*) retval=1 ;;
+ *) retval=0 ;;
+ esac
+ echo $retval
+}
+
+parseParam() {
+ # determines if --longname or -shortflagS that need individual parsing
+ trimParam=$( printf '%s' "${param}" | sed -n 's/--//p' )
+ _rest=
+ if test -n "$trimParam" ;
+ then
+ parseFlag $trimParam
+ else
+ #splitShortStrings
+ _i=2
+ while test ${_i} -le ${#param} ;
+ do
+ _j=$( expr ${_i} + 1)
+ #_char=$(expr substr "$param" $_i 1)
+ #_rest=$(expr substr "$param" $_j 255)
+ _char=$( printf '%s' "${param}" | cut -c ${_i})
+ _rest=$( printf '%s' "${param}" | cut -c ${_j}-255)
+ parseFlag $_char
+ _i=$( expr ${_i} + 1)
+ done
+ fi
+}
+
+getval() {
+ tempval=
+ if test -n "${_rest}" ;
+ then
+ tempval="${_rest}"
+ hasval=1
+ _i=255 # skip rest of splitShortStrings because found the value!
+ elif test -n "$nextparam" && test $(isflag "$nextparam") -eq 0 ;
+ then
+ tempval="$nextparam"
+ hasval=1 #DNE ; is affected by ftemplate!
+ paramnum=$nextparamnum
+ fi
+}
+
+debuglev() {
+ # call: debuglev 5 && ferror "debug level is at least a five!"
+ # added 2015-11-17
+ localdebug=0 ; localcheck=0 ;
+ fisnum ${debug} && localdebug=${debug}
+ fisnum ${1} && localcheck=${1}
+ test $localdebug -ge $localcheck && return 0 || return 1
+}
+
+debuglevoutput() {
+ # call: commandthatgeneratesstdout | debuglevoutput 8
+ # output: output to standard error prepended with "debug8: " the contents of the pipe
+ ___dlo_threshold="${1}"
+ ___dlo_silent="${2}"
+ if debuglev "${___dlo_threshold}" ;
+ then
+ if test -n "${___dlo_silent}" ;
+ then
+ cat 1>&2
+ else
+ sed -r -e "s/^/debug${___dlo_threshold}: /;" 1>&2
+ fi
+ else
+ cat 1>/dev/null 2>&1
+ fi
+}
+
+fisnum() {
+ # call: fisnum $1 && debug=$1 || debug=10
+ fisnum= ;
+ case $1 in
+ ''|*[!0-9]*) fisnum=1 ;; # invalid
+ *) fisnum=0 ;; # valid number
+ esac
+ return ${fisnum}
+}
+
+fistruthy() {
+ # call: if fistruthy "$val" ; then
+ local _return=
+ case "$( echo "${1}" | tr '[:upper:]' '[:lower:]' )" in
+ yes|1|y|true|always) _return=true ;;
+ esac
+ test -n "${_return}" ; return $?
+}
+
+setval() {
+ # call: setval 0 value1 value2 value3 ... <<EOFOPTIONS
+ # /bin/foo1 --optforfoo1
+ # /usr/bin/foo2 --optforfoo2
+ # EOFOPTIONS
+ # ^ 0 = soft fail, 1 = critical-fail
+ quitonfail="${1}" ; shift
+ _vars="${@}"
+ #echo "_vars=${_vars}"
+ _varcount=0
+ for _word in ${_vars} ; do _varcount=$( expr $_varcount + 1 ) ; eval "_var${_varcount}=${_word}" ; done
+ _usethis=0
+ while read line ;
+ do
+ _varcount=0
+ if test ! "${_usethis}x" = "0x" ; then break ; fi
+ #echo "line=${line}" ;
+ for _word in ${line} ;
+ do
+ _varcount=$( expr $_varcount + 1 )
+ #echo "word ${_varcount}=${_word}" ;
+ case "${_varcount}" in
+ 1)
+ #echo "Testing for existence of file ${_word}"
+ if test -f "${_word}" ;
+ then
+ _usethis=1
+ #echo "${_var1}=${_word}"
+ eval "${_var1}=${_word}"
+ fi
+ ;;
+ *)
+ #echo "just an option: ${_word}"
+ if test "${_usethis}x" = "1x" ;
+ then
+ #eval echo "\${_var${_varcount}}=${_word}"
+ eval eval "\${_var${_varcount}}=${_word}"
+ fi
+ ;;
+ esac
+ done
+ done
+ #eval echo "testfile=\$${_var1}"
+ eval _testfile=\$${_var1}
+ if test ! -f "${_testfile}" ;
+ then
+ case "${quitonfail}" in 1) _failval="critical-fail" ;; *) _failval="fail" ;; esac
+ eval "${_var1}=${_failval}"
+ setvalout=${_failval}
+ else
+ eval setvalout="valid-${_var1}"
+ fi
+}
+
+flecho() {
+ if test "$lechoscript" = "" ; #so only run the first time!
+ then
+ setval 0 lechoscript << EOFLECHOSCRIPTS
+./plecho.sh
+${scriptdir}/plecho.sh
+~/bin/bgscripts/plecho.sh
+~/bin/plecho.sh
+~/bgscripts/plecho.sh
+~/plecho.sh
+/usr/local/bin/bgscripts/plecho.sh
+/usr/local/bin/plecho.sh
+/usr/bin/bgscripts/plecho.sh
+/usr/bin/plecho.sh
+/usr/bin/plecho
+/bin/bgscripts/plecho.sh
+/usr/local/share/bgscripts/plecho.sh
+/usr/share/bgscripts/plecho.sh
+/usr/libexec/bgscripts/plecho.sh
+EOFLECHOSCRIPTS
+ lechoscriptvalid="${setvalout}"
+ fi
+ if test "$lechoscriptvalid" = "valid-lechoscript" ;
+ then
+ $lechoscript "$@"
+ else
+ #ORIGINAL echo [`date '+%Y-%m-%d %T'`]$USER@`uname -n`: "$*"
+ myflecho() {
+ mflnow=$( date '+%Y-%m-%d %T' )
+ while test -z "$1" && test -n "$@" ; do shift ; done
+ sisko="$@"
+ test -z "$sisko" && \
+ printf "[%19s]%s@%s\n" "$mflnow" "$USER" "$server" || \
+ printf "[%19s]%s@%s: %s\n" "$mflnow" "$USER" "$server" "${sisko#" *"}" ;
+ }
+ if test ! -t 0 ; # observe that this is different from plecho
+ then
+ _x=0
+ while read line ;
+ do
+ _x=1
+ myflecho "$@" "$line"
+ done
+ test $_x -eq 0 && myflecho "$@" "$line"
+ else
+ myflecho "$@"
+ fi
+ fi
+}
+
+ferror() {
+ # call: ferror "$scriptfile: 2. Something bad happened-- error message 2."
+ echo "$@" 1>&2
+}
+
+setdebug() {
+ # call: setdebug
+ debug=10
+ getval
+ if test $hasval -eq 1 ;
+ then
+ if fisnum ${tempval} ;
+ then
+ debug=${tempval}
+ else
+ #test paramnum -le paramcount && paramnum=$( expr ${paramnum} - 1 )
+ hasval=0
+ fi
+ elif fisnum ${_rest} ;
+ then
+ debug=${_rest}
+ _i=255
+ else
+ test $paramnum -le $paramcount && test -z ${nextparam} && paramnum=$( expr ${paramnum} - 1 )
+ fi
+}
+
+isvalidip() {
+ # call: if isvalidip "${input}" ; then echo yes ; fi
+ # or: isvalidip $input && echo yes
+ iptotest="${1}"
+ echo "${iptotest}" | grep -qoE "^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})$"
+}
+
+get_conf() {
+ # call: get_conf "${conffile}"
+ local _infile="$1"
+ local _tmpfile1="$( mktemp )"
+ sed -e 's/^\s*//;s/\s*$//;/^[#$]/d;s/\s*[^\]#.*$//;' "${_infile}" | grep -viE "^$" | while read _line ;
+ do
+ local _left="$( echo "${_line}" | cut -d'=' -f1 )"
+ eval "_thisval=\"\${${_left}}\""
+ test -z "${_thisval}" && echo "${_line}" >> "${_tmpfile1}"
+ done
+ test -f "${_tmpfile1}" && { . "${_tmpfile1}" 1>/dev/null 2>&1 ; debuglev 10 && cat "${_tmpfile1}" 1>&2 ; }
+ /bin/rm -rf "${_tmpfile1}" 1>/dev/null 2>&1
+}
+
+define_if_new() {
+ # call: define_if_new IFW_IN_LOG_FILE "/var/log/messages"
+ eval thisval="\${${1}}"
+ test -z "${thisval}" && eval "$1"=\"$2\"
+}
+
+fchmodref() {
+ # call: fchmodref "${oldfile}" "${newfile}"
+ local oldfile="${1}"
+ local newfile="${2}"
+ case "${thisos}" in
+ Linux)
+ chmod --reference "${oldfile}" "${newfile}"
+ ;;
+ FreeBSD)
+ chmod $( stat -f '%p' "${oldfile}" ) "${newfile}"
+ ;;
+ esac
+}
+
+return_code() {
+ # call: return_code 45
+ return $1 ;
+}
+
+# INITIALIZE VARIABLES
+#infile1=
+#outfile1=
+#logfile=
+server=$( hostname -s )
+thisos="$( uname -s )"
+# get thisflavor and thisflavorversion. Examples: centos, ubuntu, redhat
+if test -f /etc/os-release ;
+then
+ eval thisflavor=$( grep -iE "^\s*ID=" /etc/os-release 2>/dev/null | sed 's/^.*=//;' | tr 'A-Z' 'a-z' )
+ eval thisflavorversion=$( grep -iE "^\s*PRETTY_NAME=" /etc/os-release 2>/dev/null | sed -e 's/^.*=//;' | tr -dc '0-9.' )
+elif test -f /etc/system-release && test $( wc -l < /etc/system-release 2>/dev/null ) -eq 1 ;
+then
+ eval thisflavor=$( awk '{print $1}' < /etc/system-release 2>/dev/null | tr 'A-Z' 'a-z' )
+ eval thisflavorversion=$( </etc/system-release sed -e 's/^.*=//;' 2>/dev/null | tr -dc '0-9.' )
+else
+ if test "${thisos}" = "FreeBSD" ; then
+ thisflavor="$( uname -i )" ; thisflavorversion="$( uname -r )" ;
+ else
+ thisflavor="other"
+ thisflavorversion="unknown"
+ fi
+fi
+case "${thisos}" in FreeBSD) sed=gsed ;; *) sed=sed ;; esac
+
+# if framework is dot sourced then $0 will be "-bash" and screw things up
+case ${0} in
+ "-bash")
+ scriptdir="$( pwd )"
+ scriptfile="dot-sourced" ;;
+ *)
+ scriptdir="$( cd $( dirname ${0} ) ; pwd )"
+ scriptfile="$( basename ${0} | sed 's!/./!/!g;s!\./!!g' )"
+ scripttrim="${scriptfile%%.sh}"
+ ;;
+esac
+
+# SPECIAL RUNTIME-RELATED VARIABLES
+{ test "$USER" = "root" || test "$( stat -c '%u' /proc/$$/exe 2>/dev/null )" = 0 ; } && is_root=1
+test -n "$SUDO_USER" && is_root="sudo"
+
+nullflagcount=0
+validateparams() {
+ # VALIDATE PARAMETERS
+ # scroll through all parameters and check for isflag.
+ # if isflag, get all flags listed. Also grab param#.
+ paramcount=$#
+ thiscount=0 ;thisopt=0 ;freeopt=0 ;
+ varsyet=0
+ paramnum=0
+ debug=0
+ fallopts=
+ while test $paramnum -lt $paramcount ;
+ do
+ paramnum=$( expr ${paramnum} + 1 )
+ eval param=\${$paramnum}
+ nextparamnum=$( expr ${paramnum} + 1 )
+ eval nextparam=\${$nextparamnum}
+ case $param in
+ "-")
+ if test "$varsyet" = "0" ;
+ then
+ # first instance marks beginning of flags and parameters.
+ #Until then it was the names of variables to fill.
+ varsyet=1
+ else
+ nullflagcount=$( expr ${nullflagcount} + 1 ) #useful for separating flags from something else?
+ debuglev 10 && ferror "null flag!" # second instance is null flag.
+ fi
+ ;;
+ esac
+ if test -n "$param" ;
+ then
+ # parameter $param exists.
+ if test $(isflag $param) -gt 0 ;
+ then
+ # IS FLAG
+ parseParam
+ else
+ # IS VALUE
+ if test "$varsyet" = "0" ;
+ then
+ thisopt=$( expr ${thisopt} + 1 )
+ test "${param}" = "DEBUG" && debug=10 && thisopt=$( expr ${thisopt} - 1 ) || \
+ eval "varname${thisopt}=${param}"
+ #varname[${thisopt}]="${param}"
+ debuglev 10 && ferror "var \"${param}\" named"
+ else
+ thiscount=$( expr ${thiscount} + 1 )
+ test $thiscount -gt $thisopt && freeopt=$( expr ${freeopt} + 1 )
+ #eval ${varname[${thiscount}]:-opt${freeopt}}="\"${param}\""
+ eval "thisvarname=\${varname${thiscount}}"
+ test -z "${thisvarname}" && eval "thisvarname=opt${freeopt}"
+ eval "${thisvarname}=\"${param}\""
+ eval fallopts=\"${fallopts} ${param}\"
+ debuglev 10 && ferror "${thisvarname} value: ${param}"
+ fi
+ fi
+ fi
+ done
+ fallopts="${fallopts# }"
+ if debuglev 10 ;
+ then
+ ferror "thiscount=$thiscount"
+ ferror "fallopts=$fallopts"
+ ferror "Framework $fversion"
+ ferror "Finput $fiversion"
+ fi
+}
+### END IMPORT
+
+define_if_new logfile "/var/log/systemctl.log"
+
+# REACT TO OPERATING SYSTEM TYPE
+case $( uname -s ) in
+ Linux) : ;;
+ FreeBSD) : ;;
+ *) echo "${scriptfile}: 3. Indeterminate OS: $( uname -s )" 1>&2 && exit 3 ;;
+esac
+
+# VALIDATE PARAMETERS
+# objects before the dash are options, which get filled with the optvals
+# to debug flags, use option DEBUG. Variables set in framework: fallopts
+validateparams action - "$@"
+
+# LEARN EX_DEBUG
+test -z "${__debug_set_by_param}" && fisnum "${SYSTEMCTL_DEBUG}" && debug="${SYSTEMCTL_DEBUG}"
+debug=10
+
+# CONFIGURE VARIABLES AFTER PARAMETERS
+
+log_to_file "${0} ${@}"
+case "${0}" in
+ *hostnamectl|*systemd-detect-virt) exit 0 ;;
+esac
+
+# MAIN LOOP
+#{
+
+ # actions
+ actionlist=""
+ case "${action}" in
+
+ restart|start|stop|status|reload|condrestart|try-restart|reload-or-try-restart)
+ # re-map a few actions
+ case "${action}" in
+ "reload-or-try-restart") action=restart ;;
+ esac
+ x=1
+ while test ${x:-${thiscount}} -le $(( thiscount - 1 )) && test ${thiscount} -gt 1 ;
+ do
+ eval thisopt="\${opt${x}}"
+ thisopt="$( echo "${thisopt}" | sed -r -e 's/\.service$//;' )"
+ actionstatement="$( printf "%s" "service ${thisopt} ${action};" )"
+ actionlist="${actionlist:+${actionlist} }${actionstatement}"
+ x=$(( x + 1 ))
+ done
+ ;;
+
+ enable|disable|mask|unmask)
+ case "${action}" in
+ mask) action=disable ;;
+ unmask) action=enable ;;
+ esac
+ x=1
+ while test ${x:-${thiscount}} -le $(( thiscount - 1 )) && test ${thiscount} -gt 1 ;
+ do
+ eval thisopt="\${opt${x}}"
+ thisopt="$( echo "${thisopt}" | sed -r -e 's/\.service$//;' )"
+ actionstatement="$( printf "%s" "update-rc.d ${thisopt} ${action};" )"
+ actionlist="${actionlist:+${actionlist} }${actionstatement}"
+ test "${SYSTEMCTL_NOW}" = "1" && {
+ case "${action}" in
+ enable)
+ nowaction=start
+ ;;
+ disable)
+ nowaction=stop
+ ;;
+ esac
+ actionstatement="$( printf "%s" "service ${thisopt} ${nowaction:-stop};" )"
+ actionlist="${actionlist:+${actionlist} }${actionstatement}"
+ }
+ x=$(( x + 1 ))
+ done
+ ;;
+
+ daemon-reload)
+ debuglev 1 && echo "${action} is a NOP."
+ ;;
+
+ list-unit-files)
+ # Future improvement: can consume --full, but I do not care enough to deal with it now.
+ ls -Al /etc/init.d
+ ;;
+
+ is-enabled)
+ currentrunlevel="$( who -r | grep -oE 'run-level\s+[[:digit:]]+' | awk '{print $NF}' )"
+ responsenumber=1
+
+ # loop through each service on the command line
+ x=1
+ while test ${x:-${thiscount}} -le $(( thiscount - 1 )) && test ${thiscount} -gt 1 ;
+ do
+ eval thisopt="\${opt${x}}"
+ thisopt="$( echo "${thisopt}" | sed -r -e 's/\.service$//;' )"
+ #actionstatement="$( printf "%s" "service ${thisopt} ${action};" )"
+ scriptfile="$( find "/etc/rc${currentrunlevel}.d" -mindepth 1 -maxdepth 1 -name "S??${thisopt}" 2>/dev/null )"
+ responsetext="disabled"
+ # if file exists, let us return 0.
+ if test -n "${scriptfile}" ;
+ then
+ debuglev 2 && echo "${scriptfile}"
+ responsenumber=0 # any "enabled" response makes systemctl return 0
+ responsetext="enabled"
+ fi
+ echo "${responsetext:-UNKNOWN}"
+ x=$(( x + 1 ))
+ done
+ exit "${responsenumber}"
+ ;;
+
+ is-active)
+ responsenumber=3
+ x=1
+ while test ${x:-${thiscount}} -le $(( thiscount - 1 )) && test ${thiscount} -gt 1 ;
+ do
+ eval thisopt="\${opt${x}}"
+ thisopt="$( echo "${thisopt}" | sed -r -e 's/\.service$//;' )"
+ #actionstatement="$( printf "%s" "service ${thisopt} ${action};" )"
+ servicestatus="$( service "${thisopt}" status 1>/dev/null 2>&1 ; echo "${?}" )"
+ responsetext="stopped"
+ # if file exists, let us return 0.
+ if test ${servicestatus:-1} -eq 0 ;
+ then
+ responsenumber=0
+ responsetext="active"
+ fi
+ echo "${responsetext:-unknown}"
+ x=$(( x + 1 ))
+ done
+ exit "${responsenumber}"
+ ;;
+
+ *)
+ ferror "Fatal! 2. Unable to understand action ${action}. Aborted."
+ exit 2
+ ;;
+ esac
+
+ # list of actions
+ if test -n "${actionlist}" ;
+ then
+ #debuglev 1 && ferror "Full list: ${actionlist}"
+ printf "%s" "${actionlist}" | tr ';' '\n' | while read thisaction ;
+ do
+ log_to_file "ACTION: ${thisaction}"
+ debuglev 5 && ferror "${thisaction}"
+ eval "${thisaction}"
+ done
+ fi
+#} | tee -a ${logfile}
+
+# exit cleanly
+:
bgstack15