aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-05-02 16:11:59 +0000
committerEric Andersen <andersen@codepoet.org>2001-05-02 16:11:59 +0000
commitbafd94f154d0a6fdf04706f7cf5687dcc8ba634b (patch)
tree070bd581bfc06c4a1eae8c230f6734720117a586
parent1c8a59ab95d4b1a91506c69fb211fe1077e0c755 (diff)
downloadbusybox-w32-bafd94f154d0a6fdf04706f7cf5687dcc8ba634b.tar.gz
busybox-w32-bafd94f154d0a6fdf04706f7cf5687dcc8ba634b.tar.bz2
busybox-w32-bafd94f154d0a6fdf04706f7cf5687dcc8ba634b.zip
First pass at getting job control working. This gets the infrastructure
in place, but something is still missing/wrong in there. Testing with 'grep foo &' seems to put _hush_ into the background. Pondering... -Erik
-rw-r--r--hush.c155
-rw-r--r--shell/hush.c155
2 files changed, 284 insertions, 26 deletions
diff --git a/hush.c b/hush.c
index 4641e59c8..ed4979818 100644
--- a/hush.c
+++ b/hush.c
@@ -213,7 +213,6 @@ struct pipe {
213 int job_context; /* bitmask defining current context */ 213 int job_context; /* bitmask defining current context */
214 pipe_style followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */ 214 pipe_style followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
215 reserved_style r_mode; /* supports if, for, while, until */ 215 reserved_style r_mode; /* supports if, for, while, until */
216 struct jobset *job_list;
217}; 216};
218 217
219struct jobset { 218struct jobset {
@@ -244,7 +243,7 @@ static int fake_mode=0;
244static int interactive=0; 243static int interactive=0;
245static struct close_me *close_me_head = NULL; 244static struct close_me *close_me_head = NULL;
246static char *cwd; 245static char *cwd;
247/* static struct jobset job_list = { NULL, NULL }; */ 246static struct jobset *job_list;
248static unsigned int last_bg_pid=0; 247static unsigned int last_bg_pid=0;
249static char *PS1; 248static char *PS1;
250static char *PS2 = "> "; 249static char *PS2 = "> ";
@@ -377,6 +376,11 @@ static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *in
377static int parse_stream_outer(struct in_str *inp); 376static int parse_stream_outer(struct in_str *inp);
378static int parse_string_outer(const char *s); 377static int parse_string_outer(const char *s);
379static int parse_file_outer(FILE *f); 378static int parse_file_outer(FILE *f);
379/* job management: */
380static void checkjobs();
381static void insert_bg_job(struct pipe *pi);
382static void remove_bg_job(struct pipe *pi);
383static void free_pipe(struct pipe *pi);
380 384
381/* Table of built-in functions. They can be forked or not, depending on 385/* Table of built-in functions. They can be forked or not, depending on
382 * context: within pipes, they fork. As simple commands, they do not. 386 * context: within pipes, they fork. As simple commands, they do not.
@@ -481,7 +485,7 @@ static int builtin_fg_bg(struct child_prog *child)
481 return EXIT_FAILURE; 485 return EXIT_FAILURE;
482 } 486 }
483 487
484 for (job = child->family->job_list->head; job; job = job->next) { 488 for (job = job_list->head; job; job = job->next) {
485 if (job->jobid == jobNum) { 489 if (job->jobid == jobNum) {
486 break; 490 break;
487 } 491 }
@@ -498,7 +502,7 @@ static int builtin_fg_bg(struct child_prog *child)
498 /* suppress messages when run from /linuxrc mag@sysgo.de */ 502 /* suppress messages when run from /linuxrc mag@sysgo.de */
499 if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY) 503 if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY)
500 perror_msg("tcsetpgrp"); 504 perror_msg("tcsetpgrp");
501 child->family->job_list->fg = job; 505 job_list->fg = job;
502 } 506 }
503 507
504 /* Restart the processes in the job */ 508 /* Restart the processes in the job */
@@ -533,7 +537,7 @@ static int builtin_jobs(struct child_prog *child)
533 struct pipe *job; 537 struct pipe *job;
534 char *status_string; 538 char *status_string;
535 539
536 for (job = child->family->job_list->head; job; job = job->next) { 540 for (job = job_list->head; job; job = job->next) {
537 if (job->running_progs == job->stopped_progs) 541 if (job->running_progs == job->stopped_progs)
538 status_string = "Stopped"; 542 status_string = "Stopped";
539 else 543 else
@@ -1031,6 +1035,121 @@ static void pseudo_exec(struct child_prog *child)
1031 } 1035 }
1032} 1036}
1033 1037
1038static void insert_bg_job(struct pipe *pi)
1039{
1040 struct pipe *thejob;
1041
1042 /* Linear search for the ID of the job to use */
1043 pi->jobid = 1;
1044 for (thejob = job_list->head; thejob; thejob = thejob->next)
1045 if (thejob->jobid >= pi->jobid)
1046 pi->jobid = thejob->jobid + 1;
1047
1048 /* add thejob to the list of running jobs */
1049 if (!job_list->head) {
1050 thejob = job_list->head = xmalloc(sizeof(*thejob));
1051 } else {
1052 for (thejob = job_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1053 thejob->next = xmalloc(sizeof(*thejob));
1054 thejob = thejob->next;
1055 }
1056
1057 /* physically copy the struct job */
1058 *thejob = *pi;
1059 thejob->next = NULL;
1060 thejob->running_progs = thejob->num_progs;
1061 thejob->stopped_progs = 0;
1062
1063 /* we don't wait for background thejobs to return -- append it
1064 to the list of backgrounded thejobs and leave it alone */
1065 printf("[%d] %d\n", pi->jobid, pi->pgrp);
1066 last_bg_pid = pi->pgrp;
1067}
1068
1069/* remove a backgrounded job from a jobset */
1070static void remove_bg_job(struct pipe *pi)
1071{
1072 struct pipe *prev_pipe;
1073
1074 free_pipe(pi);
1075 if (pi == job_list->head) {
1076 job_list->head = pi->next;
1077 } else {
1078 prev_pipe = job_list->head;
1079 while (prev_pipe->next != pi)
1080 prev_pipe = prev_pipe->next;
1081 prev_pipe->next = pi->next;
1082 }
1083
1084 free(pi);
1085}
1086
1087/* free up all memory from a pipe */
1088static void free_pipe(struct pipe *pi)
1089{
1090 int i;
1091
1092 for (i = 0; i < pi->num_progs; i++) {
1093 free(pi->progs[i].argv);
1094 if (pi->progs[i].redirects)
1095 free(pi->progs[i].redirects);
1096 }
1097 if (pi->progs)
1098 free(pi->progs);
1099 if (pi->text)
1100 free(pi->text);
1101 if (pi->cmdbuf)
1102 free(pi->cmdbuf);
1103 memset(pi, 0, sizeof(struct pipe));
1104}
1105
1106/* Checks to see if any background processes have exited -- if they
1107 have, figure out why and see if a job has completed */
1108static void checkjobs()
1109{
1110 int status;
1111 int prognum = 0;
1112 struct pipe *pi;
1113 pid_t childpid;
1114
1115 while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
1116 for (pi = job_list->head; pi; pi = pi->next) {
1117 prognum = 0;
1118 while (prognum < pi->num_progs &&
1119 pi->progs[prognum].pid != childpid) prognum++;
1120 if (prognum < pi->num_progs)
1121 break;
1122 }
1123
1124 if (WIFEXITED(status) || WIFSIGNALED(status)) {
1125 /* child exited */
1126 pi->running_progs--;
1127 pi->progs[prognum].pid = 0;
1128
1129 if (!pi->running_progs) {
1130 printf(JOB_STATUS_FORMAT, pi->jobid, "Done", pi->text);
1131 remove_bg_job(pi);
1132 }
1133 } else {
1134 /* child stopped */
1135 pi->stopped_progs++;
1136 pi->progs[prognum].is_stopped = 1;
1137
1138 if (pi->stopped_progs == pi->num_progs) {
1139 printf(JOB_STATUS_FORMAT, pi->jobid, "Stopped",
1140 pi->text);
1141 }
1142 }
1143 }
1144
1145 /* move the shell to the foreground */
1146 if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY)
1147 perror_msg("tcsetpgrp");
1148
1149 if (childpid == -1 && errno != ECHILD)
1150 perror_msg("waitpid");
1151}
1152
1034/* run_pipe_real() starts all the jobs, but doesn't wait for anything 1153/* run_pipe_real() starts all the jobs, but doesn't wait for anything
1035 * to finish. See pipe_wait(). 1154 * to finish. See pipe_wait().
1036 * 1155 *
@@ -1106,6 +1225,8 @@ static int run_pipe_real(struct pipe *pi)
1106 1225
1107 /* XXX test for failed fork()? */ 1226 /* XXX test for failed fork()? */
1108 if (!(child->pid = fork())) { 1227 if (!(child->pid = fork())) {
1228 signal(SIGTTOU, SIG_DFL);
1229
1109 close_all(); 1230 close_all();
1110 1231
1111 if (nextin != 0) { 1232 if (nextin != 0) {
@@ -1174,22 +1295,25 @@ static int run_list_real(struct pipe *pi)
1174 /* XXX check bash's behavior with nontrivial pipes */ 1295 /* XXX check bash's behavior with nontrivial pipes */
1175 /* XXX compute jobid */ 1296 /* XXX compute jobid */
1176 /* XXX what does bash do with attempts to background builtins? */ 1297 /* XXX what does bash do with attempts to background builtins? */
1298#if 0
1177 printf("[%d] %d\n", pi->jobid, pi->pgrp); 1299 printf("[%d] %d\n", pi->jobid, pi->pgrp);
1178 last_bg_pid = pi->pgrp; 1300 last_bg_pid = pi->pgrp;
1301#endif
1302 insert_bg_job(pi);
1179 rcode = EXIT_SUCCESS; 1303 rcode = EXIT_SUCCESS;
1180 } else { 1304 } else {
1181 if (interactive) { 1305 if (interactive) {
1182 /* move the new process group into the foreground */ 1306 /* move the new process group into the foreground */
1183 /* suppress messages when run from /linuxrc mag@sysgo.de */ 1307 /* suppress messages when run from /linuxrc mag@sysgo.de */
1184 signal(SIGTTIN, SIG_IGN); 1308 //signal(SIGTTIN, SIG_IGN);
1185 signal(SIGTTOU, SIG_IGN); 1309 //signal(SIGTTOU, SIG_IGN);
1186 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY) 1310 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY)
1187 perror_msg("tcsetpgrp"); 1311 perror_msg("tcsetpgrp");
1188 rcode = pipe_wait(pi); 1312 rcode = pipe_wait(pi);
1189 if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY) 1313 if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY)
1190 perror_msg("tcsetpgrp"); 1314 perror_msg("tcsetpgrp");
1191 signal(SIGTTIN, SIG_DFL); 1315 //signal(SIGTTIN, SIG_DFL);
1192 signal(SIGTTOU, SIG_DFL); 1316 //signal(SIGTTOU, SIG_DFL);
1193 } else { 1317 } else {
1194 rcode = pipe_wait(pi); 1318 rcode = pipe_wait(pi);
1195 } 1319 }
@@ -1202,6 +1326,7 @@ static int run_list_real(struct pipe *pi)
1202 skip_more_in_this_rmode=rmode; 1326 skip_more_in_this_rmode=rmode;
1203 /* return rcode; */ /* XXX broken if list is part of if/then/else */ 1327 /* return rcode; */ /* XXX broken if list is part of if/then/else */
1204 } 1328 }
1329 checkjobs();
1205 return rcode; 1330 return rcode;
1206} 1331}
1207 1332
@@ -1298,7 +1423,7 @@ static int globhack(const char *src, int flags, glob_t *pglob)
1298 int cnt, pathc; 1423 int cnt, pathc;
1299 const char *s; 1424 const char *s;
1300 char *dest; 1425 char *dest;
1301 for (cnt=1, s=src; s && *s; s++) { 1426 for (cnt=1, s=src; *s; s++) {
1302 if (*s == '\\') s++; 1427 if (*s == '\\') s++;
1303 cnt++; 1428 cnt++;
1304 } 1429 }
@@ -1315,7 +1440,7 @@ static int globhack(const char *src, int flags, glob_t *pglob)
1315 if (pglob->gl_pathv == NULL) return GLOB_NOSPACE; 1440 if (pglob->gl_pathv == NULL) return GLOB_NOSPACE;
1316 pglob->gl_pathv[pathc-1]=dest; 1441 pglob->gl_pathv[pathc-1]=dest;
1317 pglob->gl_pathv[pathc]=NULL; 1442 pglob->gl_pathv[pathc]=NULL;
1318 for (s=src; s && *s; s++, dest++) { 1443 for (s=src; *s; s++, dest++) {
1319 if (*s == '\\') s++; 1444 if (*s == '\\') s++;
1320 *dest = *s; 1445 *dest = *s;
1321 } 1446 }
@@ -1482,8 +1607,6 @@ int reserved_word(o_string *dest, struct p_context *ctx)
1482 { "done", RES_DONE, FLAG_END } 1607 { "done", RES_DONE, FLAG_END }
1483 }; 1608 };
1484 struct reserved_combo *r; 1609 struct reserved_combo *r;
1485 if (dest->data == NULL)
1486 return 0;
1487 for (r=reserved_list; 1610 for (r=reserved_list;
1488#define NRES sizeof(reserved_list)/sizeof(struct reserved_combo) 1611#define NRES sizeof(reserved_list)/sizeof(struct reserved_combo)
1489 r<reserved_list+NRES; r++) { 1612 r<reserved_list+NRES; r++) {
@@ -2080,6 +2203,8 @@ int shell_main(int argc, char **argv)
2080{ 2203{
2081 int opt; 2204 int opt;
2082 FILE *input; 2205 FILE *input;
2206 struct jobset joblist_end = { NULL, NULL };
2207 job_list = &joblist_end;
2083 2208
2084 last_return_code=EXIT_SUCCESS; 2209 last_return_code=EXIT_SUCCESS;
2085 2210
@@ -2087,6 +2212,10 @@ int shell_main(int argc, char **argv)
2087 global_argc = argc; 2212 global_argc = argc;
2088 global_argv = argv; 2213 global_argv = argv;
2089 2214
2215 /* don't pay any attention to this signal; it just confuses
2216 things and isn't really meant for shells anyway */
2217 signal(SIGTTOU, SIG_IGN);
2218
2090 if (argv[0] && argv[0][0] == '-') { 2219 if (argv[0] && argv[0][0] == '-') {
2091 debug_printf("\nsourcing /etc/profile\n"); 2220 debug_printf("\nsourcing /etc/profile\n");
2092 input = xfopen("/etc/profile", "r"); 2221 input = xfopen("/etc/profile", "r");
diff --git a/shell/hush.c b/shell/hush.c
index 4641e59c8..ed4979818 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -213,7 +213,6 @@ struct pipe {
213 int job_context; /* bitmask defining current context */ 213 int job_context; /* bitmask defining current context */
214 pipe_style followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */ 214 pipe_style followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
215 reserved_style r_mode; /* supports if, for, while, until */ 215 reserved_style r_mode; /* supports if, for, while, until */
216 struct jobset *job_list;
217}; 216};
218 217
219struct jobset { 218struct jobset {
@@ -244,7 +243,7 @@ static int fake_mode=0;
244static int interactive=0; 243static int interactive=0;
245static struct close_me *close_me_head = NULL; 244static struct close_me *close_me_head = NULL;
246static char *cwd; 245static char *cwd;
247/* static struct jobset job_list = { NULL, NULL }; */ 246static struct jobset *job_list;
248static unsigned int last_bg_pid=0; 247static unsigned int last_bg_pid=0;
249static char *PS1; 248static char *PS1;
250static char *PS2 = "> "; 249static char *PS2 = "> ";
@@ -377,6 +376,11 @@ static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *in
377static int parse_stream_outer(struct in_str *inp); 376static int parse_stream_outer(struct in_str *inp);
378static int parse_string_outer(const char *s); 377static int parse_string_outer(const char *s);
379static int parse_file_outer(FILE *f); 378static int parse_file_outer(FILE *f);
379/* job management: */
380static void checkjobs();
381static void insert_bg_job(struct pipe *pi);
382static void remove_bg_job(struct pipe *pi);
383static void free_pipe(struct pipe *pi);
380 384
381/* Table of built-in functions. They can be forked or not, depending on 385/* Table of built-in functions. They can be forked or not, depending on
382 * context: within pipes, they fork. As simple commands, they do not. 386 * context: within pipes, they fork. As simple commands, they do not.
@@ -481,7 +485,7 @@ static int builtin_fg_bg(struct child_prog *child)
481 return EXIT_FAILURE; 485 return EXIT_FAILURE;
482 } 486 }
483 487
484 for (job = child->family->job_list->head; job; job = job->next) { 488 for (job = job_list->head; job; job = job->next) {
485 if (job->jobid == jobNum) { 489 if (job->jobid == jobNum) {
486 break; 490 break;
487 } 491 }
@@ -498,7 +502,7 @@ static int builtin_fg_bg(struct child_prog *child)
498 /* suppress messages when run from /linuxrc mag@sysgo.de */ 502 /* suppress messages when run from /linuxrc mag@sysgo.de */
499 if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY) 503 if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY)
500 perror_msg("tcsetpgrp"); 504 perror_msg("tcsetpgrp");
501 child->family->job_list->fg = job; 505 job_list->fg = job;
502 } 506 }
503 507
504 /* Restart the processes in the job */ 508 /* Restart the processes in the job */
@@ -533,7 +537,7 @@ static int builtin_jobs(struct child_prog *child)
533 struct pipe *job; 537 struct pipe *job;
534 char *status_string; 538 char *status_string;
535 539
536 for (job = child->family->job_list->head; job; job = job->next) { 540 for (job = job_list->head; job; job = job->next) {
537 if (job->running_progs == job->stopped_progs) 541 if (job->running_progs == job->stopped_progs)
538 status_string = "Stopped"; 542 status_string = "Stopped";
539 else 543 else
@@ -1031,6 +1035,121 @@ static void pseudo_exec(struct child_prog *child)
1031 } 1035 }
1032} 1036}
1033 1037
1038static void insert_bg_job(struct pipe *pi)
1039{
1040 struct pipe *thejob;
1041
1042 /* Linear search for the ID of the job to use */
1043 pi->jobid = 1;
1044 for (thejob = job_list->head; thejob; thejob = thejob->next)
1045 if (thejob->jobid >= pi->jobid)
1046 pi->jobid = thejob->jobid + 1;
1047
1048 /* add thejob to the list of running jobs */
1049 if (!job_list->head) {
1050 thejob = job_list->head = xmalloc(sizeof(*thejob));
1051 } else {
1052 for (thejob = job_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1053 thejob->next = xmalloc(sizeof(*thejob));
1054 thejob = thejob->next;
1055 }
1056
1057 /* physically copy the struct job */
1058 *thejob = *pi;
1059 thejob->next = NULL;
1060 thejob->running_progs = thejob->num_progs;
1061 thejob->stopped_progs = 0;
1062
1063 /* we don't wait for background thejobs to return -- append it
1064 to the list of backgrounded thejobs and leave it alone */
1065 printf("[%d] %d\n", pi->jobid, pi->pgrp);
1066 last_bg_pid = pi->pgrp;
1067}
1068
1069/* remove a backgrounded job from a jobset */
1070static void remove_bg_job(struct pipe *pi)
1071{
1072 struct pipe *prev_pipe;
1073
1074 free_pipe(pi);
1075 if (pi == job_list->head) {
1076 job_list->head = pi->next;
1077 } else {
1078 prev_pipe = job_list->head;
1079 while (prev_pipe->next != pi)
1080 prev_pipe = prev_pipe->next;
1081 prev_pipe->next = pi->next;
1082 }
1083
1084 free(pi);
1085}
1086
1087/* free up all memory from a pipe */
1088static void free_pipe(struct pipe *pi)
1089{
1090 int i;
1091
1092 for (i = 0; i < pi->num_progs; i++) {
1093 free(pi->progs[i].argv);
1094 if (pi->progs[i].redirects)
1095 free(pi->progs[i].redirects);
1096 }
1097 if (pi->progs)
1098 free(pi->progs);
1099 if (pi->text)
1100 free(pi->text);
1101 if (pi->cmdbuf)
1102 free(pi->cmdbuf);
1103 memset(pi, 0, sizeof(struct pipe));
1104}
1105
1106/* Checks to see if any background processes have exited -- if they
1107 have, figure out why and see if a job has completed */
1108static void checkjobs()
1109{
1110 int status;
1111 int prognum = 0;
1112 struct pipe *pi;
1113 pid_t childpid;
1114
1115 while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
1116 for (pi = job_list->head; pi; pi = pi->next) {
1117 prognum = 0;
1118 while (prognum < pi->num_progs &&
1119 pi->progs[prognum].pid != childpid) prognum++;
1120 if (prognum < pi->num_progs)
1121 break;
1122 }
1123
1124 if (WIFEXITED(status) || WIFSIGNALED(status)) {
1125 /* child exited */
1126 pi->running_progs--;
1127 pi->progs[prognum].pid = 0;
1128
1129 if (!pi->running_progs) {
1130 printf(JOB_STATUS_FORMAT, pi->jobid, "Done", pi->text);
1131 remove_bg_job(pi);
1132 }
1133 } else {
1134 /* child stopped */
1135 pi->stopped_progs++;
1136 pi->progs[prognum].is_stopped = 1;
1137
1138 if (pi->stopped_progs == pi->num_progs) {
1139 printf(JOB_STATUS_FORMAT, pi->jobid, "Stopped",
1140 pi->text);
1141 }
1142 }
1143 }
1144
1145 /* move the shell to the foreground */
1146 if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY)
1147 perror_msg("tcsetpgrp");
1148
1149 if (childpid == -1 && errno != ECHILD)
1150 perror_msg("waitpid");
1151}
1152
1034/* run_pipe_real() starts all the jobs, but doesn't wait for anything 1153/* run_pipe_real() starts all the jobs, but doesn't wait for anything
1035 * to finish. See pipe_wait(). 1154 * to finish. See pipe_wait().
1036 * 1155 *
@@ -1106,6 +1225,8 @@ static int run_pipe_real(struct pipe *pi)
1106 1225
1107 /* XXX test for failed fork()? */ 1226 /* XXX test for failed fork()? */
1108 if (!(child->pid = fork())) { 1227 if (!(child->pid = fork())) {
1228 signal(SIGTTOU, SIG_DFL);
1229
1109 close_all(); 1230 close_all();
1110 1231
1111 if (nextin != 0) { 1232 if (nextin != 0) {
@@ -1174,22 +1295,25 @@ static int run_list_real(struct pipe *pi)
1174 /* XXX check bash's behavior with nontrivial pipes */ 1295 /* XXX check bash's behavior with nontrivial pipes */
1175 /* XXX compute jobid */ 1296 /* XXX compute jobid */
1176 /* XXX what does bash do with attempts to background builtins? */ 1297 /* XXX what does bash do with attempts to background builtins? */
1298#if 0
1177 printf("[%d] %d\n", pi->jobid, pi->pgrp); 1299 printf("[%d] %d\n", pi->jobid, pi->pgrp);
1178 last_bg_pid = pi->pgrp; 1300 last_bg_pid = pi->pgrp;
1301#endif
1302 insert_bg_job(pi);
1179 rcode = EXIT_SUCCESS; 1303 rcode = EXIT_SUCCESS;
1180 } else { 1304 } else {
1181 if (interactive) { 1305 if (interactive) {
1182 /* move the new process group into the foreground */ 1306 /* move the new process group into the foreground */
1183 /* suppress messages when run from /linuxrc mag@sysgo.de */ 1307 /* suppress messages when run from /linuxrc mag@sysgo.de */
1184 signal(SIGTTIN, SIG_IGN); 1308 //signal(SIGTTIN, SIG_IGN);
1185 signal(SIGTTOU, SIG_IGN); 1309 //signal(SIGTTOU, SIG_IGN);
1186 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY) 1310 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY)
1187 perror_msg("tcsetpgrp"); 1311 perror_msg("tcsetpgrp");
1188 rcode = pipe_wait(pi); 1312 rcode = pipe_wait(pi);
1189 if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY) 1313 if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY)
1190 perror_msg("tcsetpgrp"); 1314 perror_msg("tcsetpgrp");
1191 signal(SIGTTIN, SIG_DFL); 1315 //signal(SIGTTIN, SIG_DFL);
1192 signal(SIGTTOU, SIG_DFL); 1316 //signal(SIGTTOU, SIG_DFL);
1193 } else { 1317 } else {
1194 rcode = pipe_wait(pi); 1318 rcode = pipe_wait(pi);
1195 } 1319 }
@@ -1202,6 +1326,7 @@ static int run_list_real(struct pipe *pi)
1202 skip_more_in_this_rmode=rmode; 1326 skip_more_in_this_rmode=rmode;
1203 /* return rcode; */ /* XXX broken if list is part of if/then/else */ 1327 /* return rcode; */ /* XXX broken if list is part of if/then/else */
1204 } 1328 }
1329 checkjobs();
1205 return rcode; 1330 return rcode;
1206} 1331}
1207 1332
@@ -1298,7 +1423,7 @@ static int globhack(const char *src, int flags, glob_t *pglob)
1298 int cnt, pathc; 1423 int cnt, pathc;
1299 const char *s; 1424 const char *s;
1300 char *dest; 1425 char *dest;
1301 for (cnt=1, s=src; s && *s; s++) { 1426 for (cnt=1, s=src; *s; s++) {
1302 if (*s == '\\') s++; 1427 if (*s == '\\') s++;
1303 cnt++; 1428 cnt++;
1304 } 1429 }
@@ -1315,7 +1440,7 @@ static int globhack(const char *src, int flags, glob_t *pglob)
1315 if (pglob->gl_pathv == NULL) return GLOB_NOSPACE; 1440 if (pglob->gl_pathv == NULL) return GLOB_NOSPACE;
1316 pglob->gl_pathv[pathc-1]=dest; 1441 pglob->gl_pathv[pathc-1]=dest;
1317 pglob->gl_pathv[pathc]=NULL; 1442 pglob->gl_pathv[pathc]=NULL;
1318 for (s=src; s && *s; s++, dest++) { 1443 for (s=src; *s; s++, dest++) {
1319 if (*s == '\\') s++; 1444 if (*s == '\\') s++;
1320 *dest = *s; 1445 *dest = *s;
1321 } 1446 }
@@ -1482,8 +1607,6 @@ int reserved_word(o_string *dest, struct p_context *ctx)
1482 { "done", RES_DONE, FLAG_END } 1607 { "done", RES_DONE, FLAG_END }
1483 }; 1608 };
1484 struct reserved_combo *r; 1609 struct reserved_combo *r;
1485 if (dest->data == NULL)
1486 return 0;
1487 for (r=reserved_list; 1610 for (r=reserved_list;
1488#define NRES sizeof(reserved_list)/sizeof(struct reserved_combo) 1611#define NRES sizeof(reserved_list)/sizeof(struct reserved_combo)
1489 r<reserved_list+NRES; r++) { 1612 r<reserved_list+NRES; r++) {
@@ -2080,6 +2203,8 @@ int shell_main(int argc, char **argv)
2080{ 2203{
2081 int opt; 2204 int opt;
2082 FILE *input; 2205 FILE *input;
2206 struct jobset joblist_end = { NULL, NULL };
2207 job_list = &joblist_end;
2083 2208
2084 last_return_code=EXIT_SUCCESS; 2209 last_return_code=EXIT_SUCCESS;
2085 2210
@@ -2087,6 +2212,10 @@ int shell_main(int argc, char **argv)
2087 global_argc = argc; 2212 global_argc = argc;
2088 global_argv = argv; 2213 global_argv = argv;
2089 2214
2215 /* don't pay any attention to this signal; it just confuses
2216 things and isn't really meant for shells anyway */
2217 signal(SIGTTOU, SIG_IGN);
2218
2090 if (argv[0] && argv[0][0] == '-') { 2219 if (argv[0] && argv[0][0] == '-') {
2091 debug_printf("\nsourcing /etc/profile\n"); 2220 debug_printf("\nsourcing /etc/profile\n");
2092 input = xfopen("/etc/profile", "r"); 2221 input = xfopen("/etc/profile", "r");