diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-01-05 20:58:22 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-01-05 20:58:22 +0000 |
commit | 8ea28be6d286c1b4adf1e787c5a3ad087b1b1341 (patch) | |
tree | dc9b8ee9e36f9b9d16b1d07363e6b3a1e2d5c437 | |
parent | 0bcc813a3494fcf31dda25258ed3facc034c77f6 (diff) | |
download | busybox-w32-8ea28be6d286c1b4adf1e787c5a3ad087b1b1341.tar.gz busybox-w32-8ea28be6d286c1b4adf1e787c5a3ad087b1b1341.tar.bz2 busybox-w32-8ea28be6d286c1b4adf1e787c5a3ad087b1b1341.zip |
Patch from larry doolittle to be ever so careful to cleanup
all open file descriptors, lest wierdness happen later.
-rw-r--r-- | lash.c | 88 | ||||
-rw-r--r-- | sh.c | 88 | ||||
-rw-r--r-- | shell/lash.c | 88 |
3 files changed, 216 insertions, 48 deletions
@@ -25,6 +25,12 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | /* The parsing engine of this program is officially at a dead-end. | ||
29 | * Future work in that direction should move to the work posted | ||
30 | * at http://doolittle.faludi.com/~larry/parser.html . | ||
31 | * A start on the integration of that work with the rest of sh.c | ||
32 | * is at http://codepoet.org/sh.c . | ||
33 | */ | ||
28 | // | 34 | // |
29 | //This works pretty well now, and is now on by default. | 35 | //This works pretty well now, and is now on by default. |
30 | #define BB_FEATURE_SH_ENVIRONMENT | 36 | #define BB_FEATURE_SH_ENVIRONMENT |
@@ -117,6 +123,11 @@ struct built_in_command { | |||
117 | int (*function) (struct child_prog *); /* function ptr */ | 123 | int (*function) (struct child_prog *); /* function ptr */ |
118 | }; | 124 | }; |
119 | 125 | ||
126 | struct close_me { | ||
127 | int fd; | ||
128 | struct close_me *next; | ||
129 | }; | ||
130 | |||
120 | /* function prototypes for builtins */ | 131 | /* function prototypes for builtins */ |
121 | static int builtin_cd(struct child_prog *cmd); | 132 | static int builtin_cd(struct child_prog *cmd); |
122 | static int builtin_env(struct child_prog *dummy); | 133 | static int builtin_env(struct child_prog *dummy); |
@@ -141,6 +152,8 @@ static int run_command_predicate(char *cmd); | |||
141 | 152 | ||
142 | 153 | ||
143 | /* function prototypes for shell stuff */ | 154 | /* function prototypes for shell stuff */ |
155 | static void mark_open(int fd); | ||
156 | static void mark_closed(int fd); | ||
144 | static void checkjobs(struct jobset *job_list); | 157 | static void checkjobs(struct jobset *job_list); |
145 | static int get_command(FILE * source, char *command); | 158 | static int get_command(FILE * source, char *command); |
146 | static int parse_command(char **command_ptr, struct job *job, int *inbg); | 159 | static int parse_command(char **command_ptr, struct job *job, int *inbg); |
@@ -194,6 +207,7 @@ static char *local_pending_command; | |||
194 | static struct jobset job_list = { NULL, NULL }; | 207 | static struct jobset job_list = { NULL, NULL }; |
195 | static int argc; | 208 | static int argc; |
196 | static char **argv; | 209 | static char **argv; |
210 | static struct close_me *close_me_head = NULL; | ||
197 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 211 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
198 | static int last_bg_pid=-1; | 212 | static int last_bg_pid=-1; |
199 | static int last_return_code=-1; | 213 | static int last_return_code=-1; |
@@ -545,6 +559,7 @@ static int builtin_source(struct child_prog *child) | |||
545 | { | 559 | { |
546 | FILE *input; | 560 | FILE *input; |
547 | int status; | 561 | int status; |
562 | int fd; | ||
548 | 563 | ||
549 | if (child->argv[1] == NULL) | 564 | if (child->argv[1] == NULL) |
550 | return EXIT_FAILURE; | 565 | return EXIT_FAILURE; |
@@ -555,9 +570,12 @@ static int builtin_source(struct child_prog *child) | |||
555 | return EXIT_FAILURE; | 570 | return EXIT_FAILURE; |
556 | } | 571 | } |
557 | 572 | ||
573 | fd=fileno(input); | ||
574 | mark_open(fd); | ||
558 | /* Now run the file */ | 575 | /* Now run the file */ |
559 | status = busy_loop(input); | 576 | status = busy_loop(input); |
560 | fclose(input); | 577 | fclose(input); |
578 | mark_closed(fd); | ||
561 | return (status); | 579 | return (status); |
562 | } | 580 | } |
563 | 581 | ||
@@ -592,6 +610,34 @@ static int run_command_predicate(char *cmd) | |||
592 | } | 610 | } |
593 | #endif | 611 | #endif |
594 | 612 | ||
613 | static void mark_open(int fd) | ||
614 | { | ||
615 | struct close_me *new = xmalloc(sizeof(struct close_me)); | ||
616 | new->fd = fd; | ||
617 | new->next = close_me_head; | ||
618 | close_me_head = new; | ||
619 | } | ||
620 | |||
621 | static void mark_closed(int fd) | ||
622 | { | ||
623 | struct close_me *tmp; | ||
624 | if (close_me_head == NULL || close_me_head->fd != fd) | ||
625 | error_msg_and_die("corrupt close_me"); | ||
626 | tmp = close_me_head; | ||
627 | close_me_head = close_me_head->next; | ||
628 | free(tmp); | ||
629 | } | ||
630 | |||
631 | static void close_all() | ||
632 | { | ||
633 | struct close_me *c; | ||
634 | for (c=close_me_head; c; c=c->next) { | ||
635 | close(c->fd); | ||
636 | } | ||
637 | close_me_head = NULL; | ||
638 | } | ||
639 | |||
640 | |||
595 | /* free up all memory from a job */ | 641 | /* free up all memory from a job */ |
596 | static void free_job(struct job *cmd) | 642 | static void free_job(struct job *cmd) |
597 | { | 643 | { |
@@ -767,7 +813,7 @@ static char* setup_prompt_string(int state) | |||
767 | static int get_command(FILE * source, char *command) | 813 | static int get_command(FILE * source, char *command) |
768 | { | 814 | { |
769 | char *prompt_str; | 815 | char *prompt_str; |
770 | 816 | ||
771 | if (source == NULL) { | 817 | if (source == NULL) { |
772 | if (local_pending_command) { | 818 | if (local_pending_command) { |
773 | /* a command specified (-c option): return it & mark it done */ | 819 | /* a command specified (-c option): return it & mark it done */ |
@@ -781,7 +827,7 @@ static int get_command(FILE * source, char *command) | |||
781 | 827 | ||
782 | if (source == stdin) { | 828 | if (source == stdin) { |
783 | prompt_str = setup_prompt_string(shell_context); | 829 | prompt_str = setup_prompt_string(shell_context); |
784 | 830 | ||
785 | #ifdef BB_FEATURE_SH_COMMAND_EDITING | 831 | #ifdef BB_FEATURE_SH_COMMAND_EDITING |
786 | /* | 832 | /* |
787 | ** enable command line editing only while a command line | 833 | ** enable command line editing only while a command line |
@@ -791,11 +837,12 @@ static int get_command(FILE * source, char *command) | |||
791 | */ | 837 | */ |
792 | cmdedit_init(); | 838 | cmdedit_init(); |
793 | cmdedit_read_input(prompt_str, command); | 839 | cmdedit_read_input(prompt_str, command); |
794 | free( prompt_str); | 840 | free(prompt_str); |
795 | cmdedit_terminate(); | 841 | cmdedit_terminate(); |
796 | return 0; | 842 | return 0; |
797 | #else | 843 | #else |
798 | fprintf(stdout, "%s", prompt_str); | 844 | fputs(prompt_str, stdout); |
845 | free(prompt_str); | ||
799 | #endif | 846 | #endif |
800 | } | 847 | } |
801 | 848 | ||
@@ -1151,6 +1198,9 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1151 | #ifdef BB_FEATURE_SH_BACKTICKS | 1198 | #ifdef BB_FEATURE_SH_BACKTICKS |
1152 | case '`': | 1199 | case '`': |
1153 | /* Exec a backtick-ed command */ | 1200 | /* Exec a backtick-ed command */ |
1201 | /* Besides any previous brokenness, I have not | ||
1202 | * updated backtick handling for close_me support. | ||
1203 | * I don't know if it needs it or not. -- LRD */ | ||
1154 | { | 1204 | { |
1155 | char* charptr1=NULL, *charptr2; | 1205 | char* charptr1=NULL, *charptr2; |
1156 | char* ptr=NULL; | 1206 | char* ptr=NULL; |
@@ -1359,8 +1409,7 @@ static int pseudo_exec(struct child_prog *child) | |||
1359 | #endif | 1409 | #endif |
1360 | 1410 | ||
1361 | execvp(child->argv[0], child->argv); | 1411 | execvp(child->argv[0], child->argv); |
1362 | error_msg_and_die("%s: %s\n", child->argv[0], | 1412 | perror_msg_and_die("%s", child->argv[0]); |
1363 | strerror(errno)); | ||
1364 | } | 1413 | } |
1365 | 1414 | ||
1366 | static void insert_job(struct job *newjob, int inbg) | 1415 | static void insert_job(struct job *newjob, int inbg) |
@@ -1464,6 +1513,8 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2]) | |||
1464 | if (!(child->pid = fork())) { | 1513 | if (!(child->pid = fork())) { |
1465 | signal(SIGTTOU, SIG_DFL); | 1514 | signal(SIGTTOU, SIG_DFL); |
1466 | 1515 | ||
1516 | close_all(); | ||
1517 | |||
1467 | if (outpipe[1]!=-1) { | 1518 | if (outpipe[1]!=-1) { |
1468 | close(outpipe[0]); | 1519 | close(outpipe[0]); |
1469 | } | 1520 | } |
@@ -1559,7 +1610,8 @@ static int busy_loop(FILE * input) | |||
1559 | while (!job_list.fg->progs[i].pid || | 1610 | while (!job_list.fg->progs[i].pid || |
1560 | job_list.fg->progs[i].is_stopped == 1) i++; | 1611 | job_list.fg->progs[i].is_stopped == 1) i++; |
1561 | 1612 | ||
1562 | waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED); | 1613 | if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED)<0) |
1614 | perror_msg_and_die("waitpid(%d)",job_list.fg->progs[i].pid); | ||
1563 | 1615 | ||
1564 | if (WIFEXITED(status) || WIFSIGNALED(status)) { | 1616 | if (WIFEXITED(status) || WIFSIGNALED(status)) { |
1565 | /* the child exited */ | 1617 | /* the child exited */ |
@@ -1649,15 +1701,18 @@ int shell_main(int argc_l, char **argv_l) | |||
1649 | #endif | 1701 | #endif |
1650 | 1702 | ||
1651 | if (argv[0] && argv[0][0] == '-') { | 1703 | if (argv[0] && argv[0][0] == '-') { |
1652 | FILE *input; | 1704 | FILE *prof_input; |
1653 | input = fopen("/etc/profile", "r"); | 1705 | prof_input = fopen("/etc/profile", "r"); |
1654 | if (!input) { | 1706 | if (!prof_input) { |
1655 | fprintf(stdout, "Couldn't open file '/etc/profile'\n"); | 1707 | fprintf(stdout, "Couldn't open file '/etc/profile'\n"); |
1656 | } else { | 1708 | } else { |
1657 | /* Now run the file */ | 1709 | int tmp_fd = fileno(prof_input); |
1658 | busy_loop(input); | 1710 | mark_open(tmp_fd); |
1659 | fclose(input); | 1711 | /* Now run the file */ |
1660 | } | 1712 | busy_loop(prof_input); |
1713 | fclose(prof_input); | ||
1714 | mark_closed(tmp_fd); | ||
1715 | } | ||
1661 | } | 1716 | } |
1662 | 1717 | ||
1663 | while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) { | 1718 | while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) { |
@@ -1701,6 +1756,7 @@ int shell_main(int argc_l, char **argv_l) | |||
1701 | } else if (local_pending_command==NULL) { | 1756 | } else if (local_pending_command==NULL) { |
1702 | //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]); | 1757 | //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]); |
1703 | input = xfopen(argv[optind], "r"); | 1758 | input = xfopen(argv[optind], "r"); |
1759 | mark_open(fileno(input)); /* be lazy, never mark this closed */ | ||
1704 | } | 1760 | } |
1705 | 1761 | ||
1706 | /* initialize the cwd -- this is never freed...*/ | 1762 | /* initialize the cwd -- this is never freed...*/ |
@@ -25,6 +25,12 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | /* The parsing engine of this program is officially at a dead-end. | ||
29 | * Future work in that direction should move to the work posted | ||
30 | * at http://doolittle.faludi.com/~larry/parser.html . | ||
31 | * A start on the integration of that work with the rest of sh.c | ||
32 | * is at http://codepoet.org/sh.c . | ||
33 | */ | ||
28 | // | 34 | // |
29 | //This works pretty well now, and is now on by default. | 35 | //This works pretty well now, and is now on by default. |
30 | #define BB_FEATURE_SH_ENVIRONMENT | 36 | #define BB_FEATURE_SH_ENVIRONMENT |
@@ -117,6 +123,11 @@ struct built_in_command { | |||
117 | int (*function) (struct child_prog *); /* function ptr */ | 123 | int (*function) (struct child_prog *); /* function ptr */ |
118 | }; | 124 | }; |
119 | 125 | ||
126 | struct close_me { | ||
127 | int fd; | ||
128 | struct close_me *next; | ||
129 | }; | ||
130 | |||
120 | /* function prototypes for builtins */ | 131 | /* function prototypes for builtins */ |
121 | static int builtin_cd(struct child_prog *cmd); | 132 | static int builtin_cd(struct child_prog *cmd); |
122 | static int builtin_env(struct child_prog *dummy); | 133 | static int builtin_env(struct child_prog *dummy); |
@@ -141,6 +152,8 @@ static int run_command_predicate(char *cmd); | |||
141 | 152 | ||
142 | 153 | ||
143 | /* function prototypes for shell stuff */ | 154 | /* function prototypes for shell stuff */ |
155 | static void mark_open(int fd); | ||
156 | static void mark_closed(int fd); | ||
144 | static void checkjobs(struct jobset *job_list); | 157 | static void checkjobs(struct jobset *job_list); |
145 | static int get_command(FILE * source, char *command); | 158 | static int get_command(FILE * source, char *command); |
146 | static int parse_command(char **command_ptr, struct job *job, int *inbg); | 159 | static int parse_command(char **command_ptr, struct job *job, int *inbg); |
@@ -194,6 +207,7 @@ static char *local_pending_command; | |||
194 | static struct jobset job_list = { NULL, NULL }; | 207 | static struct jobset job_list = { NULL, NULL }; |
195 | static int argc; | 208 | static int argc; |
196 | static char **argv; | 209 | static char **argv; |
210 | static struct close_me *close_me_head = NULL; | ||
197 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 211 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
198 | static int last_bg_pid=-1; | 212 | static int last_bg_pid=-1; |
199 | static int last_return_code=-1; | 213 | static int last_return_code=-1; |
@@ -545,6 +559,7 @@ static int builtin_source(struct child_prog *child) | |||
545 | { | 559 | { |
546 | FILE *input; | 560 | FILE *input; |
547 | int status; | 561 | int status; |
562 | int fd; | ||
548 | 563 | ||
549 | if (child->argv[1] == NULL) | 564 | if (child->argv[1] == NULL) |
550 | return EXIT_FAILURE; | 565 | return EXIT_FAILURE; |
@@ -555,9 +570,12 @@ static int builtin_source(struct child_prog *child) | |||
555 | return EXIT_FAILURE; | 570 | return EXIT_FAILURE; |
556 | } | 571 | } |
557 | 572 | ||
573 | fd=fileno(input); | ||
574 | mark_open(fd); | ||
558 | /* Now run the file */ | 575 | /* Now run the file */ |
559 | status = busy_loop(input); | 576 | status = busy_loop(input); |
560 | fclose(input); | 577 | fclose(input); |
578 | mark_closed(fd); | ||
561 | return (status); | 579 | return (status); |
562 | } | 580 | } |
563 | 581 | ||
@@ -592,6 +610,34 @@ static int run_command_predicate(char *cmd) | |||
592 | } | 610 | } |
593 | #endif | 611 | #endif |
594 | 612 | ||
613 | static void mark_open(int fd) | ||
614 | { | ||
615 | struct close_me *new = xmalloc(sizeof(struct close_me)); | ||
616 | new->fd = fd; | ||
617 | new->next = close_me_head; | ||
618 | close_me_head = new; | ||
619 | } | ||
620 | |||
621 | static void mark_closed(int fd) | ||
622 | { | ||
623 | struct close_me *tmp; | ||
624 | if (close_me_head == NULL || close_me_head->fd != fd) | ||
625 | error_msg_and_die("corrupt close_me"); | ||
626 | tmp = close_me_head; | ||
627 | close_me_head = close_me_head->next; | ||
628 | free(tmp); | ||
629 | } | ||
630 | |||
631 | static void close_all() | ||
632 | { | ||
633 | struct close_me *c; | ||
634 | for (c=close_me_head; c; c=c->next) { | ||
635 | close(c->fd); | ||
636 | } | ||
637 | close_me_head = NULL; | ||
638 | } | ||
639 | |||
640 | |||
595 | /* free up all memory from a job */ | 641 | /* free up all memory from a job */ |
596 | static void free_job(struct job *cmd) | 642 | static void free_job(struct job *cmd) |
597 | { | 643 | { |
@@ -767,7 +813,7 @@ static char* setup_prompt_string(int state) | |||
767 | static int get_command(FILE * source, char *command) | 813 | static int get_command(FILE * source, char *command) |
768 | { | 814 | { |
769 | char *prompt_str; | 815 | char *prompt_str; |
770 | 816 | ||
771 | if (source == NULL) { | 817 | if (source == NULL) { |
772 | if (local_pending_command) { | 818 | if (local_pending_command) { |
773 | /* a command specified (-c option): return it & mark it done */ | 819 | /* a command specified (-c option): return it & mark it done */ |
@@ -781,7 +827,7 @@ static int get_command(FILE * source, char *command) | |||
781 | 827 | ||
782 | if (source == stdin) { | 828 | if (source == stdin) { |
783 | prompt_str = setup_prompt_string(shell_context); | 829 | prompt_str = setup_prompt_string(shell_context); |
784 | 830 | ||
785 | #ifdef BB_FEATURE_SH_COMMAND_EDITING | 831 | #ifdef BB_FEATURE_SH_COMMAND_EDITING |
786 | /* | 832 | /* |
787 | ** enable command line editing only while a command line | 833 | ** enable command line editing only while a command line |
@@ -791,11 +837,12 @@ static int get_command(FILE * source, char *command) | |||
791 | */ | 837 | */ |
792 | cmdedit_init(); | 838 | cmdedit_init(); |
793 | cmdedit_read_input(prompt_str, command); | 839 | cmdedit_read_input(prompt_str, command); |
794 | free( prompt_str); | 840 | free(prompt_str); |
795 | cmdedit_terminate(); | 841 | cmdedit_terminate(); |
796 | return 0; | 842 | return 0; |
797 | #else | 843 | #else |
798 | fprintf(stdout, "%s", prompt_str); | 844 | fputs(prompt_str, stdout); |
845 | free(prompt_str); | ||
799 | #endif | 846 | #endif |
800 | } | 847 | } |
801 | 848 | ||
@@ -1151,6 +1198,9 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1151 | #ifdef BB_FEATURE_SH_BACKTICKS | 1198 | #ifdef BB_FEATURE_SH_BACKTICKS |
1152 | case '`': | 1199 | case '`': |
1153 | /* Exec a backtick-ed command */ | 1200 | /* Exec a backtick-ed command */ |
1201 | /* Besides any previous brokenness, I have not | ||
1202 | * updated backtick handling for close_me support. | ||
1203 | * I don't know if it needs it or not. -- LRD */ | ||
1154 | { | 1204 | { |
1155 | char* charptr1=NULL, *charptr2; | 1205 | char* charptr1=NULL, *charptr2; |
1156 | char* ptr=NULL; | 1206 | char* ptr=NULL; |
@@ -1359,8 +1409,7 @@ static int pseudo_exec(struct child_prog *child) | |||
1359 | #endif | 1409 | #endif |
1360 | 1410 | ||
1361 | execvp(child->argv[0], child->argv); | 1411 | execvp(child->argv[0], child->argv); |
1362 | error_msg_and_die("%s: %s\n", child->argv[0], | 1412 | perror_msg_and_die("%s", child->argv[0]); |
1363 | strerror(errno)); | ||
1364 | } | 1413 | } |
1365 | 1414 | ||
1366 | static void insert_job(struct job *newjob, int inbg) | 1415 | static void insert_job(struct job *newjob, int inbg) |
@@ -1464,6 +1513,8 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2]) | |||
1464 | if (!(child->pid = fork())) { | 1513 | if (!(child->pid = fork())) { |
1465 | signal(SIGTTOU, SIG_DFL); | 1514 | signal(SIGTTOU, SIG_DFL); |
1466 | 1515 | ||
1516 | close_all(); | ||
1517 | |||
1467 | if (outpipe[1]!=-1) { | 1518 | if (outpipe[1]!=-1) { |
1468 | close(outpipe[0]); | 1519 | close(outpipe[0]); |
1469 | } | 1520 | } |
@@ -1559,7 +1610,8 @@ static int busy_loop(FILE * input) | |||
1559 | while (!job_list.fg->progs[i].pid || | 1610 | while (!job_list.fg->progs[i].pid || |
1560 | job_list.fg->progs[i].is_stopped == 1) i++; | 1611 | job_list.fg->progs[i].is_stopped == 1) i++; |
1561 | 1612 | ||
1562 | waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED); | 1613 | if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED)<0) |
1614 | perror_msg_and_die("waitpid(%d)",job_list.fg->progs[i].pid); | ||
1563 | 1615 | ||
1564 | if (WIFEXITED(status) || WIFSIGNALED(status)) { | 1616 | if (WIFEXITED(status) || WIFSIGNALED(status)) { |
1565 | /* the child exited */ | 1617 | /* the child exited */ |
@@ -1649,15 +1701,18 @@ int shell_main(int argc_l, char **argv_l) | |||
1649 | #endif | 1701 | #endif |
1650 | 1702 | ||
1651 | if (argv[0] && argv[0][0] == '-') { | 1703 | if (argv[0] && argv[0][0] == '-') { |
1652 | FILE *input; | 1704 | FILE *prof_input; |
1653 | input = fopen("/etc/profile", "r"); | 1705 | prof_input = fopen("/etc/profile", "r"); |
1654 | if (!input) { | 1706 | if (!prof_input) { |
1655 | fprintf(stdout, "Couldn't open file '/etc/profile'\n"); | 1707 | fprintf(stdout, "Couldn't open file '/etc/profile'\n"); |
1656 | } else { | 1708 | } else { |
1657 | /* Now run the file */ | 1709 | int tmp_fd = fileno(prof_input); |
1658 | busy_loop(input); | 1710 | mark_open(tmp_fd); |
1659 | fclose(input); | 1711 | /* Now run the file */ |
1660 | } | 1712 | busy_loop(prof_input); |
1713 | fclose(prof_input); | ||
1714 | mark_closed(tmp_fd); | ||
1715 | } | ||
1661 | } | 1716 | } |
1662 | 1717 | ||
1663 | while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) { | 1718 | while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) { |
@@ -1701,6 +1756,7 @@ int shell_main(int argc_l, char **argv_l) | |||
1701 | } else if (local_pending_command==NULL) { | 1756 | } else if (local_pending_command==NULL) { |
1702 | //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]); | 1757 | //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]); |
1703 | input = xfopen(argv[optind], "r"); | 1758 | input = xfopen(argv[optind], "r"); |
1759 | mark_open(fileno(input)); /* be lazy, never mark this closed */ | ||
1704 | } | 1760 | } |
1705 | 1761 | ||
1706 | /* initialize the cwd -- this is never freed...*/ | 1762 | /* initialize the cwd -- this is never freed...*/ |
diff --git a/shell/lash.c b/shell/lash.c index 9e017b169..36e8aa5ea 100644 --- a/shell/lash.c +++ b/shell/lash.c | |||
@@ -25,6 +25,12 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | /* The parsing engine of this program is officially at a dead-end. | ||
29 | * Future work in that direction should move to the work posted | ||
30 | * at http://doolittle.faludi.com/~larry/parser.html . | ||
31 | * A start on the integration of that work with the rest of sh.c | ||
32 | * is at http://codepoet.org/sh.c . | ||
33 | */ | ||
28 | // | 34 | // |
29 | //This works pretty well now, and is now on by default. | 35 | //This works pretty well now, and is now on by default. |
30 | #define BB_FEATURE_SH_ENVIRONMENT | 36 | #define BB_FEATURE_SH_ENVIRONMENT |
@@ -117,6 +123,11 @@ struct built_in_command { | |||
117 | int (*function) (struct child_prog *); /* function ptr */ | 123 | int (*function) (struct child_prog *); /* function ptr */ |
118 | }; | 124 | }; |
119 | 125 | ||
126 | struct close_me { | ||
127 | int fd; | ||
128 | struct close_me *next; | ||
129 | }; | ||
130 | |||
120 | /* function prototypes for builtins */ | 131 | /* function prototypes for builtins */ |
121 | static int builtin_cd(struct child_prog *cmd); | 132 | static int builtin_cd(struct child_prog *cmd); |
122 | static int builtin_env(struct child_prog *dummy); | 133 | static int builtin_env(struct child_prog *dummy); |
@@ -141,6 +152,8 @@ static int run_command_predicate(char *cmd); | |||
141 | 152 | ||
142 | 153 | ||
143 | /* function prototypes for shell stuff */ | 154 | /* function prototypes for shell stuff */ |
155 | static void mark_open(int fd); | ||
156 | static void mark_closed(int fd); | ||
144 | static void checkjobs(struct jobset *job_list); | 157 | static void checkjobs(struct jobset *job_list); |
145 | static int get_command(FILE * source, char *command); | 158 | static int get_command(FILE * source, char *command); |
146 | static int parse_command(char **command_ptr, struct job *job, int *inbg); | 159 | static int parse_command(char **command_ptr, struct job *job, int *inbg); |
@@ -194,6 +207,7 @@ static char *local_pending_command; | |||
194 | static struct jobset job_list = { NULL, NULL }; | 207 | static struct jobset job_list = { NULL, NULL }; |
195 | static int argc; | 208 | static int argc; |
196 | static char **argv; | 209 | static char **argv; |
210 | static struct close_me *close_me_head = NULL; | ||
197 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 211 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
198 | static int last_bg_pid=-1; | 212 | static int last_bg_pid=-1; |
199 | static int last_return_code=-1; | 213 | static int last_return_code=-1; |
@@ -545,6 +559,7 @@ static int builtin_source(struct child_prog *child) | |||
545 | { | 559 | { |
546 | FILE *input; | 560 | FILE *input; |
547 | int status; | 561 | int status; |
562 | int fd; | ||
548 | 563 | ||
549 | if (child->argv[1] == NULL) | 564 | if (child->argv[1] == NULL) |
550 | return EXIT_FAILURE; | 565 | return EXIT_FAILURE; |
@@ -555,9 +570,12 @@ static int builtin_source(struct child_prog *child) | |||
555 | return EXIT_FAILURE; | 570 | return EXIT_FAILURE; |
556 | } | 571 | } |
557 | 572 | ||
573 | fd=fileno(input); | ||
574 | mark_open(fd); | ||
558 | /* Now run the file */ | 575 | /* Now run the file */ |
559 | status = busy_loop(input); | 576 | status = busy_loop(input); |
560 | fclose(input); | 577 | fclose(input); |
578 | mark_closed(fd); | ||
561 | return (status); | 579 | return (status); |
562 | } | 580 | } |
563 | 581 | ||
@@ -592,6 +610,34 @@ static int run_command_predicate(char *cmd) | |||
592 | } | 610 | } |
593 | #endif | 611 | #endif |
594 | 612 | ||
613 | static void mark_open(int fd) | ||
614 | { | ||
615 | struct close_me *new = xmalloc(sizeof(struct close_me)); | ||
616 | new->fd = fd; | ||
617 | new->next = close_me_head; | ||
618 | close_me_head = new; | ||
619 | } | ||
620 | |||
621 | static void mark_closed(int fd) | ||
622 | { | ||
623 | struct close_me *tmp; | ||
624 | if (close_me_head == NULL || close_me_head->fd != fd) | ||
625 | error_msg_and_die("corrupt close_me"); | ||
626 | tmp = close_me_head; | ||
627 | close_me_head = close_me_head->next; | ||
628 | free(tmp); | ||
629 | } | ||
630 | |||
631 | static void close_all() | ||
632 | { | ||
633 | struct close_me *c; | ||
634 | for (c=close_me_head; c; c=c->next) { | ||
635 | close(c->fd); | ||
636 | } | ||
637 | close_me_head = NULL; | ||
638 | } | ||
639 | |||
640 | |||
595 | /* free up all memory from a job */ | 641 | /* free up all memory from a job */ |
596 | static void free_job(struct job *cmd) | 642 | static void free_job(struct job *cmd) |
597 | { | 643 | { |
@@ -767,7 +813,7 @@ static char* setup_prompt_string(int state) | |||
767 | static int get_command(FILE * source, char *command) | 813 | static int get_command(FILE * source, char *command) |
768 | { | 814 | { |
769 | char *prompt_str; | 815 | char *prompt_str; |
770 | 816 | ||
771 | if (source == NULL) { | 817 | if (source == NULL) { |
772 | if (local_pending_command) { | 818 | if (local_pending_command) { |
773 | /* a command specified (-c option): return it & mark it done */ | 819 | /* a command specified (-c option): return it & mark it done */ |
@@ -781,7 +827,7 @@ static int get_command(FILE * source, char *command) | |||
781 | 827 | ||
782 | if (source == stdin) { | 828 | if (source == stdin) { |
783 | prompt_str = setup_prompt_string(shell_context); | 829 | prompt_str = setup_prompt_string(shell_context); |
784 | 830 | ||
785 | #ifdef BB_FEATURE_SH_COMMAND_EDITING | 831 | #ifdef BB_FEATURE_SH_COMMAND_EDITING |
786 | /* | 832 | /* |
787 | ** enable command line editing only while a command line | 833 | ** enable command line editing only while a command line |
@@ -791,11 +837,12 @@ static int get_command(FILE * source, char *command) | |||
791 | */ | 837 | */ |
792 | cmdedit_init(); | 838 | cmdedit_init(); |
793 | cmdedit_read_input(prompt_str, command); | 839 | cmdedit_read_input(prompt_str, command); |
794 | free( prompt_str); | 840 | free(prompt_str); |
795 | cmdedit_terminate(); | 841 | cmdedit_terminate(); |
796 | return 0; | 842 | return 0; |
797 | #else | 843 | #else |
798 | fprintf(stdout, "%s", prompt_str); | 844 | fputs(prompt_str, stdout); |
845 | free(prompt_str); | ||
799 | #endif | 846 | #endif |
800 | } | 847 | } |
801 | 848 | ||
@@ -1151,6 +1198,9 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1151 | #ifdef BB_FEATURE_SH_BACKTICKS | 1198 | #ifdef BB_FEATURE_SH_BACKTICKS |
1152 | case '`': | 1199 | case '`': |
1153 | /* Exec a backtick-ed command */ | 1200 | /* Exec a backtick-ed command */ |
1201 | /* Besides any previous brokenness, I have not | ||
1202 | * updated backtick handling for close_me support. | ||
1203 | * I don't know if it needs it or not. -- LRD */ | ||
1154 | { | 1204 | { |
1155 | char* charptr1=NULL, *charptr2; | 1205 | char* charptr1=NULL, *charptr2; |
1156 | char* ptr=NULL; | 1206 | char* ptr=NULL; |
@@ -1359,8 +1409,7 @@ static int pseudo_exec(struct child_prog *child) | |||
1359 | #endif | 1409 | #endif |
1360 | 1410 | ||
1361 | execvp(child->argv[0], child->argv); | 1411 | execvp(child->argv[0], child->argv); |
1362 | error_msg_and_die("%s: %s\n", child->argv[0], | 1412 | perror_msg_and_die("%s", child->argv[0]); |
1363 | strerror(errno)); | ||
1364 | } | 1413 | } |
1365 | 1414 | ||
1366 | static void insert_job(struct job *newjob, int inbg) | 1415 | static void insert_job(struct job *newjob, int inbg) |
@@ -1464,6 +1513,8 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2]) | |||
1464 | if (!(child->pid = fork())) { | 1513 | if (!(child->pid = fork())) { |
1465 | signal(SIGTTOU, SIG_DFL); | 1514 | signal(SIGTTOU, SIG_DFL); |
1466 | 1515 | ||
1516 | close_all(); | ||
1517 | |||
1467 | if (outpipe[1]!=-1) { | 1518 | if (outpipe[1]!=-1) { |
1468 | close(outpipe[0]); | 1519 | close(outpipe[0]); |
1469 | } | 1520 | } |
@@ -1559,7 +1610,8 @@ static int busy_loop(FILE * input) | |||
1559 | while (!job_list.fg->progs[i].pid || | 1610 | while (!job_list.fg->progs[i].pid || |
1560 | job_list.fg->progs[i].is_stopped == 1) i++; | 1611 | job_list.fg->progs[i].is_stopped == 1) i++; |
1561 | 1612 | ||
1562 | waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED); | 1613 | if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED)<0) |
1614 | perror_msg_and_die("waitpid(%d)",job_list.fg->progs[i].pid); | ||
1563 | 1615 | ||
1564 | if (WIFEXITED(status) || WIFSIGNALED(status)) { | 1616 | if (WIFEXITED(status) || WIFSIGNALED(status)) { |
1565 | /* the child exited */ | 1617 | /* the child exited */ |
@@ -1649,15 +1701,18 @@ int shell_main(int argc_l, char **argv_l) | |||
1649 | #endif | 1701 | #endif |
1650 | 1702 | ||
1651 | if (argv[0] && argv[0][0] == '-') { | 1703 | if (argv[0] && argv[0][0] == '-') { |
1652 | FILE *input; | 1704 | FILE *prof_input; |
1653 | input = fopen("/etc/profile", "r"); | 1705 | prof_input = fopen("/etc/profile", "r"); |
1654 | if (!input) { | 1706 | if (!prof_input) { |
1655 | fprintf(stdout, "Couldn't open file '/etc/profile'\n"); | 1707 | fprintf(stdout, "Couldn't open file '/etc/profile'\n"); |
1656 | } else { | 1708 | } else { |
1657 | /* Now run the file */ | 1709 | int tmp_fd = fileno(prof_input); |
1658 | busy_loop(input); | 1710 | mark_open(tmp_fd); |
1659 | fclose(input); | 1711 | /* Now run the file */ |
1660 | } | 1712 | busy_loop(prof_input); |
1713 | fclose(prof_input); | ||
1714 | mark_closed(tmp_fd); | ||
1715 | } | ||
1661 | } | 1716 | } |
1662 | 1717 | ||
1663 | while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) { | 1718 | while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) { |
@@ -1701,6 +1756,7 @@ int shell_main(int argc_l, char **argv_l) | |||
1701 | } else if (local_pending_command==NULL) { | 1756 | } else if (local_pending_command==NULL) { |
1702 | //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]); | 1757 | //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]); |
1703 | input = xfopen(argv[optind], "r"); | 1758 | input = xfopen(argv[optind], "r"); |
1759 | mark_open(fileno(input)); /* be lazy, never mark this closed */ | ||
1704 | } | 1760 | } |
1705 | 1761 | ||
1706 | /* initialize the cwd -- this is never freed...*/ | 1762 | /* initialize the cwd -- this is never freed...*/ |