Upgrade busybox to 1.7.2
authorFelix Fietkau <nbd@openwrt.org>
Fri, 5 Oct 2007 00:27:49 +0000 (00:27 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Fri, 5 Oct 2007 00:27:49 +0000 (00:27 +0000)
- clean up insmod crap
- add some lineno/programname fixes for awx
- clean up awk getopt stuff
- remove unnecessary patches

SVN-Revision: 9130

51 files changed:
package/busybox/Makefile
package/busybox/config/Config.in
package/busybox/config/archival/Config.in
package/busybox/config/console-tools/Config.in
package/busybox/config/coreutils/Config.in
package/busybox/config/debianutils/Config.in
package/busybox/config/editors/Config.in
package/busybox/config/findutils/Config.in
package/busybox/config/init/Config.in
package/busybox/config/ipsvd/Config.in [new file with mode: 0644]
package/busybox/config/libbb/Config.in
package/busybox/config/loginutils/Config.in
package/busybox/config/miscutils/Config.in
package/busybox/config/modutils/Config.in
package/busybox/config/networking/Config.in
package/busybox/config/networking/udhcp/Config.in
package/busybox/config/procps/Config.in
package/busybox/config/selinux/Config.in [new file with mode: 0644]
package/busybox/config/shell/Config.in
package/busybox/config/sysklogd/Config.in
package/busybox/config/util-linux/Config.in
package/busybox/patches/000-autoconf.patch
package/busybox/patches/110-wget_getopt_fix.patch
package/busybox/patches/130-drop_werror.patch [deleted file]
package/busybox/patches/243-udhcpc_changed_ifindex.patch
package/busybox/patches/250-ash_export-n.patch
package/busybox/patches/260-broadcast_plus.patch [deleted file]
package/busybox/patches/270-ash_performance.patch [deleted file]
package/busybox/patches/280-printf.patch [deleted file]
package/busybox/patches/310-passwd_access.patch
package/busybox/patches/330-httpd_user_agent.patch [deleted file]
package/busybox/patches/350-httpd_redir.patch
package/busybox/patches/360-awk_multi_f.patch [new file with mode: 0644]
package/busybox/patches/400-revert_awk_getopt.patch [deleted file]
package/busybox/patches/401-darwin_includes.patch
package/busybox/patches/410-httpd_cgi_headers.patch
package/busybox/patches/420-httpd_sendcgi_fix.patch [deleted file]
package/busybox/patches/440-httpd_chdir.patch
package/busybox/patches/440-usage_compressed_fix.patch [deleted file]
package/busybox/patches/450-truncated_ping_results.patch [deleted file]
package/busybox/patches/450-usage_compressed_fix.patch [new file with mode: 0644]
package/busybox/patches/460-httpd_cgi_bin.patch [deleted file]
package/busybox/patches/460-truncated_ping_results.patch [new file with mode: 0644]
package/busybox/patches/470-insmod_search.patch [new file with mode: 0644]
package/busybox/patches/500-ipkg.patch [new file with mode: 0644]
package/busybox/patches/501-libbb_hash.patch [new file with mode: 0644]
package/busybox/patches/510-awx.patch [new file with mode: 0644]
package/busybox/patches/911-ipkg.patch [deleted file]
package/busybox/patches/913-libbb_hash.patch [deleted file]
package/busybox/patches/920-awx.patch [deleted file]
package/busybox/patches/999-insmod2.6_search.patch [deleted file]

index 3844e87..8fefb60 100644 (file)
@@ -9,13 +9,13 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=busybox
-PKG_VERSION:=1.4.2
+PKG_VERSION:=1.7.2
 PKG_RELEASE:=3
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
 PKG_SOURCE_URL:=http://www.busybox.net/downloads \
                http://distfiles.gentoo.org/distfiles/
-PKG_MD5SUM:=b4c61fb15642be9dde20e8493788c585
+PKG_MD5SUM:=c91ec9756e2000073a9dd8fa9fc3f89e
 
 include $(INCLUDE_DIR)/package.mk
 
index 4df12cc..d3c1cb6 100644 (file)
@@ -100,8 +100,7 @@ config BUSYBOX_CONFIG_FEATURE_INSTALLER
        help
          Enable 'busybox --install [-s]' support.  This will allow you to use
          busybox at runtime to create hard links or symlinks for all the
-         applets that are compiled into busybox.  This feature requires the
-         /proc filesystem.
+         applets that are compiled into busybox.
 
 config BUSYBOX_CONFIG_LOCALE_SUPPORT
        bool "Enable locale support (system needs locale for this to work)"
@@ -140,6 +139,13 @@ config BUSYBOX_CONFIG_FEATURE_CLEAN_UP
          Don't enable this unless you have a really good reason to clean
          things up manually.
 
+config BUSYBOX_CONFIG_FEATURE_PIDFILE
+       bool "Support writing pidfiles"
+       default y
+       help
+         This option makes some applets (e.g. crond, syslogd, inetd) write
+         a pidfile in /var/run. Some applications rely on them.
+
 config BUSYBOX_CONFIG_FEATURE_SUID
        bool "Support for SUID/SGID handling"
        default y
@@ -155,13 +161,6 @@ config BUSYBOX_CONFIG_FEATURE_SUID
          are login, passwd, su, ping, traceroute, crontab, dnsd, ipcrm, ipcs,
          and vlock.
 
-config BUSYBOX_CONFIG_FEATURE_SYSLOG
-       bool "Support for syslog"
-       default y
-       help
-         This option is auto-selected when you select any applet which may
-         send its output to syslog. You do not need to select it manually.
-
 config BUSYBOX_CONFIG_FEATURE_SUID_CONFIG
        bool "Runtime SUID/SGID configuration via /etc/busybox.conf"
        default n if BUSYBOX_CONFIG_FEATURE_SUID
@@ -202,14 +201,6 @@ config BUSYBOX_CONFIG_FEATURE_SUID_CONFIG_QUIET
          /etc/busybox.conf should be readable by the user needing the SUID, check
          this option to avoid users to be notified about missing permissions.
 
-config BUSYBOX_CONFIG_FEATURE_HAVE_RPC
-       bool "RPC support"
-       default y
-       help
-         Select this if you have rpc support.
-         This automatically turns off all configuration options that rely
-         on RPC.
-
 config BUSYBOX_CONFIG_SELINUX
        bool "Support NSA Security Enhanced Linux"
        default n
@@ -230,6 +221,20 @@ config BUSYBOX_CONFIG_SELINUX
 
          Most people will leave this set to 'N'.
 
+config BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS
+       bool "exec prefers applets"
+       default y
+       help
+         This is an experimental option which directs applets about to
+         call 'exec' to try and find an applicable busybox applet before
+         searching the PATH. This is typically done by exec'ing
+         /proc/self/exe.
+         This may affect shell, find -exec, xargs and similar applets.
+         They will use applets even if /bin/<applet> -> busybox link
+         is missing (or is not a link to busybox). However, this causes
+         problems in chroot jails without mounted /proc and with ps/top
+         (command name can be shown as 'exe' for applets started this way).
+
 config BUSYBOX_CONFIG_BUSYBOX_EXEC_PATH
        string "Path to BusyBox executable"
        default "/proc/self/exe"
@@ -240,6 +245,22 @@ config BUSYBOX_CONFIG_BUSYBOX_EXEC_PATH
          executable.  If you haven't got /proc, set this to wherever you
          want to run BusyBox from.
 
+# These are auto-selected by other options
+
+config BUSYBOX_CONFIG_FEATURE_SYSLOG
+       bool "Support for logging to syslog"
+       default y
+       help
+         This option is auto-selected when you select any applet which may
+         send its output to syslog. You do not need to select it manually.
+
+config BUSYBOX_CONFIG_FEATURE_HAVE_RPC
+       bool "RPC support"
+       default y
+       help
+         This is automatically selected if any of enabled applets need it.
+         You do not need to select it manually.
+
 endmenu
 
 menu 'Build Options'
@@ -298,7 +319,7 @@ config BUSYBOX_CONFIG_FEATURE_SHARED_BUSYBOX
          You need to have a working dynamic linker to use this variant.
 
 config BUSYBOX_CONFIG_LFS
-       bool "Support large files over 2 GB"
+       bool
        default y
        select BUSYBOX_CONFIG_FDISK_SUPPORT_LARGE_DISKS
        help
@@ -343,21 +364,29 @@ config BUSYBOX_CONFIG_DEBUG
 
          Most people should answer N.
 
-config BUSYBOX_CONFIG_DEBUG_PESSIMIZE
-       bool "Disable compiler optimizations."
+config BUSYBOX_CONFIG_WERROR
+       bool "Abort compilation on any warning"
        default n
-       depends on BUSYBOX_CONFIG_DEBUG
        help
-         The compiler's optimization of source code can eliminate and reorder
-         code, resulting in an executable that's hard to understand when
-         stepping through it with a debugger.  This switches it off, resulting
-         in a much bigger executable that more closely matches the source
-         code.
+         Selecting this will add -Werror to gcc command line.
+
+         Most people should answer N.
+
+# Seems to be unused
+#config DEBUG_PESSIMIZE
+#      bool "Disable compiler optimizations."
+#      default n
+#      depends on DEBUG
+#      help
+#        The compiler's optimization of source code can eliminate and reorder
+#        code, resulting in an executable that's hard to understand when
+#        stepping through it with a debugger.  This switches it off, resulting
+#        in a much bigger executable that more closely matches the source
+#        code.
 
 choice
        prompt "Additional debugging library"
        default BUSYBOX_CONFIG_NO_DEBUG_LIB
-       depends on BUSYBOX_CONFIG_DEBUG
        help
          Using an additional debugging library will make BusyBox become
          considerable larger and will cause it to run more slowly.  You
@@ -417,31 +446,30 @@ config BUSYBOX_CONFIG_INSTALL_NO_USR
          that you really want this behaviour.
 
 choice
-       prompt "Applets links"
-       default BUSYBOX_CONFIG_INSTALL_APPLET_SYMLINKS
-       help
-         Choose how you install applets links.
+       prompt "Applets links"
+       default BUSYBOX_CONFIG_INSTALL_APPLET_SYMLINKS
+       help
+         Choose how you install applets links.
 
 config BUSYBOX_CONFIG_INSTALL_APPLET_SYMLINKS
-       bool "as soft-links"
-       help
-         Install applets as soft-links to the busybox binary. This needs some
-         free inodes on the filesystem, but might help with filesystem
-         generators that can't cope with hard-links.
+       bool "as soft-links"
+       help
+         Install applets as soft-links to the busybox binary. This needs some
+         free inodes on the filesystem, but might help with filesystem
+         generators that can't cope with hard-links.
 
 config BUSYBOX_CONFIG_INSTALL_APPLET_HARDLINKS
-       bool "as hard-links"
-       help
-         Install applets as hard-links to the busybox binary. This might count
-         on a filesystem with few inodes.
+       bool "as hard-links"
+       help
+         Install applets as hard-links to the busybox binary. This might count
+         on a filesystem with few inodes.
 
 config BUSYBOX_CONFIG_INSTALL_APPLET_DONT
-       bool
-       prompt "not installed"
-       depends on BUSYBOX_CONFIG_FEATURE_INSTALLER || BUSYBOX_CONFIG_FEATURE_SH_STANDALONE_SHELL
-       help
-         Do not install applet links. Useful when using the -install feature
-         or a standalone shell for rescue pruposes.
+       bool "not installed"
+       depends on BUSYBOX_CONFIG_FEATURE_INSTALLER || BUSYBOX_CONFIG_FEATURE_SH_STANDALONE || BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS
+       help
+         Do not install applet links. Useful when using the -install feature
+         or a standalone shell for rescue purposes.
 
 endchoice
 
@@ -476,3 +504,5 @@ source package/busybox/config/procps/Config.in
 source package/busybox/config/shell/Config.in
 source package/busybox/config/sysklogd/Config.in
 source package/busybox/config/runit/Config.in
+source package/busybox/config/selinux/Config.in
+source package/busybox/config/ipsvd/Config.in
index 989d8d5..9895dba 100644 (file)
@@ -142,6 +142,13 @@ config BUSYBOX_CONFIG_RPM
        help
          Mini RPM applet - queries and extracts RPM packages.
 
+config BUSYBOX_CONFIG_FEATURE_RPM_BZ2
+       bool "Enable handling of rpms with bzip2-compressed data inside"
+       default n
+       depends on BUSYBOX_CONFIG_RPM
+       help
+         Enable handling of rpms with bzip2-compressed data inside.
+
 config BUSYBOX_CONFIG_TAR
        bool "tar"
        default y
@@ -207,6 +214,15 @@ config BUSYBOX_CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY
          the old GNU format; help to kill this old format by
          repacking your ancient archives with the new format.
 
+config BUSYBOX_CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY
+       bool "Enable untarring of tarballs with checksums produced by buggy Sun tar"
+       default n
+       depends on BUSYBOX_CONFIG_TAR
+       help
+         This option is required to unpack archives created by some old
+         version of Sun's tar (it was calculating checksum using signed arithmetic).
+         It is said to be fixed in newer Sun tar, but "old" tarballs still exist.
+
 config BUSYBOX_CONFIG_FEATURE_TAR_GNU_EXTENSIONS
        bool "Enable support for some GNU tar extensions"
        default y
index 661e894..7b044ea 100644 (file)
@@ -85,7 +85,7 @@ config BUSYBOX_CONFIG_SETCONSOLE
 config BUSYBOX_CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS
        bool "Enable long options"
        default n
-       depends on BUSYBOX_CONFIG_SET_CONSOLE && BUSYBOX_CONFIG_GETOPT_LONG
+       depends on BUSYBOX_CONFIG_SETCONSOLE && BUSYBOX_CONFIG_GETOPT_LONG
        help
          Support long options for the setconsole applet.
 
index 91f93e1..5a0220c 100644 (file)
@@ -65,13 +65,6 @@ config BUSYBOX_CONFIG_CKSUM
        help
          cksum is used to calculate the CRC32 checksum of a file.
 
-config BUSYBOX_CONFIG_CMP
-       bool "cmp"
-       default n
-       help
-         cmp is used to compare two files and returns the result
-         to standard output.
-
 config BUSYBOX_CONFIG_COMM
        bool "comm"
        default n
@@ -142,38 +135,6 @@ config BUSYBOX_CONFIG_DF
          df reports the amount of disk space used and available
          on filesystems.
 
-config BUSYBOX_CONFIG_DIFF
-       bool "diff"
-       default n
-       help
-         diff compares two files or directories and outputs the
-         differences between them in a form that can be given to
-         the patch command.
-
-config BUSYBOX_CONFIG_FEATURE_DIFF_BINARY
-       bool "Enable checks for binary files"
-       default n
-       depends on BUSYBOX_CONFIG_DIFF
-       help
-         This option enables support for checking for binary files
-         before a comparison is carried out.
-
-config BUSYBOX_CONFIG_FEATURE_DIFF_DIR
-       bool "Enable directory support"
-       default n
-       depends on BUSYBOX_CONFIG_DIFF
-       help
-         This option enables support for directory and subdirectory
-         comparison.
-
-config BUSYBOX_CONFIG_FEATURE_DIFF_MINIMAL
-       bool "Enable -d option to find smaller sets of changes"
-       default n
-       depends on BUSYBOX_CONFIG_DIFF
-       help
-         Enabling this option allows the use of -d to make diff
-         try hard to find the smallest possible set of changes.
-
 config BUSYBOX_CONFIG_DIRNAME
        bool "dirname"
        default y
@@ -239,6 +200,19 @@ config BUSYBOX_CONFIG_FEATURE_ENV_LONG_OPTIONS
        help
          Support long options for the env applet.
 
+config BUSYBOX_CONFIG_EXPAND
+       bool "expand"
+       default n
+       help
+         By default, convert all tabs to spaces.
+
+config BUSYBOX_CONFIG_FEATURE_EXPAND_LONG_OPTIONS
+       bool "Enable long options"
+       default n
+       depends on BUSYBOX_CONFIG_EXPAND && BUSYBOX_CONFIG_GETOPT_LONG
+       help
+         Support long options for the expand applet.
+
 config BUSYBOX_CONFIG_EXPR
        bool "expr"
        default y
@@ -474,6 +448,20 @@ config BUSYBOX_CONFIG_PWD
        help
          pwd is used to print the current directory.
 
+config BUSYBOX_CONFIG_READLINK
+       bool "readlink"
+       default n
+       help
+         This program reads a symbolic link and returns the name
+         of the file it points to
+
+config BUSYBOX_CONFIG_FEATURE_READLINK_FOLLOW
+       bool "Enable canonicalization by following all symlinks (-f)"
+       default n
+       depends on BUSYBOX_CONFIG_READLINK
+       help
+         Enable the readlink option (-f).
+
 config BUSYBOX_CONFIG_REALPATH
        bool "realpath"
        default n
@@ -536,6 +524,21 @@ config BUSYBOX_CONFIG_FEATURE_SORT_BIG
          The SuSv3 sort standard is available at:
          http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html
 
+config BUSYBOX_CONFIG_SPLIT
+       bool "split"
+       default n
+       help
+         split a file into pieces.
+
+config BUSYBOX_CONFIG_FEATURE_SPLIT_FANCY
+       bool "fancy extensions"
+       default n
+       depends on BUSYBOX_CONFIG_SPLIT
+       help
+         Add support for features not required by SUSv3.
+         Supports additional suffixes 'b' for 512 bytes,
+         'g' for 1GiB for the -b option.
+
 config BUSYBOX_CONFIG_STAT
        bool "stat"
        default n
@@ -665,6 +668,19 @@ config BUSYBOX_CONFIG_UNAME
        help
          uname is used to print system information.
 
+config BUSYBOX_CONFIG_UNEXPAND
+       bool "unexpand"
+       default n
+       help
+         By default, convert only leading sequences of blanks to tabs.
+
+config BUSYBOX_CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS
+       bool "Enable long options"
+       default n
+       depends on BUSYBOX_CONFIG_UNEXPAND && BUSYBOX_CONFIG_GETOPT_LONG
+       help
+         Support long options for the unexpand applet.
+
 config BUSYBOX_CONFIG_UNIQ
        bool "uniq"
        default y
@@ -689,14 +705,6 @@ config BUSYBOX_CONFIG_UUENCODE
        help
          uuencode is used to uuencode a file.
 
-config BUSYBOX_CONFIG_WATCH
-       bool "watch"
-       default n
-       select BUSYBOX_CONFIG_DATE
-       help
-         watch is used to execute a program periodically, showing
-         output to the screen.
-
 config BUSYBOX_CONFIG_WC
        bool "wc"
        default y
index f047a90..bc37c15 100644 (file)
@@ -17,20 +17,6 @@ config BUSYBOX_CONFIG_PIPE_PROGRESS
        help
          Display a dot to indicate pipe activity.
 
-config BUSYBOX_CONFIG_READLINK
-       bool "readlink"
-       default n
-       help
-         This program reads a symbolic link and returns the name
-         of the file it points to
-
-config BUSYBOX_CONFIG_FEATURE_READLINK_FOLLOW
-       bool "Enable canonicalization by following all symlinks (-f)"
-       default n
-       depends on BUSYBOX_CONFIG_READLINK
-       help
-         Enable the readlink option (-f).
-
 config BUSYBOX_CONFIG_RUN_PARTS
        bool "run-parts"
        default n
@@ -53,6 +39,15 @@ config BUSYBOX_CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS
        help
          Support long options for the run-parts applet.
 
+config BUSYBOX_CONFIG_FEATURE_RUN_PARTS_FANCY
+       bool "Support additional arguments"
+       default n
+       depends on BUSYBOX_CONFIG_RUN_PARTS
+       help
+         Support additional options:
+         -l --list print the names of the all matching files (not
+                   limited to executables), but don't actually run them.
+
 config BUSYBOX_CONFIG_START_STOP_DAEMON
        bool "start-stop-daemon"
        default y
index 8973c36..6d1f6f2 100644 (file)
@@ -27,6 +27,45 @@ config BUSYBOX_CONFIG_FEATURE_AWK_MATH
          Enable math functions of the Awk programming language.
          NOTE: This will require libm to be present for linking.
 
+config BUSYBOX_CONFIG_CMP
+       bool "cmp"
+       default n
+       help
+         cmp is used to compare two files and returns the result
+         to standard output.
+
+config BUSYBOX_CONFIG_DIFF
+       bool "diff"
+       default y
+       help
+         diff compares two files or directories and outputs the
+         differences between them in a form that can be given to
+         the patch command.
+
+config BUSYBOX_CONFIG_FEATURE_DIFF_BINARY
+       bool "Enable checks for binary files"
+       default n
+       depends on BUSYBOX_CONFIG_DIFF
+       help
+         This option enables support for checking for binary files
+         before a comparison is carried out.
+
+config BUSYBOX_CONFIG_FEATURE_DIFF_DIR
+       bool "Enable directory support"
+       default n
+       depends on BUSYBOX_CONFIG_DIFF
+       help
+         This option enables support for directory and subdirectory
+         comparison.
+
+config BUSYBOX_CONFIG_FEATURE_DIFF_MINIMAL
+       bool "Enable -d option to find smaller sets of changes"
+       default n
+       depends on BUSYBOX_CONFIG_DIFF
+       help
+         Enabling this option allows the use of -d to make diff
+         try hard to find the smallest possible set of changes.
+
 config BUSYBOX_CONFIG_ED
        bool "ed"
        default n
@@ -57,6 +96,16 @@ config BUSYBOX_CONFIG_VI
          learning curve.  If you are not already comfortable with 'vi'
          you may wish to use something else.
 
+config BUSYBOX_CONFIG_FEATURE_VI_MAX_LEN
+       int "Maximum line length in vi"
+       range 256 16384
+       default 1024
+       depends on BUSYBOX_CONFIG_VI
+       help
+         vi uses on-stack buffers for intermediate line buffers.
+         You may want to decrease this parameter if your target machine
+         benefits from smaller stack usage.
+
 config BUSYBOX_CONFIG_FEATURE_VI_COLON
        bool "Enable \":\" colon commands (no \"ex\" mode)"
        default y
index dc0bbce..3f89c33 100644 (file)
@@ -30,7 +30,7 @@ config BUSYBOX_CONFIG_FEATURE_FIND_MTIME
          files, in days.
 
 config BUSYBOX_CONFIG_FEATURE_FIND_MMIN
-       bool "Enable modified time matching (-min) option"
+       bool "Enable modified time matching (-mmin) option"
        default n
        depends on BUSYBOX_CONFIG_FIND
        help
@@ -57,8 +57,14 @@ config BUSYBOX_CONFIG_FEATURE_FIND_XDEV
        default y
        depends on BUSYBOX_CONFIG_FIND
        help
-         This option will allow find to restrict searches to a single
-         filesystem.
+         This option allows find to restrict searches to a single filesystem.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_MAXDEPTH
+       bool "Enable -maxdepth N option"
+       default y
+       depends on BUSYBOX_CONFIG_FIND
+       help
+         This option enables -maxdepth N option.
 
 config BUSYBOX_CONFIG_FEATURE_FIND_NEWER
        bool "Enable -newer option for comparing file mtimes"
@@ -83,6 +89,88 @@ config BUSYBOX_CONFIG_FEATURE_FIND_EXEC
          Support the 'find -exec' option for executing commands based upon
          the files matched.
 
+config BUSYBOX_CONFIG_FEATURE_FIND_USER
+       bool "Enable username/uid matching (-user) option"
+       default y
+       depends on BUSYBOX_CONFIG_FIND
+       help
+         Support the 'find -user' option for searching by username or uid.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_GROUP
+       bool "Enable group/gid matching (-group) option"
+       default y
+       depends on BUSYBOX_CONFIG_FIND
+       help
+         Support the 'find -group' option for searching by group name or gid.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_NOT
+       bool "Enable the 'not' (!) operator"
+       default y
+       depends on BUSYBOX_CONFIG_FIND
+       help
+         Support the '!' operator to invert the test results.
+         If 'Enable full-blown desktop' is enabled, then will also support
+         the non-POSIX notation '-not'.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_DEPTH
+       bool "Enable the -depth option"
+       default y
+       depends on BUSYBOX_CONFIG_FIND
+       help
+         Process each directory's contents before the directory itself.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_PAREN
+       bool "Enable parens in options"
+       default y
+       depends on BUSYBOX_CONFIG_FIND
+       help
+         Enable usage of parens '(' to specify logical order of arguments.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_SIZE
+       bool "Enable (-size) option allowing matching for file size"
+       default y
+       depends on BUSYBOX_CONFIG_FIND
+       help
+         Support the 'find -size' option for searching by file size.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_PRUNE
+       bool "Enable (-prune) option allowing to exclude subdirectories"
+       default y
+       depends on BUSYBOX_CONFIG_FIND
+       help
+         If the file is a directory, dont descend into it. Useful for
+         exclusion .svn and CVS directories.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_DELETE
+       bool "Enable -delete option allowing to delete files"
+       default n
+       depends on BUSYBOX_CONFIG_FIND && BUSYBOX_CONFIG_FEATURE_FIND_DEPTH
+       help
+         Support the 'find -delete' option for deleting files and direcotries.
+         WARNING: This option can do much harm if used wrong. Busybox will not
+         try to protect the user from doing stupid things. Use with care.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_PATH
+       bool "Enable -path option allowing to match pathname patterns"
+       default y
+       depends on BUSYBOX_CONFIG_FIND
+       help
+         The -path option matches whole pathname instead of just filename.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_REGEX
+       bool "Enable -regex: match pathname to regex"
+       default y
+       depends on BUSYBOX_CONFIG_FIND
+       help
+         The -regex option matches whole pathname against regular expression.
+
+config BUSYBOX_CONFIG_FEATURE_FIND_CONTEXT
+       bool "Enable (-context) option for matching security context"
+       default n
+       depends on BUSYBOX_CONFIG_FIND && BUSYBOX_CONFIG_SELINUX
+       help
+         Support the 'find -context' option for matching security context.
+
 config BUSYBOX_CONFIG_GREP
        bool "grep"
        default y
index b8ad0d6..104af26 100644 (file)
@@ -38,6 +38,11 @@ config BUSYBOX_CONFIG_FEATURE_INIT_SCTTY
          behavour, but is often what you want in an embedded system where
          the console is only accessed during development or for maintenance.
 
+config BUSYBOX_CONFIG_FEATURE_INIT_SYSLOG
+       bool "Enable init to write to syslog"
+       default y
+       depends on BUSYBOX_CONFIG_INIT
+
 config BUSYBOX_CONFIG_FEATURE_EXTRA_QUIET
        bool "Be _extra_ quiet on boot"
        default n
diff --git a/package/busybox/config/ipsvd/Config.in b/package/busybox/config/ipsvd/Config.in
new file mode 100644 (file)
index 0000000..d163ade
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "ipsvd utilities"
+
+config BUSYBOX_CONFIG_TCPSVD
+       bool "tcpsvd"
+       default n
+       help
+         tcpsvd listens on a tcp port and runs a program for each new connection
+
+config BUSYBOX_CONFIG_UDPSVD
+       bool "udpsvd"
+       default n
+       help
+         udpsvd listens on a udp port and runs a program for each new connection
+
+endmenu
index 4919f9b..4e23b8a 100644 (file)
@@ -26,4 +26,105 @@ config BUSYBOX_CONFIG_MD5_SIZE_VS_SPEED
          2                   3.0                5088
          3 (smallest)        5.1                4912
 
+config BUSYBOX_CONFIG_FEATURE_FAST_TOP
+       bool "Faster /proc scanning code (+100 bytes)"
+       default y
+       help
+         This option makes top (and ps) ~20% faster (or 20% less CPU hungry),
+         but code size is slightly bigger.
+
+config BUSYBOX_CONFIG_FEATURE_ETC_NETWORKS
+       bool "Support for /etc/networks"
+       default n
+       help
+         Enable support for network names in /etc/networks. This is
+         a rarely used feature which allows you to use names
+         instead of IP/mask pairs in route command.
+
+config BUSYBOX_CONFIG_FEATURE_EDITING
+       bool "Command line editing"
+       default y
+       help
+         Enable line editing (mainly for shell command line).
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_MAX_LEN
+       int "Maximum length of input"
+       range 128 8192
+       default 512
+       depends on BUSYBOX_CONFIG_FEATURE_EDITING
+       help
+         Line editing code uses on-stack buffers for storage.
+         You may want to decrease this parameter if your target machine
+         benefits from smaller stack usage.
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_FANCY_KEYS
+       bool "Additional editing keys"
+       default y
+       depends on BUSYBOX_CONFIG_FEATURE_EDITING
+       help
+         Enable additonal editing keys (Ctrl-E, Ctrl-U etc).
+         Arrow keys, Home/End/Delete and Ctrl-W work even without this option.
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_VI
+       bool "vi-style line editing commands"
+       default n
+       depends on BUSYBOX_CONFIG_FEATURE_EDITING
+       help
+         Enable vi-style line editing.  In shells, this mode can be
+         turned on and off with "set -o vi" and "set +o vi".
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_HISTORY
+       int "History size"
+       range 0 99999
+       default 256
+       depends on BUSYBOX_CONFIG_FEATURE_EDITING
+       help
+         Specify command history size.
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY
+       bool "History saving"
+       default n
+       depends on BUSYBOX_CONFIG_ASH && BUSYBOX_CONFIG_FEATURE_EDITING
+       help
+         Enable history saving in ash shell.
+
+config BUSYBOX_CONFIG_FEATURE_TAB_COMPLETION
+       bool "Tab completion"
+       default y
+       depends on BUSYBOX_CONFIG_FEATURE_EDITING
+       help
+         Enable tab completion.
+
+config BUSYBOX_CONFIG_FEATURE_USERNAME_COMPLETION
+       bool "Username completion"
+       default n
+       depends on BUSYBOX_CONFIG_FEATURE_TAB_COMPLETION
+       help
+         Enable username completion.
+
+config BUSYBOX_CONFIG_FEATURE_EDITING_FANCY_PROMPT
+       bool "Fancy shell prompts"
+       default y
+       depends on BUSYBOX_CONFIG_FEATURE_EDITING
+       help
+         Setting this option allows for prompts to use things like \w and
+         \$ and escape codes.
+
+config BUSYBOX_CONFIG_MONOTONIC_SYSCALL
+       bool "Use clock_gettime(CLOCK_MONOTONIC) syscall"
+       default n
+       help
+         Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring
+         time intervals (time, ping, traceroute etc need this).
+         Probably requires Linux 2.6+. If not selected, gettimeofday
+         will be used instead (which gives wrong results if date/time
+         is reset).
+
+config BUSYBOX_CONFIG_IOCTL_HEX2STR_ERROR
+       bool "Use ioctl names rather than hex values in error messages"
+       default y
+       help
+         Use ioctl names rather than hex values in error messages
+         (e.g. VT_DISALLOCATE rather than 0x5608). If disabled this
+         saves about 1400 bytes.
 endmenu
index 6171d02..15019c1 100644 (file)
@@ -59,12 +59,29 @@ config BUSYBOX_CONFIG_ADDGROUP
        help
          Utility for creating a new group account.
 
+config BUSYBOX_CONFIG_FEATURE_ADDUSER_TO_GROUP
+       bool "Support for adding users to groups"
+       default n
+       depends on BUSYBOX_CONFIG_ADDGROUP
+       help
+         If  called  with two non-option arguments,
+         addgroup will add an existing user to an
+         existing group.
+
 config BUSYBOX_CONFIG_DELGROUP
        bool "delgroup"
        default n
        help
          Utility for deleting a group account.
 
+config BUSYBOX_CONFIG_FEATURE_DEL_USER_FROM_GROUP
+       bool "Support for removing users from groups."
+       default n
+       depends on BUSYBOX_CONFIG_DELGROUP
+       help
+         If called with two non-option arguments, deluser
+         or delgroup will remove an user from a specified group.
+
 config BUSYBOX_CONFIG_ADDUSER
        bool "adduser"
        default n
@@ -111,6 +128,13 @@ config BUSYBOX_CONFIG_LOGIN
          Note that Busybox binary must be setuid root for this applet to
          work properly.
 
+config BUSYBOX_CONFIG_PAM
+       bool "Support for PAM (Pluggable Authentication Modules)"
+       default n
+       depends on BUSYBOX_CONFIG_LOGIN
+       help
+         Use PAM in login(1) instead of direct access to password database.
+
 config BUSYBOX_CONFIG_LOGIN_SCRIPTS
        bool "Support for login scripts"
        depends on BUSYBOX_CONFIG_LOGIN
@@ -119,12 +143,20 @@ config BUSYBOX_CONFIG_LOGIN_SCRIPTS
          Enable this if you want login to execute $LOGIN_PRE_SUID_SCRIPT
          just prior to switching from root to logged-in user.
 
+config BUSYBOX_CONFIG_FEATURE_NOLOGIN
+       bool "Support for /etc/nologin"
+       default n
+       depends on BUSYBOX_CONFIG_LOGIN
+       help
+         The file /etc/nologin is used by (some versions of) login(1).
+         If it exists, non-root logins are prohibited.
+
 config BUSYBOX_CONFIG_FEATURE_SECURETTY
        bool "Support for /etc/securetty"
        default n
        depends on BUSYBOX_CONFIG_LOGIN
        help
-         The file  /etc/securetty  is used by (some versions of) login(1).
+         The file /etc/securetty is used by (some versions of) login(1).
          The file contains the device names of tty lines (one per line,
          without leading /dev/) on which root is allowed to login.
 
@@ -149,6 +181,20 @@ config BUSYBOX_CONFIG_FEATURE_PASSWD_WEAK_CHECK
        help
          With this option passwd will refuse new passwords which are "weak".
 
+config BUSYBOX_CONFIG_CRYPTPW
+       bool "cryptpw"
+       default n
+       help
+         Applet for crypting a string.
+
+config BUSYBOX_CONFIG_CHPASSWD
+       bool "chpasswd"
+       default n
+       help
+         chpasswd  reads  a  file  of user name and password pairs from
+         standard input and uses this information to update a group of
+         existing users.
+
 config BUSYBOX_CONFIG_SU
        bool "su"
        default n
index 7784a82..44f11a9 100644 (file)
@@ -19,6 +19,13 @@ config BUSYBOX_CONFIG_BBCONFIG
          The bbconfig applet will print the config file with which
          busybox was built.
 
+config BUSYBOX_CONFIG_CHRT
+       bool "chrt"
+       default n
+       help
+         manipulate real-time attributes of a process.
+         This requires sched_{g,s}etparam support in your libc.
+
 config BUSYBOX_CONFIG_CROND
        bool "crond"
        default y
@@ -256,19 +263,19 @@ config BUSYBOX_CONFIG_MAKEDEVS
          'leaf' is traditionally what busybox follows, it allows multiple
          devices of a particluar type to be created per command.
          e.g. /dev/hda[0-9]
-          Device properties are passed as command line arguments.
+         Device properties are passed as command line arguments.
          .
          'table' reads device properties from a file or stdin, allowing
          a batch of unrelated devices to be made with one command.
-          User/group names are allowed as an alternative to uid/gid.
+         User/group names are allowed as an alternative to uid/gid.
 
 choice
        prompt "Choose makedevs behaviour"
-       depends BUSYBOX_CONFIG_MAKEDEVS
+       depends on BUSYBOX_CONFIG_MAKEDEVS
        default BUSYBOX_CONFIG_FEATURE_MAKEDEVS_TABLE
 
 config BUSYBOX_CONFIG_FEATURE_MAKEDEVS_LEAF
-        bool "leaf"
+       bool "leaf"
 
 config BUSYBOX_CONFIG_FEATURE_MAKEDEVS_TABLE
        bool "table"
@@ -289,12 +296,6 @@ config BUSYBOX_CONFIG_MT
          to advance or rewind a tape past a specified number of archive
          files on the tape.
 
-config BUSYBOX_CONFIG_NMETER
-       bool "nmeter"
-       default n
-       help
-         nmeter prints various system parameters continuously.
-
 config BUSYBOX_CONFIG_RAIDAUTORUN
        bool "raidautorun"
        default n
@@ -303,11 +304,11 @@ config BUSYBOX_CONFIG_RAIDAUTORUN
          search and start RAID arrays.
 
 config BUSYBOX_CONFIG_READAHEAD
-        bool "readahead"
+       bool "readahead"
        default n
-       depends on LFS
+       depends on BUSYBOX_CONFIG_LFS
        help
-         Preload the files listed on the command line into RAM cache so that
+         Preload the files listed on the command line into RAM cache so that
          subsequent reads on these files will not block on disk I/O.
 
          This applet just calls the readahead(2) system call on each file.
@@ -320,19 +321,19 @@ config BUSYBOX_CONFIG_READAHEAD
          run this applet as a background job.
 
 config BUSYBOX_CONFIG_RUNLEVEL
-        bool "runlevel"
+       bool "runlevel"
        default n
        help
-         find the current and previous system runlevel.
+         find the current and previous system runlevel.
 
          This applet uses utmp but does not rely on busybox supporing
          utmp on purpose. It is used by e.g. emdebian via /etc/init.d/rc.
 
 config BUSYBOX_CONFIG_RX
-        bool "rx"
+       bool "rx"
        default n
        help
-         Receive files using the Xmodem protocol.
+         Receive files using the Xmodem protocol.
 
 config BUSYBOX_CONFIG_STRINGS
        bool "strings"
@@ -371,6 +372,14 @@ config BUSYBOX_CONFIG_TIME
          When the command finishes, time writes a message to standard output
          giving timing statistics about this program run.
 
+config BUSYBOX_CONFIG_TTYSIZE
+       bool "ttysize"
+       default n
+       help
+         A replacement for "stty size". Unlike stty, can report only width,
+         only height, or both, in any order. It also does not complain on error,
+         but returns default 80x24. Usage in shell scripts: width=`ttysize w`.
+
 config BUSYBOX_CONFIG_WATCHDOG
        bool "watchdog"
        default y
index 9183145..7ffca93 100644 (file)
@@ -134,7 +134,7 @@ config BUSYBOX_CONFIG_FEATURE_CHECK_TAINTED_MODULE
 config BUSYBOX_CONFIG_FEATURE_2_4_MODULES
        # Simulate indentation
        bool "Support version 2.2.x to 2.4.x Linux kernels"
-       default y
+       default n
        depends on BUSYBOX_CONFIG_INSMOD || BUSYBOX_CONFIG_RMMOD || BUSYBOX_CONFIG_MODPROBE
        help
          Support module loading for 2.2.x and 2.4.x Linux kernels.
index 6c88baf..1da1dc5 100644 (file)
@@ -12,17 +12,25 @@ config BUSYBOX_CONFIG_FEATURE_IPV6
          Enable IPv6 support in busybox.
          This adds IPv6 support in the networking applets.
 
+config BUSYBOX_CONFIG_VERBOSE_RESOLUTION_ERRORS
+       bool "Verbose resolution errors"
+       default y
+       help
+         Enable if you are not satisfied with simplistic
+         "can't resolve 'hostname.com'" and want to know more.
+         This may increase size of your executable a bit.
+
 config BUSYBOX_CONFIG_ARP
        bool "arp"
        default n
        help
-         Manipulate the system ARP cache
+         Manipulate the system ARP cache.
 
 config BUSYBOX_CONFIG_ARPING
        bool "arping"
        default y
        help
-         Ping hosts by ARP packets
+         Ping hosts by ARP packets.
 
 config BUSYBOX_CONFIG_DNSD
        bool "dnsd"
@@ -67,7 +75,7 @@ config BUSYBOX_CONFIG_HOSTNAME
        bool "hostname"
        default n
        help
-         Show or set the system's host name
+         Show or set the system's host name.
 
 config BUSYBOX_CONFIG_HTTPD
        bool "httpd"
@@ -75,6 +83,14 @@ config BUSYBOX_CONFIG_HTTPD
        help
          Serve web pages via an HTTP server.
 
+config BUSYBOX_CONFIG_FEATURE_HTTPD_USE_SENDFILE
+       bool "Use sendfile system call"
+       default y
+       depends on BUSYBOX_CONFIG_HTTPD
+       help
+         When enabled, httpd will use the kernel sendfile() function
+         instead of read/write loop.
+
 config BUSYBOX_CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
        bool "Support reloading the global config file using hup signal"
        default y
@@ -132,7 +148,7 @@ config BUSYBOX_CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
        help
          This option enables support for running scripts through an
          interpreter. Turn this on if you want PHP scripts to work
-         properly. You need to supply an addition line in your httpd
+         properly. You need to supply an additional line in your httpd
          config file:
          *.php:/path/to/your/php
 
@@ -154,6 +170,19 @@ config BUSYBOX_CONFIG_FEATURE_HTTPD_ENCODE_URL_STR
          For example, httpd -e "<Hello World>" as
          "&#60Hello&#32World&#62".
 
+config BUSYBOX_CONFIG_FEATURE_HTTPD_ERROR_PAGES
+       bool "Enable support for custom error pages"
+       default y
+       depends on BUSYBOX_CONFIG_HTTPD
+       help
+         This option allows you to define custom error pages in
+         the configuration file instead of the default HTTP status
+         error pages. For instance, if you add the line:
+               E404:/path/e404.html
+         in the config file, the server will respond the specified
+         '/path/e404.html' file instead of the terse '404 NOT FOUND'
+         message.
+
 config BUSYBOX_CONFIG_IFCONFIG
        bool "ifconfig"
        default y
@@ -204,7 +233,6 @@ config BUSYBOX_CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
 config BUSYBOX_CONFIG_IFUPDOWN
        bool "ifupdown"
        default n
-       select BUSYBOX_CONFIG_RUN_PARTS
        help
          Activate or deactivate the specified interfaces.  This applet makes
          use of either "ifconfig" and "route" or the "ip" command to actually
@@ -215,8 +243,18 @@ config BUSYBOX_CONFIG_IFUPDOWN
          against my better judgement (since this will surely result in plenty
          of support questions on the mailing list), I do not force you to
          enable these additional options.  It is up to you to supply either
-         "ifconfig" and "route" or the "ip" command, either via busybox or via
-         standalone utilities.
+         "ifconfig", "route" and "run-parts" or the "ip" command, either
+         via busybox or via standalone utilities.
+
+config BUSYBOX_CONFIG_IFUPDOWN_IFSTATE_PATH
+       string "Absolute path to ifstate file"
+       default "/var/run/ifstate"
+       help
+         ifupdown keeps state information in a file called ifstate.
+         Typically it is located in /var/run/ifstate, however
+         some distributions tend to put it in other places
+         (debian, for example, uses /etc/network/run/ifstate).
+         This config option defines location of ifstate.
 
 config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IP
        bool "Use ip applet"
@@ -259,7 +297,7 @@ config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IPV4
        default n
        depends on BUSYBOX_CONFIG_IFUPDOWN
        help
-         If you want busybox to talk IPv4, leave this on.
+         If you want ifup/ifdown to talk IPv4, leave this on.
 
 config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IPV6
        bool "Enable support for IPv6"
@@ -268,13 +306,14 @@ config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IPV6
        help
          If you need support for IPv6, turn this option on.
 
-config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_IPX
-       bool "Enable support for IPX"
-       default n
-       depends on BUSYBOX_CONFIG_IFUPDOWN
-       help
-         If this option is selected you can use busybox to work with IPX
-         networks.
+### UNUSED
+### config FEATURE_IFUPDOWN_IPX
+###    bool "Enable support for IPX"
+###    default n
+###    depends on IFUPDOWN
+###    help
+###      If this option is selected you can use busybox to work with IPX
+###      networks.
 
 config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_MAPPING
        bool "Enable mapping support"
@@ -284,6 +323,16 @@ config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_MAPPING
          This enables support for the "mapping" stanza, unless you have
          a weird network setup you don't need it.
 
+config BUSYBOX_CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP
+       bool "Enable support for external dhcp clients"
+       default n
+       depends on BUSYBOX_CONFIG_IFUPDOWN
+       help
+         This enables support for the external dhcp clients. Clients are
+         tried in the following order: dhcpcd, dhclient, pump and udhcpc.
+         Otherwise, if udhcpc applet is enabled, it is used.
+         Otherwise, ifup/ifdown will have no support for DHCP.
+
 config BUSYBOX_CONFIG_INETD
        bool "inetd"
        default n
@@ -330,7 +379,7 @@ config BUSYBOX_CONFIG_FEATURE_INETD_RPC
        bool "Support RPC services"
        default n
        depends on BUSYBOX_CONFIG_INETD
-       depends on BUSYBOX_CONFIG_FEATURE_HAVE_RPC
+       select BUSYBOX_CONFIG_FEATURE_HAVE_RPC
        help
          Support Sun-RPC based services
 
@@ -387,6 +436,7 @@ config BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS
          ip link   -> iplink
          ip route  -> iproute
          ip tunnel -> iptunnel
+         ip rule   -> iprule
 
          Say N unless you desparately need the short form of the ip
          object commands.
@@ -466,7 +516,7 @@ config BUSYBOX_CONFIG_NETMSG
          simple program for sending udp broadcast messages
 
 config BUSYBOX_CONFIG_NC_SERVER
-       bool "Netcat server options (-lp)"
+       bool "Netcat server options (-l)"
        default n
        depends on BUSYBOX_CONFIG_NC
        help
@@ -487,6 +537,14 @@ config BUSYBOX_CONFIG_NETSTAT
        help
          netstat prints information about the Linux networking subsystem.
 
+config BUSYBOX_CONFIG_FEATURE_NETSTAT_WIDE
+       bool "  Enable wide netstat output"
+       default y
+       depends on BUSYBOX_CONFIG_NETSTAT
+       help
+         Add support for wide columns. Useful when displaying IPv6 addresses
+         (-W option).
+
 config BUSYBOX_CONFIG_NSLOOKUP
        bool "nslookup"
        default y
@@ -500,27 +558,25 @@ config BUSYBOX_CONFIG_PING
          ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to
          elicit an ICMP ECHO_RESPONSE from a host or gateway.
 
-config BUSYBOX_CONFIG_FEATURE_FANCY_PING
-       bool "Enable fancy ping output"
-       default y
-       depends on BUSYBOX_CONFIG_PING
-       help
-         Make the output from the ping applet include statistics, and at the
-         same time provide full support for ICMP packets.
-
 config BUSYBOX_CONFIG_PING6
        bool "ping6"
        default y
-       depends on BUSYBOX_CONFIG_FEATURE_IPV6
+       depends on BUSYBOX_CONFIG_FEATURE_IPV6 && BUSYBOX_CONFIG_PING
        help
          This will give you a ping that can talk IPv6.
 
-config BUSYBOX_CONFIG_FEATURE_FANCY_PING6
-       bool "Enable fancy ping6 output"
+config BUSYBOX_CONFIG_PSCAN
+       bool "pscan"
+       default n
+       help
+         Simple network port scanner.
+
+config BUSYBOX_CONFIG_FEATURE_FANCY_PING
+       bool "Enable fancy ping output"
        default y
-       depends on BUSYBOX_CONFIG_PING6
+       depends on BUSYBOX_CONFIG_PING
        help
-         Make the output from the ping6 applet include statistics, and at the
+         Make the output from the ping applet include statistics, and at the
          same time provide full support for ICMP packets.
 
 config BUSYBOX_CONFIG_ROUTE
@@ -529,6 +585,12 @@ config BUSYBOX_CONFIG_ROUTE
        help
          Route displays or manipulates the kernel's IP routing tables.
 
+config BUSYBOX_CONFIG_SLATTACH
+       bool "slattach"
+       default n
+       help
+         slattach is a small utility to attach network interfaces to serial lines.
+
 config BUSYBOX_CONFIG_TELNET
        bool "telnet"
        default y
@@ -703,13 +765,6 @@ config BUSYBOX_CONFIG_FEATURE_WGET_AUTHENTICATION
        help
          Support authenticated HTTP transfers.
 
-config BUSYBOX_CONFIG_FEATURE_WGET_IP6_LITERAL
-       bool "Enable IPv6 literal addresses"
-       default y
-       depends on BUSYBOX_CONFIG_WGET && BUSYBOX_CONFIG_FEATURE_IPV6
-       help
-         Support IPv6 address literal notation in URLs.
-
 config BUSYBOX_CONFIG_FEATURE_WGET_LONG_OPTIONS
        bool "Enable long options"
        default y
index 04a2ada..65462ef 100644 (file)
@@ -32,6 +32,16 @@ config BUSYBOX_CONFIG_APP_DUMPLEASES
 
          See http://udhcp.busybox.net for further details.
 
+config BUSYBOX_CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY
+       bool "Rewrite the lease file at every new acknowledge"
+       default n
+       depends on BUSYBOX_CONFIG_APP_UDHCPD
+       help
+         If selected, udhcpd will write a new file with leases every
+         time a new lease has been accepted, thus eleminating the need
+         to send SIGUSR1 for the initial writing, or updating. Any timed
+         rewriting remains undisturbed
+
 config BUSYBOX_CONFIG_APP_UDHCPC
        bool "udhcp Client (udhcpc)"
        default y
@@ -44,17 +54,6 @@ config BUSYBOX_CONFIG_APP_UDHCPC
 
          See http://udhcp.busybox.net for further details.
 
-config BUSYBOX_CONFIG_FEATURE_UDHCP_SYSLOG
-       bool "Log udhcp messages to syslog"
-       default n
-       depends on BUSYBOX_CONFIG_APP_UDHCPD || BUSYBOX_CONFIG_APP_UDHCPC
-       select BUSYBOX_CONFIG_FEATURE_SYSLOG
-       help
-         If not daemonized, udhcpd prints its messages to stdout/stderr.
-         If this option is selected, it will also log them to syslog.
-
-         See http://udhcp.busybox.net for further details.
-
 config BUSYBOX_CONFIG_FEATURE_UDHCP_DEBUG
        bool "Compile udhcp with noisy debugging messages"
        default n
@@ -65,3 +64,11 @@ config BUSYBOX_CONFIG_FEATURE_UDHCP_DEBUG
          the background.
 
          See http://udhcp.busybox.net for further details.
+
+config BUSYBOX_CONFIG_FEATURE_RFC3397
+       bool "Support for RFC3397 domain search (experimental)"
+       default y
+       depends on BUSYBOX_CONFIG_APP_UDHCPD || BUSYBOX_CONFIG_APP_UDHCPC
+       help
+         If selected, both client and server will support passing of domain
+         search lists via option 119, specified in RFC3397.
index ef0c6a2..cd063db 100644 (file)
@@ -43,6 +43,12 @@ config BUSYBOX_CONFIG_KILLALL5
        default y
        depends on BUSYBOX_CONFIG_KILL
 
+config BUSYBOX_CONFIG_NMETER
+       bool "nmeter"
+       default n
+       help
+         Prints selected system stats continuously, one line per update.
+
 config BUSYBOX_CONFIG_PIDOF
        bool "pidof"
        default y
@@ -74,7 +80,7 @@ config BUSYBOX_CONFIG_PS
 
 config BUSYBOX_CONFIG_FEATURE_PS_WIDE
        bool "Enable argument for wide output (-w)"
-       default y
+       default n
        depends on BUSYBOX_CONFIG_PS
        help
          Support argument 'w' for wide output.
@@ -102,11 +108,25 @@ config BUSYBOX_CONFIG_TOP
          system.
 
 config BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
-       bool "Support showing CPU usage percentage (add 2k bytes)"
+       bool "Show CPU per-process usage percentage (adds 2k bytes)"
        default y
        depends on BUSYBOX_CONFIG_TOP
        help
-         Make top display CPU usage.
+         Make top display CPU usage for each process.
+
+config BUSYBOX_CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS
+       bool "Show CPU global usage percentage (adds 0.5k bytes)"
+       default y
+       depends on BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+       help
+         Makes top display "CPU: NN% usr NN% sys..." line.
+
+config BUSYBOX_CONFIG_FEATURE_TOP_DECIMALS
+       bool "Show 1/10th of a percent in CPU/mem statistics (adds 0.3k bytes)"
+       default n
+       depends on BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+       help
+         Show 1/10th of a percent in CPU/mem statistics.
 
 config BUSYBOX_CONFIG_UPTIME
        bool "uptime"
@@ -116,6 +136,14 @@ config BUSYBOX_CONFIG_UPTIME
          the system has been running, how many users are currently logged
          on, and the system load averages for the past 1, 5, and 15 minutes.
 
+config BUSYBOX_CONFIG_WATCH
+       bool "watch"
+       default n
+       #huh?? select DATE
+       help
+         watch is used to execute a program periodically, showing
+         output to the screen.
+
 
 endmenu
 
diff --git a/package/busybox/config/selinux/Config.in b/package/busybox/config/selinux/Config.in
new file mode 100644 (file)
index 0000000..907c975
--- /dev/null
@@ -0,0 +1,108 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Selinux Utilities"
+       depends on BUSYBOX_CONFIG_SELINUX
+
+config BUSYBOX_CONFIG_CHCON
+       bool "chcon"
+       default n
+       depends on BUSYBOX_CONFIG_SELINUX
+       help
+         Enable support to change the security context of file.
+
+config BUSYBOX_CONFIG_FEATURE_CHCON_LONG_OPTIONS
+       bool "Enable long options"
+       default n
+       depends on BUSYBOX_CONFIG_CHCON && BUSYBOX_CONFIG_GETOPT_LONG
+       help
+         Support long options for the chcon applet.
+
+config BUSYBOX_CONFIG_GETENFORCE
+       bool "getenforce"
+       default n
+       depends on BUSYBOX_CONFIG_SELINUX
+       help
+         Enable support to get the current mode of SELinux.
+
+config BUSYBOX_CONFIG_GETSEBOOL
+       bool "getsebool"
+       default n
+       depends on BUSYBOX_CONFIG_SELINUX
+       help
+         Enable support to get SELinux boolean values.
+
+config BUSYBOX_CONFIG_LOAD_POLICY
+       bool "load_policy"
+       default n
+       depends on BUSYBOX_CONFIG_SELINUX
+       help
+         Enable support to load SELinux policy.
+
+config BUSYBOX_CONFIG_MATCHPATHCON
+       bool "matchpathcon"
+       default n
+       depends on BUSYBOX_CONFIG_SELINUX
+       help
+         Enable support to get default security context of the
+         specified path from the file contexts configuration.
+
+config BUSYBOX_CONFIG_RESTORECON
+       bool "restorecon"
+       default n
+       depends on BUSYBOX_CONFIG_SELINUX
+       help
+         Enable support to relabel files. The feature is almost
+         the same as setfiles, but usage is a little different.
+
+config BUSYBOX_CONFIG_RUNCON
+       bool "runcon"
+       default n
+       depends on BUSYBOX_CONFIG_SELINUX
+       help
+         Enable support to run command in speficied security context.
+
+config BUSYBOX_CONFIG_FEATURE_RUNCON_LONG_OPTIONS
+       bool "Enable long options"
+       default n
+       depends on BUSYBOX_CONFIG_RUNCON && BUSYBOX_CONFIG_GETOPT_LONG
+       help
+         Support long options for the runcon applet.
+
+config BUSYBOX_CONFIG_SELINUXENABLED
+       bool "selinuxenabled"
+       default n
+       depends on BUSYBOX_CONFIG_SELINUX
+       help
+         Enable support for this command to be used within shell scripts
+         to determine if selinux is enabled.
+
+config BUSYBOX_CONFIG_SETENFORCE
+       bool "setenforce"
+       default n
+       depends on BUSYBOX_CONFIG_SELINUX
+       help
+         Enable support to modify the mode SELinux is running in.
+
+config BUSYBOX_CONFIG_SETFILES
+       bool "setfiles"
+       default n
+       depends on BUSYBOX_CONFIG_SELINUX
+       help
+         Enable support to modify to relabel files.
+         Notice: If you built libselinux with -D_FILE_OFFSET_BITS=64,
+         (It is default in libselinux's Makefile), you _must_ enable
+         CONFIG_LFS.
+
+config BUSYBOX_CONFIG_FEATURE_SETFILES_CHECK_OPTION
+       bool "Enable check option"
+       default n
+       depends on BUSYBOX_CONFIG_SETFILES
+       help
+         Support "-c" option (check the validity of the contexts against
+         the specified binary policy) for setfiles. Requires libsepol.
+
+endmenu
+
index d4cd52d..d2b1056 100644 (file)
@@ -87,7 +87,7 @@ config BUSYBOX_CONFIG_ASH_MATH_SUPPORT
 
 config BUSYBOX_CONFIG_ASH_MATH_SUPPORT_64
        bool "Extend Posix math support to 64 bit"
-       default n
+       default y
        depends on BUSYBOX_CONFIG_ASH_MATH_SUPPORT
        help
          Enable 64-bit math support in the ash shell.  This will make
@@ -107,7 +107,7 @@ config BUSYBOX_CONFIG_ASH_BUILTIN_ECHO
        select BUSYBOX_CONFIG_ECHO
        depends on BUSYBOX_CONFIG_ASH
        help
-         Enable support for echo, built in to ash.
+         Enable support for echo, builtin to ash.
 
 config BUSYBOX_CONFIG_ASH_BUILTIN_TEST
        bool "Builtin version of 'test'"
@@ -115,7 +115,7 @@ config BUSYBOX_CONFIG_ASH_BUILTIN_TEST
        select BUSYBOX_CONFIG_TEST
        depends on BUSYBOX_CONFIG_ASH
        help
-         Enable support for test, built in to ash.
+         Enable support for test, builtin to ash.
 
 config BUSYBOX_CONFIG_ASH_CMDCMD
        bool "'command' command to override shell builtins"
@@ -135,7 +135,7 @@ config BUSYBOX_CONFIG_ASH_MAIL
 
 config BUSYBOX_CONFIG_ASH_OPTIMIZE_FOR_SIZE
        bool "Optimize for size instead of speed"
-       default y
+       default n
        depends on BUSYBOX_CONFIG_ASH
        help
          Compile ash for reduced size at the price of speed.
@@ -153,7 +153,7 @@ config BUSYBOX_CONFIG_ASH_RANDOM_SUPPORT
 
 config BUSYBOX_CONFIG_ASH_EXPAND_PRMT
        bool "Expand prompt string"
-       default n
+       default y
        depends on BUSYBOX_CONFIG_ASH
        help
          "PS#" may be contain volatile content, such as backquote commands.
@@ -176,6 +176,54 @@ config BUSYBOX_CONFIG_HUSH
          word ), arithmetic expansion, aliases, brace expansion, tilde
          expansion, &> and >& redirection of stdout+stderr, etc.
 
+config BUSYBOX_CONFIG_HUSH_HELP
+       bool "help builtin"
+       default n
+       depends on BUSYBOX_CONFIG_HUSH
+       help
+         Enable help builtin in hush. Code size + ~1 kbyte.
+
+config BUSYBOX_CONFIG_HUSH_INTERACTIVE
+       bool "Interactive mode"
+       default n
+       depends on BUSYBOX_CONFIG_HUSH
+       help
+         Enable interactive mode (prompt and command editing).
+         Without this, hush simply reads and executes commands
+         from stdin just like a shell script from the file.
+         No prompt, no PS1/PS2 magic shell variables.
+
+config BUSYBOX_CONFIG_HUSH_JOB
+       bool "Job control"
+       default n
+       depends on BUSYBOX_CONFIG_HUSH_INTERACTIVE
+       help
+         Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
+         command (not entire shell), fg/bg builtins work. Without this option,
+         "cmd &" still works by simply spawning a process and immediately
+         prompting for next command (or executing next command in a script),
+         but no separate process group is formed.
+
+config BUSYBOX_CONFIG_HUSH_TICK
+       bool "Process substitution"
+       default n
+       depends on BUSYBOX_CONFIG_HUSH
+       help
+         Enable process substitution `command` and $(command) in hush.
+
+config BUSYBOX_CONFIG_HUSH_IF
+       bool "Support if/then/elif/else/fi"
+       default n
+       depends on BUSYBOX_CONFIG_HUSH
+       help
+         Enable if/then/elif/else/fi in hush.
+
+config BUSYBOX_CONFIG_HUSH_LOOPS
+       bool "Support for, while and until loops"
+       default n
+       depends on BUSYBOX_CONFIG_HUSH
+       help
+         Enable for, while and until loops in hush.
 
 config BUSYBOX_CONFIG_LASH
        bool "lash"
@@ -216,12 +264,12 @@ config BUSYBOX_CONFIG_FEATURE_SH_EXTRA_QUIET
        help
          Remove the busybox introduction when starting a shell.
 
-config BUSYBOX_CONFIG_FEATURE_SH_STANDALONE_SHELL
+config BUSYBOX_CONFIG_FEATURE_SH_STANDALONE
        bool "Standalone shell"
        default n
-       depends on BUSYBOX_CONFIG_MSH || BUSYBOX_CONFIG_LASH || BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH
+       depends on (BUSYBOX_CONFIG_MSH || BUSYBOX_CONFIG_LASH || BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH) && BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS
        help
-         This option causes the selected busybox shell to use busybox applets
+         This option causes busybox shells to use busybox applets
          in preference to executables in the PATH whenever possible.  For
          example, entering the command 'ifconfig' into the shell would cause
          busybox to use the ifconfig busybox applet.  Specifying the fully
@@ -230,66 +278,43 @@ config BUSYBOX_CONFIG_FEATURE_SH_STANDALONE_SHELL
          is generally used when creating a statically linked version of busybox
          for use as a rescue shell, in the event that you screw up your system.
 
-         Note that this will *also* cause applets to take precedence
-         over shell builtins of the same name.  So turning this on will
-         eliminate any performance gained by turning on the builtin "echo"
-         and "test" commands in ash.
-
-         Note that when using this option, the shell will attempt to directly
-         run '/bin/busybox'.  If you do not have the busybox binary sitting in
-         that exact location with that exact name, this option will not work at
-         all.
-
-config BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING
-       bool "Command line editing"
-       default y
-       depends on BUSYBOX_CONFIG_MSH || BUSYBOX_CONFIG_LASH || BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH
-       help
-         Enable command editing in shell.
-
-config BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING_VI
-       bool "vi-style line editing commands"
+         This is implemented by re-execing /proc/self/exe (typically)
+         with right parameters. Some selected applets ("NOFORK" applets)
+         can even be executed without creating new process.
+         Instead, busybox will call <applet>_main() internally.
+
+         However, this causes problems in chroot jails without mounted /proc
+         and with ps/top (command name can be shown as 'exe' for applets
+         started this way).
+# untrue?
+#        Note that this will *also* cause applets to take precedence
+#        over shell builtins of the same name.  So turning this on will
+#        eliminate any performance gained by turning on the builtin "echo"
+#        and "test" commands in ash.
+# untrue?
+#        Note that when using this option, the shell will attempt to directly
+#        run '/bin/busybox'.  If you do not have the busybox binary sitting in
+#        that exact location with that exact name, this option will not work at
+#        all.
+
+config BUSYBOX_CONFIG_CTTYHACK
+       bool "cttyhack"
        default n
-       depends on BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING
        help
-         Enable vi-style line editing in the shell.  This mode can be
-         turned on and off with "set -o vi" and "set +o vi".
-
-config BUSYBOX_CONFIG_FEATURE_COMMAND_HISTORY
-       int "History size"
-       range 0 99999
-       default 15
-       depends on BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING
-       help
-         Specify command history size in shell.
+         One common problem reported on the mailing list is "can't access tty;
+         job control turned off" error message which typically appears when
+         one tries to use shell with stdin/stdout opened to /dev/console.
+         This device is special - it cannot be a controlling tty.
 
-config BUSYBOX_CONFIG_FEATURE_COMMAND_SAVEHISTORY
-       bool "History saving"
-       default n
-       depends on BUSYBOX_CONFIG_ASH && BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING
-       help
-         Enable history saving in ash shell.
-
-config BUSYBOX_CONFIG_FEATURE_COMMAND_TAB_COMPLETION
-       bool "Tab completion"
-       default y
-       depends on BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING
-       help
-         Enable tab completion in shell.
+         Proper solution is to use correct device instead of /dev/console.
 
-config BUSYBOX_CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION
-       bool "Username completion"
-       default n
-       depends on BUSYBOX_CONFIG_FEATURE_COMMAND_TAB_COMPLETION
-       help
-         Enable username completion in shell.
+         cttyhack provides "quick and dirty" solution to this problem.
+         It analyzes stdin with various ioctls, trying to determine whether
+         it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line).
+         If it detects one, it closes stdin/out/err and reopens that device.
+         Then it executes given program. Usage example for /etc/inittab
+         (for busybox init):
 
-config BUSYBOX_CONFIG_FEATURE_SH_FANCY_PROMPT
-       bool "Fancy shell prompts"
-       default y
-       depends on BUSYBOX_CONFIG_FEATURE_COMMAND_EDITING
-       help
-         Setting this option allows for prompts to use things like \w and
-         \$ and also using escape codes.
+         ::respawn:/bin/cttyhack /bin/sh
 
 endmenu
index 12e08d3..9eebd77 100644 (file)
@@ -59,6 +59,7 @@ config BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG
 config BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE
        int "    Circular buffer size in Kbytes (minimum 4KB)"
        default 16
+       range 4 2147483647
        depends on BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG
        help
          This option sets the size of the circular buffer
@@ -88,8 +89,6 @@ config BUSYBOX_CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
 config BUSYBOX_CONFIG_KLOGD
        bool "klogd"
        default y
-       depends on BUSYBOX_CONFIG_SYSLOGD
-       select BUSYBOX_CONFIG_FEATURE_SYSLOG
        help
          klogd is a utility which intercepts and logs all
          messages from the Linux kernel and sends the messages
index ab3dc37..28dc7b7 100644 (file)
@@ -127,7 +127,7 @@ config BUSYBOX_CONFIG_FEATURE_SGI_LABEL
 config BUSYBOX_CONFIG_FEATURE_SUN_LABEL
        bool "Support SUN disklabels"
        default n
-       depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
+       depends on BUSYBOX_CONFIG_FDISK && BUSYBOX_CONFIG_FEATURE_FDISK_WRITABLE
        help
          Enabling this option allows you to create or change SUN disklabels.
          Most people can safely leave this option disabled.
@@ -181,7 +181,7 @@ config BUSYBOX_CONFIG_MKFS_MINIX
          this utility will do the job for you.
 
 comment "Minix filesystem support"
-    depends on BUSYBOX_CONFIG_FSCK_MINIX || BUSYBOX_CONFIG_MKFS_MINIX
+       depends on BUSYBOX_CONFIG_FSCK_MINIX || BUSYBOX_CONFIG_MKFS_MINIX
 
 config BUSYBOX_CONFIG_FEATURE_MINIX2
        bool "Support Minix fs v2 (fsck_minix/mkfs_minix)"
@@ -269,46 +269,41 @@ config BUSYBOX_CONFIG_MDEV
        bool "mdev"
        default n
        help
-         mdev is a mini-udev implementation: call it with -s to populate
-         /dev from /sys, then "echo /sbin/mdev > /proc/sys/kernel/hotplug" to
-         have it handle hotplug events afterwards.  Device names are taken
-         from sysfs.
+         mdev is a mini-udev implementation for dynamically creating device
+         nodes in the /dev directory.
+
+         For more information, please see docs/mdev.txt
 
 config BUSYBOX_CONFIG_FEATURE_MDEV_CONF
        bool "Support /etc/mdev.conf"
        default n
        depends on BUSYBOX_CONFIG_MDEV
        help
-         The mdev config file contains lines that look like:
-
-           hd[a-z][0-9]* 0:3 660
-
-         That's device name (with regex match), uid:gid, and permissions.
+         Add support for the mdev config file to control ownership and
+         permissions of the device nodes.
 
-         Config file parsing stops on the first matching line.  If no config
-         entry is matched, devices are created with default 0:0 660.  (Make
-         the last line match .* to override this.)
+         For more information, please see docs/mdev.txt
 
 config BUSYBOX_CONFIG_FEATURE_MDEV_EXEC
        bool "Support command execution at device addition/removal"
        default n
        depends on BUSYBOX_CONFIG_FEATURE_MDEV_CONF
        help
-         This adds support for an optional field to /etc/mdev.conf, consisting
-         of a special character and a command line to run after creating the
-         corresponding device(s) and before removing, ala:
+         This adds support for an optional field to /etc/mdev.conf for
+         executing commands when devices are created/removed.
 
-           hdc root:cdrom 660  *ln -s $MDEV cdrom
+         For more information, please see docs/mdev.txt
 
-         The $MDEV environment variable is set to the name of the device.
-
-         The special characters and their meanings are:
-           @ Run after creating the device.
-           $ Run before removing the device.
-           * Run both after creating and before removing the device.
+config BUSYBOX_CONFIG_FEATURE_MDEV_LOAD_FIRMWARE
+       bool "Support loading of firmwares"
+       default n
+       depends on BUSYBOX_CONFIG_MDEV
+       help
+         Some devices need to load firmware before they can be usable.
 
-         Commands are executed via system() so you need /bin/sh, meaning you
-         probably want to select a default shell in the Shells menu.
+         These devices will request userspace look up the files in
+         /lib/firmware/ and if it exists, send it to the kernel for
+         loading into the hardware.
 
 config BUSYBOX_CONFIG_MKSWAP
        bool "mkswap"
@@ -369,7 +364,7 @@ config BUSYBOX_CONFIG_FEATURE_MOUNT_NFS
        bool "Support mounting NFS file systems"
        default y
        depends on BUSYBOX_CONFIG_MOUNT
-       depends on BUSYBOX_CONFIG_FEATURE_HAVE_RPC
+       select BUSYBOX_CONFIG_FEATURE_HAVE_RPC
        select BUSYBOX_CONFIG_FEATURE_SYSLOG
        help
          Enable mounting of NFS file systems.
@@ -495,7 +490,7 @@ config BUSYBOX_CONFIG_FEATURE_MOUNT_LOOP
          The umount command will also free that loopback device.
 
          You can still use the 'losetup' utility (to manually associate files
-          with loop devices) if you need to do something advanced, such as
+         with loop devices) if you need to do something advanced, such as
          specify an offset or cryptographic options to the loopback device.
          (If you don't want umount to free the loop device, use "umount -D".)
 
index d19cf0c..52fd92a 100644 (file)
@@ -1,12 +1,13 @@
-Index: busybox-1.4.2/applets/Kbuild
+Index: busybox-1.7.2/applets/Kbuild
 ===================================================================
---- busybox-1.4.2.orig/applets/Kbuild  2007-06-04 13:21:32.429046704 +0200
-+++ busybox-1.4.2/applets/Kbuild       2007-06-04 13:21:32.495036672 +0200
-@@ -10,6 +10,7 @@
+--- busybox-1.7.2.orig/applets/Kbuild  2007-10-04 14:30:23.484330073 +0200
++++ busybox-1.7.2/applets/Kbuild       2007-10-04 14:33:47.751970627 +0200
+@@ -20,6 +20,6 @@
+ HOSTCFLAGS_usage.o = -I$(srctree)/include
  
- # Generated file needs additional love
-+applets/usage: include/autoconf.h
- applets/applets.o: include/usage_compressed.h
- hostprogs-y += usage
+ applets/applets.o:          include/usage_compressed.h
+-applets/usage:              .config $(srctree)/applets/usage_compressed
+-include/usage_compressed.h: applets/usage $(srctree)/applets/usage_compressed
++applets/usage:              .config $(srctree)/applets/usage_compressed include/autoconf.h
++include/usage_compressed.h: applets/usage $(srctree)/applets/usage_compressed include/autoconf.h
+       $(call cmd,gen_usage_compressed)
index fd530df..657f83a 100644 (file)
@@ -1,13 +1,13 @@
-Index: busybox-1.4.2/networking/wget.c
+Index: busybox-1.7.2/networking/wget.c
 ===================================================================
---- busybox-1.4.2.orig/networking/wget.c       2007-06-04 13:21:32.408049896 +0200
-+++ busybox-1.4.2/networking/wget.c    2007-06-04 13:21:32.681008400 +0200
-@@ -136,7 +136,7 @@
-               { "directory-prefix", required_argument, NULL, 'P' },
-               { "proxy",            required_argument, NULL, 'Y' },
-               { "user-agent",       required_argument, NULL, 'U' },
--              { "passive-ftp",      no_argument, NULL, 0xff },
-+              { "passive-ftp",      no_argument, NULL, 0xfd },
-               { "header",           required_argument, NULL, 0xfe },
-               { 0, 0, 0, 0 }
-       };
+--- busybox-1.7.2.orig/networking/wget.c       2007-10-04 14:35:17.057059834 +0200
++++ busybox-1.7.2/networking/wget.c    2007-10-04 14:35:27.013627222 +0200
+@@ -140,7 +140,7 @@
+               "directory-prefix\0" Required_argument "P"
+               "proxy\0"            Required_argument "Y"
+               "user-agent\0"       Required_argument "U"
+-              "passive-ftp\0"      No_argument       "\xff"
++              "passive-ftp\0"      No_argument       "\xfd"
+               "header\0"           Required_argument "\xfe"
+               ;
+       applet_long_options = wget_longopts;
diff --git a/package/busybox/patches/130-drop_werror.patch b/package/busybox/patches/130-drop_werror.patch
deleted file mode 100644 (file)
index cd3a67b..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-Index: busybox-1.4.2/Makefile.flags
-===================================================================
---- busybox-1.4.2.orig/Makefile.flags  2007-06-04 13:21:32.387053088 +0200
-+++ busybox-1.4.2/Makefile.flags       2007-06-04 13:21:32.871979368 +0200
-@@ -16,7 +16,7 @@
-       -D"BB_VER=KBUILD_STR($(BB_VER))" -DBB_BT=AUTOCONF_TIMESTAMP
- CFLAGS += \
--      -Wall -Wstrict-prototypes -Wshadow -Werror -Wundef \
-+      -Wall -Wstrict-prototypes -Wshadow -Wundef \
-       -funsigned-char -fno-builtin-strlen -finline-limit=0 -static-libgcc \
-       -Os -falign-functions=1 -falign-jumps=1 -falign-loops=1 \
-       -fomit-frame-pointer -ffunction-sections -fdata-sections
index 3a95174..b304604 100644 (file)
@@ -1,9 +1,9 @@
-Index: busybox-1.4.2/networking/udhcp/dhcpc.c
+Index: busybox-1.7.2/networking/udhcp/dhcpc.c
 ===================================================================
---- busybox-1.4.2.orig/networking/udhcp/dhcpc.c        2007-07-18 10:07:20.161035443 +0200
-+++ busybox-1.4.2/networking/udhcp/dhcpc.c     2007-07-18 10:09:15.515609124 +0200
-@@ -273,6 +273,12 @@
-               tv.tv_sec = timeout - uptime();
+--- busybox-1.7.2.orig/networking/udhcp/dhcpc.c        2007-10-04 14:36:41.521873204 +0200
++++ busybox-1.7.2/networking/udhcp/dhcpc.c     2007-10-04 14:38:28.231954268 +0200
+@@ -309,6 +309,12 @@
+  jump_in:
                tv.tv_usec = 0;
  
 +              /* When running on a bridge, the ifindex may have changed (e.g. if
@@ -12,6 +12,6 @@ Index: busybox-1.4.2/networking/udhcp/dhcpc.c
 +               * Workaround: refresh it here before processing the next packet */
 +              read_interface(client_config.interface, &client_config.ifindex, NULL, client_config.arp);
 +
-               if (listen_mode != LISTEN_NONE && fd < 0) {
+               if (listen_mode != LISTEN_NONE && sockfd < 0) {
                        if (listen_mode == LISTEN_KERNEL)
-                               fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface);
+                               sockfd = listen_socket(/*INADDR_ANY,*/ CLIENT_PORT, client_config.interface);
index b5a8794..8ee2aee 100644 (file)
@@ -1,37 +1,37 @@
-Index: busybox-1.4.2/shell/ash.c
+Index: busybox-1.7.2/shell/ash.c
 ===================================================================
---- busybox-1.4.2.orig/shell/ash.c     2007-06-04 13:21:32.248074216 +0200
-+++ busybox-1.4.2/shell/ash.c  2007-06-04 13:21:34.000807760 +0200
-@@ -12237,9 +12237,18 @@
+--- busybox-1.7.2.orig/shell/ash.c     2007-09-03 13:48:38.000000000 +0200
++++ busybox-1.7.2/shell/ash.c  2007-10-04 14:47:41.607489342 +0200
+@@ -11310,8 +11310,18 @@
        const char *p;
        char **aptr;
        int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
 +      int mask = ~0;
-       int notp;
++      int nopt;
  
--      notp = nextopt("p") - 'p';
-+      while ((notp = nextopt("np"))) {
-+              if (notp == 'n') {
+-      if (nextopt("p") != 'p') {
++      while ((nopt = nextopt("np"))) {
++              if (nopt == 'n') {
 +                              mask = ~flag;
 +              } else { /* p */
 +                      break;
 +              }
 +      }
 +
-+      notp -= 'p';
-       if (notp && ((name = *(aptr = argptr)))) {
-               do {
-                       if ((p = strchr(name, '=')) != NULL) {
-@@ -12247,10 +12256,11 @@
-                       } else {
-                               if ((vp = *findvar(hashvar(name), name))) {
-                                       vp->flags |= flag;
-+                                      vp->flags &= mask;
-                                       continue;
++      if (nopt != 'p') {
+               aptr = argptr;
+               name = *aptr;
+               if (name) {
+@@ -11323,10 +11333,11 @@
+                                       vp = *findvar(hashvar(name), name);
+                                       if (vp) {
+                                               vp->flags |= flag;
++                                              vp->flags &= mask;
+                                               continue;
+                                       }
                                }
-                       }
--                      setvar(name, p, flag);
-+                      setvar(name, p, flag & mask);
-               } while ((name = *++aptr) != NULL);
-       } else {
-               showvars(argv[0], flag, 0);
+-                              setvar(name, p, flag);
++                              setvar(name, p, flag & mask);
+                       } while ((name = *++aptr) != NULL);
+                       return 0;
+               }
diff --git a/package/busybox/patches/260-broadcast_plus.patch b/package/busybox/patches/260-broadcast_plus.patch
deleted file mode 100644 (file)
index 60b2afc..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-Index: busybox-1.4.2/networking/ifconfig.c
-===================================================================
---- busybox-1.4.2.orig/networking/ifconfig.c   2007-06-29 02:03:17.046772952 +0200
-+++ busybox-1.4.2/networking/ifconfig.c        2007-06-29 02:03:49.938772608 +0200
-@@ -376,18 +376,18 @@
- #endif
-                                               sai.sin_family = AF_INET;
-                                               sai.sin_port = 0;
--                                              if (!strcmp(host, bb_str_default)) {
--                                                      /* Default is special, meaning 0.0.0.0. */
--                                                      sai.sin_addr.s_addr = INADDR_ANY;
--                                              }
- #if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS
--                                              else if ((host[0] == '+' && !host[1]) && (mask & A_BROADCAST)
-+                                              if ((host[0] == '+' && !host[1]) && (mask & A_BROADCAST)
-                                                && (did_flags & (A_NETMASK|A_HOSTNAME)) == (A_NETMASK|A_HOSTNAME)
-                                               ) {
-                                                       /* + is special, meaning broadcast is derived. */
-                                                       sai.sin_addr.s_addr = (~sai_netmask) | (sai_hostname & sai_netmask);
--                                              }
-+                                              } else
- #endif
-+                                              if (!strcmp(host, bb_str_default)) {
-+                                                      /* Default is special, meaning 0.0.0.0. */
-+                                                      sai.sin_addr.s_addr = INADDR_ANY;
-+                                              }
- #if ENABLE_FEATURE_IPV6
-                                               else if (inet_pton(AF_INET6, host, &sai6.sin6_addr) > 0) {
-                                                       int sockfd6;
diff --git a/package/busybox/patches/270-ash_performance.patch b/package/busybox/patches/270-ash_performance.patch
deleted file mode 100644 (file)
index eff7a5b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-Index: busybox-1.4.2/shell/ash.c
-===================================================================
---- busybox-1.4.2.orig/shell/ash.c     2007-07-01 05:33:08.371737750 +0200
-+++ busybox-1.4.2/shell/ash.c  2007-07-01 05:33:11.703946000 +0200
-@@ -3957,12 +3957,6 @@
-       }
- #endif
--      if (is_safe_applet(name)) {
--              entry->cmdtype = CMDNORMAL;
--              entry->u.index = -1;
--              return;
--      }
--
-       updatetbl = (path == pathval());
-       if (!updatetbl) {
-               act |= DO_ALTPATH;
-@@ -4074,6 +4068,12 @@
-               goto success;
-       }
-+      if (is_safe_applet(name)) {
-+              entry->cmdtype = CMDNORMAL;
-+              entry->u.index = -1;
-+              return;
-+      }
-+
-       /* We failed.  If there was an entry for this command, delete it */
-       if (cmdp && updatetbl)
-               delete_cmd_entry();
diff --git a/package/busybox/patches/280-printf.patch b/package/busybox/patches/280-printf.patch
deleted file mode 100644 (file)
index d8442dc..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-Index: busybox-1.4.2/coreutils/printf.c
-===================================================================
---- busybox-1.4.2.orig/coreutils/printf.c      2007-07-09 03:00:31.808788500 +0200
-+++ busybox-1.4.2/coreutils/printf.c   2007-07-09 03:00:42.257441500 +0200
-@@ -60,11 +60,11 @@
- static void conv_strtoul(char *arg, void *result)
- {
--      *(unsigned long*)result = bb_strtoul(arg, NULL, 10);
-+      *(unsigned long*)result = bb_strtoul(arg, NULL, 0);
- }
- static void conv_strtol(char *arg, void *result)
- {
--      *(long*)result = bb_strtol(arg, NULL, 10);
-+      *(long*)result = bb_strtol(arg, NULL, 0);
- }
- static void conv_strtod(char *arg, void *result)
- {
index 22e6abc..b8c8db7 100644 (file)
@@ -1,19 +1,19 @@
 
        Copyright (C) 2006 OpenWrt.org
 
-Index: busybox-1.4.2/networking/httpd.c
+Index: busybox-1.7.2/networking/httpd.c
 ===================================================================
---- busybox-1.4.2.orig/networking/httpd.c      2007-06-04 13:21:32.190083032 +0200
-+++ busybox-1.4.2/networking/httpd.c   2007-06-04 13:21:34.401746808 +0200
-@@ -1402,12 +1402,26 @@
+--- busybox-1.7.2.orig/networking/httpd.c      2007-09-30 01:54:12.000000000 +0200
++++ busybox-1.7.2/networking/httpd.c   2007-10-04 14:59:20.287304836 +0200
+@@ -1527,12 +1527,26 @@
                        if (ENABLE_FEATURE_HTTPD_AUTH_MD5) {
                                char *cipher;
                                char *pp;
 +                              char *ppnew = NULL;
 +                              struct passwd *pwd = NULL;
  
-                               if (strncmp(p, request, u-request) != 0) {
-                                       /* user uncompared */
+                               if (strncmp(p, request, u - request) != 0) {
+                                       /* user doesn't match */
                                        continue;
                                }
                                pp = strchr(p, ':');
@@ -29,10 +29,10 @@ Index: busybox-1.4.2/networking/httpd.c
 +                                      strcpy(ppnew + 1, pwd->pw_passwd);
 +                                      pp = ppnew;
 +                              }
-                               if (pp && pp[1] == '$' && pp[2] == '1' &&
-                                               pp[3] == '$' && pp[4]) {
-                                       pp++;
-@@ -1417,6 +1431,10 @@
+                               if (pp && pp[1] == '$' && pp[2] == '1'
+                                && pp[3] == '$' && pp[4]
+                               ) {
+@@ -1543,6 +1557,10 @@
                                        /* unauthorized */
                                        continue;
                                }
diff --git a/package/busybox/patches/330-httpd_user_agent.patch b/package/busybox/patches/330-httpd_user_agent.patch
deleted file mode 100644 (file)
index d9fa874..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-Index: busybox-1.4.2/networking/httpd.c
-===================================================================
---- busybox-1.4.2.orig/networking/httpd.c      2007-06-04 13:21:34.401746808 +0200
-+++ busybox-1.4.2/networking/httpd.c   2007-06-04 13:21:34.588718384 +0200
-@@ -137,6 +137,7 @@
-       const char *query;
-       USE_FEATURE_HTTPD_CGI(char *referer;)
-+      USE_FEATURE_HTTPD_CGI(char *user_agent;)
-       const char *configFile;
-@@ -1066,6 +1067,7 @@
-                       if (cp) *cp = '\0'; /* delete :PORT */
-                       setenv1("REMOTE_ADDR", p);
-               }
-+              setenv1("HTTP_USER_AGENT", config->user_agent);
- #if ENABLE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
-               setenv_long("REMOTE_PORT", config->port);
- #endif
-@@ -1647,6 +1649,8 @@
-                                       content_type = strdup(skip_whitespace(buf + sizeof("Content-Type:")-1));
-                               } else if ((STRNCASECMP(buf, "Referer:") == 0)) {
-                                       config->referer = strdup(skip_whitespace(buf + sizeof("Referer:")-1));
-+                              } else if ((STRNCASECMP(buf, "User-Agent:") == 0)) {
-+                                      config->user_agent = strdup(skip_whitespace(buf + sizeof("User-Agent:")-1));
-                               }
- #endif
index d8f430b..7cb8246 100644 (file)
@@ -1,69 +1,76 @@
-Index: busybox-1.4.2/include/usage.h
+Index: busybox-1.7.2/include/usage.h
 ===================================================================
---- busybox-1.4.2.orig/include/usage.h 2007-06-04 13:21:32.103096256 +0200
-+++ busybox-1.4.2/include/usage.h      2007-06-04 13:21:35.005655000 +0200
-@@ -1257,7 +1257,8 @@
-       USE_FEATURE_HTTPD_BASIC_AUTH(" [-r <realm>]") \
+--- busybox-1.7.2.orig/include/usage.h 2007-10-04 17:12:35.230910708 +0200
++++ busybox-1.7.2/include/usage.h      2007-10-04 17:32:12.994027602 +0200
+@@ -1350,7 +1350,8 @@
+       USE_FEATURE_HTTPD_BASIC_AUTH(" [-r realm]") \
        USE_FEATURE_HTTPD_AUTH_MD5(" [-m pass]") \
         " [-h home]" \
--       " [-d/-e <string>]"
-+       " [-d/-e <string>]" \
+-       " [-d/-e string]"
++       " [-d/-e string]" \
 +       " [-R <path> [-H <host>]]"
  #define httpd_full_usage \
-        "Listen for incoming http server requests" \
-        "\n\nOptions:\n" \
-@@ -1273,7 +1274,9 @@
-        "      -m PASS         Crypt PASS with md5 algorithm\n") \
-        "      -h HOME         Specifies http HOME directory (default ./)\n" \
-        "      -e STRING       HTML encode STRING\n" \
--       "      -d STRING       URL decode STRING"
-+       "      -d STRING       URL decode STRING\n" \
-+       "      -R PATH         Redirect target path\n" \
-+       "      -H HOST         Redirect target host"
+        "Listen for incoming HTTP requests" \
+        "\n\nOptions:" \
+@@ -1368,6 +1369,8 @@
+        "\n    -h HOME         Home directory (default .)" \
+        "\n    -e STRING       HTML encode STRING" \
+        "\n    -d STRING       URL decode STRING" \
++       "\n    -R PATH         Redirect target path" \
++       "\n    -H HOST         Redirect target host" \
  
  #define hwclock_trivial_usage \
-        "[-r|--show] [-s|--hctosys] [-w|--systohc] [-l|--localtime] [-u|--utc]"
-Index: busybox-1.4.2/networking/httpd.c
+        "[-r|--show] [-s|--hctosys] [-w|--systohc]" \
+Index: busybox-1.7.2/networking/httpd.c
 ===================================================================
---- busybox-1.4.2.orig/networking/httpd.c      2007-06-04 13:21:34.588718384 +0200
-+++ busybox-1.4.2/networking/httpd.c   2007-06-04 13:21:35.006654848 +0200
-@@ -140,6 +140,8 @@
-       USE_FEATURE_HTTPD_CGI(char *user_agent;)
+--- busybox-1.7.2.orig/networking/httpd.c      2007-10-04 17:13:12.509035065 +0200
++++ busybox-1.7.2/networking/httpd.c   2007-10-04 17:32:33.711208213 +0200
+@@ -230,6 +230,8 @@
  
-       const char *configFile;
-+      const char *redirectPath;
-+      const char *redirectHost;
+       const char *found_mime_type;
+       const char *found_moved_temporarily;
++      const char *redirect_path;
++      const char *redirect_host;
+       Htaccess_IP *ip_a_d;    /* config allow/deny lines */
  
-       unsigned int rmt_ip;
- #if ENABLE_FEATURE_HTTPD_CGI || DEBUG
-@@ -880,8 +882,11 @@
+       USE_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;)
+@@ -264,6 +266,8 @@
+ #define home_httpd        (G.home_httpd       )
+ #define found_mime_type   (G.found_mime_type  )
+ #define found_moved_temporarily (G.found_moved_temporarily)
++#define redirect_path     (G.redirect_path    )
++#define redirect_host     (G.redirect_host    )
+ #define ContentLength     (G.ContentLength    )
+ #define last_mod          (G.last_mod         )
+ #define ip_a_d            (G.ip_a_d           )
+@@ -901,8 +905,11 @@
        }
  #endif
        if (responseNum == HTTP_MOVED_TEMPORARILY) {
--              len += sprintf(buf+len, "Location: %s/%s%s\r\n",
-+              len += sprintf(buf+len, "Location: %s%s%s%s%s%s\r\n",
-+                              (config->redirectHost ? "http://" : ""),
-+                              (config->redirectHost ? config->redirectHost : ""),
-                               config->found_moved_temporarily,
-+                              (config->redirectHost ? "" : "/"),
-                               (config->query ? "?" : ""),
-                               (config->query ? config->query : ""));
+-              len += sprintf(iobuf + len, "Location: %s/%s%s\r\n",
++              len += sprintf(iobuf + len, "Location: %s%s%s%s%s%s\r\n",
++                              (redirect_host ? "http://" : ""),
++                              (redirect_host ? redirect_host : ""),
+                               found_moved_temporarily,
++                              (redirect_host ? "" : "/"),
+                               (g_query ? "?" : ""),
+                               (g_query ? g_query : ""));
        }
-@@ -1594,8 +1599,12 @@
-               *++purl = '\0';       /* so keep last character */
-               test = purl;          /* end ptr */
+@@ -1730,8 +1737,12 @@
+       *++urlp = '\0';       /* so keep last character */
+       tptr = urlp;          /* end ptr */
  
-+              /* redirect active */
-+              if (config->redirectPath && (strncmp(url, config->redirectPath, strlen(config->redirectPath)) != 0))
-+                      config->found_moved_temporarily = config->redirectPath;
++      /* redirect active */
++      if (redirect_path && (strncmp(urlcopy, redirect_path, strlen(redirect_path)) != 0))
++              found_moved_temporarily = redirect_path;
 +
-               /* If URL is directory, adding '/' */
--              if (test[-1] != '/') {
-+              if(!config->redirectPath && (test[-1] != '/')) {
-                       if (is_directory(url + 1, 1, &sb)) {
-                               config->found_moved_temporarily = url;
-                       }
-@@ -1897,7 +1906,9 @@
+       /* If URL is a directory, add '/' */
+-      if (tptr[-1] != '/') {
++      if (!redirect_path && (tptr[-1] != '/')) {
+               if (is_directory(urlcopy + 1, 1, &sb)) {
+                       found_moved_temporarily = urlcopy;
+               }
+@@ -2004,7 +2015,9 @@
  #endif
  
  enum {
@@ -74,20 +81,18 @@ Index: busybox-1.4.2/networking/httpd.c
        d_opt_decode_url,
        h_opt_home_httpd,
        USE_FEATURE_HTTPD_ENCODE_URL_STR(e_opt_encode_url,)
-@@ -1919,7 +1930,7 @@
-       OPT_FOREGROUND  = 1 << p_opt_foreground,
- };
--static const char httpd_opts[] = "c:d:h:"
-+static const char httpd_opts[] = "R:H:c:d:h:"
-       USE_FEATURE_HTTPD_ENCODE_URL_STR("e:")
-       USE_FEATURE_HTTPD_BASIC_AUTH("r:")
-       USE_FEATURE_HTTPD_AUTH_MD5("m:")
-@@ -1951,6 +1962,7 @@
-       config->ContentLength = -1;
-       opt = getopt32(argc, argv, httpd_opts,
-+                      &(config->redirectPath), &(config->redirectHost),
-                       &(config->configFile), &url_for_decode, &home_httpd
+@@ -2053,12 +2066,13 @@
+       /* We do not "absolutize" path given by -h (home) opt.
+        * If user gives relative path in -h, $SCRIPT_FILENAME can end up
+        * relative too. */
+-      opt = getopt32(argv, "c:d:h:"
++      opt = getopt32(argv, "R:H:c:d:h:"
+                       USE_FEATURE_HTTPD_ENCODE_URL_STR("e:")
+                       USE_FEATURE_HTTPD_BASIC_AUTH("r:")
+                       USE_FEATURE_HTTPD_AUTH_MD5("m:")
+                       USE_FEATURE_HTTPD_SETUID("u:")
+                       "p:ifv",
++                      &redirect_path, &redirect_host,
+                       &configFile, &url_for_decode, &home_httpd
                        USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode)
-                       USE_FEATURE_HTTPD_BASIC_AUTH(, &(config->realm))
+                       USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm)
diff --git a/package/busybox/patches/360-awk_multi_f.patch b/package/busybox/patches/360-awk_multi_f.patch
new file mode 100644 (file)
index 0000000..8f738a6
--- /dev/null
@@ -0,0 +1,72 @@
+Index: busybox-1.7.2/editors/awk.c
+===================================================================
+--- busybox-1.7.2.orig/editors/awk.c   2007-10-04 19:57:46.859742242 +0200
++++ busybox-1.7.2/editors/awk.c        2007-10-05 02:20:02.910793305 +0200
+@@ -2757,6 +2757,7 @@
+ {
+       unsigned opt;
+       char *opt_F, *opt_W;
++      llist_t *opt_f = NULL;
+       llist_t *opt_v = NULL;
+       int i, j, flen;
+       var *v;
+@@ -2816,8 +2817,8 @@
+                       *s1 = '=';
+               }
+       }
+-      opt_complementary = "v::";
+-      opt = getopt32(argv, "F:v:f:W:", &opt_F, &opt_v, &g_progname, &opt_W);
++      opt_complementary = "v::f::";
++      opt = getopt32(argv, "F:v:f:W:", &opt_F, &opt_v, &opt_f, &opt_W);
+       argv += optind;
+       argc -= optind;
+       if (opt & 0x1)
+@@ -2826,25 +2827,31 @@
+               if (!is_assignment(llist_pop(&opt_v)))
+                       bb_show_usage();
+       }
+-      if (opt & 0x4) { // -f
+-              char *s = s; /* die, gcc, die */
+-              FILE *from_file = afopen(g_progname, "r");
+-              /* one byte is reserved for some trick in next_token */
+-              if (fseek(from_file, 0, SEEK_END) == 0) {
+-                      flen = ftell(from_file);
+-                      s = xmalloc(flen + 4);
+-                      fseek(from_file, 0, SEEK_SET);
+-                      i = 1 + fread(s + 1, 1, flen, from_file);
+-              } else {
+-                      for (i = j = 1; j > 0; i += j) {
+-                              s = xrealloc(s, i + 4096);
+-                              j = fread(s + i, 1, 4094, from_file);
++      if (opt_f != NULL) { // -f
++              while (opt_f != NULL) {
++                      char *s = NULL;
++                      FILE *from_file;
++
++                      g_progname = opt_f->data;
++                      from_file = afopen(g_progname, "r");
++                      /* one byte is reserved for some trick in next_token */
++                      if (fseek(from_file, 0, SEEK_END) == 0) {
++                              flen = ftell(from_file);
++                              s = xmalloc(flen + 4);
++                              fseek(from_file, 0, SEEK_SET);
++                              i = 1 + fread(s + 1, 1, flen, from_file);
++                      } else {
++                              for (i = j = 1; j > 0; i += j) {
++                                      s = xrealloc(s, i + 4096);
++                                      j = fread(s + i, 1, 4094, from_file);
++                              }
+                       }
++                      s[i] = '\0';
++                      fclose(from_file);
++                      parse_program(s + 1);
++                      free(s);
++                      opt_f = opt_f->link;
+               }
+-              s[i] = '\0';
+-              fclose(from_file);
+-              parse_program(s + 1);
+-              free(s);
+       } else { // no -f: take program from 1st parameter
+               if (!argc)
+                       bb_show_usage();
diff --git a/package/busybox/patches/400-revert_awk_getopt.patch b/package/busybox/patches/400-revert_awk_getopt.patch
deleted file mode 100644 (file)
index 33c6790..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-Index: busybox-1.4.2/editors/awk.c
-===================================================================
---- busybox-1.4.2.orig/editors/awk.c   2007-06-15 23:43:26.460690280 +0200
-+++ busybox-1.4.2/editors/awk.c        2007-06-15 23:45:26.283474448 +0200
-@@ -2639,14 +2639,13 @@
- int awk_main(int argc, char **argv)
- {
--      unsigned opt;
--      char *opt_F, *opt_v, *opt_W;
-       int i, j, flen;
-       var *v;
-       var tv;
-       char **envp;
-       char *vnames = (char *)vNames; /* cheat */
-       char *vvalues = (char *)vValues;
-+      int c;
-       /* Undo busybox.c, or else strtod may eat ','! This breaks parsing:
-        * $1,$2 == '$1,' '$2', NOT '$1' ',' '$2' */
-@@ -2694,40 +2693,56 @@
-               free(s);
-       }
--      opt = getopt32(argc, argv, "F:v:f:W:", &opt_F, &opt_v, &programname, &opt_W);
--      argv += optind;
--      argc -= optind;
--      if (opt & 0x1) setvar_s(V[FS], opt_F); // -F
--      if (opt & 0x2) if (!is_assignment(opt_v)) bb_show_usage(); // -v
--      if (opt & 0x4) { // -f
--              char *s = s; /* die, gcc, die */
--              FILE *from_file = afopen(programname, "r");
--              /* one byte is reserved for some trick in next_token */
--              if (fseek(from_file, 0, SEEK_END) == 0) {
--                      flen = ftell(from_file);
--                      s = xmalloc(flen + 4);
--                      fseek(from_file, 0, SEEK_SET);
--                      i = 1 + fread(s + 1, 1, flen, from_file);
--              } else {
--                      for (i = j = 1; j > 0; i += j) {
--                              s = xrealloc(s, i + 4096);
--                              j = fread(s + i, 1, 4094, from_file);
-+      programname = NULL;
-+      while((c = getopt(argc, argv, "F:v:f:W:")) != EOF) {
-+              switch (c) {
-+                      case 'F':
-+                              setvar_s(V[FS], optarg);
-+                              break;
-+                      case 'v':
-+                              if (! is_assignment(optarg))
-+                                      bb_show_usage();
-+                              break;
-+                      case 'f': {
-+                              FILE *F = afopen(programname = optarg, "r");
-+                              char *s = NULL;
-+                              /* one byte is reserved for some trick in next_token */
-+                              if (fseek(F, 0, SEEK_END) == 0) {
-+                                      flen = ftell(F);
-+                                      s = (char *)xmalloc(flen+4);
-+                                      fseek(F, 0, SEEK_SET);
-+                                      i = 1 + fread(s+1, 1, flen, F);
-+                              } else {
-+                                      for (i=j=1; j>0; i+=j) {
-+                                              s = (char *)xrealloc(s, i+4096);
-+                                              j = fread(s+i, 1, 4094, F);
-+                                      }
-+                              }
-+                              s[i] = '\0';
-+                              fclose(F);
-+                              parse_program(s+1);
-+                              free(s);
-+                              break;
-                       }
-+                      case 'W':
-+                              bb_error_msg("Warning: unrecognized option '-W %s' ignored\n", optarg);
-+                              break;
-+
-+                      default:
-+                              bb_show_usage();
-               }
--              s[i] = '\0';
--              fclose(from_file);
--              parse_program(s + 1);
--              free(s);
--      } else { // no -f: take program from 1st parameter
-+      }
-+      argc -= optind;
-+      argv += optind;
-+
-+      if (!programname) {
-               if (!argc)
-                       bb_show_usage();
-               programname = "cmd. line";
-               parse_program(*argv++);
-               argc--;
-       }
--      if (opt & 0x8) // -W
--              bb_error_msg("warning: unrecognized option '-W %s' ignored", opt_W);
--
-+      
-       /* fill in ARGV array */
-       setvar_i(V[ARGC], argc + 1);
-       setari_u(V[ARGV], 0, "awk");
index f563e10..6506f27 100644 (file)
@@ -1,8 +1,8 @@
-Index: busybox-1.4.2/include/platform.h
+Index: busybox-1.7.2/include/platform.h
 ===================================================================
---- busybox-1.4.2.orig/include/platform.h      2007-06-04 13:21:32.055103552 +0200
-+++ busybox-1.4.2/include/platform.h   2007-06-04 13:21:35.387596936 +0200
-@@ -128,9 +128,11 @@
+--- busybox-1.7.2.orig/include/platform.h      2007-09-03 13:48:46.000000000 +0200
++++ busybox-1.7.2/include/platform.h   2007-10-04 15:20:58.301274440 +0200
+@@ -137,9 +137,11 @@
  # include <netinet/in.h>
  #endif
  
@@ -14,30 +14,20 @@ Index: busybox-1.4.2/include/platform.h
  
  /* ---- Compiler dependent settings ------------------------- */
  #if (defined __digital__ && defined __unix__)
-@@ -161,7 +163,7 @@
+@@ -179,7 +181,7 @@
  #define HAVE_STDINT_H
  #else
  /* Largest integral types.  */
 -#if __BIG_ENDIAN__
 +#if __BIG_ENDIAN__ && !__APPLE__
- typedef long int                intmax_t;
- typedef unsigned long int       uintmax_t;
+ typedef long                intmax_t;
+ typedef unsigned long       uintmax_t;
  #else
-Index: busybox-1.4.2/include/libbb.h
+Index: busybox-1.7.2/include/libbb.h
 ===================================================================
---- busybox-1.4.2.orig/include/libbb.h 2007-06-04 13:21:32.062102488 +0200
-+++ busybox-1.4.2/include/libbb.h      2007-06-04 13:21:35.388596784 +0200
-@@ -17,7 +17,9 @@
- #include <errno.h>
- #include <fcntl.h>
- #include <inttypes.h>
-+#ifndef __APPLE__
- #include <malloc.h>
-+#endif
- #include <netdb.h>
- #include <setjmp.h>
- #include <signal.h>
-@@ -30,7 +32,9 @@
+--- busybox-1.7.2.orig/include/libbb.h 2007-09-16 20:48:10.000000000 +0200
++++ busybox-1.7.2/include/libbb.h      2007-10-04 15:20:22.275221430 +0200
+@@ -31,7 +31,9 @@
  #include <sys/mman.h>
  #include <sys/socket.h>
  #include <sys/stat.h>
index 98f094e..cfbbed6 100644 (file)
@@ -1,26 +1,18 @@
-Index: busybox-1.4.2/networking/httpd.c
+Index: busybox-1.7.2/networking/httpd.c
 ===================================================================
---- busybox-1.4.2.orig/networking/httpd.c      2007-06-04 13:21:35.006654848 +0200
-+++ busybox-1.4.2/networking/httpd.c   2007-06-04 13:21:35.585566840 +0200
-@@ -1231,7 +1231,7 @@
-                                * "chopped up into small chunks" syndrome here */
-                               rbuf[count] = '\0';
-                               /* check to see if the user script added headers */
--#define HTTP_200 "HTTP/1.0 200 OK\r\n\r\n"
-+#define HTTP_200 "HTTP/1.0 200 OK\r\n"
-                               if (memcmp(rbuf, HTTP_200, 4) != 0) {
-                                       /* there is no "HTTP", do it ourself */
-                                       full_write(s, HTTP_200, sizeof(HTTP_200)-1);
-@@ -1242,9 +1242,9 @@
-                                * echo -en "Location: http://www.busybox.net\r\n"
-                                * echo -en "\r\n"
-                                */
--                              //if (!strstr(rbuf, "ontent-")) {
--                              //      full_write(s, "Content-type: text/plain\r\n\r\n", 28);
--                              //}
-+                              if (!strstr(rbuf, "ontent-")) {
-+                                      full_write(s, "Content-type: text/plain\r\n\r\n", 28);
-+                              }
-                               firstLine = 0;
-                       }
-                       if (full_write(s, rbuf, count) != count)
+--- busybox-1.7.2.orig/networking/httpd.c      2007-10-04 15:06:51.993046080 +0200
++++ busybox-1.7.2/networking/httpd.c   2007-10-04 15:25:10.815664410 +0200
+@@ -1314,10 +1314,10 @@
+                                               if (full_write(1, HTTP_200, sizeof(HTTP_200)-1) != sizeof(HTTP_200)-1)
+                                                       break;
+                                       }
+-                                      /* Commented out:
+-                                      if (!strstr(rbuf, "ontent-")) {
+-                                              full_write(s, "Content-type: text/plain\r\n\r\n", 28);
++                                      if (!strstr(rbuf, "ontent-") && !strstr(rbuf, "ocation:")) {
++                                              full_write(1, "Content-type: text/plain\r\n\r\n", 28);
+                                       }
++                                      /* Previously commented out:
+                                        * Counter-example of valid CGI without Content-type:
+                                        * echo -en "HTTP/1.0 302 Found\r\n"
+                                        * echo -en "Location: http://www.busybox.net\r\n"
diff --git a/package/busybox/patches/420-httpd_sendcgi_fix.patch b/package/busybox/patches/420-httpd_sendcgi_fix.patch
deleted file mode 100644 (file)
index 9998cc2..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-Index: busybox-1.4.2/networking/httpd.c
-===================================================================
---- busybox-1.4.2.orig/networking/httpd.c      2007-06-04 13:21:35.585566840 +0200
-+++ busybox-1.4.2/networking/httpd.c   2007-06-04 13:21:35.775537960 +0200
-@@ -1218,9 +1218,10 @@
- #if PIPESIZE >= MAX_MEMORY_BUFF
- # error "PIPESIZE >= MAX_MEMORY_BUFF"
- #endif
--                      /* NB: was safe_read. If it *has to be* safe_read, */
--                      /* please explain why in this comment... */
--                      count = full_read(inFd, rbuf, PIPESIZE);
-+                      /* reverted back to safe_read, otherwise httpd may block if the */
-+                      /* cgi-script outputs page date before it has fully received all */
-+                      /* (eg POST) data */
-+                      count = safe_read(inFd, rbuf, PIPESIZE);
-                       if (count == 0)
-                               break;  /* closed */
-                       if (count < 0)
index 8ef70b8..b3eb308 100644 (file)
@@ -1,29 +1,12 @@
-Index: busybox-1.4.2/networking/httpd.c
+Index: busybox-1.7.2/networking/httpd.c
 ===================================================================
---- busybox-1.4.2.orig/networking/httpd.c      2007-06-04 13:21:35.775537960 +0200
-+++ busybox-1.4.2/networking/httpd.c   2007-06-04 13:21:36.144481872 +0200
-@@ -102,6 +102,7 @@
- static const char default_path_httpd_conf[] = "/etc";
- static const char httpd_conf[] = "httpd.conf";
- static const char home[] = "./";
-+static const char *home_httpd = home;
- #define TIMEOUT 60
-@@ -1505,6 +1506,8 @@
+--- busybox-1.7.2.orig/networking/httpd.c      2007-10-04 15:25:10.815664410 +0200
++++ busybox-1.7.2/networking/httpd.c   2007-10-04 15:31:22.936870392 +0200
+@@ -1616,6 +1616,7 @@
  #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
        int credentials = -1;  /* if not required this is Ok */
  #endif
-+      
 +      xchdir(home_httpd);
  
-       sa.sa_handler = handle_sigalrm;
-       sigemptyset(&sa.sa_mask);
-@@ -1942,7 +1945,6 @@
- int httpd_main(int argc, char *argv[])
- {
-       unsigned opt;
--      const char *home_httpd = home;
-       char *url_for_decode;
-       USE_FEATURE_HTTPD_ENCODE_URL_STR(const char *url_for_encode;)
-       const char *s_port;
+       /* Allocation of iobuf is postponed until now
+        * (IOW, server process doesn't need to waste 8k) */
diff --git a/package/busybox/patches/440-usage_compressed_fix.patch b/package/busybox/patches/440-usage_compressed_fix.patch
deleted file mode 100644 (file)
index c9e29ce..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-Index: busybox-1.4.2/applets/usage_compressed
-===================================================================
---- busybox-1.4.2.orig/applets/usage_compressed        2007-06-04 13:21:31.952119208 +0200
-+++ busybox-1.4.2/applets/usage_compressed     2007-06-04 13:21:36.331453448 +0200
-@@ -14,6 +14,6 @@
- echo 'static const char packed_usage[] = '
- "$loc/usage" | bzip2 -1 | od -v -t x1 \
--| $SED -e 's/^[^ ]*//' -e 's/ \(..\)/\\x\1/g' -e 's/^\(.*\)$/"\1"/'
-+| $SED -e 's/^[^ ]*//' -e 's/ \([a-f0-9][a-f0-9]\)/\\x\1/g' -e 's/^\(.*\)$/"\1"/'
- echo ';'
- echo '#define SIZEOF_usage_messages' `expr 0 + $sz`
diff --git a/package/busybox/patches/450-truncated_ping_results.patch b/package/busybox/patches/450-truncated_ping_results.patch
deleted file mode 100644 (file)
index 34582c2..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-Index: busybox-1.4.2/networking/ping.c
-===================================================================
---- busybox-1.4.2.orig/networking/ping.c       2007-06-04 13:21:31.931122400 +0200
-+++ busybox-1.4.2/networking/ping.c    2007-06-04 13:21:36.518425024 +0200
-@@ -70,7 +70,7 @@
-       struct sockaddr_in pingaddr;
-       struct icmp *pkt;
-       int pingsock, c;
--      char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
-+      char packet[datalen + ICMP_MINLEN + MAXIPLEN + MAXICMPLEN];
-       pingsock = create_icmp_socket();
-@@ -86,7 +86,7 @@
-       pkt->icmp_type = ICMP_ECHO;
-       pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet));
--      c = sendto(pingsock, packet, DEFDATALEN + ICMP_MINLEN, 0,
-+      c = sendto(pingsock, packet, datalen + ICMP_MINLEN, 0,
-                          (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));
-       if (c < 0) {
-@@ -274,6 +274,10 @@
-               ++nreceived;
-               tp = (struct timeval *) icmppkt->icmp_data;
-+              /* If packet is too short, results will be truncated */
-+              if (sz < (ICMP_MINLEN + sizeof(tv.tv_sec) + sizeof(tv.tv_usec)))
-+                      return;
-+
-               if ((tv.tv_usec -= tp->tv_usec) < 0) {
-                       --tv.tv_sec;
-                       tv.tv_usec += 1000000;
diff --git a/package/busybox/patches/450-usage_compressed_fix.patch b/package/busybox/patches/450-usage_compressed_fix.patch
new file mode 100644 (file)
index 0000000..3a9d2ad
--- /dev/null
@@ -0,0 +1,12 @@
+Index: busybox-1.7.2/applets/usage_compressed
+===================================================================
+--- busybox-1.7.2.orig/applets/usage_compressed        2007-09-03 13:48:55.000000000 +0200
++++ busybox-1.7.2/applets/usage_compressed     2007-10-04 15:32:54.578092727 +0200
+@@ -14,6 +14,6 @@
+ echo 'static const char packed_usage[] ALIGN1 = '
+ "$loc/usage" | bzip2 -1 | od -v -t x1 \
+-| $SED -e 's/^[^ ]*//' -e 's/  *\(..\)/\\x\1/g' -e 's/^\(.*\)$/"\1"/'
++| $SED -e 's/^[^ ]*//' -e 's/  *\([a-f0-9][a-f0-9]\)/\\x\1/g' -e 's/^\(.*\)$/"\1"/'
+ echo ';'
+ echo '#define SIZEOF_usage_messages' `expr 0 + $sz`
diff --git a/package/busybox/patches/460-httpd_cgi_bin.patch b/package/busybox/patches/460-httpd_cgi_bin.patch
deleted file mode 100644 (file)
index d21c518..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-Index: busybox-1.4.2/networking/httpd.c
-===================================================================
---- busybox-1.4.2.orig/networking/httpd.c      2007-06-21 18:12:06.791080496 +0200
-+++ busybox-1.4.2/networking/httpd.c   2007-06-21 18:14:48.914434000 +0200
-@@ -1715,8 +1715,8 @@
-               test = url + 1;      /* skip first '/' */
- #if ENABLE_FEATURE_HTTPD_CGI
--              if (strncmp(test, "cgi-bin", 7) == 0) {
--                      if (test[7] == '/' && test[8] == 0)
-+              if (strncmp(test, "cgi-bin/", 8) == 0) {
-+                      if (test[8] == 0)
-                               goto FORBIDDEN;     /* protect listing cgi-bin/ */
-                       sendCgi(url, prequest, length, cookie, content_type);
-                       break;
diff --git a/package/busybox/patches/460-truncated_ping_results.patch b/package/busybox/patches/460-truncated_ping_results.patch
new file mode 100644 (file)
index 0000000..e655acf
--- /dev/null
@@ -0,0 +1,40 @@
+Index: busybox-1.7.2/networking/ping.c
+===================================================================
+--- busybox-1.7.2.orig/networking/ping.c       2007-09-03 13:48:27.000000000 +0200
++++ busybox-1.7.2/networking/ping.c    2007-10-04 15:38:15.424376713 +0200
+@@ -91,7 +91,7 @@
+       struct sockaddr_in pingaddr;
+       struct icmp *pkt;
+       int pingsock, c;
+-      char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
++      char packet[datalen + ICMP_MINLEN + MAXIPLEN + MAXICMPLEN];
+       pingsock = create_icmp_socket();
+       pingaddr = lsa->sin;
+@@ -101,7 +101,7 @@
+       pkt->icmp_type = ICMP_ECHO;
+       pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet));
+-      c = xsendto(pingsock, packet, DEFDATALEN + ICMP_MINLEN,
++      c = xsendto(pingsock, packet, datalen + ICMP_MINLEN,
+                          (struct sockaddr *) &pingaddr, sizeof(pingaddr));
+       /* listen for replies */
+@@ -135,7 +135,7 @@
+       struct icmp6_hdr *pkt;
+       int pingsock, c;
+       int sockopt;
+-      char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
++      char packet[datalen + ICMP_MINLEN + MAXIPLEN + MAXICMPLEN];
+       pingsock = create_icmp6_socket();
+       pingaddr = lsa->sin6;
+@@ -147,7 +147,7 @@
+       sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
+       setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt));
+-      c = xsendto(pingsock, packet, DEFDATALEN + sizeof (struct icmp6_hdr),
++      c = xsendto(pingsock, packet, datalen + sizeof (struct icmp6_hdr),
+                          (struct sockaddr *) &pingaddr, sizeof(pingaddr));
+       /* listen for replies */
diff --git a/package/busybox/patches/470-insmod_search.patch b/package/busybox/patches/470-insmod_search.patch
new file mode 100644 (file)
index 0000000..26c5650
--- /dev/null
@@ -0,0 +1,488 @@
+Index: busybox-1.7.2/modutils/insmod.c
+===================================================================
+--- busybox-1.7.2.orig/modutils/insmod.c       2007-09-03 13:48:35.000000000 +0200
++++ busybox-1.7.2/modutils/insmod.c    2007-10-05 01:43:47.686834357 +0200
+@@ -61,19 +61,107 @@
+ #include "libbb.h"
+ #include <libgen.h>
+ #include <sys/utsname.h>
++#if ENABLE_FEATURE_2_6_MODULES
++#include <sys/mman.h>
++#include <asm/unistd.h>
++#include <sys/syscall.h>
++#endif
+ #if !ENABLE_FEATURE_2_4_MODULES && !ENABLE_FEATURE_2_6_MODULES
+ #undef ENABLE_FEATURE_2_4_MODULES
+ #define ENABLE_FEATURE_2_4_MODULES 1
+ #endif
+-#if !ENABLE_FEATURE_2_4_MODULES
+-#define insmod_ng_main insmod_main
++#if ENABLE_FEATURE_2_4_MODULES
++int insmod_main_24(int argc, char **argv);
+ #endif
+-
+ #if ENABLE_FEATURE_2_6_MODULES
+-extern int insmod_ng_main( int argc, char **argv);
++int insmod_main_26(int argc, char **argv);
+ #endif
++int insmod_main(int argc, char **argv);
++
++static char *g_filename = NULL;
++#define _PATH_MODULES "/lib/modules"
++
++static int check_module_name_match(const char *filename, struct stat *statbuf,
++                                 void *userdata, int depth)
++{
++      char *fullname = (char *) userdata;
++
++      if (fullname[0] == '\0')
++              return FALSE;
++      else {
++              char *tmp, *tmp1 = xstrdup(filename);
++              tmp = bb_get_last_path_component(tmp1);
++              if (strcmp(tmp, fullname) == 0) {
++                      free(tmp1);
++                      /* Stop searching if we find a match */
++                      g_filename = xstrdup(filename);
++                      return FALSE;
++              }
++              free(tmp1);
++      }
++      return TRUE;
++}
++
++static int find_module(char *filename)
++{
++      char *module_dir, real_module_dir[FILENAME_MAX];
++      int len, slen, ret = ENOENT, k_version;
++      struct utsname myuname;
++      const char *suffix;
++      struct stat st;
++
++      /* check the kernel version */
++      if ((uname(&myuname) != 0) || (myuname.release[0] != '2'))
++              return EINVAL;
++
++      k_version = myuname.release[2] - '0';
++#if ENABLE_FEATURE_2_4_MODULES
++      if (k_version <= 4)
++              suffix = ".o";
++      else
++#endif
++              suffix = ".ko";
++
++      len = strlen(filename);
++      slen = strlen(suffix);
++
++      /* check for suffix and absolute path first */
++      if ((len < slen + 2) || (strcmp(filename + len - slen, suffix) != 0)) {
++              filename = xasprintf("%s%s", filename, suffix);
++      } else {
++              filename = strdup(filename);
++              if ((stat(filename, &st) == 0) && S_ISREG(st.st_mode))
++                      return 0;
++      }
++
++      /* next: scan /lib/modules/<release> */
++      /* Jump through hoops in case /lib/modules/`uname -r`
++      * is a symlink.  We do not want recursive_action to
++      * follow symlinks, but we do want to follow the
++      * /lib/modules/`uname -r` dir, So resolve it ourselves
++      * if it is a link... */
++      module_dir = concat_path_file(_PATH_MODULES, myuname.release);
++      if (realpath(module_dir, real_module_dir) != NULL) {
++              free(module_dir);
++              module_dir = real_module_dir;
++      }
++
++      recursive_action(module_dir, ACTION_RECURSE,
++              check_module_name_match, 0, filename, 0);
++
++      /* Check if we have a complete path */
++      if (g_filename != NULL) {
++              if ((stat(g_filename, &st) == 0) && S_ISREG(st.st_mode))
++                      ret = 0;
++              else
++                      free(g_filename);
++      }
++      free(filename);
++
++      return ret;
++}
+ #if ENABLE_FEATURE_2_4_MODULES
+@@ -677,7 +765,6 @@
+ #endif
+-#define _PATH_MODULES "/lib/modules"
+ enum { STRVERSIONLEN = 64 };
+ /*======================================================================*/
+@@ -790,37 +877,6 @@
+ static int n_ext_modules_used;
+ extern int delete_module(const char *);
+-static char *m_filename;
+-static char *m_fullName;
+-
+-
+-/*======================================================================*/
+-
+-
+-static int check_module_name_match(const char *filename, struct stat *statbuf,
+-                              void *userdata, int depth)
+-{
+-      char *fullname = (char *) userdata;
+-
+-      if (fullname[0] == '\0')
+-              return FALSE;
+-      else {
+-              char *tmp, *tmp1 = xstrdup(filename);
+-              tmp = bb_get_last_path_component(tmp1);
+-              if (strcmp(tmp, fullname) == 0) {
+-                      free(tmp1);
+-                      /* Stop searching if we find a match */
+-                      m_filename = xstrdup(filename);
+-                      return FALSE;
+-              }
+-              free(tmp1);
+-      }
+-      return TRUE;
+-}
+-
+-
+-/*======================================================================*/
+-
+ static struct obj_file *arch_new_file(void)
+ {
+       struct arch_file *f;
+@@ -3952,33 +4008,35 @@
+ void print_load_map(struct obj_file *f);
+ #endif
+-int insmod_main( int argc, char **argv);
+-int insmod_main( int argc, char **argv)
++int insmod_main_24( int argc, char **argv)
+ {
+       char *opt_o, *arg1;
+       int len;
+       int k_crcs;
+-      char *tmp, *tmp1;
+       unsigned long m_size;
+       ElfW(Addr) m_addr;
+       struct obj_file *f;
+       struct stat st;
+       char *m_name = 0;
+-      int exit_status = EXIT_FAILURE;
++      int ret = EINVAL;
+       int m_has_modinfo;
+ #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
+       struct utsname uts_info;
+       char m_strversion[STRVERSIONLEN];
+       int m_version, m_crcs;
+ #endif
+-#if ENABLE_FEATURE_CLEAN_UP
+-      FILE *fp = 0;
+-#else
+-      FILE *fp;
+-#endif
+-      int k_version = 0;
++      FILE *fp = NULL;
++      int k_version;
+       struct utsname myuname;
++      /* check the kernel version */
++      if ((uname(&myuname) != 0) || (myuname.release[0] != '2'))
++              return EINVAL;
++
++      k_version = myuname.release[2] - '0';
++      if (k_version > 4)
++              return ENOTSUP;
++
+       /* Parse any options */
+       getopt32(argv, OPTION_STR, &opt_o);
+       arg1 = argv[optind];
+@@ -3987,110 +4045,18 @@
+               m_name = xstrdup(opt_o);
+       }
+-      if (arg1 == NULL) {
++      if (arg1 == NULL)
+               bb_show_usage();
+-      }
+-
+-      /* Grab the module name */
+-      tmp1 = xstrdup(arg1);
+-      tmp = basename(tmp1);
+-      len = strlen(tmp);
+-
+-      if (uname(&myuname) == 0) {
+-              if (myuname.release[0] == '2') {
+-                      k_version = myuname.release[2] - '0';
+-              }
+-      }
+-
+-#if ENABLE_FEATURE_2_6_MODULES
+-      if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
+-       && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
+-      ) {
+-              len -= 3;
+-              tmp[len] = '\0';
+-      } else
+-#endif
+-              if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
+-                      len -= 2;
+-                      tmp[len] = '\0';
+-              }
+-
+-
+-#if ENABLE_FEATURE_2_6_MODULES
+-      if (k_version > 4)
+-              m_fullName = xasprintf("%s.ko", tmp);
+-      else
+-#endif
+-              m_fullName = xasprintf("%s.o", tmp);
+-      if (!m_name) {
+-              m_name = tmp;
+-      } else {
+-              free(tmp1);
+-              tmp1 = 0;       /* flag for free(m_name) before exit() */
+-      }
+-
+-      /* Get a filedesc for the module.  Check we we have a complete path */
+-      if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
+-       || (fp = fopen(arg1, "r")) == NULL
+-      ) {
+-              /* Hmm.  Could not open it.  First search under /lib/modules/`uname -r`,
+-               * but do not error out yet if we fail to find it... */
+-              if (k_version) {        /* uname succeedd */
+-                      char *module_dir;
+-                      char *tmdn;
+-                      char real_module_dir[FILENAME_MAX];
+-
+-                      tmdn = concat_path_file(_PATH_MODULES, myuname.release);
+-                      /* Jump through hoops in case /lib/modules/`uname -r`
+-                       * is a symlink.  We do not want recursive_action to
+-                       * follow symlinks, but we do want to follow the
+-                       * /lib/modules/`uname -r` dir, So resolve it ourselves
+-                       * if it is a link... */
+-                      if (realpath(tmdn, real_module_dir) == NULL)
+-                              module_dir = tmdn;
+-                      else
+-                              module_dir = real_module_dir;
+-                      recursive_action(module_dir, ACTION_RECURSE,
+-                                      check_module_name_match, 0, m_fullName, 0);
+-                      free(tmdn);
+-              }
+-
+-              /* Check if we have found anything yet */
+-              if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL)) {
+-                      char module_dir[FILENAME_MAX];
+-
+-                      free(m_filename);
+-                      m_filename = 0;
+-                      if (realpath (_PATH_MODULES, module_dir) == NULL)
+-                              strcpy(module_dir, _PATH_MODULES);
+-                      /* No module found under /lib/modules/`uname -r`, this
+-                       * time cast the net a bit wider.  Search /lib/modules/ */
+-                      if (!recursive_action(module_dir, ACTION_RECURSE,
+-                                                  check_module_name_match, 0, m_fullName, 0)
+-                      ) {
+-                              if (m_filename == 0
+-                               || ((fp = fopen(m_filename, "r")) == NULL)
+-                              ) {
+-                                      bb_error_msg("%s: no module by that name found", m_fullName);
+-                                      goto out;
+-                              }
+-                      } else
+-                              bb_error_msg_and_die("%s: no module by that name found", m_fullName);
+-              }
+-      } else
+-              m_filename = xstrdup(arg1);
+-
+-      if (flag_verbose)
+-              printf("Using %s\n", m_filename);
++      ret = find_module(arg1);
++      if (ret)
++              goto out;
+-#if ENABLE_FEATURE_2_6_MODULES
+-      if (k_version > 4) {
+-              argv[optind] = m_filename;
+-              optind--;
+-              return insmod_ng_main(argc - optind, argv + optind);
++      fp = fopen(g_filename, "r");
++      if (!fp) {
++              ret = errno;
++              goto out;
+       }
+-#endif
+       f = obj_load(fp, LOADBITS);
+       if (f == NULL)
+@@ -4120,7 +4086,7 @@
+                               "\t%s was compiled for kernel version %s\n"
+                               "\twhile this kernel is version %s",
+                               flag_force_load ? "warning: " : "",
+-                              m_filename, m_strversion, uts_info.release);
++                              g_filename, m_strversion, uts_info.release);
+                       if (!flag_force_load)
+                               goto out;
+               }
+@@ -4173,7 +4139,7 @@
+       hide_special_symbols(f);
+ #if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+-      add_ksymoops_symbols(f, m_filename, m_name);
++      add_ksymoops_symbols(f, g_filename, m_name);
+ #endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
+       new_create_module_ksymtab(f);
+@@ -4220,8 +4186,7 @@
+       if (flag_print_load_map)
+               print_load_map(f);
+-      exit_status = EXIT_SUCCESS;
+-
++      ret = 0;
+ out:
+ #if ENABLE_FEATURE_CLEAN_UP
+       if (fp)
+@@ -4229,21 +4194,13 @@
+       free(tmp1);
+       if (!tmp1)
+               free(m_name);
+-      free(m_filename);
++      free(g_filename);
+ #endif
+       return exit_status;
+ }
+-
+-
+ #endif
+-
+ #if ENABLE_FEATURE_2_6_MODULES
+-
+-#include <sys/mman.h>
+-#include <asm/unistd.h>
+-#include <sys/syscall.h>
+-
+ /* We use error numbers in a loose translation... */
+ static const char *moderror(int err)
+ {
+@@ -4261,19 +4218,33 @@
+       }
+ }
+-int insmod_ng_main(int argc, char **argv);
+-int insmod_ng_main(int argc, char **argv)
++int insmod_main_26(int argc, char **argv)
+ {
+-      long ret;
+-      size_t len;
++      char *filename, *options;
++      struct utsname myuname;
++      int k_version;
+       int optlen;
++      size_t len;
+       void *map;
+-      char *filename, *options;
++      long ret = 0;
++
++      /* check the kernel version */
++      if ((uname(&myuname) != 0) || (myuname.release[0] != '2'))
++              return EINVAL;
++
++      k_version = myuname.release[2] - '0';
++      if (k_version <= 4)
++              return ENOTSUP;
+       filename = *++argv;
+       if (!filename)
+               bb_show_usage();
++      g_filename = filename;
++      ret = find_module(filename);
++      if (ret)
++              goto done;
++
+       /* Rest is options */
+       options = xzalloc(1);
+       optlen = 0;
+@@ -4283,36 +4254,46 @@
+               optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
+       }
+-#if 0
+-      /* Any special reason why mmap? It isn't performace critical... */
+-      int fd;
+-      struct stat st;
+-      unsigned long len;
+-      fd = xopen(filename, O_RDONLY);
+-      fstat(fd, &st);
+-      len = st.st_size;
+-      map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
+-      if (map == MAP_FAILED) {
+-              bb_perror_msg_and_die("cannot mmap '%s'", filename);
+-      }
+-
+-      /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
+-      if (map == NULL) {
+-              map = xmalloc(len);
+-              xread(fd, map, len);
+-      }
+-#else
+       len = MAXINT(ssize_t);
+-      map = xmalloc_open_read_close(filename, &len);
+-#endif
+-
++      map = xmalloc_open_read_close(g_filename, &len);
+       ret = syscall(__NR_init_module, map, len, options);
+       if (ret != 0) {
+               bb_perror_msg_and_die("cannot insert '%s': %s (%li)",
+-                              filename, moderror(errno), ret);
++                              g_filename, moderror(errno), ret);
+       }
++done:
++      if (g_filename && (g_filename != filename))
++              free(g_filename);
+-      return 0;
++      return ret;
+ }
+ #endif
++
++int insmod_main(int argc, char **argv)
++{
++      int ret;
++
++#if ENABLE_FEATURE_2_6_MODULES
++      ret = insmod_main_26(argc, argv);
++      if (ret != ENOTSUP)
++              goto done;
++#endif
++
++#if ENABLE_FEATURE_2_4_MODULES
++      ret = insmod_main_24(argc, argv);
++      if (ret != ENOTSUP)
++              goto done;
++#endif
++
++      fprintf(stderr, "Error: Kernel version not supported\n");
++      return 1;
++
++done:
++      if (ret) {
++              errno = ret;
++              bb_perror_msg("Loading module failed");
++              return ret;
++      } else
++              return 0;
++}
diff --git a/package/busybox/patches/500-ipkg.patch b/package/busybox/patches/500-ipkg.patch
new file mode 100644 (file)
index 0000000..a186162
--- /dev/null
@@ -0,0 +1,13753 @@
+Index: busybox-1.7.2/archival/Config.in
+===================================================================
+--- busybox-1.7.2.orig/archival/Config.in      2007-10-04 17:12:34.094845964 +0200
++++ busybox-1.7.2/archival/Config.in   2007-10-04 17:14:22.056998379 +0200
+@@ -121,6 +121,15 @@
+         gzip is used to compress files.
+         It's probably the most widely used UNIX compression program.
++config IPKG
++      bool "ipkg"
++      default n
++      select MD5SUM
++      select WGET
++      select DIFF
++      help
++        ipkg is the itsy package management system.
++
+ config RPM2CPIO
+       bool "rpm2cpio"
+       default n
+Index: busybox-1.7.2/archival/dpkg.c
+===================================================================
+--- busybox-1.7.2.orig/archival/dpkg.c 2007-10-04 17:12:34.102846422 +0200
++++ busybox-1.7.2/archival/dpkg.c      2007-10-04 17:14:22.060998604 +0200
+@@ -1455,6 +1455,10 @@
+       return ar_handle->sub_archive->buffer;
+ }
++/*
++
++// moved to data_extract_all.c
++
+ static void data_extract_all_prefix(archive_handle_t *archive_handle)
+ {
+       char *name_ptr = archive_handle->file_header->name;
+@@ -1466,6 +1470,8 @@
+       }
+ }
++*/
++
+ static void unpack_package(deb_file_t *deb_file)
+ {
+       const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
+Index: busybox-1.7.2/archival/ipkg.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/ipkg.c      2007-10-04 17:14:22.084999973 +0200
+@@ -0,0 +1,26 @@
++/* ipkg.c - the itsy package management system
++
++   Florina Boor
++
++   Copyright (C) 2003 kernel concepts
++
++   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, 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.
++   
++   ipkg command line frontend using libipkg
++   
++*/
++
++#include "libipkg/libipkg.h"
++
++int ipkg_main(int argc, char **argv)
++{
++      return ipkg_op(argc, argv);
++}
+Index: busybox-1.7.2/archival/Kbuild
+===================================================================
+--- busybox-1.7.2.orig/archival/Kbuild 2007-10-04 17:12:34.110846879 +0200
++++ busybox-1.7.2/archival/Kbuild      2007-10-04 17:14:22.109001341 +0200
+@@ -15,6 +15,7 @@
+ lib-$(CONFIG_DPKG_DEB)                += dpkg_deb.o
+ lib-$(CONFIG_GUNZIP)          += bbunzip.o
+ lib-$(CONFIG_GZIP)            += gzip.o bbunzip.o
++lib-$(CONFIG_IPKG)            += ipkg.o
+ lib-$(CONFIG_RPM2CPIO)                += rpm2cpio.o
+ lib-$(CONFIG_RPM)             += rpm.o
+ lib-$(CONFIG_TAR)             += tar.o
+Index: busybox-1.7.2/archival/libipkg/args.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/args.c      2007-10-04 17:14:22.145003392 +0200
+@@ -0,0 +1,242 @@
++/* args.c - parse command-line args
++ 
++  Carl D. Worth
++
++  Copyright 2001 University of Southern California
++ 
++  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, 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.
++ */
++
++#include <getopt.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++
++#include "ipkg.h"
++#include "ipkg_message.h"
++
++#include "args.h"
++#include "sprintf_alloc.h"
++
++#include "libbb.h"
++
++
++static void print_version(void);
++
++enum long_args_opt
++{
++     ARGS_OPT_FORCE_DEFAULTS = 129,
++     ARGS_OPT_FORCE_DEPENDS,
++     ARGS_OPT_FORCE_OVERWRITE,
++     ARGS_OPT_FORCE_DOWNGRADE,
++     ARGS_OPT_FORCE_REINSTALL,
++     ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES,
++     ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES,
++     ARGS_OPT_FORCE_SPACE,
++     ARGS_OPT_NOACTION,
++     ARGS_OPT_NODEPS,
++     ARGS_OPT_VERBOSE_WGET,
++     ARGS_OPT_VERBOSITY,
++     ARGS_OPT_MULTIPLE_PROVIDERS
++};
++
++int args_init(args_t *args)
++{
++     char *conf_file_dir;
++
++     memset(args, 0, sizeof(args_t));
++
++     args->dest = ARGS_DEFAULT_DEST;
++
++     conf_file_dir = getenv("IPKG_CONF_DIR");
++     if (conf_file_dir == NULL || conf_file_dir[0] == '\0') {
++        conf_file_dir = ARGS_DEFAULT_CONF_FILE_DIR;
++     }
++     sprintf_alloc(&args->conf_file, "%s/%s", conf_file_dir,
++                 ARGS_DEFAULT_CONF_FILE_NAME);
++
++     args->force_defaults = ARGS_DEFAULT_FORCE_DEFAULTS;
++     args->force_depends = ARGS_DEFAULT_FORCE_DEPENDS;
++     args->force_overwrite = ARGS_DEFAULT_FORCE_OVERWRITE;
++     args->force_downgrade = ARGS_DEFAULT_FORCE_DOWNGRADE;
++     args->force_reinstall = ARGS_DEFAULT_FORCE_REINSTALL;
++     args->force_removal_of_dependent_packages = ARGS_DEFAULT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES;
++     args->force_removal_of_essential_packages = ARGS_DEFAULT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES;
++     args->noaction = ARGS_DEFAULT_NOACTION;
++     args->nodeps = ARGS_DEFAULT_NODEPS;
++     args->verbose_wget = ARGS_DEFAULT_VERBOSE_WGET;
++     args->verbosity = ARGS_DEFAULT_VERBOSITY;
++     args->offline_root = ARGS_DEFAULT_OFFLINE_ROOT;
++     args->offline_root_pre_script_cmd = ARGS_DEFAULT_OFFLINE_ROOT_PRE_SCRIPT_CMD;
++     args->offline_root_post_script_cmd = ARGS_DEFAULT_OFFLINE_ROOT_POST_SCRIPT_CMD;
++     args->multiple_providers = 0;
++     args->nocheckfordirorfile = 0;
++     args->noreadfeedsfile = 0;
++
++     return 1;
++}
++
++void args_deinit(args_t *args)
++{
++     free(args->conf_file);
++     args->conf_file = NULL;
++}
++
++int args_parse(args_t *args, int argc, char *argv[])
++{
++     int c;
++     int option_index = 0;
++     int parse_err = 0;
++     static struct option long_options[] = {
++        {"query-all", 0, 0, 'A'},
++        {"conf-file", 1, 0, 'f'},
++        {"conf", 1, 0, 'f'},
++        {"dest", 1, 0, 'd'},
++        {"force-defaults", 0, 0, ARGS_OPT_FORCE_DEFAULTS},
++        {"force_defaults", 0, 0, ARGS_OPT_FORCE_DEFAULTS},
++        {"force-depends", 0, 0, ARGS_OPT_FORCE_DEPENDS},
++        {"force_depends", 0, 0, ARGS_OPT_FORCE_DEPENDS},
++        {"force-overwrite", 0, 0, ARGS_OPT_FORCE_OVERWRITE},
++        {"force_overwrite", 0, 0, ARGS_OPT_FORCE_OVERWRITE},
++        {"force_downgrade", 0, 0, ARGS_OPT_FORCE_DOWNGRADE},
++        {"force-downgrade", 0, 0, ARGS_OPT_FORCE_DOWNGRADE},
++        {"force-reinstall", 0, 0, ARGS_OPT_FORCE_REINSTALL},
++        {"force_reinstall", 0, 0, ARGS_OPT_FORCE_REINSTALL},
++        {"force-space", 0, 0, ARGS_OPT_FORCE_SPACE},
++        {"force_space", 0, 0, ARGS_OPT_FORCE_SPACE},
++        {"recursive", 0, 0,
++         ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES},
++        {"force-removal-of-dependent-packages", 0, 0,
++         ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES},
++        {"force_removal_of_dependent_packages", 0, 0,
++         ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES},
++        {"force-removal-of-essential-packages", 0, 0,
++         ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES},
++        {"force_removal_of_essential_packages", 0, 0,
++         ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES},
++        {"multiple-providers", 0, 0, ARGS_OPT_MULTIPLE_PROVIDERS},
++        {"multiple_providers", 0, 0, ARGS_OPT_MULTIPLE_PROVIDERS},
++        {"noaction", 0, 0, ARGS_OPT_NOACTION},
++        {"nodeps", 0, 0, ARGS_OPT_NODEPS},
++        {"offline", 1, 0, 'o'},
++        {"offline-root", 1, 0, 'o'},
++        {"test", 0, 0, ARGS_OPT_NOACTION},
++        {"tmp-dir", 1, 0, 't'},
++        {"verbose-wget", 0, 0, ARGS_OPT_VERBOSE_WGET},
++        {"verbose_wget", 0, 0, ARGS_OPT_VERBOSE_WGET},
++        {"verbosity", 2, 0, 'V'},
++        {"version", 0, 0, 'v'},
++        {0, 0, 0, 0}
++     };
++
++     while (1) {
++        c = getopt_long_only(argc, argv, "Ad:f:no:t:vV:", long_options, &option_index);
++        if (c == -1)
++             break;
++
++        switch (c) {
++        case 'A':
++             args->query_all = 1;
++             break;
++        case 'd':
++             args->dest = optarg;
++             break;
++        case 'f':
++             free(args->conf_file);
++             args->conf_file = strdup(optarg);
++             break;
++        case 'o':
++             args->offline_root = optarg;
++             break;
++        case 'n':
++             args->noaction = 1;
++             break;
++        case 't':
++             args->tmp_dir = strdup(optarg);
++             break;
++        case 'v':
++             print_version();
++             exit(0);
++        case 'V':
++        case ARGS_OPT_VERBOSITY:
++             if (optarg)
++                  args->verbosity = atoi(optarg);
++             else
++                  args->verbosity += 1;
++             break;
++        case ARGS_OPT_FORCE_DEFAULTS:
++             args->force_defaults = 1;
++             break;
++        case ARGS_OPT_FORCE_DEPENDS:
++             args->force_depends = 1;
++             break;
++        case ARGS_OPT_FORCE_OVERWRITE:
++             args->force_overwrite = 1;
++             break;
++        case ARGS_OPT_FORCE_DOWNGRADE:
++             args->force_downgrade = 1;
++             break;
++        case ARGS_OPT_FORCE_REINSTALL:
++             args->force_reinstall = 1;
++             break;
++        case ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES:
++             args->force_removal_of_essential_packages = 1;
++             break;
++        case ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES:
++             args->force_removal_of_dependent_packages = 1;
++             break;
++        case ARGS_OPT_FORCE_SPACE:
++             args->force_space = 1;
++             break;
++        case ARGS_OPT_VERBOSE_WGET:
++             args->verbose_wget = 1;
++             break;
++        case ARGS_OPT_MULTIPLE_PROVIDERS:
++             args->multiple_providers = 1;
++             break;
++        case ARGS_OPT_NODEPS:
++             args->nodeps = 1;
++             break;
++        case ARGS_OPT_NOACTION:
++             args->noaction = 1;
++             break;
++        case ':':
++             parse_err++;
++             break;
++        case '?':
++             parse_err++;
++             break;
++        default:
++             bb_error_msg("Confusion: getopt_long returned %d\n", c);
++        }
++     }
++    
++     if (parse_err) {
++        return -parse_err;
++     } else {
++        return optind;
++     }
++}
++
++void args_usage(char *complaint)
++{
++     if (complaint) {
++          bb_error_msg("%s\n", complaint);
++     }
++     print_version();
++     bb_show_usage();
++     exit(1);
++}
++
++static void print_version(void)
++{
++      bb_error_msg("version %s\n", IPKG_VERSION);
++}
+Index: busybox-1.7.2/archival/libipkg/args.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/args.h      2007-10-04 17:14:22.173004992 +0200
+@@ -0,0 +1,72 @@
++/* args.h - parse command-line args
++
++  Carl D. Worth
++
++  Copyright 2001 University of Southern California
++ 
++  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, 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.
++*/
++
++#ifndef ARGS_H
++#define ARGS_H
++
++struct args
++{
++    char *conf_file;
++    char *dest;
++    char *tmp_dir;
++    int force_defaults;
++    int force_depends;
++    int force_overwrite;
++    int force_downgrade;
++    int force_reinstall;
++    int force_removal_of_essential_packages;
++    int force_removal_of_dependent_packages;
++    int force_space;
++    int noaction;
++    int nodeps;
++    int multiple_providers;
++    int query_all;
++    int verbose_wget;
++    int verbosity;
++    int nocheckfordirorfile;
++    int noreadfeedsfile;
++    char *offline_root;
++    char *offline_root_pre_script_cmd;
++    char *offline_root_post_script_cmd;
++};
++typedef struct args args_t;
++
++#define ARGS_DEFAULT_CONF_FILE_DIR "/etc"
++#define ARGS_DEFAULT_CONF_FILE_NAME "ipkg.conf"
++#define ARGS_DEFAULT_DEST NULL
++#define ARGS_DEFAULT_FORCE_DEFAULTS 0
++#define ARGS_DEFAULT_FORCE_DEPENDS 0
++#define ARGS_DEFAULT_FORCE_OVERWRITE 0 
++#define ARGS_DEFAULT_FORCE_DOWNGRADE 0 
++#define ARGS_DEFAULT_FORCE_REINSTALL 0
++#define ARGS_DEFAULT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES 0
++#define ARGS_DEFAULT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES 0
++#define ARGS_DEFAULT_FORCE_SPACE 0
++#define ARGS_DEFAULT_OFFLINE_ROOT NULL
++#define ARGS_DEFAULT_OFFLINE_ROOT_PRE_SCRIPT_CMD NULL
++#define ARGS_DEFAULT_OFFLINE_ROOT_POST_SCRIPT_CMD NULL
++#define ARGS_DEFAULT_NOACTION 0
++#define ARGS_DEFAULT_NODEPS 0
++#define ARGS_DEFAULT_VERBOSE_WGET 0
++#define ARGS_DEFAULT_VERBOSITY 1
++
++int args_init(args_t *args);
++void args_deinit(args_t *args);
++int args_parse(args_t *args, int argc, char *argv[]);
++void args_usage(char *complaint);
++
++#endif
+Index: busybox-1.7.2/archival/libipkg/conffile.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/conffile.c  2007-10-04 17:14:22.249009320 +0200
+@@ -0,0 +1,64 @@
++/* conffile.c - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#include <string.h>
++#include <stdlib.h>
++
++#include "ipkg.h"
++#include "ipkg_message.h"
++
++#include "conffile.h"
++#include "file_util.h"
++#include "sprintf_alloc.h"
++
++int conffile_init(conffile_t *conffile, const char *file_name, const char *md5sum)
++{
++    return nv_pair_init(conffile, file_name, md5sum);
++}
++
++void conffile_deinit(conffile_t *conffile)
++{
++    nv_pair_deinit(conffile);
++}
++
++int conffile_has_been_modified(ipkg_conf_t *conf, conffile_t *conffile)
++{
++    char *md5sum;
++    char *filename = conffile->name;
++    char *root_filename;
++    int ret;
++
++    if (conffile->value == NULL) {
++       ipkg_message(conf, IPKG_NOTICE, "%s: conffile %s has no md5sum\n", __FUNCTION__, conffile->name);
++       return 1;
++    }
++
++    root_filename = root_filename_alloc(conf, filename);
++
++    md5sum = file_md5sum_alloc(root_filename);
++
++    ret = strcmp(md5sum, conffile->value);
++    if (ret) {
++      ipkg_message(conf, IPKG_NOTICE, "%s: conffile %s: \t\nold md5=%s \t\nnew md5=%s\n", __FUNCTION__,
++              conffile->name, md5sum, conffile->value);
++    }
++
++    free(root_filename);
++    free(md5sum);
++
++    return ret;
++}
+Index: busybox-1.7.2/archival/libipkg/conffile.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/conffile.h  2007-10-04 17:14:22.277010917 +0200
+@@ -0,0 +1,30 @@
++/* conffile.h - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#ifndef CONFFILE_H
++#define CONFFILE_H
++
++#include "nv_pair.h"
++
++typedef struct nv_pair conffile_t;
++
++int conffile_init(conffile_t *conffile, const char *file_name, const char *md5sum);
++void conffile_deinit(conffile_t *conffile);
++int conffile_has_been_modified(struct ipkg_conf *conf, conffile_t *conffile);
++
++#endif
++
+Index: busybox-1.7.2/archival/libipkg/conffile_list.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/conffile_list.c     2007-10-04 17:14:22.301012282 +0200
+@@ -0,0 +1,47 @@
++/* conffile_list.c - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#include "ipkg.h"
++
++#include "conffile_list.h"
++
++int conffile_list_init(conffile_list_t *list)
++{
++    return nv_pair_list_init(list);
++}
++
++void conffile_list_deinit(conffile_list_t *list)
++{
++    nv_pair_list_deinit(list);
++}
++
++conffile_t *conffile_list_append(conffile_list_t *list, const char *file_name,
++                       const char *md5sum)
++{
++    return nv_pair_list_append(list, file_name, md5sum);
++}
++
++int conffile_list_push(conffile_list_t *list, conffile_t *data)
++{
++    return nv_pair_list_push(list, data);
++}
++
++conffile_list_elt_t *conffile_list_pop(conffile_list_t *list)
++{
++    return nv_pair_list_pop(list);
++}
++
+Index: busybox-1.7.2/archival/libipkg/conffile_list.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/conffile_list.h     2007-10-04 17:14:22.325013650 +0200
+@@ -0,0 +1,36 @@
++/* conffile_list.h - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#ifndef CONFFILE_LIST_H
++#define CONFFILE_LIST_H
++
++#include "conffile.h"
++#include "nv_pair_list.h"
++
++typedef struct nv_pair_list_elt conffile_list_elt_t;
++typedef struct nv_pair_list conffile_list_t;
++
++int conffile_list_init(conffile_list_t *list);
++void conffile_list_deinit(conffile_list_t *list);
++
++conffile_t *conffile_list_append(conffile_list_t *list, const char *name,
++                             const char *root_dir);
++int conffile_list_push(conffile_list_t *list, conffile_t *data);
++conffile_list_elt_t *conffile_list_pop(conffile_list_t *list);
++
++#endif
++
+Index: busybox-1.7.2/archival/libipkg/file_util.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/file_util.c 2007-10-04 17:14:22.353015250 +0200
+@@ -0,0 +1,132 @@
++/* file_util.c - convenience routines for common stat operations
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#include "ipkg.h"
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#include "sprintf_alloc.h"
++#include "file_util.h"
++#include "libbb.h"
++#undef strlen
++
++int file_exists(const char *file_name)
++{
++    int err;
++    struct stat stat_buf;
++
++    err = stat(file_name, &stat_buf);
++    if (err == 0) {
++      return 1;
++    } else {
++      return 0;
++    }
++}
++
++int file_is_dir(const char *file_name)
++{
++    int err;
++    struct stat stat_buf;
++
++    err = stat(file_name, &stat_buf);
++    if (err) {
++      return 0;
++    }
++
++    return S_ISDIR(stat_buf.st_mode);
++}
++
++/* read a single line from a file, stopping at a newline or EOF.
++   If a newline is read, it will appear in the resulting string.
++   Return value is a malloc'ed char * which should be freed at
++   some point by the caller.
++
++   Return value is NULL if the file is at EOF when called.
++*/
++#define FILE_READ_LINE_BUF_SIZE 1024
++char *file_read_line_alloc(FILE *file)
++{
++    char buf[FILE_READ_LINE_BUF_SIZE];
++    int buf_len;
++    char *line = NULL;
++    int line_size = 0;
++
++    memset(buf, 0, FILE_READ_LINE_BUF_SIZE);
++    while (fgets(buf, FILE_READ_LINE_BUF_SIZE, file)) {
++      buf_len = strlen(buf);
++      if (line) {
++          line_size += buf_len;
++          line = realloc(line, line_size);
++          if (line == NULL) {
++              fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
++              break;
++          }
++          strcat(line, buf);
++      } else {
++          line_size = buf_len + 1;
++          line = strdup(buf);
++      }
++      if (buf[buf_len - 1] == '\n') {
++          break;
++      }
++    }
++
++    return line;
++}
++
++int file_move(const char *src, const char *dest)
++{
++    int err;
++
++    err = rename(src, dest);
++
++    if (err && errno == EXDEV) {
++      err = file_copy(src, dest);
++      unlink(src);
++    } else if (err) {
++      fprintf(stderr, "%s: ERROR: failed to rename %s to %s: %s\n",
++              __FUNCTION__, src, dest, strerror(errno));
++    }
++
++    return err;
++}
++
++/* I put these here to keep libbb dependencies from creeping all over
++   the ipkg code */
++int file_copy(const char *src, const char *dest)
++{
++    int err;
++
++    err = copy_file(src, dest, FILEUTILS_FORCE | FILEUTILS_PRESERVE_STATUS);
++    if (err) {
++      fprintf(stderr, "%s: ERROR: failed to copy %s to %s\n",
++              __FUNCTION__, src, dest);
++    }
++
++    return err;
++}
++
++int file_mkdir_hier(const char *path, long mode)
++{
++    return bb_make_directory((char *)path, mode, FILEUTILS_RECUR);
++}
++
++char *file_md5sum_alloc(const char *file_name)
++{
++      return hash_file(file_name, HASH_MD5);
++}
++
+Index: busybox-1.7.2/archival/libipkg/file_util.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/file_util.h 2007-10-04 17:14:22.377016616 +0200
+@@ -0,0 +1,29 @@
++/* file_util.h - convenience routines for common file operations
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#ifndef FILE_UTIL_H
++#define FILE_UTIL_H
++
++int file_exists(const char *file_name);
++int file_is_dir(const char *file_name);
++char *file_read_line_alloc(FILE *file);
++int file_move(const char *src, const char *dest);
++int file_copy(const char *src, const char *dest);
++int file_mkdir_hier(const char *path, long mode);
++char *file_md5sum_alloc(const char *file_name);
++
++#endif
+Index: busybox-1.7.2/archival/libipkg/hash_table.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/hash_table.c        2007-10-04 17:14:22.397017756 +0200
+@@ -0,0 +1,155 @@
++/* hash.c - hash tables for ipkg
++
++   Steven M. Ayer, Jamey Hicks
++   
++   Copyright (C) 2002 Compaq Computer Corporation
++
++   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, 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.
++*/
++
++#include <errno.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include "hash_table.h"
++#include "ipkg_message.h"
++
++
++static int hash_index(hash_table_t *hash, const char *pkg_name);
++static int rotating(const char *key, int len, int prime);
++
++static int hash_index(hash_table_t *hash, const char *pkg_name)
++{
++    return rotating(pkg_name, strlen(pkg_name), hash->n_entries);
++}
++  
++static int rotating(const char *key, int len, int prime)
++{
++    unsigned int hash, i;
++    for (hash=len, i=0; i<len; ++i)
++      hash = (hash<<4)^(hash>>28)^key[i];
++    return (hash % prime);
++}
++
++
++/*
++ * this is an open table keyed by strings
++ */
++int hash_table_init(const char *name, hash_table_t *hash, int len)
++{
++    static int primes_table[] = {
++      379, 761, 983, 1423, 2711, 3361, 3931, 4679, 5519, 6701, 9587,
++      19471, 23143, 33961, 46499, 49727, 99529, 0
++    };
++    int *picker;
++
++    if (hash->entries != NULL) {
++      /* we have been here already */
++      return 0;
++    }
++
++    hash->name = name;
++    hash->entries = NULL;
++    hash->n_entries = 0;
++    hash->hash_entry_key = NULL;
++
++    picker = primes_table;
++    while(*picker && (*picker++ < len));
++    if(!*picker)
++      fprintf(stderr, "%s: primes table might not be big enough (! << %d)\n", __FUNCTION__, len);
++    --picker;
++
++    hash->n_entries = *picker;
++    hash->entries = (hash_entry_t *)calloc(hash->n_entries, sizeof(hash_entry_t));
++    if (hash->entries == NULL) {
++      fprintf(stderr, "%s: Out of memory.\n", __FUNCTION__);
++      return ENOMEM;
++    }
++    return 0;
++}
++
++void hash_table_deinit(hash_table_t *hash)
++{
++    free(hash->entries);
++    hash->entries = NULL;
++    hash->n_entries = 0;
++}
++
++void *hash_table_get(hash_table_t *hash, const char *key)
++{
++  int ndx= hash_index(hash, key);
++  hash_entry_t *hash_entry = hash->entries + ndx;
++  while (hash_entry) 
++  {
++    if (hash_entry->key) 
++    {
++      if (strcmp(key, hash_entry->key) == 0) {
++         // ipkg_message(NULL, IPKG_DEBUG, "Function: %s. Key found for '%s' \n", __FUNCTION__, key);
++       return hash_entry->data;
++      }
++    }
++    hash_entry = hash_entry->next;
++  }
++  return NULL;
++}
++
++int hash_table_insert(hash_table_t *hash, const char *key, void *value)
++{
++     int ndx= hash_index(hash, key);
++     hash_entry_t *hash_entry = hash->entries + ndx;
++     if (0) ipkg_message(NULL, IPKG_DEBUG2, "Function: %s. Inserting in hash for '%s' \n", __FUNCTION__, key);
++     if (hash_entry->key) {
++        if (strcmp(hash_entry->key, key) == 0) {
++             /* alread in table, update the value */
++               if (0) ipkg_message(NULL, IPKG_DEBUG2, "Function: %s. Value already in hash for '%s' \n", __FUNCTION__, key);
++             hash_entry->data = value;
++             return 0;
++        } else {
++             /* 
++              * if this is a collision, we have to go to the end of the ll,
++              * then add a new entry
++              * before we can hook up the value
++              */
++               if (0) ipkg_message(NULL, IPKG_DEBUG2, "Function: %s. Value already in hash by collision for '%s' \n", __FUNCTION__, key);
++             while (hash_entry->next)
++                  hash_entry = hash_entry->next;
++             hash_entry->next = (hash_entry_t *)malloc(sizeof(hash_entry_t));
++             if (!hash_entry->next) {
++                  return -ENOMEM;
++             }
++             hash_entry = hash_entry->next;
++             hash_entry->next = NULL;
++        }
++     }
++     hash->n_elements++;
++     hash_entry->key = strdup(key);
++     hash_entry->data = value;
++
++     return 0;
++}
++
++
++void hash_table_foreach(hash_table_t *hash, void (*f)(const char *key, void *entry, void *data), void *data)
++{ 
++    int i;
++    if (!hash || !f)
++      return;
++
++    for (i = 0; i < hash->n_entries; i++) {
++      hash_entry_t *hash_entry = (hash->entries + i);
++      do {
++          if(hash_entry->key) {
++              f(hash_entry->key, hash_entry->data, data);
++          }
++      } while((hash_entry = hash_entry->next));
++    }
++}
++
+Index: busybox-1.7.2/archival/libipkg/hash_table.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/hash_table.h        2007-10-04 17:14:22.425019349 +0200
+@@ -0,0 +1,44 @@
++/* hash.h - hash tables for ipkg
++
++   Steven M. Ayer, Jamey Hicks
++   
++   Copyright (C) 2002 Compaq Computer Corporation
++
++   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, 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.
++*/
++
++#ifndef _HASH_TABLE_H_
++#define _HASH_TABLE_H_
++
++typedef struct hash_entry hash_entry_t;
++typedef struct hash_table hash_table_t;
++
++struct hash_entry {
++  const char * key;
++  void * data;
++  struct hash_entry * next;
++};
++
++struct hash_table {
++  const char *name; 
++  hash_entry_t * entries;  
++  int n_entries; /* number of buckets */
++  int n_elements;
++  const char * (*hash_entry_key)(void * data);
++};
++
++int hash_table_init(const char *name, hash_table_t *hash, int len);
++void hash_table_deinit(hash_table_t *hash);
++void *hash_table_get(hash_table_t *hash, const char *key);
++int hash_table_insert(hash_table_t *hash, const char *key, void *value);
++void hash_table_foreach(hash_table_t *hash, void (*f)(const char *key, void *entry, void *data), void *data);
++
++#endif /* _HASH_TABLE_H_ */
+Index: busybox-1.7.2/archival/libipkg/ipkg_cmd.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/ipkg_cmd.c  2007-10-04 17:14:22.449020718 +0200
+@@ -0,0 +1,1431 @@
++/* ipkg_cmd.c - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#include <string.h>
++
++#include "ipkg.h"
++#include <libgen.h>
++#include <glob.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <signal.h>
++#include <stdio.h>
++#include <dirent.h>
++
++#include "ipkg_conf.h"
++#include "ipkg_cmd.h"
++#include "ipkg_message.h"
++#include "pkg.h"
++#include "pkg_dest.h"
++#include "pkg_parse.h"
++#include "sprintf_alloc.h"
++#include "pkg.h"
++#include "file_util.h"
++#include "str_util.h"
++#include "libbb.h"
++#include "unarchive.h"
++
++#include <fnmatch.h>
++
++
++#include "ipkg_download.h"
++#include "ipkg_install.h"
++#include "ipkg_upgrade.h"
++#include "ipkg_remove.h"
++#include "ipkg_configure.h"
++#include "ipkg_message.h"
++
++#ifdef IPKG_LIB
++#include "libipkg.h"
++static void *p_userdata = NULL;
++#endif
++
++static int ipkg_update_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_upgrade_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_list_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_info_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_status_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_install_pending_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_install_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_list_installed_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_remove_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_purge_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_flag_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_files_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_search_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_download_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_depends_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatdepends_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatdepends_recursively_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatsuggests_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatrecommends_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatprovides_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatconflicts_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_whatreplaces_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_compare_versions_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_print_architecture_cmd(ipkg_conf_t *conf, int argc, char **argv);
++static int ipkg_configure_cmd(ipkg_conf_t *conf, int argc, char **argv);
++
++/* XXX: CLEANUP: The usage strings should be incorporated into this
++   array for easier maintenance */
++static ipkg_cmd_t cmds[] = {
++     {"update", 0, (ipkg_cmd_fun_t)ipkg_update_cmd}, 
++     {"upgrade", 0, (ipkg_cmd_fun_t)ipkg_upgrade_cmd},
++     {"list", 0, (ipkg_cmd_fun_t)ipkg_list_cmd},
++     {"list_installed", 0, (ipkg_cmd_fun_t)ipkg_list_installed_cmd},
++     {"info", 0, (ipkg_cmd_fun_t)ipkg_info_cmd},
++     {"flag", 1, (ipkg_cmd_fun_t)ipkg_flag_cmd},
++     {"status", 0, (ipkg_cmd_fun_t)ipkg_status_cmd},
++     {"install_pending", 0, (ipkg_cmd_fun_t)ipkg_install_pending_cmd},
++     {"install", 1, (ipkg_cmd_fun_t)ipkg_install_cmd},
++     {"remove", 1, (ipkg_cmd_fun_t)ipkg_remove_cmd},
++     {"purge", 1, (ipkg_cmd_fun_t)ipkg_purge_cmd},
++     {"configure", 0, (ipkg_cmd_fun_t)ipkg_configure_cmd},
++     {"files", 1, (ipkg_cmd_fun_t)ipkg_files_cmd},
++     {"search", 1, (ipkg_cmd_fun_t)ipkg_search_cmd},
++     {"download", 1, (ipkg_cmd_fun_t)ipkg_download_cmd},
++     {"compare_versions", 1, (ipkg_cmd_fun_t)ipkg_compare_versions_cmd},
++     {"compare-versions", 1, (ipkg_cmd_fun_t)ipkg_compare_versions_cmd},
++     {"print-architecture", 0, (ipkg_cmd_fun_t)ipkg_print_architecture_cmd},
++     {"print_architecture", 0, (ipkg_cmd_fun_t)ipkg_print_architecture_cmd},
++     {"print-installation-architecture", 0, (ipkg_cmd_fun_t)ipkg_print_architecture_cmd},
++     {"print_installation_architecture", 0, (ipkg_cmd_fun_t)ipkg_print_architecture_cmd},
++     {"depends", 1, (ipkg_cmd_fun_t)ipkg_depends_cmd},
++     {"whatdepends", 1, (ipkg_cmd_fun_t)ipkg_whatdepends_cmd},
++     {"whatdependsrec", 1, (ipkg_cmd_fun_t)ipkg_whatdepends_recursively_cmd},
++     {"whatrecommends", 1, (ipkg_cmd_fun_t)ipkg_whatrecommends_cmd},
++     {"whatsuggests", 1, (ipkg_cmd_fun_t)ipkg_whatsuggests_cmd},
++     {"whatprovides", 1, (ipkg_cmd_fun_t)ipkg_whatprovides_cmd},
++     {"whatreplaces", 1, (ipkg_cmd_fun_t)ipkg_whatreplaces_cmd},
++     {"whatconflicts", 1, (ipkg_cmd_fun_t)ipkg_whatconflicts_cmd},
++};
++
++int ipkg_state_changed;
++static void write_status_files_if_changed(ipkg_conf_t *conf)
++{
++     if (ipkg_state_changed && !conf->noaction) {
++        ipkg_message(conf, IPKG_INFO,
++                     "  writing status file\n");
++        ipkg_conf_write_status_files(conf);
++        pkg_write_changed_filelists(conf);
++     } else { 
++        ipkg_message(conf, IPKG_NOTICE, "Nothing to be done\n");
++     }
++}
++
++
++static int num_cmds = sizeof(cmds) / sizeof(ipkg_cmd_t);
++
++ipkg_cmd_t *ipkg_cmd_find(const char *name)
++{
++     int i;
++     ipkg_cmd_t *cmd;
++
++     for (i=0; i < num_cmds; i++) {
++        cmd = &cmds[i];
++        if (strcmp(name, cmd->name) == 0) {
++             return cmd;
++        }
++     }
++
++     return NULL;
++}
++
++#ifdef IPKG_LIB
++int ipkg_cmd_exec(ipkg_cmd_t *cmd, ipkg_conf_t *conf, int argc, const char **argv, void *userdata)
++{
++      int result;
++      p_userdata = userdata;
++      
++
++      result = (cmd->fun)(conf, argc, argv);
++        if ( result == 0 ) {
++           ipkg_message(conf, IPKG_NOTICE, "Done.\n");
++        } else {
++           ipkg_message(conf, IPKG_NOTICE, "An error ocurred, return value: %d.\n", result);
++
++        }
++        if ( error_list ) {
++           reverse_error_list(&error_list);
++
++           ipkg_message(conf, IPKG_NOTICE, "Collected errors:\n");
++           /* Here we print the errors collected and free the list */
++           while (error_list != NULL) {
++                 ipkg_message(conf, IPKG_NOTICE, "%s",error_list->errmsg);
++                 error_list = error_list->next;
++
++           }
++           free_error_list(&error_list);
++
++        }
++   
++      p_userdata = NULL;
++      return result;
++}
++#else
++int ipkg_cmd_exec(ipkg_cmd_t *cmd, ipkg_conf_t *conf, int argc, const char **argv)
++{
++     return (cmd->fun)(conf, argc, argv);
++}
++#endif
++
++static int ipkg_update_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     int err;
++     int failures;
++     char *lists_dir;
++     pkg_src_list_elt_t *iter;
++     pkg_src_t *src;
++
++ 
++    sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
++ 
++    if (! file_is_dir(lists_dir)) {
++        if (file_exists(lists_dir)) {
++             ipkg_message(conf, IPKG_ERROR,
++                          "%s: ERROR: %s exists, but is not a directory\n",
++                          __FUNCTION__, lists_dir);
++             free(lists_dir);
++             return EINVAL;
++        }
++        err = file_mkdir_hier(lists_dir, 0755);
++        if (err) {
++             ipkg_message(conf, IPKG_ERROR,
++                          "%s: ERROR: failed to make directory %s: %s\n",
++                          __FUNCTION__, lists_dir, strerror(errno));
++             free(lists_dir);
++             return EINVAL;
++        }     
++     } 
++
++     failures = 0;
++     for (iter = conf->pkg_src_list.head; iter; iter = iter->next) {
++        char *url, *list_file_name;
++
++        src = iter->data;
++
++        if (src->extra_data)  /* debian style? */
++            sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data, 
++                          src->gzip ? "Packages.gz" : "Packages");
++        else
++            sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
++
++        sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
++        if (src->gzip) {
++            char *tmp;
++            char *tmp_file_name;
++            FILE *in, *out;
++
++            tmp = strdup ("/tmp/ipkg.XXXXXX");
++
++            if (mkdtemp (tmp) == NULL) {
++                perror ("mkdtemp");
++                failures++;
++                continue;
++            }
++            
++            sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
++            err = ipkg_download(conf, url, tmp_file_name);
++            if (err == 0) {
++                 ipkg_message (conf, IPKG_NOTICE, "Inflating %s\n", url);
++                 in = fopen (tmp_file_name, "r");
++                 out = fopen (list_file_name, "w");
++                 if (in && out) {
++                      inflate_unzip_result res;
++                      inflate_unzip (&res, 0x8000, fileno(in), fileno(out));
++                 } else
++                      err = 1;
++                 if (in)
++                      fclose (in);
++                 if (out)
++                      fclose (out);
++                 unlink (tmp_file_name);
++                 rmdir (tmp);
++                 free (tmp);
++            }
++        } else
++            err = ipkg_download(conf, url, list_file_name);
++        if (err) {
++             failures++;
++        } else {
++             ipkg_message(conf, IPKG_NOTICE,
++                          "Updated list of available packages in %s\n",
++                          list_file_name);
++        }
++        free(url);
++        free(list_file_name);
++     }
++     free(lists_dir);
++
++#ifdef CONFIG_CLEAR_SW_INSTALL_FLAG
++#warning here
++     /* clear SW_INSTALL on any package where state is SS_NOT_INSTALLED.
++      * this is a hack to work around poor bookkeeping in old ipkg upgrade code 
++      * -Jamey 3/1/03
++      */
++     {
++        int i;
++        int changed = 0;
++        pkg_vec_t *available = pkg_vec_alloc();
++        pkg_hash_fetch_available(&conf->pkg_hash, available);
++        ipkg_message(conf, IPKG_DEBUG, "Clearing SW_INSTALL for SS_NOT_INSTALLED packages.\n");
++        for (i = 0; i < available->len; i++) {
++             pkg_t *pkg = available->pkgs[i];
++             if (pkg->state_want == SW_INSTALL && pkg->state_status == SS_NOT_INSTALLED) {
++                  ipkg_message(conf, IPKG_DEBUG, "Clearing SW_INSTALL on package %s.\n", pkg->name);
++                  pkg->state_want = SW_UNKNOWN;
++                  changed = 1;
++             }
++        }
++        pkg_vec_free(available);
++        if (changed) {
++             write_status_files_if_changed(conf);
++        }
++     }
++#endif
++
++     return failures;
++}
++
++
++/* scan the args passed and cache the local filenames of the packages */
++int ipkg_multiple_files_scan(ipkg_conf_t *conf, int argc, char **argv)
++{
++     int i;
++     int err;
++    
++     /* 
++      * First scan through package names/urls
++      * For any urls, download the packages and install in database.
++      * For any files, install package info in database.
++      */
++     for (i = 0; i < argc; i ++) {
++        char *filename = argv [i];
++        //char *tmp = basename (tmp);
++        //int tmplen = strlen (tmp);
++
++        //if (strcmp (tmp + (tmplen - strlen (IPKG_PKG_EXTENSION)), IPKG_PKG_EXTENSION) != 0)
++        //     continue;
++        //if (strcmp (tmp + (tmplen - strlen (DPKG_PKG_EXTENSION)), DPKG_PKG_EXTENSION) != 0)
++        //     continue;
++      
++          ipkg_message(conf, IPKG_DEBUG2, "Debug mfs: %s  \n",filename );
++
++        err = ipkg_prepare_url_for_install(conf, filename, &argv[i]);
++        if (err)
++          return err;
++     }
++     return 0;
++}
++
++struct ipkg_intercept
++{
++    char *oldpath;
++    char *statedir;
++};
++
++typedef struct ipkg_intercept *ipkg_intercept_t;
++
++ipkg_intercept_t ipkg_prep_intercepts(ipkg_conf_t *conf)
++{
++    ipkg_intercept_t ctx;
++    char *newpath;
++    int gen;
++
++    ctx = malloc (sizeof (*ctx));
++    ctx->oldpath = strdup (getenv ("PATH"));
++
++    sprintf_alloc (&newpath, "%s/ipkg/intercept:%s", IPKGLIBDIR, ctx->oldpath);
++    setenv ("PATH", newpath, 1);
++    free (newpath);
++    
++    gen = 0;
++ retry:
++    sprintf_alloc (&ctx->statedir, "/tmp/ipkg-intercept-%d-%d", getpid (), gen);
++    if (mkdir (ctx->statedir, 0770) < 0) {
++      if (errno == EEXIST) {
++          free (ctx->statedir);
++          gen++;
++          goto retry;
++      }
++      perror (ctx->statedir);
++      return NULL;
++    }
++    setenv ("IPKG_INTERCEPT_DIR", ctx->statedir, 1);
++    return ctx;
++}
++
++int ipkg_finalize_intercepts(ipkg_intercept_t ctx)
++{
++    char *cmd;
++    DIR *dir;
++    int err = 0;
++
++    setenv ("PATH", ctx->oldpath, 1);
++    free (ctx->oldpath);
++
++    dir = opendir (ctx->statedir);
++    if (dir) {
++      struct dirent *de;
++      while (de = readdir (dir), de != NULL) {
++          char *path;
++          
++          if (de->d_name[0] == '.')
++              continue;
++          
++          sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
++          if (access (path, X_OK) == 0) {
++              if (system (path)) {
++                  err = errno;
++                  perror (de->d_name);
++              }
++          }
++          free (path);
++      }
++    } else
++      perror (ctx->statedir);
++      
++    sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
++    system (cmd);
++    free (cmd);
++
++    free (ctx->statedir);
++    free (ctx);
++
++    return err;
++}
++
++int ipkg_configure_packages(ipkg_conf_t *conf, char *pkg_name)
++{
++     pkg_vec_t *all;
++     int i;
++     pkg_t *pkg;
++     ipkg_intercept_t ic;
++     int r, err = 0;
++
++     ipkg_message(conf, IPKG_INFO,
++                "Configuring unpacked packages\n");
++     fflush( stdout );
++
++     all = pkg_vec_alloc();
++     pkg_hash_fetch_available(&conf->pkg_hash, all);
++
++     ic = ipkg_prep_intercepts (conf);
++    
++     for(i = 0; i < all->len; i++) {
++        pkg = all->pkgs[i];
++
++        if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) 
++             continue;
++
++        if (pkg->state_status == SS_UNPACKED) {
++             ipkg_message(conf, IPKG_NOTICE,
++                          "Configuring %s\n", pkg->name);
++             fflush( stdout );
++             r = ipkg_configure(conf, pkg);
++             if (r == 0) {
++                  pkg->state_status = SS_INSTALLED;
++                  pkg->parent->state_status = SS_INSTALLED;
++                  pkg->state_flag &= ~SF_PREFER;
++             } else {
++                  if (!err)
++                      err = r;
++             }
++        }
++     }
++
++     r = ipkg_finalize_intercepts (ic);
++     if (r && !err)
++       err = r;
++
++     pkg_vec_free(all);
++     return err;
++}
++
++static void sigint_handler(int sig)
++{
++     signal(sig, SIG_DFL);
++     ipkg_message(NULL, IPKG_NOTICE,
++                "ipkg: interrupted. writing out status database\n");
++     write_status_files_if_changed(global_conf);
++     exit(128 + sig);
++}
++
++static int ipkg_install_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     int i;
++     char *arg;
++     int err=0;
++
++     global_conf = conf;
++     signal(SIGINT, sigint_handler);
++
++     /*
++      * Now scan through package names and install
++      */
++     for (i=0; i < argc; i++) {
++        arg = argv[i];
++
++          ipkg_message(conf, IPKG_DEBUG2, "Debug install_cmd: %s  \n",arg );
++          err = ipkg_prepare_url_for_install(conf, arg, &argv[i]);
++          if (err != EINVAL && err != 0)
++              return err;
++     }
++     pkg_info_preinstall_check(conf);
++
++     for (i=0; i < argc; i++) {
++        arg = argv[i];
++        if (conf->multiple_providers)
++             err = ipkg_install_multi_by_name(conf, arg);
++        else{
++             err = ipkg_install_by_name(conf, arg);
++          }
++        if (err == IPKG_PKG_HAS_NO_CANDIDATE) {
++             ipkg_message(conf, IPKG_ERROR,
++                          "Cannot find package %s.\n"
++                          "Check the spelling or perhaps run 'ipkg update'\n",
++                          arg);
++        }
++     }
++
++     /* recheck to verify that all dependences are satisfied */
++     if (0) ipkg_satisfy_all_dependences(conf);
++
++     ipkg_configure_packages(conf, NULL);
++
++     write_status_files_if_changed(conf);
++
++     return err;
++}
++
++static int ipkg_upgrade_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     int i;
++     pkg_t *pkg;
++     int err;
++
++     global_conf = conf;
++     signal(SIGINT, sigint_handler);
++
++     if (argc) {
++        for (i=0; i < argc; i++) {
++             char *arg = argv[i];
++
++               err = ipkg_prepare_url_for_install(conf, arg, &arg);
++               if (err != EINVAL && err != 0)
++                   return err;
++        }
++        pkg_info_preinstall_check(conf);
++
++        for (i=0; i < argc; i++) {
++             char *arg = argv[i];
++             if (conf->restrict_to_default_dest) {
++                  pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
++                                                              argv[i],
++                                                              conf->default_dest);
++                  if (pkg == NULL) {
++                       ipkg_message(conf, IPKG_NOTICE,
++                                    "Package %s not installed in %s\n",
++                                    argv[i], conf->default_dest->name);
++                       continue;
++                  }
++             } else {
++                  pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
++                                                         argv[i]);
++             }
++             if (pkg)
++                  ipkg_upgrade_pkg(conf, pkg);
++             else {
++                  ipkg_install_by_name(conf, arg);
++               }
++        }
++     } else {
++        pkg_vec_t *installed = pkg_vec_alloc();
++
++        pkg_info_preinstall_check(conf);
++
++        pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
++        for (i = 0; i < installed->len; i++) {
++             pkg = installed->pkgs[i];
++             ipkg_upgrade_pkg(conf, pkg);
++        }
++        pkg_vec_free(installed);
++     }
++
++     /* recheck to verify that all dependences are satisfied */
++     if (0) ipkg_satisfy_all_dependences(conf);
++
++     ipkg_configure_packages(conf, NULL);
++
++     write_status_files_if_changed(conf);
++
++     return 0;
++}
++
++static int ipkg_download_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     int i, err;
++     char *arg;
++     pkg_t *pkg;
++
++     pkg_info_preinstall_check(conf);
++     for (i = 0; i < argc; i++) {
++        arg = argv[i];
++
++        pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg);
++        if (pkg == NULL) {
++             ipkg_message(conf, IPKG_ERROR,
++                          "Cannot find package %s.\n"
++                          "Check the spelling or perhaps run 'ipkg update'\n",
++                          arg);
++             continue;
++        }
++
++        err = ipkg_download_pkg(conf, pkg, ".");
++
++        if (err) {
++             ipkg_message(conf, IPKG_ERROR,
++                          "Failed to download %s\n", pkg->name);
++        } else {
++             ipkg_message(conf, IPKG_NOTICE,
++                          "Downloaded %s as %s\n",
++                          pkg->name, pkg->local_filename);
++        }
++     }
++
++     return 0;
++}
++
++
++static int ipkg_list_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     int i ;
++     pkg_vec_t *available;
++     pkg_t *pkg;
++     char desc_short[IPKG_LIST_DESCRIPTION_LENGTH];
++     char *newline;
++     char *pkg_name = NULL;
++     char *version_str;
++
++     if (argc > 0) {
++        pkg_name = argv[0];
++     }
++     available = pkg_vec_alloc();
++     pkg_hash_fetch_available(&conf->pkg_hash, available);
++     for (i=0; i < available->len; i++) {
++        pkg = available->pkgs[i];
++        /* if we have package name or pattern and pkg does not match, then skip it */
++        if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) 
++             continue;
++        if (pkg->description) {
++             strncpy(desc_short, pkg->description, IPKG_LIST_DESCRIPTION_LENGTH);
++        } else {
++             desc_short[0] = '\0';
++        }
++        desc_short[IPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
++        newline = strchr(desc_short, '\n');
++        if (newline) {
++             *newline = '\0';
++        }
++#ifndef IPKG_LIB
++        printf("%s - %s\n", pkg->name, desc_short);
++#else
++        if (ipkg_cb_list) {
++              version_str = pkg_version_str_alloc(pkg);
++              ipkg_cb_list(pkg->name,desc_short,
++                                           version_str,
++                                       pkg->state_status,
++                                       p_userdata);
++              free(version_str);
++        }
++#endif
++     }
++     pkg_vec_free(available);
++
++     return 0;
++}
++
++
++static int ipkg_list_installed_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     int i ;
++     pkg_vec_t *available;
++     pkg_t *pkg;
++     char desc_short[IPKG_LIST_DESCRIPTION_LENGTH];
++     char *newline;
++     char *pkg_name = NULL;
++     char *version_str;
++
++     if (argc > 0) {
++        pkg_name = argv[0];
++     }
++     available = pkg_vec_alloc();
++     pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
++     for (i=0; i < available->len; i++) {
++        pkg = available->pkgs[i];
++        /* if we have package name or pattern and pkg does not match, then skip it */
++        if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) 
++             continue;
++        if (pkg->description) {
++             strncpy(desc_short, pkg->description, IPKG_LIST_DESCRIPTION_LENGTH);
++        } else {
++             desc_short[0] = '\0';
++        }
++        desc_short[IPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
++        newline = strchr(desc_short, '\n');
++        if (newline) {
++             *newline = '\0';
++        }
++#ifndef IPKG_LIB
++        printf("%s - %s\n", pkg->name, desc_short);
++#else
++        if (ipkg_cb_list) {
++              version_str = pkg_version_str_alloc(pkg);
++              ipkg_cb_list(pkg->name,desc_short,
++                                           version_str,
++                                       pkg->state_status,
++                                       p_userdata);
++              free(version_str);
++        }
++#endif
++     }
++
++     return 0;
++}
++
++static int ipkg_info_status_cmd(ipkg_conf_t *conf, int argc, char **argv, int installed_only)
++{
++     int i;
++     pkg_vec_t *available;
++     pkg_t *pkg;
++     char *pkg_name = NULL;
++     char **pkg_fields = NULL;
++     int n_fields = 0;
++     char *buff ; // = (char *)malloc(1);
++
++     if (argc > 0) {
++        pkg_name = argv[0];
++     }
++     if (argc > 1) {
++        pkg_fields = &argv[1];
++        n_fields = argc - 1;
++     }
++
++     available = pkg_vec_alloc();
++     if (installed_only)
++        pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
++     else
++        pkg_hash_fetch_available(&conf->pkg_hash, available);
++     for (i=0; i < available->len; i++) {
++        pkg = available->pkgs[i];
++        if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
++             continue;
++        }
++#ifndef IPKG_LIB
++        if (n_fields) {
++             for (j = 0; j < n_fields; j++)
++                  pkg_print_field(pkg, stdout, pkg_fields[j]);
++        } else {
++             pkg_print_info(pkg, stdout);
++        }
++#else
++
++        buff = pkg_formatted_info(pkg);
++          if ( buff ) {
++             if (ipkg_cb_status) ipkg_cb_status(pkg->name,
++                                                pkg->state_status,
++                                                buff,
++                                                p_userdata);
++/* 
++   We should not forget that actually the pointer is allocated. 
++   We need to free it :)  ( Thanks florian for seeing the error )
++*/
++               free(buff);
++          }
++#endif
++        if (conf->verbosity > 1) {
++             conffile_list_elt_t *iter;
++             for (iter = pkg->conffiles.head; iter; iter = iter->next) {
++                  conffile_t *cf = iter->data;
++                  int modified = conffile_has_been_modified(conf, cf);
++                  ipkg_message(conf, IPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
++                               cf->name, cf->value, modified);
++             }
++        }
++     }
++#ifndef IPKG_LIB
++     if (buff)
++        free(buff);
++#endif
++     pkg_vec_free(available);
++
++     return 0;
++}
++
++static int ipkg_info_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     return ipkg_info_status_cmd(conf, argc, argv, 0);
++}
++
++static int ipkg_status_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     return ipkg_info_status_cmd(conf, argc, argv, 1);
++}
++
++static int ipkg_configure_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     
++     int err;
++     if (argc > 0) {
++        char *pkg_name = NULL;
++
++        pkg_name = argv[0];
++
++        err = ipkg_configure_packages (conf, pkg_name);
++     
++     } else {
++        err = ipkg_configure_packages (conf, NULL);
++     }
++
++     write_status_files_if_changed(conf);
++
++     return err;
++}
++
++static int ipkg_install_pending_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     int i, err;
++     char *globpattern;
++     glob_t globbuf;
++    
++     sprintf_alloc(&globpattern, "%s/*" IPKG_PKG_EXTENSION, conf->pending_dir);
++     err = glob(globpattern, 0, NULL, &globbuf);
++     free(globpattern);
++     if (err) {
++        return 0;
++     }
++
++     ipkg_message(conf, IPKG_NOTICE,
++                "The following packages in %s will now be installed.\n",
++                conf->pending_dir);
++     for (i = 0; i < globbuf.gl_pathc; i++) {
++        ipkg_message(conf, IPKG_NOTICE,
++                     "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
++     }
++     ipkg_message(conf, IPKG_NOTICE, "\n");
++     for (i = 0; i < globbuf.gl_pathc; i++) {
++        err = ipkg_install_from_file(conf, globbuf.gl_pathv[i]);
++        if (err == 0) {
++             err = unlink(globbuf.gl_pathv[i]);
++             if (err) {
++                  ipkg_message(conf, IPKG_ERROR,
++                               "%s: ERROR: failed to unlink %s: %s\n",
++                               __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
++                  return err;
++             }
++        }
++     }
++     globfree(&globbuf);
++
++     return err;
++}
++
++static int ipkg_remove_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     int i,a,done;
++     pkg_t *pkg;
++     pkg_t *pkg_to_remove;
++     pkg_vec_t *available;
++     char *pkg_name = NULL;
++     global_conf = conf;
++     signal(SIGINT, sigint_handler);
++
++// ENH: Add the "no pkg removed" just in case.
++
++    done = 0;
++
++     available = pkg_vec_alloc();
++     pkg_info_preinstall_check(conf);
++     if ( argc > 0 ) {
++        pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
++        for (i=0; i < argc; i++) {
++           pkg_name = malloc(strlen(argv[i])+2);
++           strcpy(pkg_name,argv[i]);
++           for (a=0; a < available->len; a++) {
++               pkg = available->pkgs[a];
++             if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
++                  continue;
++               }
++               if (conf->restrict_to_default_dest) {
++                  pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
++                                                              pkg->name,
++                                                              conf->default_dest);
++               } else {
++                  pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
++               }
++        
++               if (pkg == NULL) {
++                  ipkg_message(conf, IPKG_ERROR, "Package %s is not installed.\n", pkg->name);
++                  continue;
++               }
++               if (pkg->state_status == SS_NOT_INSTALLED) {    // Added the control, so every already removed package could be skipped
++                  ipkg_message(conf, IPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
++                    continue;
++               }
++               ipkg_remove_pkg(conf, pkg_to_remove,0);
++               done = 1;
++           }
++           free (pkg_name);
++        }
++        pkg_vec_free(available);
++     } else {
++        pkg_vec_t *installed_pkgs = pkg_vec_alloc();
++        int flagged_pkg_count = 0;
++        int removed;
++
++        pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
++
++        for (i = 0; i < installed_pkgs->len; i++) {
++             pkg = installed_pkgs->pkgs[i];
++             if (pkg->state_flag & SF_USER) {
++                  flagged_pkg_count++;
++             } else {
++                  if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
++                       ipkg_message(conf, IPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
++             }
++        }
++        if (!flagged_pkg_count) {
++             ipkg_message(conf, IPKG_NOTICE, "No packages flagged as installed by user, \n"
++                          "so refusing to uninstall unflagged non-leaf packages\n");
++             return 0;
++        }
++
++        /* find packages not flagged SF_USER (i.e., installed to
++         * satisfy a dependence) and not having any dependents, and
++         * remove them */
++        do {
++             removed = 0;
++             for (i = 0; i < installed_pkgs->len; i++) {
++                  pkg = installed_pkgs->pkgs[i];
++                  if (!(pkg->state_flag & SF_USER)
++                      && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
++                       removed++;
++                       ipkg_message(conf, IPKG_NOTICE, "Removing non-user leaf package %s\n");
++                       ipkg_remove_pkg(conf, pkg,0);
++                         done = 1;
++                  }
++             }
++        } while (removed);
++        pkg_vec_free(installed_pkgs);
++     }
++
++     if ( done == 0 ) 
++        ipkg_message(conf, IPKG_NOTICE, "No packages removed.\n");
++
++     write_status_files_if_changed(conf);
++     return 0;
++}
++
++static int ipkg_purge_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     int i;
++     pkg_t *pkg;
++
++     global_conf = conf;
++     signal(SIGINT, sigint_handler);
++
++     pkg_info_preinstall_check(conf);
++
++     for (i=0; i < argc; i++) {
++        if (conf->restrict_to_default_dest) {
++             pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
++                                                         argv[i],
++                                                         conf->default_dest);
++        } else {
++             pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
++        }
++
++        if (pkg == NULL) {
++             ipkg_message(conf, IPKG_ERROR,
++                          "Package %s is not installed.\n", argv[i]);
++             continue;
++        }
++        ipkg_purge_pkg(conf, pkg);
++     }
++
++     write_status_files_if_changed(conf);
++     return 0;
++}
++
++static int ipkg_flag_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     int i;
++     pkg_t *pkg;
++     char *flags = argv[0];
++    
++     global_conf = conf;
++     signal(SIGINT, sigint_handler);
++
++     for (i=1; i < argc; i++) {
++        if (conf->restrict_to_default_dest) {
++             pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
++                                                         argv[i],
++                                                         conf->default_dest);
++        } else {
++             pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
++        }
++
++        if (pkg == NULL) {
++             ipkg_message(conf, IPKG_ERROR,
++                          "Package %s is not installed.\n", argv[i]);
++             continue;
++        }
++          if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
++              ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
++            pkg->state_flag = pkg_state_flag_from_str(flags);
++          }
++/* pb_ asked this feature 03292004 */
++/* Actually I will use only this two, but this is an open for various status */
++          if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
++            pkg->state_status = pkg_state_status_from_str(flags);
++          }
++        ipkg_state_changed++;
++        ipkg_message(conf, IPKG_NOTICE,
++                     "Setting flags for package %s to %s\n",
++                     pkg->name, flags);
++     }
++
++     write_status_files_if_changed(conf);
++     return 0;
++}
++
++static int ipkg_files_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     pkg_t *pkg;
++     str_list_t *installed_files;
++     str_list_elt_t *iter;
++     char *pkg_version;
++     size_t buff_len = 8192;
++     size_t used_len;
++     char *buff ;
++
++     buff = (char *)malloc(buff_len);
++     if ( buff == NULL ) {
++        fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
++        return ENOMEM;
++     }
++ 
++     if (argc < 1) {
++        return EINVAL;
++     }
++
++     pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
++                                          argv[0]);
++     if (pkg == NULL) {
++        ipkg_message(conf, IPKG_ERROR,
++                     "Package %s not installed.\n", argv[0]);
++        return 0;
++     }
++
++     installed_files = pkg_get_installed_files(pkg);
++     pkg_version = pkg_version_str_alloc(pkg);
++
++#ifndef IPKG_LIB
++     printf("Package %s (%s) is installed on %s and has the following files:\n",
++          pkg->name, pkg_version, pkg->dest->name);
++     for (iter = installed_files->head; iter; iter = iter->next) {
++        puts(iter->data);
++     }
++#else
++     if (buff) {
++     try_again:
++        used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
++                            pkg->name, pkg_version, pkg->dest->name) + 1;
++        if (used_len > buff_len) {
++             buff_len *= 2;
++             buff = realloc (buff, buff_len);
++             goto try_again;
++        }
++        for (iter = installed_files->head; iter; iter = iter->next) {
++             used_len += strlen (iter->data) + 1;
++             while (buff_len <= used_len) {
++                  buff_len *= 2;
++                  buff = realloc (buff, buff_len);
++             }
++             strncat(buff, iter->data, buff_len);
++             strncat(buff, "\n", buff_len);
++        } 
++        if (ipkg_cb_list) ipkg_cb_list(pkg->name,
++                                       buff,
++                                       pkg_version_str_alloc(pkg),
++                                       pkg->state_status,
++                                       p_userdata);
++        free(buff);
++     }
++#endif
++
++     free(pkg_version);
++     pkg_free_installed_files(pkg);
++
++     return 0;
++}
++
++static int ipkg_depends_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++
++     if (argc > 0) {
++        pkg_vec_t *available_pkgs = pkg_vec_alloc();
++        const char *rel_str = "depends on";
++        int i;
++     
++        pkg_info_preinstall_check(conf);
++
++        if (conf->query_all)
++             pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
++        else
++             pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
++        for (i = 0; i < argc; i++) {
++             const char *target = argv[i];
++             int j;
++
++             ipkg_message(conf, IPKG_ERROR, "target=%s\n", target);
++
++             for (j = 0; j < available_pkgs->len; j++) {
++                  pkg_t *pkg = available_pkgs->pkgs[j];
++                  if (fnmatch(target, pkg->name, 0) == 0) {
++                       int k;
++                       int count = pkg->depends_count + pkg->pre_depends_count;
++                       ipkg_message(conf, IPKG_ERROR, "What %s (arch=%s) %s\n",
++                                    target, pkg->architecture, rel_str);
++                       for (k = 0; k < count; k++) {
++                            compound_depend_t *cdepend = &pkg->depends[k];
++                            int l;
++                            for (l = 0; l < cdepend->possibility_count; l++) {
++                                 depend_t *possibility = cdepend->possibilities[l];
++                                 ipkg_message(conf, IPKG_ERROR, "    %s", possibility->pkg->name);
++                                 if (conf->verbosity > 0) {
++                                      // char *ver = abstract_pkg_version_str_alloc(possibility->pkg); 
++                                      ipkg_message(conf, IPKG_NOTICE, " %s", possibility->version);
++                                      if (possibility->version) {
++                                           char *typestr = NULL;
++                                           switch (possibility->constraint) {
++                                           case NONE: typestr = "none"; break;
++                                           case EARLIER: typestr = "<"; break;
++                                           case EARLIER_EQUAL: typestr = "<="; break;
++                                           case EQUAL: typestr = "="; break;
++                                           case LATER_EQUAL: typestr = ">="; break;
++                                           case LATER: typestr = ">"; break;
++                                           }
++                                           ipkg_message(conf, IPKG_NOTICE, " (%s %s)", typestr, possibility->version);
++                                      }
++                                      // free(ver);
++                                 }
++                                 ipkg_message(conf, IPKG_ERROR, "\n");
++                            }
++                       }
++                  }
++             }
++        }
++        pkg_vec_free(available_pkgs);
++     }
++     return 0;
++}
++
++enum what_field_type {
++  WHATDEPENDS,
++  WHATCONFLICTS,
++  WHATPROVIDES,
++  WHATREPLACES,
++  WHATRECOMMENDS,
++  WHATSUGGESTS
++};
++
++static int ipkg_what_depends_conflicts_cmd(ipkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
++{
++
++     if (argc > 0) {
++        pkg_vec_t *available_pkgs = pkg_vec_alloc();
++        const char *rel_str = NULL;
++        int i;
++        int changed;
++
++        switch (what_field_type) {
++        case WHATDEPENDS: rel_str = "depends on"; break;
++        case WHATCONFLICTS: rel_str = "conflicts with"; break;
++        case WHATSUGGESTS: rel_str = "suggests"; break;
++        case WHATRECOMMENDS: rel_str = "recommends"; break;
++        case WHATPROVIDES: rel_str = "provides"; break;
++        case WHATREPLACES: rel_str = "replaces"; break;
++        }
++     
++        if (conf->query_all)
++             pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
++        else
++             pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
++
++        /* mark the root set */
++        pkg_vec_clear_marks(available_pkgs);
++        ipkg_message(conf, IPKG_NOTICE, "Root set:\n");
++        for (i = 0; i < argc; i++) {
++             const char *dependee_pattern = argv[i];
++             pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
++        }
++        for (i = 0; i < available_pkgs->len; i++) {
++             pkg_t *pkg = available_pkgs->pkgs[i];
++             if (pkg->state_flag & SF_MARKED) {
++                  /* mark the parent (abstract) package */
++                  pkg_mark_provides(pkg);
++                  ipkg_message(conf, IPKG_NOTICE, "  %s\n", pkg->name);
++             }
++        }
++
++        ipkg_message(conf, IPKG_NOTICE, "What %s root set\n", rel_str);
++        do {
++             int j;
++             changed = 0;
++
++             for (j = 0; j < available_pkgs->len; j++) {
++                  pkg_t *pkg = available_pkgs->pkgs[j];
++                  int k;
++                  int count = ((what_field_type == WHATCONFLICTS)
++                               ? pkg->conflicts_count
++                               : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
++                  /* skip this package if it is already marked */
++                  if (pkg->parent->state_flag & SF_MARKED) {
++                       continue;
++                  }
++                  for (k = 0; k < count; k++) {
++                       compound_depend_t *cdepend = 
++                            (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
++                       int l;
++                       for (l = 0; l < cdepend->possibility_count; l++) {
++                            depend_t *possibility = cdepend->possibilities[l];
++                            if (possibility->pkg->state_flag & SF_MARKED) {
++                                 /* mark the depending package so we won't visit it again */
++                                 pkg->state_flag |= SF_MARKED;
++                                 pkg_mark_provides(pkg);
++                                 changed++;
++
++                                 ipkg_message(conf, IPKG_NOTICE, "    %s", pkg->name);
++                                 if (conf->verbosity > 0) {
++                                      char *ver = pkg_version_str_alloc(pkg); 
++                                      ipkg_message(conf, IPKG_NOTICE, " %s", ver);
++                                      ipkg_message(conf, IPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
++                                      if (possibility->version) {
++                                           char *typestr = NULL;
++                                           switch (possibility->constraint) {
++                                           case NONE: typestr = "none"; break;
++                                           case EARLIER: typestr = "<"; break;
++                                           case EARLIER_EQUAL: typestr = "<="; break;
++                                           case EQUAL: typestr = "="; break;
++                                           case LATER_EQUAL: typestr = ">="; break;
++                                           case LATER: typestr = ">"; break;
++                                           }
++                                           ipkg_message(conf, IPKG_NOTICE, " (%s %s)", typestr, possibility->version);
++                                      }
++                                      free(ver);
++                                      if (!pkg_dependence_satisfiable(conf, possibility))
++                                           ipkg_message(conf, IPKG_NOTICE, " unsatisfiable");
++                                 }
++                                 ipkg_message(conf, IPKG_NOTICE, "\n");
++                                 goto next_package;
++                            }
++                       }
++                  }
++             next_package:
++                  ;
++             }
++        } while (changed && recursive);
++        pkg_vec_free(available_pkgs);
++     }
++
++     return 0;
++}
++
++int pkg_mark_provides(pkg_t *pkg)
++{
++     int provides_count = pkg->provides_count;
++     abstract_pkg_t **provides = pkg->provides;
++     int i;
++     pkg->parent->state_flag |= SF_MARKED;
++     for (i = 0; i < provides_count; i++) {
++        provides[i]->state_flag |= SF_MARKED;
++     }
++     return 0;
++}
++
++static int ipkg_whatdepends_recursively_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     return ipkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
++}
++static int ipkg_whatdepends_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     return ipkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
++}
++
++static int ipkg_whatsuggests_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     return ipkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
++}
++
++static int ipkg_whatrecommends_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     return ipkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
++}
++
++static int ipkg_whatconflicts_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     return ipkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
++}
++
++static int ipkg_what_provides_replaces_cmd(ipkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
++{
++
++     if (argc > 0) {
++        pkg_vec_t *available_pkgs = pkg_vec_alloc();
++        const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
++        int i;
++     
++        pkg_info_preinstall_check(conf);
++
++        if (conf->query_all)
++             pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
++        else
++             pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
++        for (i = 0; i < argc; i++) {
++             const char *target = argv[i];
++             int j;
++
++             ipkg_message(conf, IPKG_ERROR, "What %s %s\n",
++                          rel_str, target);
++             for (j = 0; j < available_pkgs->len; j++) {
++                  pkg_t *pkg = available_pkgs->pkgs[j];
++                  int k;
++                  int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
++                  for (k = 0; k < count; k++) {
++                       abstract_pkg_t *apkg = 
++                            ((what_field_type == WHATPROVIDES) 
++                             ? pkg->provides[k]
++                             : pkg->replaces[k]);
++                       if (fnmatch(target, apkg->name, 0) == 0) {
++                            ipkg_message(conf, IPKG_ERROR, "    %s", pkg->name);
++                            if (strcmp(target, apkg->name) != 0)
++                                 ipkg_message(conf, IPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
++                            ipkg_message(conf, IPKG_ERROR, "\n");
++                       }
++                  }
++             }
++        }
++        pkg_vec_free(available_pkgs);
++     }
++     return 0;
++}
++
++static int ipkg_whatprovides_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     return ipkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
++}
++
++static int ipkg_whatreplaces_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     return ipkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
++}
++
++static int ipkg_search_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     int i;
++
++     pkg_vec_t *installed;
++     pkg_t *pkg;
++     str_list_t *installed_files;
++     str_list_elt_t *iter;
++     char *installed_file;
++
++     if (argc < 1) {
++        return EINVAL;
++     }
++ 
++     installed = pkg_vec_alloc();
++     pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
++
++     for (i=0; i < installed->len; i++) {
++        pkg = installed->pkgs[i];
++
++        installed_files = pkg_get_installed_files(pkg);
++
++        for (iter = installed_files->head; iter; iter = iter->next) {
++             installed_file = iter->data;
++             if (fnmatch(argv[0], installed_file, 0)==0)  {
++#ifndef IPKG_LIB
++                  printf("%s: %s\n", pkg->name, installed_file);
++#else
++                      if (ipkg_cb_list) ipkg_cb_list(pkg->name, 
++                                                     installed_file, 
++                                                     pkg_version_str_alloc(pkg), 
++                                                     pkg->state_status, p_userdata);
++#endif                           
++             }                
++        }
++
++        pkg_free_installed_files(pkg);
++     }
++
++     /* XXX: CLEANUP: It's not obvious from the name of
++      pkg_hash_fetch_all_installed that we need to call
++      pkg_vec_free to avoid a memory leak. */
++     pkg_vec_free(installed);
++
++     return 0;
++}
++
++static int ipkg_compare_versions_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     if (argc == 3) {
++        /* this is a bit gross */
++        struct pkg p1, p2;
++        parseVersion(&p1, argv[0]); 
++        parseVersion(&p2, argv[2]); 
++        return pkg_version_satisfied(&p1, &p2, argv[1]);
++     } else {
++        ipkg_message(conf, IPKG_ERROR,
++                     "ipkg compare_versions <v1> <op> <v2>\n"
++                     "<op> is one of <= >= << >> =\n");
++        return -1;
++     }
++}
++
++#ifndef HOST_CPU_STR
++#define HOST_CPU_STR__(X) #X
++#define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
++#define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
++#endif
++
++static int ipkg_print_architecture_cmd(ipkg_conf_t *conf, int argc, char **argv)
++{
++     nv_pair_list_elt_t *l;
++
++     l = conf->arch_list.head;
++     while (l) {
++        nv_pair_t *nv = l->data;
++        printf("arch %s %s\n", nv->name, nv->value);
++        l = l->next;
++     }
++     return 0;
++}
++
++
+Index: busybox-1.7.2/archival/libipkg/ipkg_cmd.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/ipkg_cmd.h  2007-10-04 17:14:22.493023228 +0200
+@@ -0,0 +1,46 @@
++/* ipkg_cmd.h - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#ifndef IPKG_CMD_H
++#define IPKG_CMD_H
++
++typedef int (*ipkg_cmd_fun_t)(ipkg_conf_t *conf, int argc, const char **argv);
++
++struct ipkg_cmd
++{
++    char *name;
++    int requires_args;
++    ipkg_cmd_fun_t fun;
++};
++typedef struct ipkg_cmd ipkg_cmd_t;
++
++ipkg_cmd_t *ipkg_cmd_find(const char *name);
++#ifdef IPKG_LIB
++int ipkg_cmd_exec(ipkg_cmd_t *cmd, ipkg_conf_t *conf, int argc, 
++                  const char **argv, void *userdata);
++#else
++int ipkg_cmd_exec(ipkg_cmd_t *cmd, ipkg_conf_t *conf, int argc, const char **argv);
++#endif
++int ipkg_multiple_files_scan (ipkg_conf_t *conf, int argc, char *argv[]);
++/* install any packges with state_want == SW_INSTALL */
++int ipkg_install_wanted_packages(ipkg_conf_t *conf);
++/* ensure that all dependences are satisfied */
++int ipkg_configure_packages(ipkg_conf_t *conf, char *pkg_name);
++
++int pkg_mark_provides(pkg_t *pkg);
++
++#endif
+Index: busybox-1.7.2/archival/libipkg/ipkg_conf.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/ipkg_conf.c 2007-10-04 17:14:22.513024368 +0200
+@@ -0,0 +1,711 @@
++/* ipkg_conf.c - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#include <glob.h>
++
++#include "ipkg.h"
++#include "ipkg_conf.h"
++
++#include "xregex.h"
++#include "sprintf_alloc.h"
++#include "ipkg_conf.h"
++#include "ipkg_message.h"
++#include "file_util.h"
++#include "str_util.h"
++#include "xsystem.h"
++
++
++ipkg_conf_t *global_conf;
++
++static int ipkg_conf_parse_file(ipkg_conf_t *conf, const char *filename,
++                              pkg_src_list_t *pkg_src_list,
++                              nv_pair_list_t *tmp_dest_nv_pair_list,
++                              char **tmp_lists_dir);
++static int ipkg_init_options_array(const ipkg_conf_t *conf, ipkg_option_t **options);
++static int ipkg_conf_set_option(const ipkg_option_t *options,
++                              const char *name, const char *value);
++static int ipkg_conf_set_default_dest(ipkg_conf_t *conf,
++                                    const char *default_dest_name);
++static int set_and_load_pkg_src_list(ipkg_conf_t *conf,
++                                   pkg_src_list_t *nv_pair_list);
++static int set_and_load_pkg_dest_list(ipkg_conf_t *conf,
++                                    nv_pair_list_t *nv_pair_list, char * lists_dir);
++
++int ipkg_init_options_array(const ipkg_conf_t *conf, ipkg_option_t **options)
++{
++     ipkg_option_t tmp[] = {
++        { "force_defaults", IPKG_OPT_TYPE_BOOL, &conf->force_defaults },
++        { "force_depends", IPKG_OPT_TYPE_BOOL, &conf->force_depends },
++        { "force_overwrite", IPKG_OPT_TYPE_BOOL, &conf->force_overwrite },
++        { "force_downgrade", IPKG_OPT_TYPE_BOOL, &conf->force_downgrade },
++        { "force_reinstall", IPKG_OPT_TYPE_BOOL, &conf->force_reinstall },
++        { "force_space", IPKG_OPT_TYPE_BOOL, &conf->force_space },
++        { "ftp_proxy", IPKG_OPT_TYPE_STRING, &conf->ftp_proxy },
++        { "http_proxy", IPKG_OPT_TYPE_STRING, &conf->http_proxy },
++        { "multiple_providers", IPKG_OPT_TYPE_BOOL, &conf->multiple_providers },
++        { "no_proxy", IPKG_OPT_TYPE_STRING, &conf->no_proxy },
++        { "test", IPKG_OPT_TYPE_INT, &conf->noaction },
++        { "noaction", IPKG_OPT_TYPE_INT, &conf->noaction },
++        { "nodeps", IPKG_OPT_TYPE_BOOL, &conf->nodeps },
++        { "offline_root", IPKG_OPT_TYPE_STRING, &conf->offline_root },
++        { "offline_root_post_script_cmd", IPKG_OPT_TYPE_STRING, &conf->offline_root_post_script_cmd },
++        { "offline_root_pre_script_cmd", IPKG_OPT_TYPE_STRING, &conf->offline_root_pre_script_cmd },
++        { "proxy_passwd", IPKG_OPT_TYPE_STRING, &conf->proxy_passwd },
++        { "proxy_user", IPKG_OPT_TYPE_STRING, &conf->proxy_user },
++        { "query-all", IPKG_OPT_TYPE_BOOL, &conf->query_all },
++        { "verbose-wget", IPKG_OPT_TYPE_BOOL, &conf->verbose_wget },
++        { "verbosity", IPKG_OPT_TYPE_BOOL, &conf->verbosity },
++        { NULL }
++     };
++
++     *options = (ipkg_option_t *)malloc(sizeof(tmp));
++     if ( options == NULL ){
++        fprintf(stderr,"%s: Unable to allocate memory\n",__FUNCTION__);
++        return -1;
++     }
++
++     memcpy(*options, tmp, sizeof(tmp));
++     return 0;
++};
++
++static void ipkg_conf_override_string(char **conf_str, char *arg_str) 
++{
++     if (arg_str) {
++        if (*conf_str) {
++             free(*conf_str);
++        }
++        *conf_str = strdup(arg_str);
++     }
++}
++
++static void ipkg_conf_free_string(char **conf_str)
++{
++     if (*conf_str) {
++        free(*conf_str);
++        *conf_str = NULL;
++     }
++}
++
++int ipkg_conf_init(ipkg_conf_t *conf, const args_t *args)
++{
++     int err;
++     char *tmp_dir_base;
++     nv_pair_list_t tmp_dest_nv_pair_list;
++     char * lists_dir =NULL;
++     glob_t globbuf;
++     char *etc_ipkg_conf_pattern = "/etc/ipkg/*.conf";
++     char *pending_dir  =NULL;
++
++     memset(conf, 0, sizeof(ipkg_conf_t));
++
++     pkg_src_list_init(&conf->pkg_src_list);
++
++     nv_pair_list_init(&tmp_dest_nv_pair_list);
++     pkg_dest_list_init(&conf->pkg_dest_list);
++
++     nv_pair_list_init(&conf->arch_list);
++
++     conf->restrict_to_default_dest = 0;
++     conf->default_dest = NULL;
++
++
++     if (args->tmp_dir)
++        tmp_dir_base = args->tmp_dir;
++     else 
++        tmp_dir_base = getenv("TMPDIR");
++     sprintf_alloc(&conf->tmp_dir, "%s/%s",
++                 tmp_dir_base ? tmp_dir_base : IPKG_CONF_DEFAULT_TMP_DIR_BASE,
++                 IPKG_CONF_TMP_DIR_SUFFIX);
++     conf->tmp_dir = mkdtemp(conf->tmp_dir);
++     if (conf->tmp_dir == NULL) {
++        fprintf(stderr, "%s: Failed to create temporary directory `%s': %s\n",
++                __FUNCTION__, conf->tmp_dir, strerror(errno));
++        return errno;
++     }
++
++     conf->force_depends = 0;
++     conf->force_defaults = 0;
++     conf->force_overwrite = 0;
++     conf->force_downgrade = 0;
++     conf->force_reinstall = 0;
++     conf->force_space = 0;
++     conf->force_removal_of_essential_packages = 0;
++     conf->force_removal_of_dependent_packages = 0;
++     conf->nodeps = 0;
++     conf->verbose_wget = 0;
++     conf->offline_root = NULL;
++     conf->offline_root_pre_script_cmd = NULL;
++     conf->offline_root_post_script_cmd = NULL;
++     conf->multiple_providers = 0;
++     conf->verbosity = 1;
++     conf->noaction = 0;
++
++     conf->http_proxy = NULL;
++     conf->ftp_proxy = NULL;
++     conf->no_proxy = NULL;
++     conf->proxy_user = NULL;
++     conf->proxy_passwd = NULL;
++
++     pkg_hash_init("pkg-hash", &conf->pkg_hash, IPKG_CONF_DEFAULT_HASH_LEN);
++     hash_table_init("file-hash", &conf->file_hash, IPKG_CONF_DEFAULT_HASH_LEN);
++     hash_table_init("obs-file-hash", &conf->obs_file_hash, IPKG_CONF_DEFAULT_HASH_LEN);
++     lists_dir=(char *)malloc(1);
++     lists_dir[0]='\0';
++     if (args->conf_file) {
++        struct stat stat_buf;
++        err = stat(args->conf_file, &stat_buf);
++        if (err == 0)
++             if (ipkg_conf_parse_file(conf, args->conf_file,
++                                  &conf->pkg_src_list, &tmp_dest_nv_pair_list,&lists_dir)<0) {
++                   /* Memory leakage from ipkg_conf_parse-file */
++                   return -1;
++               }
++                   
++     }
++
++     /* if (!lists_dir ){*/
++     if (strlen(lists_dir)<=1 ){
++        lists_dir = realloc(lists_dir,strlen(IPKG_CONF_LISTS_DIR)+2);
++        sprintf (lists_dir,"%s",IPKG_CONF_LISTS_DIR);
++     }
++
++     if (args->offline_root) {
++            char *tmp = malloc(strlen(lists_dir) + strlen(args->offline_root) + 1);
++            sprintf_alloc(&tmp, "%s/%s",args->offline_root,lists_dir);
++            free(lists_dir);
++            lists_dir = tmp;
++     }
++
++     pending_dir = malloc(strlen(lists_dir)+strlen("/pending")+5);
++     snprintf(pending_dir,strlen(lists_dir)+strlen("/pending") ,"%s%s",lists_dir,"/pending");
++
++     conf->lists_dir = strdup(lists_dir);
++     conf->pending_dir = strdup(pending_dir);
++
++     if (args->offline_root) 
++        sprintf_alloc(&etc_ipkg_conf_pattern, "%s/etc/ipkg/*.conf", args->offline_root);
++     memset(&globbuf, 0, sizeof(globbuf));
++     err = glob(etc_ipkg_conf_pattern, 0, NULL, &globbuf);
++     if (!err) {
++        int i;
++        for (i = 0; i < globbuf.gl_pathc; i++) {
++             if (globbuf.gl_pathv[i]) 
++                  if ( ipkg_conf_parse_file(conf, globbuf.gl_pathv[i], 
++                                       &conf->pkg_src_list, &tmp_dest_nv_pair_list,&lists_dir)<0) {
++                        /* Memory leakage from ipkg_conf_parse-file */
++                        return -1;
++                  }
++        }
++     }
++     globfree(&globbuf);
++
++     /* if no architectures were defined, then default all, noarch, and host architecture */
++     if (nv_pair_list_empty(&conf->arch_list)) {
++        nv_pair_list_append(&conf->arch_list, "all", "1");
++        nv_pair_list_append(&conf->arch_list, "noarch", "1");
++        nv_pair_list_append(&conf->arch_list, HOST_CPU_STR, "10");
++     }
++
++     /* Even if there is no conf file, we'll need at least one dest. */
++     if (tmp_dest_nv_pair_list.head == NULL) {
++        nv_pair_list_append(&tmp_dest_nv_pair_list,
++                            IPKG_CONF_DEFAULT_DEST_NAME,
++                            IPKG_CONF_DEFAULT_DEST_ROOT_DIR);
++     }
++
++     /* After parsing the file, set options from command-line, (so that
++      command-line arguments take precedence) */
++     /* XXX: CLEANUP: The interaction between args.c and ipkg_conf.c
++      really needs to be cleaned up. There is so much duplication
++      right now it is ridiculous. Maybe ipkg_conf_t should just save
++      a pointer to args_t (which could then not be freed), rather
++      than duplicating every field here? */
++     if (args->force_depends) {
++        conf->force_depends = 1;
++     }
++     if (args->force_defaults) {
++        conf->force_defaults = 1;
++     }
++     if (args->force_overwrite) {
++        conf->force_overwrite = 1;
++     }
++     if (args->force_downgrade) {
++        conf->force_downgrade = 1;
++     }
++     if (args->force_reinstall) {
++        conf->force_reinstall = 1;
++     }
++     if (args->force_removal_of_dependent_packages) {
++        conf->force_removal_of_dependent_packages = 1;
++     }
++     if (args->force_removal_of_essential_packages) {
++        conf->force_removal_of_essential_packages = 1;
++     }
++     if (args->nodeps) {
++        conf->nodeps = 1;
++     }
++     if (args->noaction) {
++        conf->noaction = 1;
++     }
++     if (args->query_all) {
++        conf->query_all = 1;
++     }
++     if (args->verbose_wget) {
++        conf->verbose_wget = 1;
++     }
++     if (args->multiple_providers) {
++        conf->multiple_providers = 1;
++     }
++     if (args->verbosity != conf->verbosity) {
++        conf->verbosity = args->verbosity;
++     } 
++
++     ipkg_conf_override_string(&conf->offline_root, 
++                             args->offline_root);
++     ipkg_conf_override_string(&conf->offline_root_pre_script_cmd, 
++                             args->offline_root_pre_script_cmd);
++     ipkg_conf_override_string(&conf->offline_root_post_script_cmd, 
++                             args->offline_root_post_script_cmd);
++
++/* Pigi: added a flag to disable the checking of structures if the command does not need to 
++         read anything from there.
++*/
++     if ( !(args->nocheckfordirorfile)){
++        /* need to run load the source list before dest list -Jamey */
++        if ( !(args->noreadfeedsfile))
++           set_and_load_pkg_src_list(conf, &conf->pkg_src_list);
++   
++        /* Now that we have resolved conf->offline_root, we can commit to
++         the directory names for the dests and load in all the package
++         lists. */
++        set_and_load_pkg_dest_list(conf, &tmp_dest_nv_pair_list,lists_dir);
++   
++        if (args->dest) {
++           err = ipkg_conf_set_default_dest(conf, args->dest);
++           if (err) {
++                return err;
++           }
++        }
++     }
++     nv_pair_list_deinit(&tmp_dest_nv_pair_list);
++     free(lists_dir);
++     free(pending_dir);
++
++     return 0;
++}
++
++void ipkg_conf_deinit(ipkg_conf_t *conf)
++{
++#ifdef IPKG_DEBUG_NO_TMP_CLEANUP
++#error
++     fprintf(stderr, "%s: Not cleaning up %s since ipkg compiled "
++           "with IPKG_DEBUG_NO_TMP_CLEANUP\n",
++           __FUNCTION__, conf->tmp_dir);
++#else
++     int err;
++
++     err = rmdir(conf->tmp_dir);
++     if (err) {
++        if (errno == ENOTEMPTY) {
++             char *cmd;
++             sprintf_alloc(&cmd, "rm -fr %s\n", conf->tmp_dir);
++             err = xsystem(cmd);
++             free(cmd);
++        }
++        if (err)
++             fprintf(stderr, "WARNING: Unable to remove temporary directory: %s: %s\n", conf->tmp_dir, strerror(errno));
++     }
++#endif /* IPKG_DEBUG_NO_TMP_CLEANUP */
++
++     free(conf->tmp_dir); /*XXX*/
++
++     pkg_src_list_deinit(&conf->pkg_src_list);
++     pkg_dest_list_deinit(&conf->pkg_dest_list);
++     nv_pair_list_deinit(&conf->arch_list);
++     if (&conf->pkg_hash)
++                  pkg_hash_deinit(&conf->pkg_hash);
++     if (&conf->file_hash)
++                  hash_table_deinit(&conf->file_hash);
++     if (&conf->obs_file_hash)
++                  hash_table_deinit(&conf->obs_file_hash);
++
++     ipkg_conf_free_string(&conf->offline_root);
++     ipkg_conf_free_string(&conf->offline_root_pre_script_cmd);
++     ipkg_conf_free_string(&conf->offline_root_post_script_cmd);
++
++     if (conf->verbosity > 1) { 
++        int i;
++        hash_table_t *hashes[] = {
++             &conf->pkg_hash,
++             &conf->file_hash,
++             &conf->obs_file_hash };
++        for (i = 0; i < 3; i++) {
++             hash_table_t *hash = hashes[i];
++             int c = 0;
++             int n_conflicts = 0;
++             int j;
++             for (j = 0; j < hash->n_entries; j++) {
++                  int len = 0;
++                  hash_entry_t *e = &hash->entries[j];
++                  if (e->next)
++                       n_conflicts++;
++                  while (e && e->key) {
++                       len++;
++                       e = e->next;
++                  }
++                  if (len > c) 
++                       c = len;
++             }
++             ipkg_message(conf, IPKG_DEBUG, "hash_table[%s] n_buckets=%d n_elements=%d max_conflicts=%d n_conflicts=%d\n", 
++                          hash->name, hash->n_entries, hash->n_elements, c, n_conflicts);
++             hash_table_deinit(hash);
++        }
++     }
++}
++
++static int ipkg_conf_set_default_dest(ipkg_conf_t *conf,
++                                    const char *default_dest_name)
++{
++     pkg_dest_list_elt_t *iter;
++     pkg_dest_t *dest;
++
++     for (iter = conf->pkg_dest_list.head; iter; iter = iter->next) {
++        dest = iter->data;
++        if (strcmp(dest->name, default_dest_name) == 0) {
++             conf->default_dest = dest;
++             conf->restrict_to_default_dest = 1;
++             return 0;
++        }
++     }
++
++     fprintf(stderr, "ERROR: Unknown dest name: `%s'\n", default_dest_name);
++
++     return 1;
++}
++
++static int set_and_load_pkg_src_list(ipkg_conf_t *conf, pkg_src_list_t *pkg_src_list)
++{
++     pkg_src_list_elt_t *iter;
++     pkg_src_t *src;
++     char *list_file;
++
++     for (iter = pkg_src_list->head; iter; iter = iter->next) {
++          src = iter->data;
++        if (src == NULL) {
++             continue;
++        }
++
++        sprintf_alloc(&list_file, "%s/%s", 
++                        conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir, 
++                        src->name);
++
++        if (file_exists(list_file)) {
++             pkg_hash_add_from_file(conf, list_file, src, NULL, 0);
++        }
++        free(list_file);
++     }
++
++     return 0;
++}
++
++static int set_and_load_pkg_dest_list(ipkg_conf_t *conf, nv_pair_list_t *nv_pair_list, char *lists_dir )
++{
++     nv_pair_list_elt_t *iter;
++     nv_pair_t *nv_pair;
++     pkg_dest_t *dest;
++     char *root_dir;
++
++     for (iter = nv_pair_list->head; iter; iter = iter->next) {
++        nv_pair = iter->data;
++
++        if (conf->offline_root) {
++             sprintf_alloc(&root_dir, "%s%s", conf->offline_root, nv_pair->value);
++        } else {
++             root_dir = strdup(nv_pair->value);
++        }
++        dest = pkg_dest_list_append(&conf->pkg_dest_list, nv_pair->name, root_dir, lists_dir);
++        free(root_dir);
++        if (dest == NULL) {
++             continue;
++        }
++        if (conf->default_dest == NULL) {
++             conf->default_dest = dest;
++        }
++        if (file_exists(dest->status_file_name)) {
++             pkg_hash_add_from_file(conf, dest->status_file_name,
++                                    NULL, dest, 1);
++        }
++     }
++
++     return 0;
++}
++
++static int ipkg_conf_parse_file(ipkg_conf_t *conf, const char *filename,
++                              pkg_src_list_t *pkg_src_list,
++                              nv_pair_list_t *tmp_dest_nv_pair_list,
++                              char **lists_dir)
++{
++     ipkg_option_t * options;
++     FILE *file = fopen(filename, "r");
++     regex_t valid_line_re, comment_re;
++#define regmatch_size 12
++     regmatch_t regmatch[regmatch_size];
++
++     if (ipkg_init_options_array(conf, &options)<0)
++        return ENOMEM;
++
++     if (file == NULL) {
++        fprintf(stderr, "%s: failed to open %s: %s\n",
++                __FUNCTION__, filename, strerror(errno));
++        free(options);
++        return errno;
++     }
++     ipkg_message(conf, IPKG_NOTICE, "loading conf file %s\n", filename);
++
++     xregcomp(&comment_re, 
++                  "^[[:space:]]*(#.*|[[:space:]]*)$",
++                  REG_EXTENDED);
++     xregcomp(&valid_line_re, "^[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))([[:space:]]+([^[:space:]]+))?[[:space:]]*$", REG_EXTENDED);
++
++     while(1) {
++        int line_num = 0;
++        char *line;
++        char *type, *name, *value, *extra;
++
++        line = file_read_line_alloc(file);
++        line_num++;
++        if (line == NULL) {
++             break;
++        }
++
++        str_chomp(line);
++
++        if (regexec(&comment_re, line, 0, 0, 0) == 0) {
++             goto NEXT_LINE;
++        }
++
++        if (regexec(&valid_line_re, line, regmatch_size, regmatch, 0) == REG_NOMATCH) {
++             str_chomp(line);
++             fprintf(stderr, "%s:%d: Ignoring invalid line: `%s'\n",
++                     filename, line_num, line);
++             goto NEXT_LINE;
++        }
++
++        /* This has to be so ugly to deal with optional quotation marks */
++        if (regmatch[2].rm_so > 0) {
++             type = strndup(line + regmatch[2].rm_so,
++                            regmatch[2].rm_eo - regmatch[2].rm_so);
++        } else {
++             type = strndup(line + regmatch[3].rm_so,
++                            regmatch[3].rm_eo - regmatch[3].rm_so);
++        }
++        if (regmatch[5].rm_so > 0) {
++             name = strndup(line + regmatch[5].rm_so,
++                            regmatch[5].rm_eo - regmatch[5].rm_so);
++        } else {
++             name = strndup(line + regmatch[6].rm_so,
++                            regmatch[6].rm_eo - regmatch[6].rm_so);
++        }
++        if (regmatch[8].rm_so > 0) {
++             value = strndup(line + regmatch[8].rm_so,
++                             regmatch[8].rm_eo - regmatch[8].rm_so);
++        } else {
++             value = strndup(line + regmatch[9].rm_so,
++                             regmatch[9].rm_eo - regmatch[9].rm_so);
++        }
++        extra = NULL;
++        if (regmatch[11].rm_so > 0) {
++             extra = strndup (line + regmatch[11].rm_so,
++                              regmatch[11].rm_eo - regmatch[11].rm_so);
++        }
++
++        /* We use the tmp_dest_nv_pair_list below instead of
++           conf->pkg_dest_list because we might encounter an
++           offline_root option later and that would invalidate the
++           directories we would have computed in
++           pkg_dest_list_init. (We do a similar thing with
++           tmp_src_nv_pair_list for sake of symmetry.) */
++        if (strcmp(type, "option") == 0) {
++             ipkg_conf_set_option(options, name, value);
++        } else if (strcmp(type, "src") == 0) {
++             if (!nv_pair_list_find((nv_pair_list_t *)pkg_src_list, name)) {
++                  pkg_src_list_append (pkg_src_list, name, value, extra, 0);
++             } else {
++                  ipkg_message(conf, IPKG_ERROR, "ERROR: duplicate src declaration.  Skipping:\n\t src %s %s\n",
++                               name, value);
++             }
++        } else if (strcmp(type, "src/gz") == 0) {
++             if (!nv_pair_list_find((nv_pair_list_t *)pkg_src_list, name)) {
++                  pkg_src_list_append (pkg_src_list, name, value, extra, 1);
++             } else {
++                  ipkg_message(conf, IPKG_ERROR, "ERROR: duplicate src declaration.  Skipping:\n\t src %s %s\n",
++                               name, value);
++             }
++        } else if (strcmp(type, "dest") == 0) {
++             nv_pair_list_append(tmp_dest_nv_pair_list, name, value);
++        } else if (strcmp(type, "lists_dir") == 0) {
++             *lists_dir = realloc(*lists_dir,strlen(value)+1);
++               if (*lists_dir == NULL) {
++                  ipkg_message(conf, IPKG_ERROR, "ERROR: Not enough memory\n");
++                  free(options);
++                  return EINVAL;
++               }
++               sprintf (*lists_dir,"%s",value);
++        } else if (strcmp(type, "arch") == 0) {
++             ipkg_message(conf, IPKG_INFO, "supported arch %s priority (%s)\n", name, value);
++             if (!value) {
++                  ipkg_message(conf, IPKG_NOTICE, "defaulting architecture %s priority to 10\n", name);
++                  value = strdup("10");
++             }
++             nv_pair_list_append(&conf->arch_list, strdup(name), strdup(value));
++        } else {
++             fprintf(stderr, "WARNING: Ignoring unknown configuration "
++                     "parameter: %s %s %s\n", type, name, value);
++             free(options);
++             return EINVAL;
++        }
++
++        free(type);
++        free(name);
++        free(value);
++        if (extra)
++             free (extra);
++
++     NEXT_LINE:
++        free(line);
++     }
++
++     free(options);
++     regfree(&comment_re);
++     regfree(&valid_line_re);
++     fclose(file);
++
++     return 0;
++}
++
++static int ipkg_conf_set_option(const ipkg_option_t *options,
++                              const char *name, const char *value)
++{
++     int i = 0;
++     while (options[i].name) {
++        if (strcmp(options[i].name, name) == 0) {
++             switch (options[i].type) {
++             case IPKG_OPT_TYPE_BOOL:
++                  *((int *)options[i].value) = 1;
++                  return 0;
++             case IPKG_OPT_TYPE_INT:
++                  if (value) {
++                       *((int *)options[i].value) = atoi(value);
++                       return 0;
++                  } else {
++                       printf("%s: Option %s need an argument\n",
++                              __FUNCTION__, name);
++                       return EINVAL;
++                  }               
++             case IPKG_OPT_TYPE_STRING:
++                  if (value) {
++                       *((char **)options[i].value) = strdup(value);
++                       return 0;
++                  } else {
++                       printf("%s: Option %s need an argument\n",
++                              __FUNCTION__, name);
++                       return EINVAL;
++                  }
++             }
++        }
++        i++;
++     }
++    
++     fprintf(stderr, "%s: Unrecognized option: %s=%s\n",
++           __FUNCTION__, name, value);
++     return EINVAL;
++}
++
++int ipkg_conf_write_status_files(ipkg_conf_t *conf)
++{
++     pkg_dest_list_elt_t *iter;
++     pkg_dest_t *dest;
++     pkg_vec_t *all;
++     pkg_t *pkg;
++     register int i;
++     int err;
++
++     if (conf->noaction)
++        return 0;
++     for (iter = conf->pkg_dest_list.head; iter; iter = iter->next) {
++        dest = iter->data;
++        dest->status_file = fopen(dest->status_file_tmp_name, "w");
++        if (dest->status_file == NULL) {
++             fprintf(stderr, "%s: Can't open status file: %s for writing: %s\n",
++                     __FUNCTION__, dest->status_file_name, strerror(errno));
++        }
++     }
++
++     all = pkg_vec_alloc();
++     pkg_hash_fetch_available(&conf->pkg_hash, all);
++
++     for(i = 0; i < all->len; i++) {
++        pkg = all->pkgs[i];
++        /* We don't need most uninstalled packages in the status file */
++        if (pkg->state_status == SS_NOT_INSTALLED
++            && (pkg->state_want == SW_UNKNOWN
++                || pkg->state_want == SW_DEINSTALL
++                || pkg->state_want == SW_PURGE)) {
++             continue;
++        }
++        if (!pkg) {
++          fprintf(stderr, "Null package\n");
++        }
++        if (pkg->dest == NULL) {
++             fprintf(stderr, "%s: ERROR: Can't write status for "
++                     "package %s since it has a NULL dest\n",
++                     __FUNCTION__, pkg->name);
++             continue;
++        }
++        if (pkg->dest->status_file) {
++             pkg_print_status(pkg, pkg->dest->status_file);
++        }
++     }
++
++     pkg_vec_free(all);
++
++     for (iter = conf->pkg_dest_list.head; iter; iter = iter->next) {
++        dest = iter->data;
++        if (dest->status_file) {
++             err = ferror(dest->status_file);
++             fclose(dest->status_file);
++             dest->status_file = NULL;
++             if (!err) {
++                  file_move(dest->status_file_tmp_name, dest->status_file_name);
++             } else {
++                  fprintf(stderr, "%s: ERROR: An error has occurred writing %s, "
++                          "retaining old %s\n", __FUNCTION__, 
++                          dest->status_file_tmp_name, dest->status_file_name);
++             }
++        }
++     }
++
++     return 0;
++}
++
++
++char *root_filename_alloc(ipkg_conf_t *conf, char *filename)
++{
++     char *root_filename;
++     sprintf_alloc(&root_filename, "%s%s", (conf->offline_root ? conf->offline_root : ""), filename);
++     return root_filename;
++}
+Index: busybox-1.7.2/archival/libipkg/ipkg_conf.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/ipkg_conf.h 2007-10-04 17:14:22.545026188 +0200
+@@ -0,0 +1,107 @@
++/* ipkg_conf.h - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#ifndef IPKG_CONF_H
++#define IPKG_CONF_H
++
++typedef struct ipkg_conf ipkg_conf_t;
++
++#include "hash_table.h"
++#include "ipkg.h"
++#include "args.h"
++#include "pkg.h"
++#include "pkg_hash.h"
++#include "pkg_src_list.h"
++#include "pkg_dest_list.h"
++#include "nv_pair_list.h"
++
++#define IPKG_CONF_DEFAULT_TMP_DIR_BASE "/tmp"
++#define IPKG_CONF_TMP_DIR_SUFFIX "ipkg-XXXXXX"
++#define IPKG_CONF_LISTS_DIR  IPKG_STATE_DIR_PREFIX "/lists"
++#define IPKG_CONF_PENDING_DIR IPKG_STATE_DIR_PREFIX "/pending"
++
++/* In case the config file defines no dest */
++#define IPKG_CONF_DEFAULT_DEST_NAME "root"
++#define IPKG_CONF_DEFAULT_DEST_ROOT_DIR "/"
++
++#define IPKG_CONF_DEFAULT_HASH_LEN 1024
++
++struct ipkg_conf
++{
++     pkg_src_list_t pkg_src_list;
++     pkg_dest_list_t pkg_dest_list;
++     nv_pair_list_t arch_list;
++
++     int restrict_to_default_dest;
++     pkg_dest_t *default_dest;
++
++     char *tmp_dir;
++     const char *lists_dir;
++     const char *pending_dir;
++
++     /* options */
++     int force_depends;
++     int force_defaults;
++     int force_overwrite;
++     int force_downgrade;
++     int force_reinstall;
++     int force_space;
++     int force_removal_of_dependent_packages;
++     int force_removal_of_essential_packages;
++     int nodeps; /* do not follow dependences */
++     int verbose_wget;
++     int multiple_providers;
++     char *offline_root;
++     char *offline_root_pre_script_cmd;
++     char *offline_root_post_script_cmd;
++     int query_all;
++     int verbosity;
++     int noaction;
++
++     /* proxy options */
++     char *http_proxy;
++     char *ftp_proxy;
++     char *no_proxy;
++     char *proxy_user;
++     char *proxy_passwd;
++
++     hash_table_t pkg_hash;
++     hash_table_t file_hash;
++     hash_table_t obs_file_hash;
++};
++
++enum ipkg_option_type {
++     IPKG_OPT_TYPE_BOOL,
++     IPKG_OPT_TYPE_INT,
++     IPKG_OPT_TYPE_STRING
++};
++typedef enum ipkg_option_type ipkg_option_type_t;
++
++typedef struct ipkg_option ipkg_option_t;
++struct ipkg_option {
++     const char *name;
++     const ipkg_option_type_t type;
++     const void *value;
++};
++
++int ipkg_conf_init(ipkg_conf_t *conf, const args_t *args);
++void ipkg_conf_deinit(ipkg_conf_t *conf);
++
++int ipkg_conf_write_status_files(ipkg_conf_t *conf);
++char *root_filename_alloc(ipkg_conf_t *conf, char *filename);
++
++#endif
+Index: busybox-1.7.2/archival/libipkg/ipkg_configure.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/ipkg_configure.c    2007-10-04 17:14:22.569027557 +0200
+@@ -0,0 +1,40 @@
++/* ipkg_configure.c - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#include "ipkg.h"
++
++#include "ipkg_configure.h"
++
++int ipkg_configure(ipkg_conf_t *conf, pkg_t *pkg)
++{
++    int err;
++
++    /* DPKG_INCOMPATIBILITY:
++       dpkg actually does some conffile handling here, rather than at the
++       end of ipkg_install(). Do we care? */
++    /* DPKG_INCOMPATIBILITY:
++       dpkg actually includes a version number to this script call */
++    err = pkg_run_script(conf, pkg, "postinst", "configure");
++    if (err) {
++      printf("ERROR: %s.postinst returned %d\n", pkg->name, err);
++      return err;
++    }
++
++    ipkg_state_changed++;
++    return 0;
++}
++
+Index: busybox-1.7.2/archival/libipkg/ipkg_configure.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/ipkg_configure.h    2007-10-04 17:14:22.593028927 +0200
+@@ -0,0 +1,25 @@
++/* ipkg_configure.h - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#ifndef IPKG_CONFIGURE_H
++#define IPKG_CONFIGURE_H
++
++#include "ipkg_conf.h"
++
++int ipkg_configure(ipkg_conf_t *ipkg_conf, pkg_t *pkg);
++
++#endif
+Index: busybox-1.7.2/archival/libipkg/ipkg_download.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/ipkg_download.c     2007-10-04 17:14:22.617030294 +0200
+@@ -0,0 +1,195 @@
++/* ipkg_download.c - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#include "ipkg.h"
++#include "ipkg_download.h"
++#include "ipkg_message.h"
++
++#include "sprintf_alloc.h"
++#include "xsystem.h"
++#include "file_util.h"
++#include "str_util.h"
++
++int ipkg_download(ipkg_conf_t *conf, const char *src, const char *dest_file_name)
++{
++    int err = 0;
++
++    char *src_basec = strdup(src);
++    char *src_base = basename(src_basec);
++    char *tmp_file_location;
++    char *cmd;
++
++    ipkg_message(conf,IPKG_NOTICE,"Downloading %s\n", src);
++      
++    fflush(stdout);
++    
++    if (str_starts_with(src, "file:")) {
++      int ret;
++      const char *file_src = src + 5;
++      ipkg_message(conf,IPKG_INFO,"Copying %s to %s...", file_src, dest_file_name);
++      ret = file_copy(src + 5, dest_file_name);
++      ipkg_message(conf,IPKG_INFO,"Done.\n");
++      return ret;
++    }
++
++    sprintf_alloc(&tmp_file_location, "%s/%s", conf->tmp_dir, src_base);
++    err = unlink(tmp_file_location);
++    if (err && errno != ENOENT) {
++      ipkg_message(conf,IPKG_ERROR, "%s: ERROR: failed to unlink %s: %s\n",
++              __FUNCTION__, tmp_file_location, strerror(errno));
++      free(tmp_file_location);
++      return errno;
++    }
++
++    if (conf->http_proxy) {
++      ipkg_message(conf,IPKG_DEBUG,"Setting environment variable: http_proxy = %s\n", conf->http_proxy);
++      setenv("http_proxy", conf->http_proxy, 1);
++    }
++    if (conf->ftp_proxy) {
++      ipkg_message(conf,IPKG_DEBUG,"Setting environment variable: ftp_proxy = %s\n", conf->ftp_proxy);
++      setenv("ftp_proxy", conf->ftp_proxy, 1);
++    }
++    if (conf->no_proxy) {
++      ipkg_message(conf,IPKG_DEBUG,"Setting environment variable: no_proxy = %s\n", conf->no_proxy);
++      setenv("no_proxy", conf->no_proxy, 1);
++    }
++
++    /* XXX: BUG rewrite to use execvp or else busybox's internal wget -Jamey 7/23/2002 */ 
++    sprintf_alloc(&cmd, "wget --passive-ftp %s %s%s %s%s %s -P %s %s",
++                (conf->http_proxy || conf->ftp_proxy) ? "--proxy=on" : "",
++                conf->proxy_user ? "--proxy-user=" : "",
++                conf->proxy_user ? conf->proxy_user : "",
++                conf->proxy_passwd ? "--proxy-passwd=" : "",
++                conf->proxy_passwd ? conf->proxy_passwd : "",
++                conf->verbose_wget ? "" : "-q",
++                conf->tmp_dir,
++                src);
++    err = xsystem(cmd);
++    if (err) {
++      if (err != -1) {
++          ipkg_message(conf,IPKG_ERROR, "%s: ERROR: Command failed with return value %d: `%s'\n",
++                  __FUNCTION__, err, cmd);
++      } 
++      unlink(tmp_file_location);
++      free(tmp_file_location);
++      free(src_basec);
++      free(cmd);
++      return EINVAL;
++    }
++    free(cmd);
++
++    err = file_move(tmp_file_location, dest_file_name);
++
++    free(tmp_file_location);
++    free(src_basec);
++
++    if (err) {
++      return err;
++    }
++
++    return 0;
++}
++
++int ipkg_download_pkg(ipkg_conf_t *conf, pkg_t *pkg, const char *dir)
++{
++    int err;
++    char *url;
++
++    if (pkg->src == NULL) {
++      ipkg_message(conf,IPKG_ERROR, "ERROR: Package %s (parent %s) is not available from any configured src.\n",
++              pkg->name, pkg->parent->name);
++      return -1;
++    }
++
++    sprintf_alloc(&url, "%s/%s", pkg->src->value, pkg->filename);
++
++    /* XXX: BUG: The pkg->filename might be something like
++       "../../foo.ipk". While this is correct, and exactly what we
++       want to use to construct url above, here we actually need to
++       use just the filename part, without any directory. */
++    sprintf_alloc(&pkg->local_filename, "%s/%s", dir, pkg->filename);
++
++    err = ipkg_download(conf, url, pkg->local_filename);
++    free(url);
++
++    return err;
++}
++
++/*
++ * Downloads file from url, installs in package database, return package name. 
++ */
++int ipkg_prepare_url_for_install(ipkg_conf_t *conf, const char *url, char **namep)
++{
++     int err = 0;
++     pkg_t *pkg;
++     pkg = pkg_new();
++     if (pkg == NULL)
++        return ENOMEM;
++
++     if (str_starts_with(url, "http://")
++       || str_starts_with(url, "ftp://")) {
++        char *tmp_file;
++        char *file_basec = strdup(url);
++        char *file_base = basename(file_basec);
++
++        sprintf_alloc(&tmp_file, "%s/%s", conf->tmp_dir, file_base);
++        err = ipkg_download(conf, url, tmp_file);
++        if (err)
++             return err;
++
++        err = pkg_init_from_file(pkg, tmp_file);
++        if (err)
++             return err;
++        pkg->local_filename = strdup(tmp_file);
++
++        free(tmp_file);
++        free(file_basec);
++
++     } else if (strcmp(&url[strlen(url) - 4], IPKG_PKG_EXTENSION) == 0
++              || strcmp(&url[strlen(url) - 4], DPKG_PKG_EXTENSION) == 0) {
++
++        err = pkg_init_from_file(pkg, url);
++        if (err)
++             return err;
++        pkg->local_filename = strdup(url);
++        ipkg_message(conf, IPKG_DEBUG2, "Package %s provided by hand (%s).\n", pkg->name,pkg->local_filename);
++          pkg->provided_by_hand = 1;
++
++     } else {
++       pkg_deinit(pkg);
++       free(pkg);
++       return 0;
++     }
++
++     if (!pkg->architecture) {
++        ipkg_message(conf, IPKG_ERROR, "Package %s has no Architecture defined.\n", pkg->name);
++        return -EINVAL;
++     }
++
++     pkg->dest = conf->default_dest;
++     pkg->state_want = SW_INSTALL;
++     pkg->state_flag |= SF_PREFER;
++     pkg = hash_insert_pkg(&conf->pkg_hash, pkg, 1,conf);  
++     if ( pkg == NULL ){
++        fprintf(stderr, "%s : This should never happen. Report this Bug in bugzilla please \n ",__FUNCTION__);
++        return 0;
++     }
++     if (namep) {
++        *namep = strdup(pkg->name);
++     }
++     return 0;
++}
+Index: busybox-1.7.2/archival/libipkg/ipkg_download.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/ipkg_download.h     2007-10-04 17:14:22.645031887 +0200
+@@ -0,0 +1,30 @@
++/* ipkg_download.h - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#ifndef IPKG_DOWNLOAD_H
++#define IPKG_DOWNLOAD_H
++
++#include "ipkg_conf.h"
++
++int ipkg_download(ipkg_conf_t *conf, const char *src, const char *dest_file_name);
++int ipkg_download_pkg(ipkg_conf_t *conf, pkg_t *pkg, const char *dir);
++/*
++ * Downloads file from url, installs in package database, return package name. 
++ */
++int ipkg_prepare_url_for_install(ipkg_conf_t *conf, const char *url, char **namep);
++
++#endif
+Index: busybox-1.7.2/archival/libipkg/ipkg.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/ipkg.h      2007-10-04 17:14:22.669033256 +0200
+@@ -0,0 +1,74 @@
++/* ipkg.h - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#ifndef IPKG_H
++#define IPKG_H
++
++/*
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++*/
++
++#if 0
++#define IPKG_DEBUG_NO_TMP_CLEANUP
++#endif
++
++#include "ipkg_includes.h"
++#include "ipkg_conf.h"
++#include "ipkg_message.h"
++
++#define IPKG_PKG_EXTENSION ".ipk"
++#define DPKG_PKG_EXTENSION ".deb"
++
++#define IPKG_LEGAL_PKG_NAME_CHARS "abcdefghijklmnopqrstuvwxyz0123456789.+-"
++#define IPKG_PKG_VERSION_SEP_CHAR '_'
++
++#define IPKG_STATE_DIR_PREFIX IPKGLIBDIR"/ipkg"
++#define IPKG_LISTS_DIR_SUFFIX "lists"
++#define IPKG_INFO_DIR_SUFFIX "info"
++#define IPKG_STATUS_FILE_SUFFIX "status"
++
++#define IPKG_BACKUP_SUFFIX "-ipkg.backup"
++
++#define IPKG_LIST_DESCRIPTION_LENGTH 128
++
++#define IPKG_VERSION "0.99.162"
++
++
++enum ipkg_error {
++    IPKG_SUCCESS = 0,
++    IPKG_PKG_DEPS_UNSATISFIED,
++    IPKG_PKG_IS_ESSENTIAL,
++    IPKG_PKG_HAS_DEPENDENTS,
++    IPKG_PKG_HAS_NO_CANDIDATE
++};
++typedef enum ipkg_error ipkg_error_t;
++
++extern int ipkg_state_changed;
++
++
++struct errlist {
++    char * errmsg;
++    struct errlist * next;
++} ;
++
++extern struct errlist* error_list;
++
++extern ipkg_conf_t *global_conf;
++
++#endif
+Index: busybox-1.7.2/archival/libipkg/ipkg_includes.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/ipkg_includes.h     2007-10-04 17:14:22.685034167 +0200
+@@ -0,0 +1,79 @@
++#ifndef IPKG_INCLUDES_H
++#define IPKG_INCLUDES_H
++
++/* Define to 1 if you have the <memory.h> header file. */
++#define HAVE_MEMORY_H 1
++
++/* Define to 1 if you have the <regex.h> header file. */
++#define HAVE_REGEX_H 1
++
++/* Define to 1 if you have the <stdlib.h> header file. */
++#define HAVE_STDLIB_H 1
++
++/* Define to 1 if you have the <strings.h> header file. */
++#define HAVE_STRINGS_H 1
++
++/* Define to 1 if you have the <string.h> header file. */
++#define HAVE_STRING_H 1
++
++/* Define to 1 if you have the <sys/stat.h> header file. */
++#define HAVE_SYS_STAT_H 1
++
++/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
++#define HAVE_SYS_WAIT_H 1
++
++/* Define to 1 if you have the <unistd.h> header file. */
++#define HAVE_UNISTD_H 1
++
++/* Define to 1 if you have the ANSI C header files. */
++#define STDC_HEADERS 1
++
++
++#include <stdio.h>
++
++#if STDC_HEADERS
++# include <stdlib.h>
++# include <stdarg.h>
++# include <stddef.h>
++# include <ctype.h>
++# include <errno.h>
++#else
++# if HAVE_STDLIB_H
++#  include <stdlib.h>
++# endif
++#endif
++
++#if HAVE_REGEX_H
++# include <regex.h>
++#endif
++
++#if HAVE_STRING_H
++# if !STDC_HEADERS && HAVE_MEMORY_H
++#  include <memory.h>
++# endif
++/* XXX: What's the right way to pick up GNU's strndup declaration? */
++# if __GNUC__
++#   define __USE_GNU 1
++# endif
++# include <string.h>
++# undef __USE_GNU
++#endif
++
++#if HAVE_STRINGS_H
++# include <strings.h>
++#endif
++
++#if HAVE_SYS_STAT_H
++# include <sys/stat.h>
++#endif
++
++#if HAVE_SYS_WAIT_H
++# include <sys/wait.h>
++#endif
++
++#if HAVE_UNISTD_H
++# include <sys/types.h>
++# include <unistd.h>
++#endif
++
++#endif /* IPKG_INCLUDES_H */
+Index: busybox-1.7.2/archival/libipkg/ipkg_install.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ busybox-1.7.2/archival/libipkg/ipkg_install.c      2007-10-04 17:14:22.725036446 +0200
+@@ -0,0 +1,1942 @@
++/* ipkg_install.c - the itsy package management system
++
++   Carl D. Worth
++
++   Copyright (C) 2001 University of Southern California
++
++   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, 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.
++*/
++
++#include "ipkg.h"
++#include <errno.h>
++#include <dirent.h>
++#include <glob.h>
++#include <time.h>
++#include <signal.h>
++typedef void (*sighandler_t)(int);
++
++#include "pkg.h"
++#include "pkg_hash.h"
++#include "pkg_extract.h"
++
++#include "ipkg_install.h"
++#include "ipkg_configure.h"
++#include "ipkg_download.h"
++#include "ipkg_remove.h"
++
++#include "ipkg_utils.h"
++#include "ipkg_message.h"
++
++#include "sprintf_alloc.h"
++#include "file_util.h"
++#include "str_util.h"
++#include "xsystem.h"
++#include "user.h"
++
++int satisfy_dependencies_for(ipkg_conf_t *conf, pkg_t *pkg);
++static int verify_pkg_installable(ipkg_conf_t *conf, pkg_t *pkg);
++static int unpack_pkg_control_files(ipkg_conf_t *conf, pkg_t *pkg);
++
++static int prerm_upgrade_old_pkg(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int prerm_upgrade_old_pkg_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int prerm_deconfigure_conflictors(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *conflictors);
++static int prerm_deconfigure_conflictors_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *conflictors);
++static int preinst_configure(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int preinst_configure_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int check_data_file_clashes(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int check_data_file_clashes_change(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int check_data_file_clashes_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int backup_modified_conffiles(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int backup_modified_conffiles_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int postrm_upgrade_old_pkg(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int postrm_upgrade_old_pkg_unwind(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++
++static int remove_obsolesced_files(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int install_maintainer_scripts(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
++static int remove_disappeared(ipkg_conf_t *conf, pkg_t *pkg);
++static int install_data_files(ipkg_conf_t *conf, pkg_t *pkg);
++static int resolve_conffiles(ipkg_conf_t *conf, pkg_t *pkg);
++
++static int cleanup_temporary_files(ipkg_conf_t *conf, pkg_t *pkg);
++
++static int user_prefers_old_conffile(const char *file, const char *backup);
++
++static char *backup_filename_alloc(const char *file_name);
++static int backup_make_backup(ipkg_conf_t *conf, const char *file_name);
++static int backup_exists_for(const char *file_name);
++static int backup_remove(const char *file_name);
++
++
++int ipkg_install_from_file(ipkg_conf_t *conf, const char *filename)
++{
++     int err, cmp;
++     pkg_t *pkg, *old;
++     char *old_version, *new_version;
++
++     pkg = pkg_new();
++     if (pkg == NULL) {
++        return ENOMEM;
++     }
++
++     err = pkg_init_from_file(pkg, filename);
++     if (err) {
++        return err;
++     }
++
++     if (!pkg->architecture) {
++        ipkg_message(conf, IPKG_ERROR, "Package %s has no Architecture defined.\n", pkg->name);
++        return -EINVAL;
++     }
++
++     /* XXX: CLEANUP: hash_insert_pkg has a nasty side effect of possibly
++      freeing the pkg that we pass in. It might be nice to clean this up
++      if possible.  */
++     pkg = hash_insert_pkg(&conf->pkg_hash, pkg, 1,conf);
++     old = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name);
++
++     pkg->local_filename = strdup(filename);
++
++     if (old) {
++        old_version = pkg_version_str_alloc(old);
++        new_version = pkg_version_str_alloc(pkg);
++
++        cmp = pkg_compare_versions(old, pkg);
++          if ( (conf->force_downgrade==1) && (cmp > 0) ){     /* We've been asked to allow downgrade  and version is precedent */
++             cmp = -1 ;                                       /* then we force ipkg to downgrade */ 
++                                                              /* We need to use a value < 0 because in the 0 case we are asking to */
++                                                              /* reinstall, and some check could fail asking the "force-reinstall" option */
++          } 
++        if (cmp > 0) {
++               ipkg_message(conf, IPKG_NOTICE,
++                            "Not downgrading package %s on %s from %s to %s.\n",
++                            old->name, old->dest->name, old_version, new_version);
++               pkg->state_want = SW_DEINSTALL;
++               pkg->state_flag |= SF_OBSOLETE;
++               free(old_version);
++               free(new_version);
++               return 0;
++        } else {
++             free(old_version);
++             free(new_version);
++        }
++     }
++
++     ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_pkg \n",__FUNCTION__);
++     return ipkg_install_pkg(conf, pkg,0);
++}
++
++ipkg_error_t ipkg_install_by_name(ipkg_conf_t *conf, const char *pkg_name)
++{
++     int cmp;
++     pkg_t *old, *new;
++     char *old_version, *new_version;
++
++     ipkg_message(conf, IPKG_DEBUG2, " Getting old  from pkg_hash_fetch \n" );
++     old = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg_name);
++     if ( old ) 
++        ipkg_message(conf, IPKG_DEBUG2, " Old versions from pkg_hash_fetch %s \n",  old->version );
++    
++     ipkg_message(conf, IPKG_DEBUG2, " Getting new  from pkg_hash_fetch \n" );
++     new = pkg_hash_fetch_best_installation_candidate_by_name(conf, pkg_name);
++     if ( new ) 
++        ipkg_message(conf, IPKG_DEBUG2, " New versions from pkg_hash_fetch %s \n",  new->version );
++
++/* Pigi Basically here is broken the version stuff.
++   What's happening is that nothing provide the version to differents 
++   functions, so the returned struct is always the latest.
++   That's why the install by name don't work.
++*/
++     ipkg_message(conf, IPKG_DEBUG2, " Versions from pkg_hash_fetch in %s ", __FUNCTION__ );
++
++     if ( old ) 
++        ipkg_message(conf, IPKG_DEBUG2, " old %s ", old->version );
++     if ( new ) 
++        ipkg_message(conf, IPKG_DEBUG2, " new %s ", new->version );
++     ipkg_message(conf, IPKG_DEBUG2, " \n");
++
++     if (new == NULL) {
++        return IPKG_PKG_HAS_NO_CANDIDATE;
++     }
++
++     new->state_flag |= SF_USER;
++     if (old) {
++        old_version = pkg_version_str_alloc(old);
++        new_version = pkg_version_str_alloc(new);
++
++        cmp = pkg_compare_versions(old, new);
++          if ( (conf->force_downgrade==1) && (cmp > 0) ){     /* We've been asked to allow downgrade  and version is precedent */
++           ipkg_message(conf, IPKG_DEBUG, " Forcing downgrade \n");
++             cmp = -1 ;                                       /* then we force ipkg to downgrade */ 
++                                                              /* We need to use a value < 0 because in the 0 case we are asking to */
++                                                              /* reinstall, and some check could fail asking the "force-reinstall" option */
++          } 
++        ipkg_message(conf, IPKG_DEBUG, 
++                     "Comparing visible versions of pkg %s:"
++                     "\n\t%s is installed "
++                     "\n\t%s is available "
++                     "\n\t%d was comparison result\n",
++                     pkg_name, old_version, new_version, cmp);
++        if (cmp == 0 && !conf->force_reinstall) {
++             ipkg_message(conf, IPKG_NOTICE,
++                          "Package %s (%s) installed in %s is up to date.\n",
++                          old->name, old_version, old->dest->name);
++             free(old_version);
++             free(new_version);
++             return 0;
++        } else if (cmp > 0) {
++             ipkg_message(conf, IPKG_NOTICE,
++                          "Not downgrading package %s on %s from %s to %s.\n",
++                          old->name, old->dest->name, old_version, new_version);
++             free(old_version);
++             free(new_version);
++             return 0;
++        } else if (cmp < 0) {
++             new->dest = old->dest;
++             old->state_want = SW_DEINSTALL;    /* Here probably the problem for bug 1277 */
++        }
++     }
++
++     /* XXX: CLEANUP: The error code of ipkg_install_by_name is really
++      supposed to be an ipkg_error_t, but ipkg_install_pkg could
++      return any kind of integer, (might be errno from a syscall,
++      etc.). This is a real mess and will need to be cleaned up if
++      anyone ever wants to make a nice libipkg. */
++
++     ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_pkg \n",__FUNCTION__);
++     return ipkg_install_pkg(conf, new,0);
++}
++
++ipkg_error_t ipkg_install_multi_by_name(ipkg_conf_t *conf, const char *pkg_name)
++{
++     abstract_pkg_vec_t *providers = pkg_hash_fetch_all_installation_candidates (&conf->pkg_hash, pkg_name);
++     int i;
++     ipkg_error_t err;
++     abstract_pkg_t *ppkg ;
++
++     if (providers == NULL)
++        return IPKG_PKG_HAS_NO_CANDIDATE;
++
++     for (i = 0; i < providers->len; i++) {
++        ppkg = abstract_pkg_vec_get(providers, i);
++          ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_by_name %d \n",__FUNCTION__, i);
++        err = ipkg_install_by_name(conf, ppkg->name);
++        if (err)
++             return err;
++/* XXX Maybe ppkg should be freed ? */
++     }
++     return 0;
++}
++
++/*
++ * Walk dependence graph starting with pkg, collect packages to be
++ * installed into pkgs_needed, in dependence order.
++ */
++int pkg_mark_dependencies_for_installation(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *pkgs_needed)
++{
++     int i, err;
++     pkg_vec_t *depends = pkg_vec_alloc();
++     char **unresolved = NULL;
++     int ndepends;
++
++     ndepends = pkg_hash_fetch_unsatisfied_dependencies(conf, 
++                                                      pkg, depends, 
++                                                      &unresolved);
++
++     if (unresolved) {
++        ipkg_message(conf, IPKG_ERROR,
++                     "%s: Cannot satisfy the following dependencies for %s:\n\t",
++                     conf->force_depends ? "Warning" : "ERROR", pkg->name);
++        while (*unresolved) {
++             ipkg_message(conf, IPKG_ERROR, " %s", *unresolved);
++             unresolved++;
++        }
++        ipkg_message(conf, IPKG_ERROR, "\n");
++        if (! conf->force_depends) {
++             ipkg_message(conf, IPKG_INFO,
++                          "This could mean that your package list is out of date or that the packages\n"
++                          "mentioned above do not yet exist (try 'ipkg update'). To proceed in spite\n"
++                          "of this problem try again with the '-force-depends' option.\n");
++             pkg_vec_free(depends);
++             return IPKG_PKG_DEPS_UNSATISFIED;
++        }
++     }
++
++     if (ndepends <= 0) {
++        pkg_vec_free(depends);
++        return 0;
++     }
++
++     for (i = 0; i < depends->len; i++) {
++        pkg_t *dep = depends->pkgs[i];
++        /* The package was uninstalled when we started, but another
++           dep earlier in this loop may have depended on it and pulled
++           it in, so check first. */
++        if ((dep->state_status != SS_INSTALLED)
++            && (dep->state_status != SS_UNPACKED)
++            && (dep->state_want != SW_INSTALL)) {
++
++             /* Mark packages as to-be-installed */
++             dep->state_want = SW_INSTALL;
++
++             /* Dependencies should be installed the same place as pkg */
++             if (dep->dest == NULL) {
++                  dep->dest = pkg->dest;
++             }
++
++             err = pkg_mark_dependencies_for_installation(conf, dep, pkgs_needed);
++             if (err) {
++                  pkg_vec_free(depends);
++                  return err;
++             }
++        }
++     }
++     if (pkgs_needed)
++        pkg_vec_insert(pkgs_needed, pkg);
++
++     pkg_vec_free(depends);
++
++     return 0;
++}
++
++int name_mark_dependencies_for_installation(ipkg_conf_t *conf, const char *pkg_name, pkg_vec_t *pkgs_needed)
++{
++     int cmp;
++     pkg_t *old, *new;
++     char *old_version, *new_version;
++
++     old = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg_name);
++    
++     new = pkg_hash_fetch_best_installation_candidate_by_name(conf, pkg_name);
++     if (new == NULL) {
++        return IPKG_PKG_HAS_NO_CANDIDATE;
++     }
++     if (old) {
++        old_version = pkg_version_str_alloc(old);
++        new_version = pkg_version_str_alloc(new);
++
++        cmp = pkg_compare_versions(old, new);
++          if ( (conf->force_downgrade==1) && (cmp > 0) ){     /* We've been asked to allow downgrade  and version is precedent */
++          ipkg_message(conf, IPKG_DEBUG, " Forcing downgrade ");
++             cmp = -1 ;                                       /* then we force ipkg to downgrade */ 
++                                                              /* We need to use a value < 0 because in the 0 case we are asking to */
++                                                              /* reinstall, and some check could fail asking the "force-reinstall" option */
++          } 
++        ipkg_message(conf, IPKG_DEBUG, 
++                     "comparing visible versions of pkg %s:"
++                     "\n\t%s is installed "
++                     "\n\t%s is available "
++                     "\n\t%d was comparison result\n",
++                     pkg_name, old_version, new_version, cmp);
++        if (cmp == 0 && !conf->force_reinstall) {
++             ipkg_message(conf, IPKG_NOTICE,
++                          "Package %s (%s) installed in %s is up to date.\n",
++                          old->name, old_version, old->dest->name);
++             free(old_version);
++             free(new_version);
++             return 0;
++        } else if (cmp > 0) {
++             ipkg_message(conf, IPKG_NOTICE,
++                          "Not downgrading package %s on %s from %s to %s.\n",
++                          old->name, old->dest->name, old_version, new_version);
++             free(old_version);
++             free(new_version);
++             return 0;
++        } else if (cmp < 0) {
++             new->dest = old->dest;
++             old->state_want = SW_DEINSTALL;
++             old->state_flag |= SF_OBSOLETE;
++        }
++     }
++     return pkg_mark_dependencies_for_installation(conf, new, pkgs_needed);
++}
++
++\f
++
++int satisfy_dependencies_for(ipkg_conf_t *conf, pkg_t *pkg)
++{
++     int i, err;
++     pkg_vec_t *depends = pkg_vec_alloc();
++     pkg_t *dep;
++     char **unresolved = NULL;
++     int ndepends;
++
++     ndepends = pkg_hash_fetch_unsatisfied_dependencies(conf, 
++                                                      pkg, depends, 
++                                                      &unresolved);
++
++     if (unresolved) {
++        ipkg_message(conf, IPKG_ERROR,
++                     "%s: Cannot satisfy the following dependencies for %s:\n\t",
++                     conf->force_depends ? "Warning" : "ERROR", pkg->name);
++        while (*unresolved) {
++             ipkg_message(conf, IPKG_ERROR, " %s", *unresolved);
++             unresolved++;
++        }
++        ipkg_message(conf, IPKG_ERROR, "\n");
++        if (! conf->force_depends) {
++             ipkg_message(conf, IPKG_INFO,
++                          "This could mean that your package list is out of date or that the packages\n"
++                          "mentioned above do not yet exist (try 'ipkg update'). To proceed in spite\n"
++                          "of this problem try again with the '-force-depends' option.\n");
++             pkg_vec_free(depends);
++             return IPKG_PKG_DEPS_UNSATISFIED;
++        }
++     }
++
++     if (ndepends <= 0) {
++        return 0;
++     }
++
++     /* Mark packages as to-be-installed */
++     for (i=0; i < depends->len; i++) {
++        /* Dependencies should be installed the same place as pkg */
++        if (depends->pkgs[i]->dest == NULL) {
++             depends->pkgs[i]->dest = pkg->dest;
++        }
++        depends->pkgs[i]->state_want = SW_INSTALL;
++     }
++
++     for (i = 0; i < depends->len; i++) {
++        dep = depends->pkgs[i];
++        /* The package was uninstalled when we started, but another
++           dep earlier in this loop may have depended on it and pulled
++           it in, so check first. */
++        if ((dep->state_status != SS_INSTALLED)
++            && (dep->state_status != SS_UNPACKED)) {
++               ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_pkg \n",__FUNCTION__);
++             err = ipkg_install_pkg(conf, dep,0);
++             if (err) {
++                  pkg_vec_free(depends);
++                  return err;
++             }
++        }
++     }
++
++     pkg_vec_free(depends);
++
++     return 0;
++}
++
++
++/* check all packages have their dependences satisfied, e.g., in case an upgraded package split */ 
++int ipkg_satisfy_all_dependences(ipkg_conf_t *conf)
++{
++     if (conf->nodeps == 0) {
++        int i;
++        pkg_vec_t *installed = pkg_vec_alloc();
++        pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
++        for (i = 0; i < installed->len; i++) {
++             pkg_t *pkg = installed->pkgs[i];
++             satisfy_dependencies_for(conf, pkg);
++        }
++        pkg_vec_free(installed);
++     }
++     return 0;
++}
++
++\f
++
++static int check_conflicts_for(ipkg_conf_t *conf, pkg_t *pkg)
++{
++     int i;
++     pkg_vec_t *conflicts = NULL;
++     int level;
++     const char *prefix;
++     if (conf->force_depends) {
++        level = IPKG_NOTICE;
++        prefix = "Warning";
++     } else {
++        level = IPKG_ERROR;
++        prefix = "ERROR";
++     }
++
++     if (!conf->force_depends)
++        conflicts = (pkg_vec_t *)pkg_hash_fetch_conflicts(&conf->pkg_hash, pkg);
++
++     if (conflicts) {
++        ipkg_message(conf, level,
++                     "%s: The following packages conflict with %s:\n\t", prefix, pkg->name);
++        i = 0;
++        while (i < conflicts->len)
++             ipkg_message(conf, level, " %s", conflicts->pkgs[i++]->name);
++        ipkg_message(conf, level, "\n");
++        pkg_vec_free(conflicts);
++        return IPKG_PKG_DEPS_UNSATISFIED;
++     }
++     return 0;
++}
++
++static int update_file_ownership(ipkg_conf_t *conf, pkg_t *new_pkg, pkg_t *old_pkg)
++{
++     str_list_t *new_list = pkg_get_installed_files(new_pkg);
++     str_list_elt_t *iter;
++
++     for (iter = new_list->head; iter; iter = iter->next) {
++        char *new_file = iter->data;
++        pkg_t *owner = file_hash_get_file_owner(conf, new_file);
++        if (!new_file)
++             ipkg_message(conf, IPKG_ERROR, "Null new_file for new_pkg=%s\n", new_pkg->name);
++        if (!owner || (owner == old_pkg))
++             file_hash_set_file_owner(conf, new_file, new_pkg);
++     }
++     if (old_pkg) {
++        str_list_t *old_list = pkg_get_installed_files(old_pkg);
++        for (iter = old_list->head; iter; iter = iter->next) {
++             char *old_file = iter->data;
++             pkg_t *owner = file_hash_get_file_owner(conf, old_file);
++             if (owner == old_pkg) {
++                  /* obsolete */
++                  hash_table_insert(&conf->obs_file_hash, old_file, old_pkg);
++             }
++        }
++     }
++     return 0;
++}
++
++static int verify_pkg_installable(ipkg_conf_t *conf, pkg_t *pkg)
++{
++    /* XXX: FEATURE: Anything else needed here? Maybe a check on free space? */
++
++    /* sma 6.20.02:  yup; here's the first bit */
++    /* 
++     * XXX: BUG easy for cworth
++     * 1) please point the call below to the correct current root destination
++     * 2) we need to resolve how to check the required space for a pending pkg, 
++     *    my diddling with the .ipk file size below isn't going to cut it.
++     * 3) return a proper error code instead of 1
++     */
++     int comp_size, blocks_available;
++    
++     if (!conf->force_space && pkg->installed_size != NULL) {
++        blocks_available = get_available_blocks(conf->default_dest->root_dir);
++
++        comp_size = strtoul(pkg->installed_size, NULL, 0);
++        /* round up a blocks count without doing fancy-but-slow casting jazz */ 
++        comp_size = (int)((comp_size + 1023) / 1024);
++
++        if (comp_size >= blocks_available) {
++             ipkg_message(conf, IPKG_ERROR,
++                          "Only have %d available blocks on filesystem %s, pkg %s needs %d\n", 
++                          blocks_available, conf->default_dest->root_dir, pkg->name, comp_size);
++             return ENOSPC;
++        }
++     }
++     return 0;
++}
++
++static int unpack_pkg_control_files(ipkg_conf_t *conf, pkg_t *pkg)
++{
++     int err;
++     char *conffiles_file_name;
++     char *root_dir;
++     FILE *conffiles_file;
++
++     sprintf_alloc(&pkg->tmp_unpack_dir, "%s/%s-XXXXXX", conf->tmp_dir, pkg->name);
++
++     pkg->tmp_unpack_dir = mkdtemp(pkg->tmp_unpack_dir);
++     if (pkg->tmp_unpack_dir == NULL) {
++        ipkg_message(conf, IPKG_ERROR,
++                     "%s: Failed to create temporary directory '%s': %s\n",
++                     __FUNCTION__, pkg->tmp_unpack_dir, strerror(errno));
++        return errno;
++     }
++
++     err = pkg_extract_control_files_to_dir(pkg, pkg->tmp_unpack_dir);
++     if (err) {
++        return err;
++     }
++
++     /* XXX: CLEANUP: There might be a cleaner place to read in the
++      conffiles. Seems like I should be able to get everything to go
++      through pkg_init_from_file. If so, maybe it would make sense to
++      move all of unpack_pkg_control_files to that function. */
++
++     /* Don't need to re-read conffiles if we already have it */
++     if (pkg->conffiles.head) {
++        return 0;
++     }
++
++     sprintf_alloc(&conffiles_file_name, "%s/conffiles", pkg->tmp_unpack_dir);
++     if (! file_exists(conffiles_file_name)) {
++        free(conffiles_file_name);
++        return 0;
++     }
++    
++     conffiles_file = fopen(conffiles_file_name, "r");
++     if (conffiles_file == NULL) {
++        fprintf(stderr, "%s: failed to open %s: %s\n",
++                __FUNCTION__, conffiles_file_name, strerror(errno));
++        free(conffiles_file_name);
++        return errno;
++     }
++     free(conffiles_file_name);
++
++     while (1) {
++        char *cf_name;
++        char *cf_name_in_dest;
++
++        cf_name = file_read_line_alloc(conffiles_file);
++        if (cf_name == NULL) {
++             break;
++        }
++        str_chomp(cf_name);
++        if (cf_name[0] == '\0') {
++             continue;
++        }
++
++        /* Prepend dest->root_dir to conffile name.
++           Take pains to avoid multiple slashes. */
++        root_dir = pkg->dest->root_dir;
++        if (conf->offline_root)
++             /* skip the offline_root prefix */
++             root_dir = pkg->dest->root_dir + strlen(conf->offline_root);
++        sprintf_alloc(&cf_name_in_dest, "%s%s", root_dir,
++                      cf_name[0] == '/' ? (cf_name + 1) : cf_name);
++
++        /* Can't get an md5sum now, (file isn't extracted yet).
++           We'll wait until resolve_conffiles */
++        conffile_list_append(&pkg->conffiles, cf_name_in_dest, NULL);
++
++        free(cf_name);
++        free(cf_name_in_dest);
++     }
++
++     fclose(conffiles_file);
++
++     return 0;
++}
++
++/* returns number of installed replacees */
++int pkg_get_installed_replacees(ipkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *installed_replacees)
++{
++     abstract_pkg_t **replaces = pkg->replaces;
++     int replaces_count = pkg->replaces_count;
++     int i, j;
++     for (i = 0; i < replaces_count; i++) {
++        abstract_pkg_t *ab_pkg = replaces[i];
++        pkg_vec_t *pkg_vec = ab_pkg->pkgs;
++        if (pkg_vec) {
++             for (j = 0; j < pkg_vec->len; j++) {
++                  pkg_t *replacee = pkg_vec->pkgs[j];
++                  if (!pkg_conflicts(pkg, replacee))
++                       continue;
++                  if (replacee->state_status == SS_INSTALLED) {
++                       pkg_vec_insert(installed_replacees, replacee);
++                  }
++             }
++        }
++     }
++     return installed_replacees->len;
++}
++
++int pkg_remove_installed_replacees(ipkg_conf_t *conf, pkg_vec_t *replacees)
++{
++     int i;
++     int replaces_count = replacees->len;
++     for (i = 0; i < replaces_count; i++) {
++        pkg_t *replacee = replacees->pkgs[i];
++        int err;
++        replacee->state_flag |= SF_REPLACE; /* flag it so remove won't complain */
++        err = ipkg_remove_pkg(conf, replacee,0);
++        if (err)
++             return err;
++     }
++     return 0;
++}
++
++/* to unwind the removal: make sure they are installed */
++int pkg_remove_installed_replacees_unwind(ipkg_conf_t *conf, pkg_vec_t *replacees)
++{
++     int i, err;
++     int replaces_count = replacees->len;
++     for (i = 0; i < replaces_count; i++) {
++        pkg_t *replacee = replacees->pkgs[i];
++        if (replacee->state_status != SS_INSTALLED) {
++               ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_pkg \n",__FUNCTION__);
++             err = ipkg_install_pkg(conf, replacee,0);
++             if (err)
++                  return err;
++        }
++     }
++     return 0;
++}
++
++int caught_sigint = 0;
++static void ipkg_install_pkg_sigint_handler(int sig)
++{
++     caught_sigint = sig;
++}
++
++/* compares versions of pkg and old_pkg, returns 0 if OK to proceed with installation of pkg, 1 otherwise */
++static int ipkg_install_check_downgrade(ipkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg, int message)
++{       
++     if (old_pkg) {
++          char message_out[15];
++        char *old_version = pkg_version_str_alloc(old_pkg);
++        char *new_version = pkg_version_str_alloc(pkg);
++        int cmp = pkg_compare_versions(old_pkg, pkg);
++        int rc = 0;
++
++          memset(message_out,'\x0',15);
++          strncpy (message_out,"Upgrading ",strlen("Upgrading ")); 
++          if ( (conf->force_downgrade==1) && (cmp > 0) ){     /* We've been asked to allow downgrade  and version is precedent */
++             cmp = -1 ;                                       /* then we force ipkg to downgrade */ 
++             strncpy (message_out,"Downgrading ",strlen("Downgrading "));         /* We need to use a value < 0 because in the 0 case we are asking to */
++                                                              /* reinstall, and some check could fail asking the "force-reinstall" option */
++          } 
++
++        if (cmp > 0) {
++             ipkg_message(conf, IPKG_NOTICE,
++                          "Not downgrading package %s on %s from %s to %s.\n",
++                          old_pkg->name, old_pkg->dest->name, old_version, new_version);
++             rc = 1;
++        } else if (cmp < 0) {
++             ipkg_message(conf, IPKG_NOTICE,
++                          "%s%s on %s from %s to %s...\n",
++                          message_out, pkg->name, old_pkg->dest->name, old_version, new_version);
++             pkg->dest = old_pkg->dest;
++             rc = 0;
++        } else /* cmp == 0 */ {
++             if (conf->force_reinstall) {
++                  ipkg_message(conf, IPKG_NOTICE,
++                               "Reinstalling %s (%s) on %s...\n",
++                               pkg->name, new_version, old_pkg->dest->name);
++                  pkg->dest = old_pkg->dest;
++                  rc = 0;
++             } else {
++                  ipkg_message(conf, IPKG_NOTICE,
++                               "Not installing %s (%s) on %s -- already installed.\n",
++                               pkg->name, new_version, old_pkg->dest->name);
++                  rc = 1;
++             }
++        } 
++        free(old_version);
++        free(new_version);
++        return rc;
++     } else {
++      char message_out[15], *version ;
++      memset(message_out,'\x0',15);
++      if ( message ) 
++          strncpy( message_out,"Upgrading ",strlen("Upgrading ") );
++      else 
++          strncpy( message_out,"Installing ",strlen("Installing ") );
++        version = pkg_version_str_alloc(pkg);
++      
++        ipkg_message(conf, IPKG_NOTICE,
++                     "%s%s (%s) to %s...\n", message_out,
++                     pkg->name, version, pkg->dest->name);
++        free(version);
++        return 0;
++     }
++}
++
++/* and now the meat... */
++int ipkg_install_pkg(ipkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
++{
++     int err = 0;
++     int message = 0;
++     pkg_t *old_pkg = NULL;
++     pkg_vec_t *replacees;
++     abstract_pkg_t *ab_pkg = NULL;
++     int old_state_flag;
++     char* file_md5;
++
++    
++     if ( from_upgrade ) 
++        message = 1;            /* Coming from an upgrade, and should change the output message */
++
++     if (!pkg) {
++        ipkg_message(conf, IPKG_ERROR,
++                     "INTERNAL ERROR: null pkg passed to ipkg_install_pkg\n");
++        return -EINVAL;
++     }
++
++     ipkg_message(conf, IPKG_DEBUG2, "Function: %s calling pkg_arch_supported %s \n", __FUNCTION__, __FUNCTION__);
++
++     if (!pkg_arch_supported(conf, pkg)) {
++        ipkg_message(conf, IPKG_ERROR, "INTERNAL ERROR: architecture %s for pkg %s is unsupported.\n",
++                     pkg->architecture, pkg->name);
++        return -EINVAL;
++     }
++     if (pkg->state_status == SS_INSTALLED && conf->force_reinstall == 0 && conf->nodeps == 0) {
++        err = satisfy_dependencies_for(conf, pkg);
++        if (err) { return err; }
++
++        ipkg_message(conf, IPKG_NOTICE,
++                     "Package %s is already installed in %s.\n", 
++                     pkg->name, pkg->dest->name);
++        return 0;
++     }
++
++     if (pkg->dest == NULL) {
++        pkg->dest = conf->default_dest;
++     }
++
++     old_pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name);
++
++     err = ipkg_install_check_downgrade(conf, pkg, old_pkg, message);
++     if (err) { return err; }
++
++     pkg->state_want = SW_INSTALL;
++     if (old_pkg){                          
++         old_pkg->state_want = SW_DEINSTALL; /* needed for check_data_file_clashes of dependences */
++     }
++
++
++     /* Abhaya: conflicts check */
++     err = check_conflicts_for(conf, pkg);
++     if (err) { return err; }
++    
++     /* this setup is to remove the upgrade scenario in the end when
++      installing pkg A, A deps B & B deps on A. So both B and A are
++      installed. Then A's installation is started resulting in an
++      uncecessary upgrade */ 
++     if (pkg->state_status == SS_INSTALLED
++       && conf->force_reinstall == 0) return 0;
++    
++     err = verify_pkg_installable(conf, pkg);
++     if (err) { return err; }
++
++     if (pkg->local_filename == NULL) {
++        err = ipkg_download_pkg(conf, pkg, conf->tmp_dir);
++        if (err) {
++             ipkg_message(conf, IPKG_ERROR,
++                          "Failed to download %s. Perhaps you need to run 'ipkg update'?\n",
++                          pkg->name);
++             return err;
++        }
++     }
++
++/* Check for md5 values */
++     if (pkg->md5sum)
++     {
++         file_md5 = file_md5sum_alloc(pkg->local_filename);
++         if (strcmp(file_md5, pkg->md5sum))
++         {
++              ipkg_message(conf, IPKG_ERROR,
++                           "Package %s md5sum mismatch. Either the ipkg or the package index are corrupt. Try 'ipkg update'.\n",
++                           pkg->name);
++              free(file_md5);
++              return err;
++         }
++         free(file_md5);
++     }
++
++     if (pkg->tmp_unpack_dir == NULL) {
++        unpack_pkg_control_files(conf, pkg);
++     }
++
++     /* We should update the filelist here, so that upgrades of packages that split will not fail. -Jamey 27-MAR-03 */
++/* Pigi: check if it will pass from here when replacing. It seems to fail */
++/* That's rather strange that files don't change owner. Investigate !!!!!!*/
++     err = update_file_ownership(conf, pkg, old_pkg);
++     if (err) { return err; }
++
++     if (conf->nodeps == 0) {
++        err = satisfy_dependencies_for(conf, pkg);
++        if (err) { return err; }
++     }
++
++     replacees = pkg_vec_alloc();