aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-07 13:26:18 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-07 13:26:18 +0000
commitaf07b7c5b6717a4609ea9c77ab6ca9008456a8b0 (patch)
treefd262bbf9c855051ee2c0ac61ad876f39c63eec8
parent50f3aa454785b6acc9ef19b94eff003a83bd0b01 (diff)
downloadbusybox-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.c272
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
253typedef 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 */
265static const struct { 255static const struct {
@@ -349,10 +339,24 @@ typedef struct in_str {
349struct redir_struct { 339struct 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};
350typedef 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
357struct command { 361struct 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}
1376static 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
1364static void o_addstr_with_NUL(o_string *o, const char *str) 1385static 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
4043static 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
4066static 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);