*/
+#include "busybox.h"
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <limits.h>
-#include "busybox.h"
-
-#include "../shell/cmdedit.h"
+#include "cmdedit.h"
#ifdef CONFIG_LOCALE_SUPPORT
#define CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
#endif
-#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
-#include "pwd_.h"
-#endif /* advanced FEATURES */
-
-
/* Maximum length of the linked list for the command line history */
#ifndef CONFIG_FEATURE_COMMAND_HISTORY
#define MAX_HISTORY 15
printf("\033[7m%c\033[0m", c);
} else
#endif
- putchar(c);
+ if (initial_settings.c_lflag & ECHO) putchar(c);
if (++cmdedit_x >= cmdedit_termw) {
/* terminal is scrolled down */
cmdedit_y++;
}
-static inline void out1str(const char *s)
+static void out1str(const char *s)
{
if ( s )
fputs(s, stdout);
}
-static inline void beep(void)
+static void beep(void)
{
putchar('\007');
}
if (num < 4)
while (num-- > 0)
putchar('\b');
-
else
printf("\033[%dD", num);
} else {
int prmt_len = 0;
size_t cur_prmt_len = 0;
char flg_not_length = '[';
- char *prmt_mem_ptr = xcalloc(1, 1);
+ char *prmt_mem_ptr = xzalloc(1);
char *pwd_buf = xgetcwd(0);
char buf2[PATH_MAX + 1];
char buf[2];
case 'h':
pbuf = hostname_buf;
if (pbuf == 0) {
- pbuf = xcalloc(256, 1);
+ pbuf = xzalloc(256);
if (gethostname(pbuf, 255) < 0) {
strcpy(pbuf, "?");
} else {
pbuf = buf2;
*pbuf = '~';
strcpy(pbuf+1, pwd_buf+l);
- }
+ }
break;
#endif
case 'W':
}
#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
-static char delbuf[BUFSIZ]; /* a place to store deleted characters */
-static char *delp = delbuf;
-static int newdelflag; /* whether delbuf should be reused yet */
+#define DELBUFSIZ 128
+static char *delbuf; /* a (malloced) place to store deleted characters */
+static char *delp;
+static char newdelflag; /* whether delbuf should be reused yet */
#endif
/* Delete the char in front of the cursor, optionally saving it
#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
if (save) {
if (newdelflag) {
+ if (!delbuf)
+ delbuf = malloc(DELBUFSIZ);
+ /* safe if malloc fails */
delp = delbuf;
newdelflag = 0;
}
- if (delp - delbuf < BUFSIZ)
+ if (delbuf && (delp - delbuf < DELBUFSIZ))
*delp++ = command_ps[j];
}
#endif
my_euid = geteuid();
entry = getpwuid(my_euid);
if (entry) {
- user_buf = bb_xstrdup(entry->pw_name);
- home_pwd_buf = bb_xstrdup(entry->pw_dir);
+ user_buf = xstrdup(entry->pw_name);
+ home_pwd_buf = xstrdup(entry->pw_dir);
}
#endif
while ((entry = getpwent()) != NULL) {
/* Null usernames should result in all users as possible completions. */
if ( /*!userlen || */ !strncmp(ud, entry->pw_name, userlen)) {
- add_match(bb_xasprintf("~%s", entry->pw_name), '/');
+ add_match(xasprintf("~%s", entry->pw_name), '/');
}
}
*p = xmalloc(npth * sizeof(char *));
tmp = pth;
- (*p)[0] = bb_xstrdup(tmp);
+ (*p)[0] = xstrdup(tmp);
npth = 1; /* count words is + 1 count ':' */
for (;;) {
s[l++] = *found++;
}
if(add)
- s[l++] = (char)add;
+ s[l++] = (char)add;
s[l] = 0;
return s;
}
for (row = 0; row < nrows; row++) {
l = strlen(matches[row]);
if(add_char_to_match[row])
- l++;
+ l++;
if (column_width < l)
column_width = l;
}
printf("%s%s", matches[n], str_add_chr);
l = strlen(matches[n]);
while(l < acol) {
- putchar(' ');
- l++;
+ putchar(' ');
+ l++;
}
}
str_add_chr[0] = add_char_to_match[n];
int i, j, n, srt;
/* bubble */
n = num_matches;
- for(i=0; i<(n-1); i++)
- for(j=i+1; j<n; j++)
- if(matches[i]!=NULL && matches[j]!=NULL) {
- srt = strcmp(matches[i], matches[j]);
- if(srt == 0) {
- free(matches[j]);
- matches[j]=0;
- } else if(srt > 0) {
- tmp1 = matches[i];
- matches[i] = matches[j];
- matches[j] = tmp1;
- srt = add_char_to_match[i];
- add_char_to_match[i] = add_char_to_match[j];
- add_char_to_match[j] = srt;
- }
+ for(i=0; i<(n-1); i++) {
+ for(j=i+1; j<n; j++) {
+ if(matches[i]!=NULL && matches[j]!=NULL) {
+ srt = strcmp(matches[i], matches[j]);
+ if(srt == 0) {
+ free(matches[j]);
+ matches[j]=0;
+ } else if(srt > 0) {
+ tmp1 = matches[i];
+ matches[i] = matches[j];
+ matches[j] = tmp1;
+ srt = add_char_to_match[i];
+ add_char_to_match[i] = add_char_to_match[j];
+ add_char_to_match[j] = srt;
+ }
+ }
}
+ }
j = n;
n = 0;
for(i=0; i<j; i++)
- if(matches[i]) {
- matches[n]=matches[i];
- add_char_to_match[n]=add_char_to_match[i];
- n++;
- }
+ if(matches[i]) {
+ matches[n]=matches[i];
+ add_char_to_match[n]=add_char_to_match[i];
+ n++;
+ }
num_matches = n;
}
/* Did we find exactly one match? */
if (!matches)
return; /* not found */
/* find minimal match */
- tmp1 = bb_xstrdup(matches[0]);
+ tmp1 = xstrdup(matches[0]);
for (tmp = tmp1; *tmp; tmp++)
for (len_found = 1; len_found < num_matches; len_found++)
if (matches[len_found][(tmp - tmp1)] != *tmp) {
{
if(command_ps[0] != 0 || history[cur_history] == 0) {
free(history[cur_history]);
- history[cur_history] = bb_xstrdup(command_ps);
+ history[cur_history] = xstrdup(command_ps);
}
cur_history--;
}
}
#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
-extern void load_history ( const char *fromfile )
+void load_history ( const char *fromfile )
{
FILE *fp;
int hi;
if (( fp = fopen ( fromfile, "r" ))) {
for ( hi = 0; hi < MAX_HISTORY; ) {
- char * hl = bb_get_chomped_line_from_file(fp);
+ char * hl = xmalloc_getline(fp);
int l;
if(!hl)
cur_history = n_history = hi;
}
-extern void save_history ( const char *tofile )
+void save_history ( const char *tofile )
{
FILE *fp = fopen ( tofile, "w" );
#endif
/*
- * the normal emacs mode and vi's insert mode are the same.
- * commands entered when in vi command mode ("escape mode") get
- * an extra bit added to distinguish them. this lets them share
- * much of the code in the big switch and while loop. i
- * experimented with an ugly macro to make the case labels for
- * these cases go away entirely when vi mode isn't configured, in
- * hopes of letting the jump tables get smaller:
- * #define vcase(caselabel) caselabel
- * and then
- * case CNTRL('A'):
- * case vcase(VICMD('0'):)
- * but it didn't seem to make any difference in code size,
- * and the macro-ized code was too ugly.
+ * the emacs and vi modes share much of the code in the big
+ * command loop. commands entered when in vi's command mode (aka
+ * "escape mode") get an extra bit added to distinguish them --
+ * this keeps them from being self-inserted. this clutters the
+ * big switch a bit, but keeps all the code in one place.
*/
-#define VI_cmdbit 0x100
-#define VICMD(somecmd) ((somecmd)|VI_cmdbit)
+#define vbit 0x100
+
+/* leave out the "vi-mode"-only case labels if vi editing isn't
+ * configured. */
+#define vi_case(caselabel) USE_FEATURE_COMMAND_EDITING(caselabel)
/* convert uppercase ascii to equivalent control char, for readability */
#define CNTRL(uc_char) ((uc_char) - 0x40)
int break_out = 0;
int lastWasTab = FALSE;
unsigned char c;
+ unsigned int ic;
#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
- unsigned int ic, prevc;
+ unsigned int prevc;
int vi_cmdmode = 0;
#endif
/* prepare before init handlers */
/* if we can't read input then exit */
goto prepare_to_die;
+ ic = c;
+
#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
newdelflag = 1;
- ic = c;
if (vi_cmdmode)
- ic |= VI_cmdbit;
- switch (ic)
-#else
- switch (c)
+ ic |= vbit;
#endif
+ switch (ic)
{
case '\n':
case '\r':
- case VICMD('\n'):
- case VICMD('\r'):
+ vi_case( case '\n'|vbit: )
+ vi_case( case '\r'|vbit: )
/* Enter */
goto_new_line();
break_out = 1;
break;
case CNTRL('A'):
- case VICMD('0'):
+ vi_case( case '0'|vbit: )
/* Control-a -- Beginning of line */
input_backward(cursor);
break;
case CNTRL('B'):
- case VICMD('h'):
- case VICMD('\b'):
- case VICMD(DEL):
+ vi_case( case 'h'|vbit: )
+ vi_case( case '\b'|vbit: )
+ vi_case( case DEL|vbit: )
/* Control-b -- Move back one character */
input_backward(1);
break;
case CNTRL('C'):
- case VICMD(CNTRL('C')):
+ vi_case( case CNTRL('C')|vbit: )
/* Control-c -- stop gathering input */
goto_new_line();
#ifndef CONFIG_ASH
}
break;
case CNTRL('E'):
- case VICMD('$'):
+ vi_case( case '$'|vbit: )
/* Control-e -- End of line */
input_end();
break;
case CNTRL('F'):
- case VICMD('l'):
- case VICMD(' '):
+ vi_case( case 'l'|vbit: )
+ vi_case( case ' '|vbit: )
/* Control-f -- Move forward one character */
input_forward();
break;
printf("\033[J");
break;
case CNTRL('L'):
- case VICMD(CNTRL('L')):
+ vi_case( case CNTRL('L')|vbit: )
/* Control-l -- clear screen */
printf("\033[H");
redraw(0, len-cursor);
break;
#if MAX_HISTORY >= 1
case CNTRL('N'):
- case VICMD(CNTRL('N')):
- case VICMD('j'):
+ vi_case( case CNTRL('N')|vbit: )
+ vi_case( case 'j'|vbit: )
/* Control-n -- Get next command in history */
if (get_next_history())
goto rewrite_line;
break;
case CNTRL('P'):
- case VICMD(CNTRL('P')):
- case VICMD('k'):
+ vi_case( case CNTRL('P')|vbit: )
+ vi_case( case 'k'|vbit: )
/* Control-p -- Get previous command from history */
if (cur_history > 0) {
get_previous_history();
break;
#endif
case CNTRL('U'):
- case VICMD(CNTRL('U')):
+ vi_case( case CNTRL('U')|vbit: )
/* Control-U -- Clear line before cursor */
if (cursor) {
strcpy(command, command + cursor);
}
break;
case CNTRL('W'):
- case VICMD(CNTRL('W')):
+ vi_case( case CNTRL('W')|vbit: )
/* Control-W -- Remove the last word */
while (cursor > 0 && isspace(command[cursor-1]))
input_backspace();
input_backspace();
break;
#if CONFIG_FEATURE_COMMAND_EDITING_VI
- case VICMD('i'):
+ case 'i'|vbit:
vi_cmdmode = 0;
break;
- case VICMD('I'):
+ case 'I'|vbit:
input_backward(cursor);
vi_cmdmode = 0;
break;
- case VICMD('a'):
+ case 'a'|vbit:
input_forward();
vi_cmdmode = 0;
break;
- case VICMD('A'):
+ case 'A'|vbit:
input_end();
vi_cmdmode = 0;
break;
- case VICMD('x'):
+ case 'x'|vbit:
input_delete(1);
break;
- case VICMD('X'):
+ case 'X'|vbit:
if (cursor > 0) {
input_backward(1);
input_delete(1);
}
break;
- case VICMD('W'):
+ case 'W'|vbit:
vi_Word_motion(command, 1);
break;
- case VICMD('w'):
+ case 'w'|vbit:
vi_word_motion(command, 1);
break;
- case VICMD('E'):
+ case 'E'|vbit:
vi_End_motion(command);
break;
- case VICMD('e'):
+ case 'e'|vbit:
vi_end_motion(command);
break;
- case VICMD('B'):
+ case 'B'|vbit:
vi_Back_motion(command);
break;
- case VICMD('b'):
+ case 'b'|vbit:
vi_back_motion(command);
break;
- case VICMD('C'):
+ case 'C'|vbit:
vi_cmdmode = 0;
/* fall through */
- case VICMD('D'):
+ case 'D'|vbit:
goto clear_to_eol;
- case VICMD('c'):
+ case 'c'|vbit:
vi_cmdmode = 0;
/* fall through */
- case VICMD('d'):
+ case 'd'|vbit:
{
- int nc, sc;
- sc = cursor;
- prevc = ic;
- if (safe_read(0, &c, 1) < 1)
- goto prepare_to_die;
- if (c == (prevc & 0xff)) {
- /* "cc", "dd" */
- input_backward(cursor);
- goto clear_to_eol;
- break;
- }
- switch(c) {
- case 'w':
- case 'W':
- case 'e':
- case 'E':
- switch (c) {
- case 'w': /* "dw", "cw" */
- vi_word_motion(command, vi_cmdmode);
- break;
- case 'W': /* 'dW', 'cW' */
- vi_Word_motion(command, vi_cmdmode);
- break;
- case 'e': /* 'de', 'ce' */
- vi_end_motion(command);
- input_forward();
- break;
- case 'E': /* 'dE', 'cE' */
- vi_End_motion(command);
- input_forward();
- break;
- }
- nc = cursor;
- input_backward(cursor - sc);
- while (nc-- > cursor)
- input_delete(1);
- break;
- case 'b': /* "db", "cb" */
- case 'B': /* implemented as B */
- if (c == 'b')
- vi_back_motion(command);
- else
- vi_Back_motion(command);
- while (sc-- > cursor)
- input_delete(1);
- break;
- case ' ': /* "d ", "c " */
- input_delete(1);
- break;
- case '$': /* "d$", "c$" */
- clear_to_eol:
- while (cursor < len)
- input_delete(1);
- break;
- }
+ int nc, sc;
+ sc = cursor;
+ prevc = ic;
+ if (safe_read(0, &c, 1) < 1)
+ goto prepare_to_die;
+ if (c == (prevc & 0xff)) {
+ /* "cc", "dd" */
+ input_backward(cursor);
+ goto clear_to_eol;
+ break;
+ }
+ switch(c) {
+ case 'w':
+ case 'W':
+ case 'e':
+ case 'E':
+ switch (c) {
+ case 'w': /* "dw", "cw" */
+ vi_word_motion(command, vi_cmdmode);
+ break;
+ case 'W': /* 'dW', 'cW' */
+ vi_Word_motion(command, vi_cmdmode);
+ break;
+ case 'e': /* 'de', 'ce' */
+ vi_end_motion(command);
+ input_forward();
+ break;
+ case 'E': /* 'dE', 'cE' */
+ vi_End_motion(command);
+ input_forward();
+ break;
+ }
+ nc = cursor;
+ input_backward(cursor - sc);
+ while (nc-- > cursor)
+ input_delete(1);
+ break;
+ case 'b': /* "db", "cb" */
+ case 'B': /* implemented as B */
+ if (c == 'b')
+ vi_back_motion(command);
+ else
+ vi_Back_motion(command);
+ while (sc-- > cursor)
+ input_delete(1);
+ break;
+ case ' ': /* "d ", "c " */
+ input_delete(1);
+ break;
+ case '$': /* "d$", "c$" */
+ clear_to_eol:
+ while (cursor < len)
+ input_delete(1);
+ break;
+ }
}
break;
- case VICMD('p'):
+ case 'p'|vbit:
input_forward();
/* fallthrough */
- case VICMD('P'):
+ case 'P'|vbit:
put();
break;
- case VICMD('r'):
+ case 'r'|vbit:
if (safe_read(0, &c, 1) < 1)
goto prepare_to_die;
if (c == 0)
}
break;
#endif /* CONFIG_FEATURE_COMMAND_EDITING_VI */
- case ESC:{
+
+ case ESC:
+
#if CONFIG_FEATURE_COMMAND_EDITING_VI
if (vi_mode) {
/* ESC: insert mode --> command mode */
goto prepare_to_die;
/* different vt100 emulations */
if (c == '[' || c == 'O') {
- case VICMD('['):
- case VICMD('O'):
+ vi_case( case '['|vbit: )
+ vi_case( case 'O'|vbit: )
if (safe_read(0, &c, 1) < 1)
goto prepare_to_die;
}
beep();
}
break;
- }
default: /* If it's regular input, do the normal thing */
#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
for(i = 0; i < (MAX_HISTORY-1); i++)
history[i] = history[i+1];
}
- history[i++] = bb_xstrdup(command);
+ history[i++] = xstrdup(command);
cur_history = i;
n_history = i;
#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
#ifdef TEST
-const char *bb_applet_name = "debug stuff usage";
+const char *applet_name = "debug stuff usage";
#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
#include <locale.h>