functions.sh 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. #!/bin/sh
  2. # Copyright (C) 2006-2013 OpenWrt.org
  3. # Copyright (C) 2006 Fokus Fraunhofer <[email protected]>
  4. # Copyright (C) 2010 Vertical Communications
  5. debug () {
  6. ${DEBUG:-:} "$@"
  7. }
  8. # newline
  9. N="
  10. "
  11. _C=0
  12. NO_EXPORT=1
  13. LOAD_STATE=1
  14. LIST_SEP=" "
  15. hotplug_dev() {
  16. env -i ACTION=$1 INTERFACE=$2 /sbin/hotplug-call net
  17. }
  18. append() {
  19. local var="$1"
  20. local value="$2"
  21. local sep="${3:- }"
  22. eval "export ${NO_EXPORT:+-n} -- \"$var=\${$var:+\${$var}\${value:+\$sep}}\$value\""
  23. }
  24. list_contains() {
  25. local var="$1"
  26. local str="$2"
  27. local val
  28. eval "val=\" \${$var} \""
  29. [ "${val%% $str *}" != "$val" ]
  30. }
  31. list_remove() {
  32. local var="$1"
  33. local remove="$2"
  34. local val
  35. eval "val=\" \${$var} \""
  36. val1="${val%% $remove *}"
  37. [ "$val1" = "$val" ] && return
  38. val2="${val##* $remove }"
  39. [ "$val2" = "$val" ] && return
  40. val="${val1## } ${val2%% }"
  41. val="${val%% }"
  42. eval "export ${NO_EXPORT:+-n} -- \"$var=\$val\""
  43. }
  44. config_load() {
  45. [ -n "$IPKG_INSTROOT" ] && return 0
  46. uci_load "$@"
  47. }
  48. reset_cb() {
  49. config_cb() { return 0; }
  50. option_cb() { return 0; }
  51. list_cb() { return 0; }
  52. }
  53. reset_cb
  54. package() {
  55. return 0
  56. }
  57. config () {
  58. local cfgtype="$1"
  59. local name="$2"
  60. export ${NO_EXPORT:+-n} CONFIG_NUM_SECTIONS=$(($CONFIG_NUM_SECTIONS + 1))
  61. name="${name:-cfg$CONFIG_NUM_SECTIONS}"
  62. append CONFIG_SECTIONS "$name"
  63. [ -n "$NO_CALLBACK" ] || config_cb "$cfgtype" "$name"
  64. export ${NO_EXPORT:+-n} CONFIG_SECTION="$name"
  65. export ${NO_EXPORT:+-n} "CONFIG_${CONFIG_SECTION}_TYPE=$cfgtype"
  66. }
  67. option () {
  68. local varname="$1"; shift
  69. local value="$*"
  70. export ${NO_EXPORT:+-n} "CONFIG_${CONFIG_SECTION}_${varname}=$value"
  71. [ -n "$NO_CALLBACK" ] || option_cb "$varname" "$*"
  72. }
  73. list() {
  74. local varname="$1"; shift
  75. local value="$*"
  76. local len
  77. config_get len "$CONFIG_SECTION" "${varname}_LENGTH" 0
  78. [ $len = 0 ] && append CONFIG_LIST_STATE "${CONFIG_SECTION}_${varname}"
  79. len=$(($len + 1))
  80. config_set "$CONFIG_SECTION" "${varname}_ITEM$len" "$value"
  81. config_set "$CONFIG_SECTION" "${varname}_LENGTH" "$len"
  82. append "CONFIG_${CONFIG_SECTION}_${varname}" "$value" "$LIST_SEP"
  83. list_cb "$varname" "$*"
  84. }
  85. config_rename() {
  86. local OLD="$1"
  87. local NEW="$2"
  88. local oldvar
  89. local newvar
  90. [ -n "$OLD" -a -n "$NEW" ] || return
  91. for oldvar in `set | grep ^CONFIG_${OLD}_ | \
  92. sed -e 's/\(.*\)=.*$/\1/'` ; do
  93. newvar="CONFIG_${NEW}_${oldvar##CONFIG_${OLD}_}"
  94. eval "export ${NO_EXPORT:+-n} \"$newvar=\${$oldvar}\""
  95. unset "$oldvar"
  96. done
  97. export ${NO_EXPORT:+-n} CONFIG_SECTIONS="$(echo " $CONFIG_SECTIONS " | sed -e "s, $OLD , $NEW ,")"
  98. [ "$CONFIG_SECTION" = "$OLD" ] && export ${NO_EXPORT:+-n} CONFIG_SECTION="$NEW"
  99. }
  100. config_unset() {
  101. config_set "$1" "$2" ""
  102. }
  103. config_clear() {
  104. local SECTION="$1"
  105. local oldvar
  106. list_remove CONFIG_SECTIONS "$SECTION"
  107. export ${NO_EXPORT:+-n} CONFIG_SECTIONS="${SECTION:+$CONFIG_SECTIONS}"
  108. for oldvar in `set | grep ^CONFIG_${SECTION:+${SECTION}_} | \
  109. sed -e 's/\(.*\)=.*$/\1/'` ; do
  110. unset $oldvar
  111. done
  112. }
  113. # config_get <variable> <section> <option> [<default>]
  114. # config_get <section> <option>
  115. config_get() {
  116. case "$3" in
  117. "") eval echo "\${CONFIG_${1}_${2}:-\${4}}";;
  118. *) eval export ${NO_EXPORT:+-n} -- "${1}=\${CONFIG_${2}_${3}:-\${4}}";;
  119. esac
  120. }
  121. # config_get_bool <variable> <section> <option> [<default>]
  122. config_get_bool() {
  123. local _tmp
  124. config_get _tmp "$2" "$3" "$4"
  125. case "$_tmp" in
  126. 1|on|true|enabled) _tmp=1;;
  127. 0|off|false|disabled) _tmp=0;;
  128. *) _tmp="$4";;
  129. esac
  130. export ${NO_EXPORT:+-n} "$1=$_tmp"
  131. }
  132. config_set() {
  133. local section="$1"
  134. local option="$2"
  135. local value="$3"
  136. local old_section="$CONFIG_SECTION"
  137. CONFIG_SECTION="$section"
  138. option "$option" "$value"
  139. CONFIG_SECTION="$old_section"
  140. }
  141. config_foreach() {
  142. local ___function="$1"
  143. [ "$#" -ge 1 ] && shift
  144. local ___type="$1"
  145. [ "$#" -ge 1 ] && shift
  146. local section cfgtype
  147. [ -z "$CONFIG_SECTIONS" ] && return 0
  148. for section in ${CONFIG_SECTIONS}; do
  149. config_get cfgtype "$section" TYPE
  150. [ -n "$___type" -a "x$cfgtype" != "x$___type" ] && continue
  151. eval "$___function \"\$section\" \"\$@\""
  152. done
  153. }
  154. config_list_foreach() {
  155. [ "$#" -ge 3 ] || return 0
  156. local section="$1"; shift
  157. local option="$1"; shift
  158. local function="$1"; shift
  159. local val
  160. local len
  161. local c=1
  162. config_get len "${section}" "${option}_LENGTH"
  163. [ -z "$len" ] && return 0
  164. while [ $c -le "$len" ]; do
  165. config_get val "${section}" "${option}_ITEM$c"
  166. eval "$function \"\$val\" \"\$@\""
  167. c="$(($c + 1))"
  168. done
  169. }
  170. insert_modules() {
  171. [ -d /etc/modules.d ] && {
  172. cd /etc/modules.d
  173. sed 's/^[^#]/insmod &/' $* | ash 2>&- || :
  174. }
  175. }
  176. include() {
  177. local file
  178. for file in $(ls $1/*.sh 2>/dev/null); do
  179. . $file
  180. done
  181. }
  182. find_mtd_index() {
  183. local PART="$(grep "\"$1\"" /proc/mtd | awk -F: '{print $1}')"
  184. local INDEX="${PART##mtd}"
  185. echo ${INDEX}
  186. }
  187. find_mtd_part() {
  188. local INDEX=$(find_mtd_index "$1")
  189. local PREFIX=/dev/mtdblock
  190. [ -d /dev/mtdblock ] && PREFIX=/dev/mtdblock/
  191. echo "${INDEX:+$PREFIX$INDEX}"
  192. }
  193. find_mtd_chardev() {
  194. local INDEX=$(find_mtd_index "$1")
  195. local PREFIX=/dev/mtd
  196. [ -d /dev/mtd ] && PREFIX=/dev/mtd/
  197. echo "${INDEX:+$PREFIX$INDEX}"
  198. }
  199. mtd_get_mac_ascii()
  200. {
  201. local mtdname="$1"
  202. local key="$2"
  203. local part
  204. local mac_dirty
  205. part=$(find_mtd_part "$mtdname")
  206. if [ -z "$part" ]; then
  207. echo "mtd_get_mac_ascii: partition $mtdname not found!" >&2
  208. return
  209. fi
  210. mac_dirty=$(strings "$part" | sed -n 's/^'"$key"'=//p')
  211. # "canonicalize" mac
  212. [ -n "$mac_dirty" ] && macaddr_canonicalize "$mac_dirty"
  213. }
  214. mtd_get_blob()
  215. {
  216. local mtdname="$1"
  217. local offset="$2"
  218. local count="$3"
  219. local firmware="$4"
  220. local part
  221. part=$(find_mtd_part "$mtdname")
  222. if [ -z "$part" ]; then
  223. echo "mtd_get_blob: partition $mtdname not found!" >&2
  224. return 1
  225. fi
  226. dd if=$part of=$firmware bs=1 skip=$offset count=$count 2>/dev/null || {
  227. echo "mtd_get_blob: failed to extract $firmware from $part" >&2
  228. return 1
  229. }
  230. }
  231. mtd_get_mac_binary() {
  232. local mtdname="$1"
  233. local offset="$2"
  234. local part
  235. part=$(find_mtd_part "$mtdname")
  236. if [ -z "$part" ]; then
  237. echo "mtd_get_mac_binary: partition $mtdname not found!" >&2
  238. return
  239. fi
  240. dd bs=1 skip=$offset count=6 if=$part 2>/dev/null | hexdump -v -n 6 -e '5/1 "%02x:" 1/1 "%02x"'
  241. }
  242. mtd_get_part_size() {
  243. local part_name=$1
  244. local first dev size erasesize name
  245. while read dev size erasesize name; do
  246. name=${name#'"'}; name=${name%'"'}
  247. if [ "$name" = "$part_name" ]; then
  248. echo $((0x$size))
  249. break
  250. fi
  251. done < /proc/mtd
  252. }
  253. macaddr_add() {
  254. local mac=$1
  255. local val=$2
  256. local oui=${mac%:*:*:*}
  257. local nic=${mac#*:*:*:}
  258. nic=$(printf "%06x" $((0x${nic//:/} + $val & 0xffffff)) | sed 's/^\(.\{2\}\)\(.\{2\}\)\(.\{2\}\)/\1:\2:\3/')
  259. echo $oui:$nic
  260. }
  261. macaddr_setbit_la()
  262. {
  263. local mac=$1
  264. printf "%02x:%s" $((0x${mac%%:*} | 0x02)) ${mac#*:}
  265. }
  266. macaddr_2bin()
  267. {
  268. local mac=$1
  269. echo -ne \\x${mac//:/\\x}
  270. }
  271. macaddr_canonicalize()
  272. {
  273. local mac="$1"
  274. local canon=""
  275. [ ${#mac} -gt 17 ] && return
  276. [ -n "${mac//[a-fA-F0-9\.: -]/}" ] && return
  277. for octet in ${mac//[\.:-]/ }; do
  278. case "${#octet}" in
  279. 1)
  280. octet="0${octet}"
  281. ;;
  282. 2)
  283. ;;
  284. 4)
  285. octet="${octet:0:2} ${octet:2:2}"
  286. ;;
  287. 12)
  288. octet="${octet:0:2} ${octet:2:2} ${octet:4:2} ${octet:6:2} ${octet:8:2} ${octet:10:2}"
  289. ;;
  290. *)
  291. return
  292. ;;
  293. esac
  294. canon=${canon}${canon:+ }${octet}
  295. done
  296. [ ${#canon} -ne 17 ] && return
  297. printf "%02x:%02x:%02x:%02x:%02x:%02x" 0x${canon// / 0x} 2>/dev/null
  298. }
  299. strtok() { # <string> { <variable> [<separator>] ... }
  300. local tmp
  301. local val="$1"
  302. local count=0
  303. shift
  304. while [ $# -gt 1 ]; do
  305. tmp="${val%%$2*}"
  306. [ "$tmp" = "$val" ] && break
  307. val="${val#$tmp$2}"
  308. export ${NO_EXPORT:+-n} "$1=$tmp"; count=$((count+1))
  309. shift 2
  310. done
  311. if [ $# -gt 0 -a -n "$val" ]; then
  312. export ${NO_EXPORT:+-n} "$1=$val"; count=$((count+1))
  313. fi
  314. return $count
  315. }
  316. jffs2_mark_erase() {
  317. local part="$(find_mtd_part "$1")"
  318. [ -z "$part" ] && {
  319. echo Partition not found.
  320. return 1
  321. }
  322. echo -e "\xde\xad\xc0\xde" | mtd -qq write - "$1"
  323. }
  324. uci_apply_defaults() {
  325. cd /etc/uci-defaults || return 0
  326. files="$(ls)"
  327. [ -z "$files" ] && return 0
  328. mkdir -p /tmp/.uci
  329. for file in $files; do
  330. ( . "./$(basename $file)" ) && rm -f "$file"
  331. done
  332. uci commit
  333. }
  334. group_add() {
  335. local name="$1"
  336. local gid="$2"
  337. local rc
  338. [ -f "${IPKG_INSTROOT}/etc/group" ] || return 1
  339. [ -n "$IPKG_INSTROOT" ] || lock /var/lock/group
  340. echo "${name}:x:${gid}:" >> ${IPKG_INSTROOT}/etc/group
  341. rc=$?
  342. [ -n "$IPKG_INSTROOT" ] || lock -u /var/lock/group
  343. return $rc
  344. }
  345. group_exists() {
  346. grep -qs "^${1}:" ${IPKG_INSTROOT}/etc/group
  347. }
  348. user_add() {
  349. local name="${1}"
  350. local uid="${2}"
  351. local gid="${3:-$2}"
  352. local desc="${4:-$1}"
  353. local home="${5:-/var/run/$1}"
  354. local shell="${6:-/bin/false}"
  355. local rc
  356. [ -f "${IPKG_INSTROOT}/etc/passwd" ] || return 1
  357. [ -n "$IPKG_INSTROOT" ] || lock /var/lock/passwd
  358. echo "${name}:x:${uid}:${gid}:${desc}:${home}:${shell}" >> ${IPKG_INSTROOT}/etc/passwd
  359. echo "${name}:x:0:0:99999:7:::" >> ${IPKG_INSTROOT}/etc/shadow
  360. rc=$?
  361. [ -n "$IPKG_INSTROOT" ] || lock -u /var/lock/passwd
  362. return $rc
  363. }
  364. user_exists() {
  365. grep -qs "^${1}:" ${IPKG_INSTROOT}/etc/passwd
  366. }
  367. [ -z "$IPKG_INSTROOT" -a -f /lib/config/uci.sh ] && . /lib/config/uci.sh