X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fopenwrt.git;a=blobdiff_plain;f=package%2Fsystem%2Fprocd%2Ffiles%2Fprocd.sh;h=72f25fe0c05bd284ee025d32c6aee09c1e4c074a;hp=bee32938377afb171b5375e6c9e8ca9eec6939ee;hb=d13e86d4c2d4c1c8970a20cc1f3214b266f57ed0;hpb=e1e5f21b2f30c5a8393f977789d6a3692f1d0261 diff --git a/package/system/procd/files/procd.sh b/package/system/procd/files/procd.sh index bee3293837..72f25fe0c0 100644 --- a/package/system/procd/files/procd.sh +++ b/package/system/procd/files/procd.sh @@ -12,12 +12,14 @@ # procd_set_param(type, [value...]) # Available types: # command: command line (array). -# respawn info: array with 3 values $restart_timeout $fail_hreshold $max_fail +# respawn info: array with 3 values $fail_threshold $restart_timeout $max_fail # env: environment variable (passed to the process) # data: arbitrary name/value pairs for detecting config changes (table) # file: configuration files (array) # netdev: bound network device (detects ifindex changes) # limits: resource limits (passed to the process) +# user info: array with 1 values $username +# pidfile: file name to write pid into # # No space separation is done for arrays/tables - use one function argument per command line argument # @@ -27,11 +29,29 @@ # procd_kill(service, [instance]): # Kill a service instance (or all instances) # +# procd_send_signal(service, [instance], [signal]) +# Send a signal to a service instance (or all instances) +# -. $IPKG_INSTROOT/usr/share/libubox/jshn.sh +. "$IPKG_INSTROOT/usr/share/libubox/jshn.sh" +PROCD_RELOAD_DELAY=1000 _PROCD_SERVICE= +procd_lock() { + local basescript=$(readlink "$initscript") + local service_name="$(basename ${basescript:-$initscript})" + + flock -n 1000 &> /dev/null + if [ "$?" != "0" ]; then + exec 1000>"$IPKG_INSTROOT/var/lock/procd_${service_name}.lock" + flock 1000 + if [ "$?" != "0" ]; then + logger "warning: procd flock for $service_name failed" + fi + fi +} + _procd_call() { local old_cb @@ -41,6 +61,7 @@ _procd_call() { } _procd_wrapper() { + procd_lock while [ -n "$1" ]; do eval "$1() { _procd_call _$1 \"\$@\"; }" shift @@ -70,12 +91,17 @@ _procd_open_service() { _procd_close_service() { json_close_object + _procd_open_trigger service_triggers - _procd_ubus_call set + _procd_close_trigger + _procd_open_data + service_data + _procd_close_data + _procd_ubus_call ${1:-set} } _procd_add_array_data() { - while [ -n "$1" ]; do + while [ "$#" -gt 0 ]; do json_add_string "" "$1" shift done @@ -92,7 +118,7 @@ _procd_add_table_data() { while [ -n "$1" ]; do local var="${1%%=*}" local val="${1#*=}" - [[ "$1" == "$val" ]] && val= + [ "$1" = "$val" ] && val= json_add_string "$var" "$val" shift done @@ -111,16 +137,97 @@ _procd_open_instance() { _PROCD_INSTANCE_SEQ="$(($_PROCD_INSTANCE_SEQ + 1))" name="${name:-instance$_PROCD_INSTANCE_SEQ}" json_add_object "$name" + [ -n "$TRACE_SYSCALLS" ] && json_add_boolean trace "1" } _procd_open_trigger() { + let '_procd_trigger_open = _procd_trigger_open + 1' + [ "$_procd_trigger_open" -gt 1 ] && return json_add_array "triggers" } +_procd_close_trigger() { + let '_procd_trigger_open = _procd_trigger_open - 1' + [ "$_procd_trigger_open" -lt 1 ] || return + json_close_array +} + +_procd_open_data() { + let '_procd_data_open = _procd_data_open + 1' + [ "$_procd_data_open" -gt 1 ] && return + json_add_object "data" +} + +_procd_close_data() { + let '_procd_data_open = _procd_data_open - 1' + [ "$_procd_data_open" -lt 1 ] || return + json_close_object +} + _procd_open_validate() { + json_select .. json_add_array "validate" } +_procd_close_validate() { + json_close_array + json_select triggers +} + +_procd_add_jail() { + json_add_object "jail" + json_add_string name "$1" + + shift + + for a in $@; do + case $a in + log) json_add_boolean "log" "1";; + ubus) json_add_boolean "ubus" "1";; + procfs) json_add_boolean "procfs" "1";; + sysfs) json_add_boolean "sysfs" "1";; + ronly) json_add_boolean "ronly" "1";; + esac + done + json_add_object "mount" + json_close_object + json_close_object +} + +_procd_add_jail_mount() { + local _json_no_warning=1 + + json_select "jail" + [ $? = 0 ] || return + json_select "mount" + [ $? = 0 ] || { + json_select .. + return + } + for a in $@; do + json_add_string "$a" "0" + done + json_select .. + json_select .. +} + +_procd_add_jail_mount_rw() { + local _json_no_warning=1 + + json_select "jail" + [ $? = 0 ] || return + json_select "mount" + [ $? = 0 ] || { + json_select .. + return + } + for a in $@; do + json_add_string "$a" "1" + done + json_select .. + json_select .. +} + _procd_set_param() { local type="$1"; shift @@ -131,12 +238,31 @@ _procd_set_param() { command|netdev|file|respawn|watch) _procd_add_array "$type" "$@" ;; - nice) + error) + json_add_array "$type" + json_add_string "" "$@" + json_close_array + ;; + nice|term_timeout) json_add_int "$type" "$1" ;; + reload_signal) + json_add_int "$type" $(kill -l "$1") + ;; + pidfile|user|seccomp|capabilities) + json_add_string "$type" "$1" + ;; + stdout|stderr|no_new_privs) + json_add_boolean "$type" "$1" + ;; esac } +_procd_add_timeout() { + [ "$PROCD_RELOAD_DELAY" -gt 0 ] && json_add_int "" "$PROCD_RELOAD_DELAY" + return 0 +} + _procd_add_interface_trigger() { json_add_array _procd_add_array_data "$1" @@ -155,11 +281,11 @@ _procd_add_interface_trigger() { json_close_array json_close_array - + _procd_add_timeout json_close_array } -_procd_add_network_trigger() { +_procd_add_reload_interface_trigger() { local script=$(readlink "$initscript") local name=$(basename ${script:-$initscript}) @@ -186,6 +312,24 @@ _procd_add_config_trigger() { json_close_array json_close_array + _procd_add_timeout + json_close_array +} + +_procd_add_raw_trigger() { + json_add_array + _procd_add_array_data "$1" + shift + local timeout=$1 + shift + + json_add_array + json_add_array + _procd_add_array_data "run_script" "$@" + json_close_array + json_close_array + + json_add_int "" "$timeout" json_close_array } @@ -193,9 +337,12 @@ _procd_add_config_trigger() { _procd_add_reload_trigger() { local script=$(readlink "$initscript") local name=$(basename ${script:-$initscript}) + local file _procd_open_trigger - _procd_add_config_trigger "config.change" $1 /etc/init.d/$name reload + for file in "$@"; do + _procd_add_config_trigger "config.change" "$file" /etc/init.d/$name reload + done _procd_close_trigger } @@ -207,8 +354,13 @@ _procd_add_validation() { _procd_append_param() { local type="$1"; shift + local _json_no_warning=1 json_select "$type" + [ $? = 0 ] || { + _procd_set_param "$type" "$@" + return + } case "$type" in env|data|limits) _procd_add_table_data "$@" @@ -216,20 +368,28 @@ _procd_append_param() { command|netdev|file|respawn|watch) _procd_add_array_data "$@" ;; + error) + json_add_string "" "$@" + ;; esac json_select .. } _procd_close_instance() { - json_close_object -} - -_procd_close_trigger() { - json_close_array -} + local respawn_vals + _json_no_warning=1 + if json_select respawn ; then + json_get_values respawn_vals + if [ -z "$respawn_vals" ]; then + local respawn_threshold=$(uci_get system.@service[0].respawn_threshold) + local respawn_timeout=$(uci_get system.@service[0].respawn_timeout) + local respawn_retry=$(uci_get system.@service[0].respawn_retry) + _procd_add_array_data ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5} + fi + json_select .. + fi -_procd_close_validate() { - json_close_array + json_close_object } _procd_add_instance() { @@ -248,35 +408,122 @@ _procd_kill() { _procd_ubus_call delete } +_procd_send_signal() { + local service="$1" + local instance="$2" + local signal="$3" + + case "$signal" in + [A-Z]*) signal="$(kill -l "$signal" 2>/dev/null)" || return 1;; + esac + + json_init + json_add_string name "$service" + [ -n "$instance" -a "$instance" != "*" ] && json_add_string instance "$instance" + [ -n "$signal" ] && json_add_int signal "$signal" + _procd_ubus_call signal +} + +procd_open_data() { + local name="$1" + json_set_namespace procd __procd_old_cb + json_add_object data +} + +procd_close_data() { + json_close_object + json_set_namespace $__procd_old_cb +} + +_procd_set_config_changed() { + local package="$1" + + json_init + json_add_string type config.change + json_add_object data + json_add_string package "$package" + json_close_object + + ubus call service event "$(json_dump)" +} + +procd_add_mdns_service() { + local service proto port + service=$1; shift + proto=$1; shift + port=$1; shift + json_add_object "${service}_$port" + json_add_string "service" "_$service._$proto.local" + json_add_int port "$port" + [ -n "$1" ] && { + json_add_array txt + for txt in "$@"; do json_add_string "" "$txt"; done + json_select .. + } + json_select .. +} + +procd_add_mdns() { + procd_open_data + json_add_object "mdns" + procd_add_mdns_service "$@" + json_close_object + procd_close_data +} + uci_validate_section() { local _package="$1" local _type="$2" local _name="$3" + local _result local _error shift; shift; shift - local _result=`/sbin/validate_data "$_package" "$_type" "$_name" "$@" 2> /dev/null` + _result=`/sbin/validate_data "$_package" "$_type" "$_name" "$@" 2> /dev/null` _error=$? eval "$_result" [ "$_error" = "0" ] || `/sbin/validate_data "$_package" "$_type" "$_name" "$@" 1> /dev/null` return $_error } +uci_load_validate() { + local _package="$1" + local _type="$2" + local _name="$3" + local _function="$4" + local _option + local _result + shift; shift; shift; shift + for _option in "$@"; do + eval "local ${_option%%:*}" + done + uci_validate_section "$_package" "$_type" "$_name" "$@" + _result=$? + [ -n "$_function" ] || return $_result + eval "$_function \"\$_name\" \"\$_result\"" +} + _procd_wrapper \ procd_open_service \ procd_close_service \ procd_add_instance \ + procd_add_raw_trigger \ procd_add_config_trigger \ - procd_add_reload_trigger \ procd_add_interface_trigger \ - procd_add_network_trigger \ + procd_add_reload_trigger \ + procd_add_reload_interface_trigger \ procd_open_trigger \ procd_close_trigger \ procd_open_instance \ procd_close_instance \ procd_open_validate \ procd_close_validate \ + procd_add_jail \ + procd_add_jail_mount \ + procd_add_jail_mount_rw \ procd_set_param \ procd_append_param \ procd_add_validation \ - procd_kill + procd_set_config_changed \ + procd_kill \ + procd_send_signal