diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-29 19:43:10 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-29 19:43:10 +0000 |
commit | 87a8655f4600cdad2b9af3312084a83e619c9abd (patch) | |
tree | d7086c732732d0bfacd18efdbf7b3a55b952a055 /shell/hush.c | |
parent | ff29b4fc42f723b451ce20ea3db8b43409470e82 (diff) | |
download | busybox-w32-87a8655f4600cdad2b9af3312084a83e619c9abd.tar.gz busybox-w32-87a8655f4600cdad2b9af3312084a83e619c9abd.tar.bz2 busybox-w32-87a8655f4600cdad2b9af3312084a83e619c9abd.zip |
hush: use G.xxx instead of #define xxx G.xxx. We have too many globals
there and #defines get messy. Remove one write-only G.variable.
Diffstat (limited to '')
-rw-r--r-- | shell/hush.c | 432 |
1 files changed, 198 insertions, 234 deletions
diff --git a/shell/hush.c b/shell/hush.c index f65405563..b471bd845 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -427,9 +427,10 @@ struct globals { | |||
427 | line_input_t *line_input_state; | 427 | line_input_t *line_input_state; |
428 | #endif | 428 | #endif |
429 | pid_t root_pid; | 429 | pid_t root_pid; |
430 | pid_t last_bg_pid; | ||
430 | #if ENABLE_HUSH_JOB | 431 | #if ENABLE_HUSH_JOB |
431 | int run_list_level; | 432 | int run_list_level; |
432 | pid_t saved_task_pgrp; | 433 | // pid_t saved_task_pgrp; |
433 | pid_t saved_tty_pgrp; | 434 | pid_t saved_tty_pgrp; |
434 | int last_jobid; | 435 | int last_jobid; |
435 | struct pipe *job_list; | 436 | struct pipe *job_list; |
@@ -448,10 +449,9 @@ struct globals { | |||
448 | unsigned depth_break_continue; | 449 | unsigned depth_break_continue; |
449 | unsigned depth_of_loop; | 450 | unsigned depth_of_loop; |
450 | #endif | 451 | #endif |
451 | pid_t last_bg_pid; | ||
452 | const char *ifs; | 452 | const char *ifs; |
453 | const char *cwd; | 453 | const char *cwd; |
454 | struct variable *top_var; /* = &shell_ver (set in main()) */ | 454 | struct variable *top_var; /* = &G.shell_ver (set in main()) */ |
455 | struct variable shell_ver; | 455 | struct variable shell_ver; |
456 | #if ENABLE_FEATURE_SH_STANDALONE | 456 | #if ENABLE_FEATURE_SH_STANDALONE |
457 | struct nofork_save_area nofork_save; | 457 | struct nofork_save_area nofork_save; |
@@ -464,53 +464,9 @@ struct globals { | |||
464 | }; | 464 | }; |
465 | 465 | ||
466 | #define G (*ptr_to_globals) | 466 | #define G (*ptr_to_globals) |
467 | 467 | /* Not #defining name to G.name - this quickly gets unwieldy | |
468 | #if !ENABLE_HUSH_INTERACTIVE | 468 | * (too many defines). Also, I actually prefer to see when a variable |
469 | enum { interactive_fd = 0 }; | 469 | * is global, thus "G." prefix is a useful hint */ |
470 | #endif | ||
471 | #if !ENABLE_HUSH_JOB | ||
472 | enum { run_list_level = 0 }; | ||
473 | #endif | ||
474 | |||
475 | #if ENABLE_HUSH_INTERACTIVE | ||
476 | #define interactive_fd (G.interactive_fd ) | ||
477 | #define PS1 (G.PS1 ) | ||
478 | #define PS2 (G.PS2 ) | ||
479 | #endif | ||
480 | #if ENABLE_FEATURE_EDITING | ||
481 | #define line_input_state (G.line_input_state) | ||
482 | #endif | ||
483 | #define root_pid (G.root_pid ) | ||
484 | #if ENABLE_HUSH_JOB | ||
485 | #define run_list_level (G.run_list_level ) | ||
486 | #define saved_task_pgrp (G.saved_task_pgrp ) | ||
487 | #define saved_tty_pgrp (G.saved_tty_pgrp ) | ||
488 | #define last_jobid (G.last_jobid ) | ||
489 | #define job_list (G.job_list ) | ||
490 | #define toplevel_list (G.toplevel_list ) | ||
491 | #define toplevel_jb (G.toplevel_jb ) | ||
492 | #define ctrl_z_flag (G.ctrl_z_flag ) | ||
493 | #endif /* JOB */ | ||
494 | #define global_argv (G.global_argv ) | ||
495 | #define global_argc (G.global_argc ) | ||
496 | #define last_return_code (G.last_return_code) | ||
497 | #define ifs (G.ifs ) | ||
498 | #define flag_break_continue (G.flag_break_continue ) | ||
499 | #define depth_break_continue (G.depth_break_continue) | ||
500 | #define depth_of_loop (G.depth_of_loop ) | ||
501 | #define fake_mode (G.fake_mode ) | ||
502 | #define cwd (G.cwd ) | ||
503 | #define last_bg_pid (G.last_bg_pid ) | ||
504 | #define top_var (G.top_var ) | ||
505 | #define shell_ver (G.shell_ver ) | ||
506 | #if ENABLE_FEATURE_SH_STANDALONE | ||
507 | #define nofork_save (G.nofork_save ) | ||
508 | #endif | ||
509 | #if ENABLE_HUSH_JOB | ||
510 | #define toplevel_jb (G.toplevel_jb ) | ||
511 | #endif | ||
512 | #define charmap (G.charmap ) | ||
513 | #define user_input_buf (G.user_input_buf ) | ||
514 | #define INIT_G() do { \ | 470 | #define INIT_G() do { \ |
515 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 471 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
516 | } while (0) | 472 | } while (0) |
@@ -522,23 +478,29 @@ enum { run_list_level = 0 }; | |||
522 | /* Normal */ | 478 | /* Normal */ |
523 | static void syntax(const char *msg) | 479 | static void syntax(const char *msg) |
524 | { | 480 | { |
481 | #if ENABLE_HUSH_INTERACTIVE | ||
525 | /* Was using fancy stuff: | 482 | /* Was using fancy stuff: |
526 | * (interactive_fd ? bb_error_msg : bb_error_msg_and_die)(...params...) | 483 | * (G.interactive_fd ? bb_error_msg : bb_error_msg_and_die)(...params...) |
527 | * but it SEGVs. ?! Oh well... explicit temp ptr works around that */ | 484 | * but it SEGVs. ?! Oh well... explicit temp ptr works around that */ |
528 | void FAST_FUNC (*fp)(const char *s, ...); | 485 | void FAST_FUNC (*fp)(const char *s, ...); |
529 | 486 | fp = (G.interactive_fd ? bb_error_msg : bb_error_msg_and_die); | |
530 | fp = (interactive_fd ? bb_error_msg : bb_error_msg_and_die); | ||
531 | fp(msg ? "%s: %s" : "syntax error", "syntax error", msg); | 487 | fp(msg ? "%s: %s" : "syntax error", "syntax error", msg); |
488 | #else | ||
489 | bb_error_msg_and_die(msg ? "%s: %s" : "syntax error", "syntax error", msg); | ||
490 | #endif | ||
532 | } | 491 | } |
533 | 492 | ||
534 | #else | 493 | #else |
535 | /* Debug */ | 494 | /* Debug */ |
536 | static void syntax_lineno(int line) | 495 | static void syntax_lineno(int line) |
537 | { | 496 | { |
497 | #if ENABLE_HUSH_INTERACTIVE | ||
538 | void FAST_FUNC (*fp)(const char *s, ...); | 498 | void FAST_FUNC (*fp)(const char *s, ...); |
539 | 499 | fp = (G.interactive_fd ? bb_error_msg : bb_error_msg_and_die); | |
540 | fp = (interactive_fd ? bb_error_msg : bb_error_msg_and_die); | ||
541 | fp("syntax error hush.c:%d", line); | 500 | fp("syntax error hush.c:%d", line); |
501 | #else | ||
502 | bb_error_msg_and_die("syntax error hush.c:%d", line); | ||
503 | #endif | ||
542 | } | 504 | } |
543 | #define syntax(str) syntax_lineno(__LINE__) | 505 | #define syntax(str) syntax_lineno(__LINE__) |
544 | #endif | 506 | #endif |
@@ -844,7 +806,7 @@ static void handler_ctrl_c(int sig UNUSED_PARAM) | |||
844 | { | 806 | { |
845 | debug_printf_jobs("got sig %d\n", sig); | 807 | debug_printf_jobs("got sig %d\n", sig); |
846 | // as usual we can have all kinds of nasty problems with leaked malloc data here | 808 | // as usual we can have all kinds of nasty problems with leaked malloc data here |
847 | siglongjmp(toplevel_jb, 1); | 809 | siglongjmp(G.toplevel_jb, 1); |
848 | } | 810 | } |
849 | 811 | ||
850 | static void handler_ctrl_z(int sig UNUSED_PARAM) | 812 | static void handler_ctrl_z(int sig UNUSED_PARAM) |
@@ -855,7 +817,7 @@ static void handler_ctrl_z(int sig UNUSED_PARAM) | |||
855 | pid = fork(); | 817 | pid = fork(); |
856 | if (pid < 0) /* can't fork. Pretend there was no ctrl-Z */ | 818 | if (pid < 0) /* can't fork. Pretend there was no ctrl-Z */ |
857 | return; | 819 | return; |
858 | ctrl_z_flag = 1; | 820 | G.ctrl_z_flag = 1; |
859 | if (!pid) { /* child */ | 821 | if (!pid) { /* child */ |
860 | if (ENABLE_HUSH_JOB) | 822 | if (ENABLE_HUSH_JOB) |
861 | die_sleep = 0; /* let nofork's xfuncs die */ | 823 | die_sleep = 0; /* let nofork's xfuncs die */ |
@@ -870,13 +832,13 @@ static void handler_ctrl_z(int sig UNUSED_PARAM) | |||
870 | } | 832 | } |
871 | /* parent */ | 833 | /* parent */ |
872 | /* finish filling up pipe info */ | 834 | /* finish filling up pipe info */ |
873 | toplevel_list->pgrp = pid; /* child is in its own pgrp */ | 835 | G.toplevel_list->pgrp = pid; /* child is in its own pgrp */ |
874 | toplevel_list->progs[0].pid = pid; | 836 | G.toplevel_list->progs[0].pid = pid; |
875 | /* parent needs to longjmp out of running nofork. | 837 | /* parent needs to longjmp out of running nofork. |
876 | * we will "return" exitcode 0, with child put in background */ | 838 | * we will "return" exitcode 0, with child put in background */ |
877 | // as usual we can have all kinds of nasty problems with leaked malloc data here | 839 | // as usual we can have all kinds of nasty problems with leaked malloc data here |
878 | debug_printf_jobs("siglongjmp in parent\n"); | 840 | debug_printf_jobs("siglongjmp in parent\n"); |
879 | siglongjmp(toplevel_jb, 1); | 841 | siglongjmp(G.toplevel_jb, 1); |
880 | } | 842 | } |
881 | 843 | ||
882 | /* Restores tty foreground process group, and exits. | 844 | /* Restores tty foreground process group, and exits. |
@@ -890,8 +852,10 @@ static void sigexit(int sig) | |||
890 | /* Disable all signals: job control, SIGPIPE, etc. */ | 852 | /* Disable all signals: job control, SIGPIPE, etc. */ |
891 | sigprocmask_allsigs(SIG_BLOCK); | 853 | sigprocmask_allsigs(SIG_BLOCK); |
892 | 854 | ||
893 | if (interactive_fd) | 855 | #if ENABLE_HUSH_INTERACTIVE |
894 | tcsetpgrp(interactive_fd, saved_tty_pgrp); | 856 | if (G.interactive_fd) |
857 | tcsetpgrp(G.interactive_fd, G.saved_tty_pgrp); | ||
858 | #endif | ||
895 | 859 | ||
896 | /* Not a signal, just exit */ | 860 | /* Not a signal, just exit */ |
897 | if (sig <= 0) | 861 | if (sig <= 0) |
@@ -919,12 +883,12 @@ static void hush_exit(int exitcode) | |||
919 | 883 | ||
920 | static const char *set_cwd(void) | 884 | static const char *set_cwd(void) |
921 | { | 885 | { |
922 | if (cwd == bb_msg_unknown) | 886 | if (G.cwd == bb_msg_unknown) |
923 | cwd = NULL; /* xrealloc_getcwd_or_warn(arg) calls free(arg)! */ | 887 | G.cwd = NULL; /* xrealloc_getcwd_or_warn(arg) calls free(arg)! */ |
924 | cwd = xrealloc_getcwd_or_warn((char *)cwd); | 888 | G.cwd = xrealloc_getcwd_or_warn((char *)G.cwd); |
925 | if (!cwd) | 889 | if (!G.cwd) |
926 | cwd = bb_msg_unknown; | 890 | G.cwd = bb_msg_unknown; |
927 | return cwd; | 891 | return G.cwd; |
928 | } | 892 | } |
929 | 893 | ||
930 | 894 | ||
@@ -1224,11 +1188,11 @@ static int static_peek(struct in_str *i) | |||
1224 | static void cmdedit_set_initial_prompt(void) | 1188 | static void cmdedit_set_initial_prompt(void) |
1225 | { | 1189 | { |
1226 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT | 1190 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT |
1227 | PS1 = NULL; | 1191 | G.PS1 = NULL; |
1228 | #else | 1192 | #else |
1229 | PS1 = getenv("PS1"); | 1193 | G.PS1 = getenv("PS1"); |
1230 | if (PS1 == NULL) | 1194 | if (G.PS1 == NULL) |
1231 | PS1 = "\\w \\$ "; | 1195 | G.PS1 = "\\w \\$ "; |
1232 | #endif | 1196 | #endif |
1233 | } | 1197 | } |
1234 | #endif /* EDITING */ | 1198 | #endif /* EDITING */ |
@@ -1240,14 +1204,14 @@ static const char* setup_prompt_string(int promptmode) | |||
1240 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT | 1204 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT |
1241 | /* Set up the prompt */ | 1205 | /* Set up the prompt */ |
1242 | if (promptmode == 0) { /* PS1 */ | 1206 | if (promptmode == 0) { /* PS1 */ |
1243 | free((char*)PS1); | 1207 | free((char*)G.PS1); |
1244 | PS1 = xasprintf("%s %c ", cwd, (geteuid() != 0) ? '$' : '#'); | 1208 | G.PS1 = xasprintf("%s %c ", G.cwd, (geteuid() != 0) ? '$' : '#'); |
1245 | prompt_str = PS1; | 1209 | prompt_str = G.PS1; |
1246 | } else { | 1210 | } else { |
1247 | prompt_str = PS2; | 1211 | prompt_str = G.PS2; |
1248 | } | 1212 | } |
1249 | #else | 1213 | #else |
1250 | prompt_str = (promptmode == 0) ? PS1 : PS2; | 1214 | prompt_str = (promptmode == 0) ? G.PS1 : G.PS2; |
1251 | #endif | 1215 | #endif |
1252 | debug_printf("result '%s'\n", prompt_str); | 1216 | debug_printf("result '%s'\n", prompt_str); |
1253 | return prompt_str; | 1217 | return prompt_str; |
@@ -1263,21 +1227,21 @@ static void get_user_input(struct in_str *i) | |||
1263 | /* Enable command line editing only while a command line | 1227 | /* Enable command line editing only while a command line |
1264 | * is actually being read */ | 1228 | * is actually being read */ |
1265 | do { | 1229 | do { |
1266 | r = read_line_input(prompt_str, user_input_buf, BUFSIZ-1, line_input_state); | 1230 | r = read_line_input(prompt_str, G.user_input_buf, BUFSIZ-1, G.line_input_state); |
1267 | } while (r == 0); /* repeat if Ctrl-C */ | 1231 | } while (r == 0); /* repeat if Ctrl-C */ |
1268 | i->eof_flag = (r < 0); | 1232 | i->eof_flag = (r < 0); |
1269 | if (i->eof_flag) { /* EOF/error detected */ | 1233 | if (i->eof_flag) { /* EOF/error detected */ |
1270 | user_input_buf[0] = EOF; /* yes, it will be truncated, it's ok */ | 1234 | G.user_input_buf[0] = EOF; /* yes, it will be truncated, it's ok */ |
1271 | user_input_buf[1] = '\0'; | 1235 | G.user_input_buf[1] = '\0'; |
1272 | } | 1236 | } |
1273 | #else | 1237 | #else |
1274 | fputs(prompt_str, stdout); | 1238 | fputs(prompt_str, stdout); |
1275 | fflush(stdout); | 1239 | fflush(stdout); |
1276 | user_input_buf[0] = r = fgetc(i->file); | 1240 | G.user_input_buf[0] = r = fgetc(i->file); |
1277 | /*user_input_buf[1] = '\0'; - already is and never changed */ | 1241 | /*G.user_input_buf[1] = '\0'; - already is and never changed */ |
1278 | i->eof_flag = (r == EOF); | 1242 | i->eof_flag = (r == EOF); |
1279 | #endif | 1243 | #endif |
1280 | i->p = user_input_buf; | 1244 | i->p = G.user_input_buf; |
1281 | } | 1245 | } |
1282 | 1246 | ||
1283 | #endif /* INTERACTIVE */ | 1247 | #endif /* INTERACTIVE */ |
@@ -1300,7 +1264,7 @@ static int file_get(struct in_str *i) | |||
1300 | /* need to double check i->file because we might be doing something | 1264 | /* need to double check i->file because we might be doing something |
1301 | * more complicated by now, like sourcing or substituting. */ | 1265 | * more complicated by now, like sourcing or substituting. */ |
1302 | #if ENABLE_HUSH_INTERACTIVE | 1266 | #if ENABLE_HUSH_INTERACTIVE |
1303 | if (interactive_fd && i->promptme && i->file == stdin) { | 1267 | if (G.interactive_fd && i->promptme && i->file == stdin) { |
1304 | do { | 1268 | do { |
1305 | get_user_input(i); | 1269 | get_user_input(i); |
1306 | } while (!*i->p); /* need non-empty line */ | 1270 | } while (!*i->p); /* need non-empty line */ |
@@ -1561,15 +1525,15 @@ static void insert_bg_job(struct pipe *pi) | |||
1561 | 1525 | ||
1562 | /* Linear search for the ID of the job to use */ | 1526 | /* Linear search for the ID of the job to use */ |
1563 | pi->jobid = 1; | 1527 | pi->jobid = 1; |
1564 | for (thejob = job_list; thejob; thejob = thejob->next) | 1528 | for (thejob = G.job_list; thejob; thejob = thejob->next) |
1565 | if (thejob->jobid >= pi->jobid) | 1529 | if (thejob->jobid >= pi->jobid) |
1566 | pi->jobid = thejob->jobid + 1; | 1530 | pi->jobid = thejob->jobid + 1; |
1567 | 1531 | ||
1568 | /* Add thejob to the list of running jobs */ | 1532 | /* Add thejob to the list of running jobs */ |
1569 | if (!job_list) { | 1533 | if (!G.job_list) { |
1570 | thejob = job_list = xmalloc(sizeof(*thejob)); | 1534 | thejob = G.job_list = xmalloc(sizeof(*thejob)); |
1571 | } else { | 1535 | } else { |
1572 | for (thejob = job_list; thejob->next; thejob = thejob->next) | 1536 | for (thejob = G.job_list; thejob->next; thejob = thejob->next) |
1573 | continue; | 1537 | continue; |
1574 | thejob->next = xmalloc(sizeof(*thejob)); | 1538 | thejob->next = xmalloc(sizeof(*thejob)); |
1575 | thejob = thejob->next; | 1539 | thejob = thejob->next; |
@@ -1591,26 +1555,26 @@ static void insert_bg_job(struct pipe *pi) | |||
1591 | /* We don't wait for background thejobs to return -- append it | 1555 | /* We don't wait for background thejobs to return -- append it |
1592 | to the list of backgrounded thejobs and leave it alone */ | 1556 | to the list of backgrounded thejobs and leave it alone */ |
1593 | printf("[%d] %d %s\n", thejob->jobid, thejob->progs[0].pid, thejob->cmdtext); | 1557 | printf("[%d] %d %s\n", thejob->jobid, thejob->progs[0].pid, thejob->cmdtext); |
1594 | last_bg_pid = thejob->progs[0].pid; | 1558 | G.last_bg_pid = thejob->progs[0].pid; |
1595 | last_jobid = thejob->jobid; | 1559 | G.last_jobid = thejob->jobid; |
1596 | } | 1560 | } |
1597 | 1561 | ||
1598 | static void remove_bg_job(struct pipe *pi) | 1562 | static void remove_bg_job(struct pipe *pi) |
1599 | { | 1563 | { |
1600 | struct pipe *prev_pipe; | 1564 | struct pipe *prev_pipe; |
1601 | 1565 | ||
1602 | if (pi == job_list) { | 1566 | if (pi == G.job_list) { |
1603 | job_list = pi->next; | 1567 | G.job_list = pi->next; |
1604 | } else { | 1568 | } else { |
1605 | prev_pipe = job_list; | 1569 | prev_pipe = G.job_list; |
1606 | while (prev_pipe->next != pi) | 1570 | while (prev_pipe->next != pi) |
1607 | prev_pipe = prev_pipe->next; | 1571 | prev_pipe = prev_pipe->next; |
1608 | prev_pipe->next = pi->next; | 1572 | prev_pipe->next = pi->next; |
1609 | } | 1573 | } |
1610 | if (job_list) | 1574 | if (G.job_list) |
1611 | last_jobid = job_list->jobid; | 1575 | G.last_jobid = G.job_list->jobid; |
1612 | else | 1576 | else |
1613 | last_jobid = 0; | 1577 | G.last_jobid = 0; |
1614 | } | 1578 | } |
1615 | 1579 | ||
1616 | /* Remove a backgrounded job */ | 1580 | /* Remove a backgrounded job */ |
@@ -1705,7 +1669,7 @@ static int checkjobs(struct pipe* fg_pipe) | |||
1705 | #if ENABLE_HUSH_JOB | 1669 | #if ENABLE_HUSH_JOB |
1706 | /* We asked to wait for bg or orphaned children */ | 1670 | /* We asked to wait for bg or orphaned children */ |
1707 | /* No need to remember exitcode in this case */ | 1671 | /* No need to remember exitcode in this case */ |
1708 | for (pi = job_list; pi; pi = pi->next) { | 1672 | for (pi = G.job_list; pi; pi = pi->next) { |
1709 | for (i = 0; i < pi->num_progs; i++) { | 1673 | for (i = 0; i < pi->num_progs; i++) { |
1710 | if (pi->progs[i].pid == childpid) | 1674 | if (pi->progs[i].pid == childpid) |
1711 | goto found_pi_and_prognum; | 1675 | goto found_pi_and_prognum; |
@@ -1748,8 +1712,8 @@ static int checkjobs_and_fg_shell(struct pipe* fg_pipe) | |||
1748 | /* Job finished, move the shell to the foreground */ | 1712 | /* Job finished, move the shell to the foreground */ |
1749 | p = getpgid(0); /* pgid of our process */ | 1713 | p = getpgid(0); /* pgid of our process */ |
1750 | debug_printf_jobs("fg'ing ourself: getpgid(0)=%d\n", (int)p); | 1714 | debug_printf_jobs("fg'ing ourself: getpgid(0)=%d\n", (int)p); |
1751 | tcsetpgrp(interactive_fd, p); | 1715 | tcsetpgrp(G.interactive_fd, p); |
1752 | // if (tcsetpgrp(interactive_fd, p) && errno != ENOTTY) | 1716 | // if (tcsetpgrp(G.interactive_fd, p) && errno != ENOTTY) |
1753 | // bb_perror_msg("tcsetpgrp-4a"); | 1717 | // bb_perror_msg("tcsetpgrp-4a"); |
1754 | return rcode; | 1718 | return rcode; |
1755 | } | 1719 | } |
@@ -1865,9 +1829,9 @@ static int run_pipe(struct pipe *pi) | |||
1865 | int a = find_applet_by_name(argv_expanded[0]); | 1829 | int a = find_applet_by_name(argv_expanded[0]); |
1866 | if (a >= 0 && APPLET_IS_NOFORK(a)) { | 1830 | if (a >= 0 && APPLET_IS_NOFORK(a)) { |
1867 | setup_redirects(child, squirrel); | 1831 | setup_redirects(child, squirrel); |
1868 | save_nofork_data(&nofork_save); | 1832 | save_nofork_data(&G.nofork_save); |
1869 | debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", argv_expanded[0], argv_expanded[1]); | 1833 | debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", argv_expanded[0], argv_expanded[1]); |
1870 | rcode = run_nofork_applet_prime(&nofork_save, a, argv_expanded); | 1834 | rcode = run_nofork_applet_prime(&G.nofork_save, a, argv_expanded); |
1871 | free(argv_expanded); | 1835 | free(argv_expanded); |
1872 | restore_redirects(squirrel); | 1836 | restore_redirects(squirrel); |
1873 | debug_printf_exec("run_pipe return %d\n", rcode); | 1837 | debug_printf_exec("run_pipe return %d\n", rcode); |
@@ -1916,7 +1880,7 @@ static int run_pipe(struct pipe *pi) | |||
1916 | #if ENABLE_HUSH_JOB | 1880 | #if ENABLE_HUSH_JOB |
1917 | /* Every child adds itself to new process group | 1881 | /* Every child adds itself to new process group |
1918 | * with pgid == pid_of_first_child_in_pipe */ | 1882 | * with pgid == pid_of_first_child_in_pipe */ |
1919 | if (run_list_level == 1 && interactive_fd) { | 1883 | if (G.run_list_level == 1 && G.interactive_fd) { |
1920 | pid_t pgrp; | 1884 | pid_t pgrp; |
1921 | /* Don't do pgrp restore anymore on fatal signals */ | 1885 | /* Don't do pgrp restore anymore on fatal signals */ |
1922 | set_fatal_sighandler(SIG_DFL); | 1886 | set_fatal_sighandler(SIG_DFL); |
@@ -1926,7 +1890,7 @@ static int run_pipe(struct pipe *pi) | |||
1926 | if (setpgid(0, pgrp) == 0 && pi->followup != PIPE_BG) { | 1890 | if (setpgid(0, pgrp) == 0 && pi->followup != PIPE_BG) { |
1927 | /* We do it in *every* child, not just first, | 1891 | /* We do it in *every* child, not just first, |
1928 | * to avoid races */ | 1892 | * to avoid races */ |
1929 | tcsetpgrp(interactive_fd, pgrp); | 1893 | tcsetpgrp(G.interactive_fd, pgrp); |
1930 | } | 1894 | } |
1931 | } | 1895 | } |
1932 | #endif | 1896 | #endif |
@@ -2072,7 +2036,7 @@ static int run_list(struct pipe *pi) | |||
2072 | /*enum reserved_style*/ smallint rword = RES_NONE; | 2036 | /*enum reserved_style*/ smallint rword = RES_NONE; |
2073 | /*enum reserved_style*/ smallint skip_more_for_this_rword = RES_XXXX; | 2037 | /*enum reserved_style*/ smallint skip_more_for_this_rword = RES_XXXX; |
2074 | 2038 | ||
2075 | debug_printf_exec("run_list start lvl %d\n", run_list_level + 1); | 2039 | debug_printf_exec("run_list start lvl %d\n", G.run_list_level + 1); |
2076 | 2040 | ||
2077 | #if ENABLE_HUSH_LOOPS | 2041 | #if ENABLE_HUSH_LOOPS |
2078 | /* Check syntax for "for" */ | 2042 | /* Check syntax for "for" */ |
@@ -2082,7 +2046,7 @@ static int run_list(struct pipe *pi) | |||
2082 | /* current word is FOR or IN (BOLD in comments below) */ | 2046 | /* current word is FOR or IN (BOLD in comments below) */ |
2083 | if (cpipe->next == NULL) { | 2047 | if (cpipe->next == NULL) { |
2084 | syntax("malformed for"); | 2048 | syntax("malformed for"); |
2085 | debug_printf_exec("run_list lvl %d return 1\n", run_list_level); | 2049 | debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level); |
2086 | return 1; | 2050 | return 1; |
2087 | } | 2051 | } |
2088 | /* "FOR v; do ..." and "for v IN a b; do..." are ok */ | 2052 | /* "FOR v; do ..." and "for v IN a b; do..." are ok */ |
@@ -2093,7 +2057,7 @@ static int run_list(struct pipe *pi) | |||
2093 | || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */ | 2057 | || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */ |
2094 | ) { | 2058 | ) { |
2095 | syntax("malformed for"); | 2059 | syntax("malformed for"); |
2096 | debug_printf_exec("run_list lvl %d return 1\n", run_list_level); | 2060 | debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level); |
2097 | return 1; | 2061 | return 1; |
2098 | } | 2062 | } |
2099 | } | 2063 | } |
@@ -2108,22 +2072,22 @@ static int run_list(struct pipe *pi) | |||
2108 | * We are saving state before entering outermost list ("while...done") | 2072 | * We are saving state before entering outermost list ("while...done") |
2109 | * so that ctrl-Z will correctly background _entire_ outermost list, | 2073 | * so that ctrl-Z will correctly background _entire_ outermost list, |
2110 | * not just a part of it (like "sleep 1 | exit 2") */ | 2074 | * not just a part of it (like "sleep 1 | exit 2") */ |
2111 | if (++run_list_level == 1 && interactive_fd) { | 2075 | if (++G.run_list_level == 1 && G.interactive_fd) { |
2112 | if (sigsetjmp(toplevel_jb, 1)) { | 2076 | if (sigsetjmp(G.toplevel_jb, 1)) { |
2113 | /* ctrl-Z forked and we are parent; or ctrl-C. | 2077 | /* ctrl-Z forked and we are parent; or ctrl-C. |
2114 | * Sighandler has longjmped us here */ | 2078 | * Sighandler has longjmped us here */ |
2115 | signal(SIGINT, SIG_IGN); | 2079 | signal(SIGINT, SIG_IGN); |
2116 | signal(SIGTSTP, SIG_IGN); | 2080 | signal(SIGTSTP, SIG_IGN); |
2117 | /* Restore level (we can be coming from deep inside | 2081 | /* Restore level (we can be coming from deep inside |
2118 | * nested levels) */ | 2082 | * nested levels) */ |
2119 | run_list_level = 1; | 2083 | G.run_list_level = 1; |
2120 | #if ENABLE_FEATURE_SH_STANDALONE | 2084 | #if ENABLE_FEATURE_SH_STANDALONE |
2121 | if (nofork_save.saved) { /* if save area is valid */ | 2085 | if (G.nofork_save.saved) { /* if save area is valid */ |
2122 | debug_printf_jobs("exiting nofork early\n"); | 2086 | debug_printf_jobs("exiting nofork early\n"); |
2123 | restore_nofork_data(&nofork_save); | 2087 | restore_nofork_data(&G.nofork_save); |
2124 | } | 2088 | } |
2125 | #endif | 2089 | #endif |
2126 | if (ctrl_z_flag) { | 2090 | if (G.ctrl_z_flag) { |
2127 | /* ctrl-Z has forked and stored pid of the child in pi->pid. | 2091 | /* ctrl-Z has forked and stored pid of the child in pi->pid. |
2128 | * Remember this child as background job */ | 2092 | * Remember this child as background job */ |
2129 | insert_bg_job(pi); | 2093 | insert_bg_job(pi); |
@@ -2132,15 +2096,15 @@ static int run_list(struct pipe *pi) | |||
2132 | bb_putchar('\n'); | 2096 | bb_putchar('\n'); |
2133 | } | 2097 | } |
2134 | USE_HUSH_LOOPS(loop_top = NULL;) | 2098 | USE_HUSH_LOOPS(loop_top = NULL;) |
2135 | USE_HUSH_LOOPS(depth_of_loop = 0;) | 2099 | USE_HUSH_LOOPS(G.depth_of_loop = 0;) |
2136 | rcode = 0; | 2100 | rcode = 0; |
2137 | goto ret; | 2101 | goto ret; |
2138 | } | 2102 | } |
2139 | /* ctrl-Z handler will store pid etc in pi */ | 2103 | /* ctrl-Z handler will store pid etc in pi */ |
2140 | toplevel_list = pi; | 2104 | G.toplevel_list = pi; |
2141 | ctrl_z_flag = 0; | 2105 | G.ctrl_z_flag = 0; |
2142 | #if ENABLE_FEATURE_SH_STANDALONE | 2106 | #if ENABLE_FEATURE_SH_STANDALONE |
2143 | nofork_save.saved = 0; /* in case we will run a nofork later */ | 2107 | G.nofork_save.saved = 0; /* in case we will run a nofork later */ |
2144 | #endif | 2108 | #endif |
2145 | signal_SA_RESTART_empty_mask(SIGTSTP, handler_ctrl_z); | 2109 | signal_SA_RESTART_empty_mask(SIGTSTP, handler_ctrl_z); |
2146 | signal(SIGINT, handler_ctrl_c); | 2110 | signal(SIGINT, handler_ctrl_c); |
@@ -2155,11 +2119,11 @@ static int run_list(struct pipe *pi) | |||
2155 | rword, cond_code, skip_more_for_this_rword); | 2119 | rword, cond_code, skip_more_for_this_rword); |
2156 | #if ENABLE_HUSH_LOOPS | 2120 | #if ENABLE_HUSH_LOOPS |
2157 | if ((rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) | 2121 | if ((rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) |
2158 | && loop_top == NULL /* avoid bumping depth_of_loop twice */ | 2122 | && loop_top == NULL /* avoid bumping G.depth_of_loop twice */ |
2159 | ) { | 2123 | ) { |
2160 | /* start of a loop: remember where loop starts */ | 2124 | /* start of a loop: remember where loop starts */ |
2161 | loop_top = pi; | 2125 | loop_top = pi; |
2162 | depth_of_loop++; | 2126 | G.depth_of_loop++; |
2163 | } | 2127 | } |
2164 | #endif | 2128 | #endif |
2165 | if (rword == skip_more_for_this_rword && flag_skip) { | 2129 | if (rword == skip_more_for_this_rword && flag_skip) { |
@@ -2268,7 +2232,7 @@ static int run_list(struct pipe *pi) | |||
2268 | { | 2232 | { |
2269 | int r; | 2233 | int r; |
2270 | #if ENABLE_HUSH_LOOPS | 2234 | #if ENABLE_HUSH_LOOPS |
2271 | flag_break_continue = 0; | 2235 | G.flag_break_continue = 0; |
2272 | #endif | 2236 | #endif |
2273 | rcode = r = run_pipe(pi); /* NB: rcode is a smallint */ | 2237 | rcode = r = run_pipe(pi); /* NB: rcode is a smallint */ |
2274 | if (r != -1) { | 2238 | if (r != -1) { |
@@ -2276,17 +2240,17 @@ static int run_list(struct pipe *pi) | |||
2276 | * and we don't need to wait for anything. */ | 2240 | * and we don't need to wait for anything. */ |
2277 | #if ENABLE_HUSH_LOOPS | 2241 | #if ENABLE_HUSH_LOOPS |
2278 | /* was it "break" or "continue"? */ | 2242 | /* was it "break" or "continue"? */ |
2279 | if (flag_break_continue) { | 2243 | if (G.flag_break_continue) { |
2280 | smallint fbc = flag_break_continue; | 2244 | smallint fbc = G.flag_break_continue; |
2281 | /* we might fall into outer *loop*, | 2245 | /* we might fall into outer *loop*, |
2282 | * don't want to break it too */ | 2246 | * don't want to break it too */ |
2283 | if (loop_top) { | 2247 | if (loop_top) { |
2284 | depth_break_continue--; | 2248 | G.depth_break_continue--; |
2285 | if (depth_break_continue == 0) | 2249 | if (G.depth_break_continue == 0) |
2286 | flag_break_continue = 0; | 2250 | G.flag_break_continue = 0; |
2287 | /* else: e.g. "continue 2" should *break* once, *then* continue */ | 2251 | /* else: e.g. "continue 2" should *break* once, *then* continue */ |
2288 | } /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */ | 2252 | } /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */ |
2289 | if (depth_break_continue != 0 || fbc == BC_BREAK) | 2253 | if (G.depth_break_continue != 0 || fbc == BC_BREAK) |
2290 | goto check_jobs_and_break; | 2254 | goto check_jobs_and_break; |
2291 | /* "continue": simulate end of loop */ | 2255 | /* "continue": simulate end of loop */ |
2292 | rword = RES_DONE; | 2256 | rword = RES_DONE; |
@@ -2299,13 +2263,13 @@ static int run_list(struct pipe *pi) | |||
2299 | * try "{ { sleep 10; echo DEEP; } & echo HERE; } &". | 2263 | * try "{ { sleep 10; echo DEEP; } & echo HERE; } &". |
2300 | * I'm NOT treating inner &'s as jobs */ | 2264 | * I'm NOT treating inner &'s as jobs */ |
2301 | #if ENABLE_HUSH_JOB | 2265 | #if ENABLE_HUSH_JOB |
2302 | if (run_list_level == 1) | 2266 | if (G.run_list_level == 1) |
2303 | insert_bg_job(pi); | 2267 | insert_bg_job(pi); |
2304 | #endif | 2268 | #endif |
2305 | rcode = 0; /* EXIT_SUCCESS */ | 2269 | rcode = 0; /* EXIT_SUCCESS */ |
2306 | } else { | 2270 | } else { |
2307 | #if ENABLE_HUSH_JOB | 2271 | #if ENABLE_HUSH_JOB |
2308 | if (run_list_level == 1 && interactive_fd) { | 2272 | if (G.run_list_level == 1 && G.interactive_fd) { |
2309 | /* waits for completion, then fg's main shell */ | 2273 | /* waits for completion, then fg's main shell */ |
2310 | rcode = checkjobs_and_fg_shell(pi); | 2274 | rcode = checkjobs_and_fg_shell(pi); |
2311 | debug_printf_exec(": checkjobs_and_fg_shell returned %d\n", rcode); | 2275 | debug_printf_exec(": checkjobs_and_fg_shell returned %d\n", rcode); |
@@ -2318,7 +2282,7 @@ static int run_list(struct pipe *pi) | |||
2318 | } | 2282 | } |
2319 | } | 2283 | } |
2320 | debug_printf_exec(": setting last_return_code=%d\n", rcode); | 2284 | debug_printf_exec(": setting last_return_code=%d\n", rcode); |
2321 | last_return_code = rcode; | 2285 | G.last_return_code = rcode; |
2322 | 2286 | ||
2323 | /* Analyze how result affects subsequent commands */ | 2287 | /* Analyze how result affects subsequent commands */ |
2324 | #if ENABLE_HUSH_IF | 2288 | #if ENABLE_HUSH_IF |
@@ -2349,22 +2313,22 @@ static int run_list(struct pipe *pi) | |||
2349 | } /* for (pi) */ | 2313 | } /* for (pi) */ |
2350 | 2314 | ||
2351 | #if ENABLE_HUSH_JOB | 2315 | #if ENABLE_HUSH_JOB |
2352 | if (ctrl_z_flag) { | 2316 | if (G.ctrl_z_flag) { |
2353 | /* ctrl-Z forked somewhere in the past, we are the child, | 2317 | /* ctrl-Z forked somewhere in the past, we are the child, |
2354 | * and now we completed running the list. Exit. */ | 2318 | * and now we completed running the list. Exit. */ |
2355 | //TODO: _exit? | 2319 | //TODO: _exit? |
2356 | exit(rcode); | 2320 | exit(rcode); |
2357 | } | 2321 | } |
2358 | ret: | 2322 | ret: |
2359 | if (!--run_list_level && interactive_fd) { | 2323 | if (!--G.run_list_level && G.interactive_fd) { |
2360 | signal(SIGTSTP, SIG_IGN); | 2324 | signal(SIGTSTP, SIG_IGN); |
2361 | signal(SIGINT, SIG_IGN); | 2325 | signal(SIGINT, SIG_IGN); |
2362 | } | 2326 | } |
2363 | #endif | 2327 | #endif |
2364 | debug_printf_exec("run_list lvl %d return %d\n", run_list_level + 1, rcode); | 2328 | debug_printf_exec("run_list lvl %d return %d\n", G.run_list_level + 1, rcode); |
2365 | #if ENABLE_HUSH_LOOPS | 2329 | #if ENABLE_HUSH_LOOPS |
2366 | if (loop_top) | 2330 | if (loop_top) |
2367 | depth_of_loop--; | 2331 | G.depth_of_loop--; |
2368 | free(for_list); | 2332 | free(for_list); |
2369 | #endif | 2333 | #endif |
2370 | #if ENABLE_HUSH_CASE | 2334 | #if ENABLE_HUSH_CASE |
@@ -2449,7 +2413,7 @@ static int run_and_free_list(struct pipe *pi) | |||
2449 | { | 2413 | { |
2450 | int rcode = 0; | 2414 | int rcode = 0; |
2451 | debug_printf_exec("run_and_free_list entered\n"); | 2415 | debug_printf_exec("run_and_free_list entered\n"); |
2452 | if (!fake_mode) { | 2416 | if (!G.fake_mode) { |
2453 | debug_printf_exec(": run_list with %d members\n", pi->num_progs); | 2417 | debug_printf_exec(": run_list with %d members\n", pi->num_progs); |
2454 | rcode = run_list(pi); | 2418 | rcode = run_list(pi); |
2455 | } | 2419 | } |
@@ -2472,12 +2436,12 @@ static int run_and_free_list(struct pipe *pi) | |||
2472 | * Caller can deallocate entire list by single free(list). */ | 2436 | * Caller can deallocate entire list by single free(list). */ |
2473 | 2437 | ||
2474 | /* Store given string, finalizing the word and starting new one whenever | 2438 | /* Store given string, finalizing the word and starting new one whenever |
2475 | * we encounter ifs char(s). This is used for expanding variable values. | 2439 | * we encounter IFS char(s). This is used for expanding variable values. |
2476 | * End-of-string does NOT finalize word: think about 'echo -$VAR-' */ | 2440 | * End-of-string does NOT finalize word: think about 'echo -$VAR-' */ |
2477 | static int expand_on_ifs(o_string *output, int n, const char *str) | 2441 | static int expand_on_ifs(o_string *output, int n, const char *str) |
2478 | { | 2442 | { |
2479 | while (1) { | 2443 | while (1) { |
2480 | int word_len = strcspn(str, ifs); | 2444 | int word_len = strcspn(str, G.ifs); |
2481 | if (word_len) { | 2445 | if (word_len) { |
2482 | if (output->o_quote || !output->o_glob) | 2446 | if (output->o_quote || !output->o_glob) |
2483 | o_addQstr(output, str, word_len); | 2447 | o_addQstr(output, str, word_len); |
@@ -2490,7 +2454,7 @@ static int expand_on_ifs(o_string *output, int n, const char *str) | |||
2490 | o_addchr(output, '\0'); | 2454 | o_addchr(output, '\0'); |
2491 | debug_print_list("expand_on_ifs", output, n); | 2455 | debug_print_list("expand_on_ifs", output, n); |
2492 | n = o_save_ptr(output, n); | 2456 | n = o_save_ptr(output, n); |
2493 | str += strspn(str, ifs); /* skip ifs chars */ | 2457 | str += strspn(str, G.ifs); /* skip ifs chars */ |
2494 | } | 2458 | } |
2495 | debug_print_list("expand_on_ifs[1]", output, n); | 2459 | debug_print_list("expand_on_ifs[1]", output, n); |
2496 | return n; | 2460 | return n; |
@@ -2540,31 +2504,31 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
2540 | switch (first_ch & 0x7f) { | 2504 | switch (first_ch & 0x7f) { |
2541 | /* Highest bit in first_ch indicates that var is double-quoted */ | 2505 | /* Highest bit in first_ch indicates that var is double-quoted */ |
2542 | case '$': /* pid */ | 2506 | case '$': /* pid */ |
2543 | val = utoa(root_pid); | 2507 | val = utoa(G.root_pid); |
2544 | break; | 2508 | break; |
2545 | case '!': /* bg pid */ | 2509 | case '!': /* bg pid */ |
2546 | val = last_bg_pid ? utoa(last_bg_pid) : (char*)""; | 2510 | val = G.last_bg_pid ? utoa(G.last_bg_pid) : (char*)""; |
2547 | break; | 2511 | break; |
2548 | case '?': /* exitcode */ | 2512 | case '?': /* exitcode */ |
2549 | val = utoa(last_return_code); | 2513 | val = utoa(G.last_return_code); |
2550 | break; | 2514 | break; |
2551 | case '#': /* argc */ | 2515 | case '#': /* argc */ |
2552 | val = utoa(global_argc ? global_argc-1 : 0); | 2516 | val = utoa(G.global_argc ? G.global_argc-1 : 0); |
2553 | break; | 2517 | break; |
2554 | case '*': | 2518 | case '*': |
2555 | case '@': | 2519 | case '@': |
2556 | i = 1; | 2520 | i = 1; |
2557 | if (!global_argv[i]) | 2521 | if (!G.global_argv[i]) |
2558 | break; | 2522 | break; |
2559 | ored_ch |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ | 2523 | ored_ch |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ |
2560 | if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ | 2524 | if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ |
2561 | smallint sv = output->o_quote; | 2525 | smallint sv = output->o_quote; |
2562 | /* unquoted var's contents should be globbed, so don't quote */ | 2526 | /* unquoted var's contents should be globbed, so don't quote */ |
2563 | output->o_quote = 0; | 2527 | output->o_quote = 0; |
2564 | while (global_argv[i]) { | 2528 | while (G.global_argv[i]) { |
2565 | n = expand_on_ifs(output, n, global_argv[i]); | 2529 | n = expand_on_ifs(output, n, G.global_argv[i]); |
2566 | debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, global_argc-1); | 2530 | debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1); |
2567 | if (global_argv[i++][0] && global_argv[i]) { | 2531 | if (G.global_argv[i++][0] && G.global_argv[i]) { |
2568 | /* this argv[] is not empty and not last: | 2532 | /* this argv[] is not empty and not last: |
2569 | * put terminating NUL, start new word */ | 2533 | * put terminating NUL, start new word */ |
2570 | o_addchr(output, '\0'); | 2534 | o_addchr(output, '\0'); |
@@ -2579,8 +2543,8 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
2579 | * and in this case should treat it like '$*' - see 'else...' below */ | 2543 | * and in this case should treat it like '$*' - see 'else...' below */ |
2580 | if (first_ch == ('@'|0x80) && !or_mask) { /* quoted $@ */ | 2544 | if (first_ch == ('@'|0x80) && !or_mask) { /* quoted $@ */ |
2581 | while (1) { | 2545 | while (1) { |
2582 | o_addQstr(output, global_argv[i], strlen(global_argv[i])); | 2546 | o_addQstr(output, G.global_argv[i], strlen(G.global_argv[i])); |
2583 | if (++i >= global_argc) | 2547 | if (++i >= G.global_argc) |
2584 | break; | 2548 | break; |
2585 | o_addchr(output, '\0'); | 2549 | o_addchr(output, '\0'); |
2586 | debug_print_list("expand_vars_to_list[4]", output, n); | 2550 | debug_print_list("expand_vars_to_list[4]", output, n); |
@@ -2588,11 +2552,11 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
2588 | } | 2552 | } |
2589 | } else { /* quoted $*: add as one word */ | 2553 | } else { /* quoted $*: add as one word */ |
2590 | while (1) { | 2554 | while (1) { |
2591 | o_addQstr(output, global_argv[i], strlen(global_argv[i])); | 2555 | o_addQstr(output, G.global_argv[i], strlen(G.global_argv[i])); |
2592 | if (!global_argv[++i]) | 2556 | if (!G.global_argv[++i]) |
2593 | break; | 2557 | break; |
2594 | if (ifs[0]) | 2558 | if (G.ifs[0]) |
2595 | o_addchr(output, ifs[0]); | 2559 | o_addchr(output, G.ifs[0]); |
2596 | } | 2560 | } |
2597 | } | 2561 | } |
2598 | break; | 2562 | break; |
@@ -2620,8 +2584,8 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
2620 | arg[0] = first_ch & 0x7f; | 2584 | arg[0] = first_ch & 0x7f; |
2621 | if (isdigit(arg[0])) { | 2585 | if (isdigit(arg[0])) { |
2622 | i = xatoi_u(arg); | 2586 | i = xatoi_u(arg); |
2623 | if (i < global_argc) | 2587 | if (i < G.global_argc) |
2624 | val = global_argv[i]; | 2588 | val = G.global_argv[i]; |
2625 | /* else val remains NULL: $N with too big N */ | 2589 | /* else val remains NULL: $N with too big N */ |
2626 | } else | 2590 | } else |
2627 | val = lookup_param(arg); | 2591 | val = lookup_param(arg); |
@@ -2736,7 +2700,7 @@ static char* expand_strvec_to_string(char **argv) | |||
2736 | if (HUSH_DEBUG) | 2700 | if (HUSH_DEBUG) |
2737 | if (list[n-1] + strlen(list[n-1]) + 1 != list[n]) | 2701 | if (list[n-1] + strlen(list[n-1]) + 1 != list[n]) |
2738 | bb_error_msg_and_die("BUG in varexp3"); | 2702 | bb_error_msg_and_die("BUG in varexp3"); |
2739 | list[n][-1] = ' '; /* TODO: or to ifs[0]? */ | 2703 | list[n][-1] = ' '; /* TODO: or to G.ifs[0]? */ |
2740 | n++; | 2704 | n++; |
2741 | } | 2705 | } |
2742 | } | 2706 | } |
@@ -2755,7 +2719,7 @@ static struct variable *get_local_var(const char *name) | |||
2755 | if (!name) | 2719 | if (!name) |
2756 | return NULL; | 2720 | return NULL; |
2757 | len = strlen(name); | 2721 | len = strlen(name); |
2758 | for (cur = top_var; cur; cur = cur->next) { | 2722 | for (cur = G.top_var; cur; cur = cur->next) { |
2759 | if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=') | 2723 | if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=') |
2760 | return cur; | 2724 | return cur; |
2761 | } | 2725 | } |
@@ -2777,7 +2741,7 @@ static int set_local_var(char *str, int flg_export) | |||
2777 | } | 2741 | } |
2778 | 2742 | ||
2779 | name_len = value - str + 1; /* including '=' */ | 2743 | name_len = value - str + 1; /* including '=' */ |
2780 | cur = top_var; /* cannot be NULL (we have HUSH_VERSION and it's RO) */ | 2744 | cur = G.top_var; /* cannot be NULL (we have HUSH_VERSION and it's RO) */ |
2781 | while (1) { | 2745 | while (1) { |
2782 | if (strncmp(cur->varstr, str, name_len) != 0) { | 2746 | if (strncmp(cur->varstr, str, name_len) != 0) { |
2783 | if (!cur->next) { | 2747 | if (!cur->next) { |
@@ -2838,7 +2802,7 @@ static void unset_local_var(const char *name) | |||
2838 | if (!name) | 2802 | if (!name) |
2839 | return; | 2803 | return; |
2840 | name_len = strlen(name); | 2804 | name_len = strlen(name); |
2841 | cur = top_var; | 2805 | cur = G.top_var; |
2842 | while (cur) { | 2806 | while (cur) { |
2843 | if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') { | 2807 | if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') { |
2844 | if (cur->flg_read_only) { | 2808 | if (cur->flg_read_only) { |
@@ -3319,7 +3283,7 @@ static FILE *generate_stream_from_list(struct pipe *head) | |||
3319 | xmove_fd(channel[1], 1); | 3283 | xmove_fd(channel[1], 1); |
3320 | /* Prevent it from trying to handle ctrl-z etc */ | 3284 | /* Prevent it from trying to handle ctrl-z etc */ |
3321 | #if ENABLE_HUSH_JOB | 3285 | #if ENABLE_HUSH_JOB |
3322 | run_list_level = 1; | 3286 | G.run_list_level = 1; |
3323 | #endif | 3287 | #endif |
3324 | /* Process substitution is not considered to be usual | 3288 | /* Process substitution is not considered to be usual |
3325 | * 'command execution'. | 3289 | * 'command execution'. |
@@ -3654,7 +3618,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx, | |||
3654 | next = '\0'; | 3618 | next = '\0'; |
3655 | ch = i_getch(input); | 3619 | ch = i_getch(input); |
3656 | if (ch != EOF) { | 3620 | if (ch != EOF) { |
3657 | m = charmap[ch]; | 3621 | m = G.charmap[ch]; |
3658 | if (ch != '\n') { | 3622 | if (ch != '\n') { |
3659 | next = i_peek(input); | 3623 | next = i_peek(input); |
3660 | } | 3624 | } |
@@ -3915,29 +3879,28 @@ static int parse_stream(o_string *dest, struct p_context *ctx, | |||
3915 | static void set_in_charmap(const char *set, int code) | 3879 | static void set_in_charmap(const char *set, int code) |
3916 | { | 3880 | { |
3917 | while (*set) | 3881 | while (*set) |
3918 | charmap[(unsigned char)*set++] = code; | 3882 | G.charmap[(unsigned char)*set++] = code; |
3919 | } | 3883 | } |
3920 | 3884 | ||
3921 | static void update_charmap(void) | 3885 | static void update_charmap(void) |
3922 | { | 3886 | { |
3923 | /* char *ifs and char charmap[256] are both globals. */ | 3887 | G.ifs = getenv("IFS"); |
3924 | ifs = getenv("IFS"); | 3888 | if (G.ifs == NULL) |
3925 | if (ifs == NULL) | 3889 | G.ifs = " \t\n"; |
3926 | ifs = " \t\n"; | ||
3927 | /* Precompute a list of 'flow through' behavior so it can be treated | 3890 | /* Precompute a list of 'flow through' behavior so it can be treated |
3928 | * quickly up front. Computation is necessary because of IFS. | 3891 | * quickly up front. Computation is necessary because of IFS. |
3929 | * Special case handling of IFS == " \t\n" is not implemented. | 3892 | * Special case handling of IFS == " \t\n" is not implemented. |
3930 | * The charmap[] array only really needs two bits each, | 3893 | * The charmap[] array only really needs two bits each, |
3931 | * and on most machines that would be faster (reduced L1 cache use). | 3894 | * and on most machines that would be faster (reduced L1 cache use). |
3932 | */ | 3895 | */ |
3933 | memset(charmap, CHAR_ORDINARY, sizeof(charmap)); | 3896 | memset(G.charmap, CHAR_ORDINARY, sizeof(G.charmap)); |
3934 | #if ENABLE_HUSH_TICK | 3897 | #if ENABLE_HUSH_TICK |
3935 | set_in_charmap("\\$\"`", CHAR_SPECIAL); | 3898 | set_in_charmap("\\$\"`", CHAR_SPECIAL); |
3936 | #else | 3899 | #else |
3937 | set_in_charmap("\\$\"", CHAR_SPECIAL); | 3900 | set_in_charmap("\\$\"", CHAR_SPECIAL); |
3938 | #endif | 3901 | #endif |
3939 | set_in_charmap("<>;&|(){}#'", CHAR_ORDINARY_IF_QUOTED); | 3902 | set_in_charmap("<>;&|(){}#'", CHAR_ORDINARY_IF_QUOTED); |
3940 | set_in_charmap(ifs, CHAR_IFS); /* are ordinary if quoted */ | 3903 | set_in_charmap(G.ifs, CHAR_IFS); /* are ordinary if quoted */ |
3941 | } | 3904 | } |
3942 | 3905 | ||
3943 | /* Most recursion does not come through here, the exception is | 3906 | /* Most recursion does not come through here, the exception is |
@@ -4016,13 +3979,14 @@ static void setup_job_control(void) | |||
4016 | { | 3979 | { |
4017 | pid_t shell_pgrp; | 3980 | pid_t shell_pgrp; |
4018 | 3981 | ||
4019 | saved_task_pgrp = shell_pgrp = getpgrp(); | 3982 | // G.saved_task_pgrp = |
4020 | debug_printf_jobs("saved_task_pgrp=%d\n", saved_task_pgrp); | 3983 | shell_pgrp = getpgrp(); |
4021 | close_on_exec_on(interactive_fd); | 3984 | // debug_printf_jobs("saved_task_pgrp=%d\n", G.saved_task_pgrp); |
3985 | close_on_exec_on(G.interactive_fd); | ||
4022 | 3986 | ||
4023 | /* If we were ran as 'hush &', | 3987 | /* If we were ran as 'hush &', |
4024 | * sleep until we are in the foreground. */ | 3988 | * sleep until we are in the foreground. */ |
4025 | while (tcgetpgrp(interactive_fd) != shell_pgrp) { | 3989 | while (tcgetpgrp(G.interactive_fd) != shell_pgrp) { |
4026 | /* Send TTIN to ourself (should stop us) */ | 3990 | /* Send TTIN to ourself (should stop us) */ |
4027 | kill(- shell_pgrp, SIGTTIN); | 3991 | kill(- shell_pgrp, SIGTTIN); |
4028 | shell_pgrp = getpgrp(); | 3992 | shell_pgrp = getpgrp(); |
@@ -4039,7 +4003,7 @@ static void setup_job_control(void) | |||
4039 | /* Put ourselves in our own process group. */ | 4003 | /* Put ourselves in our own process group. */ |
4040 | setpgrp(); /* is the same as setpgid(our_pid, our_pid); */ | 4004 | setpgrp(); /* is the same as setpgid(our_pid, our_pid); */ |
4041 | /* Grab control of the terminal. */ | 4005 | /* Grab control of the terminal. */ |
4042 | tcsetpgrp(interactive_fd, getpid()); | 4006 | tcsetpgrp(G.interactive_fd, getpid()); |
4043 | } | 4007 | } |
4044 | #endif | 4008 | #endif |
4045 | 4009 | ||
@@ -4063,15 +4027,15 @@ int hush_main(int argc, char **argv) | |||
4063 | 4027 | ||
4064 | INIT_G(); | 4028 | INIT_G(); |
4065 | 4029 | ||
4066 | root_pid = getpid(); | 4030 | G.root_pid = getpid(); |
4067 | 4031 | ||
4068 | /* Deal with HUSH_VERSION */ | 4032 | /* Deal with HUSH_VERSION */ |
4069 | shell_ver = const_shell_ver; /* copying struct here */ | 4033 | G.shell_ver = const_shell_ver; /* copying struct here */ |
4070 | top_var = &shell_ver; | 4034 | G.top_var = &G.shell_ver; |
4071 | unsetenv("HUSH_VERSION"); /* in case it exists in initial env */ | 4035 | unsetenv("HUSH_VERSION"); /* in case it exists in initial env */ |
4072 | /* Initialize our shell local variables with the values | 4036 | /* Initialize our shell local variables with the values |
4073 | * currently living in the environment */ | 4037 | * currently living in the environment */ |
4074 | cur_var = top_var; | 4038 | cur_var = G.top_var; |
4075 | e = environ; | 4039 | e = environ; |
4076 | if (e) while (*e) { | 4040 | if (e) while (*e) { |
4077 | char *value = strchr(*e, '='); | 4041 | char *value = strchr(*e, '='); |
@@ -4087,22 +4051,22 @@ int hush_main(int argc, char **argv) | |||
4087 | putenv((char *)version_str); /* reinstate HUSH_VERSION */ | 4051 | putenv((char *)version_str); /* reinstate HUSH_VERSION */ |
4088 | 4052 | ||
4089 | #if ENABLE_FEATURE_EDITING | 4053 | #if ENABLE_FEATURE_EDITING |
4090 | line_input_state = new_line_input_t(FOR_SHELL); | 4054 | G.line_input_state = new_line_input_t(FOR_SHELL); |
4091 | #endif | 4055 | #endif |
4092 | /* XXX what should these be while sourcing /etc/profile? */ | 4056 | /* XXX what should these be while sourcing /etc/profile? */ |
4093 | global_argc = argc; | 4057 | G.global_argc = argc; |
4094 | global_argv = argv; | 4058 | G.global_argv = argv; |
4095 | /* Initialize some more globals to non-zero values */ | 4059 | /* Initialize some more globals to non-zero values */ |
4096 | set_cwd(); | 4060 | set_cwd(); |
4097 | #if ENABLE_HUSH_INTERACTIVE | 4061 | #if ENABLE_HUSH_INTERACTIVE |
4098 | #if ENABLE_FEATURE_EDITING | 4062 | #if ENABLE_FEATURE_EDITING |
4099 | cmdedit_set_initial_prompt(); | 4063 | cmdedit_set_initial_prompt(); |
4100 | #endif | 4064 | #endif |
4101 | PS2 = "> "; | 4065 | G.PS2 = "> "; |
4102 | #endif | 4066 | #endif |
4103 | 4067 | ||
4104 | if (EXIT_SUCCESS) /* otherwise is already done */ | 4068 | if (EXIT_SUCCESS) /* otherwise is already done */ |
4105 | last_return_code = EXIT_SUCCESS; | 4069 | G.last_return_code = EXIT_SUCCESS; |
4106 | 4070 | ||
4107 | if (argv[0] && argv[0][0] == '-') { | 4071 | if (argv[0] && argv[0][0] == '-') { |
4108 | debug_printf("sourcing /etc/profile\n"); | 4072 | debug_printf("sourcing /etc/profile\n"); |
@@ -4118,17 +4082,17 @@ int hush_main(int argc, char **argv) | |||
4118 | while ((opt = getopt(argc, argv, "c:xif")) > 0) { | 4082 | while ((opt = getopt(argc, argv, "c:xif")) > 0) { |
4119 | switch (opt) { | 4083 | switch (opt) { |
4120 | case 'c': | 4084 | case 'c': |
4121 | global_argv = argv + optind; | 4085 | G.global_argv = argv + optind; |
4122 | global_argc = argc - optind; | 4086 | G.global_argc = argc - optind; |
4123 | opt = parse_and_run_string(optarg, 0 /* parse_flag */); | 4087 | opt = parse_and_run_string(optarg, 0 /* parse_flag */); |
4124 | goto final_return; | 4088 | goto final_return; |
4125 | case 'i': | 4089 | case 'i': |
4126 | /* Well, we cannot just declare interactiveness, | 4090 | /* Well, we cannot just declare interactiveness, |
4127 | * we have to have some stuff (ctty, etc) */ | 4091 | * we have to have some stuff (ctty, etc) */ |
4128 | /* interactive_fd++; */ | 4092 | /* G.interactive_fd++; */ |
4129 | break; | 4093 | break; |
4130 | case 'f': | 4094 | case 'f': |
4131 | fake_mode = 1; | 4095 | G.fake_mode = 1; |
4132 | break; | 4096 | break; |
4133 | default: | 4097 | default: |
4134 | #ifndef BB_VER | 4098 | #ifndef BB_VER |
@@ -4151,25 +4115,25 @@ int hush_main(int argc, char **argv) | |||
4151 | if (argv[optind] == NULL && input == stdin | 4115 | if (argv[optind] == NULL && input == stdin |
4152 | && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) | 4116 | && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) |
4153 | ) { | 4117 | ) { |
4154 | saved_tty_pgrp = tcgetpgrp(STDIN_FILENO); | 4118 | G.saved_tty_pgrp = tcgetpgrp(STDIN_FILENO); |
4155 | debug_printf("saved_tty_pgrp=%d\n", saved_tty_pgrp); | 4119 | debug_printf("saved_tty_pgrp=%d\n", G.saved_tty_pgrp); |
4156 | if (saved_tty_pgrp >= 0) { | 4120 | if (G.saved_tty_pgrp >= 0) { |
4157 | /* try to dup to high fd#, >= 255 */ | 4121 | /* try to dup to high fd#, >= 255 */ |
4158 | interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255); | 4122 | G.interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255); |
4159 | if (interactive_fd < 0) { | 4123 | if (G.interactive_fd < 0) { |
4160 | /* try to dup to any fd */ | 4124 | /* try to dup to any fd */ |
4161 | interactive_fd = dup(STDIN_FILENO); | 4125 | G.interactive_fd = dup(STDIN_FILENO); |
4162 | if (interactive_fd < 0) | 4126 | if (G.interactive_fd < 0) |
4163 | /* give up */ | 4127 | /* give up */ |
4164 | interactive_fd = 0; | 4128 | G.interactive_fd = 0; |
4165 | } | 4129 | } |
4166 | // TODO: track & disallow any attempts of user | 4130 | // TODO: track & disallow any attempts of user |
4167 | // to (inadvertently) close/redirect it | 4131 | // to (inadvertently) close/redirect it |
4168 | } | 4132 | } |
4169 | } | 4133 | } |
4170 | debug_printf("interactive_fd=%d\n", interactive_fd); | 4134 | debug_printf("G.interactive_fd=%d\n", G.interactive_fd); |
4171 | if (interactive_fd) { | 4135 | if (G.interactive_fd) { |
4172 | fcntl(interactive_fd, F_SETFD, FD_CLOEXEC); | 4136 | fcntl(G.interactive_fd, F_SETFD, FD_CLOEXEC); |
4173 | /* Looks like they want an interactive shell */ | 4137 | /* Looks like they want an interactive shell */ |
4174 | setup_job_control(); | 4138 | setup_job_control(); |
4175 | /* -1 is special - makes xfuncs longjmp, not exit | 4139 | /* -1 is special - makes xfuncs longjmp, not exit |
@@ -4189,16 +4153,16 @@ int hush_main(int argc, char **argv) | |||
4189 | if (argv[optind] == NULL && input == stdin | 4153 | if (argv[optind] == NULL && input == stdin |
4190 | && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) | 4154 | && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) |
4191 | ) { | 4155 | ) { |
4192 | interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255); | 4156 | G.interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255); |
4193 | if (interactive_fd < 0) { | 4157 | if (G.interactive_fd < 0) { |
4194 | /* try to dup to any fd */ | 4158 | /* try to dup to any fd */ |
4195 | interactive_fd = dup(STDIN_FILENO); | 4159 | G.interactive_fd = dup(STDIN_FILENO); |
4196 | if (interactive_fd < 0) | 4160 | if (G.interactive_fd < 0) |
4197 | /* give up */ | 4161 | /* give up */ |
4198 | interactive_fd = 0; | 4162 | G.interactive_fd = 0; |
4199 | } | 4163 | } |
4200 | if (interactive_fd) { | 4164 | if (G.interactive_fd) { |
4201 | fcntl(interactive_fd, F_SETFD, FD_CLOEXEC); | 4165 | fcntl(G.interactive_fd, F_SETFD, FD_CLOEXEC); |
4202 | set_misc_sighandler(SIG_IGN); | 4166 | set_misc_sighandler(SIG_IGN); |
4203 | } | 4167 | } |
4204 | } | 4168 | } |
@@ -4208,8 +4172,8 @@ int hush_main(int argc, char **argv) | |||
4208 | opt = parse_and_run_file(stdin); | 4172 | opt = parse_and_run_file(stdin); |
4209 | } else { | 4173 | } else { |
4210 | debug_printf("\nrunning script '%s'\n", argv[optind]); | 4174 | debug_printf("\nrunning script '%s'\n", argv[optind]); |
4211 | global_argv = argv + optind; | 4175 | G.global_argv = argv + optind; |
4212 | global_argc = argc - optind; | 4176 | G.global_argc = argc - optind; |
4213 | input = xfopen_for_read(argv[optind]); | 4177 | input = xfopen_for_read(argv[optind]); |
4214 | fcntl(fileno(input), F_SETFD, FD_CLOEXEC); | 4178 | fcntl(fileno(input), F_SETFD, FD_CLOEXEC); |
4215 | opt = parse_and_run_file(input); | 4179 | opt = parse_and_run_file(input); |
@@ -4219,9 +4183,9 @@ int hush_main(int argc, char **argv) | |||
4219 | 4183 | ||
4220 | #if ENABLE_FEATURE_CLEAN_UP | 4184 | #if ENABLE_FEATURE_CLEAN_UP |
4221 | fclose(input); | 4185 | fclose(input); |
4222 | if (cwd != bb_msg_unknown) | 4186 | if (G.cwd != bb_msg_unknown) |
4223 | free((char*)cwd); | 4187 | free((char*)G.cwd); |
4224 | cur_var = top_var->next; | 4188 | cur_var = G.top_var->next; |
4225 | while (cur_var) { | 4189 | while (cur_var) { |
4226 | struct variable *tmp = cur_var; | 4190 | struct variable *tmp = cur_var; |
4227 | if (!cur_var->max_len) | 4191 | if (!cur_var->max_len) |
@@ -4230,7 +4194,7 @@ int hush_main(int argc, char **argv) | |||
4230 | free(tmp); | 4194 | free(tmp); |
4231 | } | 4195 | } |
4232 | #endif | 4196 | #endif |
4233 | hush_exit(opt ? opt : last_return_code); | 4197 | hush_exit(opt ? opt : G.last_return_code); |
4234 | } | 4198 | } |
4235 | 4199 | ||
4236 | 4200 | ||
@@ -4280,7 +4244,7 @@ static int builtin_eval(char **argv) | |||
4280 | char *str = expand_strvec_to_string(argv + 1); | 4244 | char *str = expand_strvec_to_string(argv + 1); |
4281 | parse_and_run_string(str, PARSEFLAG_EXIT_FROM_LOOP); | 4245 | parse_and_run_string(str, PARSEFLAG_EXIT_FROM_LOOP); |
4282 | free(str); | 4246 | free(str); |
4283 | rcode = last_return_code; | 4247 | rcode = G.last_return_code; |
4284 | } | 4248 | } |
4285 | return rcode; | 4249 | return rcode; |
4286 | } | 4250 | } |
@@ -4323,7 +4287,7 @@ static int builtin_exit(char **argv) | |||
4323 | // TODO: warn if we have background jobs: "There are stopped jobs" | 4287 | // TODO: warn if we have background jobs: "There are stopped jobs" |
4324 | // On second consecutive 'exit', exit anyway. | 4288 | // On second consecutive 'exit', exit anyway. |
4325 | if (argv[1] == NULL) | 4289 | if (argv[1] == NULL) |
4326 | hush_exit(last_return_code); | 4290 | hush_exit(G.last_return_code); |
4327 | /* mimic bash: exit 123abc == exit 255 + error msg */ | 4291 | /* mimic bash: exit 123abc == exit 255 + error msg */ |
4328 | xfunc_error_retval = 255; | 4292 | xfunc_error_retval = 255; |
4329 | /* bash: exit -2 == exit 254, no error msg */ | 4293 | /* bash: exit -2 == exit 254, no error msg */ |
@@ -4373,12 +4337,12 @@ static int builtin_fg_bg(char **argv) | |||
4373 | int i, jobnum; | 4337 | int i, jobnum; |
4374 | struct pipe *pi; | 4338 | struct pipe *pi; |
4375 | 4339 | ||
4376 | if (!interactive_fd) | 4340 | if (!G.interactive_fd) |
4377 | return EXIT_FAILURE; | 4341 | return EXIT_FAILURE; |
4378 | /* If they gave us no args, assume they want the last backgrounded task */ | 4342 | /* If they gave us no args, assume they want the last backgrounded task */ |
4379 | if (!argv[1]) { | 4343 | if (!argv[1]) { |
4380 | for (pi = job_list; pi; pi = pi->next) { | 4344 | for (pi = G.job_list; pi; pi = pi->next) { |
4381 | if (pi->jobid == last_jobid) { | 4345 | if (pi->jobid == G.last_jobid) { |
4382 | goto found; | 4346 | goto found; |
4383 | } | 4347 | } |
4384 | } | 4348 | } |
@@ -4389,7 +4353,7 @@ static int builtin_fg_bg(char **argv) | |||
4389 | bb_error_msg("%s: bad argument '%s'", argv[0], argv[1]); | 4353 | bb_error_msg("%s: bad argument '%s'", argv[0], argv[1]); |
4390 | return EXIT_FAILURE; | 4354 | return EXIT_FAILURE; |
4391 | } | 4355 | } |
4392 | for (pi = job_list; pi; pi = pi->next) { | 4356 | for (pi = G.job_list; pi; pi = pi->next) { |
4393 | if (pi->jobid == jobnum) { | 4357 | if (pi->jobid == jobnum) { |
4394 | goto found; | 4358 | goto found; |
4395 | } | 4359 | } |
@@ -4401,7 +4365,7 @@ static int builtin_fg_bg(char **argv) | |||
4401 | // of job being foregrounded (like "sleep 1 | cat") | 4365 | // of job being foregrounded (like "sleep 1 | cat") |
4402 | if (*argv[0] == 'f') { | 4366 | if (*argv[0] == 'f') { |
4403 | /* Put the job into the foreground. */ | 4367 | /* Put the job into the foreground. */ |
4404 | tcsetpgrp(interactive_fd, pi->pgrp); | 4368 | tcsetpgrp(G.interactive_fd, pi->pgrp); |
4405 | } | 4369 | } |
4406 | 4370 | ||
4407 | /* Restart the processes in the job */ | 4371 | /* Restart the processes in the job */ |
@@ -4451,7 +4415,7 @@ static int builtin_jobs(char **argv UNUSED_PARAM) | |||
4451 | struct pipe *job; | 4415 | struct pipe *job; |
4452 | const char *status_string; | 4416 | const char *status_string; |
4453 | 4417 | ||
4454 | for (job = job_list; job; job = job->next) { | 4418 | for (job = G.job_list; job; job = job->next) { |
4455 | if (job->alive_progs == job->stopped_progs) | 4419 | if (job->alive_progs == job->stopped_progs) |
4456 | status_string = "Stopped"; | 4420 | status_string = "Stopped"; |
4457 | else | 4421 | else |
@@ -4485,7 +4449,7 @@ static int builtin_set(char **argv) | |||
4485 | struct variable *e; | 4449 | struct variable *e; |
4486 | 4450 | ||
4487 | if (temp == NULL) | 4451 | if (temp == NULL) |
4488 | for (e = top_var; e; e = e->next) | 4452 | for (e = G.top_var; e; e = e->next) |
4489 | puts(e->varstr); | 4453 | puts(e->varstr); |
4490 | else | 4454 | else |
4491 | set_local_var(xstrdup(temp), 0); | 4455 | set_local_var(xstrdup(temp), 0); |
@@ -4499,10 +4463,10 @@ static int builtin_shift(char **argv) | |||
4499 | if (argv[1]) { | 4463 | if (argv[1]) { |
4500 | n = atoi(argv[1]); | 4464 | n = atoi(argv[1]); |
4501 | } | 4465 | } |
4502 | if (n >= 0 && n < global_argc) { | 4466 | if (n >= 0 && n < G.global_argc) { |
4503 | global_argv[n] = global_argv[0]; | 4467 | G.global_argv[n] = G.global_argv[0]; |
4504 | global_argc -= n; | 4468 | G.global_argc -= n; |
4505 | global_argv += n; | 4469 | G.global_argv += n; |
4506 | return EXIT_SUCCESS; | 4470 | return EXIT_SUCCESS; |
4507 | } | 4471 | } |
4508 | return EXIT_FAILURE; | 4472 | return EXIT_FAILURE; |
@@ -4525,9 +4489,9 @@ static int builtin_source(char **argv) | |||
4525 | close_on_exec_on(fileno(input)); | 4489 | close_on_exec_on(fileno(input)); |
4526 | 4490 | ||
4527 | /* Now run the file */ | 4491 | /* Now run the file */ |
4528 | /* XXX argv and argc are broken; need to save old global_argv | 4492 | /* XXX argv and argc are broken; need to save old G.global_argv |
4529 | * (pointer only is OK!) on this stack frame, | 4493 | * (pointer only is OK!) on this stack frame, |
4530 | * set global_argv=argv+1, recurse, and restore. */ | 4494 | * set G.global_argv=argv+1, recurse, and restore. */ |
4531 | status = parse_and_run_file(input); | 4495 | status = parse_and_run_file(input); |
4532 | fclose(input); | 4496 | fclose(input); |
4533 | return status; | 4497 | return status; |
@@ -4561,29 +4525,29 @@ static int builtin_unset(char **argv) | |||
4561 | #if ENABLE_HUSH_LOOPS | 4525 | #if ENABLE_HUSH_LOOPS |
4562 | static int builtin_break(char **argv) | 4526 | static int builtin_break(char **argv) |
4563 | { | 4527 | { |
4564 | if (depth_of_loop == 0) { | 4528 | if (G.depth_of_loop == 0) { |
4565 | bb_error_msg("%s: only meaningful in a loop", "break"); | 4529 | bb_error_msg("%s: only meaningful in a loop", "break"); |
4566 | return EXIT_SUCCESS; /* bash compat */ | 4530 | return EXIT_SUCCESS; /* bash compat */ |
4567 | } | 4531 | } |
4568 | flag_break_continue++; /* BC_BREAK = 1 */ | 4532 | G.flag_break_continue++; /* BC_BREAK = 1 */ |
4569 | depth_break_continue = 1; | 4533 | G.depth_break_continue = 1; |
4570 | if (argv[1]) { | 4534 | if (argv[1]) { |
4571 | depth_break_continue = bb_strtou(argv[1], NULL, 10); | 4535 | G.depth_break_continue = bb_strtou(argv[1], NULL, 10); |
4572 | if (errno || !depth_break_continue || argv[2]) { | 4536 | if (errno || !G.depth_break_continue || argv[2]) { |
4573 | bb_error_msg("bad arguments"); | 4537 | bb_error_msg("bad arguments"); |
4574 | flag_break_continue = BC_BREAK; | 4538 | G.flag_break_continue = BC_BREAK; |
4575 | depth_break_continue = UINT_MAX; | 4539 | G.depth_break_continue = UINT_MAX; |
4576 | } | 4540 | } |
4577 | } | 4541 | } |
4578 | if (depth_of_loop < depth_break_continue) | 4542 | if (G.depth_of_loop < G.depth_break_continue) |
4579 | depth_break_continue = depth_of_loop; | 4543 | G.depth_break_continue = G.depth_of_loop; |
4580 | return EXIT_SUCCESS; | 4544 | return EXIT_SUCCESS; |
4581 | } | 4545 | } |
4582 | 4546 | ||
4583 | static int builtin_continue(char **argv) | 4547 | static int builtin_continue(char **argv) |
4584 | { | 4548 | { |
4585 | if (depth_of_loop) { | 4549 | if (G.depth_of_loop) { |
4586 | flag_break_continue++; /* BC_CONTINUE = 2 = 1+1 */ | 4550 | G.flag_break_continue = 1; /* BC_CONTINUE = 2 = 1+1 */ |
4587 | return builtin_break(argv); | 4551 | return builtin_break(argv); |
4588 | } | 4552 | } |
4589 | bb_error_msg("%s: only meaningful in a loop", "continue"); | 4553 | bb_error_msg("%s: only meaningful in a loop", "continue"); |