diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-07 13:26:18 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-07 13:26:18 +0000 |
commit | af07b7c5b6717a4609ea9c77ab6ca9008456a8b0 (patch) | |
tree | fd262bbf9c855051ee2c0ac61ad876f39c63eec8 | |
parent | 50f3aa454785b6acc9ef19b94eff003a83bd0b01 (diff) | |
download | busybox-w32-af07b7c5b6717a4609ea9c77ab6ca9008456a8b0.tar.gz busybox-w32-af07b7c5b6717a4609ea9c77ab6ca9008456a8b0.tar.bz2 busybox-w32-af07b7c5b6717a4609ea9c77ab6ca9008456a8b0.zip |
hush: fix heredoc <<- handling.
hush-misc/heredoc2.tests testcase needs only one fix now -
$var and `cmd` expancsion in heredocs
function old new delta
parse_redirect 265 306 +41
parse_stream 1866 1899 +33
-rw-r--r-- | shell/hush.c | 272 |
1 files changed, 135 insertions, 137 deletions
diff --git a/shell/hush.c b/shell/hush.c index f7e5fbc5b..d82be3d70 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -250,16 +250,6 @@ static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER; | |||
250 | 250 | ||
251 | #define SPECIAL_VAR_SYMBOL 3 | 251 | #define SPECIAL_VAR_SYMBOL 3 |
252 | 252 | ||
253 | typedef enum redir_type { | ||
254 | REDIRECT_INVALID = 0, | ||
255 | REDIRECT_INPUT = 1, | ||
256 | REDIRECT_OVERWRITE = 2, | ||
257 | REDIRECT_APPEND = 3, | ||
258 | REDIRECT_HEREDOC = 4, | ||
259 | REDIRECT_IO = 5, | ||
260 | REDIRECT_HEREDOC2 = 6, /* REDIRECT_HEREDOC after heredoc load */ | ||
261 | } redir_type; | ||
262 | |||
263 | /* The descrip member of this structure is only used to make | 253 | /* The descrip member of this structure is only used to make |
264 | * debugging output pretty */ | 254 | * debugging output pretty */ |
265 | static const struct { | 255 | static const struct { |
@@ -349,10 +339,24 @@ typedef struct in_str { | |||
349 | struct redir_struct { | 339 | struct redir_struct { |
350 | struct redir_struct *next; | 340 | struct redir_struct *next; |
351 | char *rd_filename; /* filename */ | 341 | char *rd_filename; /* filename */ |
352 | int fd; /* file descriptor being redirected */ | 342 | int rd_fd; /* file descriptor being redirected */ |
353 | int dup; /* -1, or file descriptor being duplicated */ | 343 | int rd_dup; /* -1, or file descriptor being duplicated */ |
354 | smallint /*enum redir_type*/ rd_type; | 344 | smallint rd_type; /* (enum redir_type) */ |
345 | /* note: for heredocs, rd_filename contains heredoc delimiter, | ||
346 | * and subsequently heredoc itself; and rd_dup is | ||
347 | * "do we need to trim leading tabs?" bool flag | ||
348 | */ | ||
355 | }; | 349 | }; |
350 | typedef enum redir_type { | ||
351 | REDIRECT_INVALID = 0, | ||
352 | REDIRECT_INPUT = 1, | ||
353 | REDIRECT_OVERWRITE = 2, | ||
354 | REDIRECT_APPEND = 3, | ||
355 | REDIRECT_HEREDOC = 4, | ||
356 | REDIRECT_IO = 5, | ||
357 | REDIRECT_HEREDOC2 = 6, /* REDIRECT_HEREDOC after heredoc is loaded */ | ||
358 | } redir_type; | ||
359 | |||
356 | 360 | ||
357 | struct command { | 361 | struct command { |
358 | pid_t pid; /* 0 if exited */ | 362 | pid_t pid; /* 0 if exited */ |
@@ -910,6 +914,11 @@ static int check_and_run_traps(int sig) | |||
910 | } | 914 | } |
911 | 915 | ||
912 | #if ENABLE_HUSH_JOB | 916 | #if ENABLE_HUSH_JOB |
917 | /* After [v]fork, in child: do not restore tty pgrp on xfunc death */ | ||
918 | #define disable_restore_tty_pgrp_on_exit() (die_sleep = 0) | ||
919 | /* After [v]fork, in parent: do not restore tty pgrp on xfunc death */ | ||
920 | #define enable_restore_tty_pgrp_on_exit() (die_sleep = -1) | ||
921 | |||
913 | /* Restores tty foreground process group, and exits. | 922 | /* Restores tty foreground process group, and exits. |
914 | * May be called as signal handler for fatal signal | 923 | * May be called as signal handler for fatal signal |
915 | * (will faithfully resend signal to itself, producing correct exit state) | 924 | * (will faithfully resend signal to itself, producing correct exit state) |
@@ -932,6 +941,11 @@ static void sigexit(int sig) | |||
932 | 941 | ||
933 | kill_myself_with_sig(sig); /* does not return */ | 942 | kill_myself_with_sig(sig); /* does not return */ |
934 | } | 943 | } |
944 | #else | ||
945 | |||
946 | #define disable_restore_tty_pgrp_on_exit() ((void)0) | ||
947 | #define enable_restore_tty_pgrp_on_exit() ((void)0) | ||
948 | |||
935 | #endif | 949 | #endif |
936 | 950 | ||
937 | /* Restores tty foreground process group, and exits. */ | 951 | /* Restores tty foreground process group, and exits. */ |
@@ -1359,6 +1373,13 @@ static void o_addstr(o_string *o, const char *str) | |||
1359 | { | 1373 | { |
1360 | o_addblock(o, str, strlen(str)); | 1374 | o_addblock(o, str, strlen(str)); |
1361 | } | 1375 | } |
1376 | static void nommu_addchr(o_string *o, int ch) | ||
1377 | { | ||
1378 | if (o) | ||
1379 | o_addchr(o, ch); | ||
1380 | } | ||
1381 | #else | ||
1382 | #define nommu_addchr(o, str) ((void)0) | ||
1362 | #endif | 1383 | #endif |
1363 | 1384 | ||
1364 | static void o_addstr_with_NUL(o_string *o, const char *str) | 1385 | static void o_addstr_with_NUL(o_string *o, const char *str) |
@@ -2201,8 +2222,8 @@ static void setup_heredoc(int fd, const char *heredoc) | |||
2201 | 2222 | ||
2202 | /* Okay, pipe buffer was not big enough */ | 2223 | /* Okay, pipe buffer was not big enough */ |
2203 | /* Note: we must not create a stray child (bastard? :) | 2224 | /* Note: we must not create a stray child (bastard? :) |
2204 | * for the unsuspecting parent process. We create a grandchild | 2225 | * for the unsuspecting parent process. Child creates a grandchild |
2205 | * and exit before we exec the process which consumes heredoc | 2226 | * and exits before parent execs the process which consumes heredoc |
2206 | * (that exec happens after we return from this function) */ | 2227 | * (that exec happens after we return from this function) */ |
2207 | pid = vfork(); | 2228 | pid = vfork(); |
2208 | if (pid < 0) | 2229 | if (pid < 0) |
@@ -2217,24 +2238,20 @@ static void setup_heredoc(int fd, const char *heredoc) | |||
2217 | /* grandchild */ | 2238 | /* grandchild */ |
2218 | close(fd); /* read side of the pipe */ | 2239 | close(fd); /* read side of the pipe */ |
2219 | #if BB_MMU | 2240 | #if BB_MMU |
2220 | full_write(pair.wr, heredoc, len); | 2241 | full_write(pair.wr, heredoc, len); /* may loop or block */ |
2221 | _exit(0); | 2242 | _exit(0); |
2222 | #else | 2243 | #else |
2223 | /* Delegate blocking writes to another process */ | 2244 | /* Delegate blocking writes to another process */ |
2224 | # if ENABLE_HUSH_JOB | 2245 | disable_restore_tty_pgrp_on_exit(); |
2225 | die_sleep = 0; /* do not restore tty pgrp on xfunc death */ | ||
2226 | # endif | ||
2227 | xmove_fd(pair.wr, STDOUT_FILENO); | 2246 | xmove_fd(pair.wr, STDOUT_FILENO); |
2228 | re_execute_shell(heredoc, 1); | 2247 | re_execute_shell(heredoc, 1); |
2229 | #endif | 2248 | #endif |
2230 | } | 2249 | } |
2231 | /* parent */ | 2250 | /* parent */ |
2232 | #if ENABLE_HUSH_JOB | 2251 | enable_restore_tty_pgrp_on_exit(); |
2233 | die_sleep = -1; /* restore tty pgrp on xfunc death */ | ||
2234 | #endif | ||
2235 | clean_up_after_re_execute(); | 2252 | clean_up_after_re_execute(); |
2236 | close(pair.wr); | 2253 | close(pair.wr); |
2237 | wait(NULL); /* wiat till child has died */ | 2254 | wait(NULL); /* wait till child has died */ |
2238 | } | 2255 | } |
2239 | 2256 | ||
2240 | /* squirrel != NULL means we squirrel away copies of stdin, stdout, | 2257 | /* squirrel != NULL means we squirrel away copies of stdin, stdout, |
@@ -2247,18 +2264,18 @@ static int setup_redirects(struct command *prog, int squirrel[]) | |||
2247 | 2264 | ||
2248 | for (redir = prog->redirects; redir; redir = redir->next) { | 2265 | for (redir = prog->redirects; redir; redir = redir->next) { |
2249 | if (redir->rd_type == REDIRECT_HEREDOC2) { | 2266 | if (redir->rd_type == REDIRECT_HEREDOC2) { |
2250 | if (squirrel && redir->fd < 3) { | 2267 | if (squirrel && redir->rd_fd < 3) { |
2251 | squirrel[redir->fd] = dup(redir->fd); | 2268 | squirrel[redir->rd_fd] = dup(redir->rd_fd); |
2252 | } | 2269 | } |
2253 | /* for REDIRECT_HEREDOC2, rd_filename holds _contents_ | 2270 | /* for REDIRECT_HEREDOC2, rd_filename holds _contents_ |
2254 | * of the heredoc */ | 2271 | * of the heredoc */ |
2255 | debug_printf_parse("set heredoc '%s'\n", | 2272 | debug_printf_parse("set heredoc '%s'\n", |
2256 | redir->rd_filename); | 2273 | redir->rd_filename); |
2257 | setup_heredoc(redir->fd, redir->rd_filename); | 2274 | setup_heredoc(redir->rd_fd, redir->rd_filename); |
2258 | continue; | 2275 | continue; |
2259 | } | 2276 | } |
2260 | 2277 | ||
2261 | if (redir->dup == -1) { | 2278 | if (redir->rd_dup == -1) { |
2262 | char *p; | 2279 | char *p; |
2263 | if (redir->rd_filename == NULL) { | 2280 | if (redir->rd_filename == NULL) { |
2264 | /* Something went wrong in the parse. | 2281 | /* Something went wrong in the parse. |
@@ -2277,19 +2294,19 @@ static int setup_redirects(struct command *prog, int squirrel[]) | |||
2277 | return 1; | 2294 | return 1; |
2278 | } | 2295 | } |
2279 | } else { | 2296 | } else { |
2280 | openfd = redir->dup; | 2297 | openfd = redir->rd_dup; |
2281 | } | 2298 | } |
2282 | 2299 | ||
2283 | if (openfd != redir->fd) { | 2300 | if (openfd != redir->rd_fd) { |
2284 | if (squirrel && redir->fd < 3) { | 2301 | if (squirrel && redir->rd_fd < 3) { |
2285 | squirrel[redir->fd] = dup(redir->fd); | 2302 | squirrel[redir->rd_fd] = dup(redir->rd_fd); |
2286 | } | 2303 | } |
2287 | if (openfd == -3) { | 2304 | if (openfd == -3) { |
2288 | /* "-" means "close me" and we use -3 for that */ | 2305 | /* "-" means "close me" and we use -3 for that */ |
2289 | close(redir->fd); | 2306 | close(redir->rd_fd); |
2290 | } else { | 2307 | } else { |
2291 | dup2(openfd, redir->fd); | 2308 | dup2(openfd, redir->rd_fd); |
2292 | if (redir->dup == -1) | 2309 | if (redir->rd_dup == -1) |
2293 | close(openfd); | 2310 | close(openfd); |
2294 | } | 2311 | } |
2295 | } | 2312 | } |
@@ -2350,7 +2367,7 @@ static void free_pipe(struct pipe *pi, int indent) | |||
2350 | #endif | 2367 | #endif |
2351 | for (r = command->redirects; r; r = rnext) { | 2368 | for (r = command->redirects; r; r = rnext) { |
2352 | debug_printf_clean("%s redirect %d%s", indenter(indent), r->fd, redir_table[r->rd_type].descrip); | 2369 | debug_printf_clean("%s redirect %d%s", indenter(indent), r->fd, redir_table[r->rd_type].descrip); |
2353 | if (r->dup == -1) { | 2370 | if (r->rd_dup == -1) { |
2354 | /* guard against the case >$FOO, where foo is unset or blank */ | 2371 | /* guard against the case >$FOO, where foo is unset or blank */ |
2355 | if (r->rd_filename) { | 2372 | if (r->rd_filename) { |
2356 | debug_printf_clean(" %s\n", r->rd_filename); | 2373 | debug_printf_clean(" %s\n", r->rd_filename); |
@@ -2358,7 +2375,7 @@ static void free_pipe(struct pipe *pi, int indent) | |||
2358 | r->rd_filename = NULL; | 2375 | r->rd_filename = NULL; |
2359 | } | 2376 | } |
2360 | } else { | 2377 | } else { |
2361 | debug_printf_clean("&%d\n", r->dup); | 2378 | debug_printf_clean("&%d\n", r->rd_dup); |
2362 | } | 2379 | } |
2363 | rnext = r->next; | 2380 | rnext = r->next; |
2364 | free(r); | 2381 | free(r); |
@@ -2968,7 +2985,7 @@ static int run_pipe(struct pipe *pi) | |||
2968 | command->pid = BB_MMU ? fork() : vfork(); | 2985 | command->pid = BB_MMU ? fork() : vfork(); |
2969 | if (!command->pid) { /* child */ | 2986 | if (!command->pid) { /* child */ |
2970 | #if ENABLE_HUSH_JOB | 2987 | #if ENABLE_HUSH_JOB |
2971 | die_sleep = 0; /* do not restore tty pgrp on xfunc death */ | 2988 | disable_restore_tty_pgrp_on_exit(); |
2972 | 2989 | ||
2973 | /* Every child adds itself to new process group | 2990 | /* Every child adds itself to new process group |
2974 | * with pgid == pid_of_first_child_in_pipe */ | 2991 | * with pgid == pid_of_first_child_in_pipe */ |
@@ -3003,9 +3020,7 @@ static int run_pipe(struct pipe *pi) | |||
3003 | } | 3020 | } |
3004 | 3021 | ||
3005 | /* parent or error */ | 3022 | /* parent or error */ |
3006 | #if ENABLE_HUSH_JOB | 3023 | enable_restore_tty_pgrp_on_exit(); |
3007 | die_sleep = -1; /* restore tty pgrp on xfunc death */ | ||
3008 | #endif | ||
3009 | #if !BB_MMU | 3024 | #if !BB_MMU |
3010 | /* Clean up after vforked child */ | 3025 | /* Clean up after vforked child */ |
3011 | clean_up_after_re_execute(); | 3026 | clean_up_after_re_execute(); |
@@ -3914,15 +3929,11 @@ static int redirect_dup_num(o_string *as_string, struct in_str *input) | |||
3914 | return -1; | 3929 | return -1; |
3915 | 3930 | ||
3916 | ch = i_getch(input); /* get the & */ | 3931 | ch = i_getch(input); /* get the & */ |
3917 | #if !BB_MMU | 3932 | nommu_addchr(as_string, ch); |
3918 | o_addchr(as_string, ch); | ||
3919 | #endif | ||
3920 | ch = i_peek(input); | 3933 | ch = i_peek(input); |
3921 | if (ch == '-') { | 3934 | if (ch == '-') { |
3922 | ch = i_getch(input); | 3935 | ch = i_getch(input); |
3923 | #if !BB_MMU | 3936 | nommu_addchr(as_string, ch); |
3924 | o_addchr(as_string, ch); | ||
3925 | #endif | ||
3926 | return -3; /* "-" represents "close me" */ | 3937 | return -3; /* "-" represents "close me" */ |
3927 | } | 3938 | } |
3928 | d = 0; | 3939 | d = 0; |
@@ -3931,9 +3942,7 @@ static int redirect_dup_num(o_string *as_string, struct in_str *input) | |||
3931 | d = d*10 + (ch-'0'); | 3942 | d = d*10 + (ch-'0'); |
3932 | ok = 1; | 3943 | ok = 1; |
3933 | ch = i_getch(input); | 3944 | ch = i_getch(input); |
3934 | #if !BB_MMU | 3945 | nommu_addchr(as_string, ch); |
3935 | o_addchr(as_string, ch); | ||
3936 | #endif | ||
3937 | ch = i_peek(input); | 3946 | ch = i_peek(input); |
3938 | } | 3947 | } |
3939 | if (ok) return d; | 3948 | if (ok) return d; |
@@ -3962,8 +3971,21 @@ static int parse_redirect(struct parse_context *ctx, | |||
3962 | dup_num = redirect_dup_num(&ctx->as_string, input); | 3971 | dup_num = redirect_dup_num(&ctx->as_string, input); |
3963 | if (dup_num == -2) | 3972 | if (dup_num == -2) |
3964 | return 1; /* syntax error */ | 3973 | return 1; /* syntax error */ |
3974 | } else { | ||
3975 | int ch = i_peek(input); | ||
3976 | dup_num = (ch == '-'); | ||
3977 | if (dup_num) { /* <<-... */ | ||
3978 | ch = i_getch(input); | ||
3979 | nommu_addchr(&ctx->as_string, ch); | ||
3980 | ch = i_peek(input); | ||
3981 | } | ||
3982 | /* <<[-] word is the same as <<[-]word */ | ||
3983 | while (ch == ' ' || ch == '\t') { | ||
3984 | ch = i_getch(input); | ||
3985 | nommu_addchr(&ctx->as_string, ch); | ||
3986 | ch = i_peek(input); | ||
3987 | } | ||
3965 | } | 3988 | } |
3966 | //TODO: else { check for <<-word } | ||
3967 | 3989 | ||
3968 | if (style == REDIRECT_OVERWRITE && dup_num == -1) { | 3990 | if (style == REDIRECT_OVERWRITE && dup_num == -1) { |
3969 | int ch = i_peek(input); | 3991 | int ch = i_peek(input); |
@@ -3973,9 +3995,7 @@ static int parse_redirect(struct parse_context *ctx, | |||
3973 | * >| and > are the same for now. Just eat |. | 3995 | * >| and > are the same for now. Just eat |. |
3974 | */ | 3996 | */ |
3975 | ch = i_getch(input); | 3997 | ch = i_getch(input); |
3976 | #if !BB_MMU | 3998 | nommu_addchr(&ctx->as_string, ch); |
3977 | o_addchr(&ctx->as_string, ch); | ||
3978 | #endif | ||
3979 | } | 3999 | } |
3980 | } | 4000 | } |
3981 | 4001 | ||
@@ -3988,16 +4008,16 @@ static int parse_redirect(struct parse_context *ctx, | |||
3988 | /* redir->next = NULL; */ | 4008 | /* redir->next = NULL; */ |
3989 | /* redir->rd_filename = NULL; */ | 4009 | /* redir->rd_filename = NULL; */ |
3990 | redir->rd_type = style; | 4010 | redir->rd_type = style; |
3991 | redir->fd = (fd == -1) ? redir_table[style].default_fd : fd; | 4011 | redir->rd_fd = (fd == -1) ? redir_table[style].default_fd : fd; |
3992 | 4012 | ||
3993 | debug_printf_parse("redirect type %d %s\n", redir->fd, redir_table[style].descrip); | 4013 | debug_printf_parse("redirect type %d %s\n", redir->rd_fd, redir_table[style].descrip); |
3994 | 4014 | ||
3995 | redir->dup = dup_num; | 4015 | redir->rd_dup = dup_num; |
3996 | if (dup_num != -1) { | 4016 | if (style != REDIRECT_HEREDOC && dup_num != -1) { |
3997 | /* Erik had a check here that the file descriptor in question | 4017 | /* Erik had a check here that the file descriptor in question |
3998 | * is legit; I postpone that to "run time" | 4018 | * is legit; I postpone that to "run time" |
3999 | * A "-" representation of "close me" shows up as a -3 here */ | 4019 | * A "-" representation of "close me" shows up as a -3 here */ |
4000 | debug_printf_parse("duplicating redirect '%d>&%d'\n", redir->fd, redir->dup); | 4020 | debug_printf_parse("duplicating redirect '%d>&%d'\n", redir->rd_fd, redir->rd_dup); |
4001 | } else { | 4021 | } else { |
4002 | /* Set ctx->pending_redirect, so we know what to do at the | 4022 | /* Set ctx->pending_redirect, so we know what to do at the |
4003 | * end of the next parsed word. */ | 4023 | * end of the next parsed word. */ |
@@ -4039,28 +4059,45 @@ static int redirect_opt_num(o_string *o) | |||
4039 | return num; | 4059 | return num; |
4040 | } | 4060 | } |
4041 | 4061 | ||
4042 | //TODO: add NOMMU as_string fill | 4062 | #if BB_MMU |
4043 | static char *fetch_till_str(struct in_str *input, const char *word) | 4063 | #define fetch_till_str(as_string, input, word, skip_tabs) \ |
4064 | fetch_till_str(input, word, skip_tabs) | ||
4065 | #endif | ||
4066 | static char *fetch_till_str(o_string *as_string, | ||
4067 | struct in_str *input, | ||
4068 | const char *word, | ||
4069 | int skip_tabs) | ||
4044 | { | 4070 | { |
4045 | o_string heredoc = NULL_O_STRING; | 4071 | o_string heredoc = NULL_O_STRING; |
4046 | int past_EOL = 0; | 4072 | int past_EOL = 0; |
4047 | int ch; | 4073 | int ch; |
4048 | 4074 | ||
4075 | goto jump_in; | ||
4049 | while (1) { | 4076 | while (1) { |
4050 | ch = i_getch(input); | 4077 | ch = i_getch(input); |
4051 | if (ch == EOF) { | 4078 | nommu_addchr(as_string, ch); |
4052 | o_free_unsafe(&heredoc); | ||
4053 | return NULL; | ||
4054 | } | ||
4055 | if (ch == '\n') { | 4079 | if (ch == '\n') { |
4056 | if (strcmp(heredoc.data + past_EOL, word) == 0) { | 4080 | if (strcmp(heredoc.data + past_EOL, word) == 0) { |
4057 | heredoc.data[past_EOL] = '\0'; | 4081 | heredoc.data[past_EOL] = '\0'; |
4058 | debug_printf_parse("parsed heredoc '%s'\n", heredoc.data); | 4082 | debug_printf_parse("parsed heredoc '%s'\n", heredoc.data); |
4059 | return heredoc.data; | 4083 | return heredoc.data; |
4060 | } | 4084 | } |
4061 | past_EOL = heredoc.length + 1; | 4085 | do { |
4086 | o_addchr(&heredoc, ch); | ||
4087 | past_EOL = heredoc.length; | ||
4088 | jump_in: | ||
4089 | do { | ||
4090 | ch = i_getch(input); | ||
4091 | nommu_addchr(as_string, ch); | ||
4092 | } while (skip_tabs && ch == '\t'); | ||
4093 | } while (ch == '\n'); | ||
4094 | } | ||
4095 | if (ch == EOF) { | ||
4096 | o_free_unsafe(&heredoc); | ||
4097 | return NULL; | ||
4062 | } | 4098 | } |
4063 | o_addchr(&heredoc, ch); | 4099 | o_addchr(&heredoc, ch); |
4100 | nommu_addchr(as_string, ch); | ||
4064 | } | 4101 | } |
4065 | } | 4102 | } |
4066 | 4103 | ||
@@ -4076,25 +4113,27 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_ | |||
4076 | pi->num_cmds, | 4113 | pi->num_cmds, |
4077 | cmd->argv ? cmd->argv[0] : "NONE"); | 4114 | cmd->argv ? cmd->argv[0] : "NONE"); |
4078 | for (i = 0; i < pi->num_cmds; i++) { | 4115 | for (i = 0; i < pi->num_cmds; i++) { |
4079 | struct redir_struct *redirect = cmd->redirects; | 4116 | struct redir_struct *redir = cmd->redirects; |
4080 | 4117 | ||
4081 | debug_printf_parse("fetch_heredocs: %d cmd argv0:'%s'\n", | 4118 | debug_printf_parse("fetch_heredocs: %d cmd argv0:'%s'\n", |
4082 | i, cmd->argv ? cmd->argv[0] : "NONE"); | 4119 | i, cmd->argv ? cmd->argv[0] : "NONE"); |
4083 | while (redirect) { | 4120 | while (redir) { |
4084 | if (redirect->rd_type == REDIRECT_HEREDOC) { | 4121 | if (redir->rd_type == REDIRECT_HEREDOC) { |
4085 | char *p; | 4122 | char *p; |
4086 | 4123 | ||
4087 | if (heredoc_cnt <= 0) | 4124 | if (heredoc_cnt <= 0) |
4088 | return 1; /* error */ | 4125 | return 1; /* error */ |
4089 | redirect->rd_type = REDIRECT_HEREDOC2; | 4126 | redir->rd_type = REDIRECT_HEREDOC2; |
4090 | p = fetch_till_str(input, redirect->rd_filename); | 4127 | /* redir->dup is (ab)used to indicate <<- */ |
4128 | p = fetch_till_str(&ctx->as_string, input, | ||
4129 | redir->rd_filename, redir->rd_dup); | ||
4091 | if (!p) | 4130 | if (!p) |
4092 | return 1; /* unexpected EOF */ | 4131 | return 1; /* unexpected EOF */ |
4093 | free(redirect->rd_filename); | 4132 | free(redir->rd_filename); |
4094 | redirect->rd_filename = p; | 4133 | redir->rd_filename = p; |
4095 | heredoc_cnt--; | 4134 | heredoc_cnt--; |
4096 | } | 4135 | } |
4097 | redirect = redirect->next; | 4136 | redir = redir->next; |
4098 | } | 4137 | } |
4099 | cmd++; | 4138 | cmd++; |
4100 | } | 4139 | } |
@@ -4126,9 +4165,7 @@ static FILE *generate_stream_from_string(const char *s) | |||
4126 | bb_perror_msg_and_die(BB_MMU ? "fork" : "vfork"); | 4165 | bb_perror_msg_and_die(BB_MMU ? "fork" : "vfork"); |
4127 | 4166 | ||
4128 | if (pid == 0) { /* child */ | 4167 | if (pid == 0) { /* child */ |
4129 | #if ENABLE_HUSH_JOB | 4168 | disable_restore_tty_pgrp_on_exit(); |
4130 | die_sleep = 0; /* do not restore tty pgrp on xfunc death */ | ||
4131 | #endif | ||
4132 | /* Process substitution is not considered to be usual | 4169 | /* Process substitution is not considered to be usual |
4133 | * 'command execution'. | 4170 | * 'command execution'. |
4134 | * SUSv3 says ctrl-Z should be ignored, ctrl-C should not. | 4171 | * SUSv3 says ctrl-Z should be ignored, ctrl-C should not. |
@@ -4157,9 +4194,7 @@ static FILE *generate_stream_from_string(const char *s) | |||
4157 | } | 4194 | } |
4158 | 4195 | ||
4159 | /* parent */ | 4196 | /* parent */ |
4160 | #if ENABLE_HUSH_JOB | 4197 | enable_restore_tty_pgrp_on_exit(); |
4161 | die_sleep = -1; /* restore tty pgrp on xfunc death */ | ||
4162 | #endif | ||
4163 | clean_up_after_re_execute(); | 4198 | clean_up_after_re_execute(); |
4164 | close(channel[1]); | 4199 | close(channel[1]); |
4165 | pf = fdopen(channel[0], "r"); | 4200 | pf = fdopen(channel[0], "r"); |
@@ -4409,9 +4444,7 @@ static int handle_dollar(o_string *as_string, | |||
4409 | debug_printf_parse("handle_dollar entered: ch='%c'\n", ch); | 4444 | debug_printf_parse("handle_dollar entered: ch='%c'\n", ch); |
4410 | if (isalpha(ch)) { | 4445 | if (isalpha(ch)) { |
4411 | ch = i_getch(input); | 4446 | ch = i_getch(input); |
4412 | #if !BB_MMU | 4447 | nommu_addchr(as_string, ch); |
4413 | if (as_string) o_addchr(as_string, ch); | ||
4414 | #endif | ||
4415 | make_var: | 4448 | make_var: |
4416 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4449 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
4417 | while (1) { | 4450 | while (1) { |
@@ -4422,17 +4455,13 @@ static int handle_dollar(o_string *as_string, | |||
4422 | if (!isalnum(ch) && ch != '_') | 4455 | if (!isalnum(ch) && ch != '_') |
4423 | break; | 4456 | break; |
4424 | ch = i_getch(input); | 4457 | ch = i_getch(input); |
4425 | #if !BB_MMU | 4458 | nommu_addchr(as_string, ch); |
4426 | if (as_string) o_addchr(as_string, ch); | ||
4427 | #endif | ||
4428 | } | 4459 | } |
4429 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4460 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
4430 | } else if (isdigit(ch)) { | 4461 | } else if (isdigit(ch)) { |
4431 | make_one_char_var: | 4462 | make_one_char_var: |
4432 | ch = i_getch(input); | 4463 | ch = i_getch(input); |
4433 | #if !BB_MMU | 4464 | nommu_addchr(as_string, ch); |
4434 | if (as_string) o_addchr(as_string, ch); | ||
4435 | #endif | ||
4436 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4465 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
4437 | debug_printf_parse(": '%c'\n", ch); | 4466 | debug_printf_parse(": '%c'\n", ch); |
4438 | o_addchr(dest, ch | quote_mask); | 4467 | o_addchr(dest, ch | quote_mask); |
@@ -4450,18 +4479,14 @@ static int handle_dollar(o_string *as_string, | |||
4450 | 4479 | ||
4451 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4480 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
4452 | ch = i_getch(input); | 4481 | ch = i_getch(input); |
4453 | #if !BB_MMU | 4482 | nommu_addchr(as_string, ch); |
4454 | if (as_string) o_addchr(as_string, ch); | ||
4455 | #endif | ||
4456 | /* XXX maybe someone will try to escape the '}' */ | 4483 | /* XXX maybe someone will try to escape the '}' */ |
4457 | expansion = 0; | 4484 | expansion = 0; |
4458 | first_char = true; | 4485 | first_char = true; |
4459 | all_digits = false; | 4486 | all_digits = false; |
4460 | while (1) { | 4487 | while (1) { |
4461 | ch = i_getch(input); | 4488 | ch = i_getch(input); |
4462 | #if !BB_MMU | 4489 | nommu_addchr(as_string, ch); |
4463 | if (as_string) o_addchr(as_string, ch); | ||
4464 | #endif | ||
4465 | if (ch == '}') | 4490 | if (ch == '}') |
4466 | break; | 4491 | break; |
4467 | 4492 | ||
@@ -4530,15 +4555,11 @@ static int handle_dollar(o_string *as_string, | |||
4530 | int pos; | 4555 | int pos; |
4531 | # endif | 4556 | # endif |
4532 | ch = i_getch(input); | 4557 | ch = i_getch(input); |
4533 | # if !BB_MMU | 4558 | nommu_addchr(as_string, ch); |
4534 | if (as_string) o_addchr(as_string, ch); | ||
4535 | # endif | ||
4536 | # if ENABLE_SH_MATH_SUPPORT | 4559 | # if ENABLE_SH_MATH_SUPPORT |
4537 | if (i_peek(input) == '(') { | 4560 | if (i_peek(input) == '(') { |
4538 | ch = i_getch(input); | 4561 | ch = i_getch(input); |
4539 | # if !BB_MMU | 4562 | nommu_addchr(as_string, ch); |
4540 | if (as_string) o_addchr(as_string, ch); | ||
4541 | # endif | ||
4542 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4563 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
4543 | o_addchr(dest, /*quote_mask |*/ '+'); | 4564 | o_addchr(dest, /*quote_mask |*/ '+'); |
4544 | # if !BB_MMU | 4565 | # if !BB_MMU |
@@ -4578,9 +4599,7 @@ static int handle_dollar(o_string *as_string, | |||
4578 | #endif | 4599 | #endif |
4579 | case '_': | 4600 | case '_': |
4580 | ch = i_getch(input); | 4601 | ch = i_getch(input); |
4581 | #if !BB_MMU | 4602 | nommu_addchr(as_string, ch); |
4582 | if (as_string) o_addchr(as_string, ch); | ||
4583 | #endif | ||
4584 | ch = i_peek(input); | 4603 | ch = i_peek(input); |
4585 | if (isalnum(ch)) { /* it's $_name or $_123 */ | 4604 | if (isalnum(ch)) { /* it's $_name or $_123 */ |
4586 | ch = '_'; | 4605 | ch = '_'; |
@@ -4611,9 +4630,8 @@ static int parse_stream_dquoted(o_string *as_string, | |||
4611 | 4630 | ||
4612 | again: | 4631 | again: |
4613 | ch = i_getch(input); | 4632 | ch = i_getch(input); |
4614 | #if !BB_MMU | 4633 | if (ch != EOF) |
4615 | if (as_string && ch != EOF) o_addchr(as_string, ch); | 4634 | nommu_addchr(as_string, ch); |
4616 | #endif | ||
4617 | if (ch == dquote_end) { /* may be only '"' or EOF */ | 4635 | if (ch == dquote_end) { /* may be only '"' or EOF */ |
4618 | dest->nonnull = 1; | 4636 | dest->nonnull = 1; |
4619 | if (dest->o_assignment == NOT_ASSIGNMENT) | 4637 | if (dest->o_assignment == NOT_ASSIGNMENT) |
@@ -4769,9 +4787,7 @@ static struct pipe *parse_stream(char **pstring, | |||
4769 | #endif | 4787 | #endif |
4770 | return pi; | 4788 | return pi; |
4771 | } | 4789 | } |
4772 | #if !BB_MMU | 4790 | nommu_addchr(&ctx.as_string, ch); |
4773 | o_addchr(&ctx.as_string, ch); | ||
4774 | #endif | ||
4775 | is_ifs = strchr(G.ifs, ch); | 4791 | is_ifs = strchr(G.ifs, ch); |
4776 | is_special = strchr("<>;&|(){}#'" /* special outside of "str" */ | 4792 | is_special = strchr("<>;&|(){}#'" /* special outside of "str" */ |
4777 | "\\$\"" USE_HUSH_TICK("`") /* always special */ | 4793 | "\\$\"" USE_HUSH_TICK("`") /* always special */ |
@@ -4882,10 +4898,8 @@ static struct pipe *parse_stream(char **pstring, | |||
4882 | i_getch(input); | 4898 | i_getch(input); |
4883 | /* note: we do not add it to &ctx.as_string */ | 4899 | /* note: we do not add it to &ctx.as_string */ |
4884 | } | 4900 | } |
4885 | #if !BB_MMU | ||
4886 | //TODO: go back one char? | 4901 | //TODO: go back one char? |
4887 | o_addchr(&ctx.as_string, '\n'); | 4902 | nommu_addchr(&ctx.as_string, '\n'); |
4888 | #endif | ||
4889 | } else { | 4903 | } else { |
4890 | o_addQchr(&dest, ch); | 4904 | o_addQchr(&dest, ch); |
4891 | } | 4905 | } |
@@ -4898,9 +4912,7 @@ static struct pipe *parse_stream(char **pstring, | |||
4898 | o_addchr(&dest, '\\'); | 4912 | o_addchr(&dest, '\\'); |
4899 | ch = i_getch(input); | 4913 | ch = i_getch(input); |
4900 | o_addchr(&dest, ch); | 4914 | o_addchr(&dest, ch); |
4901 | #if !BB_MMU | 4915 | nommu_addchr(&ctx.as_string, ch); |
4902 | o_addchr(&ctx.as_string, ch); | ||
4903 | #endif | ||
4904 | break; | 4916 | break; |
4905 | case '$': | 4917 | case '$': |
4906 | if (handle_dollar(&ctx.as_string, &dest, input) != 0) { | 4918 | if (handle_dollar(&ctx.as_string, &dest, input) != 0) { |
@@ -4917,9 +4929,7 @@ static struct pipe *parse_stream(char **pstring, | |||
4917 | syntax("unterminated '"); | 4929 | syntax("unterminated '"); |
4918 | goto parse_error; | 4930 | goto parse_error; |
4919 | } | 4931 | } |
4920 | #if !BB_MMU | 4932 | nommu_addchr(&ctx.as_string, ch); |
4921 | o_addchr(&ctx.as_string, ch); | ||
4922 | #endif | ||
4923 | if (ch == '\'') | 4933 | if (ch == '\'') |
4924 | break; | 4934 | break; |
4925 | if (dest.o_assignment == NOT_ASSIGNMENT) | 4935 | if (dest.o_assignment == NOT_ASSIGNMENT) |
@@ -4954,9 +4964,7 @@ static struct pipe *parse_stream(char **pstring, | |||
4954 | if (next == '>') { | 4964 | if (next == '>') { |
4955 | redir_style = REDIRECT_APPEND; | 4965 | redir_style = REDIRECT_APPEND; |
4956 | ch = i_getch(input); | 4966 | ch = i_getch(input); |
4957 | #if !BB_MMU | 4967 | nommu_addchr(&ctx.as_string, ch); |
4958 | o_addchr(&ctx.as_string, ch); | ||
4959 | #endif | ||
4960 | } | 4968 | } |
4961 | #if 0 | 4969 | #if 0 |
4962 | else if (next == '(') { | 4970 | else if (next == '(') { |
@@ -4978,15 +4986,11 @@ static struct pipe *parse_stream(char **pstring, | |||
4978 | heredoc_cnt++; | 4986 | heredoc_cnt++; |
4979 | debug_printf_parse("++heredoc_cnt=%d\n", heredoc_cnt); | 4987 | debug_printf_parse("++heredoc_cnt=%d\n", heredoc_cnt); |
4980 | ch = i_getch(input); | 4988 | ch = i_getch(input); |
4981 | #if !BB_MMU | 4989 | nommu_addchr(&ctx.as_string, ch); |
4982 | o_addchr(&ctx.as_string, ch); | ||
4983 | #endif | ||
4984 | } else if (next == '>') { | 4990 | } else if (next == '>') { |
4985 | redir_style = REDIRECT_IO; | 4991 | redir_style = REDIRECT_IO; |
4986 | ch = i_getch(input); | 4992 | ch = i_getch(input); |
4987 | #if !BB_MMU | 4993 | nommu_addchr(&ctx.as_string, ch); |
4988 | o_addchr(&ctx.as_string, ch); | ||
4989 | #endif | ||
4990 | } | 4994 | } |
4991 | #if 0 | 4995 | #if 0 |
4992 | else if (next == '(') { | 4996 | else if (next == '(') { |
@@ -5013,9 +5017,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5013 | if (ch != ';') | 5017 | if (ch != ';') |
5014 | break; | 5018 | break; |
5015 | ch = i_getch(input); | 5019 | ch = i_getch(input); |
5016 | #if !BB_MMU | 5020 | nommu_addchr(&ctx.as_string, ch); |
5017 | o_addchr(&ctx.as_string, ch); | ||
5018 | #endif | ||
5019 | if (ctx.ctx_res_w == RES_CASEI) { | 5021 | if (ctx.ctx_res_w == RES_CASEI) { |
5020 | ctx.ctx_dsemicolon = 1; | 5022 | ctx.ctx_dsemicolon = 1; |
5021 | ctx.ctx_res_w = RES_MATCH; | 5023 | ctx.ctx_res_w = RES_MATCH; |
@@ -5034,9 +5036,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5034 | } | 5036 | } |
5035 | if (next == '&') { | 5037 | if (next == '&') { |
5036 | ch = i_getch(input); | 5038 | ch = i_getch(input); |
5037 | #if !BB_MMU | 5039 | nommu_addchr(&ctx.as_string, ch); |
5038 | o_addchr(&ctx.as_string, ch); | ||
5039 | #endif | ||
5040 | done_pipe(&ctx, PIPE_AND); | 5040 | done_pipe(&ctx, PIPE_AND); |
5041 | } else { | 5041 | } else { |
5042 | done_pipe(&ctx, PIPE_BG); | 5042 | done_pipe(&ctx, PIPE_BG); |
@@ -5052,9 +5052,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5052 | #endif | 5052 | #endif |
5053 | if (next == '|') { /* || */ | 5053 | if (next == '|') { /* || */ |
5054 | ch = i_getch(input); | 5054 | ch = i_getch(input); |
5055 | #if !BB_MMU | 5055 | nommu_addchr(&ctx.as_string, ch); |
5056 | o_addchr(&ctx.as_string, ch); | ||
5057 | #endif | ||
5058 | done_pipe(&ctx, PIPE_OR); | 5056 | done_pipe(&ctx, PIPE_OR); |
5059 | } else { | 5057 | } else { |
5060 | /* we could pick up a file descriptor choice here | 5058 | /* we could pick up a file descriptor choice here |
@@ -5537,7 +5535,7 @@ int hush_main(int argc, char **argv) | |||
5537 | tcsetpgrp(G_interactive_fd, getpid()); | 5535 | tcsetpgrp(G_interactive_fd, getpid()); |
5538 | /* -1 is special - makes xfuncs longjmp, not exit | 5536 | /* -1 is special - makes xfuncs longjmp, not exit |
5539 | * (we reset die_sleep = 0 whereever we [v]fork) */ | 5537 | * (we reset die_sleep = 0 whereever we [v]fork) */ |
5540 | die_sleep = -1; | 5538 | enable_restore_tty_pgrp_on_exit(); /* sets die_sleep = -1 */ |
5541 | if (setjmp(die_jmp)) { | 5539 | if (setjmp(die_jmp)) { |
5542 | /* xfunc has failed! die die die */ | 5540 | /* xfunc has failed! die die die */ |
5543 | hush_exit(xfunc_error_retval); | 5541 | hush_exit(xfunc_error_retval); |