aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-01-05 20:58:22 +0000
committerEric Andersen <andersen@codepoet.org>2001-01-05 20:58:22 +0000
commit8ea28be6d286c1b4adf1e787c5a3ad087b1b1341 (patch)
treedc9b8ee9e36f9b9d16b1d07363e6b3a1e2d5c437
parent0bcc813a3494fcf31dda25258ed3facc034c77f6 (diff)
downloadbusybox-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.c88
-rw-r--r--sh.c88
-rw-r--r--shell/lash.c88
3 files changed, 216 insertions, 48 deletions
diff --git a/lash.c b/lash.c
index 9e017b169..36e8aa5ea 100644
--- a/lash.c
+++ b/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
126struct close_me {
127 int fd;
128 struct close_me *next;
129};
130
120/* function prototypes for builtins */ 131/* function prototypes for builtins */
121static int builtin_cd(struct child_prog *cmd); 132static int builtin_cd(struct child_prog *cmd);
122static int builtin_env(struct child_prog *dummy); 133static 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 */
155static void mark_open(int fd);
156static void mark_closed(int fd);
144static void checkjobs(struct jobset *job_list); 157static void checkjobs(struct jobset *job_list);
145static int get_command(FILE * source, char *command); 158static int get_command(FILE * source, char *command);
146static int parse_command(char **command_ptr, struct job *job, int *inbg); 159static int parse_command(char **command_ptr, struct job *job, int *inbg);
@@ -194,6 +207,7 @@ static char *local_pending_command;
194static struct jobset job_list = { NULL, NULL }; 207static struct jobset job_list = { NULL, NULL };
195static int argc; 208static int argc;
196static char **argv; 209static char **argv;
210static struct close_me *close_me_head = NULL;
197#ifdef BB_FEATURE_SH_ENVIRONMENT 211#ifdef BB_FEATURE_SH_ENVIRONMENT
198static int last_bg_pid=-1; 212static int last_bg_pid=-1;
199static int last_return_code=-1; 213static 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
613static 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
621static 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
631static 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 */
596static void free_job(struct job *cmd) 642static void free_job(struct job *cmd)
597{ 643{
@@ -767,7 +813,7 @@ static char* setup_prompt_string(int state)
767static int get_command(FILE * source, char *command) 813static 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
1366static void insert_job(struct job *newjob, int inbg) 1415static 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/sh.c b/sh.c
index 9e017b169..36e8aa5ea 100644
--- a/sh.c
+++ b/sh.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
126struct close_me {
127 int fd;
128 struct close_me *next;
129};
130
120/* function prototypes for builtins */ 131/* function prototypes for builtins */
121static int builtin_cd(struct child_prog *cmd); 132static int builtin_cd(struct child_prog *cmd);
122static int builtin_env(struct child_prog *dummy); 133static 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 */
155static void mark_open(int fd);
156static void mark_closed(int fd);
144static void checkjobs(struct jobset *job_list); 157static void checkjobs(struct jobset *job_list);
145static int get_command(FILE * source, char *command); 158static int get_command(FILE * source, char *command);
146static int parse_command(char **command_ptr, struct job *job, int *inbg); 159static int parse_command(char **command_ptr, struct job *job, int *inbg);
@@ -194,6 +207,7 @@ static char *local_pending_command;
194static struct jobset job_list = { NULL, NULL }; 207static struct jobset job_list = { NULL, NULL };
195static int argc; 208static int argc;
196static char **argv; 209static char **argv;
210static struct close_me *close_me_head = NULL;
197#ifdef BB_FEATURE_SH_ENVIRONMENT 211#ifdef BB_FEATURE_SH_ENVIRONMENT
198static int last_bg_pid=-1; 212static int last_bg_pid=-1;
199static int last_return_code=-1; 213static 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
613static 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
621static 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
631static 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 */
596static void free_job(struct job *cmd) 642static void free_job(struct job *cmd)
597{ 643{
@@ -767,7 +813,7 @@ static char* setup_prompt_string(int state)
767static int get_command(FILE * source, char *command) 813static 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
1366static void insert_job(struct job *newjob, int inbg) 1415static 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
126struct close_me {
127 int fd;
128 struct close_me *next;
129};
130
120/* function prototypes for builtins */ 131/* function prototypes for builtins */
121static int builtin_cd(struct child_prog *cmd); 132static int builtin_cd(struct child_prog *cmd);
122static int builtin_env(struct child_prog *dummy); 133static 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 */
155static void mark_open(int fd);
156static void mark_closed(int fd);
144static void checkjobs(struct jobset *job_list); 157static void checkjobs(struct jobset *job_list);
145static int get_command(FILE * source, char *command); 158static int get_command(FILE * source, char *command);
146static int parse_command(char **command_ptr, struct job *job, int *inbg); 159static int parse_command(char **command_ptr, struct job *job, int *inbg);
@@ -194,6 +207,7 @@ static char *local_pending_command;
194static struct jobset job_list = { NULL, NULL }; 207static struct jobset job_list = { NULL, NULL };
195static int argc; 208static int argc;
196static char **argv; 209static char **argv;
210static struct close_me *close_me_head = NULL;
197#ifdef BB_FEATURE_SH_ENVIRONMENT 211#ifdef BB_FEATURE_SH_ENVIRONMENT
198static int last_bg_pid=-1; 212static int last_bg_pid=-1;
199static int last_return_code=-1; 213static 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
613static 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
621static 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
631static 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 */
596static void free_job(struct job *cmd) 642static void free_job(struct job *cmd)
597{ 643{
@@ -767,7 +813,7 @@ static char* setup_prompt_string(int state)
767static int get_command(FILE * source, char *command) 813static 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
1366static void insert_job(struct job *newjob, int inbg) 1415static 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...*/