diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-08-02 05:02:46 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-08-02 05:02:46 +0000 |
commit | 34506361697643277042fc8d7294bc17a27d4e28 (patch) | |
tree | bf2c45a12020be4e0a37547abb50c40c0074e8ec /shell | |
parent | 2d91deba45d5a284614e06cc55e2be03599ca26d (diff) | |
download | busybox-w32-34506361697643277042fc8d7294bc17a27d4e28.tar.gz busybox-w32-34506361697643277042fc8d7294bc17a27d4e28.tar.bz2 busybox-w32-34506361697643277042fc8d7294bc17a27d4e28.zip |
Latest patch from vodz. Adds a check for divide by zero in the posix
math suport, cleaner math syntax error checking, moves redundant signal
string tables (from kill and ash) into libbb and provides a few
cleanups elsewhere.
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 171 | ||||
-rw-r--r-- | shell/cmdedit.c | 24 |
2 files changed, 55 insertions, 140 deletions
diff --git a/shell/ash.c b/shell/ash.c index b1aec6278..bcd12f106 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -52,6 +52,7 @@ | |||
52 | 52 | ||
53 | /* If you need ash to act as a full Posix shell, with full math | 53 | /* If you need ash to act as a full Posix shell, with full math |
54 | * support, enable this. This adds a bit over 2k an x86 system. */ | 54 | * support, enable this. This adds a bit over 2k an x86 system. */ |
55 | //#undef ASH_MATH_SUPPORT | ||
55 | #define ASH_MATH_SUPPORT | 56 | #define ASH_MATH_SUPPORT |
56 | 57 | ||
57 | /* Getopts is used by shell procedures to parse positional parameters. | 58 | /* Getopts is used by shell procedures to parse positional parameters. |
@@ -78,8 +79,6 @@ | |||
78 | /* These are here to work with glibc -- Don't change these... */ | 79 | /* These are here to work with glibc -- Don't change these... */ |
79 | #undef FNMATCH_BROKEN | 80 | #undef FNMATCH_BROKEN |
80 | #undef GLOB_BROKEN | 81 | #undef GLOB_BROKEN |
81 | #undef _GNU_SOURCE | ||
82 | #undef __USE_GNU | ||
83 | 82 | ||
84 | #include <assert.h> | 83 | #include <assert.h> |
85 | #include <ctype.h> | 84 | #include <ctype.h> |
@@ -4839,6 +4838,7 @@ static void | |||
4839 | expari(int flag) | 4838 | expari(int flag) |
4840 | { | 4839 | { |
4841 | char *p, *start; | 4840 | char *p, *start; |
4841 | int errcode; | ||
4842 | int result; | 4842 | int result; |
4843 | int begoff; | 4843 | int begoff; |
4844 | int quotes = flag & (EXP_FULL | EXP_CASE); | 4844 | int quotes = flag & (EXP_FULL | EXP_CASE); |
@@ -4877,9 +4877,13 @@ expari(int flag) | |||
4877 | removerecordregions(begoff); | 4877 | removerecordregions(begoff); |
4878 | if (quotes) | 4878 | if (quotes) |
4879 | rmescapes(p+2); | 4879 | rmescapes(p+2); |
4880 | result = arith(p+2); | 4880 | result = arith(p+2, &errcode); |
4881 | if (result < 0) | 4881 | if (errcode < 0) { |
4882 | error("arith: syntax error: \"%s\"\n", p+2); | 4882 | if(errcode == -2) |
4883 | error("divide by zero"); | ||
4884 | else | ||
4885 | error("syntax error: \"%s\"\n", p+2); | ||
4886 | } | ||
4883 | snprintf(p, 12, "%d", result); | 4887 | snprintf(p, 12, "%d", result); |
4884 | 4888 | ||
4885 | while (*p++) | 4889 | while (*p++) |
@@ -5429,9 +5433,9 @@ expandmeta(str, flag) | |||
5429 | goto nometa; | 5433 | goto nometa; |
5430 | p = preglob(str->text); | 5434 | p = preglob(str->text); |
5431 | INTOFF; | 5435 | INTOFF; |
5432 | switch (glob(p, GLOB_NOMAGIC, 0, &pglob)) { | 5436 | switch (glob(p, 0, 0, &pglob)) { |
5433 | case 0: | 5437 | case 0: |
5434 | if (!(pglob.gl_flags & GLOB_MAGCHAR)) | 5438 | if(pglob.gl_pathv[1]==0 && !strcmp(p, pglob.gl_pathv[0])) |
5435 | goto nometa2; | 5439 | goto nometa2; |
5436 | addglob(&pglob); | 5440 | addglob(&pglob); |
5437 | globfree(&pglob); | 5441 | globfree(&pglob); |
@@ -6006,7 +6010,7 @@ static int histcmd(argc, argv) | |||
6006 | struct redirtab { | 6010 | struct redirtab { |
6007 | struct redirtab *next; | 6011 | struct redirtab *next; |
6008 | short renamed[10]; /* Current ash support only 0-9 descriptors */ | 6012 | short renamed[10]; /* Current ash support only 0-9 descriptors */ |
6009 | /* char renamed[10]; */ /* char on arm (and others) can't be negative */ | 6013 | /* char on arm (and others) can't be negative */ |
6010 | }; | 6014 | }; |
6011 | 6015 | ||
6012 | static struct redirtab *redirlist; | 6016 | static struct redirtab *redirlist; |
@@ -6166,7 +6170,7 @@ preadfd(void) | |||
6166 | retry: | 6170 | retry: |
6167 | #ifdef BB_FEATURE_COMMAND_EDITING | 6171 | #ifdef BB_FEATURE_COMMAND_EDITING |
6168 | { | 6172 | { |
6169 | if (parsefile->fd) | 6173 | if (!iflag || parsefile->fd) |
6170 | nr = safe_read(parsefile->fd, buf, BUFSIZ - 1); | 6174 | nr = safe_read(parsefile->fd, buf, BUFSIZ - 1); |
6171 | else { | 6175 | else { |
6172 | nr = cmdedit_read_input((char*)cmdedit_prompt, buf); | 6176 | nr = cmdedit_read_input((char*)cmdedit_prompt, buf); |
@@ -6468,80 +6472,6 @@ static void setjobctl(int enable) | |||
6468 | #endif | 6472 | #endif |
6469 | 6473 | ||
6470 | 6474 | ||
6471 | /* A translation list so we can be polite to our users. */ | ||
6472 | static char *signal_names[NSIG + 2] = { | ||
6473 | "EXIT", | ||
6474 | "SIGHUP", | ||
6475 | "SIGINT", | ||
6476 | "SIGQUIT", | ||
6477 | "SIGILL", | ||
6478 | "SIGTRAP", | ||
6479 | "SIGABRT", | ||
6480 | "SIGBUS", | ||
6481 | "SIGFPE", | ||
6482 | "SIGKILL", | ||
6483 | "SIGUSR1", | ||
6484 | "SIGSEGV", | ||
6485 | "SIGUSR2", | ||
6486 | "SIGPIPE", | ||
6487 | "SIGALRM", | ||
6488 | "SIGTERM", | ||
6489 | "SIGJUNK(16)", | ||
6490 | "SIGCHLD", | ||
6491 | "SIGCONT", | ||
6492 | "SIGSTOP", | ||
6493 | "SIGTSTP", | ||
6494 | "SIGTTIN", | ||
6495 | "SIGTTOU", | ||
6496 | "SIGURG", | ||
6497 | "SIGXCPU", | ||
6498 | "SIGXFSZ", | ||
6499 | "SIGVTALRM", | ||
6500 | "SIGPROF", | ||
6501 | "SIGWINCH", | ||
6502 | "SIGIO", | ||
6503 | "SIGPWR", | ||
6504 | "SIGSYS", | ||
6505 | #ifdef SIGRTMIN | ||
6506 | "SIGRTMIN", | ||
6507 | "SIGRTMIN+1", | ||
6508 | "SIGRTMIN+2", | ||
6509 | "SIGRTMIN+3", | ||
6510 | "SIGRTMIN+4", | ||
6511 | "SIGRTMIN+5", | ||
6512 | "SIGRTMIN+6", | ||
6513 | "SIGRTMIN+7", | ||
6514 | "SIGRTMIN+8", | ||
6515 | "SIGRTMIN+9", | ||
6516 | "SIGRTMIN+10", | ||
6517 | "SIGRTMIN+11", | ||
6518 | "SIGRTMIN+12", | ||
6519 | "SIGRTMIN+13", | ||
6520 | "SIGRTMIN+14", | ||
6521 | "SIGRTMIN+15", | ||
6522 | "SIGRTMAX-15", | ||
6523 | "SIGRTMAX-14", | ||
6524 | "SIGRTMAX-13", | ||
6525 | "SIGRTMAX-12", | ||
6526 | "SIGRTMAX-11", | ||
6527 | "SIGRTMAX-10", | ||
6528 | "SIGRTMAX-9", | ||
6529 | "SIGRTMAX-8", | ||
6530 | "SIGRTMAX-7", | ||
6531 | "SIGRTMAX-6", | ||
6532 | "SIGRTMAX-5", | ||
6533 | "SIGRTMAX-4", | ||
6534 | "SIGRTMAX-3", | ||
6535 | "SIGRTMAX-2", | ||
6536 | "SIGRTMAX-1", | ||
6537 | "SIGRTMAX", | ||
6538 | #endif | ||
6539 | "DEBUG", | ||
6540 | (char *)0x0, | ||
6541 | }; | ||
6542 | |||
6543 | |||
6544 | |||
6545 | #ifdef JOBS | 6475 | #ifdef JOBS |
6546 | static int | 6476 | static int |
6547 | killcmd(argc, argv) | 6477 | killcmd(argc, argv) |
@@ -6599,18 +6529,20 @@ usage: | |||
6599 | } | 6529 | } |
6600 | 6530 | ||
6601 | if (list) { | 6531 | if (list) { |
6532 | const char *name; | ||
6533 | |||
6602 | if (!*argptr) { | 6534 | if (!*argptr) { |
6603 | out1str("0\n"); | 6535 | out1str("0\n"); |
6604 | for (i = 1; i < NSIG; i++) { | 6536 | for (i = 1; i < NSIG; i++) { |
6605 | printf(snlfmt, signal_names[i] + 3); | 6537 | name = u_signal_names(0, &i, 1); |
6538 | if(name) | ||
6539 | printf(snlfmt, name); | ||
6606 | } | 6540 | } |
6607 | return 0; | 6541 | return 0; |
6608 | } | 6542 | } |
6609 | signo = atoi(*argptr); | 6543 | name = u_signal_names(*argptr, &signo, -1); |
6610 | if (signo > 128) | 6544 | if (name) |
6611 | signo -= 128; | 6545 | printf(snlfmt, name); |
6612 | if (0 < signo && signo < NSIG) | ||
6613 | printf(snlfmt, signal_names[signo] + 3); | ||
6614 | else | 6546 | else |
6615 | error("invalid signal number or exit status: %s", | 6547 | error("invalid signal number or exit status: %s", |
6616 | *argptr); | 6548 | *argptr); |
@@ -8834,12 +8766,6 @@ copynodelist(const struct nodelist *lp) | |||
8834 | static char * | 8766 | static char * |
8835 | nodesavestr(const char *s) | 8767 | nodesavestr(const char *s) |
8836 | { | 8768 | { |
8837 | #ifdef _GNU_SOURCE | ||
8838 | char *rtn = funcstring; | ||
8839 | |||
8840 | funcstring = stpcpy(funcstring, s) + 1; | ||
8841 | return rtn; | ||
8842 | #else | ||
8843 | const char *p = s; | 8769 | const char *p = s; |
8844 | char *q = funcstring; | 8770 | char *q = funcstring; |
8845 | char *rtn = funcstring; | 8771 | char *rtn = funcstring; |
@@ -8848,7 +8774,6 @@ nodesavestr(const char *s) | |||
8848 | continue; | 8774 | continue; |
8849 | funcstring = q; | 8775 | funcstring = q; |
8850 | return rtn; | 8776 | return rtn; |
8851 | #endif | ||
8852 | } | 8777 | } |
8853 | 8778 | ||
8854 | #ifdef ASH_GETOPTS | 8779 | #ifdef ASH_GETOPTS |
@@ -12052,11 +11977,15 @@ trapcmd(argc, argv) | |||
12052 | for (signo = 0 ; signo < NSIG ; signo++) { | 11977 | for (signo = 0 ; signo < NSIG ; signo++) { |
12053 | if (trap[signo] != NULL) { | 11978 | if (trap[signo] != NULL) { |
12054 | char *p; | 11979 | char *p; |
11980 | const char *sn; | ||
12055 | 11981 | ||
12056 | p = single_quote(trap[signo]); | 11982 | p = single_quote(trap[signo]); |
12057 | printf("trap -- %s %s\n", p, | 11983 | sn = sys_siglist[signo]; |
12058 | signal_names[signo] + (signo ? 3 : 0) | 11984 | if(sn==NULL) |
12059 | ); | 11985 | sn = u_signal_names(0, &signo, 0); |
11986 | if(sn==NULL) | ||
11987 | sn = "???"; | ||
11988 | printf("trap -- %s %s\n", p, sn); | ||
12060 | stunalloc(p); | 11989 | stunalloc(p); |
12061 | } | 11990 | } |
12062 | } | 11991 | } |
@@ -12273,30 +12202,11 @@ l2: _exit(status); | |||
12273 | static int decode_signal(const char *string, int minsig) | 12202 | static int decode_signal(const char *string, int minsig) |
12274 | { | 12203 | { |
12275 | int signo; | 12204 | int signo; |
12205 | const char *name = u_signal_names(string, &signo, minsig); | ||
12276 | 12206 | ||
12277 | if (is_number(string, &signo)) { | 12207 | return name ? signo : -1; |
12278 | if (signo >= NSIG) { | ||
12279 | return -1; | ||
12280 | } | ||
12281 | return signo; | ||
12282 | } | ||
12283 | |||
12284 | signo = minsig; | ||
12285 | if (!signo) { | ||
12286 | goto zero; | ||
12287 | } | ||
12288 | for (; signo < NSIG; signo++) { | ||
12289 | if (!strcasecmp(string, &(signal_names[signo])[3])) { | ||
12290 | return signo; | ||
12291 | } | ||
12292 | zero: | ||
12293 | if (!strcasecmp(string, signal_names[signo])) { | ||
12294 | return signo; | ||
12295 | } | ||
12296 | } | ||
12297 | |||
12298 | return -1; | ||
12299 | } | 12208 | } |
12209 | |||
12300 | static struct var **hashvar (const char *); | 12210 | static struct var **hashvar (const char *); |
12301 | static void showvars (const char *, int, int); | 12211 | static void showvars (const char *, int, int); |
12302 | static struct var **findvar (struct var **, const char *); | 12212 | static struct var **findvar (struct var **, const char *); |
@@ -12616,6 +12526,7 @@ found:; | |||
12616 | return 0; | 12526 | return 0; |
12617 | } | 12527 | } |
12618 | 12528 | ||
12529 | |||
12619 | /* | 12530 | /* |
12620 | * The "local" command. | 12531 | * The "local" command. |
12621 | */ | 12532 | */ |
@@ -12874,7 +12785,7 @@ findvar(struct var **vpp, const char *name) | |||
12874 | /* | 12785 | /* |
12875 | * Copyright (c) 1999 Herbert Xu <herbert@debian.org> | 12786 | * Copyright (c) 1999 Herbert Xu <herbert@debian.org> |
12876 | * This file contains code for the times builtin. | 12787 | * This file contains code for the times builtin. |
12877 | * $Id: ash.c,v 1.16 2001/08/01 17:21:33 kraai Exp $ | 12788 | * $Id: ash.c,v 1.17 2001/08/02 05:02:45 andersen Exp $ |
12878 | */ | 12789 | */ |
12879 | static int timescmd (int argc, char **argv) | 12790 | static int timescmd (int argc, char **argv) |
12880 | { | 12791 | { |
@@ -12894,24 +12805,32 @@ static int timescmd (int argc, char **argv) | |||
12894 | return 0; | 12805 | return 0; |
12895 | } | 12806 | } |
12896 | 12807 | ||
12897 | |||
12898 | #ifdef ASH_MATH_SUPPORT | 12808 | #ifdef ASH_MATH_SUPPORT |
12899 | /* The let builtin. */ | 12809 | /* The let builtin. */ |
12900 | int letcmd(int argc, char **argv) | 12810 | int letcmd(int argc, char **argv) |
12901 | { | 12811 | { |
12812 | int errcode; | ||
12902 | long result=0; | 12813 | long result=0; |
12903 | if (argc == 2) { | 12814 | if (argc == 2) { |
12904 | char *tmp, *expression, p[13]; | 12815 | char *tmp, *expression, p[13]; |
12905 | expression = strchr(argv[1], '='); | 12816 | expression = strchr(argv[1], '='); |
12906 | if (!expression) { | 12817 | if (!expression) { |
12818 | /* Cannot use 'error()' here, or the return code | ||
12819 | * will be incorrect */ | ||
12907 | out2fmt("sh: let: syntax error: \"%s\"\n", argv[1]); | 12820 | out2fmt("sh: let: syntax error: \"%s\"\n", argv[1]); |
12908 | return 0; | 12821 | return 0; |
12909 | } | 12822 | } |
12910 | *expression = '\0'; | 12823 | *expression = '\0'; |
12911 | tmp = ++expression; | 12824 | tmp = ++expression; |
12912 | result = arith(tmp); | 12825 | result = arith(tmp, &errcode); |
12913 | if (result < 0) { | 12826 | if (errcode < 0) { |
12914 | out2fmt("sh: let: syntax error: \"%s=%s\"\n", argv[1], expression); | 12827 | /* Cannot use 'error()' here, or the return code |
12828 | * will be incorrect */ | ||
12829 | out2fmt("sh: let: "); | ||
12830 | if(errcode == -2) | ||
12831 | out2fmt("divide by zero"); | ||
12832 | else | ||
12833 | out2fmt("syntax error: \"%s=%s\"\n", argv[1], expression); | ||
12915 | return 0; | 12834 | return 0; |
12916 | } | 12835 | } |
12917 | snprintf(p, 12, "%ld", result); | 12836 | snprintf(p, 12, "%ld", result); |
diff --git a/shell/cmdedit.c b/shell/cmdedit.c index 3b4750455..2ec81548d 100644 --- a/shell/cmdedit.c +++ b/shell/cmdedit.c | |||
@@ -1167,25 +1167,21 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
1167 | len = 0; | 1167 | len = 0; |
1168 | command_ps = command; | 1168 | command_ps = command; |
1169 | 1169 | ||
1170 | if (new_settings.c_cc[VERASE] == 0) { /* first call */ | 1170 | getTermSettings(0, (void *) &initial_settings); |
1171 | 1171 | memcpy(&new_settings, &initial_settings, sizeof(struct termios)); | |
1172 | getTermSettings(0, (void *) &initial_settings); | 1172 | new_settings.c_lflag &= ~ICANON; /* unbuffered input */ |
1173 | memcpy(&new_settings, &initial_settings, sizeof(struct termios)); | 1173 | /* Turn off echoing and CTRL-C, so we can trap it */ |
1174 | new_settings.c_lflag &= ~ICANON; /* unbuffered input */ | 1174 | new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG); |
1175 | /* Turn off echoing and CTRL-C, so we can trap it */ | ||
1176 | new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG); | ||
1177 | #ifndef linux | 1175 | #ifndef linux |
1178 | /* Hmm, in linux c_cc[] not parsed if set ~ICANON */ | 1176 | /* Hmm, in linux c_cc[] not parsed if set ~ICANON */ |
1179 | new_settings.c_cc[VMIN] = 1; | 1177 | new_settings.c_cc[VMIN] = 1; |
1180 | new_settings.c_cc[VTIME] = 0; | 1178 | new_settings.c_cc[VTIME] = 0; |
1181 | /* Turn off CTRL-C, so we can trap it */ | 1179 | /* Turn off CTRL-C, so we can trap it */ |
1182 | # ifndef _POSIX_VDISABLE | 1180 | # ifndef _POSIX_VDISABLE |
1183 | # define _POSIX_VDISABLE '\0' | 1181 | # define _POSIX_VDISABLE '\0' |
1184 | # endif | 1182 | # endif |
1185 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; | 1183 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; |
1186 | #endif | 1184 | #endif |
1187 | } | ||
1188 | |||
1189 | command[0] = 0; | 1185 | command[0] = 0; |
1190 | 1186 | ||
1191 | setTermSettings(0, (void *) &new_settings); | 1187 | setTermSettings(0, (void *) &new_settings); |