aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-07-29 19:43:10 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-07-29 19:43:10 +0000
commit87a8655f4600cdad2b9af3312084a83e619c9abd (patch)
treed7086c732732d0bfacd18efdbf7b3a55b952a055
parentff29b4fc42f723b451ce20ea3db8b43409470e82 (diff)
downloadbusybox-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.
-rw-r--r--shell/hush.c432
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
469enum { interactive_fd = 0 }; 469 * is global, thus "G." prefix is a useful hint */
470#endif
471#if !ENABLE_HUSH_JOB
472enum { 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 */
523static void syntax(const char *msg) 479static 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 */
536static void syntax_lineno(int line) 495static 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
850static void handler_ctrl_z(int sig UNUSED_PARAM) 812static 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
920static const char *set_cwd(void) 884static 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)
1224static void cmdedit_set_initial_prompt(void) 1188static 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
1598static void remove_bg_job(struct pipe *pi) 1562static 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-' */
2477static int expand_on_ifs(o_string *output, int n, const char *str) 2441static 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,
3915static void set_in_charmap(const char *set, int code) 3879static 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
3921static void update_charmap(void) 3885static 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
4562static int builtin_break(char **argv) 4526static 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
4583static int builtin_continue(char **argv) 4547static 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");