diff options
| author | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2001-05-07 17:59:25 +0000 |
|---|---|---|
| committer | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2001-05-07 17:59:25 +0000 |
| commit | 44f9c566b3f317e2d22f815c258b78f8a2000539 (patch) | |
| tree | 1d7aef0d43ccb92fd704280dc621cc6f33d5a4ef /shell | |
| parent | b210450df88c46cc659efea7e2819b6bea7c252e (diff) | |
| download | busybox-w32-44f9c566b3f317e2d22f815c258b78f8a2000539.tar.gz busybox-w32-44f9c566b3f317e2d22f815c258b78f8a2000539.tar.bz2 busybox-w32-44f9c566b3f317e2d22f815c258b78f8a2000539.zip | |
More hush updates from Larry:
Update some comments. Generate partial placeholders for the missing
builtins. Write builtin_umask. Properly treat exec without arguments
as a means to open/close files within the running script. Implement
"4<&-" that encodes for file descriptor closure.
git-svn-id: svn://busybox.net/trunk/busybox@2555 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/hush.c | 73 |
1 files changed, 54 insertions, 19 deletions
diff --git a/shell/hush.c b/shell/hush.c index b8e4a55c2..e58ac44b3 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -45,24 +45,25 @@ | |||
| 45 | * fancy forms of Parameter Expansion | 45 | * fancy forms of Parameter Expansion |
| 46 | * Arithmetic Expansion | 46 | * Arithmetic Expansion |
| 47 | * <(list) and >(list) Process Substitution | 47 | * <(list) and >(list) Process Substitution |
| 48 | * reserved words: case, esac, function | 48 | * reserved words: case, esac, select, function |
| 49 | * Here Documents ( << word ) | 49 | * Here Documents ( << word ) |
| 50 | * Functions | 50 | * Functions |
| 51 | * Major bugs: | 51 | * Major bugs: |
| 52 | * job handling woefully incomplete and buggy | 52 | * job handling woefully incomplete and buggy |
| 53 | * reserved word execution woefully incomplete and buggy | 53 | * reserved word execution woefully incomplete and buggy |
| 54 | * to-do: | 54 | * to-do: |
| 55 | * port selected bugfixes from post-0.49 busybox lash | 55 | * port selected bugfixes from post-0.49 busybox lash - done? |
| 56 | * finish implementing reserved words | 56 | * finish implementing reserved words: for, while, until, do, done |
| 57 | * change { and } from special chars to reserved words | ||
| 58 | * builtins: break, continue, eval, return, set, trap, ulimit | ||
| 59 | * test magic exec | ||
| 57 | * handle children going into background | 60 | * handle children going into background |
| 58 | * clean up recognition of null pipes | 61 | * clean up recognition of null pipes |
| 59 | * have builtin_exec set flag to avoid restore_redirects | 62 | * have builtin_exec set flag to avoid restore_redirects |
| 60 | * figure out if "echo foo}" is fixable | ||
| 61 | * check setting of global_argc and global_argv | 63 | * check setting of global_argc and global_argv |
| 62 | * control-C handling, probably with longjmp | 64 | * control-C handling, probably with longjmp |
| 63 | * VAR=value prefix for simple commands | 65 | * VAR=value prefix for simple commands |
| 64 | * follow IFS rules more precisely, including update semantics | 66 | * follow IFS rules more precisely, including update semantics |
| 65 | * write builtin_eval, builtin_ulimit, builtin_umask | ||
| 66 | * figure out what to do with backslash-newline | 67 | * figure out what to do with backslash-newline |
| 67 | * explain why we use signal instead of sigaction | 68 | * explain why we use signal instead of sigaction |
| 68 | * propagate syntax errors, die on resource errors? | 69 | * propagate syntax errors, die on resource errors? |
| @@ -97,6 +98,7 @@ | |||
| 97 | #include <fcntl.h> | 98 | #include <fcntl.h> |
| 98 | #include <getopt.h> /* should be pretty obvious */ | 99 | #include <getopt.h> /* should be pretty obvious */ |
| 99 | 100 | ||
| 101 | #include <sys/stat.h> /* ulimit */ | ||
| 100 | #include <sys/types.h> | 102 | #include <sys/types.h> |
| 101 | #include <sys/wait.h> | 103 | #include <sys/wait.h> |
| 102 | #include <signal.h> | 104 | #include <signal.h> |
| @@ -323,9 +325,9 @@ static int builtin_pwd(struct child_prog *child); | |||
| 323 | static int builtin_read(struct child_prog *child); | 325 | static int builtin_read(struct child_prog *child); |
| 324 | static int builtin_shift(struct child_prog *child); | 326 | static int builtin_shift(struct child_prog *child); |
| 325 | static int builtin_source(struct child_prog *child); | 327 | static int builtin_source(struct child_prog *child); |
| 326 | static int builtin_ulimit(struct child_prog *child); | ||
| 327 | static int builtin_umask(struct child_prog *child); | 328 | static int builtin_umask(struct child_prog *child); |
| 328 | static int builtin_unset(struct child_prog *child); | 329 | static int builtin_unset(struct child_prog *child); |
| 330 | static int builtin_not_written(struct child_prog *child); | ||
| 329 | /* o_string manipulation: */ | 331 | /* o_string manipulation: */ |
| 330 | static int b_check_space(o_string *o, int len); | 332 | static int b_check_space(o_string *o, int len); |
| 331 | static int b_addchr(o_string *o, int ch); | 333 | static int b_addchr(o_string *o, int ch); |
| @@ -390,8 +392,11 @@ static void free_pipe(struct pipe *pi); | |||
| 390 | * still be set at the end. */ | 392 | * still be set at the end. */ |
| 391 | static struct built_in_command bltins[] = { | 393 | static struct built_in_command bltins[] = { |
| 392 | {"bg", "Resume a job in the background", builtin_fg_bg}, | 394 | {"bg", "Resume a job in the background", builtin_fg_bg}, |
| 395 | {"break", "Exit for, while or until loop", builtin_not_written}, | ||
| 393 | {"cd", "Change working directory", builtin_cd}, | 396 | {"cd", "Change working directory", builtin_cd}, |
| 397 | {"continue", "Continue for, while or until loop", builtin_not_written}, | ||
| 394 | {"env", "Print all environment variables", builtin_env}, | 398 | {"env", "Print all environment variables", builtin_env}, |
| 399 | {"eval", "Construct and run shell command", builtin_not_written}, | ||
| 395 | {"exec", "Exec command, replacing this shell with the exec'd process", builtin_exec}, | 400 | {"exec", "Exec command, replacing this shell with the exec'd process", builtin_exec}, |
| 396 | {"exit", "Exit from shell()", builtin_exit}, | 401 | {"exit", "Exit from shell()", builtin_exit}, |
| 397 | {"export", "Set environment variable", builtin_export}, | 402 | {"export", "Set environment variable", builtin_export}, |
| @@ -399,8 +404,11 @@ static struct built_in_command bltins[] = { | |||
| 399 | {"jobs", "Lists the active jobs", builtin_jobs}, | 404 | {"jobs", "Lists the active jobs", builtin_jobs}, |
| 400 | {"pwd", "Print current directory", builtin_pwd}, | 405 | {"pwd", "Print current directory", builtin_pwd}, |
| 401 | {"read", "Input environment variable", builtin_read}, | 406 | {"read", "Input environment variable", builtin_read}, |
| 407 | {"return", "Return from a function", builtin_not_written}, | ||
| 408 | {"set", "Set/unset shell options", builtin_not_written}, | ||
| 402 | {"shift", "Shift positional parameters", builtin_shift}, | 409 | {"shift", "Shift positional parameters", builtin_shift}, |
| 403 | {"ulimit","Controls resource limits", builtin_ulimit}, | 410 | {"trap", "Trap signals", builtin_not_written}, |
| 411 | {"ulimit","Controls resource limits", builtin_not_written}, | ||
| 404 | {"umask","Sets file creation mask", builtin_umask}, | 412 | {"umask","Sets file creation mask", builtin_umask}, |
| 405 | {"unset", "Unset environment variable", builtin_unset}, | 413 | {"unset", "Unset environment variable", builtin_unset}, |
| 406 | {".", "Source-in and run commands in a file", builtin_source}, | 414 | {".", "Source-in and run commands in a file", builtin_source}, |
| @@ -640,16 +648,21 @@ static int builtin_source(struct child_prog *child) | |||
| 640 | return (status); | 648 | return (status); |
| 641 | } | 649 | } |
| 642 | 650 | ||
| 643 | static int builtin_ulimit(struct child_prog *child) | ||
| 644 | { | ||
| 645 | printf("builtin_ulimit not written\n"); | ||
| 646 | return EXIT_FAILURE; | ||
| 647 | } | ||
| 648 | |||
| 649 | static int builtin_umask(struct child_prog *child) | 651 | static int builtin_umask(struct child_prog *child) |
| 650 | { | 652 | { |
| 651 | printf("builtin_umask not written\n"); | 653 | mode_t new_umask; |
| 652 | return EXIT_FAILURE; | 654 | const char *arg = child->argv[1]; |
| 655 | char *end; | ||
| 656 | if (arg) { | ||
| 657 | new_umask=strtoul(arg, &end, 8); | ||
| 658 | if (*end!='\0' || end == arg) { | ||
| 659 | return EXIT_FAILURE; | ||
| 660 | } | ||
| 661 | } else { | ||
| 662 | printf("%.3o\n", (unsigned int) (new_umask=umask(0))); | ||
| 663 | } | ||
| 664 | umask(new_umask); | ||
| 665 | return EXIT_SUCCESS; | ||
| 653 | } | 666 | } |
| 654 | 667 | ||
| 655 | /* built-in 'unset VAR' handler */ | 668 | /* built-in 'unset VAR' handler */ |
| @@ -663,6 +676,12 @@ static int builtin_unset(struct child_prog *child) | |||
| 663 | return EXIT_SUCCESS; | 676 | return EXIT_SUCCESS; |
| 664 | } | 677 | } |
| 665 | 678 | ||
| 679 | static int builtin_not_written(struct child_prog *child) | ||
| 680 | { | ||
| 681 | printf("builtin_%s not written\n",child->argv[0]); | ||
| 682 | return EXIT_FAILURE; | ||
| 683 | } | ||
| 684 | |||
| 666 | static int b_check_space(o_string *o, int len) | 685 | static int b_check_space(o_string *o, int len) |
| 667 | { | 686 | { |
| 668 | /* It would be easy to drop a more restrictive policy | 687 | /* It would be easy to drop a more restrictive policy |
| @@ -926,8 +945,12 @@ static int setup_redirects(struct child_prog *prog, int squirrel[]) | |||
| 926 | if (squirrel && redir->fd < 3) { | 945 | if (squirrel && redir->fd < 3) { |
| 927 | squirrel[redir->fd] = dup(redir->fd); | 946 | squirrel[redir->fd] = dup(redir->fd); |
| 928 | } | 947 | } |
| 929 | dup2(openfd, redir->fd); | 948 | if (openfd == -3) { |
| 930 | close(openfd); | 949 | close(openfd); |
| 950 | } else { | ||
| 951 | dup2(openfd, redir->fd); | ||
| 952 | close(openfd); | ||
| 953 | } | ||
| 931 | } | 954 | } |
| 932 | } | 955 | } |
| 933 | return 0; | 956 | return 0; |
| @@ -1216,6 +1239,11 @@ static int run_pipe_real(struct pipe *pi) | |||
| 1216 | if (strcmp(child->argv[0], x->cmd) == 0 ) { | 1239 | if (strcmp(child->argv[0], x->cmd) == 0 ) { |
| 1217 | int squirrel[] = {-1, -1, -1}; | 1240 | int squirrel[] = {-1, -1, -1}; |
| 1218 | int rcode; | 1241 | int rcode; |
| 1242 | if (x->function == builtin_exec && child->argv[1]==NULL) { | ||
| 1243 | debug_printf("magic exec\n"); | ||
| 1244 | setup_redirects(child,NULL); | ||
| 1245 | return EXIT_SUCCESS; | ||
| 1246 | } | ||
| 1219 | debug_printf("builtin inline %s\n", child->argv[0]); | 1247 | debug_printf("builtin inline %s\n", child->argv[0]); |
| 1220 | /* XXX setup_redirects acts on file descriptors, not FILEs. | 1248 | /* XXX setup_redirects acts on file descriptors, not FILEs. |
| 1221 | * This is perfect for work that comes after exec(). | 1249 | * This is perfect for work that comes after exec(). |
| @@ -1569,7 +1597,8 @@ static int setup_redirect(struct p_context *ctx, int fd, redir_type style, | |||
| 1569 | if (redir->dup == -2) return 1; /* syntax error */ | 1597 | if (redir->dup == -2) return 1; /* syntax error */ |
| 1570 | if (redir->dup != -1) { | 1598 | if (redir->dup != -1) { |
| 1571 | /* Erik had a check here that the file descriptor in question | 1599 | /* Erik had a check here that the file descriptor in question |
| 1572 | * is legit; I postpone that to "run time" */ | 1600 | * is legit; I postpone that to "run time" |
| 1601 | * A "-" representation of "close me" shows up as a -3 here */ | ||
| 1573 | debug_printf("Duplicating redirect '%d>&%d'\n", redir->fd, redir->dup); | 1602 | debug_printf("Duplicating redirect '%d>&%d'\n", redir->fd, redir->dup); |
| 1574 | } else { | 1603 | } else { |
| 1575 | /* We do _not_ try to open the file that src points to, | 1604 | /* We do _not_ try to open the file that src points to, |
| @@ -1775,10 +1804,16 @@ static int redirect_dup_num(struct in_str *input) | |||
| 1775 | if (ch != '&') return -1; | 1804 | if (ch != '&') return -1; |
| 1776 | 1805 | ||
| 1777 | b_getch(input); /* get the & */ | 1806 | b_getch(input); /* get the & */ |
| 1778 | while (ch=b_peek(input),isdigit(ch)) { | 1807 | ch=b_peek(input); |
| 1808 | if (ch == '-') { | ||
| 1809 | b_getch(input); | ||
| 1810 | return -3; /* "-" represents "close me" */ | ||
| 1811 | } | ||
| 1812 | while (isdigit(ch)) { | ||
| 1779 | d = d*10+(ch-'0'); | 1813 | d = d*10+(ch-'0'); |
| 1780 | ok=1; | 1814 | ok=1; |
| 1781 | b_getch(input); | 1815 | b_getch(input); |
| 1816 | ch = b_peek(input); | ||
| 1782 | } | 1817 | } |
| 1783 | if (ok) return d; | 1818 | if (ok) return d; |
| 1784 | 1819 | ||
