diff -Nur busybox-1.21.1.orig/archival/Config.src busybox-1.21.1/archival/Config.src
--- busybox-1.21.1.orig/archival/Config.src	2013-05-12 01:30:43.000000000 +0200
+++ busybox-1.21.1/archival/Config.src	2014-02-17 14:25:39.802534016 +0100
@@ -214,6 +214,12 @@
 	  are actually slower than gzip at equivalent compression ratios
 	  and take up 3.2K of code.
 
+config IPKG
+	bool "ipkg"
+	default n
+	help
+	  ipkg is the itsy package management system.
+
 config RPM2CPIO
 	bool "rpm2cpio"
 	default y
diff -Nur busybox-1.21.1.orig/archival/ipkg.c busybox-1.21.1/archival/ipkg.c
--- busybox-1.21.1.orig/archival/ipkg.c	1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.21.1/archival/ipkg.c	2014-02-17 14:25:39.802534016 +0100
@@ -0,0 +1,28 @@
+/* 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 "libbb.h"
+#include "libipkg/libipkg.h"
+
+int ipkg_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int ipkg_main(int argc, char **argv)
+{
+	return ipkg_op(argc, argv);
+}
diff -Nur busybox-1.21.1.orig/archival/Kbuild.src busybox-1.21.1/archival/Kbuild.src
--- busybox-1.21.1.orig/archival/Kbuild.src	2013-05-12 01:30:43.000000000 +0200
+++ busybox-1.21.1/archival/Kbuild.src	2014-02-17 14:25:39.802534016 +0100
@@ -22,6 +22,7 @@
 lib-$(CONFIG_LZOP)		+= lzop.o bbunzip.o
 lib-$(CONFIG_GZIP)		+= gzip.o bbunzip.o
 lib-$(CONFIG_BZIP2)		+= bzip2.o bbunzip.o
+lib-$(CONFIG_IPKG)		+= ipkg.o
 
 lib-$(CONFIG_UNXZ)		+= bbunzip.o
 lib-$(CONFIG_UNLZMA)		+= bbunzip.o
diff -Nur busybox-1.21.1.orig/archival/libarchive/Kbuild.src busybox-1.21.1/archival/libarchive/Kbuild.src
--- busybox-1.21.1.orig/archival/libarchive/Kbuild.src	2013-06-29 16:58:06.000000000 +0200
+++ busybox-1.21.1/archival/libarchive/Kbuild.src	2014-02-17 14:25:39.802534016 +0100
@@ -25,14 +25,14 @@
 \
 	data_align.o \
 	find_list_entry.o \
+	get_header_tar.o \
+	get_header_tar_gz.o \
 	init_handle.o
 
 DPKG_FILES:= \
 	unpack_ar_archive.o \
 	filter_accept_list_reassign.o \
 	get_header_ar.o \
-	get_header_tar.o \
-	get_header_tar_gz.o \
 	get_header_tar_bz2.o \
 	get_header_tar_lzma.o \
 
diff -Nur busybox-1.21.1.orig/archival/libipkg/args.c busybox-1.21.1/archival/libipkg/args.c
--- busybox-1.21.1.orig/archival/libipkg/args.c	1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.21.1/archival/libipkg/args.c	2014-02-17 14:25:39.826534090 +0100
@@ -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)
+{
+     const 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(const 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);
+}
diff -Nur busybox-1.21.1.orig/archival/libipkg/args.h busybox-1.21.1/archival/libipkg/args.h
--- busybox-1.21.1.orig/archival/libipkg/args.h	1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.21.1/archival/libipkg/args.h	2014-02-17 14:25:39.826534090 +0100
@@ -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(const char *complaint);
+
+#endif
diff -Nur busybox-1.21.1.orig/archival/libipkg/conffile.c busybox-1.21.1/archival/libipkg/conffile.c
--- busybox-1.21.1.orig/archival/libipkg/conffile.c	1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.21.1/archival/libipkg/conffile.c	2014-02-17 14:25:39.826534090 +0100
@@ -0,0 +1,65 @@
+/* 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 "libbb.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 uint8_t *md5sum)
+{
+    return nv_pair_init(conffile, file_name, (char *)md5sum);
+}
+
+void conffile_deinit(conffile_t *conffile)
+{
+    nv_pair_deinit(conffile);
+}
+
+int conffile_has_been_modified(ipkg_conf_t *conf, conffile_t *conffile)
+{
+    uint8_t *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((char *)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;
+}
diff -Nur busybox-1.21.1.orig/archival/libipkg/conffile.h busybox-1.21.1/archival/libipkg/conffile.h
--- busybox-1.21.1.orig/archival/libipkg/conffile.h	1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.21.1/archival/libipkg/conffile.h	2014-02-17 14:25:39.826534090 +0100
@@ -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 uint8_t *md5sum);
+void conffile_deinit(conffile_t *conffile);
+int conffile_has_been_modified(struct ipkg_conf *conf, conffile_t *conffile);
+
+#endif
+
diff -Nur busybox-1.21.1.orig/archival/libipkg/conffile_list.c busybox-1.21.1/archival/libipkg/conffile_list.c
--- busybox-1.21.1.orig/archival/libipkg/conffile_list.c	1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.21.1/archival/libipkg/conffile_list.c	2014-02-17 14:25:39.850534164 +0100
@@ -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);
+}
+
diff -Nur busybox-1.21.1.orig/archival/libipkg/conffile_list.h busybox-1.21.1/archival/libipkg/conffile_list.h
--- busybox-1.21.1.orig/archival/libipkg/conffile_list.h	1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.21.1/archival/libipkg/conffile_list.h	2014-02-17 14:25:39.850534164 +0100
@@ -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
+
diff -Nur busybox-1.21.1.orig/archival/libipkg/file_util.c busybox-1.21.1/archival/libipkg/file_util.c
--- busybox-1.21.1.orig/archival/libipkg/file_util.c	1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.21.1/archival/libipkg/file_util.c	2014-02-17 14:25:39.850534164 +0100
@@ -0,0 +1,186 @@
+/* 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(char *path, long mode)
+{
+    return bb_make_directory(path, mode, FILEUTILS_RECUR);
+}
+
+static unsigned char *hash_bin_to_hex(unsigned char *hash_value,
+				unsigned hash_length)
+{
+	/* xzalloc zero-terminates */
+	char *hex_value = xzalloc((hash_length * 2) + 1);
+	bin2hex(hex_value, (char*)hash_value, hash_length);
+	return (unsigned char *)hex_value;
+}
+
+static uint8_t *hash_file(const char *filename, hash_algo_t hash_algo)
+{
+	int src_fd, hash_len, count;
+	union _ctx_ {
+		sha1_ctx_t sha1;
+		md5_ctx_t md5;
+	} context;
+	uint8_t *hash_value = NULL;
+	RESERVE_CONFIG_UBUFFER(in_buf, 4096);
+	void FAST_FUNC (*update)(void*, const void*, size_t);
+	void FAST_FUNC (*final)(void*, void*);
+
+	src_fd = open_or_warn_stdin(filename);
+	if (src_fd < 0) {
+		return NULL;
+	}
+
+	/* figure specific hash algorithims */
+	if (ENABLE_MD5SUM && hash_algo == HASH_MD5) {
+		md5_begin(&context.md5);
+		update = (void*)md5_hash;
+		final = (void*)md5_end;
+		hash_len = 16;
+	} else {
+		bb_error_msg_and_die("algorithm not supported");
+	}
+
+	while ((count = safe_read(src_fd, in_buf, 4096)) > 0) {
+		update(&context, in_buf, count);
+	}
+
+	if (count == 0) {
+		final(&context, in_buf);
+		hash_value = hash_bin_to_hex(in_buf, hash_len);
+	}
+
+	RELEASE_CONFIG_BUFFER(in_buf);
+
+	if (src_fd != STDIN_FILENO) {
+		close(src_fd);
+	}
+
+	return hash_value;
+}
+
+uint8_t *file_md5sum_alloc(const char *file_name)
+{
+    return hash_file(file_name, HASH_MD5);
+}
+
diff -Nur busybox-1.21.1.orig/archival/libipkg/file_util.h busybox-1.21.1/archival/libipkg/file_util.h
--- busybox-1.21.1.orig/archival/libipkg/file_util.h	1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.21.1/archival/libipkg/file_util.h	2014-02-17 14:25:39.850534164 +0100
@@ -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(char *path, long mode);
+uint8_t *file_md5sum_alloc(const char *file_name);
+
+#endif
diff -Nur busybox-1.21.1.orig/archival/libipkg/hash_table.c busybox-1.21.1/archival/libipkg/hash_table.c
--- busybox-1.21.1.orig/archival/libipkg/hash_table.c	1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.21.1/archival/libipkg/hash_table.c	2014-02-17 14:25:39.850534164 +0100
@@ -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));
+    }
+}
+
diff -Nur busybox-1.21.1.orig/archival/libipkg/hash_table.h busybox-1.21.1/archival/libipkg/hash_table.h
--- busybox-1.21.1.orig/archival/libipkg/hash_table.h	1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.21.1/archival/libipkg/hash_table.h	2014-02-17 14:25:39.854534176 +0100
@@ -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_ */
diff -Nur busybox-1.21.1.orig/archival/libipkg/ipkg_cmd.c busybox-1.21.1/archival/libipkg/ipkg_cmd.c
--- busybox-1.21.1.orig/archival/libipkg/ipkg_cmd.c	1970-01-01 01:00:00.000000000 +0100
+++ busybox-1.21.1/archival/libipkg/ipkg_cmd.c	2014-02-17 14:25:39.858534188 +0100
@@ -0,0 +1,1367 @@
+/* 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 "bb_archive.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"
+
+#include "libipkg.h"
+static void *p_userdata = NULL;
+
+static int ipkg_update_cmd(ipkg_conf_t *conf);
+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);
+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);
+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;
+}
+
+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;
+}
+
+static int ipkg_update_cmd(ipkg_conf_t *conf)
+{
+     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) {
+			transformer_aux_data_t aux;
+			init_transformer_aux_data(&aux);
+			inflate_unzip (&aux, 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(void);
+
+ipkg_intercept_t ipkg_prep_intercepts(void)
+{
+    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);
+
+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();
+    
+     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';
+	  }
+	  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);
+	  }
+     }
+     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';
+	  }
+	  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);
+	  }
+     }
+
+     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;
+	  }
+	  buff = pkg_formatted_info(pkg);
+          if ( buff ) {
+	       if (ipkg_cb_status) ipkg_cb_status(pkg->name,
+						  pkg->state_status,
+						  buff,
+						  p_userdata);
+               free(buff);
+          }
+	  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);
+	       }
+	  }
+     }
+     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 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(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(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);
+
+     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);
+     }
+
+     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) {
+					     const 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_p