#!/bin/bash ALLSCRIPTS="/etc/runvdr" ACTIVESCRIPTS="/etc/runvdr/conf.d" LINKREL="../" ##################### # OSDServer helpers # ##################### # convenient return values true=0 false=1 function error() { # Fatal error. Send quit command, close FIFO and terminate netcat [ "${reply2xx[0]}" != 202 ] && SendCmd Quit exec 3>&- exec 4>&- kill $pid exit 1 } function ConnectServer() { # Connect to the OSDServer # Set up temporary fifo and open as file descriptor 3 and 4 mkfifo --mode=700 /tmp/pipe-in$$ /tmp/pipe-out$$ exec 3<> /tmp/pipe-in$$ exec 4<> /tmp/pipe-out$$ rm /tmp/pipe-in$$ /tmp/pipe-out$$ # Connect to server using the fifo { netcat $1 $2 # In case of connection loss: echo 499 disconnected echo 202 Good Bye. } <&3 >&4 & pid=$! # Sending to the server: use >&3 # Receive from the server: use <&4 } function ReadReply() { # Read a complete server reply until 2xx return code, # and store replies in each category by number reply2xx=() reply3xx=() reply4xx=() reply5xx=() reply6xx=() while read -r code line <&4 ; do if [ "$OSDSERVER_DEBUG" ] ; then echo "< $code $line" ; fi # screen echo case $code in 2*) IFS=$' \t\n\r' reply2xx=($code "$line") ;; 3*) IFS=$' \t\n\r' reply3xx=($code $line) ;; 4*) IFS=$' \t\n\r' reply4xx=($code "$line") ;; 5*) IFS=$' \t\n\r' reply5xx=($code "$line") ;; 6*) IFS=$' \t\n\r' reply6xx=($code "$line") ;; esac [ -n "${reply2xx[0]}" ] && break done [ -n "${reply4xx[0]}" ] && return $false return $true } function SendCmd() { # Send a command and read the reply if [ "$OSDSERVER_DEBUG" ] ; then echo "> $*" ; fi # screen echo echo "$*" >&3 # network send ReadReply } function IsEvent() { # Helper to check reply for a certain event [ "${reply3xx[0]}" != 300 ] && return $false [ "${reply3xx[1]}" != "$1" ] && return $false [ "${reply3xx[2]}" != "$2" ] && return $false return $true } function QuoteString() { # Quote arbitrary string for use in '' and "" local str="${!1}" str="${str//'\'/\\\\}" str="${str//'\\'/\\\\}" # work around bash bug: double quoted '\' str="${str//\'/$'\\\''}" # This is bogus, anyone knows something better to replace ' by \' ? str="${str//\"/\\\"}" str="${str//$'\r'/\\r}" str="${str//$'\n'/\\n}" str="${str//$'\t'/\\t}" eval "$1=\$str" } function UnquoteString() { # Unquote string local str="${!1}" str="${str//\\r/$'\r'}" str="${str//\\n/$'\n'}" str="${str//\\t/$'\t'}" str="${str//\\\"/\"}" str="${str//\\\'/\'}" str="${str//\\\\/\\}" eval "$1=\$str" } ######################### # runvdr-conf.d helpers # ######################### function GetConfInfo() { name="" defaultprio=50 loaded="" local tmp if [ ! -f "$ALLSCRIPTS/$1" ] ; then return 1 fi while read -r line ; do tmp="${line#\# Plugin name:}" if [ "$tmp" != "$line" ] ; then name="${tmp# }" fi tmp="${line#\# Default priority:}" if [ "$tmp" != "$line" ] ; then tmp="${tmp#\# Default priority:}" while [ "${tmp# }" != "$tmp" ] ; do tmp="${tmp# }" ; done while [ "${tmp% }" != "$tmp" ] ; do tmp="${tmp% }" ; done if [ -z "${tmp#[0-9]}" ] ; then tmp="0$tmp" ; fi if [ -z "${tmp#[0-9][0-9]}" ] ; then defaultprio="$tmp" fi fi done < "$ALLSCRIPTS/$1" if [ -z "$name" ] ; then return 1 fi tmp=("$ACTIVESCRIPTS"/[0-9][0-9]"$1") tmp="${tmp[0]}" if [ -f "$tmp" ] ; then tmp="${tmp:${#ACTIVESCRIPTS}+1}" loaded="${tmp:0:2}" fi return 0 } function GetAllConfInfo() { local glob="*" if [ "$1" ] ; then glob="$1" ; fi confs=0 confs_short=() confs_name=() confs_defaultprio=() confs_loaded=() local i for i in "$ALLSCRIPTS"/$glob ; do i="${i:${#ALLSCRIPTS}+1}" if [ -f "$ALLSCRIPTS/$i" ] && GetConfInfo "$i" ; then confs_short[$confs]="$i" confs_name[$confs]="$name" confs_defaultprio[$confs]="$defaultprio" confs_loaded[$confs]="$loaded" let confs++ fi done } function Command_Show() { GetAllConfInfo "$1" local i; for ((i=0;i&2 ; exit 1 ; } newloaded="$loaded" if [ -z "$newloaded" ] ; then newloaded="$defaultprio" fi if [ "$2" == "--prio" ] ; then newloaded="$3" while [ "${newloaded# }" != "$newloaded" ] ; do newloaded="${newloaded# }" ; done while [ "${newloaded% }" != "$newloaded" ] ; do newloaded="${newloaded% }" ; done if [ -z "${newloaded#[0-9]}" ] ; then newloaded="0$newloaded" ; fi if [ "${newloaded#[0-9][0-9]}" ] ; then echo "Not a valid priority: $3" >&2 exit 1 fi fi echo -n "Enabling $name" mkdir -p "$ACTIVESCRIPTS" if [ "$loaded" ] ; then rm -f "$ACTIVESCRIPTS"/[0-9][0-9]"$short" fi ln -s "$LINKREL$short" "$ACTIVESCRIPTS/$newloaded$short" echo "." } function Command_Disable() { short="$1" if [ -z "$short" ] ; then echo "Usage: $0 disable conf-name" exit 1 fi GetConfInfo "$short" || { echo "Unknown Plugin $short" >&2 ; exit 1 ; } if [ -z "$loaded" ] ; then echo "$short is not loaded." >&2 exit 1 fi echo -n "Disabling $name" rm -f "$ACTIVESCRIPTS"/[0-9][0-9]"$short" echo "." } function Osdserver_edit() { local short="${confs_short[$1]}" QuoteString short local name="${confs_name[$1]}" QuoteString name local defaultprio="${confs_defaultprio[$1]}" local loaded="${confs_loaded[$1]}" local enable="Yes" if [ -z "$loaded" ] ; then enable="No" loaded="$defaultprio" fi SendCmd "enterlocal" || return $false # Preserve global variable space, so we can re-use 'menu' SendCmd "menu=New Menu 'Edit $name'" || return $false SendCmd "menu.SetColumns 15" || return $false SendCmd "menu.EnableEvent keyOk close" || return $false SendCmd "menu.AddNew OsdItem -unselectable 'Short name:\\t$short'" || return $false SendCmd "menu.AddNew OsdItem -unselectable 'Long name:\\t$name'" || return $false SendCmd "menu.AddNew OsdItem -unselectable 'Default priority:\\t$defaultprio'" || return $false SendCmd "enable=menu.AddNew EditListItem Enabled No Yes -SelectName '$enable'" || return $false SendCmd "enable.SetCurrent" || return $false SendCmd "prio=menu.AddNew EditIntItem -min 0 -max 99 'Current priority:' '$loaded'" || return $false SendCmd "_focus.addsubmenu menu" || return $false SendCmd "menu.show" || return $false while true; do SendCmd "menu.SleepEvent" || return $false if IsEvent menu keyOk ; then SendCmd "enable.GetValue -name" || return $false [ "${reply6xx[0]}" != 600 ] && return $false enable="${reply6xx[1]}" SendCmd "prio.GetValue" || return $false [ "${reply6xx[0]}" != 600 ] && return $false prio="${reply6xx[1]}" if [ "$enable" == "Yes" ] ; then Command_Enable "$short" --prio "$prio" confs_loaded[$1]="$prio" elif [ -n "${confs_loaded[$1]}" ] ; then Command_Disable "$short" confs_loaded[$1]="" fi SendCmd "menu.SendState osBack" || return $false SendCmd "delete menu" || return $false SendCmd "leavelocal" || return $false return $true fi if IsEvent menu close ; then SendCmd "delete menu" || return $false SendCmd "leavelocal" || return $false return $true fi done } function Osdserver_main() { SendCmd "menu=New Menu 'Runvdr config'" || return $false SendCmd "menu.SetColumns 5" || return $false SendCmd "menu.EnableEvent close" || return $false local i; local min=0 local prio until [ "$min" -ge 100 ] ; do local nextmin=100 for ((i=0;i&- exec 4>&- # close FIFOs } function Command_Osdserver() { if [ "$1" == "--debug" ] ; then OSDSERVER_DEBUG=1 Osdserver_connect else Osdserver_connect /dev/null & fi } if [ "$1" == "show" ] ; then shift Command_Show "$@" elif [ "$1" == "enable" ] ; then shift Command_Enable "$@" elif [ "$1" == "disable" ] ; then shift Command_Disable "$@" elif [ "$1" == "osdserver" ] ; then shift Command_Osdserver "$@" elif [ "$1" == "" -o "$1" == "help" ] ; then cat << "ENDOFTEXT" Supported commands: runvdr-conf.d show [conf-name] Show current config for one or all plugins runvdr-conf.d enable conf-name [--prio #] Enable a plugin runvdr-conf.d disable conf-name Disable a plugin runvdr-conf.d osdserver Launch osdserver interface runvdr-conf.d help This help ENDOFTEXT else echo "Unknown command: $1" >&2 fi