#/bin/bash # $syslib mustn't contain spaces (shell language limitation) [ -e /proc/progress ] && echo 110 >/proc/progress PATH="$PATH:/bin:/sbin:/usr/bin:/usr/sbin" : ${syslib:=/etc/rc.d} # currently hardcoded in facility : ${facdir:=$syslib/fac} VERSION=1.1 VENDOR_STRING="lma-init $VERSION" : ${CONSOLE:=/dev/console} # default console : ${SUTIMEOUT:=20} # default sulogin timeout (see fatal) : ${RCDIR:=/etc} # where SYSVINIT-style rcX.d files are located : ${SYSVINIT:=0} # defaults for SYSV_EXEC and SYSV_FAC : ${SYSV_EXEC=$SYSVINIT} # execute sysv-scripts in $RCDIR/rc?.d/[SK][0-9][0-9]* : ${SYSV_FAC=$SYSVINIT} # scripts in $RCDIR/init.d/* are used to supplement builtins : ${SYSV_PRI=1} # give sysv scripts priority over lmainit facilities? : ${COALESCE:=1} : ${SULOGIN:=sulogin} : ${SINGLESTEP:=0} shopt -s extglob # load additional commands enable -f $syslib/lmainit.so console setsid winsize renamefunc usleep str2hex color_r() { r="[$1m" } tgoto_r() { r="[$(($1+1));$(($2+1))H" } setscrreg_r() { r="[$(($1+1));$(($2+1))r" } tgoto() { tgoto_r "$@"; echo -n "$r"; } color() { color_r "$@"; echo -n "$r"; } clear="" clreol="" delline="" save_cursor="7" restore_cursor="8" reset() { echo -n "c" } initscreen() { eval $(winsize) } declare -a fac_args find_facility() { local fac_mode="${1:0:1}" local fac="${1:1}" local args arg i fac_name="${fac%%::*}" local ref="fac_${fac_name}_desc" if [ -z "${!ref}" ]; then # try to load the facility if [ -r "$facdir/$fac_name.fac" ] ; then . "$facdir/$fac_name.fac" fi fi if [ -n "${!ref}" ]; then case "$fac" in *::* ) args="${fac#*::}" ;; * ) args="" ;; esac IFS=: eval 'fac_args=($args)' set -- "${fac_args[@]}" eval fac_desc="\"${!ref}\"" if [ "$fac_mode" == "+" ]; then fac_mode="start" else fac_mode="stop" fi fac_run="fac_${fac_name}_${fac_mode} \"\${fac_args[@]}\"" return 0 else fac_desc="$fac_name: no such facility" fac_run=false return 1 fi } ############################################################################# # Shamelessly stolen from the bash distribution. # This is ugly code, and I believe my version would have been faster. # Arrogance is a pity. # But my version would definitely be much shorter! # usage: reverse arrayname reverse() { local -a R local -i i local rlen temp # make r a copy of the array whose name is passed as an arg eval R=\( \"\$\{$1\[@\]\}\" \) # reverse R rlen=${#R[@]} for ((i=0; i < rlen/2; i++ )) do temp=${R[i]} R[i]=${R[rlen-i-1]} R[rlen-i-1]=$temp done # and assign R back to array whose name is passed as an arg eval $1=\( \"\$\{R\[@\]\}\" \) } ############################################################################# declare -i _cnt # start a facility definition def() { _name="$1"; shift _desc="$*" end() { renamefunc start "fac_${_name}_start" renamefunc stop "fac_${_name}_stop" eval fac_${_name}_desc='"$_desc"' unset end enddef desc _name _desc } enddef() { end; } desc() { _desc="$*" } start() { :; } stop() { :; } } # start a facility sequence defseq() { _cnt=0 eval ' fac_'$1'_seq=() add() { fac_'$1'_seq[_cnt++]="$1" } fac_'$1'_desc="$2" fac_'$1'_start() { for fac in "${fac_'$1'_seq[@]}"; do if [ "${fac:0:1}" != "-" ]; then find_facility "+${fac#+}" eval "$fac_run" fi done } fac_'$1'_stop() { for fac in "${fac_'$1'_seq[@]}"; do if [ "${fac:0:1}" != "+" ]; then find_facility "-${fac#-}" eval "$fac_run" fi done } ' end() { unset add end _cnt } } defrl() { _cnt=0 eval ' add() { _rl_'$1'[_cnt++]="$1" } ' end() { unset add end _cnt } } # define an alias (name, description, alias) defalias() { # this was a major speed bottleneck, # now it's just a readability bottleneck eval ' fac_'$1'_desc="$2" fac_'$1'_alias="$3" fac_'$1'_start() { find_facility "+$fac_'$1'_alias" eval "$fac_run" } fac_'$1'_stop() { find_facility "-$fac_'$1'_alias" eval "$fac_run" } ' } ############################################################################# fatal() { echo "$@" echo "you have $SUTIMEOUT seconds to log-in as root, otherwise booting will continue" $SULOGIN -t $SUTIMEOUT } # evaluate command and, if exit-status is non-zero, # ask the user wether she wants to log-in (by starting sulogin) safe_eval() { if ! ( "$@" ); then fatal "an error occured while running '$@'" fi } daemonize() { { cd / setsid exec "$@" exit 127 } & } kill_pidfile() { local signal="$1" local path="$2" local pidfile="$3" local pid if [ -n "$pidfile" -a -r "$pidfile" ]; then read pid <"$pidfile" fi if ((pid>0)); then kill -$signal $pid || echo "$path: pidfile exists, but no process found" elif [ -n "$path" ]; then [ -n "$pidfile" ] && echo "$path: unable to find pidfile, trying killall instead" killall -$signal "$path" fi } declare -a facilities _get_facilities() { local RL="$1" local mode="$2" local i=0 j local omode="-"; [ $mode == "-" ] && omode="+" local -a facs eval facs=(\"\${_rl_$RL[@]}\") for fac in "${facs[@]}"; do if [ "$fac" == "${fac#$omode}" ]; then # facilities not prefixed with OMODE are also o.k. fac="${fac#$mode}" # facilities prefixed with the MODE are o.k. if [ "$fac" == "${fac#@}" ]; then j=${#facilities[@]} facilities[j]="$mode$fac" else _get_facilities "${fac#@}" "$mode" fi fi done } new_facilities() { facilities=() } declare -i _sysvfac_cnt=0 add_facilities() { _get_facilities "$1" "$2" # optionally check for sysv facilities if ((SYSV_EXEC)); then local prefix=S fac j [[ "$2" == "-" ]] && prefix=K local -a sysvfac prefix="$RCDIR/rc$1.d/$prefix[0-9][0-9]" for scr in $prefix*; do if [ -x "$scr" ]; then fac="_sysvfac$_sysvfac_cnt" eval "fac_${fac}_desc"='"${scr#$prefix}"' eval " fac_${fac}_start() { \"$scr\" start } fac_${fac}_stop() { \"$scr\" stop } " sysvfac[_sysvfac_cnt++]="$2$fac" fi done [[ "$2" == "-" ]] && reverse sysvfac facilities=("${facilities[@]}" "${sysvfac[@]}") fi } rev_facilities() { reverse facilities } # check facilities for dupes ("-mysqld +mysqld" and remove them both) coalesce_facilities() { local -a _facilities _facilities=("${facilities[@]}") facilities=() # pass 1, find dupes for fac in "${_facilities[@]}"; do if [ "${fac:0:1}" == "-" ]; then eval local off_$(str2hex "${fac:1}")=1 elif eval '(($'off_$(str2hex "${fac:1}")'))'; then eval local ignore_$(str2hex "${fac:1}")=1 fi done # pass 2, copy all unique facility changes local -i cnt=0 for fac in "${_facilities[@]}"; do if ! eval '(($'ignore_$(str2hex "${fac:1}")'))'; then facilities[cnt++]="$fac" fi done } # gay penguin pengo1_r() { r="\  . .                         \`----'    ......    ........    .........    .........    ..........   ..........   ........    ........    ........    ......  " } # fat penguin pengo2_r() { r="\ ####################### ####################### ##########O#O########## ####################### ####################### ####################### ####################### ####################### ####################### ####################### ####################### #######################" } # # title: # ---(VENDOR_STRING)------------------(TITLE)-------------------------------- # or # ----------------------------------(TITLE)---------------------------------- _bars="------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------" show_title () { local opt="$1" local -i offs=0 tgoto 0 0 color 37 echo -n "${_bars:0:$cols}" if [ -n "$VENDOR_STRING" ] ; then offs=$(((${#VENDOR_STRING})+6)) tgoto 0 3 echo -n "(" color 33 echo -n "$VENDOR_STRING" color 37 echo -n ")" color 33 fi tgoto 0 $(((cols-offs-${#opt})/2+offs)) echo -n "(" color 33 echo -n "$opt" color 37 echo -n ")" color 36 } #< w1 >< w2 > ##################################^ # pengo title #h1 # pengo # # pengo x1 # # xn #v #________________________________# # # ################################## run_facilities() { local title="$1" ((COALESCE)) && coalesce_facilities ((DRY_RUN)) || console "$CONSOLE" initscreen local -i nfac=${#facilities[@]} local -i h1=rows/3 local -i w1=PENGUIN?24:0 local -i w2=cols-w1 local -i y n wfac local pengo color "31;44;1"; local C_error="$r" color "36;44;1"; local C_fac="$r" color "33"; local C_desc="$r" color "37"; local C_text="$r" tgoto_r 1 0; pengo="$r" ((h1>nfac+2)) && h1=nfac+2 if ((PENGUIN==1)); then ((h1<18)) && h1=18 pengo1_r; pengo="$pengo$r" elif ((PENGUIN==2)); then ((h1<14)) && h1=14 pengo2_r; pengo="$pengo$r" fi pengo="$pengo$C_fac" echo -n "$C_fac$fac$clear" show_title "$title" echo -n "$pengo" wfac=h1-1 if ((wfac>nfac)); then wfac=nfac fi for((y=0; y