msg () { # A status reporting function [ "${VERBOSE:-0}" -gt 0 ] && echo "$*" } error () { # An error reporting function echo 1>&2 "$*" } fatal () { # Report an error and exit with a failure code error "$*" exit 1 } # The only non builtin this uses is tr... require () { # Check prerequisites e=0 props="$1" ; shift for obj in "$@" ; do [ -z "$obj" ] && continue # Too late to do anything itelligent... problems="" for prop in $(/bin/tr '+,' ' ' <<<"$props") ; do case "$prop" in e|exists) # kind of useless... [ -e "$obj" ] || problems="$problems, does not exist" ;; f|file) [ -f "$obj" ] || problems="$problems, is not a file" ;; d|dir) [ -d "$obj" ] || problems="$problems, is not a directory" ;; l|symlink) [ -L "$obj" ] || problems="$problems, is not a symlink" ;; nosymlink) [ -L "$obj" ] && problems="$problems, is a symlink" ;; r|readable) [ -r "$obj" ] || problems="$problems, is not readable" ;; w|writable) [ -w "$obj" ] || problems="$problems, is not writable" ;; x|executable) [ -x "$obj" ] || problems="$problems, is not executable" ;; *) fatal "Programmer error, unknown property: '$prop'" ;; esac done if [ -n "$problems" ] ; then error "Error: '$obj'$problems." e=1 fi done [ "$e" -ne 0 ] && fatal "Errors noted above are fatal." } require file+r+x /bin/bash /bin/grep /bin/rm /bin/tr \ /usr/bin/basename /usr/bin/env \ /usr/bin/mysql /usr/bin/sort if [ -n "$DEBUG" ] ; then for debug_opt in $(/bin/tr ',' ' ' <<<"$DEBUG") ; do echo '============================================================' echo "==== $debug_opt" # Note that the order you specifiy these debug options in matters. # I recommend always listing log first. For example: # export DEBUG=log,env,set,trace case "$debug_opt" in env) /usr/bin/env | /usr/bin/sort ;; set) set ;; trace) set -vx ;; log) logfile="/tmp/$(/usr/bin/basename $0).$$.debug" /bin/rm -f "$logfile" # Try to avoid privilege escalation bugs echo "Redirecting stdout and stderr to '$logfile'" exec >"$logfile" 2>&1 ;; *) error "Unknown debug option '$debug_opt'" ;; esac done echo '============================================================' fi must_be_root () { # For things which must be run as root [ $(/usr/bin/id -u) -ne 0 ] && fatal "You must run this script as root!" } must_be_mythtv () { # For things which must be run as mythtv (su if possible) case $(/usr/bin/id -nu) in mythtv) ;; # Continue root) /bin/su - mythtv -c "$0 $*" ; exit $? ;; *) fatal "You must run this script at mythtv or root!" ;; esac } # Use a variable so you can override it. DATABASE="mythconverg" mysql_cmd () { # Execute SQL from the command line /usr/bin/mysql -u root "$DATABASE" -sBe "$*" } mysql_stdin () { # Execute SQL from stdin /usr/bin/mysql -u root "$DATABASE" -sB } machine_clause () { # Helper function if [ -z "$1" ] ; then echo "(hostname = '' or hostname is null)" else echo "hostname = '$1'" fi } get_all_setting_names () { # List setting names case "$#" in 0) MACHINE_CLAUSE="" ;; 1) MACHINE_CLAUSE="where $(machine_clause "$1")" ;; *) fatal "Programmer error, get_all_names must be passed 0 or 1 args, got $#" ;; esac mysql_cmd "select distinct value from settings $MACHINE_CLAUSE order by value" } get_all_setting_values () { # List settings case "$#" in 0) MACHINE_CLAUSE="" ;; 1) MACHINE_CLAUSE="where $(machine_clause "$1")" ;; *) fatal "Programmer error, get_all_values must be passed 0 or 1 args, got $#" ;; esac mysql_cmd "select value, data, hostname from settings $MACHINE_CLAUSE order by hostname, value, data" } get_setting_value () { # Get the data for a setting (may return multiples!) case "$#" in 1) MACHINE_CLAUSE="" ;; 2) MACHINE_CLAUSE="and $(machine_clause "$2")" ;; *) fatal "Programmer error, get_value must be passed 1 or 2 args, got $#" ;; esac mysql_cmd "select data from settings where value = '$1' $MACHINE_CLAUSE" } set_setting_value () { # Insert or update aome setting case "$#" in 2) RECORD_CNT=$(get_value "$1" | wc -l) ;; 3) RECORD_CNT=$(get_value "$1" "$3" | wc -l) ;; *) fatal "Programmer error, set_value must be passed 2 or 3 args, got $#" ;; esac MACHINE_CLAUSE="" if [ "$RECORD_CNT" -eq 0 ] ; then [ -n "$3" ] && MACHINE_CLAUSE=", $(machine_clause "$3")" mysql_cmd "insert into settings set value = '$1', data = '$2' $MACHINE_CLAUSE" else [ "$#" -eq 3 ] && MACHINE_CLAUSE="and $(machine_clause "$3")" mysql_cmd "update settings set data = '$2' where value = '$1' $MACHINE_CLAUSE" fi } delete_setting_value () { # Totally remove some setting case "$#" in 1) MACHINE_CLAUSE="" ;; 2) MACHINE_CLAUSE="and $(machine_clause "$2")" ;; *) fatal "Programmer error, get_value must be passed 1 or 2 args, got $#" ;; esac mysql_cmd "delete from settings where value = '$1' $MACHINE_CLAUSE" } # Filter against a newline seperated exclude list filter_list () { /bin/grep -vxF "$*" | /usr/bin/sort -u }