procd.sh 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. # procd API:
  2. #
  3. # procd_open_service(name, [script]):
  4. # Initialize a new procd command message containing a service with one or more instances
  5. #
  6. # procd_close_service()
  7. # Send the command message for the service
  8. #
  9. # procd_open_instance([name]):
  10. # Add an instance to the service described by the previous procd_open_service call
  11. #
  12. # procd_set_param(type, [value...])
  13. # Available types:
  14. # command: command line (array).
  15. # respawn info: array with 3 values $fail_threshold $restart_timeout $max_fail
  16. # env: environment variable (passed to the process)
  17. # data: arbitrary name/value pairs for detecting config changes (table)
  18. # file: configuration files (array)
  19. # netdev: bound network device (detects ifindex changes)
  20. # limits: resource limits (passed to the process)
  21. # user info: array with 1 values $username
  22. #
  23. # No space separation is done for arrays/tables - use one function argument per command line argument
  24. #
  25. # procd_close_instance():
  26. # Complete the instance being prepared
  27. #
  28. # procd_kill(service, [instance]):
  29. # Kill a service instance (or all instances)
  30. #
  31. . $IPKG_INSTROOT/usr/share/libubox/jshn.sh
  32. _PROCD_SERVICE=
  33. _procd_call() {
  34. local old_cb
  35. json_set_namespace procd old_cb
  36. "$@"
  37. json_set_namespace $old_cb
  38. }
  39. _procd_wrapper() {
  40. while [ -n "$1" ]; do
  41. eval "$1() { _procd_call _$1 \"\$@\"; }"
  42. shift
  43. done
  44. }
  45. _procd_ubus_call() {
  46. local cmd="$1"
  47. [ -n "$PROCD_DEBUG" ] && json_dump >&2
  48. ubus call service "$cmd" "$(json_dump)"
  49. json_cleanup
  50. }
  51. _procd_open_service() {
  52. local name="$1"
  53. local script="$2"
  54. _PROCD_SERVICE="$name"
  55. _PROCD_INSTANCE_SEQ=0
  56. json_init
  57. json_add_string name "$name"
  58. [ -n "$script" ] && json_add_string script "$script"
  59. json_add_object instances
  60. }
  61. _procd_close_service() {
  62. json_close_object
  63. service_triggers
  64. _procd_ubus_call set
  65. }
  66. _procd_add_array_data() {
  67. while [ "$#" -gt 0 ]; do
  68. json_add_string "" "$1"
  69. shift
  70. done
  71. }
  72. _procd_add_array() {
  73. json_add_array "$1"
  74. shift
  75. _procd_add_array_data "$@"
  76. json_close_array
  77. }
  78. _procd_add_table_data() {
  79. while [ -n "$1" ]; do
  80. local var="${1%%=*}"
  81. local val="${1#*=}"
  82. [ "$1" = "$val" ] && val=
  83. json_add_string "$var" "$val"
  84. shift
  85. done
  86. }
  87. _procd_add_table() {
  88. json_add_object "$1"
  89. shift
  90. _procd_add_table_data "$@"
  91. json_close_object
  92. }
  93. _procd_open_instance() {
  94. local name="$1"; shift
  95. _PROCD_INSTANCE_SEQ="$(($_PROCD_INSTANCE_SEQ + 1))"
  96. name="${name:-instance$_PROCD_INSTANCE_SEQ}"
  97. json_add_object "$name"
  98. [ -n "$TRACE_SYSCALLS" ] && json_add_boolean trace "1"
  99. }
  100. _procd_open_trigger() {
  101. json_add_array "triggers"
  102. }
  103. _procd_open_validate() {
  104. json_add_array "validate"
  105. }
  106. _procd_add_jail() {
  107. json_add_object "jail"
  108. json_add_string name "$1"
  109. json_add_string root "/tmp/.jail/$1"
  110. shift
  111. for a in $@; do
  112. case $a in
  113. log) json_add_boolean "log" "1";;
  114. ubus) json_add_boolean "ubus" "1";;
  115. procfs) json_add_boolean "procfs" "1";;
  116. sysfs) json_add_boolean "sysfs" "1";;
  117. esac
  118. done
  119. json_add_object "mount"
  120. json_close_object
  121. json_close_object
  122. }
  123. _procd_add_jail_mount() {
  124. local _json_no_warning=1
  125. json_select "jail"
  126. [ $? = 0 ] || return
  127. json_select "mount"
  128. [ $? = 0 ] || {
  129. json_select ..
  130. return
  131. }
  132. for a in $@; do
  133. json_add_string "$a" "0"
  134. done
  135. json_select ..
  136. json_select ..
  137. }
  138. _procd_add_jail_mount_rw() {
  139. local _json_no_warning=1
  140. json_select "jail"
  141. [ $? = 0 ] || return
  142. json_select "mount"
  143. [ $? = 0 ] || {
  144. json_select ..
  145. return
  146. }
  147. for a in $@; do
  148. json_add_string "$a" "1"
  149. done
  150. json_select ..
  151. json_select ..
  152. }
  153. _procd_set_param() {
  154. local type="$1"; shift
  155. case "$type" in
  156. env|data|limits)
  157. _procd_add_table "$type" "$@"
  158. ;;
  159. command|netdev|file|respawn|watch)
  160. _procd_add_array "$type" "$@"
  161. ;;
  162. error)
  163. json_add_array "$type"
  164. json_add_string "" "$@"
  165. json_close_array
  166. ;;
  167. nice)
  168. json_add_int "$type" "$1"
  169. ;;
  170. user|seccomp)
  171. json_add_string "$type" "$1"
  172. ;;
  173. stdout|stderr)
  174. json_add_boolean "$type" "$1"
  175. ;;
  176. esac
  177. }
  178. _procd_add_interface_trigger() {
  179. json_add_array
  180. _procd_add_array_data "$1"
  181. shift
  182. json_add_array
  183. _procd_add_array_data "if"
  184. json_add_array
  185. _procd_add_array_data "eq" "interface" "$1"
  186. shift
  187. json_close_array
  188. json_add_array
  189. _procd_add_array_data "run_script" "$@"
  190. json_close_array
  191. json_close_array
  192. json_close_array
  193. }
  194. _procd_add_reload_interface_trigger() {
  195. local script=$(readlink "$initscript")
  196. local name=$(basename ${script:-$initscript})
  197. _procd_open_trigger
  198. _procd_add_interface_trigger "interface.*" $1 /etc/init.d/$name reload
  199. _procd_close_trigger
  200. }
  201. _procd_add_config_trigger() {
  202. json_add_array
  203. _procd_add_array_data "$1"
  204. shift
  205. json_add_array
  206. _procd_add_array_data "if"
  207. json_add_array
  208. _procd_add_array_data "eq" "package" "$1"
  209. shift
  210. json_close_array
  211. json_add_array
  212. _procd_add_array_data "run_script" "$@"
  213. json_close_array
  214. json_close_array
  215. json_close_array
  216. }
  217. _procd_add_raw_trigger() {
  218. json_add_array
  219. _procd_add_array_data "$1"
  220. shift
  221. local timeout=$1
  222. shift
  223. json_add_array
  224. json_add_array
  225. _procd_add_array_data "run_script" "$@"
  226. json_close_array
  227. json_close_array
  228. json_add_int "" "$timeout"
  229. json_close_array
  230. }
  231. _procd_add_reload_trigger() {
  232. local script=$(readlink "$initscript")
  233. local name=$(basename ${script:-$initscript})
  234. local file
  235. _procd_open_trigger
  236. for file in "$@"; do
  237. _procd_add_config_trigger "config.change" "$file" /etc/init.d/$name reload
  238. done
  239. _procd_close_trigger
  240. }
  241. _procd_add_validation() {
  242. _procd_open_validate
  243. $@
  244. _procd_close_validate
  245. }
  246. _procd_append_param() {
  247. local type="$1"; shift
  248. local _json_no_warning=1
  249. json_select "$type"
  250. [ $? = 0 ] || {
  251. _procd_set_param "$type" "$@"
  252. return
  253. }
  254. case "$type" in
  255. env|data|limits)
  256. _procd_add_table_data "$@"
  257. ;;
  258. command|netdev|file|respawn|watch)
  259. _procd_add_array_data "$@"
  260. ;;
  261. error)
  262. json_add_string "" "$@"
  263. ;;
  264. esac
  265. json_select ..
  266. }
  267. _procd_close_instance() {
  268. json_close_object
  269. }
  270. _procd_close_trigger() {
  271. json_close_array
  272. }
  273. _procd_close_validate() {
  274. json_close_array
  275. }
  276. _procd_add_instance() {
  277. _procd_open_instance
  278. _procd_set_param command "$@"
  279. _procd_close_instance
  280. }
  281. _procd_kill() {
  282. local service="$1"
  283. local instance="$2"
  284. json_init
  285. [ -n "$service" ] && json_add_string name "$service"
  286. [ -n "$instance" ] && json_add_string instance "$instance"
  287. _procd_ubus_call delete
  288. }
  289. procd_open_data() {
  290. local name="$1"
  291. json_set_namespace procd __procd_old_cb
  292. json_add_object data
  293. }
  294. procd_close_data() {
  295. json_close_object
  296. json_set_namespace $__procd_old_cb
  297. }
  298. _procd_set_config_changed() {
  299. local package="$1"
  300. json_init
  301. json_add_string type config.change
  302. json_add_object data
  303. json_add_string package "$package"
  304. json_close_object
  305. ubus call service event "$(json_dump)"
  306. }
  307. procd_add_mdns_service() {
  308. local service proto port
  309. service=$1; shift
  310. proto=$1; shift
  311. port=$1; shift
  312. json_add_object "${service}_$port"
  313. json_add_string "service" "_$service._$proto.local"
  314. json_add_int port "$port"
  315. [ -n "$1" ] && {
  316. json_add_array txt
  317. for txt in $@; do json_add_string "" $txt; done
  318. json_select ..
  319. }
  320. json_select ..
  321. }
  322. procd_add_mdns() {
  323. procd_open_data
  324. json_add_object "mdns"
  325. procd_add_mdns_service $@
  326. json_close_object
  327. procd_close_data
  328. }
  329. uci_validate_section()
  330. {
  331. local _package="$1"
  332. local _type="$2"
  333. local _name="$3"
  334. local _result
  335. local _error
  336. shift; shift; shift
  337. _result=`/sbin/validate_data "$_package" "$_type" "$_name" "$@" 2> /dev/null`
  338. _error=$?
  339. eval "$_result"
  340. [ "$_error" = "0" ] || `/sbin/validate_data "$_package" "$_type" "$_name" "$@" 1> /dev/null`
  341. return $_error
  342. }
  343. _procd_wrapper \
  344. procd_open_service \
  345. procd_close_service \
  346. procd_add_instance \
  347. procd_add_raw_trigger \
  348. procd_add_config_trigger \
  349. procd_add_interface_trigger \
  350. procd_add_reload_trigger \
  351. procd_add_reload_interface_trigger \
  352. procd_open_trigger \
  353. procd_close_trigger \
  354. procd_open_instance \
  355. procd_close_instance \
  356. procd_open_validate \
  357. procd_close_validate \
  358. procd_add_jail \
  359. procd_add_jail_mount \
  360. procd_add_jail_mount_rw \
  361. procd_set_param \
  362. procd_append_param \
  363. procd_add_validation \
  364. procd_set_config_changed \
  365. procd_kill