1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
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
}
|