led_ctrl: fix permission settings for test directories
[nas-tools.git] / led_ctrl / led_ctrl
1 #!/bin/sh -e
2
3 # led_ctrl: allow to configure LEDs using the LED sysfs API
4
5 # Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
6 # Copyright (C) 2010 Thomas Monjalon <thomas@monjalon.net>
7 # Copyright (C) 2010 Loic Dachary <loic@dachary.org>
8
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 # GNU General Public License for more details.
18
19 # You should have received a copy of the GNU General Public License
20 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22 SYSPATH=/sys/class/leds
23 CONFILE=/etc/led_ctrl.conf
24 DEBUG=false
25 TESTS=false
26 HELP=false
27 unset MODE
28
29 log_and_exec()
30 {
31         $DEBUG && echo "$@" >&2
32         eval "$@"
33 }
34
35 log_and_die()
36 {
37         printf "$@\n" >&2
38         exit 1
39 }
40
41 set_led_attr() # <led> <attribute> <value>
42 {
43         local attr err=0
44
45         IFS_ORIG="$IFS"
46         IFS=$'\n'
47
48         for attr in $(ls -1 $SYSPATH/$1/$2); do
49                 log_and_exec "echo $3 > \"$attr\"" || { err=1; break; }
50         done
51         IFS="$IFS_ORIG"
52
53         return $err
54 }
55
56 set_led_mode() # <mode>
57 {
58         local section leds settings setting attr value
59
60         section=$(sed -n -e "s/#.*//" -e "/{$1}/,/{.*}/p" $CONFILE)
61         [ -n "$section" ] || \
62                 log_and_die "no mode $1 in $CONFILE"
63
64         echo "$section" | grep '=' | while read leds settings; do
65                 for setting in $settings; do
66                         attr=$(echo $setting | cut -d'=' -f1)
67                         value=$(echo $setting | cut -d'=' -f2)
68                         [ -n "$attr" -a -n "$value" ] || \
69                                 log_and_die "$CONFILE: mode=$1 leds=$leds, invalid setting $setting"
70                         set_led_attr "$leds" $attr $value || \
71                                 log_and_die "$CONFILE: unable to apply $attr=$value for $leds"
72                 done
73         done || return $?
74 }
75
76 list_led_modes()
77 {
78         sed -n 's/{\(.*\)}/\1/p' $CONFILE
79 }
80
81 run_test() # <message> <test>
82 {
83         eval "$2" && echo "$1 : OK" || { echo "$1 : FAIL"; TEST_ERR=1; }
84 }
85
86 run_test_suite()
87 {
88         TEST_ERR=0
89         TEST_DIR=/tmp/$(basename $0)-test-$$
90
91         SYSPATH=$TEST_DIR/leds
92         mkdir -p $SYSPATH/led1
93         touch $SYSPATH/led1/attr1
94         touch $SYSPATH/led1/attr2
95         touch $SYSPATH/led1/attr3
96         mkdir -p $SYSPATH/led2
97         touch $SYSPATH/led2/attr1
98         touch $SYSPATH/led2/attr2
99         mkdir -p $SYSPATH/led\ 3
100         touch $SYSPATH/led\ 3/attr1
101         mkdir -p $SYSPATH/led\ 4
102         touch $SYSPATH/led\ 4/attr1
103         chmod 500 $SYSPATH/*
104         chmod 500 $SYSPATH
105
106         CONFILE=$TEST_DIR/conf
107         cat > $CONFILE <<- EOF
108                 {mode1}
109                 led1            =value
110
111                 {mode2}
112                 led1            attr1=
113
114                 {mode3}
115                 *               attr1=3
116                 led[0-9]        attr2=3
117
118                 {mode4}
119                 led\ [0-9]      attr1=4
120
121                 {mode5}
122                 #{mode6}
123                 led1            attr1=5 attr2=5 attr3=5
124                 led2            attr1=5 attr2=5 # some comments
125                 #led3           attr1=5
126         EOF
127
128         run_test 'non-defined led mode' \
129                 'set_led_mode nomatch 2>&1 | grep -q "no mode"'
130
131         run_test 'match empty attribute name' \
132                 'set_led_mode mode1 2>&1 | grep -q "invalid setting"'
133
134         run_test 'match empty attribute value' \
135                 'set_led_mode mode2 2>&1 | grep -q "invalid setting"'
136
137         run_test 'led name with wildcard and globbing' 'set_led_mode mode3'
138         run_test '  led1, set attr1=3' '[ "$(cat $SYSPATH/led1/attr1)" = 3 ]'
139         run_test '  led2, set attr1=3' '[ "$(cat $SYSPATH/led2/attr1)" = 3 ]'
140         run_test '  led 3, set attr1=3' '[ "$(cat $SYSPATH/led\ 3/attr1)" = 3 ]'
141         run_test '  led1, set attr2=3' '[ "$(cat $SYSPATH/led1/attr2)" = 3 ]'
142         run_test '  led2, set attr2=3' '[ "$(cat $SYSPATH/led2/attr2)" = 3 ]'
143
144         run_test 'led name with whitespace and globbing' 'set_led_mode mode4'
145         run_test '  led 3, set attr1=4' '[ "$(cat $SYSPATH/led\ 3/attr1)" = 4 ]'
146         run_test '  led 4, set attr1=4' '[ "$(cat $SYSPATH/led\ 4/attr1)" = 4 ]'
147
148         run_test 'multiple attributes and discarded comments' \
149                 'set_led_mode mode5'
150         run_test '  led1, set attr1=5' '[ "$(cat $SYSPATH/led1/attr1)" = 5 ]'
151         run_test '  led1, set attr2=5' '[ "$(cat $SYSPATH/led1/attr2)" = 5 ]'
152         run_test '  led1, set attr3=5' '[ "$(cat $SYSPATH/led1/attr3)" = 5 ]'
153         run_test '  led2, set attr1=5' '[ "$(cat $SYSPATH/led2/attr1)" = 5 ]'
154         run_test '  led2, set attr2=5' '[ "$(cat $SYSPATH/led2/attr1)" = 5 ]'
155
156         run_test 'commented-out led mode' \
157                 'set_led_mode mode6 2>&1 | grep -q "no mode"'
158
159         chmod -R 700 $SYSPATH
160         rm -fr $TEST_DIR
161
162         return $TEST_ERR
163 }
164
165 usage()
166 {
167         cat <<- EOF
168                 Usage: $(basename $0) [options] [mode]
169                   Configure LEDs for specified mode as defined in $CONFILE.
170                   List all modes if none is provided.
171
172                 Options:
173                   --config|-c  use an alternate configuration file
174                   --debug |-d  print debug messages
175                   --tests |-t  run non destructive internal tests
176                   --help  |-h  display this help
177         EOF
178 }
179
180 #
181 # Main
182 #
183
184 while [ $# -gt 0 ]; do
185         case $1 in
186                 --config|-c) CONFILE=$2; shift ;;
187                 --debug |-d) DEBUG=true ;;
188                 --tests |-t) TESTS=true ;;
189                 --help  |-h) HELP=true ;;
190                 -*         ) log_and_die "unknown argument: $1\n\n$(usage)" ;;
191                 *          ) MODE=$1 ;;
192         esac
193         shift
194 done
195
196 $HELP && usage
197 $TESTS && run_test_suite
198 { $HELP || $TESTS ;} && exit 0
199
200 [ -n "$(ls -A $SYSPATH 2>/dev/null)" ] || \
201         log_and_die "missing or empty sysfs LED directory: $SYSPATH"
202 [ -e $CONFILE ] || log_and_die "no configuration file: $CONFILE\n\n$(usage)"
203
204 if [ -n "$MODE" ]; then
205         set_led_mode $MODE
206 else
207         list_led_modes
208 fi