aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2000-07-25 18:06:52 +0000
committerEric Andersen <andersen@codepoet.org>2000-07-25 18:06:52 +0000
commitfad9c1198aa9486f2df01fe139afa329eb893b58 (patch)
treee4c1b0fdaff8f3b132213ddc85cd2b96a265c26d
parentb040d4f3da1545225b9a58301deb29acee6aa7f3 (diff)
downloadbusybox-w32-fad9c1198aa9486f2df01fe139afa329eb893b58.tar.gz
busybox-w32-fad9c1198aa9486f2df01fe139afa329eb893b58.tar.bz2
busybox-w32-fad9c1198aa9486f2df01fe139afa329eb893b58.zip
Finish off fixing up the memleaks (I think). Added the beginnings of
some if-then-else-fi support (nonfunctional and turned off) -Erik
-rw-r--r--lash.c161
-rw-r--r--sh.c161
-rw-r--r--shell/lash.c161
3 files changed, 369 insertions, 114 deletions
diff --git a/lash.c b/lash.c
index 6029eaa5c..b2d1d43d3 100644
--- a/lash.c
+++ b/lash.c
@@ -27,6 +27,7 @@
27 27
28 28
29#define BB_FEATURE_SH_BACKTICKS 29#define BB_FEATURE_SH_BACKTICKS
30//#define BB_FEATURE_SH_IF_EXPRESSIONS
30 31
31 32
32 33
@@ -55,6 +56,14 @@ enum redirectionType { REDIRECT_INPUT, REDIRECT_OVERWRITE,
55 REDIRECT_APPEND 56 REDIRECT_APPEND
56}; 57};
57 58
59#define REGULAR_JOB_CONTEXT 0x1
60#define IF_EXP_CONTEXT 0x2
61#define THEN_EXP_CONTEXT 0x4
62#define ELSE_EXP_CONTEXT 0x8
63
64enum jobContext { REGULAR_APP, IF_CONTEXT, THEN_CONTEXT
65};
66
58struct jobSet { 67struct jobSet {
59 struct job *head; /* head of list of running jobs */ 68 struct job *head; /* head of list of running jobs */
60 struct job *fg; /* current foreground job */ 69 struct job *fg; /* current foreground job */
@@ -86,12 +95,12 @@ struct job {
86 struct childProgram *progs; /* array of programs in job */ 95 struct childProgram *progs; /* array of programs in job */
87 struct job *next; /* to track background commands */ 96 struct job *next; /* to track background commands */
88 int stoppedProgs; /* number of programs alive, but stopped */ 97 int stoppedProgs; /* number of programs alive, but stopped */
98 int jobContext; /* bitmask defining current context */
89}; 99};
90 100
91struct builtInCommand { 101struct builtInCommand {
92 char *cmd; /* name */ 102 char *cmd; /* name */
93 char *descr; /* description */ 103 char *descr; /* description */
94 char *usage; /* usage */
95 int (*function) (struct job *, struct jobSet * jobList); /* function ptr */ 104 int (*function) (struct job *, struct jobSet * jobList); /* function ptr */
96}; 105};
97 106
@@ -107,6 +116,12 @@ static int builtin_export(struct job *cmd, struct jobSet *junk);
107static int builtin_source(struct job *cmd, struct jobSet *jobList); 116static int builtin_source(struct job *cmd, struct jobSet *jobList);
108static int builtin_unset(struct job *cmd, struct jobSet *junk); 117static int builtin_unset(struct job *cmd, struct jobSet *junk);
109static int builtin_read(struct job *cmd, struct jobSet *junk); 118static int builtin_read(struct job *cmd, struct jobSet *junk);
119#ifdef BB_FEATURE_SH_IF_EXPRESSIONS
120static int builtin_if(struct job *cmd, struct jobSet *junk);
121static int builtin_then(struct job *cmd, struct jobSet *junk);
122static int builtin_else(struct job *cmd, struct jobSet *junk);
123static int builtin_fi(struct job *cmd, struct jobSet *junk);
124#endif
110 125
111 126
112/* function prototypes for shell stuff */ 127/* function prototypes for shell stuff */
@@ -122,30 +137,38 @@ static int busy_loop(FILE * input);
122 * can change global variables in the parent shell process but they will not 137 * can change global variables in the parent shell process but they will not
123 * work with pipes and redirects; 'unset foo | whatever' will not work) */ 138 * work with pipes and redirects; 'unset foo | whatever' will not work) */
124static struct builtInCommand bltins[] = { 139static struct builtInCommand bltins[] = {
125 {"bg", "Resume a job in the background", "bg [%%job]", builtin_fg_bg}, 140 {"bg", "Resume a job in the background", builtin_fg_bg},
126 {"cd", "Change working directory", "cd [dir]", builtin_cd}, 141 {"cd", "Change working directory", builtin_cd},
127 {"exit", "Exit from shell()", "exit", builtin_exit}, 142 {"exit", "Exit from shell()", builtin_exit},
128 {"fg", "Bring job into the foreground", "fg [%%job]", builtin_fg_bg}, 143 {"fg", "Bring job into the foreground", builtin_fg_bg},
129 {"jobs", "Lists the active jobs", "jobs", builtin_jobs}, 144 {"jobs", "Lists the active jobs", builtin_jobs},
130 {"export", "Set environment variable", "export [VAR=value]", builtin_export}, 145 {"export", "Set environment variable", builtin_export},
131 {"unset", "Unset environment variable", "unset VAR", builtin_unset}, 146 {"unset", "Unset environment variable", builtin_unset},
132 {"read", "Input environment variable", "read [VAR]", builtin_read}, 147 {"read", "Input environment variable", builtin_read},
133 {NULL, NULL, NULL, NULL} 148 {NULL, NULL, NULL}
134}; 149};
135 150
136/* Table of forking built-in functions (things that fork cannot change global 151/* Table of forking built-in functions (things that fork cannot change global
137 * variables in the parent process, such as the current working directory) */ 152 * variables in the parent process, such as the current working directory) */
138static struct builtInCommand bltins_forking[] = { 153static struct builtInCommand bltins_forking[] = {
139 {"env", "Print all environment variables", "env", builtin_env}, 154 {"env", "Print all environment variables", builtin_env},
140 {"pwd", "Print current directory", "pwd", builtin_pwd}, 155 {"pwd", "Print current directory", builtin_pwd},
141 {".", "Source-in and run commands in a file", ". filename", builtin_source}, 156#ifdef BB_FEATURE_SH_IF_EXPRESSIONS
142 {"help", "List shell built-in commands", "help", builtin_help}, 157 {"if", NULL, builtin_if},
143 {NULL, NULL, NULL, NULL} 158 {"then", NULL, builtin_then},
159 {"else", NULL, builtin_else},
160 {"fi", NULL, builtin_fi},
161#endif
162 {".", "Source-in and run commands in a file", builtin_source},
163 {"help", "List shell built-in commands", builtin_help},
164 {NULL, NULL, NULL}
144}; 165};
145 166
146static char *prompt = "# "; 167static char *prompt = "# ";
147static char *cwd; 168static char *cwd;
148static char *local_pending_command = NULL; 169static char *local_pending_command = NULL;
170static char *promptStr = NULL;
171static struct jobSet jobList = { NULL, NULL };
149 172
150#ifdef BB_FEATURE_SH_COMMAND_EDITING 173#ifdef BB_FEATURE_SH_COMMAND_EDITING
151void win_changed(int junk) 174void win_changed(int junk)
@@ -256,9 +279,13 @@ static int builtin_help(struct job *dummy, struct jobSet *junk)
256 fprintf(stdout, "\nBuilt-in commands:\n"); 279 fprintf(stdout, "\nBuilt-in commands:\n");
257 fprintf(stdout, "-------------------\n"); 280 fprintf(stdout, "-------------------\n");
258 for (x = bltins; x->cmd; x++) { 281 for (x = bltins; x->cmd; x++) {
282 if (x->descr==NULL)
283 continue;
259 fprintf(stdout, "%s\t%s\n", x->cmd, x->descr); 284 fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
260 } 285 }
261 for (x = bltins_forking; x->cmd; x++) { 286 for (x = bltins_forking; x->cmd; x++) {
287 if (x->descr==NULL)
288 continue;
262 fprintf(stdout, "%s\t%s\n", x->cmd, x->descr); 289 fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
263 } 290 }
264 fprintf(stdout, "\n\n"); 291 fprintf(stdout, "\n\n");
@@ -339,6 +366,44 @@ static int builtin_read(struct job *cmd, struct jobSet *junk)
339 return (res); 366 return (res);
340} 367}
341 368
369#ifdef BB_FEATURE_SH_IF_EXPRESSIONS
370/* Built-in handler for 'if' commands */
371static int builtin_if(struct job *cmd, struct jobSet *junk)
372{
373 cmd->jobContext |= IF_EXP_CONTEXT;
374 printf("Hit an if -- jobContext=%d\n", cmd->jobContext);
375 return TRUE;
376}
377
378/* Built-in handler for 'then' (part of the 'if' command) */
379static int builtin_then(struct job *cmd, struct jobSet *junk)
380{
381 if (cmd->jobContext & IF_EXP_CONTEXT) {
382 fprintf(stderr, "unexpected token `then'\n");
383 fflush(stderr);
384 return FALSE;
385 }
386 cmd->jobContext |= THEN_EXP_CONTEXT;
387 printf("Hit an then -- jobContext=%d\n", cmd->jobContext);
388 return TRUE;
389}
390
391/* Built-in handler for 'else' (part of the 'if' command) */
392static int builtin_else(struct job *cmd, struct jobSet *junk)
393{
394 printf("Hit an else\n");
395 cmd->jobContext |= ELSE_EXP_CONTEXT;
396 return TRUE;
397}
398
399/* Built-in handler for 'fi' (part of the 'if' command) */
400static int builtin_fi(struct job *cmd, struct jobSet *junk)
401{
402 printf("Hit an fi\n");
403 return TRUE;
404}
405#endif
406
342/* Built-in '.' handler (read-in and execute commands from file) */ 407/* Built-in '.' handler (read-in and execute commands from file) */
343static int builtin_source(struct job *cmd, struct jobSet *junk) 408static int builtin_source(struct job *cmd, struct jobSet *junk)
344{ 409{
@@ -471,7 +536,6 @@ static int getCommand(FILE * source, char *command)
471 if (source == stdin) { 536 if (source == stdin) {
472#ifdef BB_FEATURE_SH_COMMAND_EDITING 537#ifdef BB_FEATURE_SH_COMMAND_EDITING
473 int len; 538 int len;
474 char *promptStr;
475 len=fprintf(stdout, "%s %s", cwd, prompt); 539 len=fprintf(stdout, "%s %s", cwd, prompt);
476 fflush(stdout); 540 fflush(stdout);
477 promptStr=(char*)xmalloc(sizeof(char)*(len+1)); 541 promptStr=(char*)xmalloc(sizeof(char)*(len+1));
@@ -587,8 +651,9 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi
587 Getting clean memory relieves us of the task of NULL 651 Getting clean memory relieves us of the task of NULL
588 terminating things and makes the rest of this look a bit 652 terminating things and makes the rest of this look a bit
589 cleaner (though it is, admittedly, a tad less efficient) */ 653 cleaner (though it is, admittedly, a tad less efficient) */
590 job->cmdBuf = command = calloc(1, 2*strlen(*commandPtr) + 1); 654 job->cmdBuf = command = calloc(2*strlen(*commandPtr) + 1, sizeof(char));
591 job->text = NULL; 655 job->text = NULL;
656 job->jobContext = REGULAR_JOB_CONTEXT;
592 657
593 prog = job->progs; 658 prog = job->progs;
594 prog->numRedirections = 0; 659 prog->numRedirections = 0;
@@ -863,7 +928,7 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi
863 928
864static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int outPipe[2]) 929static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int outPipe[2])
865{ 930{
866 struct job *job; 931 struct job *theJob;
867 int i; 932 int i;
868 int nextin, nextout; 933 int nextin, nextout;
869 int pipefds[2]; /* pipefd[0] is for reading */ 934 int pipefds[2]; /* pipefd[0] is for reading */
@@ -957,33 +1022,33 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
957 1022
958 newJob->pgrp = newJob->progs[0].pid; 1023 newJob->pgrp = newJob->progs[0].pid;
959 1024
960 /* find the ID for the job to use */ 1025 /* find the ID for the theJob to use */
961 newJob->jobId = 1; 1026 newJob->jobId = 1;
962 for (job = jobList->head; job; job = job->next) 1027 for (theJob = jobList->head; theJob; theJob = theJob->next)
963 if (job->jobId >= newJob->jobId) 1028 if (theJob->jobId >= newJob->jobId)
964 newJob->jobId = job->jobId + 1; 1029 newJob->jobId = theJob->jobId + 1;
965 1030
966 /* add the job to the list of running jobs */ 1031 /* add the theJob to the list of running jobs */
967 if (!jobList->head) { 1032 if (!jobList->head) {
968 job = jobList->head = malloc(sizeof(*job)); 1033 theJob = jobList->head = malloc(sizeof(*theJob));
969 } else { 1034 } else {
970 for (job = jobList->head; job->next; job = job->next); 1035 for (theJob = jobList->head; theJob->next; theJob = theJob->next);
971 job->next = malloc(sizeof(*job)); 1036 theJob->next = malloc(sizeof(*theJob));
972 job = job->next; 1037 theJob = theJob->next;
973 } 1038 }
974 1039
975 *job = *newJob; 1040 *theJob = *newJob;
976 job->next = NULL; 1041 theJob->next = NULL;
977 job->runningProgs = job->numProgs; 1042 theJob->runningProgs = theJob->numProgs;
978 job->stoppedProgs = 0; 1043 theJob->stoppedProgs = 0;
979 1044
980 if (inBg) { 1045 if (inBg) {
981 /* we don't wait for background jobs to return -- append it 1046 /* we don't wait for background theJobs to return -- append it
982 to the list of backgrounded jobs and leave it alone */ 1047 to the list of backgrounded theJobs and leave it alone */
983 printf("[%d] %d\n", job->jobId, 1048 printf("[%d] %d\n", theJob->jobId,
984 newJob->progs[newJob->numProgs - 1].pid); 1049 newJob->progs[newJob->numProgs - 1].pid);
985 } else { 1050 } else {
986 jobList->fg = job; 1051 jobList->fg = theJob;
987 1052
988 /* move the new process group into the foreground */ 1053 /* move the new process group into the foreground */
989 /* suppress messages when run from /linuxrc mag@sysgo.de */ 1054 /* suppress messages when run from /linuxrc mag@sysgo.de */
@@ -1037,7 +1102,6 @@ static int busy_loop(FILE * input)
1037{ 1102{
1038 char *command; 1103 char *command;
1039 char *nextCommand = NULL; 1104 char *nextCommand = NULL;
1040 struct jobSet jobList = { NULL, NULL };
1041 struct job newJob; 1105 struct job newJob;
1042 pid_t parent_pgrp; 1106 pid_t parent_pgrp;
1043 int i; 1107 int i;
@@ -1070,7 +1134,8 @@ static int busy_loop(FILE * input)
1070 newJob.numProgs) { 1134 newJob.numProgs) {
1071 int pipefds[2] = {-1,-1}; 1135 int pipefds[2] = {-1,-1};
1072 runCommand(&newJob, &jobList, inBg, pipefds); 1136 runCommand(&newJob, &jobList, inBg, pipefds);
1073 } else { 1137 }
1138 else {
1074 free(command); 1139 free(command);
1075 command = (char *) calloc(BUFSIZ, sizeof(char)); 1140 command = (char *) calloc(BUFSIZ, sizeof(char));
1076 nextCommand = NULL; 1141 nextCommand = NULL;
@@ -1079,7 +1144,7 @@ static int busy_loop(FILE * input)
1079 /* a job is running in the foreground; wait for it */ 1144 /* a job is running in the foreground; wait for it */
1080 i = 0; 1145 i = 0;
1081 while (!jobList.fg->progs[i].pid || 1146 while (!jobList.fg->progs[i].pid ||
1082 jobList.fg->progs[i].isStopped) i++; 1147 jobList.fg->progs[i].isStopped == 1) i++;
1083 1148
1084 waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED); 1149 waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED);
1085 1150
@@ -1128,6 +1193,22 @@ static int busy_loop(FILE * input)
1128} 1193}
1129 1194
1130 1195
1196#ifdef BB_FEATURE_CLEAN_UP
1197void free_memory(void)
1198{
1199 if (promptStr)
1200 free(promptStr);
1201 if (cwd)
1202 free(cwd);
1203 if (local_pending_command)
1204 free(local_pending_command);
1205
1206 if (jobList.fg && !jobList.fg->runningProgs) {
1207 removeJob(&jobList, jobList.fg);
1208 }
1209}
1210#endif
1211
1131 1212
1132int shell_main(int argc, char **argv) 1213int shell_main(int argc, char **argv)
1133{ 1214{
@@ -1137,6 +1218,10 @@ int shell_main(int argc, char **argv)
1137 cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1); 1218 cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
1138 getcwd(cwd, sizeof(char)*MAX_LINE); 1219 getcwd(cwd, sizeof(char)*MAX_LINE);
1139 1220
1221#ifdef BB_FEATURE_CLEAN_UP
1222 atexit(free_memory);
1223#endif
1224
1140#ifdef BB_FEATURE_SH_COMMAND_EDITING 1225#ifdef BB_FEATURE_SH_COMMAND_EDITING
1141 cmdedit_init(); 1226 cmdedit_init();
1142 signal(SIGWINCH, win_changed); 1227 signal(SIGWINCH, win_changed);
diff --git a/sh.c b/sh.c
index 6029eaa5c..b2d1d43d3 100644
--- a/sh.c
+++ b/sh.c
@@ -27,6 +27,7 @@
27 27
28 28
29#define BB_FEATURE_SH_BACKTICKS 29#define BB_FEATURE_SH_BACKTICKS
30//#define BB_FEATURE_SH_IF_EXPRESSIONS
30 31
31 32
32 33
@@ -55,6 +56,14 @@ enum redirectionType { REDIRECT_INPUT, REDIRECT_OVERWRITE,
55 REDIRECT_APPEND 56 REDIRECT_APPEND
56}; 57};
57 58
59#define REGULAR_JOB_CONTEXT 0x1
60#define IF_EXP_CONTEXT 0x2
61#define THEN_EXP_CONTEXT 0x4
62#define ELSE_EXP_CONTEXT 0x8
63
64enum jobContext { REGULAR_APP, IF_CONTEXT, THEN_CONTEXT
65};
66
58struct jobSet { 67struct jobSet {
59 struct job *head; /* head of list of running jobs */ 68 struct job *head; /* head of list of running jobs */
60 struct job *fg; /* current foreground job */ 69 struct job *fg; /* current foreground job */
@@ -86,12 +95,12 @@ struct job {
86 struct childProgram *progs; /* array of programs in job */ 95 struct childProgram *progs; /* array of programs in job */
87 struct job *next; /* to track background commands */ 96 struct job *next; /* to track background commands */
88 int stoppedProgs; /* number of programs alive, but stopped */ 97 int stoppedProgs; /* number of programs alive, but stopped */
98 int jobContext; /* bitmask defining current context */
89}; 99};
90 100
91struct builtInCommand { 101struct builtInCommand {
92 char *cmd; /* name */ 102 char *cmd; /* name */
93 char *descr; /* description */ 103 char *descr; /* description */
94 char *usage; /* usage */
95 int (*function) (struct job *, struct jobSet * jobList); /* function ptr */ 104 int (*function) (struct job *, struct jobSet * jobList); /* function ptr */
96}; 105};
97 106
@@ -107,6 +116,12 @@ static int builtin_export(struct job *cmd, struct jobSet *junk);
107static int builtin_source(struct job *cmd, struct jobSet *jobList); 116static int builtin_source(struct job *cmd, struct jobSet *jobList);
108static int builtin_unset(struct job *cmd, struct jobSet *junk); 117static int builtin_unset(struct job *cmd, struct jobSet *junk);
109static int builtin_read(struct job *cmd, struct jobSet *junk); 118static int builtin_read(struct job *cmd, struct jobSet *junk);
119#ifdef BB_FEATURE_SH_IF_EXPRESSIONS
120static int builtin_if(struct job *cmd, struct jobSet *junk);
121static int builtin_then(struct job *cmd, struct jobSet *junk);
122static int builtin_else(struct job *cmd, struct jobSet *junk);
123static int builtin_fi(struct job *cmd, struct jobSet *junk);
124#endif
110 125
111 126
112/* function prototypes for shell stuff */ 127/* function prototypes for shell stuff */
@@ -122,30 +137,38 @@ static int busy_loop(FILE * input);
122 * can change global variables in the parent shell process but they will not 137 * can change global variables in the parent shell process but they will not
123 * work with pipes and redirects; 'unset foo | whatever' will not work) */ 138 * work with pipes and redirects; 'unset foo | whatever' will not work) */
124static struct builtInCommand bltins[] = { 139static struct builtInCommand bltins[] = {
125 {"bg", "Resume a job in the background", "bg [%%job]", builtin_fg_bg}, 140 {"bg", "Resume a job in the background", builtin_fg_bg},
126 {"cd", "Change working directory", "cd [dir]", builtin_cd}, 141 {"cd", "Change working directory", builtin_cd},
127 {"exit", "Exit from shell()", "exit", builtin_exit}, 142 {"exit", "Exit from shell()", builtin_exit},
128 {"fg", "Bring job into the foreground", "fg [%%job]", builtin_fg_bg}, 143 {"fg", "Bring job into the foreground", builtin_fg_bg},
129 {"jobs", "Lists the active jobs", "jobs", builtin_jobs}, 144 {"jobs", "Lists the active jobs", builtin_jobs},
130 {"export", "Set environment variable", "export [VAR=value]", builtin_export}, 145 {"export", "Set environment variable", builtin_export},
131 {"unset", "Unset environment variable", "unset VAR", builtin_unset}, 146 {"unset", "Unset environment variable", builtin_unset},
132 {"read", "Input environment variable", "read [VAR]", builtin_read}, 147 {"read", "Input environment variable", builtin_read},
133 {NULL, NULL, NULL, NULL} 148 {NULL, NULL, NULL}
134}; 149};
135 150
136/* Table of forking built-in functions (things that fork cannot change global 151/* Table of forking built-in functions (things that fork cannot change global
137 * variables in the parent process, such as the current working directory) */ 152 * variables in the parent process, such as the current working directory) */
138static struct builtInCommand bltins_forking[] = { 153static struct builtInCommand bltins_forking[] = {
139 {"env", "Print all environment variables", "env", builtin_env}, 154 {"env", "Print all environment variables", builtin_env},
140 {"pwd", "Print current directory", "pwd", builtin_pwd}, 155 {"pwd", "Print current directory", builtin_pwd},
141 {".", "Source-in and run commands in a file", ". filename", builtin_source}, 156#ifdef BB_FEATURE_SH_IF_EXPRESSIONS
142 {"help", "List shell built-in commands", "help", builtin_help}, 157 {"if", NULL, builtin_if},
143 {NULL, NULL, NULL, NULL} 158 {"then", NULL, builtin_then},
159 {"else", NULL, builtin_else},
160 {"fi", NULL, builtin_fi},
161#endif
162 {".", "Source-in and run commands in a file", builtin_source},
163 {"help", "List shell built-in commands", builtin_help},
164 {NULL, NULL, NULL}
144}; 165};
145 166
146static char *prompt = "# "; 167static char *prompt = "# ";
147static char *cwd; 168static char *cwd;
148static char *local_pending_command = NULL; 169static char *local_pending_command = NULL;
170static char *promptStr = NULL;
171static struct jobSet jobList = { NULL, NULL };
149 172
150#ifdef BB_FEATURE_SH_COMMAND_EDITING 173#ifdef BB_FEATURE_SH_COMMAND_EDITING
151void win_changed(int junk) 174void win_changed(int junk)
@@ -256,9 +279,13 @@ static int builtin_help(struct job *dummy, struct jobSet *junk)
256 fprintf(stdout, "\nBuilt-in commands:\n"); 279 fprintf(stdout, "\nBuilt-in commands:\n");
257 fprintf(stdout, "-------------------\n"); 280 fprintf(stdout, "-------------------\n");
258 for (x = bltins; x->cmd; x++) { 281 for (x = bltins; x->cmd; x++) {
282 if (x->descr==NULL)
283 continue;
259 fprintf(stdout, "%s\t%s\n", x->cmd, x->descr); 284 fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
260 } 285 }
261 for (x = bltins_forking; x->cmd; x++) { 286 for (x = bltins_forking; x->cmd; x++) {
287 if (x->descr==NULL)
288 continue;
262 fprintf(stdout, "%s\t%s\n", x->cmd, x->descr); 289 fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
263 } 290 }
264 fprintf(stdout, "\n\n"); 291 fprintf(stdout, "\n\n");
@@ -339,6 +366,44 @@ static int builtin_read(struct job *cmd, struct jobSet *junk)
339 return (res); 366 return (res);
340} 367}
341 368
369#ifdef BB_FEATURE_SH_IF_EXPRESSIONS
370/* Built-in handler for 'if' commands */
371static int builtin_if(struct job *cmd, struct jobSet *junk)
372{
373 cmd->jobContext |= IF_EXP_CONTEXT;
374 printf("Hit an if -- jobContext=%d\n", cmd->jobContext);
375 return TRUE;
376}
377
378/* Built-in handler for 'then' (part of the 'if' command) */
379static int builtin_then(struct job *cmd, struct jobSet *junk)
380{
381 if (cmd->jobContext & IF_EXP_CONTEXT) {
382 fprintf(stderr, "unexpected token `then'\n");
383 fflush(stderr);
384 return FALSE;
385 }
386 cmd->jobContext |= THEN_EXP_CONTEXT;
387 printf("Hit an then -- jobContext=%d\n", cmd->jobContext);
388 return TRUE;
389}
390
391/* Built-in handler for 'else' (part of the 'if' command) */
392static int builtin_else(struct job *cmd, struct jobSet *junk)
393{
394 printf("Hit an else\n");
395 cmd->jobContext |= ELSE_EXP_CONTEXT;
396 return TRUE;
397}
398
399/* Built-in handler for 'fi' (part of the 'if' command) */
400static int builtin_fi(struct job *cmd, struct jobSet *junk)
401{
402 printf("Hit an fi\n");
403 return TRUE;
404}
405#endif
406
342/* Built-in '.' handler (read-in and execute commands from file) */ 407/* Built-in '.' handler (read-in and execute commands from file) */
343static int builtin_source(struct job *cmd, struct jobSet *junk) 408static int builtin_source(struct job *cmd, struct jobSet *junk)
344{ 409{
@@ -471,7 +536,6 @@ static int getCommand(FILE * source, char *command)
471 if (source == stdin) { 536 if (source == stdin) {
472#ifdef BB_FEATURE_SH_COMMAND_EDITING 537#ifdef BB_FEATURE_SH_COMMAND_EDITING
473 int len; 538 int len;
474 char *promptStr;
475 len=fprintf(stdout, "%s %s", cwd, prompt); 539 len=fprintf(stdout, "%s %s", cwd, prompt);
476 fflush(stdout); 540 fflush(stdout);
477 promptStr=(char*)xmalloc(sizeof(char)*(len+1)); 541 promptStr=(char*)xmalloc(sizeof(char)*(len+1));
@@ -587,8 +651,9 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi
587 Getting clean memory relieves us of the task of NULL 651 Getting clean memory relieves us of the task of NULL
588 terminating things and makes the rest of this look a bit 652 terminating things and makes the rest of this look a bit
589 cleaner (though it is, admittedly, a tad less efficient) */ 653 cleaner (though it is, admittedly, a tad less efficient) */
590 job->cmdBuf = command = calloc(1, 2*strlen(*commandPtr) + 1); 654 job->cmdBuf = command = calloc(2*strlen(*commandPtr) + 1, sizeof(char));
591 job->text = NULL; 655 job->text = NULL;
656 job->jobContext = REGULAR_JOB_CONTEXT;
592 657
593 prog = job->progs; 658 prog = job->progs;
594 prog->numRedirections = 0; 659 prog->numRedirections = 0;
@@ -863,7 +928,7 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi
863 928
864static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int outPipe[2]) 929static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int outPipe[2])
865{ 930{
866 struct job *job; 931 struct job *theJob;
867 int i; 932 int i;
868 int nextin, nextout; 933 int nextin, nextout;
869 int pipefds[2]; /* pipefd[0] is for reading */ 934 int pipefds[2]; /* pipefd[0] is for reading */
@@ -957,33 +1022,33 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
957 1022
958 newJob->pgrp = newJob->progs[0].pid; 1023 newJob->pgrp = newJob->progs[0].pid;
959 1024
960 /* find the ID for the job to use */ 1025 /* find the ID for the theJob to use */
961 newJob->jobId = 1; 1026 newJob->jobId = 1;
962 for (job = jobList->head; job; job = job->next) 1027 for (theJob = jobList->head; theJob; theJob = theJob->next)
963 if (job->jobId >= newJob->jobId) 1028 if (theJob->jobId >= newJob->jobId)
964 newJob->jobId = job->jobId + 1; 1029 newJob->jobId = theJob->jobId + 1;
965 1030
966 /* add the job to the list of running jobs */ 1031 /* add the theJob to the list of running jobs */
967 if (!jobList->head) { 1032 if (!jobList->head) {
968 job = jobList->head = malloc(sizeof(*job)); 1033 theJob = jobList->head = malloc(sizeof(*theJob));
969 } else { 1034 } else {
970 for (job = jobList->head; job->next; job = job->next); 1035 for (theJob = jobList->head; theJob->next; theJob = theJob->next);
971 job->next = malloc(sizeof(*job)); 1036 theJob->next = malloc(sizeof(*theJob));
972 job = job->next; 1037 theJob = theJob->next;
973 } 1038 }
974 1039
975 *job = *newJob; 1040 *theJob = *newJob;
976 job->next = NULL; 1041 theJob->next = NULL;
977 job->runningProgs = job->numProgs; 1042 theJob->runningProgs = theJob->numProgs;
978 job->stoppedProgs = 0; 1043 theJob->stoppedProgs = 0;
979 1044
980 if (inBg) { 1045 if (inBg) {
981 /* we don't wait for background jobs to return -- append it 1046 /* we don't wait for background theJobs to return -- append it
982 to the list of backgrounded jobs and leave it alone */ 1047 to the list of backgrounded theJobs and leave it alone */
983 printf("[%d] %d\n", job->jobId, 1048 printf("[%d] %d\n", theJob->jobId,
984 newJob->progs[newJob->numProgs - 1].pid); 1049 newJob->progs[newJob->numProgs - 1].pid);
985 } else { 1050 } else {
986 jobList->fg = job; 1051 jobList->fg = theJob;
987 1052
988 /* move the new process group into the foreground */ 1053 /* move the new process group into the foreground */
989 /* suppress messages when run from /linuxrc mag@sysgo.de */ 1054 /* suppress messages when run from /linuxrc mag@sysgo.de */
@@ -1037,7 +1102,6 @@ static int busy_loop(FILE * input)
1037{ 1102{
1038 char *command; 1103 char *command;
1039 char *nextCommand = NULL; 1104 char *nextCommand = NULL;
1040 struct jobSet jobList = { NULL, NULL };
1041 struct job newJob; 1105 struct job newJob;
1042 pid_t parent_pgrp; 1106 pid_t parent_pgrp;
1043 int i; 1107 int i;
@@ -1070,7 +1134,8 @@ static int busy_loop(FILE * input)
1070 newJob.numProgs) { 1134 newJob.numProgs) {
1071 int pipefds[2] = {-1,-1}; 1135 int pipefds[2] = {-1,-1};
1072 runCommand(&newJob, &jobList, inBg, pipefds); 1136 runCommand(&newJob, &jobList, inBg, pipefds);
1073 } else { 1137 }
1138 else {
1074 free(command); 1139 free(command);
1075 command = (char *) calloc(BUFSIZ, sizeof(char)); 1140 command = (char *) calloc(BUFSIZ, sizeof(char));
1076 nextCommand = NULL; 1141 nextCommand = NULL;
@@ -1079,7 +1144,7 @@ static int busy_loop(FILE * input)
1079 /* a job is running in the foreground; wait for it */ 1144 /* a job is running in the foreground; wait for it */
1080 i = 0; 1145 i = 0;
1081 while (!jobList.fg->progs[i].pid || 1146 while (!jobList.fg->progs[i].pid ||
1082 jobList.fg->progs[i].isStopped) i++; 1147 jobList.fg->progs[i].isStopped == 1) i++;
1083 1148
1084 waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED); 1149 waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED);
1085 1150
@@ -1128,6 +1193,22 @@ static int busy_loop(FILE * input)
1128} 1193}
1129 1194
1130 1195
1196#ifdef BB_FEATURE_CLEAN_UP
1197void free_memory(void)
1198{
1199 if (promptStr)
1200 free(promptStr);
1201 if (cwd)
1202 free(cwd);
1203 if (local_pending_command)
1204 free(local_pending_command);
1205
1206 if (jobList.fg && !jobList.fg->runningProgs) {
1207 removeJob(&jobList, jobList.fg);
1208 }
1209}
1210#endif
1211
1131 1212
1132int shell_main(int argc, char **argv) 1213int shell_main(int argc, char **argv)
1133{ 1214{
@@ -1137,6 +1218,10 @@ int shell_main(int argc, char **argv)
1137 cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1); 1218 cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
1138 getcwd(cwd, sizeof(char)*MAX_LINE); 1219 getcwd(cwd, sizeof(char)*MAX_LINE);
1139 1220
1221#ifdef BB_FEATURE_CLEAN_UP
1222 atexit(free_memory);
1223#endif
1224
1140#ifdef BB_FEATURE_SH_COMMAND_EDITING 1225#ifdef BB_FEATURE_SH_COMMAND_EDITING
1141 cmdedit_init(); 1226 cmdedit_init();
1142 signal(SIGWINCH, win_changed); 1227 signal(SIGWINCH, win_changed);
diff --git a/shell/lash.c b/shell/lash.c
index 6029eaa5c..b2d1d43d3 100644
--- a/shell/lash.c
+++ b/shell/lash.c
@@ -27,6 +27,7 @@
27 27
28 28
29#define BB_FEATURE_SH_BACKTICKS 29#define BB_FEATURE_SH_BACKTICKS
30//#define BB_FEATURE_SH_IF_EXPRESSIONS
30 31
31 32
32 33
@@ -55,6 +56,14 @@ enum redirectionType { REDIRECT_INPUT, REDIRECT_OVERWRITE,
55 REDIRECT_APPEND 56 REDIRECT_APPEND
56}; 57};
57 58
59#define REGULAR_JOB_CONTEXT 0x1
60#define IF_EXP_CONTEXT 0x2
61#define THEN_EXP_CONTEXT 0x4
62#define ELSE_EXP_CONTEXT 0x8
63
64enum jobContext { REGULAR_APP, IF_CONTEXT, THEN_CONTEXT
65};
66
58struct jobSet { 67struct jobSet {
59 struct job *head; /* head of list of running jobs */ 68 struct job *head; /* head of list of running jobs */
60 struct job *fg; /* current foreground job */ 69 struct job *fg; /* current foreground job */
@@ -86,12 +95,12 @@ struct job {
86 struct childProgram *progs; /* array of programs in job */ 95 struct childProgram *progs; /* array of programs in job */
87 struct job *next; /* to track background commands */ 96 struct job *next; /* to track background commands */
88 int stoppedProgs; /* number of programs alive, but stopped */ 97 int stoppedProgs; /* number of programs alive, but stopped */
98 int jobContext; /* bitmask defining current context */
89}; 99};
90 100
91struct builtInCommand { 101struct builtInCommand {
92 char *cmd; /* name */ 102 char *cmd; /* name */
93 char *descr; /* description */ 103 char *descr; /* description */
94 char *usage; /* usage */
95 int (*function) (struct job *, struct jobSet * jobList); /* function ptr */ 104 int (*function) (struct job *, struct jobSet * jobList); /* function ptr */
96}; 105};
97 106
@@ -107,6 +116,12 @@ static int builtin_export(struct job *cmd, struct jobSet *junk);
107static int builtin_source(struct job *cmd, struct jobSet *jobList); 116static int builtin_source(struct job *cmd, struct jobSet *jobList);
108static int builtin_unset(struct job *cmd, struct jobSet *junk); 117static int builtin_unset(struct job *cmd, struct jobSet *junk);
109static int builtin_read(struct job *cmd, struct jobSet *junk); 118static int builtin_read(struct job *cmd, struct jobSet *junk);
119#ifdef BB_FEATURE_SH_IF_EXPRESSIONS
120static int builtin_if(struct job *cmd, struct jobSet *junk);
121static int builtin_then(struct job *cmd, struct jobSet *junk);
122static int builtin_else(struct job *cmd, struct jobSet *junk);
123static int builtin_fi(struct job *cmd, struct jobSet *junk);
124#endif
110 125
111 126
112/* function prototypes for shell stuff */ 127/* function prototypes for shell stuff */
@@ -122,30 +137,38 @@ static int busy_loop(FILE * input);
122 * can change global variables in the parent shell process but they will not 137 * can change global variables in the parent shell process but they will not
123 * work with pipes and redirects; 'unset foo | whatever' will not work) */ 138 * work with pipes and redirects; 'unset foo | whatever' will not work) */
124static struct builtInCommand bltins[] = { 139static struct builtInCommand bltins[] = {
125 {"bg", "Resume a job in the background", "bg [%%job]", builtin_fg_bg}, 140 {"bg", "Resume a job in the background", builtin_fg_bg},
126 {"cd", "Change working directory", "cd [dir]", builtin_cd}, 141 {"cd", "Change working directory", builtin_cd},
127 {"exit", "Exit from shell()", "exit", builtin_exit}, 142 {"exit", "Exit from shell()", builtin_exit},
128 {"fg", "Bring job into the foreground", "fg [%%job]", builtin_fg_bg}, 143 {"fg", "Bring job into the foreground", builtin_fg_bg},
129 {"jobs", "Lists the active jobs", "jobs", builtin_jobs}, 144 {"jobs", "Lists the active jobs", builtin_jobs},
130 {"export", "Set environment variable", "export [VAR=value]", builtin_export}, 145 {"export", "Set environment variable", builtin_export},
131 {"unset", "Unset environment variable", "unset VAR", builtin_unset}, 146 {"unset", "Unset environment variable", builtin_unset},
132 {"read", "Input environment variable", "read [VAR]", builtin_read}, 147 {"read", "Input environment variable", builtin_read},
133 {NULL, NULL, NULL, NULL} 148 {NULL, NULL, NULL}
134}; 149};
135 150
136/* Table of forking built-in functions (things that fork cannot change global 151/* Table of forking built-in functions (things that fork cannot change global
137 * variables in the parent process, such as the current working directory) */ 152 * variables in the parent process, such as the current working directory) */
138static struct builtInCommand bltins_forking[] = { 153static struct builtInCommand bltins_forking[] = {
139 {"env", "Print all environment variables", "env", builtin_env}, 154 {"env", "Print all environment variables", builtin_env},
140 {"pwd", "Print current directory", "pwd", builtin_pwd}, 155 {"pwd", "Print current directory", builtin_pwd},
141 {".", "Source-in and run commands in a file", ". filename", builtin_source}, 156#ifdef BB_FEATURE_SH_IF_EXPRESSIONS
142 {"help", "List shell built-in commands", "help", builtin_help}, 157 {"if", NULL, builtin_if},
143 {NULL, NULL, NULL, NULL} 158 {"then", NULL, builtin_then},
159 {"else", NULL, builtin_else},
160 {"fi", NULL, builtin_fi},
161#endif
162 {".", "Source-in and run commands in a file", builtin_source},
163 {"help", "List shell built-in commands", builtin_help},
164 {NULL, NULL, NULL}
144}; 165};
145 166
146static char *prompt = "# "; 167static char *prompt = "# ";
147static char *cwd; 168static char *cwd;
148static char *local_pending_command = NULL; 169static char *local_pending_command = NULL;
170static char *promptStr = NULL;
171static struct jobSet jobList = { NULL, NULL };
149 172
150#ifdef BB_FEATURE_SH_COMMAND_EDITING 173#ifdef BB_FEATURE_SH_COMMAND_EDITING
151void win_changed(int junk) 174void win_changed(int junk)
@@ -256,9 +279,13 @@ static int builtin_help(struct job *dummy, struct jobSet *junk)
256 fprintf(stdout, "\nBuilt-in commands:\n"); 279 fprintf(stdout, "\nBuilt-in commands:\n");
257 fprintf(stdout, "-------------------\n"); 280 fprintf(stdout, "-------------------\n");
258 for (x = bltins; x->cmd; x++) { 281 for (x = bltins; x->cmd; x++) {
282 if (x->descr==NULL)
283 continue;
259 fprintf(stdout, "%s\t%s\n", x->cmd, x->descr); 284 fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
260 } 285 }
261 for (x = bltins_forking; x->cmd; x++) { 286 for (x = bltins_forking; x->cmd; x++) {
287 if (x->descr==NULL)
288 continue;
262 fprintf(stdout, "%s\t%s\n", x->cmd, x->descr); 289 fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
263 } 290 }
264 fprintf(stdout, "\n\n"); 291 fprintf(stdout, "\n\n");
@@ -339,6 +366,44 @@ static int builtin_read(struct job *cmd, struct jobSet *junk)
339 return (res); 366 return (res);
340} 367}
341 368
369#ifdef BB_FEATURE_SH_IF_EXPRESSIONS
370/* Built-in handler for 'if' commands */
371static int builtin_if(struct job *cmd, struct jobSet *junk)
372{
373 cmd->jobContext |= IF_EXP_CONTEXT;
374 printf("Hit an if -- jobContext=%d\n", cmd->jobContext);
375 return TRUE;
376}
377
378/* Built-in handler for 'then' (part of the 'if' command) */
379static int builtin_then(struct job *cmd, struct jobSet *junk)
380{
381 if (cmd->jobContext & IF_EXP_CONTEXT) {
382 fprintf(stderr, "unexpected token `then'\n");
383 fflush(stderr);
384 return FALSE;
385 }
386 cmd->jobContext |= THEN_EXP_CONTEXT;
387 printf("Hit an then -- jobContext=%d\n", cmd->jobContext);
388 return TRUE;
389}
390
391/* Built-in handler for 'else' (part of the 'if' command) */
392static int builtin_else(struct job *cmd, struct jobSet *junk)
393{
394 printf("Hit an else\n");
395 cmd->jobContext |= ELSE_EXP_CONTEXT;
396 return TRUE;
397}
398
399/* Built-in handler for 'fi' (part of the 'if' command) */
400static int builtin_fi(struct job *cmd, struct jobSet *junk)
401{
402 printf("Hit an fi\n");
403 return TRUE;
404}
405#endif
406
342/* Built-in '.' handler (read-in and execute commands from file) */ 407/* Built-in '.' handler (read-in and execute commands from file) */
343static int builtin_source(struct job *cmd, struct jobSet *junk) 408static int builtin_source(struct job *cmd, struct jobSet *junk)
344{ 409{
@@ -471,7 +536,6 @@ static int getCommand(FILE * source, char *command)
471 if (source == stdin) { 536 if (source == stdin) {
472#ifdef BB_FEATURE_SH_COMMAND_EDITING 537#ifdef BB_FEATURE_SH_COMMAND_EDITING
473 int len; 538 int len;
474 char *promptStr;
475 len=fprintf(stdout, "%s %s", cwd, prompt); 539 len=fprintf(stdout, "%s %s", cwd, prompt);
476 fflush(stdout); 540 fflush(stdout);
477 promptStr=(char*)xmalloc(sizeof(char)*(len+1)); 541 promptStr=(char*)xmalloc(sizeof(char)*(len+1));
@@ -587,8 +651,9 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi
587 Getting clean memory relieves us of the task of NULL 651 Getting clean memory relieves us of the task of NULL
588 terminating things and makes the rest of this look a bit 652 terminating things and makes the rest of this look a bit
589 cleaner (though it is, admittedly, a tad less efficient) */ 653 cleaner (though it is, admittedly, a tad less efficient) */
590 job->cmdBuf = command = calloc(1, 2*strlen(*commandPtr) + 1); 654 job->cmdBuf = command = calloc(2*strlen(*commandPtr) + 1, sizeof(char));
591 job->text = NULL; 655 job->text = NULL;
656 job->jobContext = REGULAR_JOB_CONTEXT;
592 657
593 prog = job->progs; 658 prog = job->progs;
594 prog->numRedirections = 0; 659 prog->numRedirections = 0;
@@ -863,7 +928,7 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi
863 928
864static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int outPipe[2]) 929static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int outPipe[2])
865{ 930{
866 struct job *job; 931 struct job *theJob;
867 int i; 932 int i;
868 int nextin, nextout; 933 int nextin, nextout;
869 int pipefds[2]; /* pipefd[0] is for reading */ 934 int pipefds[2]; /* pipefd[0] is for reading */
@@ -957,33 +1022,33 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
957 1022
958 newJob->pgrp = newJob->progs[0].pid; 1023 newJob->pgrp = newJob->progs[0].pid;
959 1024
960 /* find the ID for the job to use */ 1025 /* find the ID for the theJob to use */
961 newJob->jobId = 1; 1026 newJob->jobId = 1;
962 for (job = jobList->head; job; job = job->next) 1027 for (theJob = jobList->head; theJob; theJob = theJob->next)
963 if (job->jobId >= newJob->jobId) 1028 if (theJob->jobId >= newJob->jobId)
964 newJob->jobId = job->jobId + 1; 1029 newJob->jobId = theJob->jobId + 1;
965 1030
966 /* add the job to the list of running jobs */ 1031 /* add the theJob to the list of running jobs */
967 if (!jobList->head) { 1032 if (!jobList->head) {
968 job = jobList->head = malloc(sizeof(*job)); 1033 theJob = jobList->head = malloc(sizeof(*theJob));
969 } else { 1034 } else {
970 for (job = jobList->head; job->next; job = job->next); 1035 for (theJob = jobList->head; theJob->next; theJob = theJob->next);
971 job->next = malloc(sizeof(*job)); 1036 theJob->next = malloc(sizeof(*theJob));
972 job = job->next; 1037 theJob = theJob->next;
973 } 1038 }
974 1039
975 *job = *newJob; 1040 *theJob = *newJob;
976 job->next = NULL; 1041 theJob->next = NULL;
977 job->runningProgs = job->numProgs; 1042 theJob->runningProgs = theJob->numProgs;
978 job->stoppedProgs = 0; 1043 theJob->stoppedProgs = 0;
979 1044
980 if (inBg) { 1045 if (inBg) {
981 /* we don't wait for background jobs to return -- append it 1046 /* we don't wait for background theJobs to return -- append it
982 to the list of backgrounded jobs and leave it alone */ 1047 to the list of backgrounded theJobs and leave it alone */
983 printf("[%d] %d\n", job->jobId, 1048 printf("[%d] %d\n", theJob->jobId,
984 newJob->progs[newJob->numProgs - 1].pid); 1049 newJob->progs[newJob->numProgs - 1].pid);
985 } else { 1050 } else {
986 jobList->fg = job; 1051 jobList->fg = theJob;
987 1052
988 /* move the new process group into the foreground */ 1053 /* move the new process group into the foreground */
989 /* suppress messages when run from /linuxrc mag@sysgo.de */ 1054 /* suppress messages when run from /linuxrc mag@sysgo.de */
@@ -1037,7 +1102,6 @@ static int busy_loop(FILE * input)
1037{ 1102{
1038 char *command; 1103 char *command;
1039 char *nextCommand = NULL; 1104 char *nextCommand = NULL;
1040 struct jobSet jobList = { NULL, NULL };
1041 struct job newJob; 1105 struct job newJob;
1042 pid_t parent_pgrp; 1106 pid_t parent_pgrp;
1043 int i; 1107 int i;
@@ -1070,7 +1134,8 @@ static int busy_loop(FILE * input)
1070 newJob.numProgs) { 1134 newJob.numProgs) {
1071 int pipefds[2] = {-1,-1}; 1135 int pipefds[2] = {-1,-1};
1072 runCommand(&newJob, &jobList, inBg, pipefds); 1136 runCommand(&newJob, &jobList, inBg, pipefds);
1073 } else { 1137 }
1138 else {
1074 free(command); 1139 free(command);
1075 command = (char *) calloc(BUFSIZ, sizeof(char)); 1140 command = (char *) calloc(BUFSIZ, sizeof(char));
1076 nextCommand = NULL; 1141 nextCommand = NULL;
@@ -1079,7 +1144,7 @@ static int busy_loop(FILE * input)
1079 /* a job is running in the foreground; wait for it */ 1144 /* a job is running in the foreground; wait for it */
1080 i = 0; 1145 i = 0;
1081 while (!jobList.fg->progs[i].pid || 1146 while (!jobList.fg->progs[i].pid ||
1082 jobList.fg->progs[i].isStopped) i++; 1147 jobList.fg->progs[i].isStopped == 1) i++;
1083 1148
1084 waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED); 1149 waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED);
1085 1150
@@ -1128,6 +1193,22 @@ static int busy_loop(FILE * input)
1128} 1193}
1129 1194
1130 1195
1196#ifdef BB_FEATURE_CLEAN_UP
1197void free_memory(void)
1198{
1199 if (promptStr)
1200 free(promptStr);
1201 if (cwd)
1202 free(cwd);
1203 if (local_pending_command)
1204 free(local_pending_command);
1205
1206 if (jobList.fg && !jobList.fg->runningProgs) {
1207 removeJob(&jobList, jobList.fg);
1208 }
1209}
1210#endif
1211
1131 1212
1132int shell_main(int argc, char **argv) 1213int shell_main(int argc, char **argv)
1133{ 1214{
@@ -1137,6 +1218,10 @@ int shell_main(int argc, char **argv)
1137 cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1); 1218 cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
1138 getcwd(cwd, sizeof(char)*MAX_LINE); 1219 getcwd(cwd, sizeof(char)*MAX_LINE);
1139 1220
1221#ifdef BB_FEATURE_CLEAN_UP
1222 atexit(free_memory);
1223#endif
1224
1140#ifdef BB_FEATURE_SH_COMMAND_EDITING 1225#ifdef BB_FEATURE_SH_COMMAND_EDITING
1141 cmdedit_init(); 1226 cmdedit_init();
1142 signal(SIGWINCH, win_changed); 1227 signal(SIGWINCH, win_changed);