diff options
author | B Stack <bgstack15@gmail.com> | 2021-01-08 10:04:43 -0500 |
---|---|---|
committer | B Stack <bgstack15@gmail.com> | 2021-01-08 10:06:17 -0500 |
commit | 3ad1bb474880b7064da3cc1924b6d0a3a87aa14e (patch) | |
tree | 4e622e46eaffb722b93b2f7288d7a9aefad05383 | |
parent | add Makefile (diff) | |
download | systemdtl-scriptonly.tar.gz systemdtl-scriptonly.tar.bz2 systemdtl-scriptonly.zip |
abbrev script and remove everything elsescriptonly
-rw-r--r-- | Makefile | 66 | ||||
-rw-r--r-- | src/etc/systemdtl.conf | 2 | ||||
-rwxr-xr-x | src/sbin/systemctl | 395 | ||||
-rwxr-xr-x | systemctl | 617 |
4 files changed, 617 insertions, 463 deletions
diff --git a/Makefile b/Makefile deleted file mode 100644 index 6934631..0000000 --- a/Makefile +++ /dev/null @@ -1,66 +0,0 @@ -# File: Makefile for systemdtl -# Location: -# Author: bgstack15 -# Startdate: 2020-01-13 -# Title: Makefile for systemdtl source package -# Purpose: To use traditional Unix make utility -# History: -# Usage: -# Reference: -# bgscripts Makefile, beyond-the-titanic Makefile -# Improve: -# Document: -# Dependencies: - -APPNAME = systemctl -PKGNAME = systemdtl -APPVERSION = 0.0.1 -PKGDIR = $(CURDIR) -SRCDIR = $(CURDIR)/src -prefix = /usr -SBINDIR = $(DESTDIR)$(prefix)/sbin -SHAREDIR = $(DESTDIR)$(prefix)/share -CONFIGDIR = $(DESTDIR)/etc -#APPDIR = $(SHAREDIR)/$(APPNAME) -#APPSDIR = $(SHAREDIR)/applications -#DOCDIR = $(SHAREDIR)/doc/$(APPNAME) -#LICENSEDIR = $(SHAREDIR)/licenses/$(APPNAME) - -awkbin :=$(shell which awk) -cpbin :=$(shell which cp) -echobin :=$(shell which echo) -findbin :=$(shell which find) -grepbin :=$(shell which grep) -installbin :=$(shell which install) -rmbin :=$(shell which rm) -sedbin :=$(shell which sed) -sortbin :=$(shell which sort) -truebin :=$(shell which true) - -all: - ${echobin} No compilation required. - -.PHONY: clean install install_files uninstall list - -list: - @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | ${awkbin} -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | ${sortbin} | ${grepbin} -E -v -e '^[^[:alnum:]]' -e '^$@$$' - -install: install_files - -install_files: - ${echobin} Installing files to ${DESTDIR} - ${installbin} -d ${SBINDIR} ${CONFIGDIR} - ${installbin} -m0755 ${SRCDIR}/sbin/${APPNAME} ${SBINDIR} - ${installbin} -m0644 ${SRCDIR}/etc/${PKGNAME}.conf ${CONFIGDIR} - for word in $$( ${findbin} ${SRCDIR} ! -type d ! -name '*.*' -print ) ; do ${echobin} ${installbin} -m0644 $${word} ${APPDIR} ; done - -uninstall: - ${echobin} SRCDIR=${SRCDIR} - # remove all files whose path match the files from the src/ directory from this install location. - for word in $$( ${findbin} ${DESTDIR} -mindepth 1 ! -type d -printf '%p\n' | ${awkbin} '{print length, $$0 }' | ${sortbin} -rn | ${awkbin} '{print $$2}' ) ; do ${rmbin} $${word} 2>/dev/null || ${truebin} ; done - - # remove all installed directories that are now blank. - for word in $$( ${findbin} ${DESTDIR} -mindepth 1 -type d -printf '%p\n' | ${awkbin} '{print length, $$0 }' | ${sortbin} -rn | ${awkbin} '{print $$2}' ) ; do ${findbin} $${word} -mindepth 1 1>/dev/null 2>&1 | read 1>/dev/null 2>&1 || { rmdir "$${word}" 2>/dev/null || ${truebin} ; } ; done - -clean: - ${echobin} "target $@ not implemented yet! Gotta say unh." diff --git a/src/etc/systemdtl.conf b/src/etc/systemdtl.conf deleted file mode 100644 index 17b917f..0000000 --- a/src/etc/systemdtl.conf +++ /dev/null @@ -1,2 +0,0 @@ -# Part of systemdtl package -logfile="/var/log/systemctl.log" diff --git a/src/sbin/systemctl b/src/sbin/systemctl deleted file mode 100755 index 0e00b10..0000000 --- a/src/sbin/systemctl +++ /dev/null @@ -1,395 +0,0 @@ -#!/bin/sh -# Filename: systemctl -# Location: /usr/sbin/ -# Author: bgstack15@gmail.com -# Startdate: 2020-01-10 13:02:14 -# Title: -# Purpose: -# Package: systemdtl -# History: -# Usage: -# Should be mostly like systemctl from systemd. -# Reference: ftemplate.sh 2019-05-02a ; framework.sh 2018-05-02a -# man 1 systemctl -# Improve: -# x restart X(.service)? -# x start -# x stop -# x enable -# x status -# x disable -# x mask -# x unmask -# x is-enabled -# x is-active -# x list-unit-files --full -# x reload-or-try-restart X -# x condrestart X -# x daemon-reload --system -# x --now -fiversion="2019-05-02a" -systemctlversion="2020-01-10a" - -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 - -# DEFINE TRAPS - -clean_systemctl() { - # use at end of entire script if you need to clean up tmpfiles - # rm -f "${tmpfile1}" "${tmpfile2}" 2>/dev/null - - # Delayed cleanup - if test -z "${SYSTEMCTL_NO_CLEAN}" ; - then -# nohup /bin/bash <<EOF 1>/dev/null 2>&1 & -#sleep "${SYSTEMCTL_CLEANUP_SEC:-300}" ; /bin/rm -r "${SYSTEMCTL_TMPDIR:-NOTHINGTODELETE}" 1>/dev/null 2>&1 ; -#EOF - /bin/rm -r "${SYSTEMCTL_TMPDIR:-NOTHINGTODELETE}" 1>/dev/null 2>&1 ; - fi -} - -CTRLC() { - # use with: trap "CTRLC" 2 - # useful for controlling the ctrl+c keystroke - : -} - -CTRLZ() { - # use with: trap "CTRLZ" 18 - # useful for controlling the ctrl+z keystroke - : -} - -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}" ; } -} - -# DETERMINE LOCATION OF FRAMEWORK -f_needed=20181030 -___frameworkpath="$( find $( echo "${FRAMEWORKPATH}" | tr ':' ' ' ) -maxdepth 1 -mindepth 0 -name 'framework.sh' 2>/dev/null )" -while read flocation ; do if test -e ${flocation} ; then __thisfver="$( sh ${flocation} --fcheck 2>/dev/null )" ; if test ${__thisfver:-0} -ge ${f_needed} ; then frameworkscript="${flocation}" ; break ; elif test -n "${___thisfver}" ; then printf "Obsolete: %s %s\n" "${flocation}" "${__thisfver}" 1>&2 ; fi ; fi ; done <<EOFLOCATIONS -${FRAMEWORKBIN:-/bin/false} -${___frameworkpath:-/bin/false} -./framework.sh -${scriptdir}/framework.sh -$HOME/bin/bgscripts/framework.sh -$HOME/bin/framework.sh -$HOME/bgscripts/framework.sh -$HOME/framework.sh -$HOME/.local/share/bgscripts/framework.sh -/usr/local/bin/bgscripts/framework.sh -/usr/local/bin/framework.sh -/usr/bin/bgscripts/framework.sh -/usr/bin/framework.sh -/bin/bgscripts/framework.sh -/usr/local/share/bgscripts/framework.sh -/usr/share/bgscripts/framework.sh -EOFLOCATIONS -test -z "${frameworkscript}" && echo "$0: framework ${f_needed} not found. Try setting FRAMEWORKPATH. Aborted." 1>&2 && exit 4 - -# INITIALIZE VARIABLES -# variables set in framework: -# today server thistty scriptdir scriptfile scripttrim -# is_cronjob stdin_piped stdout_piped stderr_piped sendsh sendopts -. ${frameworkscript} || echo "$0: framework did not run properly. Continuing..." 1>&2 -infile1= -outfile1= -define_if_new logfile "/var/log/systemctl.log" -define_if_new interestedparties "bgstack15@gmail.com" -# SIMPLECONF -define_if_new default_conffile "/etc/systemdtl.conf" -#define_if_new defuser_conffile ~/.config/systemctl/systemctl.conf -#define_if_new SYSTEMCTL_TMPDIR "$( mktemp -d )" -#tmpfile1="$( TMPDIR="${SYSTEMCTL_TMPDIR}" mktemp )" -#tmpfile2="$( TMPDIR="${SYSTEMCTL_TMPDIR}" mktemp )" - -# REACT TO OPERATING SYSTEM TYPE -case $( uname -s ) in - Linux) : ;; - FreeBSD) : ;; - *) echo "${scriptfile}: 3. Indeterminate OS: $( uname -s )" 1>&2 && exit 3 ;; -esac - -## REACT TO ROOT STATUS -#case ${is_root} in -# 1) # proper root -# : ;; -# sudo) # sudo to root -# : ;; -# "") # not root at all -# #ferror "${scriptfile}: 5. Please run as root or sudo. Aborted." -# #exit 5 -# : -# ;; -#esac - -# SET CUSTOM SCRIPT AND VALUES -#setval 1 sendsh sendopts<<EOFSENDSH # if $1="1" then setvalout="critical-fail" on failure -#/usr/local/share/bgscripts/send.sh -hs # setvalout maybe be "fail" otherwise -#/usr/share/bgscripts/send.sh -hs # on success, setvalout="valid-sendsh" -#/usr/local/bin/send.sh -hs -#/usr/bin/mail -s -#EOFSENDSH -#test "${setvalout}" = "critical-fail" && ferror "${scriptfile}: 4. mailer not found. Aborted." && exit 4 - -# 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}" - -# CONFIRM TOTAL NUMBER OF FLAGLESSVALS IS CORRECT -#if test ${thiscount} -lt 2 ; -#then -# ferror "${scriptfile}: 2. Fewer than 2 flaglessvals. Aborted." -# exit 2 -#fi - -# LOAD CONFIG FROM SIMPLECONF -# This section follows a simple hierarchy of precedence, with first being used: -# 1. parameters and flags -# 2. environment -# 3. config file -# 4. default user config: ~/.config/script/script.conf -# 5. default config: /etc/script/script.conf -if test -f "${conffile}" ; -then - get_conf "${conffile}" -else - if test "${conffile}" = "${default_conffile}" || test "${conffile}" = "${defuser_conffile}" ; then : ; else test -n "${conffile}" && ferror "${scriptfile}: Ignoring conf file which is not found: ${conffile}." ; fi -fi -test -f "${defuser_conffile}" && get_conf "${defuser_conffile}" -test -f "${default_conffile}" && get_conf "${default_conffile}" - -# CONFIGURE VARIABLES AFTER PARAMETERS - -## START READ CONFIG FILE TEMPLATE -#oIFS="${IFS}" ; IFS="$( printf '\n' )" -#infiledata=$( ${sed} ':loop;/^\/\*/{s/.//;:ccom;s,^.[^*]*,,;/^$/n;/^\*\//{s/..//;bloop;};bccom;}' "${infile1}") #the crazy sed removes c style multiline comments -#IFS="${oIFS}" ; infilelines=$( echo "${infiledata}" | wc -l ) -#{ echo "${infiledata}" ; echo "ENDOFFILE" ; } | { -# while read line ; do -# # the crazy sed removes leading and trailing whitespace, blank lines, and comments -# if test ! "${line}" = "ENDOFFILE" ; -# then -# line=$( echo "${line}" | sed -e 's/^\s*//;s/\s*$//;/^[#$]/d;s/\s*[^\]#.*$//;' ) -# if test -n "${line}" ; -# then -# debuglev 8 && ferror "line=\"${line}\"" -# if echo "${line}" | grep -qiE "\[.*\]" ; -# then -# # new zone -# zone=$( echo "${line}" | tr -d '[]' ) -# debuglev 7 && ferror "zone=${zone}" -# else -# # directive -# varname=$( echo "${line}" | awk -F= '{print $1}' ) -# varval=$( echo "${line}" | awk -F= '{$1="" ; printf "%s", $0}' | sed 's/^ //;' ) -# debuglev 7 && ferror "${zone}${varname}=\"${varval}\"" -# # simple define variable -# eval "${zone}${varname}=\${varval}" -# fi -# ## this part is untested -# #read -p "Please type something here:" response < ${thistty} -# #echo "${response}" -# fi -# else - -## REACT TO BEING A CRONJOB -#if test ${is_cronjob} -eq 1 ; -#then -# : -#else -# : -#fi - -# SET TRAPS -#trap "CTRLC" 2 -#trap "CTRLZ" 18 -#trap '__ec=$? ; clean_systemctl ; trap "" 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; exit ${__ec} ;' 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 - -# DEBUG SIMPLECONF -debuglev 5 && { - ferror "Using values" - # used values: EX_(OPT1|OPT2|VERBOSE) - set | grep -iE "^SYSTEMCTL_" 1>&2 -} - -# MAIN LOOP -#{ - printf "%s\n" "${*}" >> "${logfile}" - #echo "thiscount=${thiscount}" - #x=1 - #while test ${x:-${thiscount}} -le $(( thiscount - 1 )) && test ${thiscount} -gt 1 ; - #do - # eval thisopt="\${opt${x}}" - # echo "thisopt${x}=${thisopt}" - # x=$(( x + 1 )) - #done - - # 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 - debuglev 5 && ferror "${thisaction}" - eval "${thisaction}" - done - fi -#} | tee -a ${logfile} - -# EMAIL LOGFILE -#${sendsh} ${sendopts} "${server} ${scriptfile} out" ${logfile} ${interestedparties} - -## STOP THE READ CONFIG FILE -#return_code 0 -#fi ; done ; } 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 +: |