aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-18 12:58:19 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-18 12:58:19 +0000
commit38e626df4ddac2426afb336d2e1794913c022c15 (patch)
treecac5eaf01d2219d515c93bd4e9e4eacd83f2e396 /shell
parent6a07d1fb5c89c7710d91b74b21fe26eafa1f7a72 (diff)
downloadbusybox-w32-38e626df4ddac2426afb336d2e1794913c022c15.tar.gz
busybox-w32-38e626df4ddac2426afb336d2e1794913c022c15.tar.bz2
busybox-w32-38e626df4ddac2426afb336d2e1794913c022c15.zip
hush: fix "trap -- handler SIGs..."; escape handlers in "trap" output
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c210
1 files changed, 117 insertions, 93 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 0f93ae62b..6e181ce99 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -3246,14 +3246,16 @@ static int checkjobs(struct pipe* fg_pipe)
3246 fg_pipe->alive_cmds--; 3246 fg_pipe->alive_cmds--;
3247 if (i == fg_pipe->num_cmds - 1) { 3247 if (i == fg_pipe->num_cmds - 1) {
3248 /* last process gives overall exitstatus */ 3248 /* last process gives overall exitstatus */
3249 /* Note: is WIFSIGNALED, WEXITSTATUS = sig + 128 */
3249 rcode = WEXITSTATUS(status); 3250 rcode = WEXITSTATUS(status);
3250 IF_HAS_KEYWORDS(if (fg_pipe->pi_inverted) rcode = !rcode;) 3251 IF_HAS_KEYWORDS(if (fg_pipe->pi_inverted) rcode = !rcode;)
3251 /* bash prints killing signal's name for *last* 3252 /* bash prints killing signal's name for *last*
3252 * process in pipe (prints just newline for SIGINT). 3253 * process in pipe (prints just newline for SIGINT).
3253 * we just print newline for any sig: 3254 * Mimic this. Example: "sleep 5" + ^\
3254 */ 3255 */
3255 if (WIFSIGNALED(status)) { 3256 if (WIFSIGNALED(status)) {
3256 bb_putchar('\n'); 3257 int sig = WTERMSIG(status);
3258 printf("%s\n", sig == SIGINT ? "" : get_signame(sig));
3257 } 3259 }
3258 } 3260 }
3259 } else { 3261 } else {
@@ -3489,6 +3491,7 @@ static int run_pipe(struct pipe *pi)
3489 debug_printf_exec(": builtin '%s' '%s'...\n", 3491 debug_printf_exec(": builtin '%s' '%s'...\n",
3490 x->cmd, argv_expanded[1]); 3492 x->cmd, argv_expanded[1]);
3491 rcode = x->function(argv_expanded) & 0xff; 3493 rcode = x->function(argv_expanded) & 0xff;
3494 fflush(NULL);
3492 } 3495 }
3493#if ENABLE_HUSH_FUNCTIONS 3496#if ENABLE_HUSH_FUNCTIONS
3494 else { 3497 else {
@@ -6251,81 +6254,6 @@ int lash_main(int argc, char **argv)
6251/* 6254/*
6252 * Built-ins 6255 * Built-ins
6253 */ 6256 */
6254static int builtin_trap(char **argv)
6255{
6256 int i;
6257 int sig;
6258 char *new_cmd;
6259
6260 if (!G.traps)
6261 G.traps = xzalloc(sizeof(G.traps[0]) * NSIG);
6262
6263 argv++;
6264 if (!*argv) {
6265 /* No args: print all trapped. This isn't 100% correct as we
6266 * should be escaping the cmd so that it can be pasted back in
6267 */
6268 for (i = 0; i < NSIG; ++i)
6269 if (G.traps[i])
6270 printf("trap -- '%s' %s\n", G.traps[i], get_signame(i));
6271 return EXIT_SUCCESS;
6272 }
6273
6274 new_cmd = NULL;
6275 i = 0;
6276 /* If first arg is decimal: reset all specified signals */
6277 sig = bb_strtou(*argv, NULL, 10);
6278 if (errno == 0) {
6279 int ret;
6280 set_all:
6281 ret = EXIT_SUCCESS;
6282 while (*argv) {
6283 sig = get_signum(*argv++);
6284 if (sig < 0 || sig >= NSIG) {
6285 ret = EXIT_FAILURE;
6286 /* Mimic bash message exactly */
6287 bb_perror_msg("trap: %s: invalid signal specification", argv[i]);
6288 continue;
6289 }
6290
6291 free(G.traps[sig]);
6292 G.traps[sig] = xstrdup(new_cmd);
6293
6294 debug_printf("trap: setting SIG%s (%i) to '%s'",
6295 get_signame(sig), sig, G.traps[sig]);
6296
6297 /* There is no signal for 0 (EXIT) */
6298 if (sig == 0)
6299 continue;
6300
6301 if (new_cmd) {
6302 sigaddset(&G.blocked_set, sig);
6303 } else {
6304 /* There was a trap handler, we are removing it
6305 * (if sig has non-DFL handling,
6306 * we don't need to do anything) */
6307 if (sig < 32 && (G.non_DFL_mask & (1 << sig)))
6308 continue;
6309 sigdelset(&G.blocked_set, sig);
6310 }
6311 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
6312 }
6313 return ret;
6314 }
6315
6316 /* First arg is "-": reset all specified to default */
6317 /* First arg is "": ignore all specified */
6318 /* Everything else: execute first arg upon signal */
6319 if (!argv[1]) {
6320 bb_error_msg("trap: invalid arguments");
6321 return EXIT_FAILURE;
6322 }
6323 if (NOT_LONE_DASH(*argv))
6324 new_cmd = *argv;
6325 argv++;
6326 goto set_all;
6327}
6328
6329static int builtin_true(char **argv UNUSED_PARAM) 6257static int builtin_true(char **argv UNUSED_PARAM)
6330{ 6258{
6331 return 0; 6259 return 0;
@@ -6427,6 +6355,26 @@ static int builtin_exit(char **argv)
6427 hush_exit(xatoi(*argv) & 0xff); 6355 hush_exit(xatoi(*argv) & 0xff);
6428} 6356}
6429 6357
6358static void print_escaped(const char *s)
6359{
6360 do {
6361 if (*s != '\'') {
6362 const char *p;
6363
6364 p = strchrnul(s, '\'');
6365 /* print 'xxxx', possibly just '' */
6366 printf("'%.*s'", (int)(p - s), s);
6367 if (*p == '\0')
6368 break;
6369 s = p;
6370 }
6371 /* s points to '; print "'''...'''" */
6372 putchar('"');
6373 do putchar('\''); while (*++s == '\'');
6374 putchar('"');
6375 } while (*s);
6376}
6377
6430static int builtin_export(char **argv) 6378static int builtin_export(char **argv)
6431{ 6379{
6432 if (*++argv == NULL) { 6380 if (*++argv == NULL) {
@@ -6446,25 +6394,11 @@ static int builtin_export(char **argv)
6446 continue; 6394 continue;
6447 /* export var= */ 6395 /* export var= */
6448 printf("export %.*s", (int)(p - s) + 1, s); 6396 printf("export %.*s", (int)(p - s) + 1, s);
6449 s = p + 1; 6397 print_escaped(p + 1);
6450 while (*s) {
6451 if (*s != '\'') {
6452 p = strchrnul(s, '\'');
6453 /* print 'xxxx' */
6454 printf("'%.*s'", (int)(p - s), s);
6455 if (*p == '\0')
6456 break;
6457 s = p;
6458 }
6459 /* s points to '; print ''...'''" */
6460 putchar('"');
6461 do putchar('\''); while (*++s == '\'');
6462 putchar('"');
6463 }
6464 putchar('\n'); 6398 putchar('\n');
6465#endif 6399#endif
6466 } 6400 }
6467 fflush(stdout); 6401 /*fflush(stdout); - done after each builtin anyway */
6468 } 6402 }
6469 return EXIT_SUCCESS; 6403 return EXIT_SUCCESS;
6470 } 6404 }
@@ -6494,6 +6428,96 @@ static int builtin_export(char **argv)
6494 return EXIT_SUCCESS; 6428 return EXIT_SUCCESS;
6495} 6429}
6496 6430
6431static int builtin_trap(char **argv)
6432{
6433 int i;
6434 int sig;
6435 char *new_cmd;
6436
6437 if (!G.traps)
6438 G.traps = xzalloc(sizeof(G.traps[0]) * NSIG);
6439
6440 argv++;
6441 if (!*argv) {
6442 /* No args: print all trapped */
6443 for (i = 0; i < NSIG; ++i) {
6444 if (G.traps[i]) {
6445 printf("trap -- ");
6446 print_escaped(G.traps[i]);
6447 printf(" %s\n", get_signame(i));
6448 }
6449 }
6450 /*fflush(stdout); - done after each builtin anyway */
6451 return EXIT_SUCCESS;
6452 }
6453
6454 new_cmd = NULL;
6455 i = 0;
6456 /* If first arg is a number: reset all specified signals */
6457 sig = bb_strtou(*argv, NULL, 10);
6458 if (errno == 0) {
6459 int ret;
6460 process_sig_list:
6461 ret = EXIT_SUCCESS;
6462 while (*argv) {
6463 sig = get_signum(*argv++);
6464 if (sig < 0 || sig >= NSIG) {
6465 ret = EXIT_FAILURE;
6466 /* Mimic bash message exactly */
6467 bb_perror_msg("trap: %s: invalid signal specification", argv[i]);
6468 continue;
6469 }
6470
6471 free(G.traps[sig]);
6472 G.traps[sig] = xstrdup(new_cmd);
6473
6474 debug_printf("trap: setting SIG%s (%i) to '%s'",
6475 get_signame(sig), sig, G.traps[sig]);
6476
6477 /* There is no signal for 0 (EXIT) */
6478 if (sig == 0)
6479 continue;
6480
6481 if (new_cmd) {
6482 sigaddset(&G.blocked_set, sig);
6483 } else {
6484 /* There was a trap handler, we are removing it
6485 * (if sig has non-DFL handling,
6486 * we don't need to do anything) */
6487 if (sig < 32 && (G.non_DFL_mask & (1 << sig)))
6488 continue;
6489 sigdelset(&G.blocked_set, sig);
6490 }
6491 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
6492 }
6493 return ret;
6494 }
6495
6496 if (!argv[1]) { /* no second arg */
6497 bb_error_msg("trap: invalid arguments");
6498 return EXIT_FAILURE;
6499 }
6500
6501 /* First arg is "-": reset all specified to default */
6502 /* First arg is "--": skip it, the rest is "handler SIGs..." */
6503 /* Everything else: set arg as signal handler
6504 * (includes "" case, which ignores signal) */
6505 if (argv[0][0] == '-') {
6506 if (argv[0][1] == '\0') { /* "-" */
6507 /* new_cmd remains NULL: "reset these sigs" */
6508 goto reset_traps;
6509 }
6510 if (argv[0][1] == '-' && argv[0][2] == '\0') { /* "--" */
6511 argv++;
6512 }
6513 /* else: "-something", no special meaning */
6514 }
6515 new_cmd = *argv;
6516 reset_traps:
6517 argv++;
6518 goto process_sig_list;
6519}
6520
6497#if ENABLE_HUSH_JOB 6521#if ENABLE_HUSH_JOB
6498/* built-in 'fg' and 'bg' handler */ 6522/* built-in 'fg' and 'bg' handler */
6499static int builtin_fg_bg(char **argv) 6523static int builtin_fg_bg(char **argv)