b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | #!/bin/sh /etc/rc.common |
| 2 | # Copyright © 2012 OpenWrt.org |
| 3 | # |
| 4 | # This is free software, licensed under the GNU General Public License v2. |
| 5 | # See /LICENSE for more information. |
| 6 | # |
| 7 | START=70 |
| 8 | STOP=30 |
| 9 | |
| 10 | USERS_C=/var/etc/nut/upsd.users |
| 11 | UPSD_C=/var/etc/nut/upsd.conf |
| 12 | UPS_C=/var/etc/nut/ups.conf |
| 13 | |
| 14 | USE_PROCD=1 |
| 15 | |
| 16 | get_write_driver_config() { |
| 17 | local cfg="$1" |
| 18 | local var="$2" |
| 19 | local def="$3" |
| 20 | local flag="$4" |
| 21 | local val |
| 22 | |
| 23 | [ -z "$flag" ] && { |
| 24 | config_get val "$cfg" "$var" "$def" |
| 25 | [ -n "$val" ] && [ "$val" != "0" ] && echo "$var = $val" >>"$UPS_C" |
| 26 | } |
| 27 | |
| 28 | [ -n "$flag" ] && { |
| 29 | config_get_bool val "$cfg" "$var" "$def" |
| 30 | [ "$val" = 1 ] && echo "$var" >>"$UPS_C" |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | upsd_statepath() { |
| 35 | local statepath |
| 36 | |
| 37 | config_get statepath upsd statepath /var/run/nut |
| 38 | STATEPATH="$statepath" |
| 39 | } |
| 40 | |
| 41 | upsd_runas() { |
| 42 | local runas |
| 43 | |
| 44 | [ -n "$RUNAS" ] && return 0 |
| 45 | |
| 46 | config_get runas upsd runas nut |
| 47 | RUNAS="$runas" |
| 48 | } |
| 49 | |
| 50 | listen_address() { |
| 51 | local cfg="$1" |
| 52 | |
| 53 | config_get address "$cfg" address "::1" |
| 54 | config_get port "$cfg" port |
| 55 | echo "LISTEN $address $port" >>"$UPSD_C" |
| 56 | } |
| 57 | |
| 58 | upsd_config() { |
| 59 | local cfg="$1" |
| 60 | local maxage maxconn certfile runas statepath |
| 61 | |
| 62 | # Note runas support requires you make sure USB device file is readable by |
| 63 | # the runas user |
| 64 | config_get runas "$cfg" runas nut |
| 65 | RUNAS="$runas" |
| 66 | |
| 67 | config_get statepath "$cfg" statepath /var/run/nut |
| 68 | STATEPATH="$statepath" |
| 69 | |
| 70 | config_get maxage "$cfg" maxage |
| 71 | [ -n "$maxage" ] && echo "MAXAGE $maxage" >>"$UPSD_C" |
| 72 | |
| 73 | [ -n "$statepath" ] && echo "STATEPATH $statepath" >>"$UPSD_C" |
| 74 | |
| 75 | config_get maxconn "$cfg" maxconn |
| 76 | [ -n "$maxconn" ] && echo "MAXCONN $maxconn" >>"$UPSD_C" |
| 77 | |
| 78 | #NOTE: certs only apply to SSL-enabled version |
| 79 | config_get certfile "$cfg" certfile |
| 80 | [ -n "$certfile" ] && echo "CERTFILE $certfile" >>"$UPSD_C" |
| 81 | } |
| 82 | |
| 83 | nut_user_add() { |
| 84 | local cfg="$1" |
| 85 | local a |
| 86 | local val |
| 87 | |
| 88 | config_get val "$cfg" username "$1" |
| 89 | echo "[$val]" >> "$USERS_C" |
| 90 | |
| 91 | config_get val "$cfg" password |
| 92 | echo " password = $val" >> "$USERS_C" |
| 93 | |
| 94 | config_get val "$cfg" actions |
| 95 | for a in $val; do |
| 96 | echo " actions = $a" >> "$USERS_C" |
| 97 | done |
| 98 | |
| 99 | instcmd() { |
| 100 | local val="$1" |
| 101 | echo " instcmds = $val" >> "$USERS_C" |
| 102 | } |
| 103 | |
| 104 | config_list_foreach "$cfg" instcmd instcmd |
| 105 | |
| 106 | config_get val "$cfg" upsmon |
| 107 | if [ -n "$val" ]; then |
| 108 | echo " upsmon $val" >> "$USERS_C" |
| 109 | fi |
| 110 | } |
| 111 | |
| 112 | build_server_config() { |
| 113 | mkdir -p "$(dirname "$UPSD_C")" |
| 114 | chmod 0640 "$UPS_C" |
| 115 | rm -f "$USERS_C" |
| 116 | rm -f "$UPSD_C" |
| 117 | rm -f /var/etc/nut/nut.conf |
| 118 | |
| 119 | echo "# Config file automatically generated from UCI config" > "$USERS_C" |
| 120 | echo "# Config file automatically generated from UCI config" > "$UPSD_C" |
| 121 | |
| 122 | config_foreach nut_user_add user |
| 123 | config_foreach listen_address listen_address |
| 124 | config_foreach upsd_config upsd |
| 125 | echo "MODE=netserver" >>/var/etc/nut/nut.conf |
| 126 | |
| 127 | chmod 0640 "$USERS_C" |
| 128 | chmod 0640 "$UPSD_C" |
| 129 | chmod 0644 /var/etc/nut/nut.conf |
| 130 | |
| 131 | [ -d "${STATEPATH}" ] || { |
| 132 | mkdir -p "${STATEPATH}" |
| 133 | chmod 0750 "${STATEPATH}" |
| 134 | } |
| 135 | |
| 136 | if [ -n "$RUNAS" ]; then |
| 137 | chown "$RUNAS":"$(id -gn "$RUNAS")" "${STATEPATH}" |
| 138 | chgrp "$(id -gn "$RUNAS")" "$USERS_C" |
| 139 | chgrp "$(id -gn "$RUNAS")" "$UPSD_C" |
| 140 | fi |
| 141 | haveserver=1 |
| 142 | } |
| 143 | |
| 144 | build_driver_config() { |
| 145 | local cfg="$1" |
| 146 | |
| 147 | echo "[$cfg]" >>"$UPS_C" |
| 148 | |
| 149 | get_write_driver_config "$cfg" bus |
| 150 | get_write_driver_config "$cfg" community |
| 151 | get_write_driver_config "$cfg" desc |
| 152 | get_write_driver_config "$cfg" driver "usbhid-ups" |
| 153 | get_write_driver_config "$cfg" ignorelb 0 1 |
| 154 | get_write_driver_config "$cfg" interruptonly 0 1 |
| 155 | get_write_driver_config "$cfg" interruptsize |
| 156 | get_write_driver_config "$cfg" maxreport |
| 157 | get_write_driver_config "$cfg" maxstartdelay |
| 158 | get_write_driver_config "$cfg" mfr |
| 159 | get_write_driver_config "$cfg" model |
| 160 | get_write_driver_config "$cfg" nolock 0 1 |
| 161 | get_write_driver_config "$cfg" notransferoids 0 1 |
| 162 | get_write_driver_config "$cfg" offdelay |
| 163 | get_write_driver_config "$cfg" ondelay |
| 164 | get_write_driver_config "$cfg" pollfreq |
| 165 | get_write_driver_config "$cfg" port "auto" |
| 166 | get_write_driver_config "$cfg" product |
| 167 | get_write_driver_config "$cfg" productid |
| 168 | get_write_driver_config "$cfg" retrydelay |
| 169 | get_write_driver_config "$cfg" sdorder |
| 170 | get_write_driver_config "$cfg" sdtime |
| 171 | get_write_driver_config "$cfg" serial |
| 172 | get_write_driver_config "$cfg" snmp_version |
| 173 | get_write_driver_config "$cfg" snmp_retries |
| 174 | get_write_driver_config "$cfg" snmp_timeout |
| 175 | get_write_driver_config "$cfg" synchronous |
| 176 | get_write_driver_config "$cfg" vendor |
| 177 | get_write_driver_config "$cfg" vendorid |
| 178 | |
| 179 | defoverride() { |
| 180 | local overvar="$1" |
| 181 | local defover="$2" |
| 182 | local overtype="$(echo "$overvar" | tr '_' '.')" |
| 183 | local overval |
| 184 | |
| 185 | config_get overval "${defover}_${overvar}" value |
| 186 | [ -n "$overval" ] && echo "${defover}.${overtype} = $overval" >>"$UPS_C" |
| 187 | } |
| 188 | |
| 189 | config_list_foreach "$cfg" override defoverride override |
| 190 | config_list_foreach "$cfg" default defoverride default |
| 191 | |
| 192 | other() { |
| 193 | local othervar="$1" |
| 194 | local othervarflag="$2" |
| 195 | local otherval |
| 196 | |
| 197 | if [ "$othervarflag" = "otherflag" ]; then |
| 198 | config_get_bool otherval "${othervarflag}_${othervar}" value |
| 199 | [ "$otherval" = "1" ] && echo "${othervar}" >>"$UPS_C" |
| 200 | else |
| 201 | config_get otherval "${othervarflag}_${othervar}" value |
| 202 | [ -n "$otherval" ] && echo "${othervar} = $otherval" >>"$UPS_C" |
| 203 | fi |
| 204 | } |
| 205 | |
| 206 | config_list_foreach "$cfg" other other other |
| 207 | config_list_foreach "$cfg" otherflag other otherflag |
| 208 | echo "" >>$UPS_C |
| 209 | havedriver=1 |
| 210 | } |
| 211 | |
| 212 | build_global_driver_config() { |
| 213 | local cfg="$1" |
| 214 | |
| 215 | # Global driver config |
| 216 | get_write_driver_config "$cfg" chroot |
| 217 | get_write_driver_config "$cfg" driverpath |
| 218 | get_write_driver_config "$cfg" maxstartdelay |
| 219 | get_write_driver_config "$cfg" maxretry |
| 220 | get_write_driver_config "$cfg" retrydelay |
| 221 | get_write_driver_config "$cfg" pollinterval |
| 222 | get_write_driver_config "$cfg" synchronous |
| 223 | config_get runas "$cfg" user nut |
| 224 | RUNAS="$runas" |
| 225 | |
| 226 | echo "" >>"$UPS_C" |
| 227 | } |
| 228 | |
| 229 | build_config() { |
| 230 | local STATEPATH=/var/run/nut |
| 231 | |
| 232 | mkdir -p "$(dirname "$UPS_C")" |
| 233 | rm -f "$UPS_C" |
| 234 | echo "# Config file automatically generated from UCI config" > "$UPS_C" |
| 235 | chmod 0640 "$UPS_C" |
| 236 | |
| 237 | config_load nut_server |
| 238 | |
| 239 | upsd_runas |
| 240 | config_foreach build_global_driver_config driver_global |
| 241 | config_foreach build_driver_config driver |
| 242 | upsd_statepath |
| 243 | build_server_config |
| 244 | [ -n "$RUNAS" ] && chgrp "$(id -gn "$RUNAS")" "$UPS_C" |
| 245 | } |
| 246 | |
| 247 | start_driver_instance() { |
| 248 | local cfg="$1" |
| 249 | local requested="$2" |
| 250 | local driver |
| 251 | local STATEPATH=/var/run/nut |
| 252 | local RUNAS=nut |
| 253 | |
| 254 | [ "$havedriver" != 1 ] && return |
| 255 | |
| 256 | # If wanting a specific instance, only start it |
| 257 | if [ "$requested" != "$cfg" ] && [ "$request" != "" ]; then |
| 258 | return 0 |
| 259 | fi |
| 260 | |
| 261 | mkdir -p "$(dirname "$UPS_C")" |
| 262 | chmod 0755 "$UPS_C" |
| 263 | |
| 264 | upsd_statepath |
| 265 | build_config |
| 266 | |
| 267 | # Avoid hotplug inadvertenly restarting driver during |
| 268 | # forced shutdown |
| 269 | [ -f /var/run/killpower ] && return 0 |
| 270 | if [ -d /var/run/nut ] && [ -f /var/run/nut/disable-hotplug ]; then |
| 271 | return 0 |
| 272 | fi |
| 273 | |
| 274 | if [ -n "$RUNAS" ]; then |
| 275 | chown "$RUNAS":"$(id -gn "$RUNAS")" "${STATEPATH}" |
| 276 | chgrp "$(id -gn "$RUNAS")" "$UPS_C" |
| 277 | fi |
| 278 | |
| 279 | config_get driver "$cfg" driver "usbhid-ups" |
| 280 | procd_open_instance "$cfg" |
| 281 | procd_set_param respawn |
| 282 | procd_set_param stderr 0 |
| 283 | procd_set_param stdout 1 |
| 284 | procd_set_param command /lib/nut/"${driver}" -D -a "$cfg" ${RUNAS:+-u "$RUNAS"} |
| 285 | procd_close_instance |
| 286 | } |
| 287 | |
| 288 | interface_triggers() { |
| 289 | local action="$1" |
| 290 | local triggerlist trigger |
| 291 | |
| 292 | config_get triggerlist upsd triggerlist |
| 293 | |
| 294 | . /lib/functions/network.sh |
| 295 | |
| 296 | if [ -n "$triggerlist" ]; then |
| 297 | for trigger in $triggerlist; do |
| 298 | if [ "$action" = "add_trigger" ]; then |
| 299 | procd_add_interface_trigger "interface.*" "$trigger" /etc/init.d/nut-server reload |
| 300 | else |
| 301 | network_is_up "$trigger" && return 0 |
| 302 | fi |
| 303 | done |
| 304 | else |
| 305 | if [ "$action" = "add_trigger" ]; then |
| 306 | procd_add_raw_trigger "interface.*.up" 2000 /etc/init.d/nut-server reload |
| 307 | else |
| 308 | ubus call network.device status | grep -q '"up": true' && return 0 |
| 309 | fi |
| 310 | fi |
| 311 | [ "$action" = "add_trigger" ] || return 1 |
| 312 | } |
| 313 | |
| 314 | start_server_instance() { |
| 315 | local cfg="$1" |
| 316 | |
| 317 | [ "$haveserver" != 1 ] && return |
| 318 | interface_triggers "check_interface_up" || return |
| 319 | |
| 320 | procd_open_instance "$cfg" |
| 321 | procd_set_param respawn |
| 322 | procd_set_param stderr 0 |
| 323 | procd_set_param stdout 1 |
| 324 | procd_set_param command /usr/sbin/upsd -D ${RUNAS:+-u "$RUNAS"} |
| 325 | procd_close_instance |
| 326 | } |
| 327 | |
| 328 | start_service() { |
| 329 | local STATEPATH=/var/run/nut |
| 330 | |
| 331 | # Avoid hotplug inadvertenly restarting driver during |
| 332 | # forced shutdown |
| 333 | [ -f /var/run/killpower ] && return 0 |
| 334 | |
| 335 | config_load nut_server |
| 336 | build_config |
| 337 | |
| 338 | case $@ in |
| 339 | "") |
| 340 | config_foreach start_driver_instance driver "$@" |
| 341 | start_server_instance upsd |
| 342 | ;; |
| 343 | *upsd*) |
| 344 | start_server_instance upsd |
| 345 | ;; |
| 346 | *) |
| 347 | config_foreach start_driver_instance driver "$@" |
| 348 | ;; |
| 349 | esac |
| 350 | } |
| 351 | |
| 352 | reload_service() { |
| 353 | stop_service "$@" |
| 354 | sleep 2 |
| 355 | start_service "$@" |
| 356 | } |
| 357 | |
| 358 | service_triggers() { |
| 359 | config_load nut_server |
| 360 | |
| 361 | interface_triggers "add_trigger" |
| 362 | procd_add_reload_trigger "nut_server" |
| 363 | } |