This is synced from dash-0.4.17 and full ready for insert to new busybox
version:
ftp://ftp.simtreas.ru/pub/my/bb/new
News:
- code is smalest!
- support ${var...} expr
- used new very strongly steal controlling terminal
diff --git a/shell/cmdedit.c b/shell/cmdedit.c
index 843f73f..7170672 100644
--- a/shell/cmdedit.c
+++ b/shell/cmdedit.c
@@ -9,7 +9,7 @@
* Adam Rogoyski <rogoyski@cs.utexas.edu>
* Dave Cinege <dcinege@psychosis.com>
* Jakub Jelinek (c) 1995
- * Erik Andersen <andersen@codepoet.org> (Majorly adjusted for busybox)
+ * Erik Andersen <andersee@debian.org> (Majorly adjusted for busybox)
*
* This code is 'as is' with no warranty.
*
@@ -63,7 +63,7 @@
#define D(x) x
-#endif /* TEST */
+#endif /* TEST */
#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
#include <dirent.h>
@@ -86,7 +86,7 @@
# else
# include <pwd.h>
# endif /* TEST */
-#endif /* advanced FEATURES */
+#endif /* advanced FEATURES */
/* Maximum length of the linked list for the command line history */
@@ -115,30 +115,30 @@
static
-volatile int cmdedit_termw = 80; /* actual terminal width */
+volatile int cmdedit_termw = 80; /* actual terminal width */
static
-volatile int handlers_sets = 0; /* Set next bites: */
+volatile int handlers_sets = 0; /* Set next bites: */
enum {
- SET_ATEXIT = 1, /* when atexit() has been called
+ SET_ATEXIT = 1, /* when atexit() has been called
and get euid,uid,gid to fast compare */
SET_WCHG_HANDLERS = 2, /* winchg signal handler */
SET_RESET_TERM = 4, /* if the terminal needs to be reset upon exit */
};
-static int cmdedit_x; /* real x terminal position */
-static int cmdedit_y; /* pseudoreal y terminal position */
-static int cmdedit_prmt_len; /* lenght prompt without colores string */
+static int cmdedit_x; /* real x terminal position */
+static int cmdedit_y; /* pseudoreal y terminal position */
+static int cmdedit_prmt_len; /* lenght prompt without colores string */
-static int cursor; /* required global for signal handler */
-static int len; /* --- "" - - "" - -"- --""-- --""--- */
-static char *command_ps; /* --- "" - - "" - -"- --""-- --""--- */
+static int cursor; /* required global for signal handler */
+static int len; /* --- "" - - "" - -"- --""-- --""--- */
+static char *command_ps; /* --- "" - - "" - -"- --""-- --""--- */
static
#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
const
#endif
-char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */
+char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */
#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR
static char *user_buf = "";
@@ -161,31 +161,36 @@
static int my_uid;
static int my_gid;
-#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */
+#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */
+
+/* It seems that libc5 doesn't know what a sighandler_t is... */
+#if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1)
+typedef void (*sighandler_t) (int);
+#endif
static void cmdedit_setwidth(int w, int redraw_flg);
static void win_changed(int nsig)
{
struct winsize win = { 0, 0, 0, 0 };
- static sighandler_t previous_SIGWINCH_handler; /* for reset */
+ static sighandler_t previous_SIGWINCH_handler; /* for reset */
/* emulate || signal call */
if (nsig == -SIGWINCH || nsig == SIGWINCH) {
ioctl(0, TIOCGWINSZ, &win);
if (win.ws_col > 0) {
cmdedit_setwidth(win.ws_col, nsig == SIGWINCH);
- }
+ }
}
/* Unix not all standart in recall signal */
- if (nsig == -SIGWINCH) /* save previous handler */
+ if (nsig == -SIGWINCH) /* save previous handler */
previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
- else if (nsig == SIGWINCH) /* signaled called handler */
- signal(SIGWINCH, win_changed); /* set for next call */
- else /* nsig == 0 */
+ else if (nsig == SIGWINCH) /* signaled called handler */
+ signal(SIGWINCH, win_changed); /* set for next call */
+ else /* nsig == 0 */
/* set previous handler */
- signal(SIGWINCH, previous_SIGWINCH_handler); /* reset */
+ signal(SIGWINCH, previous_SIGWINCH_handler); /* reset */
}
static void cmdedit_reset_term(void)
@@ -211,9 +216,9 @@
int c = (int)((unsigned char) command_ps[cursor]);
if (c == 0)
- c = ' '; /* destroy end char? */
+ c = ' '; /* destroy end char? */
#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
- if (!Isprint(c)) { /* Inverse put non-printable characters */
+ if (!Isprint(c)) { /* Inverse put non-printable characters */
if (c >= 128)
c -= 128;
if (c < ' ')
@@ -270,9 +275,9 @@
{
if (num > cursor)
num = cursor;
- cursor -= num; /* new cursor (in command, not terminal) */
+ cursor -= num; /* new cursor (in command, not terminal) */
- if (cmdedit_x >= num) { /* no to up line */
+ if (cmdedit_x >= num) { /* no to up line */
cmdedit_x -= num;
if (num < 4)
while (num-- > 0)
@@ -284,22 +289,22 @@
int count_y;
if (cmdedit_x) {
- putchar('\r'); /* back to first terminal pos. */
- num -= cmdedit_x; /* set previous backward */
+ putchar('\r'); /* back to first terminal pos. */
+ num -= cmdedit_x; /* set previous backward */
}
count_y = 1 + num / cmdedit_termw;
printf("\033[%dA", count_y);
cmdedit_y -= count_y;
/* require forward after uping */
cmdedit_x = cmdedit_termw * count_y - num;
- printf("\033[%dC", cmdedit_x); /* set term cursor */
+ printf("\033[%dC", cmdedit_x); /* set term cursor */
}
}
static void put_prompt(void)
{
out1str(cmdedit_prompt);
- cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */
+ cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */
cursor = 0;
cmdedit_y = 0; /* new quasireal y */
}
@@ -335,7 +340,7 @@
if (c == '\\') {
const char *cp = prmt_ptr;
int l;
-
+
c = bb_process_escape_sequence(&prmt_ptr);
if(prmt_ptr==cp) {
if (*cp == 0)
@@ -346,7 +351,7 @@
case 'u':
pbuf = user_buf;
break;
-#endif
+#endif
case 'h':
pbuf = hostname_buf;
if (pbuf == 0) {
@@ -378,7 +383,7 @@
strcpy(pbuf+1, pwd_buf+l);
}
break;
-#endif
+#endif
case 'W':
pbuf = pwd_buf;
cp = strrchr(pbuf,'/');
@@ -391,7 +396,7 @@
case 'e': case 'E': /* \e \E = \033 */
c = '\033';
break;
- case 'x': case 'X':
+ case 'x': case 'X':
for (l = 0; l < 3;) {
int h;
buf2[l++] = *prmt_ptr;
@@ -416,7 +421,7 @@
}
break;
}
- }
+ }
}
if(pbuf == buf)
*pbuf = c;
@@ -437,12 +442,12 @@
/* draw promt, editor line, and clear tail */
static void redraw(int y, int back_cursor)
{
- if (y > 0) /* up to start y */
+ if (y > 0) /* up to start y */
printf("\033[%dA", y);
putchar('\r');
put_prompt();
- input_end(); /* rewrite */
- printf("\033[J"); /* destroy tail after cursor */
+ input_end(); /* rewrite */
+ printf("\033[J"); /* destroy tail after cursor */
input_backward(back_cursor);
}
@@ -456,9 +461,9 @@
strcpy(command_ps + j, command_ps + j + 1);
len--;
- input_end(); /* rewtite new line */
- cmdedit_set_out_char(0); /* destroy end char */
- input_backward(cursor - j); /* back to old pos cursor */
+ input_end(); /* rewtite new line */
+ cmdedit_set_out_char(0); /* destroy end char */
+ input_backward(cursor - j); /* back to old pos cursor */
}
/* Delete the char in back of the cursor */
@@ -496,7 +501,7 @@
redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), len - cursor);
fflush(stdout);
}
- }
+ }
}
static void cmdedit_init(void)
@@ -527,9 +532,9 @@
#endif
my_uid = getuid();
my_gid = getgid();
-#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */
+#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */
handlers_sets |= SET_ATEXIT;
- atexit(cmdedit_reset_term); /* be sure to do this only once */
+ atexit(cmdedit_reset_term); /* be sure to do this only once */
}
}
@@ -553,35 +558,35 @@
char *temp;
- ud++; /* ~user/... to user/... */
+ ud++; /* ~user/... to user/... */
userlen = strlen(ud);
- if (num_matches == 0) { /* "~/..." or "~user/..." */
+ if (num_matches == 0) { /* "~/..." or "~user/..." */
char *sav_ud = ud - 1;
char *home = 0;
- if (*ud == '/') { /* "~/..." */
+ if (*ud == '/') { /* "~/..." */
home = home_pwd_buf;
} else {
/* "~user/..." */
temp = strchr(ud, '/');
- *temp = 0; /* ~user\0 */
+ *temp = 0; /* ~user\0 */
entry = getpwnam(ud);
- *temp = '/'; /* restore ~user/... */
+ *temp = '/'; /* restore ~user/... */
ud = temp;
if (entry)
home = entry->pw_dir;
}
if (home) {
if ((userlen + strlen(home) + 1) < BUFSIZ) {
- char temp2[BUFSIZ]; /* argument size */
+ char temp2[BUFSIZ]; /* argument size */
/* /home/user/... */
sprintf(temp2, "%s%s", home, ud);
strcpy(sav_ud, temp2);
}
}
- return 0; /* void, result save to argument :-) */
+ return 0; /* void, result save to argument :-) */
} else {
/* "~[^/]*" */
char **matches = (char **) NULL;
@@ -593,7 +598,7 @@
/* Null usernames should result in all users as possible completions. */
if ( /*!userlen || */ !strncmp(ud, entry->pw_name, userlen)) {
- bb_xasprintf(&temp, "~%s/", entry->pw_name);
+ bb_xasprintf(&temp, "~%s/", entry->pw_name);
matches = xrealloc(matches, (nm + 1) * sizeof(char *));
matches[nm++] = temp;
@@ -605,7 +610,7 @@
return (matches);
}
}
-#endif /* CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION */
+#endif /* CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION */
enum {
FIND_EXE_ONLY = 0,
@@ -630,11 +635,11 @@
npth = 0;
for (;;) {
- npth++; /* count words is + 1 count ':' */
+ npth++; /* count words is + 1 count ':' */
tmp = strchr(tmp, ':');
if (tmp) {
if (*++tmp == 0)
- break; /* :<empty> */
+ break; /* :<empty> */
} else
break;
}
@@ -643,17 +648,17 @@
tmp = pth;
(*p)[0] = bb_xstrdup(tmp);
- npth = 1; /* count words is + 1 count ':' */
+ npth = 1; /* count words is + 1 count ':' */
for (;;) {
tmp = strchr(tmp, ':');
if (tmp) {
- (*p)[0][(tmp - pth)] = 0; /* ':' -> '\0' */
+ (*p)[0][(tmp - pth)] = 0; /* ':' -> '\0' */
if (*++tmp == 0)
- break; /* :<empty> */
+ break; /* :<empty> */
} else
break;
- (*p)[npth++] = &(*p)[0][(tmp - pth)]; /* p[next]=p[0][&'\0'+1] */
+ (*p)[npth++] = &(*p)[0][(tmp - pth)]; /* p[next]=p[0][&'\0'+1] */
}
return npth;
@@ -703,20 +708,20 @@
/* set dir only */
dirbuf[(pfind - command) + 1] = 0;
#ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION
- if (dirbuf[0] == '~') /* ~/... or ~user/... */
+ if (dirbuf[0] == '~') /* ~/... or ~user/... */
username_tab_completion(dirbuf, 0);
#endif
/* "strip" dirname in command */
pfind++;
paths[0] = dirbuf;
- npaths = 1; /* only 1 dir */
+ npaths = 1; /* only 1 dir */
}
for (i = 0; i < npaths; i++) {
dir = opendir(paths[i]);
- if (!dir) /* Don't print an error */
+ if (!dir) /* Don't print an error */
continue;
while ((next = readdir(dir)) != NULL) {
@@ -728,17 +733,17 @@
/* not see .name without .match */
if (*str_found == '.' && *pfind == 0) {
if (*paths[i] == '/' && paths[i][1] == 0
- && str_found[1] == 0) str_found = ""; /* only "/" */
+ && str_found[1] == 0) str_found = ""; /* only "/" */
else
continue;
}
found = concat_path_file(paths[i], str_found);
/* hmm, remover in progress? */
- if (stat(found, &st) < 0)
+ if (stat(found, &st) < 0)
goto cont;
/* find with dirs ? */
if (paths[i] != dirbuf)
- strcpy(found, next->d_name); /* only name */
+ strcpy(found, next->d_name); /* only name */
if (S_ISDIR(st.st_mode)) {
/* name is directory */
str_found = found;
@@ -747,7 +752,7 @@
str_found = add_quote_for_spec_chars(found);
} else {
/* not put found file if search only dirs for cd */
- if (type == FIND_DIR_ONLY)
+ if (type == FIND_DIR_ONLY)
goto cont;
str_found = add_quote_for_spec_chars(found);
if (type == FIND_FILE_ONLY ||
@@ -764,7 +769,7 @@
closedir(dir);
}
if (paths != path1) {
- free(paths[0]); /* allocated memory only in first member */
+ free(paths[0]); /* allocated memory only in first member */
free(paths);
}
*num_matches = nm;
@@ -796,7 +801,7 @@
for (i = 0;; i++) {
int_buf[i] = (int) ((unsigned char) matchBuf[i]);
if (int_buf[i] == 0) {
- pos_buf[i] = -1; /* indicator end line */
+ pos_buf[i] = -1; /* indicator end line */
break;
} else
pos_buf[i] = i;
@@ -809,7 +814,7 @@
int_buf[j] |= QUOT;
i++;
#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
- if (matchBuf[i] == '\t') /* algorithm equivalent */
+ if (matchBuf[i] == '\t') /* algorithm equivalent */
int_buf[j] = ' ' | QUOT;
#endif
}
@@ -852,7 +857,7 @@
}
if (command_mode) {
collapse_pos(0, i + command_mode);
- i = -1; /* hack incremet */
+ i = -1; /* hack incremet */
}
}
/* collapse `command...` */
@@ -869,11 +874,11 @@
collapse_pos(0, i + 1);
break;
} else
- i--; /* hack incremet */
+ i--; /* hack incremet */
}
/* collapse (command...(command...)...) or {command...{command...}...} */
- c = 0; /* "recursive" level */
+ c = 0; /* "recursive" level */
c2 = 0;
for (i = 0; int_buf[i]; i++)
if (int_buf[i] == '(' || int_buf[i] == '{') {
@@ -882,7 +887,7 @@
else
c2++;
collapse_pos(0, i + 1);
- i = -1; /* hack incremet */
+ i = -1; /* hack incremet */
}
for (i = 0; pos_buf[i] >= 0 && (c > 0 || c2 > 0); i++)
if ((int_buf[i] == ')' && c > 0) || (int_buf[i] == '}' && c2 > 0)) {
@@ -891,7 +896,7 @@
else
c2--;
collapse_pos(0, i + 1);
- i = -1; /* hack incremet */
+ i = -1; /* hack incremet */
}
/* skip first not quote space */
@@ -927,7 +932,7 @@
/* skip first not quoted '\'' or '"' */
for (i = 0; int_buf[i] == '\'' || int_buf[i] == '"'; i++);
/* collapse quote or unquote // or /~ */
- while ((int_buf[i] & ~QUOT) == '/' &&
+ while ((int_buf[i] & ~QUOT) == '/' &&
((int_buf[i + 1] & ~QUOT) == '/'
|| (int_buf[i + 1] & ~QUOT) == '~')) {
i++;
@@ -991,7 +996,7 @@
static int num_matches;
static char **matches;
- if (lastWasTab == 0) { /* free all memory */
+ if (lastWasTab == 0) { /* free all memory */
if (matches) {
while (num_matches > 0)
free(matches[--num_matches]);
@@ -1008,7 +1013,7 @@
int find_type;
int recalc_pos;
- *lastWasTab = TRUE; /* flop trigger */
+ *lastWasTab = TRUE; /* flop trigger */
/* Make a local copy of the string -- up
* to the position of the cursor */
@@ -1061,7 +1066,7 @@
beep();
if (!matches)
- return; /* not found */
+ return; /* not found */
/* sort */
qsort(matches, num_matches, sizeof(char *), match_compare);
@@ -1073,11 +1078,11 @@
*tmp1 = 0;
break;
}
- if (*tmp == 0) { /* have unique */
+ if (*tmp == 0) { /* have unique */
free(tmp);
return;
}
- } else { /* one match */
+ } else { /* one match */
tmp = matches[0];
/* for next completion current found */
*lastWasTab = FALSE;
@@ -1111,7 +1116,7 @@
* just hit TAB again, print a list of all the
* available choices... */
if (matches && num_matches > 0) {
- int sav_cursor = cursor; /* change goto_new_line() */
+ int sav_cursor = cursor; /* change goto_new_line() */
/* Go to the next line */
goto_new_line();
@@ -1120,7 +1125,7 @@
}
}
}
-#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */
+#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */
#if MAX_HISTORY >= 1
static void get_previous_history(void)
@@ -1159,7 +1164,7 @@
}
if (( fp = fopen ( fromfile, "r" ))) {
-
+
for ( hi = 0; hi < MAX_HISTORY; ) {
char * hl = bb_get_chomped_line_from_file(fp);
int l;
@@ -1183,10 +1188,10 @@
extern void save_history ( const char *tofile )
{
FILE *fp = fopen ( tofile, "w" );
-
+
if ( fp ) {
int i;
-
+
for ( i = 0; i < n_history; i++ ) {
fputs ( history [i], fp );
fputc ( '\n', fp );
@@ -1220,7 +1225,7 @@
* Furthermore, the "vi" command editing keys are not implemented.
*
*/
-
+
int cmdedit_read_input(char *prompt, char command[BUFSIZ])
{
@@ -1230,7 +1235,7 @@
unsigned char c = 0;
/* prepare before init handlers */
- cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */
+ cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */
len = 0;
command_ps = command;
@@ -1247,7 +1252,7 @@
# ifndef _POSIX_VDISABLE
# define _POSIX_VDISABLE '\0'
# endif
- new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
+ new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
#endif
command[0] = 0;
@@ -1261,7 +1266,7 @@
while (1) {
- fflush(stdout); /* buffered out to fast */
+ fflush(stdout); /* buffered out to fast */
if (safe_read(0, &c, 1) < 1)
/* if we can't read input then exit */
@@ -1287,8 +1292,12 @@
goto_new_line();
command[0] = 0;
len = 0;
+#if !defined(CONFIG_ASH)
lastWasTab = FALSE;
put_prompt();
+#else
+ break_out = 2;
+#endif
break;
case 4:
/* Control-d -- Delete one character, or exit
@@ -1327,14 +1336,14 @@
#endif
break;
case 11:
- /* Control-k -- clear to end of line */
+ /* Control-k -- clear to end of line */
*(command + cursor) = 0;
len = cursor;
printf("\033[J");
break;
- case 12:
+ case 12:
/* Control-l -- clear screen */
- printf("\033[H");
+ printf("\033[H");
redraw(0, len-cursor);
break;
#if MAX_HISTORY >= 1
@@ -1371,7 +1380,7 @@
}
switch (c) {
#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
- case '\t': /* Alt-Tab */
+ case '\t': /* Alt-Tab */
input_tab(&lastWasTab);
break;
@@ -1433,7 +1442,7 @@
break;
}
- default: /* If it's regular input, do the normal thing */
+ default: /* If it's regular input, do the normal thing */
#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
/* Control-V -- Add non-printable symbol */
if (c == 22) {
@@ -1445,19 +1454,19 @@
}
} else
#endif
- if (!Isprint(c)) /* Skip non-printable characters */
+ if (!Isprint(c)) /* Skip non-printable characters */
break;
- if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */
+ if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */
break;
len++;
- if (cursor == (len - 1)) { /* Append if at the end of the line */
+ if (cursor == (len - 1)) { /* Append if at the end of the line */
*(command + cursor) = c;
*(command + cursor + 1) = 0;
cmdedit_set_out_char(0);
- } else { /* Insert otherwise */
+ } else { /* Insert otherwise */
int sc = cursor;
memmove(command + sc + 1, command + sc, len - sc);
@@ -1471,7 +1480,7 @@
break;
}
- if (break_out) /* Enter is the command terminator, no more input. */
+ if (break_out) /* Enter is the command terminator, no more input. */
break;
if (c != '\t')
@@ -1486,7 +1495,7 @@
/* cleanup may be saved current command line */
free(history[MAX_HISTORY]);
history[MAX_HISTORY] = 0;
- if (len) { /* no put empty line */
+ if (len) { /* no put empty line */
int i = n_history;
/* After max history, remove the oldest command */
if (i >= MAX_HISTORY) {
@@ -1508,23 +1517,27 @@
}
#endif
#endif /* MAX_HISTORY >= 1 */
- if(break_out>0) {
- command[len++] = '\n'; /* set '\n' */
- command[len] = 0;
+ if(break_out == 1) {
+ command[len++] = '\n'; /* set '\n' */
+ command[len] = 0;
}
#if defined(CONFIG_FEATURE_CLEAN_UP) && defined(CONFIG_FEATURE_COMMAND_TAB_COMPLETION)
- input_tab(0); /* strong free */
+ input_tab(0); /* strong free */
#endif
#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
free(cmdedit_prompt);
#endif
cmdedit_reset_term();
+#if !defined(CONFIG_ASH)
return len;
+#else
+ return break_out < 0 ? break_out : len;
+#endif
}
-#endif /* CONFIG_FEATURE_COMMAND_EDITING */
+#endif /* CONFIG_FEATURE_COMMAND_EDITING */
#ifdef TEST
@@ -1565,4 +1578,4 @@
return 0;
}
-#endif /* TEST */
+#endif /* TEST */