diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-30 22:30:09 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-30 22:30:09 +0000 |
commit | 0c886c65de93f860a54508be0df40d1a9c52ab6d (patch) | |
tree | b7938a51b43b76bbbd26bc8fbc1c98869519bcf8 | |
parent | 15d78fb7241e324a823d00654206695a4f250648 (diff) | |
download | busybox-w32-0c886c65de93f860a54508be0df40d1a9c52ab6d.tar.gz busybox-w32-0c886c65de93f860a54508be0df40d1a9c52ab6d.tar.bz2 busybox-w32-0c886c65de93f860a54508be0df40d1a9c52ab6d.zip |
hush: style fixes
-rw-r--r-- | shell/hush.c | 646 |
1 files changed, 332 insertions, 314 deletions
diff --git a/shell/hush.c b/shell/hush.c index 1540327f1..1ff9b7fd5 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -79,21 +79,11 @@ | |||
79 | */ | 79 | */ |
80 | 80 | ||
81 | #include "busybox.h" | 81 | #include "busybox.h" |
82 | #include <ctype.h> /* isalpha, isdigit */ | ||
83 | #include <unistd.h> /* getpid */ | ||
84 | #include <stdlib.h> /* getenv, atoi */ | ||
85 | #include <string.h> /* strchr */ | ||
86 | #include <stdio.h> /* popen etc. */ | ||
87 | #include <glob.h> /* glob, of course */ | 82 | #include <glob.h> /* glob, of course */ |
88 | #include <stdarg.h> /* va_list */ | ||
89 | #include <errno.h> | ||
90 | #include <fcntl.h> | ||
91 | #include <getopt.h> /* should be pretty obvious */ | 83 | #include <getopt.h> /* should be pretty obvious */ |
92 | 84 | ||
93 | #include <sys/stat.h> /* ulimit */ | 85 | //#include <sys/wait.h> |
94 | #include <sys/types.h> | 86 | //#include <signal.h> |
95 | #include <sys/wait.h> | ||
96 | #include <signal.h> | ||
97 | 87 | ||
98 | /* #include <dmalloc.h> */ | 88 | /* #include <dmalloc.h> */ |
99 | /* #define DEBUG_SHELL */ | 89 | /* #define DEBUG_SHELL */ |
@@ -168,46 +158,46 @@ struct p_context { | |||
168 | struct pipe *pipe; | 158 | struct pipe *pipe; |
169 | struct redir_struct *pending_redirect; | 159 | struct redir_struct *pending_redirect; |
170 | reserved_style w; | 160 | reserved_style w; |
171 | int old_flag; /* for figuring out valid reserved words */ | 161 | int old_flag; /* for figuring out valid reserved words */ |
172 | struct p_context *stack; | 162 | struct p_context *stack; |
173 | int type; /* define type of parser : ";$" common or special symbol */ | 163 | int type; /* define type of parser : ";$" common or special symbol */ |
174 | /* How about quoting status? */ | 164 | /* How about quoting status? */ |
175 | }; | 165 | }; |
176 | 166 | ||
177 | struct redir_struct { | 167 | struct redir_struct { |
178 | redir_type type; /* type of redirection */ | 168 | redir_type type; /* type of redirection */ |
179 | int fd; /* file descriptor being redirected */ | 169 | int fd; /* file descriptor being redirected */ |
180 | int dup; /* -1, or file descriptor being duplicated */ | 170 | int dup; /* -1, or file descriptor being duplicated */ |
181 | struct redir_struct *next; /* pointer to the next redirect in the list */ | 171 | struct redir_struct *next; /* pointer to the next redirect in the list */ |
182 | glob_t word; /* *word.gl_pathv is the filename */ | 172 | glob_t word; /* *word.gl_pathv is the filename */ |
183 | }; | 173 | }; |
184 | 174 | ||
185 | struct child_prog { | 175 | struct child_prog { |
186 | pid_t pid; /* 0 if exited */ | 176 | pid_t pid; /* 0 if exited */ |
187 | char **argv; /* program name and arguments */ | 177 | char **argv; /* program name and arguments */ |
188 | struct pipe *group; /* if non-NULL, first in group or subshell */ | 178 | struct pipe *group; /* if non-NULL, first in group or subshell */ |
189 | int subshell; /* flag, non-zero if group must be forked */ | 179 | int subshell; /* flag, non-zero if group must be forked */ |
190 | struct redir_struct *redirects; /* I/O redirections */ | 180 | struct redir_struct *redirects; /* I/O redirections */ |
191 | glob_t glob_result; /* result of parameter globbing */ | 181 | glob_t glob_result; /* result of parameter globbing */ |
192 | int is_stopped; /* is the program currently running? */ | 182 | int is_stopped; /* is the program currently running? */ |
193 | struct pipe *family; /* pointer back to the child's parent pipe */ | 183 | struct pipe *family; /* pointer back to the child's parent pipe */ |
194 | int sp; /* number of SPECIAL_VAR_SYMBOL */ | 184 | int sp; /* number of SPECIAL_VAR_SYMBOL */ |
195 | int type; | 185 | int type; |
196 | }; | 186 | }; |
197 | 187 | ||
198 | struct pipe { | 188 | struct pipe { |
199 | int jobid; /* job number */ | 189 | int jobid; /* job number */ |
200 | int num_progs; /* total number of programs in job */ | 190 | int num_progs; /* total number of programs in job */ |
201 | int running_progs; /* number of programs running */ | 191 | int running_progs; /* number of programs running */ |
202 | char *text; /* name of job */ | 192 | char *text; /* name of job */ |
203 | char *cmdbuf; /* buffer various argv's point into */ | 193 | char *cmdbuf; /* buffer various argv's point into */ |
204 | pid_t pgrp; /* process group ID for the job */ | 194 | pid_t pgrp; /* process group ID for the job */ |
205 | struct child_prog *progs; /* array of commands in pipe */ | 195 | struct child_prog *progs; /* array of commands in pipe */ |
206 | struct pipe *next; /* to track background commands */ | 196 | struct pipe *next; /* to track background commands */ |
207 | int stopped_progs; /* number of programs alive, but stopped */ | 197 | int stopped_progs; /* number of programs alive, but stopped */ |
208 | int job_context; /* bitmask defining current context */ | 198 | int job_context; /* bitmask defining current context */ |
209 | pipe_style followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */ | 199 | pipe_style followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */ |
210 | reserved_style r_mode; /* supports if, for, while, until */ | 200 | reserved_style r_mode; /* supports if, for, while, until */ |
211 | }; | 201 | }; |
212 | 202 | ||
213 | struct close_me { | 203 | struct close_me { |
@@ -238,9 +228,9 @@ static int interactive; | |||
238 | static struct close_me *close_me_head; | 228 | static struct close_me *close_me_head; |
239 | static const char *cwd; | 229 | static const char *cwd; |
240 | static struct pipe *job_list; | 230 | static struct pipe *job_list; |
241 | static unsigned int last_bg_pid; | 231 | static unsigned last_bg_pid; |
242 | static int last_jobid; | 232 | static int last_jobid; |
243 | static unsigned int shell_terminal; | 233 | static unsigned shell_terminal; |
244 | static char *PS1; | 234 | static char *PS1; |
245 | static char *PS2; | 235 | static char *PS2; |
246 | static struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 }; | 236 | static struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 }; |
@@ -301,11 +291,11 @@ static void debug_printf(const char *format, ...) | |||
301 | /* broken, of course, but OK for testing */ | 291 | /* broken, of course, but OK for testing */ |
302 | static char *indenter(int i) | 292 | static char *indenter(int i) |
303 | { | 293 | { |
304 | static char blanks[]=" "; | 294 | static char blanks[] = " "; |
305 | return &blanks[sizeof(blanks)-i-1]; | 295 | return &blanks[sizeof(blanks)-i-1]; |
306 | } | 296 | } |
307 | #else | 297 | #else |
308 | #define debug_printf(...) do {;} while(0); | 298 | #define debug_printf(...) do {;} while (0); |
309 | #endif | 299 | #endif |
310 | #define final_printf debug_printf | 300 | #define final_printf debug_printf |
311 | 301 | ||
@@ -340,7 +330,7 @@ static int b_check_space(o_string *o, int len); | |||
340 | static int b_addchr(o_string *o, int ch); | 330 | static int b_addchr(o_string *o, int ch); |
341 | static void b_reset(o_string *o); | 331 | static void b_reset(o_string *o); |
342 | static int b_addqchr(o_string *o, int ch, int quote); | 332 | static int b_addqchr(o_string *o, int ch, int quote); |
343 | static int b_adduint(o_string *o, unsigned int i); | 333 | static int b_adduint(o_string *o, unsigned i); |
344 | /* in_str manipulations: */ | 334 | /* in_str manipulations: */ |
345 | static int static_get(struct in_str *i); | 335 | static int static_get(struct in_str *i); |
346 | static int static_peek(struct in_str *i); | 336 | static int static_peek(struct in_str *i); |
@@ -404,35 +394,35 @@ static int set_local_var(const char *s, int flg_export); | |||
404 | * For example, 'unset foo | whatever' will parse and run, but foo will | 394 | * For example, 'unset foo | whatever' will parse and run, but foo will |
405 | * still be set at the end. */ | 395 | * still be set at the end. */ |
406 | static const struct built_in_command bltins[] = { | 396 | static const struct built_in_command bltins[] = { |
407 | {"bg", "Resume a job in the background", builtin_fg_bg}, | 397 | { "bg", "Resume a job in the background", builtin_fg_bg }, |
408 | {"break", "Exit for, while or until loop", builtin_not_written}, | 398 | { "break", "Exit for, while or until loop", builtin_not_written }, |
409 | {"cd", "Change working directory", builtin_cd}, | 399 | { "cd", "Change working directory", builtin_cd }, |
410 | {"continue", "Continue for, while or until loop", builtin_not_written}, | 400 | { "continue", "Continue for, while or until loop", builtin_not_written }, |
411 | {"env", "Print all environment variables", builtin_env}, | 401 | { "env", "Print all environment variables", builtin_env }, |
412 | {"eval", "Construct and run shell command", builtin_eval}, | 402 | { "eval", "Construct and run shell command", builtin_eval }, |
413 | {"exec", "Exec command, replacing this shell with the exec'd process", | 403 | { "exec", "Exec command, replacing this shell with the exec'd process", |
414 | builtin_exec}, | 404 | builtin_exec }, |
415 | {"exit", "Exit from shell()", builtin_exit}, | 405 | { "exit", "Exit from shell()", builtin_exit }, |
416 | {"export", "Set environment variable", builtin_export}, | 406 | { "export", "Set environment variable", builtin_export }, |
417 | {"fg", "Bring job into the foreground", builtin_fg_bg}, | 407 | { "fg", "Bring job into the foreground", builtin_fg_bg }, |
418 | {"jobs", "Lists the active jobs", builtin_jobs}, | 408 | { "jobs", "Lists the active jobs", builtin_jobs }, |
419 | {"pwd", "Print current directory", builtin_pwd}, | 409 | { "pwd", "Print current directory", builtin_pwd }, |
420 | {"read", "Input environment variable", builtin_read}, | 410 | { "read", "Input environment variable", builtin_read }, |
421 | {"return", "Return from a function", builtin_not_written}, | 411 | { "return", "Return from a function", builtin_not_written }, |
422 | {"set", "Set/unset shell local variables", builtin_set}, | 412 | { "set", "Set/unset shell local variables", builtin_set }, |
423 | {"shift", "Shift positional parameters", builtin_shift}, | 413 | { "shift", "Shift positional parameters", builtin_shift }, |
424 | {"trap", "Trap signals", builtin_not_written}, | 414 | { "trap", "Trap signals", builtin_not_written }, |
425 | {"ulimit","Controls resource limits", builtin_not_written}, | 415 | { "ulimit","Controls resource limits", builtin_not_written }, |
426 | {"umask","Sets file creation mask", builtin_umask}, | 416 | { "umask","Sets file creation mask", builtin_umask }, |
427 | {"unset", "Unset environment variable", builtin_unset}, | 417 | { "unset", "Unset environment variable", builtin_unset }, |
428 | {".", "Source-in and run commands in a file", builtin_source}, | 418 | { ".", "Source-in and run commands in a file", builtin_source }, |
429 | {"help", "List shell built-in commands", builtin_help}, | 419 | { "help", "List shell built-in commands", builtin_help }, |
430 | {NULL, NULL, NULL} | 420 | { NULL, NULL, NULL } |
431 | }; | 421 | }; |
432 | 422 | ||
433 | static const char *set_cwd(void) | 423 | static const char *set_cwd(void) |
434 | { | 424 | { |
435 | if(cwd==bb_msg_unknown) | 425 | if (cwd == bb_msg_unknown) |
436 | cwd = NULL; /* xgetcwd(arg) called free(arg) */ | 426 | cwd = NULL; /* xgetcwd(arg) called free(arg) */ |
437 | cwd = xgetcwd((char *)cwd); | 427 | cwd = xgetcwd((char *)cwd); |
438 | if (!cwd) | 428 | if (!cwd) |
@@ -477,8 +467,8 @@ static int builtin_env(struct child_prog *dummy ATTRIBUTE_UNUSED) | |||
477 | { | 467 | { |
478 | char **e = environ; | 468 | char **e = environ; |
479 | if (e == NULL) return EXIT_FAILURE; | 469 | if (e == NULL) return EXIT_FAILURE; |
480 | for (; *e; e++) { | 470 | for (*e) { |
481 | puts(*e); | 471 | puts(*e++); |
482 | } | 472 | } |
483 | return EXIT_SUCCESS; | 473 | return EXIT_SUCCESS; |
484 | } | 474 | } |
@@ -513,7 +503,7 @@ static int builtin_export(struct child_prog *child) | |||
513 | 503 | ||
514 | name = strdup(name); | 504 | name = strdup(name); |
515 | 505 | ||
516 | if(name) { | 506 | if (name) { |
517 | const char *value = strchr(name, '='); | 507 | const char *value = strchr(name, '='); |
518 | 508 | ||
519 | if (!value) { | 509 | if (!value) { |
@@ -525,7 +515,7 @@ static int builtin_export(struct child_prog *child) | |||
525 | size_t ln = strlen(name); | 515 | size_t ln = strlen(name); |
526 | 516 | ||
527 | tmp = realloc(name, ln+strlen(value)+2); | 517 | tmp = realloc(name, ln+strlen(value)+2); |
528 | if(tmp==NULL) | 518 | if (tmp == NULL) |
529 | res = -1; | 519 | res = -1; |
530 | else { | 520 | else { |
531 | sprintf(tmp+ln, "=%s", value); | 521 | sprintf(tmp+ln, "=%s", value); |
@@ -538,9 +528,9 @@ static int builtin_export(struct child_prog *child) | |||
538 | } | 528 | } |
539 | } | 529 | } |
540 | } | 530 | } |
541 | if (res<0) | 531 | if (res < 0) |
542 | bb_perror_msg("export"); | 532 | bb_perror_msg("export"); |
543 | else if(res==0) | 533 | else if (res == 0) |
544 | res = set_local_var(name, 1); | 534 | res = set_local_var(name, 1); |
545 | else | 535 | else |
546 | res = 0; | 536 | res = 0; |
@@ -552,7 +542,7 @@ static int builtin_export(struct child_prog *child) | |||
552 | static int builtin_fg_bg(struct child_prog *child) | 542 | static int builtin_fg_bg(struct child_prog *child) |
553 | { | 543 | { |
554 | int i, jobnum; | 544 | int i, jobnum; |
555 | struct pipe *pi=NULL; | 545 | struct pipe *pi = NULL; |
556 | 546 | ||
557 | if (!interactive) | 547 | if (!interactive) |
558 | return EXIT_FAILURE; | 548 | return EXIT_FAILURE; |
@@ -612,7 +602,7 @@ static int builtin_help(struct child_prog *dummy ATTRIBUTE_UNUSED) | |||
612 | printf("\nBuilt-in commands:\n"); | 602 | printf("\nBuilt-in commands:\n"); |
613 | printf("-------------------\n"); | 603 | printf("-------------------\n"); |
614 | for (x = bltins; x->cmd; x++) { | 604 | for (x = bltins; x->cmd; x++) { |
615 | if (x->descr==NULL) | 605 | if (x->descr == NULL) |
616 | continue; | 606 | continue; |
617 | printf("%s\t%s\n", x->cmd, x->descr); | 607 | printf("%s\t%s\n", x->cmd, x->descr); |
618 | } | 608 | } |
@@ -624,7 +614,7 @@ static int builtin_help(struct child_prog *dummy ATTRIBUTE_UNUSED) | |||
624 | static int builtin_jobs(struct child_prog *child ATTRIBUTE_UNUSED) | 614 | static int builtin_jobs(struct child_prog *child ATTRIBUTE_UNUSED) |
625 | { | 615 | { |
626 | struct pipe *job; | 616 | struct pipe *job; |
627 | char *status_string; | 617 | const char *status_string; |
628 | 618 | ||
629 | for (job = job_list; job; job = job->next) { | 619 | for (job = job_list; job; job = job->next) { |
630 | if (job->running_progs == job->stopped_progs) | 620 | if (job->running_progs == job->stopped_progs) |
@@ -652,14 +642,14 @@ static int builtin_read(struct child_prog *child) | |||
652 | 642 | ||
653 | if (child->argv[1]) { | 643 | if (child->argv[1]) { |
654 | char string[BUFSIZ]; | 644 | char string[BUFSIZ]; |
655 | char *var = 0; | 645 | char *var = NULL; |
656 | 646 | ||
657 | string[0] = 0; /* In case stdin has only EOF */ | 647 | string[0] = '\0'; /* In case stdin has only EOF */ |
658 | /* read string */ | 648 | /* read string */ |
659 | fgets(string, sizeof(string), stdin); | 649 | fgets(string, sizeof(string), stdin); |
660 | chomp(string); | 650 | chomp(string); |
661 | var = malloc(strlen(child->argv[1])+strlen(string)+2); | 651 | var = malloc(strlen(child->argv[1]) + strlen(string) + 2); |
662 | if(var) { | 652 | if (var) { |
663 | sprintf(var, "%s=%s", child->argv[1], string); | 653 | sprintf(var, "%s=%s", child->argv[1], string); |
664 | res = set_local_var(var, 0); | 654 | res = set_local_var(var, 0); |
665 | } else | 655 | } else |
@@ -668,10 +658,9 @@ static int builtin_read(struct child_prog *child) | |||
668 | bb_perror_msg("read"); | 658 | bb_perror_msg("read"); |
669 | free(var); /* So not move up to avoid breaking errno */ | 659 | free(var); /* So not move up to avoid breaking errno */ |
670 | return res; | 660 | return res; |
671 | } else { | ||
672 | do res=getchar(); while(res!='\n' && res!=EOF); | ||
673 | return 0; | ||
674 | } | 661 | } |
662 | do res = getchar(); while (res != '\n' && res != EOF); | ||
663 | return 0; | ||
675 | } | 664 | } |
676 | 665 | ||
677 | /* built-in 'set VAR=value' handler */ | 666 | /* built-in 'set VAR=value' handler */ |
@@ -681,23 +670,23 @@ static int builtin_set(struct child_prog *child) | |||
681 | struct variables *e; | 670 | struct variables *e; |
682 | 671 | ||
683 | if (temp == NULL) | 672 | if (temp == NULL) |
684 | for(e = top_vars; e; e=e->next) | 673 | for (e = top_vars; e; e = e->next) |
685 | printf("%s=%s\n", e->name, e->value); | 674 | printf("%s=%s\n", e->name, e->value); |
686 | else | 675 | else |
687 | set_local_var(temp, 0); | 676 | set_local_var(temp, 0); |
688 | 677 | ||
689 | return EXIT_SUCCESS; | 678 | return EXIT_SUCCESS; |
690 | } | 679 | } |
691 | 680 | ||
692 | 681 | ||
693 | /* Built-in 'shift' handler */ | 682 | /* Built-in 'shift' handler */ |
694 | static int builtin_shift(struct child_prog *child) | 683 | static int builtin_shift(struct child_prog *child) |
695 | { | 684 | { |
696 | int n=1; | 685 | int n = 1; |
697 | if (child->argv[1]) { | 686 | if (child->argv[1]) { |
698 | n=atoi(child->argv[1]); | 687 | n = atoi(child->argv[1]); |
699 | } | 688 | } |
700 | if (n>=0 && n<global_argc) { | 689 | if (n >= 0 && n < global_argc) { |
701 | /* XXX This probably breaks $0 */ | 690 | /* XXX This probably breaks $0 */ |
702 | global_argc -= n; | 691 | global_argc -= n; |
703 | global_argv += n; | 692 | global_argv += n; |
@@ -740,12 +729,13 @@ static int builtin_umask(struct child_prog *child) | |||
740 | const char *arg = child->argv[1]; | 729 | const char *arg = child->argv[1]; |
741 | char *end; | 730 | char *end; |
742 | if (arg) { | 731 | if (arg) { |
743 | new_umask=strtoul(arg, &end, 8); | 732 | new_umask = strtoul(arg, &end, 8); |
744 | if (*end!='\0' || end == arg) { | 733 | if (*end != '\0' || end == arg) { |
745 | return EXIT_FAILURE; | 734 | return EXIT_FAILURE; |
746 | } | 735 | } |
747 | } else { | 736 | } else { |
748 | printf("%.3o\n", (unsigned int) (new_umask=umask(0))); | 737 | new_umask = umask(0); |
738 | printf("%.3o\n", (unsigned) new_umask); | ||
749 | } | 739 | } |
750 | umask(new_umask); | 740 | umask(new_umask); |
751 | return EXIT_SUCCESS; | 741 | return EXIT_SUCCESS; |
@@ -761,7 +751,7 @@ static int builtin_unset(struct child_prog *child) | |||
761 | 751 | ||
762 | static int builtin_not_written(struct child_prog *child) | 752 | static int builtin_not_written(struct child_prog *child) |
763 | { | 753 | { |
764 | printf("builtin_%s not written\n",child->argv[0]); | 754 | printf("builtin_%s not written\n", child->argv[0]); |
765 | return EXIT_FAILURE; | 755 | return EXIT_FAILURE; |
766 | } | 756 | } |
767 | 757 | ||
@@ -784,7 +774,8 @@ static int b_check_space(o_string *o, int len) | |||
784 | static int b_addchr(o_string *o, int ch) | 774 | static int b_addchr(o_string *o, int ch) |
785 | { | 775 | { |
786 | debug_printf("b_addchr: %c %d %p\n", ch, o->length, o); | 776 | debug_printf("b_addchr: %c %d %p\n", ch, o->length, o); |
787 | if (b_check_space(o, 1)) return B_NOSPAC; | 777 | if (b_check_space(o, 1)) |
778 | return B_NOSPAC; | ||
788 | o->data[o->length] = ch; | 779 | o->data[o->length] = ch; |
789 | o->length++; | 780 | o->length++; |
790 | o->data[o->length] = '\0'; | 781 | o->data[o->length] = '\0'; |
@@ -795,7 +786,8 @@ static void b_reset(o_string *o) | |||
795 | { | 786 | { |
796 | o->length = 0; | 787 | o->length = 0; |
797 | o->nonnull = 0; | 788 | o->nonnull = 0; |
798 | if (o->data != NULL) *o->data = '\0'; | 789 | if (o->data != NULL) |
790 | *o->data = '\0'; | ||
799 | } | 791 | } |
800 | 792 | ||
801 | static void b_free(o_string *o) | 793 | static void b_free(o_string *o) |
@@ -814,17 +806,17 @@ static int b_addqchr(o_string *o, int ch, int quote) | |||
814 | if (quote && strchr("*?[\\",ch)) { | 806 | if (quote && strchr("*?[\\",ch)) { |
815 | int rc; | 807 | int rc; |
816 | rc = b_addchr(o, '\\'); | 808 | rc = b_addchr(o, '\\'); |
817 | if (rc) return rc; | 809 | if (rc) |
810 | return rc; | ||
818 | } | 811 | } |
819 | return b_addchr(o, ch); | 812 | return b_addchr(o, ch); |
820 | } | 813 | } |
821 | 814 | ||
822 | /* belongs in utility.c */ | 815 | /* belongs in utility.c */ |
823 | static char *simple_itoa(unsigned int i) | 816 | static char *simple_itoa(unsigned i) |
824 | { | 817 | { |
825 | /* 21 digits plus null terminator, good for 64-bit or smaller ints */ | 818 | static char local[sizeof(int)*3 + 2]; |
826 | static char local[22]; | 819 | char *p = &local[sizeof(int)*3 + 2 - 1]; |
827 | char *p = &local[21]; | ||
828 | *p-- = '\0'; | 820 | *p-- = '\0'; |
829 | do { | 821 | do { |
830 | *p-- = '0' + i % 10; | 822 | *p-- = '0' + i % 10; |
@@ -833,19 +825,19 @@ static char *simple_itoa(unsigned int i) | |||
833 | return p + 1; | 825 | return p + 1; |
834 | } | 826 | } |
835 | 827 | ||
836 | static int b_adduint(o_string *o, unsigned int i) | 828 | static int b_adduint(o_string *o, unsigned i) |
837 | { | 829 | { |
838 | int r; | 830 | int r; |
839 | char *p = simple_itoa(i); | 831 | char *p = simple_itoa(i); |
840 | /* no escape checking necessary */ | 832 | /* no escape checking necessary */ |
841 | do r=b_addchr(o, *p++); while (r==0 && *p); | 833 | do r = b_addchr(o, *p++); while (r==0 && *p); |
842 | return r; | 834 | return r; |
843 | } | 835 | } |
844 | 836 | ||
845 | static int static_get(struct in_str *i) | 837 | static int static_get(struct in_str *i) |
846 | { | 838 | { |
847 | int ch=*i->p++; | 839 | int ch = *i->p++; |
848 | if (ch=='\0') return EOF; | 840 | if (ch == '\0') return EOF; |
849 | return ch; | 841 | return ch; |
850 | } | 842 | } |
851 | 843 | ||
@@ -860,7 +852,7 @@ static void cmdedit_set_initial_prompt(void) | |||
860 | PS1 = NULL; | 852 | PS1 = NULL; |
861 | #else | 853 | #else |
862 | PS1 = getenv("PS1"); | 854 | PS1 = getenv("PS1"); |
863 | if(PS1==0) | 855 | if (PS1 == NULL) |
864 | PS1 = "\\w \\$ "; | 856 | PS1 = "\\w \\$ "; |
865 | #endif | 857 | #endif |
866 | } | 858 | } |
@@ -872,16 +864,16 @@ static void setup_prompt_string(int promptmode, char **prompt_str) | |||
872 | /* Set up the prompt */ | 864 | /* Set up the prompt */ |
873 | if (promptmode == 1) { | 865 | if (promptmode == 1) { |
874 | free(PS1); | 866 | free(PS1); |
875 | PS1=xmalloc(strlen(cwd)+4); | 867 | PS1 = xmalloc(strlen(cwd)+4); |
876 | sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ? "$ ":"# "); | 868 | sprintf(PS1, "%s %s", cwd, (geteuid() != 0) ? "$ " : "# "); |
877 | *prompt_str = PS1; | 869 | *prompt_str = PS1; |
878 | } else { | 870 | } else { |
879 | *prompt_str = PS2; | 871 | *prompt_str = PS2; |
880 | } | 872 | } |
881 | #else | 873 | #else |
882 | *prompt_str = (promptmode==1)? PS1 : PS2; | 874 | *prompt_str = (promptmode == 1) ? PS1 : PS2; |
883 | #endif | 875 | #endif |
884 | debug_printf("result %s\n",*prompt_str); | 876 | debug_printf("result %s\n", *prompt_str); |
885 | } | 877 | } |
886 | 878 | ||
887 | #if ENABLE_FEATURE_EDITING | 879 | #if ENABLE_FEATURE_EDITING |
@@ -905,8 +897,8 @@ static void get_user_input(struct in_str *i) | |||
905 | #else | 897 | #else |
906 | fputs(prompt_str, stdout); | 898 | fputs(prompt_str, stdout); |
907 | fflush(stdout); | 899 | fflush(stdout); |
908 | the_command[0]=fgetc(i->file); | 900 | the_command[0] = fgetc(i->file); |
909 | the_command[1]='\0'; | 901 | the_command[1] = '\0'; |
910 | #endif | 902 | #endif |
911 | fflush(stdout); | 903 | fflush(stdout); |
912 | i->p = the_command; | 904 | i->p = the_command; |
@@ -921,18 +913,18 @@ static int file_get(struct in_str *i) | |||
921 | ch = 0; | 913 | ch = 0; |
922 | /* If there is data waiting, eat it up */ | 914 | /* If there is data waiting, eat it up */ |
923 | if (i->p && *i->p) { | 915 | if (i->p && *i->p) { |
924 | ch=*i->p++; | 916 | ch = *i->p++; |
925 | } else { | 917 | } else { |
926 | /* need to double check i->file because we might be doing something | 918 | /* need to double check i->file because we might be doing something |
927 | * more complicated by now, like sourcing or substituting. */ | 919 | * more complicated by now, like sourcing or substituting. */ |
928 | if (i->__promptme && interactive && i->file == stdin) { | 920 | if (i->__promptme && interactive && i->file == stdin) { |
929 | while(! i->p || (interactive && strlen(i->p)==0) ) { | 921 | while (!i->p || !(interactive && strlen(i->p))) { |
930 | get_user_input(i); | 922 | get_user_input(i); |
931 | } | 923 | } |
932 | i->promptmode=2; | 924 | i->promptmode = 2; |
933 | i->__promptme = 0; | 925 | i->__promptme = 0; |
934 | if (i->p && *i->p) { | 926 | if (i->p && *i->p) { |
935 | ch=*i->p++; | 927 | ch = *i->p++; |
936 | } | 928 | } |
937 | } else { | 929 | } else { |
938 | ch = fgetc(i->file); | 930 | ch = fgetc(i->file); |
@@ -940,7 +932,8 @@ static int file_get(struct in_str *i) | |||
940 | 932 | ||
941 | debug_printf("b_getch: got a %d\n", ch); | 933 | debug_printf("b_getch: got a %d\n", ch); |
942 | } | 934 | } |
943 | if (ch == '\n') i->__promptme=1; | 935 | if (ch == '\n') |
936 | i->__promptme = 1; | ||
944 | return ch; | 937 | return ch; |
945 | } | 938 | } |
946 | 939 | ||
@@ -964,8 +957,8 @@ static void setup_file_in_str(struct in_str *i, FILE *f) | |||
964 | { | 957 | { |
965 | i->peek = file_peek; | 958 | i->peek = file_peek; |
966 | i->get = file_get; | 959 | i->get = file_get; |
967 | i->__promptme=1; | 960 | i->__promptme = 1; |
968 | i->promptmode=1; | 961 | i->promptmode = 1; |
969 | i->file = f; | 962 | i->file = f; |
970 | i->p = NULL; | 963 | i->p = NULL; |
971 | } | 964 | } |
@@ -1000,7 +993,7 @@ static void mark_closed(int fd) | |||
1000 | static void close_all(void) | 993 | static void close_all(void) |
1001 | { | 994 | { |
1002 | struct close_me *c; | 995 | struct close_me *c; |
1003 | for (c=close_me_head; c; c=c->next) { | 996 | for (c = close_me_head; c; c = c->next) { |
1004 | close(c->fd); | 997 | close(c->fd); |
1005 | } | 998 | } |
1006 | close_me_head = NULL; | 999 | close_me_head = NULL; |
@@ -1013,13 +1006,13 @@ static int setup_redirects(struct child_prog *prog, int squirrel[]) | |||
1013 | int openfd, mode; | 1006 | int openfd, mode; |
1014 | struct redir_struct *redir; | 1007 | struct redir_struct *redir; |
1015 | 1008 | ||
1016 | for (redir=prog->redirects; redir; redir=redir->next) { | 1009 | for (redir = prog->redirects; redir; redir = redir->next) { |
1017 | if (redir->dup == -1 && redir->word.gl_pathv == NULL) { | 1010 | if (redir->dup == -1 && redir->word.gl_pathv == NULL) { |
1018 | /* something went wrong in the parse. Pretend it didn't happen */ | 1011 | /* something went wrong in the parse. Pretend it didn't happen */ |
1019 | continue; | 1012 | continue; |
1020 | } | 1013 | } |
1021 | if (redir->dup == -1) { | 1014 | if (redir->dup == -1) { |
1022 | mode=redir_table[redir->type].mode; | 1015 | mode = redir_table[redir->type].mode; |
1023 | openfd = open(redir->word.gl_pathv[0], mode, 0666); | 1016 | openfd = open(redir->word.gl_pathv[0], mode, 0666); |
1024 | if (openfd < 0) { | 1017 | if (openfd < 0) { |
1025 | /* this could get lost if stderr has been redirected, but | 1018 | /* this could get lost if stderr has been redirected, but |
@@ -1050,7 +1043,7 @@ static int setup_redirects(struct child_prog *prog, int squirrel[]) | |||
1050 | static void restore_redirects(int squirrel[]) | 1043 | static void restore_redirects(int squirrel[]) |
1051 | { | 1044 | { |
1052 | int i, fd; | 1045 | int i, fd; |
1053 | for (i=0; i<3; i++) { | 1046 | for (i = 0; i < 3; i++) { |
1054 | fd = squirrel[i]; | 1047 | fd = squirrel[i]; |
1055 | if (fd != -1) { | 1048 | if (fd != -1) { |
1056 | /* No error checking. I sure wouldn't know what | 1049 | /* No error checking. I sure wouldn't know what |
@@ -1071,13 +1064,15 @@ static void pseudo_exec(struct child_prog *child) | |||
1071 | char *p; | 1064 | char *p; |
1072 | const struct built_in_command *x; | 1065 | const struct built_in_command *x; |
1073 | if (child->argv) { | 1066 | if (child->argv) { |
1074 | for (i=0; is_assignment(child->argv[i]); i++) { | 1067 | for (i = 0; is_assignment(child->argv[i]); i++) { |
1075 | debug_printf("pid %d environment modification: %s\n",getpid(),child->argv[i]); | 1068 | debug_printf("pid %d environment modification: %s\n", |
1069 | getpid(), child->argv[i]); | ||
1076 | p = insert_var_value(child->argv[i]); | 1070 | p = insert_var_value(child->argv[i]); |
1077 | putenv(strdup(p)); | 1071 | putenv(strdup(p)); |
1078 | if (p != child->argv[i]) free(p); | 1072 | if (p != child->argv[i]) |
1073 | free(p); | ||
1079 | } | 1074 | } |
1080 | child->argv+=i; /* XXX this hack isn't so horrible, since we are about | 1075 | child->argv += i; /* XXX this hack isn't so horrible, since we are about |
1081 | to exit, and therefore don't need to keep data | 1076 | to exit, and therefore don't need to keep data |
1082 | structures consistent for free() use. */ | 1077 | structures consistent for free() use. */ |
1083 | /* If a variable is assigned in a forest, and nobody listens, | 1078 | /* If a variable is assigned in a forest, and nobody listens, |
@@ -1118,19 +1113,20 @@ static void pseudo_exec(struct child_prog *child) | |||
1118 | char *name = child->argv[0]; | 1113 | char *name = child->argv[0]; |
1119 | 1114 | ||
1120 | /* Count argc for use in a second... */ | 1115 | /* Count argc for use in a second... */ |
1121 | for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++); | 1116 | for (argc_l = 0; *argv_l; argv_l++, argc_l++) |
1117 | /**/; | ||
1122 | optind = 1; | 1118 | optind = 1; |
1123 | debug_printf("running applet %s\n", name); | 1119 | debug_printf("running applet %s\n", name); |
1124 | run_applet_by_name(name, argc_l, child->argv); | 1120 | run_applet_by_name(name, argc_l, child->argv); |
1125 | } | 1121 | } |
1126 | #endif | 1122 | #endif |
1127 | debug_printf("exec of %s\n",child->argv[0]); | 1123 | debug_printf("exec of %s\n", child->argv[0]); |
1128 | execvp(child->argv[0],child->argv); | 1124 | execvp(child->argv[0], child->argv); |
1129 | bb_perror_msg("cannot exec: %s",child->argv[0]); | 1125 | bb_perror_msg("cannot exec: %s", child->argv[0]); |
1130 | _exit(1); | 1126 | _exit(1); |
1131 | } else if (child->group) { | 1127 | } else if (child->group) { |
1132 | debug_printf("runtime nesting to group\n"); | 1128 | debug_printf("runtime nesting to group\n"); |
1133 | interactive=0; /* crucial!!!! */ | 1129 | interactive = 0; /* crucial!!!! */ |
1134 | rcode = run_list_real(child->group); | 1130 | rcode = run_list_real(child->group); |
1135 | /* OK to leak memory by not calling free_pipe_list, | 1131 | /* OK to leak memory by not calling free_pipe_list, |
1136 | * since this process is about to exit */ | 1132 | * since this process is about to exit */ |
@@ -1156,7 +1152,8 @@ static void insert_bg_job(struct pipe *pi) | |||
1156 | if (!job_list) { | 1152 | if (!job_list) { |
1157 | thejob = job_list = xmalloc(sizeof(*thejob)); | 1153 | thejob = job_list = xmalloc(sizeof(*thejob)); |
1158 | } else { | 1154 | } else { |
1159 | for (thejob = job_list; thejob->next; thejob = thejob->next) /* nothing */; | 1155 | for (thejob = job_list; thejob->next; thejob = thejob->next) |
1156 | /* nothing */; | ||
1160 | thejob->next = xmalloc(sizeof(*thejob)); | 1157 | thejob->next = xmalloc(sizeof(*thejob)); |
1161 | thejob = thejob->next; | 1158 | thejob = thejob->next; |
1162 | } | 1159 | } |
@@ -1170,11 +1167,11 @@ static void insert_bg_job(struct pipe *pi) | |||
1170 | 1167 | ||
1171 | //if (pi->progs[0] && pi->progs[0].argv && pi->progs[0].argv[0]) | 1168 | //if (pi->progs[0] && pi->progs[0].argv && pi->progs[0].argv[0]) |
1172 | { | 1169 | { |
1173 | char *bar=thejob->text; | 1170 | char *bar = thejob->text; |
1174 | char **foo=pi->progs[0].argv; | 1171 | char **foo = pi->progs[0].argv; |
1175 | while(foo && *foo) { | 1172 | if (foo) |
1176 | bar += sprintf(bar, "%s ", *foo++); | 1173 | while (*foo) |
1177 | } | 1174 | bar += sprintf(bar, "%s ", *foo++); |
1178 | } | 1175 | } |
1179 | 1176 | ||
1180 | /* we don't wait for background thejobs to return -- append it | 1177 | /* we don't wait for background thejobs to return -- append it |
@@ -1218,18 +1215,18 @@ static int checkjobs(struct pipe* fg_pipe) | |||
1218 | pid_t childpid; | 1215 | pid_t childpid; |
1219 | 1216 | ||
1220 | attributes = WUNTRACED; | 1217 | attributes = WUNTRACED; |
1221 | if (fg_pipe==NULL) { | 1218 | if (fg_pipe == NULL) { |
1222 | attributes |= WNOHANG; | 1219 | attributes |= WNOHANG; |
1223 | } | 1220 | } |
1224 | 1221 | ||
1225 | while ((childpid = waitpid(-1, &status, attributes)) > 0) { | 1222 | while ((childpid = waitpid(-1, &status, attributes)) > 0) { |
1226 | if (fg_pipe) { | 1223 | if (fg_pipe) { |
1227 | int i, rcode = 0; | 1224 | int i, rcode = 0; |
1228 | for (i=0; i < fg_pipe->num_progs; i++) { | 1225 | for (i = 0; i < fg_pipe->num_progs; i++) { |
1229 | if (fg_pipe->progs[i].pid == childpid) { | 1226 | if (fg_pipe->progs[i].pid == childpid) { |
1230 | if (i==fg_pipe->num_progs-1) | 1227 | if (i == fg_pipe->num_progs-1) |
1231 | rcode=WEXITSTATUS(status); | 1228 | rcode = WEXITSTATUS(status); |
1232 | (fg_pipe->num_progs)--; | 1229 | fg_pipe->num_progs--; |
1233 | return rcode; | 1230 | return rcode; |
1234 | } | 1231 | } |
1235 | } | 1232 | } |
@@ -1244,8 +1241,9 @@ static int checkjobs(struct pipe* fg_pipe) | |||
1244 | break; | 1241 | break; |
1245 | } | 1242 | } |
1246 | 1243 | ||
1247 | if(pi==NULL) { | 1244 | if (pi == NULL) { |
1248 | debug_printf("checkjobs: pid %d was not in our list!\n", childpid); | 1245 | debug_printf("checkjobs: pid %d was not in our list!\n", |
1246 | childpid); | ||
1249 | continue; | 1247 | continue; |
1250 | } | 1248 | } |
1251 | 1249 | ||
@@ -1255,7 +1253,8 @@ static int checkjobs(struct pipe* fg_pipe) | |||
1255 | pi->progs[prognum].pid = 0; | 1253 | pi->progs[prognum].pid = 0; |
1256 | 1254 | ||
1257 | if (!pi->running_progs) { | 1255 | if (!pi->running_progs) { |
1258 | printf(JOB_STATUS_FORMAT, pi->jobid, "Done", pi->text); | 1256 | printf(JOB_STATUS_FORMAT, pi->jobid, |
1257 | "Done", pi->text); | ||
1259 | remove_bg_job(pi); | 1258 | remove_bg_job(pi); |
1260 | } | 1259 | } |
1261 | } else { | 1260 | } else { |
@@ -1306,9 +1305,9 @@ static int run_pipe_real(struct pipe *pi) | |||
1306 | * Builtins within pipes have to fork anyway, and are handled in | 1305 | * Builtins within pipes have to fork anyway, and are handled in |
1307 | * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. | 1306 | * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. |
1308 | */ | 1307 | */ |
1309 | child = & (pi->progs[0]); | 1308 | child = &(pi->progs[0]); |
1310 | if (pi->num_progs == 1 && child->group && child->subshell == 0) { | 1309 | if (pi->num_progs == 1 && child->group && child->subshell == 0) { |
1311 | int squirrel[] = {-1, -1, -1}; | 1310 | int squirrel[] = { -1, -1, -1 }; |
1312 | int rcode; | 1311 | int rcode; |
1313 | debug_printf("non-subshell grouping\n"); | 1312 | debug_printf("non-subshell grouping\n"); |
1314 | setup_redirects(child, squirrel); | 1313 | setup_redirects(child, squirrel); |
@@ -1318,31 +1317,32 @@ static int run_pipe_real(struct pipe *pi) | |||
1318 | restore_redirects(squirrel); | 1317 | restore_redirects(squirrel); |
1319 | return rcode; | 1318 | return rcode; |
1320 | } else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) { | 1319 | } else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) { |
1321 | for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ } | 1320 | for (i = 0; is_assignment(child->argv[i]); i++) |
1322 | if (i!=0 && child->argv[i]==NULL) { | 1321 | /* nothing */; |
1322 | if (i != 0 && child->argv[i] == NULL) { | ||
1323 | /* assignments, but no command: set the local environment */ | 1323 | /* assignments, but no command: set the local environment */ |
1324 | for (i=0; child->argv[i]!=NULL; i++) { | 1324 | for (i = 0; child->argv[i] != NULL; i++) { |
1325 | |||
1326 | /* Ok, this case is tricky. We have to decide if this is a | 1325 | /* Ok, this case is tricky. We have to decide if this is a |
1327 | * local variable, or an already exported variable. If it is | 1326 | * local variable, or an already exported variable. If it is |
1328 | * already exported, we have to export the new value. If it is | 1327 | * already exported, we have to export the new value. If it is |
1329 | * not exported, we need only set this as a local variable. | 1328 | * not exported, we need only set this as a local variable. |
1330 | * This junk is all to decide whether or not to export this | 1329 | * This junk is all to decide whether or not to export this |
1331 | * variable. */ | 1330 | * variable. */ |
1332 | int export_me=0; | 1331 | int export_me = 0; |
1333 | char *name, *value; | 1332 | char *name, *value; |
1334 | name = xstrdup(child->argv[i]); | 1333 | name = xstrdup(child->argv[i]); |
1335 | debug_printf("Local environment set: %s\n", name); | 1334 | debug_printf("Local environment set: %s\n", name); |
1336 | value = strchr(name, '='); | 1335 | value = strchr(name, '='); |
1337 | if (value) | 1336 | if (value) |
1338 | *value=0; | 1337 | *value = 0; |
1339 | if ( get_local_var(name)) { | 1338 | if (get_local_var(name)) { |
1340 | export_me=1; | 1339 | export_me = 1; |
1341 | } | 1340 | } |
1342 | free(name); | 1341 | free(name); |
1343 | p = insert_var_value(child->argv[i]); | 1342 | p = insert_var_value(child->argv[i]); |
1344 | set_local_var(p, export_me); | 1343 | set_local_var(p, export_me); |
1345 | if (p != child->argv[i]) free(p); | 1344 | if (p != child->argv[i]) |
1345 | free(p); | ||
1346 | } | 1346 | } |
1347 | return EXIT_SUCCESS; /* don't worry about errors in set_local_var() yet */ | 1347 | return EXIT_SUCCESS; /* don't worry about errors in set_local_var() yet */ |
1348 | } | 1348 | } |
@@ -1355,7 +1355,7 @@ static int run_pipe_real(struct pipe *pi) | |||
1355 | } | 1355 | } |
1356 | } | 1356 | } |
1357 | if (child->sp) { | 1357 | if (child->sp) { |
1358 | char * str = NULL; | 1358 | char *str = NULL; |
1359 | 1359 | ||
1360 | str = make_string((child->argv + i)); | 1360 | str = make_string((child->argv + i)); |
1361 | parse_string_outer(str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING); | 1361 | parse_string_outer(str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING); |
@@ -1364,9 +1364,9 @@ static int run_pipe_real(struct pipe *pi) | |||
1364 | } | 1364 | } |
1365 | for (x = bltins; x->cmd; x++) { | 1365 | for (x = bltins; x->cmd; x++) { |
1366 | if (strcmp(child->argv[i], x->cmd) == 0 ) { | 1366 | if (strcmp(child->argv[i], x->cmd) == 0 ) { |
1367 | int squirrel[] = {-1, -1, -1}; | 1367 | int squirrel[] = { -1, -1, -1 }; |
1368 | int rcode; | 1368 | int rcode; |
1369 | if (x->function == builtin_exec && child->argv[i+1]==NULL) { | 1369 | if (x->function == builtin_exec && child->argv[i+1] == NULL) { |
1370 | debug_printf("magic exec\n"); | 1370 | debug_printf("magic exec\n"); |
1371 | setup_redirects(child,NULL); | 1371 | setup_redirects(child,NULL); |
1372 | return EXIT_SUCCESS; | 1372 | return EXIT_SUCCESS; |
@@ -1377,9 +1377,9 @@ static int run_pipe_real(struct pipe *pi) | |||
1377 | * Is it really safe for inline use? Experimentally, | 1377 | * Is it really safe for inline use? Experimentally, |
1378 | * things seem to work with glibc. */ | 1378 | * things seem to work with glibc. */ |
1379 | setup_redirects(child, squirrel); | 1379 | setup_redirects(child, squirrel); |
1380 | child->argv+=i; /* XXX horrible hack */ | 1380 | child->argv += i; /* XXX horrible hack */ |
1381 | rcode = x->function(child); | 1381 | rcode = x->function(child); |
1382 | child->argv-=i; /* XXX restore hack so free() can work right */ | 1382 | child->argv -= i; /* XXX restore hack so free() can work right */ |
1383 | restore_redirects(squirrel); | 1383 | restore_redirects(squirrel); |
1384 | return rcode; | 1384 | return rcode; |
1385 | } | 1385 | } |
@@ -1387,24 +1387,25 @@ static int run_pipe_real(struct pipe *pi) | |||
1387 | } | 1387 | } |
1388 | 1388 | ||
1389 | for (i = 0; i < pi->num_progs; i++) { | 1389 | for (i = 0; i < pi->num_progs; i++) { |
1390 | child = & (pi->progs[i]); | 1390 | child = &(pi->progs[i]); |
1391 | 1391 | ||
1392 | /* pipes are inserted between pairs of commands */ | 1392 | /* pipes are inserted between pairs of commands */ |
1393 | if ((i + 1) < pi->num_progs) { | 1393 | if ((i + 1) < pi->num_progs) { |
1394 | if (pipe(pipefds)<0) bb_perror_msg_and_die("pipe"); | 1394 | if (pipe(pipefds) < 0) |
1395 | bb_perror_msg_and_die("pipe"); | ||
1395 | nextout = pipefds[1]; | 1396 | nextout = pipefds[1]; |
1396 | } else { | 1397 | } else { |
1397 | nextout=1; | 1398 | nextout = 1; |
1398 | pipefds[0] = -1; | 1399 | pipefds[0] = -1; |
1399 | } | 1400 | } |
1400 | 1401 | ||
1401 | /* XXX test for failed fork()? */ | 1402 | /* XXX test for failed fork()? */ |
1402 | #if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__) | 1403 | #if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__) |
1403 | if (!(child->pid = fork())) | 1404 | child->pid = fork(); |
1404 | #else | 1405 | #else |
1405 | if (!(child->pid = vfork())) | 1406 | child->pid = vfork(); |
1406 | #endif | 1407 | #endif |
1407 | { | 1408 | if (!child->pid) { |
1408 | /* Set the handling for job control signals back to the default. */ | 1409 | /* Set the handling for job control signals back to the default. */ |
1409 | signal(SIGINT, SIG_DFL); | 1410 | signal(SIGINT, SIG_DFL); |
1410 | signal(SIGQUIT, SIG_DFL); | 1411 | signal(SIGQUIT, SIG_DFL); |
@@ -1446,7 +1447,6 @@ static int run_pipe_real(struct pipe *pi) | |||
1446 | pseudo_exec(child); | 1447 | pseudo_exec(child); |
1447 | } | 1448 | } |
1448 | 1449 | ||
1449 | |||
1450 | /* put our child in the process group whose leader is the | 1450 | /* put our child in the process group whose leader is the |
1451 | first process in this pipe */ | 1451 | first process in this pipe */ |
1452 | if (pi->pgrp < 0) { | 1452 | if (pi->pgrp < 0) { |
@@ -1476,81 +1476,87 @@ static int run_list_real(struct pipe *pi) | |||
1476 | struct pipe *rpipe; | 1476 | struct pipe *rpipe; |
1477 | int flag_rep = 0; | 1477 | int flag_rep = 0; |
1478 | int save_num_progs; | 1478 | int save_num_progs; |
1479 | int rcode=0, flag_skip=1; | 1479 | int rcode = 0, flag_skip = 1; |
1480 | int flag_restore = 0; | 1480 | int flag_restore = 0; |
1481 | int if_code=0, next_if_code=0; /* need double-buffer to handle elif */ | 1481 | int if_code = 0, next_if_code = 0; /* need double-buffer to handle elif */ |
1482 | reserved_style rmode, skip_more_in_this_rmode=RES_XXXX; | 1482 | reserved_style rmode, skip_more_in_this_rmode = RES_XXXX; |
1483 | /* check syntax for "for" */ | 1483 | /* check syntax for "for" */ |
1484 | for (rpipe = pi; rpipe; rpipe = rpipe->next) { | 1484 | for (rpipe = pi; rpipe; rpipe = rpipe->next) { |
1485 | if ((rpipe->r_mode == RES_IN || | 1485 | if ((rpipe->r_mode == RES_IN || rpipe->r_mode == RES_FOR) |
1486 | rpipe->r_mode == RES_FOR) && | 1486 | && (rpipe->next == NULL) |
1487 | (rpipe->next == NULL)) { | 1487 | ) { |
1488 | syntax(); | 1488 | syntax(); |
1489 | return 1; | 1489 | return 1; |
1490 | } | 1490 | } |
1491 | if ((rpipe->r_mode == RES_IN && | 1491 | if ((rpipe->r_mode == RES_IN && rpipe->next->r_mode == RES_IN && rpipe->next->progs->argv != NULL) |
1492 | (rpipe->next->r_mode == RES_IN && | 1492 | || (rpipe->r_mode == RES_FOR && rpipe->next->r_mode != RES_IN) |
1493 | rpipe->next->progs->argv != NULL))|| | 1493 | ) { |
1494 | (rpipe->r_mode == RES_FOR && | 1494 | syntax(); |
1495 | rpipe->next->r_mode != RES_IN)) { | 1495 | return 1; |
1496 | syntax(); | ||
1497 | return 1; | ||
1498 | } | 1496 | } |
1499 | } | 1497 | } |
1500 | for (; pi; pi = (flag_restore != 0) ? rpipe : pi->next) { | 1498 | for (; pi; pi = (flag_restore != 0) ? rpipe : pi->next) { |
1501 | if (pi->r_mode == RES_WHILE || pi->r_mode == RES_UNTIL || | 1499 | if (pi->r_mode == RES_WHILE || pi->r_mode == RES_UNTIL |
1502 | pi->r_mode == RES_FOR) { | 1500 | || pi->r_mode == RES_FOR |
1503 | flag_restore = 0; | 1501 | ) { |
1504 | if (!rpipe) { | 1502 | flag_restore = 0; |
1505 | flag_rep = 0; | 1503 | if (!rpipe) { |
1506 | rpipe = pi; | 1504 | flag_rep = 0; |
1507 | } | 1505 | rpipe = pi; |
1506 | } | ||
1508 | } | 1507 | } |
1509 | rmode = pi->r_mode; | 1508 | rmode = pi->r_mode; |
1510 | debug_printf("rmode=%d if_code=%d next_if_code=%d skip_more=%d\n", rmode, if_code, next_if_code, skip_more_in_this_rmode); | 1509 | debug_printf("rmode=%d if_code=%d next_if_code=%d skip_more=%d\n", |
1510 | rmode, if_code, next_if_code, skip_more_in_this_rmode); | ||
1511 | if (rmode == skip_more_in_this_rmode && flag_skip) { | 1511 | if (rmode == skip_more_in_this_rmode && flag_skip) { |
1512 | if (pi->followup == PIPE_SEQ) flag_skip=0; | 1512 | if (pi->followup == PIPE_SEQ) |
1513 | flag_skip = 0; | ||
1513 | continue; | 1514 | continue; |
1514 | } | 1515 | } |
1515 | flag_skip = 1; | 1516 | flag_skip = 1; |
1516 | skip_more_in_this_rmode = RES_XXXX; | 1517 | skip_more_in_this_rmode = RES_XXXX; |
1517 | if (rmode == RES_THEN || rmode == RES_ELSE) if_code = next_if_code; | 1518 | if (rmode == RES_THEN || rmode == RES_ELSE) |
1518 | if (rmode == RES_THEN && if_code) continue; | 1519 | if_code = next_if_code; |
1519 | if (rmode == RES_ELSE && !if_code) continue; | 1520 | if (rmode == RES_THEN && if_code) |
1520 | if (rmode == RES_ELIF && !if_code) break; | 1521 | continue; |
1522 | if (rmode == RES_ELSE && !if_code) | ||
1523 | continue; | ||
1524 | if (rmode == RES_ELIF && !if_code) | ||
1525 | break; | ||
1521 | if (rmode == RES_FOR && pi->num_progs) { | 1526 | if (rmode == RES_FOR && pi->num_progs) { |
1522 | if (!list) { | 1527 | if (!list) { |
1523 | /* if no variable values after "in" we skip "for" */ | 1528 | /* if no variable values after "in" we skip "for" */ |
1524 | if (!pi->next->progs->argv) continue; | 1529 | if (!pi->next->progs->argv) |
1530 | continue; | ||
1525 | /* create list of variable values */ | 1531 | /* create list of variable values */ |
1526 | list = make_list_in(pi->next->progs->argv, | 1532 | list = make_list_in(pi->next->progs->argv, |
1527 | pi->progs->argv[0]); | 1533 | pi->progs->argv[0]); |
1528 | save_list = list; | 1534 | save_list = list; |
1529 | save_name = pi->progs->argv[0]; | 1535 | save_name = pi->progs->argv[0]; |
1530 | pi->progs->argv[0] = NULL; | 1536 | pi->progs->argv[0] = NULL; |
1531 | flag_rep = 1; | 1537 | flag_rep = 1; |
1532 | } | 1538 | } |
1533 | if (!(*list)) { | 1539 | if (!*list) { |
1534 | free(pi->progs->argv[0]); | 1540 | free(pi->progs->argv[0]); |
1535 | free(save_list); | 1541 | free(save_list); |
1536 | list = NULL; | 1542 | list = NULL; |
1537 | flag_rep = 0; | 1543 | flag_rep = 0; |
1538 | pi->progs->argv[0] = save_name; | 1544 | pi->progs->argv[0] = save_name; |
1539 | pi->progs->glob_result.gl_pathv[0] = | 1545 | pi->progs->glob_result.gl_pathv[0] = pi->progs->argv[0]; |
1540 | pi->progs->argv[0]; | ||
1541 | continue; | 1546 | continue; |
1542 | } else { | 1547 | } else { |
1543 | /* insert new value from list for variable */ | 1548 | /* insert new value from list for variable */ |
1544 | if (pi->progs->argv[0]) | 1549 | if (pi->progs->argv[0]) |
1545 | free(pi->progs->argv[0]); | 1550 | free(pi->progs->argv[0]); |
1546 | pi->progs->argv[0] = *list++; | 1551 | pi->progs->argv[0] = *list++; |
1547 | pi->progs->glob_result.gl_pathv[0] = | 1552 | pi->progs->glob_result.gl_pathv[0] = pi->progs->argv[0]; |
1548 | pi->progs->argv[0]; | ||
1549 | } | 1553 | } |
1550 | } | 1554 | } |
1551 | if (rmode == RES_IN) continue; | 1555 | if (rmode == RES_IN) |
1556 | continue; | ||
1552 | if (rmode == RES_DO) { | 1557 | if (rmode == RES_DO) { |
1553 | if (!flag_rep) continue; | 1558 | if (!flag_rep) |
1559 | continue; | ||
1554 | } | 1560 | } |
1555 | if ((rmode == RES_DONE)) { | 1561 | if ((rmode == RES_DONE)) { |
1556 | if (flag_rep) { | 1562 | if (flag_rep) { |
@@ -1559,14 +1565,15 @@ static int run_list_real(struct pipe *pi) | |||
1559 | rpipe = NULL; | 1565 | rpipe = NULL; |
1560 | } | 1566 | } |
1561 | } | 1567 | } |
1562 | if (pi->num_progs == 0) continue; | 1568 | if (pi->num_progs == 0) |
1569 | continue; | ||
1563 | save_num_progs = pi->num_progs; /* save number of programs */ | 1570 | save_num_progs = pi->num_progs; /* save number of programs */ |
1564 | rcode = run_pipe_real(pi); | 1571 | rcode = run_pipe_real(pi); |
1565 | debug_printf("run_pipe_real returned %d\n",rcode); | 1572 | debug_printf("run_pipe_real returned %d\n",rcode); |
1566 | if (rcode!=-1) { | 1573 | if (rcode != -1) { |
1567 | /* We only ran a builtin: rcode was set by the return value | 1574 | /* We only ran a builtin: rcode was set by the return value |
1568 | * of run_pipe_real(), and we don't need to wait for anything. */ | 1575 | * of run_pipe_real(), and we don't need to wait for anything. */ |
1569 | } else if (pi->followup==PIPE_BG) { | 1576 | } else if (pi->followup == PIPE_BG) { |
1570 | /* XXX check bash's behavior with nontrivial pipes */ | 1577 | /* XXX check bash's behavior with nontrivial pipes */ |
1571 | /* XXX compute jobid */ | 1578 | /* XXX compute jobid */ |
1572 | /* XXX what does bash do with attempts to background builtins? */ | 1579 | /* XXX what does bash do with attempts to background builtins? */ |
@@ -1586,17 +1593,19 @@ static int run_list_real(struct pipe *pi) | |||
1586 | } | 1593 | } |
1587 | debug_printf("checkjobs returned %d\n",rcode); | 1594 | debug_printf("checkjobs returned %d\n",rcode); |
1588 | } | 1595 | } |
1589 | last_return_code=rcode; | 1596 | last_return_code = rcode; |
1590 | pi->num_progs = save_num_progs; /* restore number of programs */ | 1597 | pi->num_progs = save_num_progs; /* restore number of programs */ |
1591 | if ( rmode == RES_IF || rmode == RES_ELIF ) | 1598 | if ( rmode == RES_IF || rmode == RES_ELIF ) |
1592 | next_if_code=rcode; /* can be overwritten a number of times */ | 1599 | next_if_code = rcode; /* can be overwritten a number of times */ |
1593 | if (rmode == RES_WHILE) | 1600 | if (rmode == RES_WHILE) |
1594 | flag_rep = !last_return_code; | 1601 | flag_rep = !last_return_code; |
1595 | if (rmode == RES_UNTIL) | 1602 | if (rmode == RES_UNTIL) |
1596 | flag_rep = last_return_code; | 1603 | flag_rep = last_return_code; |
1597 | if ( (rcode==EXIT_SUCCESS && pi->followup==PIPE_OR) || | 1604 | if ((rcode == EXIT_SUCCESS && pi->followup == PIPE_OR) |
1598 | (rcode!=EXIT_SUCCESS && pi->followup==PIPE_AND) ) | 1605 | || (rcode != EXIT_SUCCESS && pi->followup == PIPE_AND) |
1599 | skip_more_in_this_rmode=rmode; | 1606 | ) { |
1607 | skip_more_in_this_rmode = rmode; | ||
1608 | } | ||
1600 | checkjobs(NULL); | 1609 | checkjobs(NULL); |
1601 | } | 1610 | } |
1602 | return rcode; | 1611 | return rcode; |
@@ -1608,28 +1617,28 @@ static int free_pipe(struct pipe *pi, int indent) | |||
1608 | char **p; | 1617 | char **p; |
1609 | struct child_prog *child; | 1618 | struct child_prog *child; |
1610 | struct redir_struct *r, *rnext; | 1619 | struct redir_struct *r, *rnext; |
1611 | int a, i, ret_code=0; | 1620 | int a, i, ret_code = 0; |
1612 | 1621 | ||
1613 | if (pi->stopped_progs > 0) | 1622 | if (pi->stopped_progs > 0) |
1614 | return ret_code; | 1623 | return ret_code; |
1615 | final_printf("%s run pipe: (pid %d)\n",indenter(indent),getpid()); | 1624 | final_printf("%s run pipe: (pid %d)\n", indenter(indent), getpid()); |
1616 | for (i=0; i<pi->num_progs; i++) { | 1625 | for (i = 0; i < pi->num_progs; i++) { |
1617 | child = &pi->progs[i]; | 1626 | child = &pi->progs[i]; |
1618 | final_printf("%s command %d:\n",indenter(indent),i); | 1627 | final_printf("%s command %d:\n", indenter(indent), i); |
1619 | if (child->argv) { | 1628 | if (child->argv) { |
1620 | for (a=0,p=child->argv; *p; a++,p++) { | 1629 | for (a = 0, p = child->argv; *p; a++, p++) { |
1621 | final_printf("%s argv[%d] = %s\n",indenter(indent),a,*p); | 1630 | final_printf("%s argv[%d] = %s\n", indenter(indent), a, *p); |
1622 | } | 1631 | } |
1623 | globfree(&child->glob_result); | 1632 | globfree(&child->glob_result); |
1624 | child->argv=NULL; | 1633 | child->argv = NULL; |
1625 | } else if (child->group) { | 1634 | } else if (child->group) { |
1626 | final_printf("%s begin group (subshell:%d)\n",indenter(indent), child->subshell); | 1635 | final_printf("%s begin group (subshell:%d)\n", indenter(indent), child->subshell); |
1627 | ret_code = free_pipe_list(child->group,indent+3); | 1636 | ret_code = free_pipe_list(child->group, indent+3); |
1628 | final_printf("%s end group\n",indenter(indent)); | 1637 | final_printf("%s end group\n", indenter(indent)); |
1629 | } else { | 1638 | } else { |
1630 | final_printf("%s (nil)\n",indenter(indent)); | 1639 | final_printf("%s (nil)\n", indenter(indent)); |
1631 | } | 1640 | } |
1632 | for (r=child->redirects; r; r=rnext) { | 1641 | for (r = child->redirects; r; r = rnext) { |
1633 | final_printf("%s redirect %d%s", indenter(indent), r->fd, redir_table[r->type].descrip); | 1642 | final_printf("%s redirect %d%s", indenter(indent), r->fd, redir_table[r->type].descrip); |
1634 | if (r->dup == -1) { | 1643 | if (r->dup == -1) { |
1635 | /* guard against the case >$FOO, where foo is unset or blank */ | 1644 | /* guard against the case >$FOO, where foo is unset or blank */ |
@@ -1640,26 +1649,26 @@ static int free_pipe(struct pipe *pi, int indent) | |||
1640 | } else { | 1649 | } else { |
1641 | final_printf("&%d\n", r->dup); | 1650 | final_printf("&%d\n", r->dup); |
1642 | } | 1651 | } |
1643 | rnext=r->next; | 1652 | rnext = r->next; |
1644 | free(r); | 1653 | free(r); |
1645 | } | 1654 | } |
1646 | child->redirects=NULL; | 1655 | child->redirects = NULL; |
1647 | } | 1656 | } |
1648 | free(pi->progs); /* children are an array, they get freed all at once */ | 1657 | free(pi->progs); /* children are an array, they get freed all at once */ |
1649 | pi->progs=NULL; | 1658 | pi->progs = NULL; |
1650 | return ret_code; | 1659 | return ret_code; |
1651 | } | 1660 | } |
1652 | 1661 | ||
1653 | static int free_pipe_list(struct pipe *head, int indent) | 1662 | static int free_pipe_list(struct pipe *head, int indent) |
1654 | { | 1663 | { |
1655 | int rcode=0; /* if list has no members */ | 1664 | int rcode = 0; /* if list has no members */ |
1656 | struct pipe *pi, *next; | 1665 | struct pipe *pi, *next; |
1657 | for (pi=head; pi; pi=next) { | 1666 | for (pi = head; pi; pi = next) { |
1658 | final_printf("%s pipe reserved mode %d\n", indenter(indent), pi->r_mode); | 1667 | final_printf("%s pipe reserved mode %d\n", indenter(indent), pi->r_mode); |
1659 | rcode = free_pipe(pi, indent); | 1668 | rcode = free_pipe(pi, indent); |
1660 | final_printf("%s pipe followup code %d\n", indenter(indent), pi->followup); | 1669 | final_printf("%s pipe followup code %d\n", indenter(indent), pi->followup); |
1661 | next=pi->next; | 1670 | next = pi->next; |
1662 | pi->next=NULL; | 1671 | pi->next = NULL; |
1663 | free(pi); | 1672 | free(pi); |
1664 | } | 1673 | } |
1665 | return rcode; | 1674 | return rcode; |
@@ -1668,8 +1677,8 @@ static int free_pipe_list(struct pipe *head, int indent) | |||
1668 | /* Select which version we will use */ | 1677 | /* Select which version we will use */ |
1669 | static int run_list(struct pipe *pi) | 1678 | static int run_list(struct pipe *pi) |
1670 | { | 1679 | { |
1671 | int rcode=0; | 1680 | int rcode = 0; |
1672 | if (fake_mode==0) { | 1681 | if (fake_mode == 0) { |
1673 | rcode = run_list_real(pi); | 1682 | rcode = run_list_real(pi); |
1674 | } | 1683 | } |
1675 | /* free_pipe_list has the side effect of clearing memory | 1684 | /* free_pipe_list has the side effect of clearing memory |
@@ -1688,31 +1697,31 @@ static int run_list(struct pipe *pi) | |||
1688 | */ | 1697 | */ |
1689 | static int globhack(const char *src, int flags, glob_t *pglob) | 1698 | static int globhack(const char *src, int flags, glob_t *pglob) |
1690 | { | 1699 | { |
1691 | int cnt=0, pathc; | 1700 | int cnt = 0, pathc; |
1692 | const char *s; | 1701 | const char *s; |
1693 | char *dest; | 1702 | char *dest; |
1694 | for (cnt=1, s=src; s && *s; s++) { | 1703 | for (cnt = 1, s = src; s && *s; s++) { |
1695 | if (*s == '\\') s++; | 1704 | if (*s == '\\') s++; |
1696 | cnt++; | 1705 | cnt++; |
1697 | } | 1706 | } |
1698 | dest = malloc(cnt); | 1707 | dest = malloc(cnt); |
1699 | if (!dest) return GLOB_NOSPACE; | 1708 | if (!dest) return GLOB_NOSPACE; |
1700 | if (!(flags & GLOB_APPEND)) { | 1709 | if (!(flags & GLOB_APPEND)) { |
1701 | pglob->gl_pathv=NULL; | 1710 | pglob->gl_pathv = NULL; |
1702 | pglob->gl_pathc=0; | 1711 | pglob->gl_pathc = 0; |
1703 | pglob->gl_offs=0; | 1712 | pglob->gl_offs = 0; |
1704 | pglob->gl_offs=0; | 1713 | pglob->gl_offs = 0; |
1705 | } | 1714 | } |
1706 | pathc = ++pglob->gl_pathc; | 1715 | pathc = ++pglob->gl_pathc; |
1707 | pglob->gl_pathv = realloc(pglob->gl_pathv, (pathc+1)*sizeof(*pglob->gl_pathv)); | 1716 | pglob->gl_pathv = realloc(pglob->gl_pathv, (pathc+1)*sizeof(*pglob->gl_pathv)); |
1708 | if (pglob->gl_pathv == NULL) return GLOB_NOSPACE; | 1717 | if (pglob->gl_pathv == NULL) return GLOB_NOSPACE; |
1709 | pglob->gl_pathv[pathc-1]=dest; | 1718 | pglob->gl_pathv[pathc-1] = dest; |
1710 | pglob->gl_pathv[pathc]=NULL; | 1719 | pglob->gl_pathv[pathc] = NULL; |
1711 | for (s=src; s && *s; s++, dest++) { | 1720 | for (s = src; s && *s; s++, dest++) { |
1712 | if (*s == '\\') s++; | 1721 | if (*s == '\\') s++; |
1713 | *dest = *s; | 1722 | *dest = *s; |
1714 | } | 1723 | } |
1715 | *dest='\0'; | 1724 | *dest = '\0'; |
1716 | return 0; | 1725 | return 0; |
1717 | } | 1726 | } |
1718 | 1727 | ||
@@ -1721,7 +1730,7 @@ static int glob_needed(const char *s) | |||
1721 | { | 1730 | { |
1722 | for (; *s; s++) { | 1731 | for (; *s; s++) { |
1723 | if (*s == '\\') s++; | 1732 | if (*s == '\\') s++; |
1724 | if (strchr("*[?",*s)) return 1; | 1733 | if (strchr("*[?", *s)) return 1; |
1725 | } | 1734 | } |
1726 | return 0; | 1735 | return 0; |
1727 | } | 1736 | } |
@@ -1736,26 +1745,26 @@ static int xglob(o_string *dest, int flags, glob_t *pglob) | |||
1736 | if (dest->nonnull) { | 1745 | if (dest->nonnull) { |
1737 | /* bash man page calls this an "explicit" null */ | 1746 | /* bash man page calls this an "explicit" null */ |
1738 | gr = globhack(dest->data, flags, pglob); | 1747 | gr = globhack(dest->data, flags, pglob); |
1739 | debug_printf("globhack returned %d\n",gr); | 1748 | debug_printf("globhack returned %d\n", gr); |
1740 | } else { | 1749 | } else { |
1741 | return 0; | 1750 | return 0; |
1742 | } | 1751 | } |
1743 | } else if (glob_needed(dest->data)) { | 1752 | } else if (glob_needed(dest->data)) { |
1744 | gr = glob(dest->data, flags, NULL, pglob); | 1753 | gr = glob(dest->data, flags, NULL, pglob); |
1745 | debug_printf("glob returned %d\n",gr); | 1754 | debug_printf("glob returned %d\n", gr); |
1746 | if (gr == GLOB_NOMATCH) { | 1755 | if (gr == GLOB_NOMATCH) { |
1747 | /* quote removal, or more accurately, backslash removal */ | 1756 | /* quote removal, or more accurately, backslash removal */ |
1748 | gr = globhack(dest->data, flags, pglob); | 1757 | gr = globhack(dest->data, flags, pglob); |
1749 | debug_printf("globhack returned %d\n",gr); | 1758 | debug_printf("globhack returned %d\n", gr); |
1750 | } | 1759 | } |
1751 | } else { | 1760 | } else { |
1752 | gr = globhack(dest->data, flags, pglob); | 1761 | gr = globhack(dest->data, flags, pglob); |
1753 | debug_printf("globhack returned %d\n",gr); | 1762 | debug_printf("globhack returned %d\n", gr); |
1754 | } | 1763 | } |
1755 | if (gr == GLOB_NOSPACE) | 1764 | if (gr == GLOB_NOSPACE) |
1756 | bb_error_msg_and_die("out of memory during glob"); | 1765 | bb_error_msg_and_die("out of memory during glob"); |
1757 | if (gr != 0) { /* GLOB_ABORTED ? */ | 1766 | if (gr != 0) { /* GLOB_ABORTED ? */ |
1758 | bb_error_msg("glob(3) error %d",gr); | 1767 | bb_error_msg("glob(3) error %d", gr); |
1759 | } | 1768 | } |
1760 | /* globprint(glob_target); */ | 1769 | /* globprint(glob_target); */ |
1761 | return gr; | 1770 | return gr; |
@@ -1768,8 +1777,8 @@ static const char *get_local_var(const char *s) | |||
1768 | 1777 | ||
1769 | if (!s) | 1778 | if (!s) |
1770 | return NULL; | 1779 | return NULL; |
1771 | for (cur = top_vars; cur; cur=cur->next) | 1780 | for (cur = top_vars; cur; cur = cur->next) |
1772 | if(strcmp(cur->name, s)==0) | 1781 | if (strcmp(cur->name, s) == 0) |
1773 | return cur->value; | 1782 | return cur->value; |
1774 | return NULL; | 1783 | return NULL; |
1775 | } | 1784 | } |
@@ -1781,39 +1790,39 @@ static const char *get_local_var(const char *s) | |||
1781 | static int set_local_var(const char *s, int flg_export) | 1790 | static int set_local_var(const char *s, int flg_export) |
1782 | { | 1791 | { |
1783 | char *name, *value; | 1792 | char *name, *value; |
1784 | int result=0; | 1793 | int result = 0; |
1785 | struct variables *cur; | 1794 | struct variables *cur; |
1786 | 1795 | ||
1787 | name=strdup(s); | 1796 | name = strdup(s); |
1788 | 1797 | ||
1789 | /* Assume when we enter this function that we are already in | 1798 | /* Assume when we enter this function that we are already in |
1790 | * NAME=VALUE format. So the first order of business is to | 1799 | * NAME=VALUE format. So the first order of business is to |
1791 | * split 's' on the '=' into 'name' and 'value' */ | 1800 | * split 's' on the '=' into 'name' and 'value' */ |
1792 | value = strchr(name, '='); | 1801 | value = strchr(name, '='); |
1793 | if (value==0 && ++value==0) { | 1802 | if (value == 0 && ++value == 0) { |
1794 | free(name); | 1803 | free(name); |
1795 | return -1; | 1804 | return -1; |
1796 | } | 1805 | } |
1797 | *value++ = 0; | 1806 | *value++ = 0; |
1798 | 1807 | ||
1799 | for(cur = top_vars; cur; cur = cur->next) { | 1808 | for (cur = top_vars; cur; cur = cur->next) { |
1800 | if(strcmp(cur->name, name)==0) | 1809 | if (strcmp(cur->name, name) == 0) |
1801 | break; | 1810 | break; |
1802 | } | 1811 | } |
1803 | 1812 | ||
1804 | if(cur) { | 1813 | if (cur) { |
1805 | if(strcmp(cur->value, value)==0) { | 1814 | if (strcmp(cur->value, value) == 0) { |
1806 | if(flg_export>0 && cur->flg_export==0) | 1815 | if (flg_export>0 && cur->flg_export == 0) |
1807 | cur->flg_export = flg_export; | 1816 | cur->flg_export = flg_export; |
1808 | else | 1817 | else |
1809 | result++; | 1818 | result++; |
1810 | } else { | 1819 | } else { |
1811 | if(cur->flg_read_only) { | 1820 | if (cur->flg_read_only) { |
1812 | bb_error_msg("%s: readonly variable", name); | 1821 | bb_error_msg("%s: readonly variable", name); |
1813 | result = -1; | 1822 | result = -1; |
1814 | } else { | 1823 | } else { |
1815 | if(flg_export>0 || cur->flg_export>1) | 1824 | if (flg_export > 0 || cur->flg_export>1) |
1816 | cur->flg_export=1; | 1825 | cur->flg_export = 1; |
1817 | free((char*)cur->value); | 1826 | free((char*)cur->value); |
1818 | 1827 | ||
1819 | cur->value = strdup(value); | 1828 | cur->value = strdup(value); |
@@ -1821,11 +1830,11 @@ static int set_local_var(const char *s, int flg_export) | |||
1821 | } | 1830 | } |
1822 | } else { | 1831 | } else { |
1823 | cur = malloc(sizeof(struct variables)); | 1832 | cur = malloc(sizeof(struct variables)); |
1824 | if(!cur) { | 1833 | if (!cur) { |
1825 | result = -1; | 1834 | result = -1; |
1826 | } else { | 1835 | } else { |
1827 | cur->name = strdup(name); | 1836 | cur->name = strdup(name); |
1828 | if(cur->name == 0) { | 1837 | if (cur->name) { |
1829 | free(cur); | 1838 | free(cur); |
1830 | result = -1; | 1839 | result = -1; |
1831 | } else { | 1840 | } else { |
@@ -1834,18 +1843,19 @@ static int set_local_var(const char *s, int flg_export) | |||
1834 | cur->next = 0; | 1843 | cur->next = 0; |
1835 | cur->flg_export = flg_export; | 1844 | cur->flg_export = flg_export; |
1836 | cur->flg_read_only = 0; | 1845 | cur->flg_read_only = 0; |
1837 | while(bottom->next) bottom=bottom->next; | 1846 | while (bottom->next) |
1847 | bottom = bottom->next; | ||
1838 | bottom->next = cur; | 1848 | bottom->next = cur; |
1839 | } | 1849 | } |
1840 | } | 1850 | } |
1841 | } | 1851 | } |
1842 | 1852 | ||
1843 | if(result==0 && cur->flg_export==1) { | 1853 | if (result == 0 && cur->flg_export == 1) { |
1844 | *(value-1) = '='; | 1854 | *(value-1) = '='; |
1845 | result = putenv(name); | 1855 | result = putenv(name); |
1846 | } else { | 1856 | } else { |
1847 | free(name); | 1857 | free(name); |
1848 | if(result>0) /* equivalent to previous set */ | 1858 | if (result > 0) /* equivalent to previous set */ |
1849 | result = 0; | 1859 | result = 0; |
1850 | } | 1860 | } |
1851 | return result; | 1861 | return result; |
@@ -1856,24 +1866,23 @@ static void unset_local_var(const char *name) | |||
1856 | struct variables *cur; | 1866 | struct variables *cur; |
1857 | 1867 | ||
1858 | if (name) { | 1868 | if (name) { |
1859 | for (cur = top_vars; cur; cur=cur->next) { | 1869 | for (cur = top_vars; cur; cur = cur->next) { |
1860 | if(strcmp(cur->name, name)==0) | 1870 | if (strcmp(cur->name, name) == 0) |
1861 | break; | 1871 | break; |
1862 | } | 1872 | } |
1863 | if(cur!=0) { | 1873 | if (cur != 0) { |
1864 | struct variables *next = top_vars; | 1874 | struct variables *next = top_vars; |
1865 | if(cur->flg_read_only) { | 1875 | if (cur->flg_read_only) { |
1866 | bb_error_msg("%s: readonly variable", name); | 1876 | bb_error_msg("%s: readonly variable", name); |
1867 | return; | 1877 | return; |
1868 | } else { | ||
1869 | if(cur->flg_export) | ||
1870 | unsetenv(cur->name); | ||
1871 | free((char*)cur->name); | ||
1872 | free((char*)cur->value); | ||
1873 | while (next->next != cur) | ||
1874 | next = next->next; | ||
1875 | next->next = cur->next; | ||
1876 | } | 1878 | } |
1879 | if (cur->flg_export) | ||
1880 | unsetenv(cur->name); | ||
1881 | free((char*)cur->name); | ||
1882 | free((char*)cur->value); | ||
1883 | while (next->next != cur) | ||
1884 | next = next->next; | ||
1885 | next->next = cur->next; | ||
1877 | free(cur); | 1886 | free(cur); |
1878 | } | 1887 | } |
1879 | } | 1888 | } |
@@ -1881,10 +1890,12 @@ static void unset_local_var(const char *name) | |||
1881 | 1890 | ||
1882 | static int is_assignment(const char *s) | 1891 | static int is_assignment(const char *s) |
1883 | { | 1892 | { |
1884 | if (s==NULL || !isalpha(*s)) return 0; | 1893 | if (!s || !isalpha(*s)) |
1885 | ++s; | 1894 | return 0; |
1886 | while(isalnum(*s) || *s=='_') ++s; | 1895 | s++; |
1887 | return *s=='='; | 1896 | while (isalnum(*s) || *s == '_') |
1897 | s++; | ||
1898 | return *s == '='; | ||
1888 | } | 1899 | } |
1889 | 1900 | ||
1890 | /* the src parameter allows us to peek forward to a possible &n syntax | 1901 | /* the src parameter allows us to peek forward to a possible &n syntax |
@@ -1894,26 +1905,26 @@ static int is_assignment(const char *s) | |||
1894 | static int setup_redirect(struct p_context *ctx, int fd, redir_type style, | 1905 | static int setup_redirect(struct p_context *ctx, int fd, redir_type style, |
1895 | struct in_str *input) | 1906 | struct in_str *input) |
1896 | { | 1907 | { |
1897 | struct child_prog *child=ctx->child; | 1908 | struct child_prog *child = ctx->child; |
1898 | struct redir_struct *redir = child->redirects; | 1909 | struct redir_struct *redir = child->redirects; |
1899 | struct redir_struct *last_redir=NULL; | 1910 | struct redir_struct *last_redir = NULL; |
1900 | 1911 | ||
1901 | /* Create a new redir_struct and drop it onto the end of the linked list */ | 1912 | /* Create a new redir_struct and drop it onto the end of the linked list */ |
1902 | while(redir) { | 1913 | while (redir) { |
1903 | last_redir=redir; | 1914 | last_redir = redir; |
1904 | redir=redir->next; | 1915 | redir = redir->next; |
1905 | } | 1916 | } |
1906 | redir = xmalloc(sizeof(struct redir_struct)); | 1917 | redir = xmalloc(sizeof(struct redir_struct)); |
1907 | redir->next=NULL; | 1918 | redir->next = NULL; |
1908 | redir->word.gl_pathv=NULL; | 1919 | redir->word.gl_pathv = NULL; |
1909 | if (last_redir) { | 1920 | if (last_redir) { |
1910 | last_redir->next=redir; | 1921 | last_redir->next = redir; |
1911 | } else { | 1922 | } else { |
1912 | child->redirects=redir; | 1923 | child->redirects = redir; |
1913 | } | 1924 | } |
1914 | 1925 | ||
1915 | redir->type=style; | 1926 | redir->type = style; |
1916 | redir->fd= (fd==-1) ? redir_table[style].default_fd : fd ; | 1927 | redir->fd = (fd == -1) ? redir_table[style].default_fd : fd; |
1917 | 1928 | ||
1918 | debug_printf("Redirect type %d%s\n", redir->fd, redir_table[style].descrip); | 1929 | debug_printf("Redirect type %d%s\n", redir->fd, redir_table[style].descrip); |
1919 | 1930 | ||
@@ -1949,14 +1960,14 @@ static struct pipe *new_pipe(void) { | |||
1949 | 1960 | ||
1950 | static void initialize_context(struct p_context *ctx) | 1961 | static void initialize_context(struct p_context *ctx) |
1951 | { | 1962 | { |
1952 | ctx->pipe=NULL; | 1963 | ctx->pipe = NULL; |
1953 | ctx->pending_redirect=NULL; | 1964 | ctx->pending_redirect = NULL; |
1954 | ctx->child=NULL; | 1965 | ctx->child = NULL; |
1955 | ctx->list_head=new_pipe(); | 1966 | ctx->list_head = new_pipe(); |
1956 | ctx->pipe=ctx->list_head; | 1967 | ctx->pipe = ctx->list_head; |
1957 | ctx->w=RES_NONE; | 1968 | ctx->w = RES_NONE; |
1958 | ctx->stack=NULL; | 1969 | ctx->stack = NULL; |
1959 | ctx->old_flag=0; | 1970 | ctx->old_flag = 0; |
1960 | done_command(ctx); /* creates the memory for working child */ | 1971 | done_command(ctx); /* creates the memory for working child */ |
1961 | } | 1972 | } |
1962 | 1973 | ||
@@ -1991,9 +2002,8 @@ static int reserved_word(o_string *dest, struct p_context *ctx) | |||
1991 | { "done", RES_DONE, FLAG_END } | 2002 | { "done", RES_DONE, FLAG_END } |
1992 | }; | 2003 | }; |
1993 | struct reserved_combo *r; | 2004 | struct reserved_combo *r; |
1994 | for (r=reserved_list; | ||
1995 | #define NRES sizeof(reserved_list)/sizeof(struct reserved_combo) | 2005 | #define NRES sizeof(reserved_list)/sizeof(struct reserved_combo) |
1996 | r<reserved_list+NRES; r++) { | 2006 | for (r = reserved_list; r < reserved_list+NRES; r++) { |
1997 | if (strcmp(dest->data, r->literal) == 0) { | 2007 | if (strcmp(dest->data, r->literal) == 0) { |
1998 | debug_printf("found reserved word %s, code %d\n",r->literal,r->code); | 2008 | debug_printf("found reserved word %s, code %d\n",r->literal,r->code); |
1999 | if (r->flag & FLAG_START) { | 2009 | if (r->flag & FLAG_START) { |
@@ -2180,7 +2190,7 @@ static int redirect_opt_num(o_string *o) | |||
2180 | int num; | 2190 | int num; |
2181 | 2191 | ||
2182 | if (o->length==0) return -1; | 2192 | if (o->length==0) return -1; |
2183 | for(num=0; num<o->length; num++) { | 2193 | for (num=0; num<o->length; num++) { |
2184 | if (!isdigit(*(o->data+num))) { | 2194 | if (!isdigit(*(o->data+num))) { |
2185 | return -1; | 2195 | return -1; |
2186 | } | 2196 | } |
@@ -2310,7 +2320,7 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i | |||
2310 | if (isalpha(ch)) { | 2320 | if (isalpha(ch)) { |
2311 | b_addchr(dest, SPECIAL_VAR_SYMBOL); | 2321 | b_addchr(dest, SPECIAL_VAR_SYMBOL); |
2312 | ctx->child->sp++; | 2322 | ctx->child->sp++; |
2313 | while(ch=b_peek(input),isalnum(ch) || ch=='_') { | 2323 | while (ch=b_peek(input),isalnum(ch) || ch=='_') { |
2314 | b_getch(input); | 2324 | b_getch(input); |
2315 | b_addchr(dest,ch); | 2325 | b_addchr(dest,ch); |
2316 | } | 2326 | } |
@@ -2343,7 +2353,7 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i | |||
2343 | ctx->child->sp++; | 2353 | ctx->child->sp++; |
2344 | b_getch(input); | 2354 | b_getch(input); |
2345 | /* XXX maybe someone will try to escape the '}' */ | 2355 | /* XXX maybe someone will try to escape the '}' */ |
2346 | while(ch=b_getch(input),ch!=EOF && ch!='}') { | 2356 | while (ch=b_getch(input),ch!=EOF && ch!='}') { |
2347 | b_addchr(dest,ch); | 2357 | b_addchr(dest,ch); |
2348 | } | 2358 | } |
2349 | if (ch != '}') { | 2359 | if (ch != '}') { |
@@ -2427,7 +2437,12 @@ int parse_stream(o_string *dest, struct p_context *ctx, | |||
2427 | if (m!=2) switch (ch) { | 2437 | if (m!=2) switch (ch) { |
2428 | case '#': | 2438 | case '#': |
2429 | if (dest->length == 0 && !dest->quote) { | 2439 | if (dest->length == 0 && !dest->quote) { |
2430 | while(ch=b_peek(input),ch!=EOF && ch!='\n') { b_getch(input); } | 2440 | while (1) { |
2441 | ch = b_peek(input); | ||
2442 | if (ch == EOF || ch == '\n') | ||
2443 | break; | ||
2444 | b_getch(input); | ||
2445 | } | ||
2431 | } else { | 2446 | } else { |
2432 | b_addqchr(dest, ch, dest->quote); | 2447 | b_addqchr(dest, ch, dest->quote); |
2433 | } | 2448 | } |
@@ -2445,10 +2460,13 @@ int parse_stream(o_string *dest, struct p_context *ctx, | |||
2445 | break; | 2460 | break; |
2446 | case '\'': | 2461 | case '\'': |
2447 | dest->nonnull = 1; | 2462 | dest->nonnull = 1; |
2448 | while(ch=b_getch(input),ch!=EOF && ch!='\'') { | 2463 | while (1) { |
2464 | ch = b_getch(input); | ||
2465 | if (ch == EOF || ch == '\'') | ||
2466 | break; | ||
2449 | b_addchr(dest,ch); | 2467 | b_addchr(dest,ch); |
2450 | } | 2468 | } |
2451 | if (ch==EOF) { | 2469 | if (ch == EOF) { |
2452 | syntax(); | 2470 | syntax(); |
2453 | return 1; | 2471 | return 1; |
2454 | } | 2472 | } |
@@ -2766,7 +2784,7 @@ int hush_main(int argc, char **argv) | |||
2766 | free((char*)cwd); | 2784 | free((char*)cwd); |
2767 | { | 2785 | { |
2768 | struct variables *cur, *tmp; | 2786 | struct variables *cur, *tmp; |
2769 | for(cur = top_vars; cur; cur = tmp) { | 2787 | for (cur = top_vars; cur; cur = tmp) { |
2770 | tmp = cur->next; | 2788 | tmp = cur->next; |
2771 | if (!cur->flg_read_only) { | 2789 | if (!cur->flg_read_only) { |
2772 | free(cur->name); | 2790 | free(cur->name); |