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 | |
| 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')
| -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 |
