Here comes the new UCI. Enjoy :)
authorFelix Fietkau <nbd@openwrt.org>
Sun, 3 Feb 2008 06:48:15 +0000 (06:48 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sun, 3 Feb 2008 06:48:15 +0000 (06:48 +0000)
SVN-Revision: 10367

22 files changed:
package/base-files/files/bin/uci [deleted file]
package/base-files/files/etc/functions.sh
package/base-files/files/etc/hotplug.d/iface/00-netstate
package/base-files/files/etc/hotplug.d/iface/10-routes
package/base-files/files/etc/init.d/boot
package/base-files/files/lib/config/uci.awk [deleted file]
package/base-files/files/lib/config/uci.sh [deleted file]
package/base-files/files/lib/network/config.sh
package/base-files/files/sbin/ifdown
package/base-files/files/sbin/wifi
package/base-files/files/usr/share/udhcpc/default.script
package/dnsmasq/files/dnsmasq.init
package/iptables/files/firewall.init
package/ppp/files/etc/ppp/ip-down
package/ppp/files/etc/ppp/ip-up
package/pptp/files/pptp.sh
package/qos-scripts/files/usr/lib/qos/generate.sh
package/uci/Makefile [new file with mode: 0644]
package/uci/files/uci-sh/bin/uci [new file with mode: 0755]
package/uci/files/uci-sh/lib/config/uci.awk [new file with mode: 0644]
package/uci/files/uci-sh/lib/config/uci.sh [new file with mode: 0644]
package/uci/files/uci/lib/config/uci.sh [new file with mode: 0644]

diff --git a/package/base-files/files/bin/uci b/package/base-files/files/bin/uci
deleted file mode 100755 (executable)
index f89fe82..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-#!/bin/sh
-# Shell script for interacting with config files
-#
-# Copyright (C) 2006        Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de>
-# Copyright (C) 2006,2007      Felix Fietkau <nbd@openwrt.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-. $UCI_ROOT/etc/functions.sh
-include $UCI_ROOT/lib/config
-
-SEP="[^0-9A-Za-z_]"
-
-do_get() {
-       local PACKAGE
-       local CONFIG
-       local OPTION
-       local DUMMY
-
-       strtok "$*" PACKAGE . CONFIG . OPTION $SEP DUMMY
-
-       [ $? -ne 3 ] && {
-               uci_usage get
-               exit 1
-       }
-
-       uci_load "$PACKAGE"
-       config_get "$CONFIG" "$OPTION"
-}
-
-do_set() {
-       local PACKAGE
-       local CONFIG
-       local OPTION
-       local VALUE
-
-       strtok "$1" PACKAGE . CONFIG = VALUE
-       [ $? -ne 3 -a $? -ne 2 ] && {
-               uci_usage set
-               exit 1
-       }
-       
-       strtok "$CONFIG" CONFIG . OPTION
-       
-       if [ $? -eq 1 ]; then
-               uci_add "$PACKAGE" "$VALUE" "$CONFIG"
-       else
-               uci_set "$PACKAGE" "$CONFIG" "$OPTION" "$VALUE"
-       fi
-}
-
-do_rename() {
-       [ $# -ne 3 ] && {
-               uci_usage rename
-               exit 1
-       }
-       uci_rename "$@"
-}
-
-do_remove() {
-       local PACKAGE
-       local CONFIG
-       local OPTION
-       local DUMMY
-
-       strtok "$*" PACKAGE . CONFIG . OPTION $SEP DUMMY
-       [ $? -ne 3 -a $? -ne 2 ] && {
-               uci_usage rename
-               exit 1
-       }
-       uci_remove "$PACKAGE" "$CONFIG" ${OPTION:+"$OPTION"}
-}
-
-do_commit() {
-       local PACKAGE="$1"
-       for package in ${PACKAGE:-$(cd /tmp/.uci; ls)}; do 
-               [ lock = "${package##*.}" ] && continue # ignore .lock files
-               uci_commit "$package"
-       done
-}
-
-do_show() {
-       local PACKAGE
-       local CONFIG
-       local DUMMY
-
-       strtok "$*" PACKAGE . CONFIG $SEP DUMMY
-       [ $? -gt 2 ] && {
-               uci_usage show
-               exit 1
-       }
-       
-       for package in ${PACKAGE:-$(cd $UCI_ROOT/etc/config; ls)}; do
-               SECTION=""
-       
-               config_cb() {
-                       if [ -z "$CONFIG" -o ."$CONFIG" = ."$2" ]; then
-                               append SECTION "$2"
-                               option_cb() {
-                                       append "${CONFIG_SECTION}_VARS" "$1"
-                               }
-                       else
-                               option_cb() {
-                                       return 0
-                               }
-                       fi
-               }
-                       
-               uci_load "$package"
-       
-               for section in $SECTION; do
-                       config_get type "$section" TYPE
-                       [ -z "$type" ] && continue
-                       echo "$package.$section=$type"
-                       eval "VARS=\"\${${section}_VARS}\""
-                       for var in $VARS; do
-                               config_get val "$section" "$var"
-                               [ -n "$val" ] && {
-                                       echo "$package.$section.$var=$val"
-                                       config_set "$section" "$var" ""
-                               }
-                       done
-                       config_set "$section" TYPE ""
-               done
-       done
-}
-
-do_validate() {
-       [ "$#" -ne 1 ] && {
-               uci_usage validate
-               exit 1
-       }
-       uci_validate "$1" || exit "$?"
-}
-
-uci_usage() {
-       case "$1" in
-               show) echo "$0 show [<package>[.<config>]]";;
-               get) echo "$0 get <package>.<config>.<option>";;
-               set) echo "$0 set <package>.<config>[.<option>]=<value>";;
-               del) echo "$0 del <package>.<config>[.<option>]";;
-               rename) echo "$0 rename <package> <config> <name>";;
-               commit) echo "$0 commit [<package> ... ]";;
-               validate) echo "$0 validate <package>";;
-               *) 
-                       echo "Syntax: $0 <command> <arguments...>"
-                       echo
-                       uci_usage show
-                       uci_usage get
-                       uci_usage set
-                       uci_usage del
-                       uci_usage rename
-                       uci_usage commit
-                       uci_usage validate 
-                       echo
-                       exit 1
-               ;;
-       esac
-}
-
-if [ $# -eq 0 ] ; then
-       uci_usage
-       exit 0
-fi
-
-CMD="$1"
-shift
-case "$CMD" in
-       set) do_set "$@";;
-       del) do_remove "$@";;
-       rename) do_rename "$@";;
-       get) do_get "$@";;
-       show) do_show "$@";;
-       commit) do_commit "$@";;
-       validate) do_validate "$@";;
-       *) uci_usage;;
-esac
-exit 0
index ef28015..5ad45ec 100755 (executable)
@@ -10,6 +10,7 @@ N="
 
 _C=0
 NO_EXPORT=1
+LOAD_STATE=1
 
 hotplug_dev() {
        env -i ACTION=$1 INTERFACE=$2 /sbin/hotplug-call net
@@ -23,12 +24,21 @@ append() {
        eval "export ${NO_EXPORT:+-n} -- \"$var=\${$var:+\${$var}\${value:+\$sep}}\$value\""
 }
 
+config_load() {
+       [ -n "$IPKG_INSTROOT" ] && return 0
+       uci_load "$@"
+}
+
 reset_cb() {
        config_cb() { return 0; }
        option_cb() { return 0; }
 }
 reset_cb
 
+package() {
+       return 0
+}
+
 config () {
        local cfgtype="$1"
        local name="$2"
@@ -84,37 +94,6 @@ config_clear() {
        done
 }
 
-config_load() {
-       local cfg
-       local uci
-       local PACKAGE="$1"
-
-       case "$PACKAGE" in
-               /*)     cfg="$PACKAGE"
-                       uci=""
-               ;;
-               *)      cfg="$UCI_ROOT/etc/config/$PACKAGE"
-                       uci="/tmp/.uci/${PACKAGE}"
-               ;;
-       esac
-
-       [ -e "$cfg" ] || cfg=""
-       [ -e "$uci" ] || uci=""
-
-       # no config
-       [ -z "$cfg" -a -z "$uci" ] && return 1
-
-       _C=0
-       export ${NO_EXPORT:+-n} CONFIG_SECTIONS=
-       export ${NO_EXPORT:+-n} CONFIG_NUM_SECTIONS=0
-       export ${NO_EXPORT:+-n} CONFIG_SECTION=
-
-       ${cfg:+. "$cfg"}
-       ${uci:+. "$uci"}
-       
-       ${CONFIG_SECTION:+config_cb}
-}
-
 config_get() {
        case "$3" in
                "") eval "echo \"\${CONFIG_${1}_${2}}\"";;
@@ -218,8 +197,15 @@ jffs2_mark_erase() {
        echo -e "\xde\xad\xc0\xde" | mtd -qq write - "$1"
 }
 
-uci_set_default() {
-       local PACKAGE="$1"
-       [ -e "/etc/config/$1" ] && return 0
-       cat > "/etc/config/$1"
-}
+uci_apply_defaults() {(
+       cd /etc/uci-defaults || return 0
+       files="$(ls)"
+       [ -z "$files" ] && return 0
+       mkdir -p /tmp/.uci
+       for file in $files; do
+               ( . "./$(basename $file)" ) && rm -f "$file"
+       done
+       uci commit
+)}
+
+[ -z "$IPKG_INSTROOT" ] && . /lib/config/uci.sh
index 6bf6214..f215d29 100644 (file)
@@ -1,3 +1,3 @@
 [ ifup = "$ACTION" ] && {
-       uci set "/var/state/network.$INTERFACE.up=1"
+       uci_set_state network "$INTERFACE" up 1 
 }
index 7e957f7..963728f 100644 (file)
@@ -63,7 +63,6 @@ case "$ACTION" in
        ifup)
                include /lib/network
                scan_interfaces
-               . /var/state/network
                config_foreach "add_route" route
                config_foreach "add_route6" route6
        ;;
index b524c39..0b77447 100755 (executable)
@@ -36,6 +36,8 @@ start() {
        mkdir -p /var/log
        mkdir -p /var/lock
        mkdir -p /var/state
+       mkdir -p /tmp/.uci
+       chown 0700 /tmp/.uci
        touch /var/log/wtmp
        touch /var/log/lastlog
        ln -sf /tmp/resolv.conf.auto /tmp/resolv.conf
diff --git a/package/base-files/files/lib/config/uci.awk b/package/base-files/files/lib/config/uci.awk
deleted file mode 100644 (file)
index 5972ad2..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-# Configuration update functions - AWK API
-#
-# Copyright (C) 2006 by Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de>
-# Copyright (C) 2006 by Felix Fietkau <nbd@openwrt.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-# parameters: 1
-function config_load(package, var) {
-       while (("/bin/ash -c '. /etc/functions.sh; unset NO_EXPORT; config_load \""package"\"; env | grep \"^CONFIG_\"'" | getline) == 1) {
-               sub("^CONFIG_", "")
-               if (match($0, "=") == 0) {
-                       if (var != "") CONFIG[var] = CONFIG[var] "\n" $0
-                       next
-               }
-               var=substr($0, 1, RSTART-1)
-               CONFIG[var] = substr($0, RSTART+1, length($0) - RSTART)
-       }
-}
-
-# parameters: 2
-function config_get(package, option) {
-       return CONFIG[package "_" option]
-}
-
-# parameters: 3
-function config_get_bool(package, option, default, var) {
-       var = config_get(package, option);
-       if ((var == "enabled") || (var == "true") || (var == "1") || (var == "on")) return 1
-       if ((var == "disabled") || (var == "false") || (var == "0") || (var == "off")) return 1
-       return (var && var != "0" ? 1 : 0)
-}
-
-
-function read_file(filename,  result) {
-       while ((getline <filename) == 1) {
-               result = result $0 "\n"
-       }
-       gsub(/\n*$/, "", result)
-       return result
-}
-
-function uci_cmd2option(str,  tmp) {
-       if (match(str,"=")!=0) {
-               res = "\toption " substr(str,1,RSTART-1) "\t'" substr(str,RSTART+1) "'"
-       } else {
-               res= ""
-       }
-       return res
-}
-
-function uci_cmd2config(atype,  aname) {
-       return "config \"" atype "\" \"" aname "\""
-}
-
-function uci_update_config(cfg, update,  \
-  lines, line, l, n, i, i2, section, scnt, remove, tmp, aidx, rest) {
-       scnt = 1
-       linecnt=split(cfg "\n", lines, "\n")
-
-       cfg = ""
-       for (n = 1; n < linecnt; n++) {
-               # stupid parser for quoted arguments (e.g. for the type string).
-               # not to be used to gather variable values (backslash escaping doesn't work)
-               line = lines[n]
-               gsub(/^[ \t]*/, "", line)
-               gsub(/#.*$/, "", line)
-               i2 = 1
-               delete l
-               rest = line
-               while (length(rest)) {
-                       if (match(rest, /[ \t\"]+/)) {
-                               if (RSTART>1) {
-                                       l[i2] = substr(rest,1,RSTART-1)
-                                       i2++
-                               }
-                               aidx=index(rest,"\"")
-                               if (aidx>=RSTART && aidx<=RSTART+RLENGTH) {
-                                       rest=substr(rest,aidx+1)
-                                       # find the end of the string
-                                       match(rest,/\"/)
-                                       l[i2]=substr(rest,1,RSTART-1)
-                                       i2++
-                               }
-                               rest=substr(rest,RSTART+RLENGTH)
-                       } else {
-                               l[i2] = rest
-                               i2++
-                               rest = ""
-                       }
-               }
-               line = lines[n]
-               
-               # when a command wants to set a config value for the current
-               # section and a blank line is encountered before an option with
-               # the same name, insert it here to maintain some coherency between
-               # manually and automatically created option lines
-               # if an option with the same name appears after this point, simply
-               # ignore it, because it is already set.
-               if ((section != "") && (l[1] != "option")) {
-                       if (line ~ /^[ \t]*$/) {
-                               if (update ~ "^" section "\\.") {
-                                       gsub("^" section ".", "", update)
-                                       cfg = cfg uci_cmd2option(update) "\n"
-                                       gsub(/=.*$/, "", update)
-                                       update = "-" section "." update
-                               }
-                       }
-               }
-
-               if (l[1] == "config") {
-                       # look for all unset values
-                       if (section != "") {
-                               flag=0
-                               if (update ~ "^" section "\\.") {
-                                       flag=1
-                                       gsub("^" section ".", "", update)
-                                       cfg = cfg uci_cmd2option(update) "\n"
-                                       
-                                       update = "-" section "." update
-                               } 
-                               if (flag!=0) cfg = cfg "\n"
-                       }
-                       
-                       remove = ""
-                       section = l[3]
-                       if (!length(section)) {
-                               section = "cfg" scnt
-                       }       
-                       scnt++
-                       if (update == "-" section) {
-                               remove = "section"
-                               update = ""
-                       } else if (update ~ "^@" section "=") {
-                               update = ""
-                       } else if (update ~ "^&" section "=") {
-                               gsub("^&" section "=", "", update)
-                               line = uci_cmd2config(l[2],update) 
-                               update = ""
-                       }
-               }
-               if (remove == "option") remove = ""
-               if (l[1] == "option") {
-                       if (update ~ "^-" section "\\." l[2] "$") remove = "option"
-                       # if a supplied config value already exists, replace the whole line
-                       if (match(update, "^" section "." l[2] "=")) {
-                               gsub("^" section ".", "", update)
-                               line = uci_cmd2option(update)
-                               update = ""
-                       }
-               }
-               if (remove == "") cfg = cfg line "\n"
-       }
-       
-       # any new options for the last section??
-       if (section != "") {
-               if (update ~ "^" section "\\.") {
-                       gsub("^" section ".", "", update)
-                       cfg = cfg uci_cmd2option(update) "\n"
-
-                       update = "-" section "." update
-               } 
-       }
-
-       if (update ~ "^@") {
-               # new section
-               section = stype = substr(update,2)
-               gsub(/=.*$/,"",section)
-               gsub(/^.*=/,"",stype)
-               cfg = cfg "\nconfig \"" stype "\" \"" section "\"\n"
-       }
-
-       return cfg
-}
diff --git a/package/base-files/files/lib/config/uci.sh b/package/base-files/files/lib/config/uci.sh
deleted file mode 100644 (file)
index 71f2048..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-#!/bin/sh
-# Shell script defining macros for manipulating config files
-#
-# Copyright (C) 2006        Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de>
-# Copyright (C) 2006,2007   Felix Fietkau <nbd@openwrt.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-uci_load() {
-       config_load "$1"
-}
-
-uci_apply_defaults() {(
-       cd /etc/uci-defaults || return 0
-       files="$(ls)"
-       [ -z "$files" ] && return 0
-       mkdir -p /tmp/.uci
-       for file in $files; do
-               ( . "./$(basename $file)" ) && rm -f "$file"
-       done
-       uci commit
-)}
-
-uci_call_awk() {
-       local CMD="$*"
-       awk -f $UCI_ROOT/lib/config/uci.awk -f - <<EOF
-BEGIN {
-       $CMD
-}
-EOF
-}
-
-uci_do_update() {
-       local FILENAME="$1"
-       local UPDATE="$2"
-       uci_call_awk "
-       config = read_file(\"$FILENAME\")
-       $UPDATE
-       print config
-"
-}
-
-uci_add_update() {
-       local PACKAGE="$1"
-       local UPDATE="$2"
-       local PACKAGE_BASE="$(basename "$PACKAGE")"
-       local UCIFILE
-
-       case "$PACKAGE" in
-               /*) UCIFILE="$PACKAGE";;
-               *)
-                       UCIFILE="/tmp/.uci/$PACKAGE_BASE"
-                       mkdir -p "/tmp/.uci"
-               ;;
-       esac
-
-       # FIXME: add locking?
-       echo "$UPDATE" >> "$UCIFILE"
-}
-
-uci_set() {
-       local PACKAGE="$1"
-       local CONFIG="$2"
-       local OPTION="$3"
-       local VALUE="$4"
-
-       case "$PACKAGE" in
-               /*)
-                       uci_add_update "$PACKAGE" "config_set '$CONFIG' '$OPTION' '$VALUE'"
-               ;;
-               *)
-                       ( # spawn a subshell so you don't mess up the current environment
-                               uci_load "$PACKAGE"
-                               config_get OLDVAL "$CONFIG" "$OPTION"
-                               if [ "x$OLDVAL" != "x$VALUE" ]; then
-                                       config_get type "$CONFIG" TYPE
-                                       [ -z "$type" ]
-                               fi
-                       ) || uci_add_update "$PACKAGE" "config_set '$CONFIG' '$OPTION' '$VALUE'"
-               ;;
-       esac
-}
-
-uci_add() {
-       local PACKAGE="$1"
-       local TYPE="$2"
-       local CONFIG="$3"
-
-       uci_add_update "$PACKAGE" "config '$TYPE' '$CONFIG'"
-}
-
-uci_rename() {
-       local PACKAGE="$1"
-       local CONFIG="$2"
-       local VALUE="$3"
-
-       uci_add_update "$PACKAGE" "config_rename '$CONFIG' '$VALUE'"
-}
-
-uci_remove() {
-       local PACKAGE="$1"
-       local CONFIG="$2"
-       local OPTION="$3"
-
-       if [ -z "$OPTION" ]; then
-               uci_add_update "$PACKAGE" "config_clear '$CONFIG'"
-       else
-               uci_add_update "$PACKAGE" "config_unset '$CONFIG' '$OPTION'"
-       fi
-}
-
-uci_commit() {
-       local PACKAGE="$1"
-       local PACKAGE_BASE="$(basename "$PACKAGE")"
-
-       case "$PACKAGE" in
-               /*) return 0;;
-       esac
-       mkdir -p /tmp/.uci
-       LOCK=`which lock` || LOCK=:
-       $LOCK "/tmp/.uci/$PACKAGE_BASE.lock"
-       [ -f "/tmp/.uci/$PACKAGE_BASE" ] && (
-               updatestr=""
-               
-               # replace handlers
-               config() {
-                       append updatestr "config = uci_update_config(config, \"@$2=$1\")" "$N"
-               }
-               option() {
-                       append updatestr "config = uci_update_config(config, \"$CONFIG_SECTION.$1=$2\")" "$N"
-               }
-               config_rename() {
-                       append updatestr "config = uci_update_config(config, \"&$1=$2\")" "$N"
-               }
-               config_unset() {
-                       append updatestr "config = uci_update_config(config, \"-$1.$2\")" "$N"
-               }
-               config_clear() {
-                       append updatestr "config = uci_update_config(config, \"-$1\")" "$N"
-               }
-               
-               . "/tmp/.uci/$PACKAGE_BASE"
-
-               # completely disable handlers so that they don't get in the way
-               config() {
-                       return 0
-               }
-               option() {
-                       return 0
-               }
-               
-               config_load "$PACKAGE"
-               CONFIG_FILENAME="${CONFIG_FILENAME:-$UCI_ROOT/etc/config/$PACKAGE_BASE}"
-               uci_do_update "$CONFIG_FILENAME" "$updatestr" > "/tmp/.uci/$PACKAGE_BASE.new" && {
-                       mv -f "/tmp/.uci/$PACKAGE_BASE.new" "$CONFIG_FILENAME" && \
-                       rm -f "/tmp/.uci/$PACKAGE_BASE"
-               } 
-       )
-       $LOCK -u "/tmp/.uci/$PACKAGE_BASE.lock"
-}
-
-
index 98d6f13..611da71 100755 (executable)
@@ -140,7 +140,7 @@ setup_interface() {
        config_get macaddr "$config" macaddr
        grep "$iface:" /proc/net/dev > /dev/null && \
                $DEBUG ifconfig "$iface" ${macaddr:+hw ether "$macaddr"} ${mtu:+mtu $mtu} up
-       uci set "/var/state/network.$config.ifname=$iface"
+       uci_set_state network "$config" ifname "$iface"
 
        pidfile="/var/run/$iface.pid"
        case "$proto" in
index 08433c7..1f200fb 100755 (executable)
        exit
 }
 
-config_load /var/state/network
-
 # remove the interface's network state
-FILE=/var/state/network.$$
-grep -v "^config_set '$1' " /var/state/network > "$FILE"
-mv "$FILE" /var/state/network
+uci_revert_state network "$1"
 
 include /lib/network
 scan_interfaces
index 8b65e45..54e55b4 100755 (executable)
@@ -75,22 +75,19 @@ start_net() {(
 set_wifi_up() {
        local cfg="$1"
        local ifname="$2"
-       uci set "/var/state/wireless.${cfg}.up=1"
-       uci set "/var/state/wireless.${cfg}.ifname=$ifname"
+       uci_set_state wireless "$cfg" up 1
+       uci_set_state wireless "$cfg" ifname "$ifname"
 }
 
 set_wifi_down() {
        local cfg="$1"
        local vifs vif vifstr
-       [ -f /var/state/wireless ] || return
 
+       uci_revert_state wireless "$cfg"
        config_get vifs "$cfg" vifs
        for vif in $vifs; do
-               append vifstr "$vif" "|"
+               uci_revert_state wireless "$vif"
        done
-       FILE="/var/state/wireless.$$"
-       grep -vE "^config_set '($vifstr)' " /var/state/wireless > "$FILE"
-       mv "$FILE" /var/state/wireless
 }
 
 scan_wifi() {
index 30e84e6..147b9f1 100755 (executable)
@@ -7,7 +7,6 @@ RESOLV_CONF="/tmp/resolv.conf.auto"
 
 hotplug_event() {
        scan_interfaces
-       config_load /var/state/network
        for ifc in $interfaces; do
                config_get ifname $ifc ifname
                [ "$ifname" = "$interface" ] || continue
@@ -15,11 +14,11 @@ hotplug_event() {
                config_get proto $ifc proto
                [ "$proto" = "dhcp" ] || continue
                [ ifup = "$1" ] && {
-                       uci set "/var/state/network.$ifc.ipaddr=$ip"
-                       uci set "/var/state/network.$ifc.netmask=${subnet:-255.255.255.0}"
-                       uci set "/var/state/network.$ifc.dnsdomain=$domain"
-                       uci set "/var/state/network.$ifc.dns=$dns"
-                       uci set "/var/state/network.$ifc.gateway=$router"
+                       uci_set_state network "$ifc" ipaddr "$ip"
+                       uci_set_state network "$ifc" netmask "${subnet:-255.255.255.0}"
+                       uci_set_state network "$ifc" dnsdomain "$domain"
+                       uci_set_state network "$ifc" dns "$dns"
+                       uci_set_state network "$ifc" gateway "$router"
                }
                env -i ACTION="$1" INTERFACE="$ifc" DEVICE="$ifname" PROTO=dhcp /sbin/hotplug-call iface
        done
index 4425504..62e2f51 100644 (file)
@@ -231,7 +231,6 @@ dhcp_option_add() {
 start() {
        include /lib/network
        scan_interfaces
-       config_load /var/state/network
        config_load dhcp
 
        args=""
index 204310a..2d8c5ed 100755 (executable)
@@ -6,7 +6,6 @@ START=45
 start() {
        include /lib/network
        scan_interfaces
-       config_load /var/state/network
        
        config_get WAN wan ifname
        config_get WANDEV wan device
index f3d63a0..30151f4 100755 (executable)
@@ -10,9 +10,7 @@ export PPP_IFACE PPP_TTY PPP_SPEED PPP_LOCAL PPP_REMOTE PPP_IPPARAM
        env -i ACTION="ifdown" INTERFACE="$PPP_IPPARAM" DEVICE="$PPP_IFACE" PROTO=ppp /sbin/hotplug-call "iface"
 
        # remove the interface's network state
-       FILE=/var/state/network.$$
-       grep -v "^config_set '$PPP_IPPARAM' " /var/state/network > "$FILE"
-       mv "$FILE" /var/state/network
+       uci_revert_state network "$PPP_IPPARAM"
 }
 
 [ -d /etc/ppp/ip-down.d ] && {
index a50137f..acbb599 100755 (executable)
@@ -8,8 +8,8 @@ PPP_IPPARAM="$6"
 export PPP_IFACE PPP_TTY PPP_SPEED PPP_LOCAL PPP_REMOTE PPP_IPPARAM
 [ -z "$PPP_IPPARAM" ] || env -i ACTION="ifup" INTERFACE="$PPP_IPPARAM" DEVICE="$PPP_IFACE" PROTO=ppp /sbin/hotplug-call "iface"
 [ -z "$PPP_IPPARAM" -o -z "$PPP_LOCAL" ] || {
-       uci set "/var/state/network.$PPP_IPPARAM.ipaddr=$PPP_LOCAL"
-       uci set "/var/state/network.$PPP_IPPARAM.gateway=$PPP_REMOTE"
+       uci_set_state network "$PPP_IPPARAM" ipaddr "$PPP_LOCAL"
+       uci_set_state network "$PPP_IPPARAM" gateway "$PPP_REMOTE"
 }
 
 
index f1c46c9..0743082 100644 (file)
@@ -23,7 +23,7 @@ setup_interface_pptp() {
        # make sure the network state references the correct ifname
        scan_ppp "$config"
        config_get ifname "$config" ifname
-       uci set "/var/state/network.$config.ifname=$ifname"
+       uci_set_state network "$config" ifname "$ifname"
 
        config_get mtu "$cfg" mtu
        config_get server "$cfg" server
index 55ddf3c..04c833b 100755 (executable)
@@ -17,7 +17,6 @@ add_insmod() {
                reset_cb
                include /lib/network
                scan_interfaces
-               config_load /var/state/network
                config_get "$1" ifname
        )}
 } || {
diff --git a/package/uci/Makefile b/package/uci/Makefile
new file mode 100644 (file)
index 0000000..f4bd07f
--- /dev/null
@@ -0,0 +1,75 @@
+# 
+# Copyright (C) 2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=uci
+PKG_VERSION:=0.1
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://downloads.openwrt.org/sources
+PKG_MD5SUM:=f6340dce09f5f1552c4e03be98e64265
+
+include $(INCLUDE_DIR)/package.mk
+
+# set to 1 to enable debugging
+DEBUG=
+
+define Package/libuci
+  SECTION:=libs
+  CATEGORY:=Libraries
+  DEPENDS:=+libuci
+  TITLE:=C library for the Unified Configuration Interface (UCI)
+endef
+
+define Package/uci
+  SECTION:=base
+  CATEGORY:=Base system
+  DEPENDS:=+libuci
+  TITLE:=Utility for the Unified Configuration Interface (UCI)
+endef
+
+define Package/uci-sh
+  SECTION:=base
+  CATEGORY:=Base system
+  DEPENDS:=@!PACKAGE_uci
+  TITLE:=Old shell/awk implementation of UCI
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+       $(MAKE) -C $(PKG_BUILD_DIR) \
+               $(TARGET_CONFIGURE_OPTS) \
+               COPTS="$(TARGET_CFLAGS)" \
+               DEBUG="$(DEBUG)" \
+               VERSION="$(PKG_VERSION)" \
+               OS="Linux"
+endef
+
+define Package/libuci/install
+       $(INSTALL_DIR) $(1)/lib
+       $(CP) $(PKG_BUILD_DIR)/libuci.so* $(1)/lib/
+endef
+
+define Package/uci/install
+       $(INSTALL_DIR) $(1)/sbin
+       $(INSTALL_BIN) $(PKG_BUILD_DIR)/uci $(1)/sbin/
+       $(CP) ./files/uci/* $(1)/
+endef
+
+define Package/uci-sh/install
+       $(INSTALL_DIR) $(1)
+       $(CP) ./files/uci-sh/* $(1)/
+endef
+
+$(eval $(call BuildPackage,uci))
+$(eval $(call BuildPackage,libuci))
+$(eval $(call BuildPackage,uci-sh))
diff --git a/package/uci/files/uci-sh/bin/uci b/package/uci/files/uci-sh/bin/uci
new file mode 100755 (executable)
index 0000000..f89fe82
--- /dev/null
@@ -0,0 +1,190 @@
+#!/bin/sh
+# Shell script for interacting with config files
+#
+# Copyright (C) 2006        Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de>
+# Copyright (C) 2006,2007      Felix Fietkau <nbd@openwrt.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. $UCI_ROOT/etc/functions.sh
+include $UCI_ROOT/lib/config
+
+SEP="[^0-9A-Za-z_]"
+
+do_get() {
+       local PACKAGE
+       local CONFIG
+       local OPTION
+       local DUMMY
+
+       strtok "$*" PACKAGE . CONFIG . OPTION $SEP DUMMY
+
+       [ $? -ne 3 ] && {
+               uci_usage get
+               exit 1
+       }
+
+       uci_load "$PACKAGE"
+       config_get "$CONFIG" "$OPTION"
+}
+
+do_set() {
+       local PACKAGE
+       local CONFIG
+       local OPTION
+       local VALUE
+
+       strtok "$1" PACKAGE . CONFIG = VALUE
+       [ $? -ne 3 -a $? -ne 2 ] && {
+               uci_usage set
+               exit 1
+       }
+       
+       strtok "$CONFIG" CONFIG . OPTION
+       
+       if [ $? -eq 1 ]; then
+               uci_add "$PACKAGE" "$VALUE" "$CONFIG"
+       else
+               uci_set "$PACKAGE" "$CONFIG" "$OPTION" "$VALUE"
+       fi
+}
+
+do_rename() {
+       [ $# -ne 3 ] && {
+               uci_usage rename
+               exit 1
+       }
+       uci_rename "$@"
+}
+
+do_remove() {
+       local PACKAGE
+       local CONFIG
+       local OPTION
+       local DUMMY
+
+       strtok "$*" PACKAGE . CONFIG . OPTION $SEP DUMMY
+       [ $? -ne 3 -a $? -ne 2 ] && {
+               uci_usage rename
+               exit 1
+       }
+       uci_remove "$PACKAGE" "$CONFIG" ${OPTION:+"$OPTION"}
+}
+
+do_commit() {
+       local PACKAGE="$1"
+       for package in ${PACKAGE:-$(cd /tmp/.uci; ls)}; do 
+               [ lock = "${package##*.}" ] && continue # ignore .lock files
+               uci_commit "$package"
+       done
+}
+
+do_show() {
+       local PACKAGE
+       local CONFIG
+       local DUMMY
+
+       strtok "$*" PACKAGE . CONFIG $SEP DUMMY
+       [ $? -gt 2 ] && {
+               uci_usage show
+               exit 1
+       }
+       
+       for package in ${PACKAGE:-$(cd $UCI_ROOT/etc/config; ls)}; do
+               SECTION=""
+       
+               config_cb() {
+                       if [ -z "$CONFIG" -o ."$CONFIG" = ."$2" ]; then
+                               append SECTION "$2"
+                               option_cb() {
+                                       append "${CONFIG_SECTION}_VARS" "$1"
+                               }
+                       else
+                               option_cb() {
+                                       return 0
+                               }
+                       fi
+               }
+                       
+               uci_load "$package"
+       
+               for section in $SECTION; do
+                       config_get type "$section" TYPE
+                       [ -z "$type" ] && continue
+                       echo "$package.$section=$type"
+                       eval "VARS=\"\${${section}_VARS}\""
+                       for var in $VARS; do
+                               config_get val "$section" "$var"
+                               [ -n "$val" ] && {
+                                       echo "$package.$section.$var=$val"
+                                       config_set "$section" "$var" ""
+                               }
+                       done
+                       config_set "$section" TYPE ""
+               done
+       done
+}
+
+do_validate() {
+       [ "$#" -ne 1 ] && {
+               uci_usage validate
+               exit 1
+       }
+       uci_validate "$1" || exit "$?"
+}
+
+uci_usage() {
+       case "$1" in
+               show) echo "$0 show [<package>[.<config>]]";;
+               get) echo "$0 get <package>.<config>.<option>";;
+               set) echo "$0 set <package>.<config>[.<option>]=<value>";;
+               del) echo "$0 del <package>.<config>[.<option>]";;
+               rename) echo "$0 rename <package> <config> <name>";;
+               commit) echo "$0 commit [<package> ... ]";;
+               validate) echo "$0 validate <package>";;
+               *) 
+                       echo "Syntax: $0 <command> <arguments...>"
+                       echo
+                       uci_usage show
+                       uci_usage get
+                       uci_usage set
+                       uci_usage del
+                       uci_usage rename
+                       uci_usage commit
+                       uci_usage validate 
+                       echo
+                       exit 1
+               ;;
+       esac
+}
+
+if [ $# -eq 0 ] ; then
+       uci_usage
+       exit 0
+fi
+
+CMD="$1"
+shift
+case "$CMD" in
+       set) do_set "$@";;
+       del) do_remove "$@";;
+       rename) do_rename "$@";;
+       get) do_get "$@";;
+       show) do_show "$@";;
+       commit) do_commit "$@";;
+       validate) do_validate "$@";;
+       *) uci_usage;;
+esac
+exit 0
diff --git a/package/uci/files/uci-sh/lib/config/uci.awk b/package/uci/files/uci-sh/lib/config/uci.awk
new file mode 100644 (file)
index 0000000..c560907
--- /dev/null
@@ -0,0 +1,186 @@
+# Configuration update functions - AWK API
+#
+# Copyright (C) 2006 by Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de>
+# Copyright (C) 2006 by Felix Fietkau <nbd@openwrt.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# parameters: 1
+function config_load(package, var) {
+       while (("/bin/ash -c '. /etc/functions.sh; unset NO_EXPORT; config_load \""package"\"; env | grep \"^CONFIG_\"'" | getline) == 1) {
+               sub("^CONFIG_", "")
+               if (match($0, "=") == 0) {
+                       if (var != "") CONFIG[var] = CONFIG[var] "\n" $0
+                       next
+               }
+               var=substr($0, 1, RSTART-1)
+               CONFIG[var] = substr($0, RSTART+1, length($0) - RSTART)
+       }
+}
+
+# parameters: 2
+function config_get(package, option) {
+       return CONFIG[package "_" option]
+}
+
+# parameters: 3
+function config_get_bool(package, option, default, var) {
+       var = config_get(package, option);
+       if ((var == "enabled") || (var == "true") || (var == "1") || (var == "on")) return 1
+       if ((var == "disabled") || (var == "false") || (var == "0") || (var == "off")) return 1
+       return (var && var != "0" ? 1 : 0)
+}
+
+
+function read_file(filename,  result) {
+       while ((getline <filename) == 1) {
+               result = result $0 "\n"
+       }
+       gsub(/\n*$/, "", result)
+       return result
+}
+
+function uci_cmd2option(str,  tmp) {
+       if (match(str,"=")!=0) {
+               res = "\toption " substr(str,1,RSTART-1) "\t'" substr(str,RSTART+1) "'"
+       } else {
+               res= ""
+       }
+       return res
+}
+
+function uci_cmd2config(atype,  aname) {
+       return "config \"" atype "\" \"" aname "\""
+}
+
+function uci_update_config(cfg, update,  \
+  lines, line, l, n, i, i2, section, scnt, remove, tmp, aidx, rest) {
+       scnt = 1
+       linecnt=split(cfg "\n", lines, "\n")
+
+       cfg = ""
+       for (n = 1; n < linecnt; n++) {
+               # stupid parser for quoted arguments (e.g. for the type string).
+               # not to be used to gather variable values (backslash escaping doesn't work)
+               line = lines[n]
+               gsub(/^[ \t]*/, "", line)
+               gsub(/#.*$/, "", line)
+               i2 = 1
+               delete l
+               rest = line
+               while (length(rest)) {
+                       if (match(rest, /[ \t\"]+/)) {
+                               if (RSTART>1) {
+                                       l[i2] = substr(rest,1,RSTART-1)
+                                       i2++
+                               }
+                               aidx=index(rest,"\"")
+                               if (aidx>=RSTART && aidx<=RSTART+RLENGTH) {
+                                       rest=substr(rest,aidx+1)
+                                       # find the end of the string
+                                       match(rest,/\"/)
+                                       l[i2]=substr(rest,1,RSTART-1)
+                                       i2++
+                               }
+                               rest=substr(rest,RSTART+RLENGTH)
+                       } else {
+                               l[i2] = rest
+                               i2++
+                               rest = ""
+                       }
+               }
+               line = lines[n]
+
+               # when a command wants to set a config value for the current
+               # section and a blank line is encountered before an option with
+               # the same name, insert it here to maintain some coherency between
+               # manually and automatically created option lines
+               # if an option with the same name appears after this point, simply
+               # ignore it, because it is already set.
+               if ((section != "") && (l[1] != "option")) {
+                       if (line ~ /^[ \t]*$/) {
+                               if (update ~ "^" section "\\.") {
+                                       gsub("^" section ".", "", update)
+                                       cfg = cfg uci_cmd2option(update) "\n"
+                                       gsub(/=.*$/, "", update)
+                                       update = "-" section "." update
+                               }
+                       }
+               }
+
+               if (l[1] == "config") {
+                       # look for all unset values
+                       if (section != "") {
+                               flag=0
+                               if (update ~ "^" section "\\.") {
+                                       flag=1
+                                       gsub("^" section ".", "", update)
+                                       cfg = cfg uci_cmd2option(update) "\n"
+
+                                       update = "-" section "." update
+                               }
+                               if (flag!=0) cfg = cfg "\n"
+                       }
+
+                       remove = ""
+                       section = l[3]
+                       if (!length(section)) {
+                               section = "cfg" scnt
+                       }
+                       scnt++
+                       if (update == "-" section) {
+                               remove = "section"
+                               update = ""
+                       } else if (update ~ "^@" section "=") {
+                               update = ""
+                       } else if (update ~ "^&" section "=") {
+                               gsub("^&" section "=", "", update)
+                               line = uci_cmd2config(l[2],update)
+                               update = ""
+                       }
+               }
+               if (remove == "option") remove = ""
+               if (l[1] == "option") {
+                       if (update ~ "^-" section "\\." l[2] "$") remove = "option"
+                       # if a supplied config value already exists, replace the whole line
+                       if (match(update, "^" section "." l[2] "=")) {
+                               gsub("^" section ".", "", update)
+                               line = uci_cmd2option(update)
+                               update = ""
+                       }
+               }
+               if (remove == "") cfg = cfg line "\n"
+       }
+
+       # any new options for the last section??
+       if (section != "") {
+               if (update ~ "^" section "\\.") {
+                       gsub("^" section ".", "", update)
+                       cfg = cfg uci_cmd2option(update) "\n"
+
+                       update = "-" section "." update
+               }
+       }
+
+       if (update ~ "^@") {
+               # new section
+               section = stype = substr(update,2)
+               gsub(/=.*$/,"",section)
+               gsub(/^.*=/,"",stype)
+               cfg = cfg "\nconfig \"" stype "\" \"" section "\"\n"
+       }
+
+       return cfg
+}
diff --git a/package/uci/files/uci-sh/lib/config/uci.sh b/package/uci/files/uci-sh/lib/config/uci.sh
new file mode 100644 (file)
index 0000000..f584832
--- /dev/null
@@ -0,0 +1,214 @@
+#!/bin/sh
+# Shell script defining macros for manipulating config files
+#
+# Copyright (C) 2006        Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de>
+# Copyright (C) 2006,2007   Felix Fietkau <nbd@openwrt.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+uci_set_default() {
+       local PACKAGE="$1"
+       [ -e "/etc/config/$1" ] && return 0
+       cat > "/etc/config/$1"
+}
+
+uci_load() {
+       local cfg
+       local uci
+
+       _C=0
+       export ${NO_EXPORT:+-n} CONFIG_SECTIONS=
+       export ${NO_EXPORT:+-n} CONFIG_NUM_SECTIONS=0
+       export ${NO_EXPORT:+-n} CONFIG_SECTION=
+
+       case "$PACKAGE" in
+               /*) cfg="$PACKAGE";;
+                *) 
+                       cfg="$UCI_ROOT/etc/config/$PACKAGE"
+                       uci="$UCI_ROOT/tmp/.uci/$PACKAGE"
+                       state="$UCI_ROOT/var/state/$PACKAGE"
+               ;;
+       esac
+
+       # no config?
+       [ -z "$cfg" -o \! -f "$cfg" ] && return 1
+       . "$cfg"
+
+       ${CONFIG_SECTION:+config_cb}
+
+       [ -z "$uci" -o \! -f "$uci" ] || . "$uci"
+       [ -z "$LOAD_STATE" -z "$state" -o \! -f "$state" ] || . "$state"
+
+       return 0
+}
+
+uci_call_awk() {
+       local CMD="$*"
+       awk -f $UCI_ROOT/lib/config/uci.awk -f - <<EOF
+BEGIN {
+       $CMD
+}
+EOF
+}
+
+uci_do_update() {
+       local FILENAME="$1"
+       local UPDATE="$2"
+       uci_call_awk "
+       config = read_file(\"$FILENAME\")
+       $UPDATE
+       print config
+"
+}
+
+uci_add_update() {
+       local PACKAGE="$1"
+       local UPDATE="$2"
+       local PACKAGE_BASE="$(basename "$PACKAGE")"
+       local UCIFILE
+
+       case "$PACKAGE" in
+               /*) UCIFILE="$PACKAGE";;
+               *)
+                       UCIFILE="/tmp/.uci/$PACKAGE_BASE"
+                       mkdir -p "/tmp/.uci"
+               ;;
+       esac
+
+       # FIXME: add locking?
+       echo "$UPDATE" >> "$UCIFILE"
+}
+
+uci_revert_state() {
+       local PACKAGE="$1"
+       local CONFIG="$2"
+       FILE="/var/state/$PACKAGE.$$"
+       grep -v "^config_set '$CONFIG' " "/var/state/$PAKAGE" > "$FILE"
+       mv "$FILE" "/var/state/$PACKAGE"
+}
+
+uci_set_state() {
+       local PACKAGE="$1"
+       local CONFIG="$2"
+       local OPTION="$3"
+       local VALUE="$4"
+
+       [ -z "$VALUE" ] && return 1
+       uci_set "/var/state/$PACKAGE" "$CONFIG" "$OPTION" "$VALUE"
+}
+
+
+uci_set() {
+       local PACKAGE="$1"
+       local CONFIG="$2"
+       local OPTION="$3"
+       local VALUE="$4"
+
+       case "$PACKAGE" in
+               /*)
+                       uci_add_update "$PACKAGE" "config_set '$CONFIG' '$OPTION' '$VALUE'"
+               ;;
+               *)
+                       ( # spawn a subshell so you don't mess up the current environment
+                               uci_load "$PACKAGE"
+                               config_get OLDVAL "$CONFIG" "$OPTION"
+                               if [ "x$OLDVAL" != "x$VALUE" ]; then
+                                       config_get type "$CONFIG" TYPE
+                                       [ -z "$type" ]
+                               fi
+                       ) || uci_add_update "$PACKAGE" "config_set '$CONFIG' '$OPTION' '$VALUE'"
+               ;;
+       esac
+}
+
+uci_add() {
+       local PACKAGE="$1"
+       local TYPE="$2"
+       local CONFIG="$3"
+
+       uci_add_update "$PACKAGE" "config '$TYPE' '$CONFIG'"
+}
+
+uci_rename() {
+       local PACKAGE="$1"
+       local CONFIG="$2"
+       local VALUE="$3"
+
+       uci_add_update "$PACKAGE" "config_rename '$CONFIG' '$VALUE'"
+}
+
+uci_remove() {
+       local PACKAGE="$1"
+       local CONFIG="$2"
+       local OPTION="$3"
+
+       if [ -z "$OPTION" ]; then
+               uci_add_update "$PACKAGE" "config_clear '$CONFIG'"
+       else
+               uci_add_update "$PACKAGE" "config_unset '$CONFIG' '$OPTION'"
+       fi
+}
+
+uci_commit() {
+       local PACKAGE="$1"
+       local PACKAGE_BASE="$(basename "$PACKAGE")"
+
+       case "$PACKAGE" in
+               /*) return 0;;
+       esac
+       mkdir -p /tmp/.uci
+       LOCK=`which lock` || LOCK=:
+       $LOCK "/tmp/.uci/$PACKAGE_BASE.lock"
+       [ -f "/tmp/.uci/$PACKAGE_BASE" ] && (
+               updatestr=""
+               
+               # replace handlers
+               config() {
+                       append updatestr "config = uci_update_config(config, \"@$2=$1\")" "$N"
+               }
+               option() {
+                       append updatestr "config = uci_update_config(config, \"$CONFIG_SECTION.$1=$2\")" "$N"
+               }
+               config_rename() {
+                       append updatestr "config = uci_update_config(config, \"&$1=$2\")" "$N"
+               }
+               config_unset() {
+                       append updatestr "config = uci_update_config(config, \"-$1.$2\")" "$N"
+               }
+               config_clear() {
+                       append updatestr "config = uci_update_config(config, \"-$1\")" "$N"
+               }
+               
+               . "/tmp/.uci/$PACKAGE_BASE"
+
+               # completely disable handlers so that they don't get in the way
+               config() {
+                       return 0
+               }
+               option() {
+                       return 0
+               }
+               
+               config_load "$PACKAGE"
+               CONFIG_FILENAME="${CONFIG_FILENAME:-$UCI_ROOT/etc/config/$PACKAGE_BASE}"
+               uci_do_update "$CONFIG_FILENAME" "$updatestr" > "/tmp/.uci/$PACKAGE_BASE.new" && {
+                       mv -f "/tmp/.uci/$PACKAGE_BASE.new" "$CONFIG_FILENAME" && \
+                       rm -f "/tmp/.uci/$PACKAGE_BASE"
+               } 
+       )
+       $LOCK -u "/tmp/.uci/$PACKAGE_BASE.lock"
+}
+
+
diff --git a/package/uci/files/uci/lib/config/uci.sh b/package/uci/files/uci/lib/config/uci.sh
new file mode 100644 (file)
index 0000000..3a264a2
--- /dev/null
@@ -0,0 +1,93 @@
+#!/bin/sh
+# Shell script compatibility wrappers for /sbin/uci
+#
+# Copyright (C) 2008  Felix Fietkau <nbd@openwrt.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+uci_load() {
+       local PACKAGE="$1"
+
+       _C=0
+       export ${NO_EXPORT:+-n} CONFIG_SECTIONS=
+       export ${NO_EXPORT:+-n} CONFIG_NUM_SECTIONS=0
+       export ${NO_EXPORT:+-n} CONFIG_SECTION=
+
+       eval "$(/sbin/uci ${LOAD_STATE:+-P /var/state} -S -n export "$PACKAGE")"
+
+       ${CONFIG_SECTION:+config_cb}
+}
+
+uci_set_default() {
+       local PACKAGE="$1"
+       /sbin/uci -q show "$1" > /dev/null && return 0
+       /sbin/uci import "$1"
+}
+
+uci_revert_state() {
+       local PACKAGE="$1"
+       local CONFIG="$2"
+       local OPTION="$3"
+
+       /bin/uci -P /var/state revert "$PACKAGE${CONFIG:+.$CONFIG}${OPTION:+.$OPTION}"
+}
+
+uci_set_state() {
+       local PACKAGE="$1"
+       local CONFIG="$2"
+       local OPTION="$3"
+       local VALUE="$4"
+
+       [ -z "$VALUE" ] && return 0
+       /sbin/uci -P /var/state set "$PACKAGE.$CONFIG${OPTION:+.$OPTION}=$VALUE"
+}
+
+uci_set() {
+       local PACKAGE="$1"
+       local CONFIG="$2"
+       local OPTION="$3"
+       local VALUE="$4"
+
+       /sbin/uci set "$PACKAGE.$CONFIG.$OPTION=$TYPE"
+}
+
+uci_add() {
+       local PACKAGE="$1"
+       local TYPE="$2"
+       local CONFIG="$3"
+
+       /sbin/uci set "$PACKAGE.$CONFIG=$TYPE"
+}
+
+uci_rename() {
+       local PACKAGE="$1"
+       local CONFIG="$2"
+       local VALUE="$3"
+
+       /sbin/uci rename "$PACKAGE.$CONFIG=$VALUE"
+}
+
+uci_remove() {
+       local PACKAGE="$1"
+       local CONFIG="$2"
+       local OPTION="$3"
+
+       /sbin/uci del "$PACKAGE.$CONFIG${OPTION:+.$OPTION}"
+}
+
+uci_commit() {
+       local PACKAGE="$1"
+       /sbin/uci commit $PACKAGE
+}