aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-05-07 17:59:25 +0000
committerEric Andersen <andersen@codepoet.org>2001-05-07 17:59:25 +0000
commit83a2ae2184f5a77adfc4c0207aee5d195991a1ab (patch)
tree1d7aef0d43ccb92fd704280dc621cc6f33d5a4ef
parent7e1273edf7a75f2797ea5c0d95d33ff1056f21d8 (diff)
downloadbusybox-w32-83a2ae2184f5a77adfc4c0207aee5d195991a1ab.tar.gz
busybox-w32-83a2ae2184f5a77adfc4c0207aee5d195991a1ab.tar.bz2
busybox-w32-83a2ae2184f5a77adfc4c0207aee5d195991a1ab.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.
-rw-r--r--hush.c73
-rw-r--r--shell/hush.c73
2 files changed, 108 insertions, 38 deletions
diff --git a/hush.c b/hush.c
index b8e4a55c2..e58ac44b3 100644
--- a/hush.c
+++ b/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);
323static int builtin_read(struct child_prog *child); 325static int builtin_read(struct child_prog *child);
324static int builtin_shift(struct child_prog *child); 326static int builtin_shift(struct child_prog *child);
325static int builtin_source(struct child_prog *child); 327static int builtin_source(struct child_prog *child);
326static int builtin_ulimit(struct child_prog *child);
327static int builtin_umask(struct child_prog *child); 328static int builtin_umask(struct child_prog *child);
328static int builtin_unset(struct child_prog *child); 329static int builtin_unset(struct child_prog *child);
330static int builtin_not_written(struct child_prog *child);
329/* o_string manipulation: */ 331/* o_string manipulation: */
330static int b_check_space(o_string *o, int len); 332static int b_check_space(o_string *o, int len);
331static int b_addchr(o_string *o, int ch); 333static 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. */
391static struct built_in_command bltins[] = { 393static 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
643static int builtin_ulimit(struct child_prog *child)
644{
645 printf("builtin_ulimit not written\n");
646 return EXIT_FAILURE;
647}
648
649static int builtin_umask(struct child_prog *child) 651static 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
679static 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
666static int b_check_space(o_string *o, int len) 685static 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
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);
323static int builtin_read(struct child_prog *child); 325static int builtin_read(struct child_prog *child);
324static int builtin_shift(struct child_prog *child); 326static int builtin_shift(struct child_prog *child);
325static int builtin_source(struct child_prog *child); 327static int builtin_source(struct child_prog *child);
326static int builtin_ulimit(struct child_prog *child);
327static int builtin_umask(struct child_prog *child); 328static int builtin_umask(struct child_prog *child);
328static int builtin_unset(struct child_prog *child); 329static int builtin_unset(struct child_prog *child);
330static int builtin_not_written(struct child_prog *child);
329/* o_string manipulation: */ 331/* o_string manipulation: */
330static int b_check_space(o_string *o, int len); 332static int b_check_space(o_string *o, int len);
331static int b_addchr(o_string *o, int ch); 333static 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. */
391static struct built_in_command bltins[] = { 393static 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
643static int builtin_ulimit(struct child_prog *child)
644{
645 printf("builtin_ulimit not written\n");
646 return EXIT_FAILURE;
647}
648
649static int builtin_umask(struct child_prog *child) 651static 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
679static 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
666static int b_check_space(o_string *o, int len) 685static 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