@@ -0,0 +1,164 @@
+--- busybox-1.12.0/editors/vi.c Wed Aug 6 00:56:11 2008
++++ busybox-1.12.0-crontab_vi/editors/vi.c Sun Sep 21 17:30:47 2008
+@@ -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;
+ }
+@@ -2157,21 +2157,21 @@
+ //----- Come here when we get a continue signal -------------------
+ static void cont_sig(int sig UNUSED_PARAM)
+ {
+- rawmode(); // terminal to "raw"
+- last_status_cksum = 0; // force status update
+- redraw(TRUE); // re-draw the screen
++ rawmode(); // terminal to "raw"
++ last_status_cksum = 0; // force status update
++ redraw(TRUE); // re-draw the screen
+
+ signal(SIGTSTP, suspend_sig);
+ signal(SIGCONT, SIG_DFL);
+- kill(my_pid, SIGCONT);
++ kill(my_pid, SIGCONT); // huh? why? we are already "continued"...
+ }
+
+ //----- Come here when we get a Suspend signal -------------------
+ static void suspend_sig(int sig UNUSED_PARAM)
+ {
+- place_cursor(rows - 1, 0, FALSE); // go to bottom of screen
+- clear_to_eol(); // Erase to end of line
+- cookmode(); // terminal to "cooked"
++ place_cursor(rows - 1, 0, FALSE); // go to bottom of screen
++ clear_to_eol(); // erase to end of line
++ cookmode(); // terminal to "cooked"
+
+ signal(SIGCONT, cont_sig);
+ signal(SIGTSTP, SIG_DFL);
+@@ -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) {
++ 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");
+ }
+- if (n <= 0)
+- return 0; // error
++ /* 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
+--- busybox-1.12.0/miscutils/crontab.c Wed Aug 6 00:56:08 2008
++++ busybox-1.12.0-crontab_vi/miscutils/crontab.c Sun Sep 21 17:30:47 2008
+@@ -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 {
|
@@ -0,0 +1,78 @@
+--- busybox-1.12.0/findutils/grep.c Sat Aug 9 18:14:59 2008
++++ busybox-1.12.0-grep/findutils/grep.c Fri Sep 19 23:33:15 2008
+@@ -87,7 +87,11 @@
+
+ struct globals {
+ int max_matches;
++#if !ENABLE_EXTRA_COMPAT
+ int reflags;
++#else
++ RE_TRANSLATE_TYPE case_fold; /* RE_TRANSLATE_TYPE is [[un]signed] char* */
++#endif
+ smalluint invert_search;
+ smalluint print_filename;
+ smalluint open_errors;
+@@ -110,7 +114,19 @@
+ }; \
+ } while (0)
+ #define max_matches (G.max_matches )
++#if !ENABLE_EXTRA_COMPAT
+ #define reflags (G.reflags )
++#else
++#define case_fold (G.case_fold )
++/* http://www.delorie.com/gnu/docs/regex/regex_46.html */
++#define reflags re_syntax_options
++#undef REG_NOSUB
++#undef REG_EXTENDED
++#undef REG_ICASE
++#define REG_NOSUB bug:is:here /* should not be used */
++#define REG_EXTENDED RE_SYNTAX_EGREP
++#define REG_ICASE bug:is:here /* should not be used */
++#endif
+ #define invert_search (G.invert_search )
+ #define print_filename (G.print_filename )
+ #define open_errors (G.open_errors )
+@@ -240,6 +256,7 @@
+ xregcomp(&gl->compiled_regex, gl->pattern, reflags);
+ #else
+ memset(&gl->compiled_regex, 0, sizeof(gl->compiled_regex));
++ gl->compiled_regex.translate = case_fold; /* for -i */
+ if (re_compile_pattern(gl->pattern, strlen(gl->pattern), &gl->compiled_regex))
+ bb_error_msg_and_die("bad regex '%s'", gl->pattern);
+ #endif
+@@ -532,17 +549,34 @@
+ if (ENABLE_FEATURE_GREP_FGREP_ALIAS && applet_name[0] == 'f')
+ option_mask32 |= OPT_F;
+
++#if !ENABLE_EXTRA_COMPAT
+ if (!(option_mask32 & (OPT_o | OPT_w)))
+ reflags = REG_NOSUB;
++#endif
+
+ if (ENABLE_FEATURE_GREP_EGREP_ALIAS
+ && (applet_name[0] == 'e' || (option_mask32 & OPT_E))
+ ) {
+ reflags |= REG_EXTENDED;
+ }
++#if ENABLE_EXTRA_COMPAT
++ else {
++ reflags = RE_SYNTAX_GREP;
++ }
++#endif
+
+- if (option_mask32 & OPT_i)
++ if (option_mask32 & OPT_i) {
++#if !ENABLE_EXTRA_COMPAT
+ reflags |= REG_ICASE;
++#else
++ int i;
++ case_fold = xmalloc(256);
++ for (i = 0; i < 256; i++)
++ case_fold[i] = (unsigned char)i;
++ for (i = 'a'; i <= 'z'; i++)
++ case_fold[i] = (unsigned char)(i - ('a' - 'A'));
++#endif
++ }
+
+ argv += optind;
+ argc -= optind;
|
@@ -0,0 +1,145 @@
+--- busybox-1.12.0/libbb/lineedit.c Wed Aug 20 02:48:13 2008
++++ busybox-1.12.0-lineedit/libbb/lineedit.c Mon Sep 22 00:27:18 2008
+@@ -956,24 +956,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();
+@@ -995,6 +1004,7 @@
+ for (hi = state->cnt_history; hi > 0;) {
+ hi--;
+ free(state->history[hi]);
++ state->history[hi] = NULL;
+ }
+
+ for (hi = 0; hi < MAX_HISTORY;) {
+@@ -1006,7 +1016,7 @@
+ l = strlen(hl);
+ if (l >= MAX_LINELEN)
+ hl[MAX_LINELEN-1] = '\0';
+- if (l == 0 || hl[0] == ' ') {
++ if (l == 0) {
+ free(hl);
+ continue;
+ }
+@@ -1043,19 +1053,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
+@@ -1432,6 +1450,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);
+
+@@ -1540,11 +1565,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
+
+@@ -1733,10 +1755,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':
+@@ -1746,7 +1766,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;
|