summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile67
-rw-r--r--README19
-rw-r--r--lbu371
-rwxr-xr-xlibalpine.sh54
-rw-r--r--setup-alpine48
-rwxr-xr-xsetup-dns25
-rwxr-xr-xsetup-hostname14
-rwxr-xr-xsetup-interfaces136
-rw-r--r--setup-webconf21
-rw-r--r--update-conf74
10 files changed, 829 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..87d1658
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,67 @@
+V=0.6.0
+P=alpine-conf
+PV=$(P)-$(V)
+APKF=$(PV).apk
+TARGZ=$(PV).tar.gz
+PREFIX=/usr/local
+TMP=$(PV)
+
+LIB_FILES=libalpine.sh
+SBIN_FILES=lbu\
+ setup-interfaces\
+ setup-dns\
+ setup-hostname\
+ setup-alpine\
+ setup-webconf\
+ update-conf
+EXTRA_DIST=Makefile README
+
+DIST_FILES=$(LIB_FILES) $(SBIN_FILES) $(EXTRA_DIST)
+
+DESC="Alpine configuration scripts"
+WWW="http://alpinelinux.org/alpine-conf"
+
+
+TAR=tar
+DB=$(TMP)/var/db/apk/$(PV)
+
+.PHONY: all apk clean dist install uninstall
+all:
+ sed -i 's|^PREFIX=.*|PREFIX=$(PREFIX)|' $(SBIN_FILES)
+
+apk: $(APKF)
+
+dist: $(TARGZ)
+
+$(APKF): $(SBIN_FILES)
+ rm -rf $(TMP)
+ make all PREFIX=
+ make install DESTDIR=$(TMP) PREFIX=
+ mkdir -p $(DB)
+ echo $(DESC) > $(DB)/DESC
+ cd $(TMP) && $(TAR) -czf ../$@ .
+ rm -rf $(TMP)
+
+$(TARGZ): $(DIST_FILES)
+ rm -rf $(TMP)
+ mkdir -p $(TMP)
+ cp $(DIST_FILES) $(TMP)
+ $(TAR) -czf $@ $(TMP)
+
+install:
+ install -m 755 -d $(DESTDIR)/$(PREFIX)/sbin
+ install -m 755 $(SBIN_FILES) $(DESTDIR)/$(PREFIX)/sbin
+ install -m 755 -d $(DESTDIR)/$(PREFIX)/lib
+ install -m 755 $(LIB_FILES) $(DESTDIR)/$(PREFIX)/lib
+
+uninstall:
+ for i in $(SBIN_FILES); do \
+ rm -f "$(DESTDIR)/$(PREFIX)/sbin/$$i";\
+ done
+ for i in $(LIB_FILES); do \
+ rm -f "$(DESTDIR)/$(PREFIX)/lib/$$i";\
+ done
+
+clean:
+ rm -rf $(APKF) $(TMP) $(TARGZ)
+
diff --git a/README b/README
new file mode 100644
index 0000000..64a2cab
--- /dev/null
+++ b/README
@@ -0,0 +1,19 @@
+Alpine Conf are a set of utilities for making backup of config files.
+
+* The concept
+Specify the files you want to backup in a list, /etc/backuplist. You can add
+or delete entries in this list with the utilities lbu_add and lbu_delete.
+
+To actually prform the backup, use the utility lbu_commit. The files can be
+"commited" (backed up) to either floppy or usb.
+
+For example:
+
+ lbu_add /etc/networking/interfaces
+ lbu_commit floppy
+
+
+To install, run:
+
+ make install
+
diff --git a/lbu b/lbu
new file mode 100644
index 0000000..f7ee4bf
--- /dev/null
+++ b/lbu
@@ -0,0 +1,371 @@
+#!/bin/sh
+
+# lbu - utility to create local backups.
+# Copyright (c) 2006 Natanael Copa
+# May be distributed under GPL2
+
+PREFIX=
+. $PREFIX/lib/libalpine.sh
+# this one is from apk-tools
+. $PREFIX/lib/apk/libutil.sh
+
+VERSION=0.6_beta1
+[ "$SFIC" ] && SFIC="$SFIC -i d"
+
+# globals
+CURRENT_TDB="$APK_CACHE/current.tdb"
+TMPCURRENT_TDB="$APK_CACHE/tmp-current.tdb"
+COMMITED_TDB="$APK_CACHE/commited.tdb"
+
+EXCLUDE_LIST=/etc/lbu/exclude
+INCLUDE_LIST=/etc/lbu/include
+
+MASK="Npugsh"
+
+LBUDIRS=`echo "$APK_LBUDIRS" | sed 's/:/ /g'`
+
+retcode=0
+usage() {
+ echo "$PROGRAM $VERSION"
+ echo "usage: $PROGRAM <subcommand> [options] [args]
+
+Available subcommands:
+ commit (ci)
+ exclude (ex, delete)
+ include (inc, add)
+ status (stat, st)
+ update (up)
+
+Common options:
+ -h Show help for subcommand.
+ -q Quiet mode.
+ -v Verbose mode.
+"
+ exit 1
+}
+
+
+#gen_temp_tdb() {
+# # generate temp tdb
+# local opwd="$PWD"
+# rm -f "$TMP_TDB"
+# cd "$ROOT"
+# $SFIC -R --add "$TMP_TDB" $LBUDIRS
+# cd "$opwd"
+#}
+
+gen_current_tdb() {
+# [ -f "$TMP_TDB" ] || gen_temp_tdb
+ # generate current tdb
+ rm -f "$CURRENT_TDB"
+ $SFIC -R -t --mask "$MASK" --old "$APK_DEFAULT_TDB" $LBUDIRS \
+ | grep -v ^D | awk '{print $2}' | $SFIC --add $CURRENT_TDB --file -
+}
+
+# list_add(char *listfile, char* file...)
+list_add() {
+ local list="$1"
+ shift
+ mkdir -p `dirname "$list"`
+ while [ $# -gt 0 ] ; do
+ filename=`echo "$1" | sed 's:^/\+::'`
+ if grep "^$filename$" "$list" >/dev/null 2>&1 ; then
+ [ "$VERBOSE" ] echo "$filename is already in $list."
+ else
+ [ "$VERBOSE" ] && echo "Adding $filename to $list."
+ echo "$filename" >> "$list"
+ fi
+ shift
+ done
+}
+
+# list_delete(char *listfile, char *file...)
+list_delete() {
+ local list="$1"
+ local tmp="$list.old"
+ shift
+ [ -f "$list" ] || return 1
+ while [ $# -gt 0 ] ; do
+ filename=`echo "$1" | sed 's:^/\+::'`
+ mv "$list" "$tmp"
+ [ "$VERBOSE" ] && echo "Removing $filename from list."
+ grep -v "^$filename$" "$tmp" > "$list"
+ rm "$tmp"
+ shift
+ done
+}
+
+
+
+#
+# lbu_include - add/remove files to include list
+#
+usage_include() {
+ echo "$PROGRAM $VERSION
+usage: $PROGRAM include [-rv] <file> ...
+ $PROGRAM include [-v] -l
+
+Options:
+ -l List contents of include list.
+ -r Remove specified file(s) from include list instead of adding.
+ -v Verbose mode.
+"
+ exit 1
+}
+
+cmd_include() {
+ if [ "$LIST" ] ; then
+ [ $# -gt 0 ] && usage_include
+ show_include
+ return
+ fi
+
+ [ $# -lt 1 ] && usage_include
+ if [ "$REMOVE" ] ; then
+ list_delete "$INCLUDE_LIST" "$@"
+ else
+ list_add "$INCLUDE_LIST" "$@"
+ list_delete "$EXCLUDE_LIST" "$@"
+ fi
+}
+
+show_include() {
+ if [ -f "$INCLUDE_LIST" ] ; then
+ [ "$VERBOSE" ] && echo "Include files:"
+ cat "$INCLUDE_LIST"
+ fi
+}
+
+
+#
+# lbu_commit - commit config files to writeable media
+#
+usage_commit() {
+ echo "$PROGRAM $VERSION
+usage: $PROGRAM commit [-nv] [<media>]
+
+Options:
+ -n Don't commit, just show what would have been commited.
+ -v Verbose mode.
+
+The following values for <media> is supported: floppy usb
+If <media> is not specified, the environment variable LBU_MEDIA will be used.
+"
+ exit 1
+}
+
+cmd_commit() {
+ local media mnt was_mounted statuslist tmplist currentlist
+ local incl excl outfile
+
+ if [ "$1" ] ; then
+ media="$1"
+ else
+ media="$LBU_MEDIA"
+ fi
+ [ -z "$media" ] && usage_commit
+
+ mnt=/media/$media
+
+ [ -d $mnt ] || usage
+ was_mounted=`grep $mnt /proc/mounts`
+
+ cd "$ROOT"
+
+ # Automatically add list and modified files
+ currentlist=`VERBOSE="" USE_DEFAULT="-a" cmd_status -a | grep -v ^D | awk '{print $2}'`
+
+ if [ -z "$was_mounted" ]; then
+ mount $mnt || die "failed to mount $mnt."
+ fi
+
+ # we generate a tmpcurrent before we commit to avoid race condition
+ [ -f "$CURRENT_TDB" ] || $SFIC --add "$CURRENT_TDB" $currentlist
+
+ # commit files to archive
+ if [ "$DRYRUN" ] ; then
+ outfile=/dev/null
+ VERBOSE="-v"
+ else
+ outfile="$mnt/`hostname`.apkovl.tar.gz"
+ fi
+
+ [ -f "$EXCLUDE_LIST" ] && excl="-X $EXCLUDE_LIST"
+ [ -f "$INCLUDE_LIST" ] && incl="-T $INCLUDE_LIST"
+
+ if ! tar $VERBOSE $excl $incl -c $currentlist | gzip -c >"$outfile" ; then
+ rm -f "$CURRENT_TDB"
+ [ -z "$was_mounted" ] && umount $mnt
+ die "Problems creating archive. aborting"
+ fi
+
+ #cp /etc/alpine.conf $mnt
+ # we strip off the version number to make upgrades easier.
+ [ "$DRYRUN" ] || apk_info | sed 's/-[0-9].*//' > $mnt/packages.list
+
+ sync
+ sleep 1
+ [ -z "$was_mounted" ] && umount $mnt
+
+ # move current to commited.
+ [ "$DRYRUN" ] || mv "$CURRENT_TDB" "$COMMITED_TDB"
+}
+
+#---------------------------------------------------------------------------
+# lbu_exclude - add remove file(s) from exclude list
+
+usage_exclude() {
+ echo "$PROGRAM $VERSION
+usage: $PROGRAM exclude [-rv] <file> ...
+ $PROGRAM exclude [-v] -l
+
+Options:
+ -l List contents of exclude list.
+ -r Remove specified file(s) from exclude list instead of adding.
+ -v Verbose mode.
+"
+ exit 1
+}
+
+cmd_exclude() {
+ if [ "$LIST" ] ; then
+ [ $# -gt 0 ] && usage_exclude
+ show_exclude
+ return
+ fi
+
+ [ $# -lt 1 ] && usage_exclude
+ if [ "$REMOVE" ] ; then
+ list_delete "$EXCLUDE_LIST" "$@"
+ else
+ list_delete "$INCLUDE_LIST" "$@"
+ list_add "$EXCLUDE_LIST" "$@"
+ fi
+}
+
+show_exclude() {
+ if [ -f "$EXCLUDE_LIST" ] ; then
+ [ "$VERBOSE" ] && echo "Exclude files:"
+ cat "$EXCLUDE_LIST"
+ fi
+}
+
+#---------------------------------------------------------------------------
+# lbu_status - check what files have been changed since last save
+usage_status() {
+ echo "$PROGRAM $VERSION
+Check what files have been changed since last commit.
+
+usage: $PROGRAM status [-M <MASK>] [-av]
+
+Options:
+ -M Use a different mask for comparing. (see sfic -h)
+ -a Compare all files, not just since last commit.
+ -v Also show include and exclude lists.
+"
+ exit 1
+}
+
+cmd_status() {
+ cd "$ROOT"
+
+ [ "$SFIC" ] || die "Need sfic."
+ [ -f "$APK_DEFAULT_TDB" ] || die "$APK_DEFAULT_TDB not found."
+
+ # genereate temp tdb
+ #gen_temp_tdb
+
+ if [ -f "$COMMITED_TDB" ] && [ -z "$USE_DEFAULT" ]; then
+ # generate current tdb
+ gen_current_tdb
+ OLD="$COMMITED_TDB"
+ NEW="--new $CURRENT_TDB"
+ else
+ OLD="$APK_DEFAULT_TDB"
+ NEW="-R $LBUDIRS"
+ fi
+
+ $SFIC $QUIET $VERBOSE --mask "$MASK" -t --old "$OLD" $NEW
+ retcode=$?
+
+ if [ "$VERBOSE" ] ; then
+ echo ""
+ show_include
+ echo ""
+ show_exclude
+ fi
+}
+
+#------------------------------------------------
+# lbu_update - Update the database wihtout commit to media.
+usage_update() {
+ echo "$PROGRAM $VERSION
+Update the commited database without commit to media.
+
+usage: $PROGRAM update [-v] <file> ...
+
+Options:
+ -v Verbose mode.
+"
+ exit 1
+}
+
+cmd_update() {
+ [ $# -lt 1 ] && usage_update
+ cd "$ROOT"
+ for i in "$@" ; do
+ echo $i | sed 's:^/::'
+ done | lbu_filter | $SFIC $VERBOSE --add "$COMMITED_TDB" --file -
+}
+
+#-----------------------------------------------------------
+# Main
+
+cmd=`echo "$PROGRAM" | cut -s -d_ -f2`
+PROGRAM=`echo "$PROGRAM" | cut -d_ -f1`
+if [ -z "$cmd" ] ; then
+ cmd="$1"
+ [ -z "$cmd" ] && usage
+ shift
+fi
+
+# check for valid sub command
+case "$cmd" in
+ include|inc|add) SUBCMD="include";;
+ commit|ci) SUBCMD="commit";;
+ exclude|ex|delete) SUBCMD="exclude";;
+ status|stat|st) SUBCMD="status";;
+ update|up) SUBCMD="update";;
+ *) usage;;
+esac
+
+# parse common args
+while getopts "ahlM:nqrv" opt ; do
+ case "$opt" in
+ a) [ $SUBCMD = status ] || usage_$SUBCMD
+ USE_DEFAULT="-a"
+ ;;
+ h) usage_$SUBCMD
+ ;;
+ l) LIST="-l"
+ ;;
+ M) [ $SUBCMD = status ] || usage_$SUBCMD
+ MASK="$OPTARG"
+ ;;
+ n) [ $SUBCMD = commit ] || usage_$SUBCMD
+ DRYRUN="-n"
+ ;;
+ q) QUIET="$QUIET -q"
+ ;;
+ r) REMOVE="-r"
+ ;;
+ v) VERBOSE="$VERBOSE -v"
+ ;;
+ esac
+done
+shift `expr $OPTIND - 1`
+
+cmd_$SUBCMD "$@"
+# cleanup
+rm -f "$CURRENT_TDB"
+exit $retcode
diff --git a/libalpine.sh b/libalpine.sh
new file mode 100755
index 0000000..871459f
--- /dev/null
+++ b/libalpine.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+PREFIX=
+
+PROGRAM=`basename $0`
+
+
+echon () {
+ if [ X"$ECHON" = X ]; then
+ # Determine how to "echo" without newline: "echo -n"
+ # or "echo ...\c"
+ if [ X`echo -n` = X-n ]; then
+ ECHON=echo
+ NNL="\c"
+ # "
+ else
+ ECHON="echo -n"
+ NNL=""
+ fi
+ fi
+ $ECHON "$*$NNL"
+}
+
+init_tmpdir() {
+ local omask=`umask`
+ local __tmpd="/tmp/$PROGRAM-${$}-`date +%s`"
+ umask 077 || die "umask"
+ mkdir "$__tmpd" || exit 1
+ trap "rm -fr \"$__tmpd\"; exit" 0
+ umask $omask
+ eval "$1=\"$__tmpd\""
+}
+
+pkg_inst() {
+ [ -z "$NOCOMMIT" ] && apk_add $*
+}
+
+default_read() {
+ local n
+ read n
+ [ -z "$n" ] && n="$2"
+ eval "$1=\"$n\""
+}
+
+
+invalid_ip() {
+ [ "$1" ] || return 0
+ ! ipcalc -s $1
+}
+
+
+cfg_add() {
+ [ -z "$NOCOMMIT" ] && lbu_add "$@"
+}
diff --git a/setup-alpine b/setup-alpine
new file mode 100644
index 0000000..fc87e7b
--- /dev/null
+++ b/setup-alpine
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+PROGRAM=setup-alpine
+VERSION=0.1
+
+PREFIX=
+. $PREFIX/lib/libalpine.sh
+
+while getopts "ah" opt ; do
+ case $opt in
+ a) ARCHIVE=yes;;
+ h) usage;;
+ *) usage;;
+ esac
+done
+shift `expr $OPTIND - 1`
+
+if [ "$ARCHIVE" ] ; then
+ echo "Creating an Alpine overlay"
+ init_tmpdir ROOT
+else
+ PKGADD=apk_add
+fi
+
+$PREFIX/sbin/setup-hostname
+$PREFIX/sbin/setup-interfaces
+
+# setup up dns if no dhcp was configured
+grep '^iface.*dhcp' $ROOT/etc/network/interfaces > /dev/null ||\
+ $PREFIX/sbin/setup-dns
+
+# set root password
+[ -z "$NOCOMMIT" ] && while ! passwd ; do echo "Please retry." ; done
+
+# add some boot services
+rc_add -s 01 hwclock
+rc_add -s 04 modutils
+rc_add -s 06 procps
+rc_add -s 08 hostname
+
+rc_add -s 20 syslog
+rc_add -s 22 bootmisc.sh
+rc_add -s 24 -k networking
+
+# start up the services
+for i in hwclock modutils procps hostname syslog bootmisc.sh networking ; do
+ /etc/init.d/$i start
+done
diff --git a/setup-dns b/setup-dns
new file mode 100755
index 0000000..fd6b04e
--- /dev/null
+++ b/setup-dns
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+PREFIX=
+. "$PREFIX/lib/libalpine.sh"
+
+conf="$ROOT/etc/resolv.conf"
+if [ -f "$conf" ] ; then
+ domain=`awk '/^domain/ {print $2}' $conf`
+ dns=`awk '/^nameserver/ {print $2}' $conf`
+fi
+
+echon "DNS domain name? (e.g 'bar.com') [$domain] "
+default_read domain $domain
+echon "DNS nameserver(s)? ["
+for i in $dns ; do
+ echon "$i "
+done
+echon "] "
+default_read dns "$dns"
+
+echo "search $domain" > $conf
+for i in $dns ; do
+ echo "nameserver $i" >> $conf
+done
+
diff --git a/setup-hostname b/setup-hostname
new file mode 100755
index 0000000..b1c2379
--- /dev/null
+++ b/setup-hostname
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+PROGRAM=setup-hostname
+PREFIX=
+
+. $PREFIX/lib/libalpine.sh
+
+HOST=`hostname`
+echon "Enter system hostname (short form, e.g. 'foo') [$HOST]: "
+default_read HOST `hostname`
+
+mkdir -p "$ROOT/etc"
+echo "$HOST" > "$ROOT/etc/hostname"
+
diff --git a/setup-interfaces b/setup-interfaces
new file mode 100755
index 0000000..cfb4ad0
--- /dev/null
+++ b/setup-interfaces
@@ -0,0 +1,136 @@
+#!/bin/sh
+
+PROGRAM=setup-interfaces
+PREFIX=
+
+. $PREFIX/lib/libalpine.sh
+
+
+detect_interfaces() {
+ ip addr | grep -v ' lo:' | awk -F : '/^[0-9]*:/ { print $2}'
+}
+
+get_first_unconfigured() {
+ ls *.noconf 2>/dev/null | head -n 1 | sed 's/.noconf//'
+}
+
+get_default_addr() {
+ # check if dhcpcd is running
+ if pidof dhcpcd > /dev/null && [ -f "$ROOT/var/lib/dhcpc/dhcpcd-$1.info" ]; then
+ echo dhcp
+ else
+ ip addr show $1 | awk '/inet / {print $2}' | head -n 1 | sed 's:/.*::'
+ fi
+}
+
+get_default_mask() {
+ if [ "$1" ] ; then
+ ipcalc -m $1 | sed 's/.*=//'
+ else
+ echo "255.255.255.0"
+ fi
+}
+
+get_default_gateway() {
+ ip route show dev $1 | awk '/^default/ {print $3}'
+}
+
+
+config_iface() {
+ local iface=$1
+ local address
+ local netmask
+ local gateway
+ while invalid_ip $address ; do
+ address=`get_default_addr $iface`
+ echon "Ip address for $iface? (or 'dhcp') [$address] "
+ default_read address $address
+ [ "$address" = "abort" ] && return
+ if [ "$address" = "dhcp" ] ; then
+ HAS_DHCP=yes
+ echo "type=dhcp" > $iface.conf
+ rm $iface.noconf
+ return
+ fi
+ done
+
+ while invalid_ip $netmask ; do
+ netmask=`get_default_mask $address`
+ echon "Netmask? [$netmask] "
+ default_read netmask "$netmask"
+ [ "$netmask" = "abort" ] && return
+ done
+
+ while invalid_ip $gateway ; do
+ gateway=`get_default_gateway $iface`
+ [ -z "$gateway" ] && gateway=none
+ echon "Gateway? (or 'none') [$gateway] "
+ default_read gateway $gateway
+ [ "$gateway" = "abort" ] && return
+ [ "$gateway" = "none" ] && gateway=""
+ [ -z "$gateway" ] && break
+ done
+
+ echo "type=static" > $iface.conf
+ echo "address=$address" >> $iface.conf
+ echo "netmask=$netmask" >> $iface.conf
+ echo "gateway=$gateway" >> $iface.conf
+
+ rm $iface.noconf
+}
+
+init_tmpdir TMP
+
+cd $TMP
+for i in $(detect_interfaces); do
+ touch $i.noconf
+done
+
+
+while ls *.noconf > /dev/null 2>&1 ; do
+ echon "Available interfaces are:"
+ for i in *.noconf; do
+ echon " `basename $i .noconf`"
+ done
+ echo "."
+
+ firstif=`get_first_unconfigured`
+ echon "Which one do you want to initialize? (or 'done') [$firstif] "
+ default_read iface "$firstif"
+
+ [ "$iface" = "done" ] && break
+ [ -f $iface.noconf ] || continue
+ config_iface $iface
+done
+
+echo "type=loopback" > lo.conf
+echo "" > interface
+for i in *.conf ; do
+ iface=`basename $i .conf`
+ . ./$i
+ echo "" >> interfaces
+ echo "auto $iface" >> interfaces
+ echo "iface $iface inet $type" >> interfaces
+ [ "$type" = "static" ] || continue
+ echo " address $address" >> interfaces
+ echo " netmask $netmask" >> interfaces
+ [ "$gateway" ] && echo " gateway $gateway" >> interfaces
+done
+
+while [ "$answer" != "yes" ] && [ "$answer" != "no" ] ; do
+ echon "Do you want to do any manual network configuration? [no] "
+ default_read answer no
+done
+
+if [ "$answer" = "yes" ]; then
+ [ -z "$EDITOR" ] && EDITOR=nano
+ case $EDITOR in
+ nano) pkg_inst nano;;
+ vim) pkg_inst vim;;
+ esac
+ $EDITOR interfaces
+fi
+
+mkdir -p $ROOT/etc/network
+cp interfaces $ROOT/etc/network/
+
diff --git a/setup-webconf b/setup-webconf
new file mode 100644
index 0000000..939b6e2
--- /dev/null
+++ b/setup-webconf
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# script to set up webconf
+
+apk_add mini_httpd webconf-mvc
+
+sed -i 's:MINI_HTTPD_OPTS=.*:MINI_HTTPD_OPTS="-C /etc/mini_httpd.conf":
+ s:#MINI_HTTPD_DOCROOT=.*:MINI_HTTPD_DOCROOT=/var/lib/webconf/www:
+ ' /etc/conf.d/mini_httpd
+
+cat - > /etc/mini_httpd.conf <<EOF
+nochroot
+dir=/var/lib/webconf/www
+user=root
+logfile=/var/log/mini_httpd.log
+cgipat=cgi-bin**
+
+EOF
+
+rc_add mini_httpd
+/etc/init.d/mini_httpd start
diff --git a/update-conf b/update-conf
new file mode 100644
index 0000000..c13d8cb
--- /dev/null
+++ b/update-conf
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+
+PREFIX=
+. $PREFIX/lib/libalpine.sh
+
+# set up temp dir
+init_tmpdir TMPD
+
+LBUCACHE="$TMPD/lbucache"
+
+usage() {
+ echo "$PROGRAM $VERSION
+Usage: $PROGAM [-ahl]
+
+ -a Select all updated files.
+ -h Show this help.
+ -l List updated files.
+"
+}
+
+
+is_modified() {
+ [ -f "$LBUCACHE" ] || lbu status -a | awk '{print $2}' > "$LBUCACHE"
+ test -n "`( echo \"$1\" ; cat \"$LBUCACHE\" ) | sort | uniq -d`"
+}
+
+while getopts "alh" opt ; do
+ case "$opt" in
+ a) aflag="-a" ;;
+ l) lflag="-l" ;;
+ h|*) usage;;
+ esac
+done
+shift `expr $OPTIND - 1`
+
+find "$ROOT/etc" -name '*.apk-new' | while read apknew ; do
+ p="${apknew%.apk-new}"
+ f="${p#${ROOT}/}"
+ unset choice
+
+ if [ "$lflag" ] ; then
+
+ # just list the file
+ if [ "$aflag" ] || is_modified "$f" ; then
+ echo "$p"
+ fi
+
+ elif [ "$aflag" ] || is_modified "$f" ; then
+
+ # ask user what to do with the file
+ while [ -z "$choice" ] ; do
+ echo "New $p available:"
+ echon "Quit, Next, Show diff, Edit new, Zap new, Use new (q/n/s/e/z/u) [s]: "
+ default_read choice "s" </dev/tty
+ case "$choice" in
+ q) exit;;
+ n) continue;;
+ s) diff -u "$p" "$apknew" | ${PAGER:-less}
+ unset choice
+ ;;
+ e) ${EDITOR:-vi} "$apknew" ; unset choice;;
+ z) rm "$apknew";;
+ u) mv "$apknew" "$p";;
+ *) unset choice;;
+ esac
+ done
+ else
+ # auto update
+ echo "Autoupdating unchanged $p"
+ mv "$apknew" "$p"
+ fi
+done
+