diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-17 15:38:46 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-17 15:38:46 +0000 |
commit | c8be5ee325a374525f503d11eccb5da3ee35a509 (patch) | |
tree | 0d2e996f0222c828da06bbbe25d32098aaa18dfa /shell/hush.c | |
parent | b6a741ffa7be0926049c663e218864288e9161c1 (diff) | |
download | busybox-w32-c8be5ee325a374525f503d11eccb5da3ee35a509.tar.gz busybox-w32-c8be5ee325a374525f503d11eccb5da3ee35a509.tar.bz2 busybox-w32-c8be5ee325a374525f503d11eccb5da3ee35a509.zip |
hush: do "struct globals" trick. hush.o data+bss = 0 bytes now.
+60 bytes to image, but -8000 bytes in bss.
Diffstat (limited to 'shell/hush.c')
-rw-r--r-- | shell/hush.c | 239 |
1 files changed, 134 insertions, 105 deletions
diff --git a/shell/hush.c b/shell/hush.c index 9f0cc641e..a462090c6 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -81,6 +81,7 @@ | |||
81 | #include <glob.h> /* glob, of course */ | 81 | #include <glob.h> /* glob, of course */ |
82 | #include <getopt.h> /* should be pretty obvious */ | 82 | #include <getopt.h> /* should be pretty obvious */ |
83 | /* #include <dmalloc.h> */ | 83 | /* #include <dmalloc.h> */ |
84 | extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */ | ||
84 | 85 | ||
85 | 86 | ||
86 | /* If you comment out one of these below, it will be #defined later | 87 | /* If you comment out one of these below, it will be #defined later |
@@ -273,49 +274,6 @@ struct variables { | |||
273 | int flg_read_only; | 274 | int flg_read_only; |
274 | }; | 275 | }; |
275 | 276 | ||
276 | /* globals, connect us to the outside world | ||
277 | * the first three support $?, $#, and $1 */ | ||
278 | static char **global_argv; | ||
279 | static int global_argc; | ||
280 | static int last_return_code; | ||
281 | extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */ | ||
282 | |||
283 | /* "globals" within this file */ | ||
284 | enum { | ||
285 | CHAR_ORDINARY = 0, | ||
286 | CHAR_ORDINARY_IF_QUOTED = 1, /* example: *, # */ | ||
287 | CHAR_IFS = 2, /* treated as ordinary if quoted */ | ||
288 | CHAR_SPECIAL = 3, /* example: $ */ | ||
289 | }; | ||
290 | static unsigned char charmap[256]; | ||
291 | static const char *ifs; | ||
292 | static int fake_mode; | ||
293 | static struct close_me *close_me_head; | ||
294 | static const char *cwd; | ||
295 | static unsigned last_bg_pid; | ||
296 | #if !ENABLE_HUSH_INTERACTIVE | ||
297 | enum { interactive_fd = 0 }; | ||
298 | #else | ||
299 | /* 'interactive_fd' is a fd# open to ctty, if we have one | ||
300 | * _AND_ if we decided to act interactively */ | ||
301 | static int interactive_fd; | ||
302 | #if ENABLE_HUSH_JOB | ||
303 | static pid_t saved_task_pgrp; | ||
304 | static pid_t saved_tty_pgrp; | ||
305 | static int last_jobid; | ||
306 | static struct pipe *job_list; | ||
307 | #endif | ||
308 | static const char *PS1; | ||
309 | static const char *PS2; | ||
310 | #endif | ||
311 | |||
312 | #define HUSH_VER_STR "0.02" | ||
313 | static struct variables shell_ver = { NULL, "HUSH_VERSION", HUSH_VER_STR, 1, 1 }; | ||
314 | static struct variables *top_vars = &shell_ver; | ||
315 | |||
316 | #define B_CHUNK 100 | ||
317 | #define B_NOSPAC 1 | ||
318 | |||
319 | typedef struct { | 277 | typedef struct { |
320 | char *data; | 278 | char *data; |
321 | int length; | 279 | int length; |
@@ -324,8 +282,7 @@ typedef struct { | |||
324 | int nonnull; | 282 | int nonnull; |
325 | } o_string; | 283 | } o_string; |
326 | #define NULL_O_STRING {NULL,0,0,0,0} | 284 | #define NULL_O_STRING {NULL,0,0,0,0} |
327 | /* used for initialization: | 285 | /* used for initialization: o_string foo = NULL_O_STRING; */ |
328 | o_string foo = NULL_O_STRING; */ | ||
329 | 286 | ||
330 | /* I can almost use ordinary FILE *. Is open_memstream() universally | 287 | /* I can almost use ordinary FILE *. Is open_memstream() universally |
331 | * available? Where is it documented? */ | 288 | * available? Where is it documented? */ |
@@ -345,14 +302,114 @@ struct in_str { | |||
345 | #define b_getch(input) ((input)->get(input)) | 302 | #define b_getch(input) ((input)->get(input)) |
346 | #define b_peek(input) ((input)->peek(input)) | 303 | #define b_peek(input) ((input)->peek(input)) |
347 | 304 | ||
348 | #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" | 305 | enum { |
306 | CHAR_ORDINARY = 0, | ||
307 | CHAR_ORDINARY_IF_QUOTED = 1, /* example: *, # */ | ||
308 | CHAR_IFS = 2, /* treated as ordinary if quoted */ | ||
309 | CHAR_SPECIAL = 3, /* example: $ */ | ||
310 | }; | ||
349 | 311 | ||
350 | struct built_in_command { | 312 | |
351 | const char *cmd; /* name */ | 313 | /* "Globals" within this file */ |
352 | const char *descr; /* description */ | 314 | |
353 | int (*function) (char **argv); /* function ptr */ | 315 | #define HUSH_VER_STR "0.02" |
316 | static const struct variables const_shell_ver = { | ||
317 | NULL, "HUSH_VERSION", HUSH_VER_STR, 1, 1 | ||
318 | }; | ||
319 | |||
320 | /* Sorted roughly by size (smaller offsets == smaller code) */ | ||
321 | struct globals { | ||
322 | #if ENABLE_HUSH_INTERACTIVE | ||
323 | /* 'interactive_fd' is a fd# open to ctty, if we have one | ||
324 | * _AND_ if we decided to act interactively */ | ||
325 | int interactive_fd; | ||
326 | const char *PS1; | ||
327 | const char *PS2; | ||
328 | #endif | ||
329 | #if ENABLE_FEATURE_EDITING | ||
330 | line_input_t *line_input_state; | ||
331 | #endif | ||
332 | #if ENABLE_HUSH_JOB | ||
333 | int run_list_level; | ||
334 | pid_t saved_task_pgrp; | ||
335 | pid_t saved_tty_pgrp; | ||
336 | int last_jobid; | ||
337 | struct pipe *job_list; | ||
338 | struct pipe *toplevel_list; | ||
339 | smallint ctrl_z_flag; | ||
340 | #endif | ||
341 | smallint fake_mode; | ||
342 | /* these three support $?, $#, and $1 */ | ||
343 | char **global_argv; | ||
344 | int global_argc; | ||
345 | int last_return_code; | ||
346 | const char *ifs; | ||
347 | struct close_me *close_me_head; | ||
348 | const char *cwd; | ||
349 | unsigned last_bg_pid; | ||
350 | struct variables *top_vars; /* = &shell_ver (both are set in main()) */ | ||
351 | struct variables shell_ver; /* = const_shell_ver */ | ||
352 | #if ENABLE_FEATURE_SH_STANDALONE | ||
353 | struct nofork_save_area nofork_save; | ||
354 | #endif | ||
355 | #if ENABLE_HUSH_JOB | ||
356 | sigjmp_buf toplevel_jb; | ||
357 | #endif | ||
358 | unsigned char charmap[256]; | ||
359 | char user_input_buf[ENABLE_FEATURE_EDITING ? BUFSIZ : 2]; | ||
354 | }; | 360 | }; |
355 | 361 | ||
362 | #define G (*ptr_to_globals) | ||
363 | |||
364 | #if !ENABLE_HUSH_INTERACTIVE | ||
365 | enum { interactive_fd = 0 }; | ||
366 | #endif | ||
367 | #if !ENABLE_HUSH_JOB | ||
368 | enum { run_list_level = 0 }; | ||
369 | #endif | ||
370 | |||
371 | #if ENABLE_HUSH_INTERACTIVE | ||
372 | #define interactive_fd (G.interactive_fd ) | ||
373 | #define PS1 (G.PS1 ) | ||
374 | #define PS2 (G.PS2 ) | ||
375 | #endif | ||
376 | #if ENABLE_FEATURE_EDITING | ||
377 | #define line_input_state (G.line_input_state) | ||
378 | #endif | ||
379 | #if ENABLE_HUSH_JOB | ||
380 | #define run_list_level (G.run_list_level ) | ||
381 | #define saved_task_pgrp (G.saved_task_pgrp ) | ||
382 | #define saved_tty_pgrp (G.saved_tty_pgrp ) | ||
383 | #define last_jobid (G.last_jobid ) | ||
384 | #define job_list (G.job_list ) | ||
385 | #define toplevel_list (G.toplevel_list ) | ||
386 | #define toplevel_jb (G.toplevel_jb ) | ||
387 | #define ctrl_z_flag (G.ctrl_z_flag ) | ||
388 | #endif /* JOB */ | ||
389 | #define global_argv (G.global_argv ) | ||
390 | #define global_argc (G.global_argc ) | ||
391 | #define last_return_code (G.last_return_code) | ||
392 | #define ifs (G.ifs ) | ||
393 | #define fake_mode (G.fake_mode ) | ||
394 | #define close_me_head (G.close_me_head ) | ||
395 | #define cwd (G.cwd ) | ||
396 | #define last_bg_pid (G.last_bg_pid ) | ||
397 | #define top_vars (G.top_vars ) | ||
398 | #define shell_ver (G.shell_ver ) | ||
399 | #if ENABLE_FEATURE_SH_STANDALONE | ||
400 | #define nofork_save (G.nofork_save ) | ||
401 | #endif | ||
402 | #if ENABLE_HUSH_JOB | ||
403 | #define toplevel_jb (G.toplevel_jb ) | ||
404 | #endif | ||
405 | #define charmap (G.charmap ) | ||
406 | #define user_input_buf (G.user_input_buf ) | ||
407 | |||
408 | |||
409 | #define B_CHUNK 100 | ||
410 | #define B_NOSPAC 1 | ||
411 | #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" | ||
412 | |||
356 | static void __syntax(int line) | 413 | static void __syntax(int line) |
357 | { | 414 | { |
358 | bb_error_msg("syntax error hush.c:%d", line); | 415 | bb_error_msg("syntax error hush.c:%d", line); |
@@ -457,6 +514,12 @@ static void unset_local_var(const char *name); | |||
457 | * in the parent shell process. If forked, of course they cannot. | 514 | * in the parent shell process. If forked, of course they cannot. |
458 | * For example, 'unset foo | whatever' will parse and run, but foo will | 515 | * For example, 'unset foo | whatever' will parse and run, but foo will |
459 | * still be set at the end. */ | 516 | * still be set at the end. */ |
517 | struct built_in_command { | ||
518 | const char *cmd; /* name */ | ||
519 | const char *descr; /* description */ | ||
520 | int (*function) (char **argv); /* function ptr */ | ||
521 | }; | ||
522 | |||
460 | static const struct built_in_command bltins[] = { | 523 | static const struct built_in_command bltins[] = { |
461 | #if ENABLE_HUSH_JOB | 524 | #if ENABLE_HUSH_JOB |
462 | { "bg", "Resume a job in the background", builtin_fg_bg }, | 525 | { "bg", "Resume a job in the background", builtin_fg_bg }, |
@@ -487,10 +550,6 @@ static const struct built_in_command bltins[] = { | |||
487 | { NULL, NULL, NULL } | 550 | { NULL, NULL, NULL } |
488 | }; | 551 | }; |
489 | 552 | ||
490 | #if ENABLE_FEATURE_SH_STANDALONE | ||
491 | struct nofork_save_area nofork_save; | ||
492 | #endif | ||
493 | |||
494 | #if ENABLE_HUSH_JOB | 553 | #if ENABLE_HUSH_JOB |
495 | 554 | ||
496 | /* move to libbb? */ | 555 | /* move to libbb? */ |
@@ -539,9 +598,6 @@ static void set_every_sighandler(void (*handler)(int)) | |||
539 | signal(SIGCHLD, handler); | 598 | signal(SIGCHLD, handler); |
540 | } | 599 | } |
541 | 600 | ||
542 | static struct pipe *toplevel_list; | ||
543 | static sigjmp_buf toplevel_jb; | ||
544 | smallint ctrl_z_flag; | ||
545 | static void handler_ctrl_c(int sig) | 601 | static void handler_ctrl_c(int sig) |
546 | { | 602 | { |
547 | debug_printf_jobs("got sig %d\n", sig); | 603 | debug_printf_jobs("got sig %d\n", sig); |
@@ -1062,14 +1118,8 @@ static const char* setup_prompt_string(int promptmode) | |||
1062 | return prompt_str; | 1118 | return prompt_str; |
1063 | } | 1119 | } |
1064 | 1120 | ||
1065 | #if ENABLE_FEATURE_EDITING | ||
1066 | static line_input_t *line_input_state; | ||
1067 | #endif | ||
1068 | |||
1069 | static void get_user_input(struct in_str *i) | 1121 | static void get_user_input(struct in_str *i) |
1070 | { | 1122 | { |
1071 | static char the_command[ENABLE_FEATURE_EDITING ? BUFSIZ : 2]; | ||
1072 | |||
1073 | int r; | 1123 | int r; |
1074 | const char *prompt_str; | 1124 | const char *prompt_str; |
1075 | 1125 | ||
@@ -1081,20 +1131,20 @@ static void get_user_input(struct in_str *i) | |||
1081 | ** atexit() handlers and other unwanted stuff to our | 1131 | ** atexit() handlers and other unwanted stuff to our |
1082 | ** child processes (rob@sysgo.de) | 1132 | ** child processes (rob@sysgo.de) |
1083 | */ | 1133 | */ |
1084 | r = read_line_input(prompt_str, the_command, BUFSIZ-1, line_input_state); | 1134 | r = read_line_input(prompt_str, user_input_buf, BUFSIZ-1, line_input_state); |
1085 | i->eof_flag = (r < 0); | 1135 | i->eof_flag = (r < 0); |
1086 | if (i->eof_flag) { /* EOF/error detected */ | 1136 | if (i->eof_flag) { /* EOF/error detected */ |
1087 | the_command[0] = EOF; /* yes, it will be truncated, it's ok */ | 1137 | user_input_buf[0] = EOF; /* yes, it will be truncated, it's ok */ |
1088 | the_command[1] = '\0'; | 1138 | user_input_buf[1] = '\0'; |
1089 | } | 1139 | } |
1090 | #else | 1140 | #else |
1091 | fputs(prompt_str, stdout); | 1141 | fputs(prompt_str, stdout); |
1092 | fflush(stdout); | 1142 | fflush(stdout); |
1093 | the_command[0] = r = fgetc(i->file); | 1143 | user_input_buf[0] = r = fgetc(i->file); |
1094 | /*the_command[1] = '\0'; - already is and never changed */ | 1144 | /*user_input_buf[1] = '\0'; - already is and never changed */ |
1095 | i->eof_flag = (r == EOF); | 1145 | i->eof_flag = (r == EOF); |
1096 | #endif | 1146 | #endif |
1097 | i->p = the_command; | 1147 | i->p = user_input_buf; |
1098 | } | 1148 | } |
1099 | #endif /* INTERACTIVE */ | 1149 | #endif /* INTERACTIVE */ |
1100 | 1150 | ||
@@ -1879,12 +1929,6 @@ static void debug_print_tree(struct pipe *pi, int lvl) | |||
1879 | * global data until exec/_exit (we can be a child after vfork!) */ | 1929 | * global data until exec/_exit (we can be a child after vfork!) */ |
1880 | static int run_list_real(struct pipe *pi) | 1930 | static int run_list_real(struct pipe *pi) |
1881 | { | 1931 | { |
1882 | #if ENABLE_HUSH_JOB | ||
1883 | static int level; | ||
1884 | #else | ||
1885 | enum { level = 0 }; | ||
1886 | #endif | ||
1887 | |||
1888 | char *for_varname = NULL; | 1932 | char *for_varname = NULL; |
1889 | char **for_lcur = NULL; | 1933 | char **for_lcur = NULL; |
1890 | char **for_list = NULL; | 1934 | char **for_list = NULL; |
@@ -1897,7 +1941,7 @@ static int run_list_real(struct pipe *pi) | |||
1897 | int if_code = 0, next_if_code = 0; /* need double-buffer to handle elif */ | 1941 | int if_code = 0, next_if_code = 0; /* need double-buffer to handle elif */ |
1898 | reserved_style rmode, skip_more_in_this_rmode = RES_XXXX; | 1942 | reserved_style rmode, skip_more_in_this_rmode = RES_XXXX; |
1899 | 1943 | ||
1900 | debug_printf_exec("run_list_real start lvl %d\n", level + 1); | 1944 | debug_printf_exec("run_list_real start lvl %d\n", run_list_level + 1); |
1901 | 1945 | ||
1902 | /* check syntax for "for" */ | 1946 | /* check syntax for "for" */ |
1903 | for (rpipe = pi; rpipe; rpipe = rpipe->next) { | 1947 | for (rpipe = pi; rpipe; rpipe = rpipe->next) { |
@@ -1905,7 +1949,7 @@ static int run_list_real(struct pipe *pi) | |||
1905 | && (rpipe->next == NULL) | 1949 | && (rpipe->next == NULL) |
1906 | ) { | 1950 | ) { |
1907 | syntax(); /* unterminated FOR (no IN or no commands after IN) */ | 1951 | syntax(); /* unterminated FOR (no IN or no commands after IN) */ |
1908 | debug_printf_exec("run_list_real lvl %d return 1\n", level); | 1952 | debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level); |
1909 | return 1; | 1953 | return 1; |
1910 | } | 1954 | } |
1911 | if ((rpipe->r_mode == RES_IN && rpipe->next->r_mode == RES_IN && rpipe->next->progs[0].argv != NULL) | 1955 | if ((rpipe->r_mode == RES_IN && rpipe->next->r_mode == RES_IN && rpipe->next->progs[0].argv != NULL) |
@@ -1913,7 +1957,7 @@ static int run_list_real(struct pipe *pi) | |||
1913 | ) { | 1957 | ) { |
1914 | /* TODO: what is tested in the first condition? */ | 1958 | /* TODO: what is tested in the first condition? */ |
1915 | syntax(); /* 2nd: malformed FOR (not followed by IN) */ | 1959 | syntax(); /* 2nd: malformed FOR (not followed by IN) */ |
1916 | debug_printf_exec("run_list_real lvl %d return 1\n", level); | 1960 | debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level); |
1917 | return 1; | 1961 | return 1; |
1918 | } | 1962 | } |
1919 | } | 1963 | } |
@@ -1923,7 +1967,7 @@ static int run_list_real(struct pipe *pi) | |||
1923 | * We are saving state before entering outermost list ("while...done") | 1967 | * We are saving state before entering outermost list ("while...done") |
1924 | * so that ctrl-Z will correctly background _entire_ outermost list, | 1968 | * so that ctrl-Z will correctly background _entire_ outermost list, |
1925 | * not just a part of it (like "sleep 1 | exit 2") */ | 1969 | * not just a part of it (like "sleep 1 | exit 2") */ |
1926 | if (++level == 1 && interactive_fd) { | 1970 | if (++run_list_level == 1 && interactive_fd) { |
1927 | if (sigsetjmp(toplevel_jb, 1)) { | 1971 | if (sigsetjmp(toplevel_jb, 1)) { |
1928 | /* ctrl-Z forked and we are parent; or ctrl-C. | 1972 | /* ctrl-Z forked and we are parent; or ctrl-C. |
1929 | * Sighandler has longjmped us here */ | 1973 | * Sighandler has longjmped us here */ |
@@ -1931,7 +1975,7 @@ static int run_list_real(struct pipe *pi) | |||
1931 | signal(SIGTSTP, SIG_IGN); | 1975 | signal(SIGTSTP, SIG_IGN); |
1932 | /* Restore level (we can be coming from deep inside | 1976 | /* Restore level (we can be coming from deep inside |
1933 | * nested levels) */ | 1977 | * nested levels) */ |
1934 | level = 1; | 1978 | run_list_level = 1; |
1935 | #if ENABLE_FEATURE_SH_STANDALONE | 1979 | #if ENABLE_FEATURE_SH_STANDALONE |
1936 | if (nofork_save.saved) { /* if save area is valid */ | 1980 | if (nofork_save.saved) { /* if save area is valid */ |
1937 | debug_printf_jobs("exiting nofork early\n"); | 1981 | debug_printf_jobs("exiting nofork early\n"); |
@@ -2039,7 +2083,7 @@ static int run_list_real(struct pipe *pi) | |||
2039 | /* Even bash 3.2 doesn't do that well with nested bg: | 2083 | /* Even bash 3.2 doesn't do that well with nested bg: |
2040 | * try "{ { sleep 10; echo DEEP; } & echo HERE; } &". | 2084 | * try "{ { sleep 10; echo DEEP; } & echo HERE; } &". |
2041 | * I'm considering NOT treating inner bgs as jobs - | 2085 | * I'm considering NOT treating inner bgs as jobs - |
2042 | * thus maybe "if (level == 1 && pi->followup == PIPE_BG)" | 2086 | * thus maybe "if (run_list_level == 1 && pi->followup == PIPE_BG)" |
2043 | * above? */ | 2087 | * above? */ |
2044 | #if ENABLE_HUSH_JOB | 2088 | #if ENABLE_HUSH_JOB |
2045 | insert_bg_job(pi); | 2089 | insert_bg_job(pi); |
@@ -2048,7 +2092,7 @@ static int run_list_real(struct pipe *pi) | |||
2048 | } else { | 2092 | } else { |
2049 | #if ENABLE_HUSH_JOB | 2093 | #if ENABLE_HUSH_JOB |
2050 | /* Paranoia, just "interactive_fd" should be enough */ | 2094 | /* Paranoia, just "interactive_fd" should be enough */ |
2051 | if (level == 1 && interactive_fd) { | 2095 | if (run_list_level == 1 && interactive_fd) { |
2052 | rcode = checkjobs_and_fg_shell(pi); | 2096 | rcode = checkjobs_and_fg_shell(pi); |
2053 | } else | 2097 | } else |
2054 | #endif | 2098 | #endif |
@@ -2081,9 +2125,9 @@ static int run_list_real(struct pipe *pi) | |||
2081 | exit(rcode); | 2125 | exit(rcode); |
2082 | } | 2126 | } |
2083 | ret: | 2127 | ret: |
2084 | level--; | 2128 | run_list_level--; |
2085 | #endif | 2129 | #endif |
2086 | debug_printf_exec("run_list_real lvl %d return %d\n", level + 1, rcode); | 2130 | debug_printf_exec("run_list_real lvl %d return %d\n", run_list_level + 1, rcode); |
2087 | return rcode; | 2131 | return rcode; |
2088 | } | 2132 | } |
2089 | 2133 | ||
@@ -3544,40 +3588,25 @@ int hush_main(int argc, char **argv) | |||
3544 | FILE *input; | 3588 | FILE *input; |
3545 | char **e; | 3589 | char **e; |
3546 | 3590 | ||
3591 | PTR_TO_GLOBALS = xzalloc(sizeof(G)); | ||
3592 | top_vars = &shell_ver; | ||
3593 | shell_ver = const_shell_ver; /* copying struct here */ | ||
3594 | |||
3547 | #if ENABLE_FEATURE_EDITING | 3595 | #if ENABLE_FEATURE_EDITING |
3548 | line_input_state = new_line_input_t(FOR_SHELL); | 3596 | line_input_state = new_line_input_t(FOR_SHELL); |
3549 | #endif | 3597 | #endif |
3550 | |||
3551 | /* XXX what should these be while sourcing /etc/profile? */ | 3598 | /* XXX what should these be while sourcing /etc/profile? */ |
3552 | global_argc = argc; | 3599 | global_argc = argc; |
3553 | global_argv = argv; | 3600 | global_argv = argv; |
3554 | |||
3555 | /* (re?) initialize globals. Sometimes hush_main() ends up calling | ||
3556 | * hush_main(), therefore we cannot rely on the BSS to zero out this | ||
3557 | * stuff. Reset these to 0 every time. */ | ||
3558 | ifs = NULL; | ||
3559 | /* charmap[] is taken care of with call to update_charmap() */ | ||
3560 | fake_mode = 0; | ||
3561 | close_me_head = NULL; | ||
3562 | #if ENABLE_HUSH_INTERACTIVE | ||
3563 | interactive_fd = 0; | ||
3564 | #endif | ||
3565 | #if ENABLE_HUSH_JOB | ||
3566 | last_bg_pid = 0; | ||
3567 | job_list = NULL; | ||
3568 | last_jobid = 0; | ||
3569 | #endif | ||
3570 | |||
3571 | /* Initialize some more globals to non-zero values */ | 3601 | /* Initialize some more globals to non-zero values */ |
3572 | set_cwd(); | 3602 | set_cwd(); |
3573 | #if ENABLE_HUSH_INTERACTIVE | 3603 | #if ENABLE_HUSH_INTERACTIVE |
3574 | #if ENABLE_FEATURE_EDITING | 3604 | #if ENABLE_FEATURE_EDITING |
3575 | cmdedit_set_initial_prompt(); | 3605 | cmdedit_set_initial_prompt(); |
3576 | #else | ||
3577 | PS1 = NULL; | ||
3578 | #endif | 3606 | #endif |
3579 | PS2 = "> "; | 3607 | PS2 = "> "; |
3580 | #endif | 3608 | #endif |
3609 | |||
3581 | /* initialize our shell local variables with the values | 3610 | /* initialize our shell local variables with the values |
3582 | * currently living in the environment */ | 3611 | * currently living in the environment */ |
3583 | e = environ; | 3612 | e = environ; |
@@ -3612,7 +3641,7 @@ int hush_main(int argc, char **argv) | |||
3612 | /* interactive_fd++; */ | 3641 | /* interactive_fd++; */ |
3613 | break; | 3642 | break; |
3614 | case 'f': | 3643 | case 'f': |
3615 | fake_mode++; | 3644 | fake_mode = 1; |
3616 | break; | 3645 | break; |
3617 | default: | 3646 | default: |
3618 | #ifndef BB_VER | 3647 | #ifndef BB_VER |