aboutsummaryrefslogtreecommitdiff
path: root/src/sbin/systemctl
diff options
context:
space:
mode:
authorB Stack <bgstack15@gmail.com>2020-01-12 18:42:10 -0500
committerB Stack <bgstack15@gmail.com>2020-01-12 18:42:10 -0500
commit595982218707cbbe30e7920d3a6af8f9398e32b0 (patch)
tree0b7071723719121a6cae63e403b05b63e4773101 /src/sbin/systemctl
parentWIP: initial commit, 5% done (diff)
downloadsystemdtl-595982218707cbbe30e7920d3a6af8f9398e32b0.tar.gz
systemdtl-595982218707cbbe30e7920d3a6af8f9398e32b0.tar.bz2
systemdtl-595982218707cbbe30e7920d3a6af8f9398e32b0.zip
WIP: add most parsing
Still need to add the commands to execute the action list.
Diffstat (limited to 'src/sbin/systemctl')
-rwxr-xr-xsrc/sbin/systemctl388
1 files changed, 388 insertions, 0 deletions
diff --git a/src/sbin/systemctl b/src/sbin/systemctl
new file mode 100755
index 0000000..3f13c9d
--- /dev/null
+++ b/src/sbin/systemctl
@@ -0,0 +1,388 @@
+#!/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
+ echo "Need to perform these commands:"
+ echo "${actionlist}"
+#} | tee -a ${logfile}
+
+# EMAIL LOGFILE
+#${sendsh} ${sendopts} "${server} ${scriptfile} out" ${logfile} ${interestedparties}
+
+## STOP THE READ CONFIG FILE
+#return_code 0
+#fi ; done ; }
bgstack15