aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbb/process_escape_sequence.c8
-rw-r--r--shell/ash.c118
2 files changed, 62 insertions, 64 deletions
diff --git a/libbb/process_escape_sequence.c b/libbb/process_escape_sequence.c
index 6de2cacdd..11059d1a5 100644
--- a/libbb/process_escape_sequence.c
+++ b/libbb/process_escape_sequence.c
@@ -45,6 +45,9 @@ char FAST_FUNC bb_process_escape_sequence(const char **ptr)
45 } 45 }
46#endif 46#endif
47 47
48 /* bash requires leading 0 in octal escapes:
49 * \02 works, \2 does not (prints \ and 2).
50 * We treat \2 as a valid octal escape sequence. */
48 do { 51 do {
49 d = (unsigned char)(*q) - '0'; 52 d = (unsigned char)(*q) - '0';
50#ifdef WANT_HEX_ESCAPES 53#ifdef WANT_HEX_ESCAPES
@@ -80,7 +83,10 @@ char FAST_FUNC bb_process_escape_sequence(const char **ptr)
80 break; 83 break;
81 } 84 }
82 } while (*++p); 85 } while (*++p);
83 n = *(p + (sizeof(charmap)/2)); 86 /* p points to found escape char or NUL,
87 * advance it and find what it translates to */
88 p += sizeof(charmap) / 2;
89 n = *p;
84 } 90 }
85 91
86 *ptr = q; 92 *ptr = q;
diff --git a/shell/ash.c b/shell/ash.c
index 1690c469b..524910950 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -112,7 +112,7 @@ enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
112 112
113static const char homestr[] ALIGN1 = "HOME"; 113static const char homestr[] ALIGN1 = "HOME";
114static const char snlfmt[] ALIGN1 = "%s\n"; 114static const char snlfmt[] ALIGN1 = "%s\n";
115static const char illnum[] ALIGN1 = "Illegal number: %s"; 115static const char msg_illnum[] ALIGN1 = "Illegal number: %s";
116 116
117/* 117/*
118 * We enclose jmp_buf in a structure so that we can declare pointers to 118 * We enclose jmp_buf in a structure so that we can declare pointers to
@@ -142,17 +142,10 @@ struct globals_misc {
142 142
143 struct jmploc *exception_handler; 143 struct jmploc *exception_handler;
144 144
145// disabled by vda: cannot understand how it was supposed to work - 145 volatile int suppress_int; /* counter */
146// cannot fix bugs. That's why you have to explain your non-trivial designs! 146 volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
147// /* do we generate EXSIG events */
148// int exsig; /* counter */
149 volatile int suppressint; /* counter */
150// TODO: rename
151// pendingsig -> pending_sig
152// intpending -> pending_int
153 volatile /*sig_atomic_t*/ smallint intpending; /* 1 = got SIGINT */
154 /* last pending signal */ 147 /* last pending signal */
155 volatile /*sig_atomic_t*/ smallint pendingsig; 148 volatile /*sig_atomic_t*/ smallint pending_sig;
156 smallint exception_type; /* kind of exception (0..5) */ 149 smallint exception_type; /* kind of exception (0..5) */
157 /* exceptions */ 150 /* exceptions */
158#define EXINT 0 /* SIGINT received */ 151#define EXINT 0 /* SIGINT received */
@@ -220,10 +213,9 @@ extern struct globals_misc *const ash_ptr_to_globals_misc;
220#define arg0 (G_misc.arg0 ) 213#define arg0 (G_misc.arg0 )
221#define exception_handler (G_misc.exception_handler) 214#define exception_handler (G_misc.exception_handler)
222#define exception_type (G_misc.exception_type ) 215#define exception_type (G_misc.exception_type )
223#define suppressint (G_misc.suppressint ) 216#define suppress_int (G_misc.suppress_int )
224#define intpending (G_misc.intpending ) 217#define pending_int (G_misc.pending_int )
225//#define exsig (G_misc.exsig ) 218#define pending_sig (G_misc.pending_sig )
226#define pendingsig (G_misc.pendingsig )
227#define isloginsh (G_misc.isloginsh ) 219#define isloginsh (G_misc.isloginsh )
228#define nullstr (G_misc.nullstr ) 220#define nullstr (G_misc.nullstr )
229#define optlist (G_misc.optlist ) 221#define optlist (G_misc.optlist )
@@ -283,7 +275,7 @@ static int isdigit_str9(const char *str)
283 * more fun than worrying about efficiency and portability. :-)) 275 * more fun than worrying about efficiency and portability. :-))
284 */ 276 */
285#define INT_OFF do { \ 277#define INT_OFF do { \
286 suppressint++; \ 278 suppress_int++; \
287 xbarrier(); \ 279 xbarrier(); \
288} while (0) 280} while (0)
289 281
@@ -324,11 +316,11 @@ raise_interrupt(void)
324{ 316{
325 int ex_type; 317 int ex_type;
326 318
327 intpending = 0; 319 pending_int = 0;
328 /* Signal is not automatically unmasked after it is raised, 320 /* Signal is not automatically unmasked after it is raised,
329 * do it ourself - unmask all signals */ 321 * do it ourself - unmask all signals */
330 sigprocmask_allsigs(SIG_UNBLOCK); 322 sigprocmask_allsigs(SIG_UNBLOCK);
331 /* pendingsig = 0; - now done in onsig() */ 323 /* pending_sig = 0; - now done in onsig() */
332 324
333 ex_type = EXSIG; 325 ex_type = EXSIG;
334 if (gotsig[SIGINT - 1] && !trap[SIGINT]) { 326 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
@@ -353,7 +345,7 @@ static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
353int_on(void) 345int_on(void)
354{ 346{
355 xbarrier(); 347 xbarrier();
356 if (--suppressint == 0 && intpending) { 348 if (--suppress_int == 0 && pending_int) {
357 raise_interrupt(); 349 raise_interrupt();
358 } 350 }
359} 351}
@@ -362,18 +354,18 @@ static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
362force_int_on(void) 354force_int_on(void)
363{ 355{
364 xbarrier(); 356 xbarrier();
365 suppressint = 0; 357 suppress_int = 0;
366 if (intpending) 358 if (pending_int)
367 raise_interrupt(); 359 raise_interrupt();
368} 360}
369#define FORCE_INT_ON force_int_on() 361#define FORCE_INT_ON force_int_on()
370 362
371#define SAVE_INT(v) ((v) = suppressint) 363#define SAVE_INT(v) ((v) = suppress_int)
372 364
373#define RESTORE_INT(v) do { \ 365#define RESTORE_INT(v) do { \
374 xbarrier(); \ 366 xbarrier(); \
375 suppressint = (v); \ 367 suppress_int = (v); \
376 if (suppressint == 0 && intpending) \ 368 if (suppress_int == 0 && pending_int) \
377 raise_interrupt(); \ 369 raise_interrupt(); \
378} while (0) 370} while (0)
379 371
@@ -685,7 +677,7 @@ trace_printf(const char *fmt, ...)
685 if (DEBUG_PID) 677 if (DEBUG_PID)
686 fprintf(tracefile, "[%u] ", (int) getpid()); 678 fprintf(tracefile, "[%u] ", (int) getpid());
687 if (DEBUG_SIG) 679 if (DEBUG_SIG)
688 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint); 680 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
689 va_start(va, fmt); 681 va_start(va, fmt);
690 vfprintf(tracefile, fmt, va); 682 vfprintf(tracefile, fmt, va);
691 va_end(va); 683 va_end(va);
@@ -701,7 +693,7 @@ trace_vprintf(const char *fmt, va_list va)
701 if (DEBUG_PID) 693 if (DEBUG_PID)
702 fprintf(tracefile, "[%u] ", (int) getpid()); 694 fprintf(tracefile, "[%u] ", (int) getpid());
703 if (DEBUG_SIG) 695 if (DEBUG_SIG)
704 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint); 696 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
705 vfprintf(tracefile, fmt, va); 697 vfprintf(tracefile, fmt, va);
706} 698}
707 699
@@ -1556,7 +1548,7 @@ static int
1556number(const char *s) 1548number(const char *s)
1557{ 1549{
1558 if (!is_number(s)) 1550 if (!is_number(s))
1559 ash_msg_and_raise_error(illnum, s); 1551 ash_msg_and_raise_error(msg_illnum, s);
1560 return atoi(s); 1552 return atoi(s);
1561} 1553}
1562 1554
@@ -2351,8 +2343,6 @@ setprompt(int whichprompt)
2351#define CD_PHYSICAL 1 2343#define CD_PHYSICAL 1
2352#define CD_PRINT 2 2344#define CD_PRINT 2
2353 2345
2354static int docd(const char *, int);
2355
2356static int 2346static int
2357cdopt(void) 2347cdopt(void)
2358{ 2348{
@@ -2360,7 +2350,7 @@ cdopt(void)
2360 int i, j; 2350 int i, j;
2361 2351
2362 j = 'L'; 2352 j = 'L';
2363 while ((i = nextopt("LP"))) { 2353 while ((i = nextopt("LP")) != '\0') {
2364 if (i != j) { 2354 if (i != j) {
2365 flags ^= CD_PHYSICAL; 2355 flags ^= CD_PHYSICAL;
2366 j = i; 2356 j = i;
@@ -3315,14 +3305,14 @@ onsig(int signo)
3315{ 3305{
3316 gotsig[signo - 1] = 1; 3306 gotsig[signo - 1] = 1;
3317 3307
3318 if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) { 3308 if (signo == SIGINT && !trap[SIGINT]) {
3319 if (!suppressint) { 3309 if (!suppress_int) {
3320 pendingsig = 0; 3310 pending_sig = 0;
3321 raise_interrupt(); /* does not return */ 3311 raise_interrupt(); /* does not return */
3322 } 3312 }
3323 intpending = 1; 3313 pending_int = 1;
3324 } else { 3314 } else {
3325 pendingsig = signo; 3315 pending_sig = signo;
3326 } 3316 }
3327} 3317}
3328 3318
@@ -3545,7 +3535,6 @@ getjob(const char *name, int getctl)
3545 } 3535 }
3546 3536
3547 if (is_number(p)) { 3537 if (is_number(p)) {
3548// TODO: number() instead? It does error checking...
3549 num = atoi(p); 3538 num = atoi(p);
3550 if (num < njobs) { 3539 if (num < njobs) {
3551 jp = jobtab + num - 1; 3540 jp = jobtab + num - 1;
@@ -3917,7 +3906,7 @@ static int
3917blocking_wait_with_raise_on_sig(struct job *job) 3906blocking_wait_with_raise_on_sig(struct job *job)
3918{ 3907{
3919 pid_t pid = dowait(DOWAIT_BLOCK, job); 3908 pid_t pid = dowait(DOWAIT_BLOCK, job);
3920 if (pid <= 0 && pendingsig) 3909 if (pid <= 0 && pending_sig)
3921 raise_exception(EXSIG); 3910 raise_exception(EXSIG);
3922 return pid; 3911 return pid;
3923} 3912}
@@ -4025,7 +4014,7 @@ jobscmd(int argc UNUSED_PARAM, char **argv)
4025 int mode, m; 4014 int mode, m;
4026 4015
4027 mode = 0; 4016 mode = 0;
4028 while ((m = nextopt("lp"))) { 4017 while ((m = nextopt("lp")) != '\0') {
4029 if (m == 'l') 4018 if (m == 'l')
4030 mode |= SHOW_PIDS; 4019 mode |= SHOW_PIDS;
4031 else 4020 else
@@ -4079,9 +4068,7 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4079 int retval; 4068 int retval;
4080 struct job *jp; 4069 struct job *jp;
4081 4070
4082// exsig++; 4071 if (pending_sig)
4083// xbarrier();
4084 if (pendingsig)
4085 raise_exception(EXSIG); 4072 raise_exception(EXSIG);
4086 4073
4087 nextopt(nullstr); 4074 nextopt(nullstr);
@@ -4317,7 +4304,7 @@ cmdputs(const char *s)
4317 if (!str) 4304 if (!str)
4318 continue; 4305 continue;
4319 dostr: 4306 dostr:
4320 while ((c = *str++)) { 4307 while ((c = *str++) != '\0') {
4321 USTPUTC(c, nextc); 4308 USTPUTC(c, nextc);
4322 } 4309 }
4323 } 4310 }
@@ -6126,15 +6113,15 @@ subevalvar(char *p, char *str, int strloc, int subtype,
6126#if ENABLE_ASH_BASH_COMPAT 6113#if ENABLE_ASH_BASH_COMPAT
6127 case VSSUBSTR: 6114 case VSSUBSTR:
6128 loc = str = stackblock() + strloc; 6115 loc = str = stackblock() + strloc;
6129// TODO: number() instead? It does error checking... 6116 /* Read POS in ${var:POS:LEN} */
6130 pos = atoi(loc); 6117 pos = atoi(loc); /* number(loc) errors out on "1:4" */
6131 len = str - startp - 1; 6118 len = str - startp - 1;
6132 6119
6133 /* *loc != '\0', guaranteed by parser */ 6120 /* *loc != '\0', guaranteed by parser */
6134 if (quotes) { 6121 if (quotes) {
6135 char *ptr; 6122 char *ptr;
6136 6123
6137 /* We must adjust the length by the number of escapes we find. */ 6124 /* Adjust the length by the number of escapes */
6138 for (ptr = startp; ptr < (str - 1); ptr++) { 6125 for (ptr = startp; ptr < (str - 1); ptr++) {
6139 if (*ptr == CTLESC) { 6126 if (*ptr == CTLESC) {
6140 len--; 6127 len--;
@@ -6145,15 +6132,22 @@ subevalvar(char *p, char *str, int strloc, int subtype,
6145 orig_len = len; 6132 orig_len = len;
6146 6133
6147 if (*loc++ == ':') { 6134 if (*loc++ == ':') {
6148// TODO: number() instead? It does error checking... 6135 /* ${var::LEN} */
6149 len = atoi(loc); 6136 len = number(loc);
6150 } else { 6137 } else {
6138 /* Skip POS in ${var:POS:LEN} */
6151 len = orig_len; 6139 len = orig_len;
6152 while (*loc && *loc != ':') 6140 while (*loc && *loc != ':') {
6141 /* TODO?
6142 * bash complains on: var=qwe; echo ${var:1a:123}
6143 if (!isdigit(*loc))
6144 ash_msg_and_raise_error(msg_illnum, str);
6145 */
6153 loc++; 6146 loc++;
6154 if (*loc++ == ':') 6147 }
6155// TODO: number() instead? It does error checking... 6148 if (*loc++ == ':') {
6156 len = atoi(loc); 6149 len = number(loc);
6150 }
6157 } 6151 }
6158 if (pos >= orig_len) { 6152 if (pos >= orig_len) {
6159 pos = 0; 6153 pos = 0;
@@ -6372,7 +6366,7 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6372 ap = shellparam.p; 6366 ap = shellparam.p;
6373 if (!ap) 6367 if (!ap)
6374 return -1; 6368 return -1;
6375 while ((p = *ap++)) { 6369 while ((p = *ap++) != NULL) {
6376 size_t partlen; 6370 size_t partlen;
6377 6371
6378 partlen = strlen(p); 6372 partlen = strlen(p);
@@ -6406,8 +6400,7 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6406 case '7': 6400 case '7':
6407 case '8': 6401 case '8':
6408 case '9': 6402 case '9':
6409// TODO: number() instead? It does error checking... 6403 num = number(name);
6410 num = atoi(name);
6411 if (num < 0 || num > shellparam.nparam) 6404 if (num < 0 || num > shellparam.nparam)
6412 return -1; 6405 return -1;
6413 p = num ? shellparam.p[num - 1] : arg0; 6406 p = num ? shellparam.p[num - 1] : arg0;
@@ -6819,7 +6812,7 @@ expmeta(char *enddir, char *name)
6819 p++; 6812 p++;
6820 if (*p == '.') 6813 if (*p == '.')
6821 matchdot++; 6814 matchdot++;
6822 while (!intpending && (dp = readdir(dirp)) != NULL) { 6815 while (!pending_int && (dp = readdir(dirp)) != NULL) {
6823 if (dp->d_name[0] == '.' && !matchdot) 6816 if (dp->d_name[0] == '.' && !matchdot)
6824 continue; 6817 continue;
6825 if (pmatch(start, dp->d_name)) { 6818 if (pmatch(start, dp->d_name)) {
@@ -7213,8 +7206,8 @@ shellexec(char **argv, const char *path, int idx)
7213 break; 7206 break;
7214 } 7207 }
7215 exitstatus = exerrno; 7208 exitstatus = exerrno;
7216 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n", 7209 TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7217 argv[0], e, suppressint)); 7210 argv[0], e, suppress_int));
7218 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found")); 7211 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
7219 /* NOTREACHED */ 7212 /* NOTREACHED */
7220} 7213}
@@ -8016,7 +8009,7 @@ dotrap(void)
8016 uint8_t savestatus; 8009 uint8_t savestatus;
8017 8010
8018 savestatus = exitstatus; 8011 savestatus = exitstatus;
8019 pendingsig = 0; 8012 pending_sig = 0;
8020 xbarrier(); 8013 xbarrier();
8021 8014
8022 TRACE(("dotrap entered\n")); 8015 TRACE(("dotrap entered\n"));
@@ -8196,7 +8189,7 @@ evaltree(union node *n, int flags)
8196 out1: 8189 out1:
8197 if (checkexit & exitstatus) 8190 if (checkexit & exitstatus)
8198 evalskip |= SKIPEVAL; 8191 evalskip |= SKIPEVAL;
8199 else if (pendingsig && dotrap()) 8192 else if (pending_sig && dotrap())
8200 goto exexit; 8193 goto exexit;
8201 8194
8202 if (flags & EV_EXIT) { 8195 if (flags & EV_EXIT) {
@@ -9116,7 +9109,7 @@ evalcommand(union node *cmd, int flags)
9116 if (i == EXINT) 9109 if (i == EXINT)
9117 exit_status = 128 + SIGINT; 9110 exit_status = 128 + SIGINT;
9118 if (i == EXSIG) 9111 if (i == EXSIG)
9119 exit_status = 128 + pendingsig; 9112 exit_status = 128 + pending_sig;
9120 exitstatus = exit_status; 9113 exitstatus = exit_status;
9121 if (i == EXINT || spclbltin > 0) { 9114 if (i == EXINT || spclbltin > 0) {
9122 raise: 9115 raise:
@@ -9170,7 +9163,6 @@ evalbltin(const struct builtincmd *cmd, int argc, char **argv)
9170 exitstatus |= ferror(stdout); 9163 exitstatus |= ferror(stdout);
9171 clearerr(stdout); 9164 clearerr(stdout);
9172 commandname = savecmdname; 9165 commandname = savecmdname;
9173// exsig = 0;
9174 exception_handler = savehandler; 9166 exception_handler = savehandler;
9175 9167
9176 return i; 9168 return i;
@@ -9221,7 +9213,7 @@ breakcmd(int argc UNUSED_PARAM, char **argv)
9221 int n = argv[1] ? number(argv[1]) : 1; 9213 int n = argv[1] ? number(argv[1]) : 1;
9222 9214
9223 if (n <= 0) 9215 if (n <= 0)
9224 ash_msg_and_raise_error(illnum, argv[1]); 9216 ash_msg_and_raise_error(msg_illnum, argv[1]);
9225 if (n > loopnest) 9217 if (n > loopnest)
9226 n = loopnest; 9218 n = loopnest;
9227 if (n > 0) { 9219 if (n > 0) {
@@ -12712,7 +12704,7 @@ umaskcmd(int argc UNUSED_PARAM, char **argv)
12712 mask = 0; 12704 mask = 0;
12713 do { 12705 do {
12714 if (*ap >= '8' || *ap < '0') 12706 if (*ap >= '8' || *ap < '0')
12715 ash_msg_and_raise_error(illnum, argv[1]); 12707 ash_msg_and_raise_error(msg_illnum, argv[1]);
12716 mask = (mask << 3) + (*ap - '0'); 12708 mask = (mask << 3) + (*ap - '0');
12717 } while (*++ap != '\0'); 12709 } while (*++ap != '\0');
12718 umask(mask); 12710 umask(mask);