include $(TOPDIR)/rules.mk
PKG_NAME:=busybox
-PKG_VERSION:=1.11.1
+PKG_VERSION:=1.11.2
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=http://www.busybox.net/downloads \
http://distfiles.gentoo.org/distfiles/
-PKG_MD5SUM:=c64bbb5c0c3e19f12892941a0ae86c48
+PKG_MD5SUM:=63f11148e09fe9844fa726061414e9ac
include $(INCLUDE_DIR)/package.mk
--- a/shell/ash.c
+++ b/shell/ash.c
-@@ -11875,8 +11875,17 @@
+@@ -11909,8 +11909,17 @@
const char *p;
char **aptr;
int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
aptr = argptr;
name = *aptr;
if (name) {
-@@ -11888,10 +11897,12 @@
+@@ -11922,10 +11931,12 @@
vp = *findvar(hashvar(name), name);
if (vp) {
vp->flags |= flag;
/*======================================================================*/
-@@ -835,27 +909,18 @@
+@@ -835,32 +909,20 @@
static enum obj_reloc
arch_apply_relocation(struct obj_file *f,
struct obj_section *targsec,
ElfW(RelM) *rel, ElfW(Addr) v)
{
-#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \
-- || defined(__sh__) || defined(__s390__) || defined(__x86_64__)
+- || defined(__sh__) || defined(__s390__) || defined(__x86_64__) \
+- || defined(__powerpc__) || defined(__mips__)
struct arch_file *ifile = (struct arch_file *) f;
-#endif
enum obj_reloc ret = obj_reloc_ok;
#endif
-#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \
- || defined(__sh__) || defined(__s390__)
-+#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
#if defined(USE_GOT_ENTRIES)
ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
#endif
-@@ -953,7 +1018,6 @@
+-#endif
+ #if defined(USE_PLT_ENTRIES)
+ ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
+ unsigned long *ip;
+@@ -954,7 +1016,6 @@
case R_386_PLT32:
case R_386_PC32:
*loc += v - dot;
break;
-@@ -972,6 +1036,9 @@
+@@ -973,6 +1034,9 @@
case R_386_GOT32:
goto bb_use_got;
break;
#elif defined(__microblaze__)
-@@ -1758,7 +1825,7 @@
+@@ -1759,7 +1823,7 @@
#if defined(USE_SINGLE)
int offset, int size)
{
if (single->allocated == 0) {
-@@ -1906,7 +1973,7 @@
+@@ -1907,7 +1971,7 @@
#if defined(USE_GOT_ENTRIES)
if (got_allocate) {
got_offset += arch_single_init(
got_offset, GOT_ENTRY_SIZE);
got_needed = 1;
-@@ -1920,7 +1987,7 @@
+@@ -1921,7 +1985,7 @@
plt_offset, PLT_ENTRY_SIZE);
#else
plt_offset += arch_single_init(
plt_offset, PLT_ENTRY_SIZE);
#endif
plt_needed = 1;
-@@ -1958,8 +2025,7 @@
+@@ -1959,8 +2023,7 @@
while (n > 0) {
ch = *name++;
h = (h << 4) + ch;
h ^= g >> 24;
h &= ~g;
}
-@@ -2038,7 +2104,7 @@
+@@ -2039,7 +2102,7 @@
int n_type = ELF_ST_TYPE(info);
int n_binding = ELF_ST_BIND(info);
if (f->symbol_cmp(sym->name, name) == 0) {
int o_secidx = sym->secidx;
int o_info = sym->info;
-@@ -2097,14 +2163,14 @@
+@@ -2098,14 +2161,14 @@
return sym;
}
}
if (symidx >= f->local_symtab_size)
bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
name, (long) symidx, (long) f->local_symtab_size);
-@@ -3227,7 +3293,7 @@
+@@ -3228,7 +3291,7 @@
/* Do it! */
switch (arch_apply_relocation
) {
case obj_reloc_ok:
break;
-@@ -3306,11 +3372,11 @@
+@@ -3307,11 +3370,11 @@
/*======================================================================*/
char *shstrtab;
/* Read the file header. */
-@@ -3582,7 +3648,7 @@
+@@ -3583,7 +3646,7 @@
while (ptr < endptr) {
value = strchr(ptr, '=');
if (value && strncmp(ptr, "license", value-ptr) == 0) {
if (license)
*license = value+1;
for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) {
-@@ -3686,9 +3752,6 @@
+@@ -3687,9 +3750,6 @@
* start of some sections. this info is used by ksymoops to do better
* debugging.
*/
static int
get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
{
-@@ -3721,8 +3784,7 @@
+@@ -3722,8 +3782,7 @@
struct obj_symbol *sym;
char *name, *absolute_filename;
char str[STRVERSIONLEN];
struct stat statbuf;
/* WARNING: was using realpath, but replaced by readlink to stop using
-@@ -3909,145 +3971,57 @@
+@@ -3910,145 +3969,57 @@
void print_load_map(struct obj_file *f);
#endif
+ if (arg1 == NULL)
bb_show_usage();
- }
--
+
- /* Grab the module name */
- tmp1 = xstrdup(arg1);
- tmp = basename(tmp1);
- len -= 2;
- tmp[len] = '\0';
- }
-
+-
-
-#if ENABLE_FEATURE_2_6_MODULES
- if (k_version > 4)
f = obj_load(fp, LOADBITS);
-@@ -4074,7 +4048,7 @@
+@@ -4075,7 +4046,7 @@
"\t%s was compiled for kernel version %s\n"
"\twhile this kernel is version %s",
flag_force_load ? "warning: " : "",
if (!flag_force_load)
goto out;
}
-@@ -4116,7 +4090,7 @@
+@@ -4117,7 +4088,7 @@
hide_special_symbols(f);
#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
new_create_module_ksymtab(f);
-@@ -4125,7 +4099,7 @@
+@@ -4126,7 +4097,7 @@
m_size = obj_load_size(f);
m_addr = create_module(m_name, m_size);
case EEXIST:
bb_error_msg_and_die("a module named %s already exists", m_name);
case ENOMEM:
-@@ -4141,36 +4115,37 @@
+@@ -4142,36 +4113,37 @@
* now we can load them directly into the kernel memory
*/
if (!obj_load_progbits(fp, f, (char*)m_addr)) {
}
#endif /* ENABLE_FEATURE_2_4_MODULES */
-@@ -4182,15 +4157,8 @@
+@@ -4183,15 +4155,8 @@
#if ENABLE_FEATURE_2_6_MODULES
#include <sys/mman.h>
/* We use error numbers in a loose translation... */
static const char *moderror(int err)
-@@ -4209,22 +4177,32 @@
+@@ -4210,22 +4175,32 @@
}
}
/* Rest is options */
options = xzalloc(1);
optlen = 0;
-@@ -4234,41 +4212,47 @@
+@@ -4235,41 +4210,47 @@
optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
}
+++ /dev/null
---- a/coreutils/basename.c
-+++ b/coreutils/basename.c
-@@ -48,5 +48,5 @@
-
- /* puts(s) will do, but we can do without stdio this way: */
- s[m++] = '\n';
-- return full_write(STDOUT_FILENO, s, m) == (ssize_t)m;
-+ return full_write(STDOUT_FILENO, s, m) != (ssize_t)m;
- }
--- /dev/null
+--- a/console-tools/kbd_mode.c
++++ b/console-tools/kbd_mode.c
+@@ -2,7 +2,7 @@
+ /*
+ * Mini kbd_mode implementation for busybox
+ *
+- * Copyright (C) 2007 Loïc Grenié <loic.grenie@gmail.com>
++ * Copyright (C) 2007 Loic Grenie <loic.grenie@gmail.com>
+ * written using Andries Brouwer <aeb@cwi.nl>'s kbd_mode from
+ * console-utils v0.2.3, licensed under GNU GPLv2
+ *
+@@ -46,7 +46,8 @@
+ printf("The keyboard is in %s mode\n", mode);
+ } else {
+ opt = opt & UNICODE ? 3 : opt >> 1;
+- xioctl(fd, KDSKBMODE, opt);
++ /* double cast prevents warnings about widening conversion */
++ xioctl(fd, KDSKBMODE, (void*)(ptrdiff_t)opt);
+ }
+
+ if (ENABLE_FEATURE_CLEAN_UP)
--- /dev/null
+--- a/editors/vi.c
++++ b/editors/vi.c
+@@ -147,10 +147,10 @@
+ #endif
+
+ smallint editing; // >0 while we are editing a file
+- // [code audit says "can be 0 or 1 only"]
++ // [code audit says "can be 0, 1 or 2 only"]
+ smallint cmd_mode; // 0=command 1=insert 2=replace
+ int file_modified; // buffer contents changed (counter, not flag!)
+- int last_file_modified; // = -1;
++ int last_file_modified; // = -1;
+ int fn_start; // index of first cmd line file name
+ int save_argc; // how many file names on cmd line
+ int cmdcnt; // repetition count
+@@ -623,7 +623,7 @@
+ // These are commands that change text[].
+ // Remember the input for the "." command
+ if (!adding2q && ioq_start == NULL
+- && strchr(modifying_cmds, c)
++ && c != '\0' && strchr(modifying_cmds, c)
+ ) {
+ start_new_cmd_q(c);
+ }
+@@ -645,8 +645,8 @@
+ }
+ //-------------------------------------------------------------------
+
+- place_cursor(rows, 0, FALSE); // go to bottom of screen
+- clear_to_eol(); // Erase to end of line
++ place_cursor(rows - 1, 0, FALSE); // go to bottom of screen
++ clear_to_eol(); // erase to end of line
+ cookmode();
+ #undef cur_line
+ }
+@@ -2009,9 +2009,9 @@
+ {
+ // get buffer for new cmd
+ // if there is a current cmd count put it in the buffer first
+- if (cmdcnt > 0)
++ if (cmdcnt > 0) {
+ lmc_len = sprintf(last_modifying_cmd, "%d%c", cmdcnt, c);
+- else { // just save char c onto queue
++ } else { // just save char c onto queue
+ last_modifying_cmd[0] = c;
+ lmc_len = 1;
+ }
+@@ -2247,18 +2247,20 @@
+
+ fflush(stdout);
+ n = chars_to_parse;
+- // get input from User- are there already input chars in Q?
++ // get input from User - are there already input chars in Q?
+ if (n <= 0) {
+ // the Q is empty, wait for a typed char
++ again:
+ n = safe_read(STDIN_FILENO, readbuffer, sizeof(readbuffer));
+- if (n < 0) {
+- if (errno == EBADF || errno == EFAULT || errno == EINVAL
+- || errno == EIO)
+- editing = 0; // want to exit
+- errno = 0;
+- }
+- if (n <= 0)
+- return 0; // error
++ if (n <= 0) {
++ place_cursor(rows - 1, 0, FALSE); // go to bottom of screen
++ clear_to_eol(); // erase to end of line
++ cookmode(); // terminal to "cooked"
++ bb_error_msg_and_die("can't read user input");
++ }
++ /* elsewhere we can get very confused by NULs */
++ if (readbuffer[0] == '\0')
++ goto again;
+ if (readbuffer[0] == 27) {
+ // This is an ESC char. Is this Esc sequence?
+ // Could be bare Esc key. See if there are any
+--- a/miscutils/crontab.c
++++ b/miscutils/crontab.c
+@@ -93,6 +93,7 @@
+ char *new_fname;
+ char *user_name; /* -u USER */
+ int fd;
++ int src_fd;
+ int opt_ler;
+
+ /* file [opts] Replace crontab from file
+@@ -144,15 +145,15 @@
+ bb_show_usage();
+
+ /* Read replacement file under user's UID/GID/group vector */
++ src_fd = STDIN_FILENO;
+ if (!opt_ler) { /* Replace? */
+ if (!argv[0])
+ bb_show_usage();
+ if (NOT_LONE_DASH(argv[0])) {
+- fd = open_as_user(pas, argv[0]);
+- if (fd < 0)
++ src_fd = open_as_user(pas, argv[0]);
++ if (src_fd < 0)
+ bb_error_msg_and_die("user %s cannot read %s",
+ pas->pw_name, argv[0]);
+- xmove_fd(fd, STDIN_FILENO);
+ }
+ }
+
+@@ -180,23 +181,23 @@
+ tmp_fname = xasprintf("%s.%u", crontab_dir, (unsigned)getpid());
+ /* No O_EXCL: we don't want to be stuck if earlier crontabs
+ * were killed, leaving stale temp file behind */
+- fd = xopen3(tmp_fname, O_RDWR|O_CREAT|O_TRUNC, 0600);
+- xmove_fd(fd, STDIN_FILENO);
+- fchown(STDIN_FILENO, pas->pw_uid, pas->pw_gid);
++ src_fd = xopen3(tmp_fname, O_RDWR|O_CREAT|O_TRUNC, 0600);
++ fchown(src_fd, pas->pw_uid, pas->pw_gid);
+ fd = open(pas->pw_name, O_RDONLY);
+ if (fd >= 0) {
+- bb_copyfd_eof(fd, STDIN_FILENO);
++ bb_copyfd_eof(fd, src_fd);
+ close(fd);
++ xlseek(src_fd, 0, SEEK_SET);
+ }
++ close_on_exec_on(src_fd); /* don't want editor to see this fd */
+ edit_file(pas, tmp_fname);
+- xlseek(STDIN_FILENO, 0, SEEK_SET);
+ /* fall through */
+
+ case 0: /* Replace (no -l, -e, or -r were given) */
+ new_fname = xasprintf("%s.new", pas->pw_name);
+ fd = open(new_fname, O_WRONLY|O_CREAT|O_TRUNC|O_APPEND, 0600);
+ if (fd >= 0) {
+- bb_copyfd_eof(STDIN_FILENO, fd);
++ bb_copyfd_eof(src_fd, fd);
+ close(fd);
+ xrename(new_fname, pas->pw_name);
+ } else {
+++ /dev/null
---- a/archival/libunarchive/get_header_tar.c
-+++ b/archival/libunarchive/get_header_tar.c
-@@ -261,26 +261,33 @@
- case '0':
- #if ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
- if (last_char_is(file_header->name, '/')) {
-- file_header->mode |= S_IFDIR;
-- } else
-+ goto set_dir;
-+ }
- #endif
- file_header->mode |= S_IFREG;
- break;
- case '2':
- file_header->mode |= S_IFLNK;
-+ /* have seen tarballs with size field containing
-+ * the size of the link target's name */
-+ size0:
-+ file_header->size = 0;
- break;
- case '3':
- file_header->mode |= S_IFCHR;
-- break;
-+ goto size0; /* paranoia */
- case '4':
- file_header->mode |= S_IFBLK;
-- break;
-+ goto size0;
- case '5':
-+#if ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
-+ set_dir:
-+#endif
- file_header->mode |= S_IFDIR;
-- break;
-+ goto size0;
- case '6':
- file_header->mode |= S_IFIFO;
-- break;
-+ goto size0;
- #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
- case 'L':
- /* free: paranoia: tar with several consecutive longnames */
---- a/archival/libunarchive/seek_by_jump.c
-+++ b/archival/libunarchive/seek_by_jump.c
-@@ -8,7 +8,9 @@
-
- void seek_by_jump(const archive_handle_t *archive_handle, unsigned amount)
- {
-- if (lseek(archive_handle->src_fd, (off_t) amount, SEEK_CUR) == (off_t) -1) {
-+ if (amount
-+ && lseek(archive_handle->src_fd, (off_t) amount, SEEK_CUR) == (off_t) -1
-+ ) {
- if (errno == ESPIPE)
- seek_by_read(archive_handle, amount);
- else
+++ /dev/null
---- a/shell/ash.c
-+++ b/shell/ash.c
-@@ -1569,14 +1569,14 @@
- static char *optptr; /* used by nextopt */
-
- /*
-- * XXX - should get rid of. have all builtins use getopt(3). the
-- * library getopt must have the BSD extension static variable "optreset"
-- * otherwise it can't be used within the shell safely.
-+ * XXX - should get rid of. Have all builtins use getopt(3).
-+ * The library getopt must have the BSD extension static variable
-+ * "optreset", otherwise it can't be used within the shell safely.
- *
-- * Standard option processing (a la getopt) for builtin routines. The
-- * only argument that is passed to nextopt is the option string; the
-- * other arguments are unnecessary. It return the character, or '\0' on
-- * end of input.
-+ * Standard option processing (a la getopt) for builtin routines.
-+ * The only argument that is passed to nextopt is the option string;
-+ * the other arguments are unnecessary. It returns the character,
-+ * or '\0' on end of input.
- */
- static int
- nextopt(const char *optstring)
-@@ -1587,13 +1587,20 @@
-
- p = optptr;
- if (p == NULL || *p == '\0') {
-+ /* We ate entire "-param", take next one */
- p = *argptr;
-- if (p == NULL || *p != '-' || *++p == '\0')
-+ if (p == NULL)
-+ return '\0';
-+ if (*p != '-')
-+ return '\0';
-+ if (*++p == '\0') /* just "-" ? */
- return '\0';
- argptr++;
-- if (LONE_DASH(p)) /* check for "--" */
-+ if (LONE_DASH(p)) /* "--" ? */
- return '\0';
-+ /* p => next "-param" */
- }
-+ /* p => some option char in the middle of a "-param" */
- c = *p++;
- for (q = optstring; *q != c;) {
- if (*q == '\0')
-@@ -1602,8 +1609,11 @@
- q++;
- }
- if (*++q == ':') {
-- if (*p == '\0' && (p = *argptr++) == NULL)
-- ash_msg_and_raise_error("no arg for -%c option", c);
-+ if (*p == '\0') {
-+ p = *argptr++;
-+ if (p == NULL)
-+ ash_msg_and_raise_error("no arg for -%c option", c);
-+ }
- optionarg = p;
- p = NULL;
- }
-@@ -7428,8 +7438,10 @@
- else if (c != 'p')
- abort();
- #endif
-- if (verify)
-+ /* Mimic bash: just "command -v" doesn't complain, it's a nop */
-+ if (verify && (*argptr != NULL)) {
- return describe_command(*argptr, verify - VERIFY_BRIEF);
-+ }
-
- return 0;
- }
-@@ -7788,16 +7800,33 @@
- static void
- evaltree(union node *n, int flags)
- {
-+
-+ struct jmploc *volatile savehandler = exception_handler;
-+ struct jmploc jmploc;
- int checkexit = 0;
- void (*evalfn)(union node *, int);
-- unsigned isor;
- int status;
-+
- if (n == NULL) {
- TRACE(("evaltree(NULL) called\n"));
-- goto out;
-+ goto out1;
- }
- TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
- getpid(), n, n->type, flags));
-+
-+ exception_handler = &jmploc;
-+ {
-+ int err = setjmp(jmploc.loc);
-+ if (err) {
-+ /* if it was a signal, check for trap handlers */
-+ if (exception == EXSIG)
-+ goto out;
-+ /* continue on the way out */
-+ exception_handler = savehandler;
-+ longjmp(exception_handler->loc, err);
-+ }
-+ }
-+
- switch (n->type) {
- default:
- #if DEBUG
-@@ -7843,19 +7872,20 @@
- goto calleval;
- case NAND:
- case NOR:
-- case NSEMI:
-+ case NSEMI: {
-+
- #if NAND + 1 != NOR
- #error NAND + 1 != NOR
- #endif
- #if NOR + 1 != NSEMI
- #error NOR + 1 != NSEMI
- #endif
-- isor = n->type - NAND;
-+ unsigned is_or = n->type - NAND;
- evaltree(
- n->nbinary.ch1,
-- (flags | ((isor >> 1) - 1)) & EV_TESTED
-+ (flags | ((is_or >> 1) - 1)) & EV_TESTED
- );
-- if (!exitstatus == isor)
-+ if (!exitstatus == is_or)
- break;
- if (!evalskip) {
- n = n->nbinary.ch2;
-@@ -7866,6 +7896,7 @@
- break;
- }
- break;
-+ }
- case NIF:
- evaltree(n->nif.test, EV_TESTED);
- if (evalskip)
-@@ -7886,8 +7917,11 @@
- exitstatus = status;
- break;
- }
-+
- out:
-- if ((checkexit & exitstatus))
-+ exception_handler = savehandler;
-+ out1:
-+ if (checkexit & exitstatus)
- evalskip |= SKIPEVAL;
- else if (pendingsig && dotrap())
- goto exexit;
--- /dev/null
+--- a/libbb/lineedit.c
++++ b/libbb/lineedit.c
+@@ -953,24 +953,33 @@
+
+ #if MAX_HISTORY > 0
+
++static void save_command_ps_at_cur_history(void)
++{
++ if (command_ps[0] != '\0') {
++ int cur = state->cur_history;
++ free(state->history[cur]);
++ state->history[cur] = xstrdup(command_ps);
++ }
++}
++
+ /* state->flags is already checked to be nonzero */
+-static void get_previous_history(void)
++static int get_previous_history(void)
+ {
+- if (command_ps[0] != '\0' || state->history[state->cur_history] == NULL) {
+- free(state->history[state->cur_history]);
+- state->history[state->cur_history] = xstrdup(command_ps);
++ if ((state->flags & DO_HISTORY) && state->cur_history) {
++ save_command_ps_at_cur_history();
++ state->cur_history--;
++ return 1;
+ }
+- state->cur_history--;
++ beep();
++ return 0;
+ }
+
+ static int get_next_history(void)
+ {
+ if (state->flags & DO_HISTORY) {
+- int ch = state->cur_history;
+- if (ch < state->cnt_history) {
+- get_previous_history(); /* save the current history line */
+- state->cur_history = ch + 1;
+- return state->cur_history;
++ if (state->cur_history < state->cnt_history) {
++ save_command_ps_at_cur_history(); /* save the current history line */
++ return ++state->cur_history;
+ }
+ }
+ beep();
+@@ -992,6 +1001,7 @@
+ for (hi = state->cnt_history; hi > 0;) {
+ hi--;
+ free(state->history[hi]);
++ state->history[hi] = NULL;
+ }
+
+ for (hi = 0; hi < MAX_HISTORY;) {
+@@ -1003,7 +1013,7 @@
+ l = strlen(hl);
+ if (l >= MAX_LINELEN)
+ hl[MAX_LINELEN-1] = '\0';
+- if (l == 0 || hl[0] == ' ') {
++ if (l == 0) {
+ free(hl);
+ continue;
+ }
+@@ -1040,19 +1050,27 @@
+
+ if (!(state->flags & DO_HISTORY))
+ return;
+-
++ if (str[0] == '\0')
++ return;
+ i = state->cnt_history;
+- free(state->history[MAX_HISTORY]);
+- state->history[MAX_HISTORY] = NULL;
+- /* After max history, remove the oldest command */
++ /* Don't save dupes */
++ if (i && strcmp(state->history[i-1], str) == 0)
++ return;
++
++ free(state->history[MAX_HISTORY]); /* redundant, paranoia */
++ state->history[MAX_HISTORY] = NULL; /* redundant, paranoia */
++
++ /* If history[] is full, remove the oldest command */
++ /* we need to keep history[MAX_HISTORY] empty, hence >=, not > */
+ if (i >= MAX_HISTORY) {
+ free(state->history[0]);
+ for (i = 0; i < MAX_HISTORY-1; i++)
+ state->history[i] = state->history[i+1];
++ /* i == MAX_HISTORY-1 */
+ }
+-// Maybe "if (!i || strcmp(history[i-1], command) != 0) ..."
+-// (i.e. do not save dups?)
++ /* i <= MAX_HISTORY-1 */
+ state->history[i++] = xstrdup(str);
++ /* i <= MAX_HISTORY */
+ state->cur_history = i;
+ state->cnt_history = i;
+ #if ENABLE_FEATURE_EDITING_SAVEHISTORY
+@@ -1429,6 +1447,13 @@
+ }
+ }
+ #endif
++
++#if 0
++ for (ic = 0; ic <= MAX_HISTORY; ic++)
++ bb_error_msg("history[%d]:'%s'", ic, state->history[ic]);
++ bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history);
++#endif
++
+ /* Print out the command prompt */
+ parse_and_put_prompt(prompt);
+
+@@ -1537,11 +1562,8 @@
+ vi_case(CTRL('P')|vbit:)
+ vi_case('k'|vbit:)
+ /* Control-p -- Get previous command from history */
+- if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
+- get_previous_history();
++ if (get_previous_history())
+ goto rewrite_line;
+- }
+- beep();
+ break;
+ #endif
+
+@@ -1730,10 +1752,8 @@
+ #if MAX_HISTORY > 0
+ case 'A':
+ /* Up Arrow -- Get previous command from history */
+- if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
+- get_previous_history();
++ if (get_previous_history())
+ goto rewrite_line;
+- }
+ beep();
+ break;
+ case 'B':
+@@ -1743,7 +1763,7 @@
+ rewrite_line:
+ /* Rewrite the line with the selected history item */
+ /* change command */
+- command_len = strlen(strcpy(command, state->history[state->cur_history]));
++ command_len = strlen(strcpy(command, state->history[state->cur_history] ? : ""));
+ /* redraw and go to eol (bol, in vi */
+ redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
+ break;
+++ /dev/null
---- a/applets/usage_compressed
-+++ b/applets/usage_compressed
-@@ -14,14 +14,21 @@
-
- echo 'static const char packed_usage[] ALIGN1 = {'
-
--# Extra effort to avoid using "od -t x1": -t is not available
--# in non-CONFIG_DESKTOPed busybox od
-+## Breaks on big-endian systems!
-+## # Extra effort to avoid using "od -t x1": -t is not available
-+## # in non-CONFIG_DESKTOPed busybox od
-+##
-+## "$loc/usage" | bzip2 -1 | od -v -x \
-+## | $SED -e 's/^[^ ]*//' \
-+## | $SED -e 's/ //g' \
-+## | grep -v '^$' \
-+## | $SED -e 's/\(..\)\(..\)/0x\2,0x\1,/g'
-
--"$loc/usage" | bzip2 -1 | od -v -x \
-+"$loc/usage" | bzip2 -1 | od -v -t x1 \
- | $SED -e 's/^[^ ]*//' \
- | $SED -e 's/ //g' \
- | grep -v '^$' \
--| $SED -e 's/\(..\)\(..\)/0x\2,0x\1,/g'
-+| $SED -e 's/\(..\)/0x\1,/g'
-
- echo '};'
- echo '#define SIZEOF_usage_messages' `expr 0 + $sz`