aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-06-22 06:49:26 +0000
committerEric Andersen <andersen@codepoet.org>2001-06-22 06:49:26 +0000
commit52a97ca00cf5d290c9beb65ba7c217a5ed69ee42 (patch)
treed87fec02a954a19653c67025d22ba8ecb8df4123
parentc798b0776264950350b53a0aa58101bb1dfcf6dc (diff)
downloadbusybox-w32-52a97ca00cf5d290c9beb65ba7c217a5ed69ee42.tar.gz
busybox-w32-52a97ca00cf5d290c9beb65ba7c217a5ed69ee42.tar.bz2
busybox-w32-52a97ca00cf5d290c9beb65ba7c217a5ed69ee42.zip
Some more cleanups. Of special importance, never free a pipe
that still has running jobs. Instead, we ignore it and expect it to be cleaned by the background job stuff. -Erik
-rw-r--r--hush.c79
-rw-r--r--shell/hush.c79
2 files changed, 104 insertions, 54 deletions
diff --git a/hush.c b/hush.c
index a9d3a16ac..fa01d9135 100644
--- a/hush.c
+++ b/hush.c
@@ -257,6 +257,7 @@ static char *PS2;
257struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 }; 257struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
258struct variables *top_vars = &shell_ver; 258struct variables *top_vars = &shell_ver;
259 259
260
260#define B_CHUNK (100) 261#define B_CHUNK (100)
261#define B_NOSPAC 1 262#define B_NOSPAC 1
262 263
@@ -394,7 +395,7 @@ static void remove_bg_job(struct pipe *pi);
394static char *get_local_var(const char *var); 395static char *get_local_var(const char *var);
395static void unset_local_var(const char *name); 396static void unset_local_var(const char *name);
396static int set_local_var(const char *s, int flg_export); 397static int set_local_var(const char *s, int flg_export);
397 398static void sigchld_handler(int sig);
398 399
399/* Table of built-in functions. They can be forked or not, depending on 400/* Table of built-in functions. They can be forked or not, depending on
400 * context: within pipes, they fork. As simple commands, they do not. 401 * context: within pipes, they fork. As simple commands, they do not.
@@ -556,7 +557,6 @@ static int builtin_fg_bg(struct child_prog *child)
556 error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]); 557 error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]);
557 return EXIT_FAILURE; 558 return EXIT_FAILURE;
558 } 559 }
559
560 for (pi = job_list; pi; pi = pi->next) { 560 for (pi = job_list; pi; pi = pi->next) {
561 if (pi->jobid == jobnum) { 561 if (pi->jobid == jobnum) {
562 break; 562 break;
@@ -567,6 +567,7 @@ static int builtin_fg_bg(struct child_prog *child)
567 return EXIT_FAILURE; 567 return EXIT_FAILURE;
568 } 568 }
569 } 569 }
570
570 if (*child->argv[0] == 'f') { 571 if (*child->argv[0] == 'f') {
571 /* Make this job the foreground job */ 572 /* Make this job the foreground job */
572 signal(SIGTTOU, SIG_IGN); 573 signal(SIGTTOU, SIG_IGN);
@@ -613,6 +614,7 @@ static int builtin_jobs(struct child_prog *child)
613 status_string = "Stopped"; 614 status_string = "Stopped";
614 else 615 else
615 status_string = "Running"; 616 status_string = "Running";
617
616 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text); 618 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
617 } 619 }
618 return EXIT_SUCCESS; 620 return EXIT_SUCCESS;
@@ -1142,7 +1144,7 @@ static void insert_bg_job(struct pipe *pi)
1142 1144
1143 /* add thejob to the list of running jobs */ 1145 /* add thejob to the list of running jobs */
1144 if (!job_list) { 1146 if (!job_list) {
1145 thejob = job_list= xmalloc(sizeof(*thejob)); 1147 thejob = job_list = xmalloc(sizeof(*thejob));
1146 } else { 1148 } else {
1147 for (thejob = job_list; thejob->next; thejob = thejob->next) /* nothing */; 1149 for (thejob = job_list; thejob->next; thejob = thejob->next) /* nothing */;
1148 thejob->next = xmalloc(sizeof(*thejob)); 1150 thejob->next = xmalloc(sizeof(*thejob));
@@ -1178,14 +1180,14 @@ static void remove_bg_job(struct pipe *pi)
1178 struct pipe *prev_pipe; 1180 struct pipe *prev_pipe;
1179 1181
1180 if (pi == job_list) { 1182 if (pi == job_list) {
1181 job_list= pi->next; 1183 job_list = pi->next;
1182 } else { 1184 } else {
1183 prev_pipe = job_list; 1185 prev_pipe = job_list;
1184 while (prev_pipe->next != pi) 1186 while (prev_pipe->next != pi)
1185 prev_pipe = prev_pipe->next; 1187 prev_pipe = prev_pipe->next;
1186 prev_pipe->next = pi->next; 1188 prev_pipe->next = pi->next;
1187 } 1189 }
1188 1190 pi->stopped_progs = 0;
1189 free_pipe(pi, 0); 1191 free_pipe(pi, 0);
1190 free(pi); 1192 free(pi);
1191} 1193}
@@ -1210,7 +1212,7 @@ static int checkjobs(struct pipe* fg_pipe)
1210 int i, rcode = 0; 1212 int i, rcode = 0;
1211 for (i=0; i < fg_pipe->num_progs; i++) { 1213 for (i=0; i < fg_pipe->num_progs; i++) {
1212 if (fg_pipe->progs[i].pid == childpid) { 1214 if (fg_pipe->progs[i].pid == childpid) {
1213 if (i==fg_pipe->num_progs-1) 1215 if (i==fg_pipe->num_progs-1)
1214 rcode=WEXITSTATUS(status); 1216 rcode=WEXITSTATUS(status);
1215 (fg_pipe->num_progs)--; 1217 (fg_pipe->num_progs)--;
1216 return(rcode); 1218 return(rcode);
@@ -1220,8 +1222,9 @@ static int checkjobs(struct pipe* fg_pipe)
1220 1222
1221 for (pi = job_list; pi; pi = pi->next) { 1223 for (pi = job_list; pi; pi = pi->next) {
1222 prognum = 0; 1224 prognum = 0;
1223 while (prognum < pi->num_progs && 1225 while (prognum < pi->num_progs && pi->progs[prognum].pid != childpid) {
1224 pi->progs[prognum].pid != childpid) prognum++; 1226 prognum++;
1227 }
1225 if (prognum < pi->num_progs) 1228 if (prognum < pi->num_progs)
1226 break; 1229 break;
1227 } 1230 }
@@ -1245,9 +1248,14 @@ static int checkjobs(struct pipe* fg_pipe)
1245 pi->stopped_progs++; 1248 pi->stopped_progs++;
1246 pi->progs[prognum].is_stopped = 1; 1249 pi->progs[prognum].is_stopped = 1;
1247 1250
1251#if 0
1252 /* Printing this stuff is a pain, since it tends to
1253 * overwrite the prompt an inconveinient moments. So
1254 * don't do that. */
1248 if (pi->stopped_progs == pi->num_progs) { 1255 if (pi->stopped_progs == pi->num_progs) {
1249 printf(JOB_STATUS_FORMAT, pi->jobid, "Stopped", pi->text); 1256 printf("\n"JOB_STATUS_FORMAT, pi->jobid, "Stopped", pi->text);
1250 } 1257 }
1258#endif
1251 } 1259 }
1252 } 1260 }
1253 1261
@@ -1394,7 +1402,6 @@ static int run_pipe_real(struct pipe *pi)
1394 1402
1395 /* XXX test for failed fork()? */ 1403 /* XXX test for failed fork()? */
1396 if (!(child->pid = fork())) { 1404 if (!(child->pid = fork())) {
1397
1398 signal(SIGTTOU, SIG_DFL); 1405 signal(SIGTTOU, SIG_DFL);
1399 1406
1400 close_all(); 1407 close_all();
@@ -1414,7 +1421,7 @@ static int run_pipe_real(struct pipe *pi)
1414 /* Like bash, explicit redirects override pipes, 1421 /* Like bash, explicit redirects override pipes,
1415 * and the pipe fd is available for dup'ing. */ 1422 * and the pipe fd is available for dup'ing. */
1416 setup_redirects(child,NULL); 1423 setup_redirects(child,NULL);
1417 1424
1418 if (interactive && pi->followup!=PIPE_BG) { 1425 if (interactive && pi->followup!=PIPE_BG) {
1419 /* If we (the child) win the race, put ourselves in the process 1426 /* If we (the child) win the race, put ourselves in the process
1420 * group whose leader is the first process in this pipe. */ 1427 * group whose leader is the first process in this pipe. */
@@ -1423,15 +1430,17 @@ static int run_pipe_real(struct pipe *pi)
1423 } 1430 }
1424 if (setpgid(0, pi->pgrp) == 0) { 1431 if (setpgid(0, pi->pgrp) == 0) {
1425 signal(SIGTTOU, SIG_IGN); 1432 signal(SIGTTOU, SIG_IGN);
1426 tcsetpgrp(ctty, pi->pgrp); 1433 tcsetpgrp(2, pi->pgrp);
1427 signal(SIGTTOU, SIG_DFL); 1434 signal(SIGTTOU, SIG_DFL);
1428 } 1435 }
1429 } 1436 }
1430 1437
1431 pseudo_exec(child); 1438 pseudo_exec(child);
1432 } 1439 }
1433 /* Put our child in the process group whose leader is the 1440
1434 * first process in this pipe. */ 1441
1442 /* put our child in the process group whose leader is the
1443 first process in this pipe */
1435 if (pi->pgrp < 0) { 1444 if (pi->pgrp < 0) {
1436 pi->pgrp = child->pid; 1445 pi->pgrp = child->pid;
1437 } 1446 }
@@ -1478,18 +1487,18 @@ static int run_list_real(struct pipe *pi)
1478 insert_bg_job(pi); 1487 insert_bg_job(pi);
1479 rcode = EXIT_SUCCESS; 1488 rcode = EXIT_SUCCESS;
1480 } else { 1489 } else {
1481
1482 if (interactive) { 1490 if (interactive) {
1483 /* move the new process group into the foreground */ 1491 /* move the new process group into the foreground */
1484 if (tcsetpgrp(ctty, pi->pgrp) && errno != ENOTTY) 1492 if (tcsetpgrp(ctty, pi->pgrp) && errno != ENOTTY)
1485 perror_msg("tcsetpgrp-3"); 1493 perror_msg("tcsetpgrp-3");
1486 rcode = checkjobs(pi); 1494 rcode = checkjobs(pi);
1495 /* move the shell to the foreground */
1487 if (tcsetpgrp(ctty, getpgid(0)) && errno != ENOTTY) 1496 if (tcsetpgrp(ctty, getpgid(0)) && errno != ENOTTY)
1488 perror_msg("tcsetpgrp-4"); 1497 perror_msg("tcsetpgrp-4");
1489 } else { 1498 } else {
1490 rcode = checkjobs(pi); 1499 rcode = checkjobs(pi);
1491 } 1500 }
1492 debug_printf("pipe_wait returned %d\n",rcode); 1501 debug_printf("checkjobs returned %d\n",rcode);
1493 } 1502 }
1494 last_return_code=rcode; 1503 last_return_code=rcode;
1495 if ( rmode == RES_IF || rmode == RES_ELIF ) 1504 if ( rmode == RES_IF || rmode == RES_ELIF )
@@ -1517,6 +1526,9 @@ static int free_pipe(struct pipe *pi, int indent)
1517 struct redir_struct *r, *rnext; 1526 struct redir_struct *r, *rnext;
1518 int a, i, ret_code=0; 1527 int a, i, ret_code=0;
1519 char *ind = indenter(indent); 1528 char *ind = indenter(indent);
1529
1530 if (pi->stopped_progs > 0)
1531 return ret_code;
1520 final_printf("%s run pipe: (pid %d)\n",ind,getpid()); 1532 final_printf("%s run pipe: (pid %d)\n",ind,getpid());
1521 for (i=0; i<pi->num_progs; i++) { 1533 for (i=0; i<pi->num_progs; i++) {
1522 child = &pi->progs[i]; 1534 child = &pi->progs[i];
@@ -2516,6 +2528,27 @@ static int parse_file_outer(FILE *f)
2516 return rcode; 2528 return rcode;
2517} 2529}
2518 2530
2531static void sigchld_handler(int sig)
2532{
2533 checkjobs(NULL);
2534 signal(SIGCHLD, sigchld_handler);
2535}
2536
2537static void setup_job_control()
2538{
2539 /* If we get started under a job aware app (like bash
2540 * for example), make sure we are now in charge so we
2541 * don't fight over who gets the foreground */
2542 /* don't pay any attention to this signal; it just confuses
2543 things and isn't really meant for shells anyway */
2544 setpgrp();
2545 controlling_tty(0);
2546 signal(SIGTTOU, SIG_IGN);
2547 setpgid(0, getpid());
2548 tcsetpgrp(ctty, getpid());
2549 signal(SIGCHLD, sigchld_handler);
2550}
2551
2519 2552
2520int shell_main(int argc, char **argv) 2553int shell_main(int argc, char **argv)
2521{ 2554{
@@ -2536,11 +2569,11 @@ int shell_main(int argc, char **argv)
2536 interactive = 0; 2569 interactive = 0;
2537 close_me_head = NULL; 2570 close_me_head = NULL;
2538 last_bg_pid = 0; 2571 last_bg_pid = 0;
2572 job_list = NULL;
2539 last_jobid = 0; 2573 last_jobid = 0;
2540 2574
2541 /* Initialize some more globals to non-zero values */ 2575 /* Initialize some more globals to non-zero values */
2542 set_cwd(); 2576 set_cwd();
2543 job_list = NULL;
2544#ifdef BB_FEATURE_COMMAND_EDITING 2577#ifdef BB_FEATURE_COMMAND_EDITING
2545 cmdedit_set_initial_prompt(); 2578 cmdedit_set_initial_prompt();
2546#else 2579#else
@@ -2558,16 +2591,6 @@ int shell_main(int argc, char **argv)
2558 last_return_code=EXIT_SUCCESS; 2591 last_return_code=EXIT_SUCCESS;
2559 2592
2560 2593
2561 /* If we get started under a job aware app (like bash
2562 * for example), make sure we are now in charge so we
2563 * don't fight over who gets the foreground */
2564 /* don't pay any attention to this signal; it just confuses
2565 things and isn't really meant for shells anyway */
2566 controlling_tty(0);
2567 signal(SIGTTOU, SIG_IGN);
2568 setpgid(0, getpid());
2569 tcsetpgrp(ctty, getpid());
2570
2571 if (argv[0] && argv[0][0] == '-') { 2594 if (argv[0] && argv[0][0] == '-') {
2572 debug_printf("\nsourcing /etc/profile\n"); 2595 debug_printf("\nsourcing /etc/profile\n");
2573 input = xfopen("/etc/profile", "r"); 2596 input = xfopen("/etc/profile", "r");
@@ -2620,7 +2643,9 @@ int shell_main(int argc, char **argv)
2620 if (interactive) { 2643 if (interactive) {
2621 /* Looks like they want an interactive shell */ 2644 /* Looks like they want an interactive shell */
2622 fprintf(stdout, "\nhush -- the humble shell v0.01 (testing)\n\n"); 2645 fprintf(stdout, "\nhush -- the humble shell v0.01 (testing)\n\n");
2646 setup_job_control();
2623 } 2647 }
2648
2624 if (argv[optind]==NULL) { 2649 if (argv[optind]==NULL) {
2625 opt=parse_file_outer(stdin); 2650 opt=parse_file_outer(stdin);
2626 goto final_return; 2651 goto final_return;
diff --git a/shell/hush.c b/shell/hush.c
index a9d3a16ac..fa01d9135 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -257,6 +257,7 @@ static char *PS2;
257struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 }; 257struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
258struct variables *top_vars = &shell_ver; 258struct variables *top_vars = &shell_ver;
259 259
260
260#define B_CHUNK (100) 261#define B_CHUNK (100)
261#define B_NOSPAC 1 262#define B_NOSPAC 1
262 263
@@ -394,7 +395,7 @@ static void remove_bg_job(struct pipe *pi);
394static char *get_local_var(const char *var); 395static char *get_local_var(const char *var);
395static void unset_local_var(const char *name); 396static void unset_local_var(const char *name);
396static int set_local_var(const char *s, int flg_export); 397static int set_local_var(const char *s, int flg_export);
397 398static void sigchld_handler(int sig);
398 399
399/* Table of built-in functions. They can be forked or not, depending on 400/* Table of built-in functions. They can be forked or not, depending on
400 * context: within pipes, they fork. As simple commands, they do not. 401 * context: within pipes, they fork. As simple commands, they do not.
@@ -556,7 +557,6 @@ static int builtin_fg_bg(struct child_prog *child)
556 error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]); 557 error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]);
557 return EXIT_FAILURE; 558 return EXIT_FAILURE;
558 } 559 }
559
560 for (pi = job_list; pi; pi = pi->next) { 560 for (pi = job_list; pi; pi = pi->next) {
561 if (pi->jobid == jobnum) { 561 if (pi->jobid == jobnum) {
562 break; 562 break;
@@ -567,6 +567,7 @@ static int builtin_fg_bg(struct child_prog *child)
567 return EXIT_FAILURE; 567 return EXIT_FAILURE;
568 } 568 }
569 } 569 }
570
570 if (*child->argv[0] == 'f') { 571 if (*child->argv[0] == 'f') {
571 /* Make this job the foreground job */ 572 /* Make this job the foreground job */
572 signal(SIGTTOU, SIG_IGN); 573 signal(SIGTTOU, SIG_IGN);
@@ -613,6 +614,7 @@ static int builtin_jobs(struct child_prog *child)
613 status_string = "Stopped"; 614 status_string = "Stopped";
614 else 615 else
615 status_string = "Running"; 616 status_string = "Running";
617
616 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text); 618 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
617 } 619 }
618 return EXIT_SUCCESS; 620 return EXIT_SUCCESS;
@@ -1142,7 +1144,7 @@ static void insert_bg_job(struct pipe *pi)
1142 1144
1143 /* add thejob to the list of running jobs */ 1145 /* add thejob to the list of running jobs */
1144 if (!job_list) { 1146 if (!job_list) {
1145 thejob = job_list= xmalloc(sizeof(*thejob)); 1147 thejob = job_list = xmalloc(sizeof(*thejob));
1146 } else { 1148 } else {
1147 for (thejob = job_list; thejob->next; thejob = thejob->next) /* nothing */; 1149 for (thejob = job_list; thejob->next; thejob = thejob->next) /* nothing */;
1148 thejob->next = xmalloc(sizeof(*thejob)); 1150 thejob->next = xmalloc(sizeof(*thejob));
@@ -1178,14 +1180,14 @@ static void remove_bg_job(struct pipe *pi)
1178 struct pipe *prev_pipe; 1180 struct pipe *prev_pipe;
1179 1181
1180 if (pi == job_list) { 1182 if (pi == job_list) {
1181 job_list= pi->next; 1183 job_list = pi->next;
1182 } else { 1184 } else {
1183 prev_pipe = job_list; 1185 prev_pipe = job_list;
1184 while (prev_pipe->next != pi) 1186 while (prev_pipe->next != pi)
1185 prev_pipe = prev_pipe->next; 1187 prev_pipe = prev_pipe->next;
1186 prev_pipe->next = pi->next; 1188 prev_pipe->next = pi->next;
1187 } 1189 }
1188 1190 pi->stopped_progs = 0;
1189 free_pipe(pi, 0); 1191 free_pipe(pi, 0);
1190 free(pi); 1192 free(pi);
1191} 1193}
@@ -1210,7 +1212,7 @@ static int checkjobs(struct pipe* fg_pipe)
1210 int i, rcode = 0; 1212 int i, rcode = 0;
1211 for (i=0; i < fg_pipe->num_progs; i++) { 1213 for (i=0; i < fg_pipe->num_progs; i++) {
1212 if (fg_pipe->progs[i].pid == childpid) { 1214 if (fg_pipe->progs[i].pid == childpid) {
1213 if (i==fg_pipe->num_progs-1) 1215 if (i==fg_pipe->num_progs-1)
1214 rcode=WEXITSTATUS(status); 1216 rcode=WEXITSTATUS(status);
1215 (fg_pipe->num_progs)--; 1217 (fg_pipe->num_progs)--;
1216 return(rcode); 1218 return(rcode);
@@ -1220,8 +1222,9 @@ static int checkjobs(struct pipe* fg_pipe)
1220 1222
1221 for (pi = job_list; pi; pi = pi->next) { 1223 for (pi = job_list; pi; pi = pi->next) {
1222 prognum = 0; 1224 prognum = 0;
1223 while (prognum < pi->num_progs && 1225 while (prognum < pi->num_progs && pi->progs[prognum].pid != childpid) {
1224 pi->progs[prognum].pid != childpid) prognum++; 1226 prognum++;
1227 }
1225 if (prognum < pi->num_progs) 1228 if (prognum < pi->num_progs)
1226 break; 1229 break;
1227 } 1230 }
@@ -1245,9 +1248,14 @@ static int checkjobs(struct pipe* fg_pipe)
1245 pi->stopped_progs++; 1248 pi->stopped_progs++;
1246 pi->progs[prognum].is_stopped = 1; 1249 pi->progs[prognum].is_stopped = 1;
1247 1250
1251#if 0
1252 /* Printing this stuff is a pain, since it tends to
1253 * overwrite the prompt an inconveinient moments. So
1254 * don't do that. */
1248 if (pi->stopped_progs == pi->num_progs) { 1255 if (pi->stopped_progs == pi->num_progs) {
1249 printf(JOB_STATUS_FORMAT, pi->jobid, "Stopped", pi->text); 1256 printf("\n"JOB_STATUS_FORMAT, pi->jobid, "Stopped", pi->text);
1250 } 1257 }
1258#endif
1251 } 1259 }
1252 } 1260 }
1253 1261
@@ -1394,7 +1402,6 @@ static int run_pipe_real(struct pipe *pi)
1394 1402
1395 /* XXX test for failed fork()? */ 1403 /* XXX test for failed fork()? */
1396 if (!(child->pid = fork())) { 1404 if (!(child->pid = fork())) {
1397
1398 signal(SIGTTOU, SIG_DFL); 1405 signal(SIGTTOU, SIG_DFL);
1399 1406
1400 close_all(); 1407 close_all();
@@ -1414,7 +1421,7 @@ static int run_pipe_real(struct pipe *pi)
1414 /* Like bash, explicit redirects override pipes, 1421 /* Like bash, explicit redirects override pipes,
1415 * and the pipe fd is available for dup'ing. */ 1422 * and the pipe fd is available for dup'ing. */
1416 setup_redirects(child,NULL); 1423 setup_redirects(child,NULL);
1417 1424
1418 if (interactive && pi->followup!=PIPE_BG) { 1425 if (interactive && pi->followup!=PIPE_BG) {
1419 /* If we (the child) win the race, put ourselves in the process 1426 /* If we (the child) win the race, put ourselves in the process
1420 * group whose leader is the first process in this pipe. */ 1427 * group whose leader is the first process in this pipe. */
@@ -1423,15 +1430,17 @@ static int run_pipe_real(struct pipe *pi)
1423 } 1430 }
1424 if (setpgid(0, pi->pgrp) == 0) { 1431 if (setpgid(0, pi->pgrp) == 0) {
1425 signal(SIGTTOU, SIG_IGN); 1432 signal(SIGTTOU, SIG_IGN);
1426 tcsetpgrp(ctty, pi->pgrp); 1433 tcsetpgrp(2, pi->pgrp);
1427 signal(SIGTTOU, SIG_DFL); 1434 signal(SIGTTOU, SIG_DFL);
1428 } 1435 }
1429 } 1436 }
1430 1437
1431 pseudo_exec(child); 1438 pseudo_exec(child);
1432 } 1439 }
1433 /* Put our child in the process group whose leader is the 1440
1434 * first process in this pipe. */ 1441
1442 /* put our child in the process group whose leader is the
1443 first process in this pipe */
1435 if (pi->pgrp < 0) { 1444 if (pi->pgrp < 0) {
1436 pi->pgrp = child->pid; 1445 pi->pgrp = child->pid;
1437 } 1446 }
@@ -1478,18 +1487,18 @@ static int run_list_real(struct pipe *pi)
1478 insert_bg_job(pi); 1487 insert_bg_job(pi);
1479 rcode = EXIT_SUCCESS; 1488 rcode = EXIT_SUCCESS;
1480 } else { 1489 } else {
1481
1482 if (interactive) { 1490 if (interactive) {
1483 /* move the new process group into the foreground */ 1491 /* move the new process group into the foreground */
1484 if (tcsetpgrp(ctty, pi->pgrp) && errno != ENOTTY) 1492 if (tcsetpgrp(ctty, pi->pgrp) && errno != ENOTTY)
1485 perror_msg("tcsetpgrp-3"); 1493 perror_msg("tcsetpgrp-3");
1486 rcode = checkjobs(pi); 1494 rcode = checkjobs(pi);
1495 /* move the shell to the foreground */
1487 if (tcsetpgrp(ctty, getpgid(0)) && errno != ENOTTY) 1496 if (tcsetpgrp(ctty, getpgid(0)) && errno != ENOTTY)
1488 perror_msg("tcsetpgrp-4"); 1497 perror_msg("tcsetpgrp-4");
1489 } else { 1498 } else {
1490 rcode = checkjobs(pi); 1499 rcode = checkjobs(pi);
1491 } 1500 }
1492 debug_printf("pipe_wait returned %d\n",rcode); 1501 debug_printf("checkjobs returned %d\n",rcode);
1493 } 1502 }
1494 last_return_code=rcode; 1503 last_return_code=rcode;
1495 if ( rmode == RES_IF || rmode == RES_ELIF ) 1504 if ( rmode == RES_IF || rmode == RES_ELIF )
@@ -1517,6 +1526,9 @@ static int free_pipe(struct pipe *pi, int indent)
1517 struct redir_struct *r, *rnext; 1526 struct redir_struct *r, *rnext;
1518 int a, i, ret_code=0; 1527 int a, i, ret_code=0;
1519 char *ind = indenter(indent); 1528 char *ind = indenter(indent);
1529
1530 if (pi->stopped_progs > 0)
1531 return ret_code;
1520 final_printf("%s run pipe: (pid %d)\n",ind,getpid()); 1532 final_printf("%s run pipe: (pid %d)\n",ind,getpid());
1521 for (i=0; i<pi->num_progs; i++) { 1533 for (i=0; i<pi->num_progs; i++) {
1522 child = &pi->progs[i]; 1534 child = &pi->progs[i];
@@ -2516,6 +2528,27 @@ static int parse_file_outer(FILE *f)
2516 return rcode; 2528 return rcode;
2517} 2529}
2518 2530
2531static void sigchld_handler(int sig)
2532{
2533 checkjobs(NULL);
2534 signal(SIGCHLD, sigchld_handler);
2535}
2536
2537static void setup_job_control()
2538{
2539 /* If we get started under a job aware app (like bash
2540 * for example), make sure we are now in charge so we
2541 * don't fight over who gets the foreground */
2542 /* don't pay any attention to this signal; it just confuses
2543 things and isn't really meant for shells anyway */
2544 setpgrp();
2545 controlling_tty(0);
2546 signal(SIGTTOU, SIG_IGN);
2547 setpgid(0, getpid());
2548 tcsetpgrp(ctty, getpid());
2549 signal(SIGCHLD, sigchld_handler);
2550}
2551
2519 2552
2520int shell_main(int argc, char **argv) 2553int shell_main(int argc, char **argv)
2521{ 2554{
@@ -2536,11 +2569,11 @@ int shell_main(int argc, char **argv)
2536 interactive = 0; 2569 interactive = 0;
2537 close_me_head = NULL; 2570 close_me_head = NULL;
2538 last_bg_pid = 0; 2571 last_bg_pid = 0;
2572 job_list = NULL;
2539 last_jobid = 0; 2573 last_jobid = 0;
2540 2574
2541 /* Initialize some more globals to non-zero values */ 2575 /* Initialize some more globals to non-zero values */
2542 set_cwd(); 2576 set_cwd();
2543 job_list = NULL;
2544#ifdef BB_FEATURE_COMMAND_EDITING 2577#ifdef BB_FEATURE_COMMAND_EDITING
2545 cmdedit_set_initial_prompt(); 2578 cmdedit_set_initial_prompt();
2546#else 2579#else
@@ -2558,16 +2591,6 @@ int shell_main(int argc, char **argv)
2558 last_return_code=EXIT_SUCCESS; 2591 last_return_code=EXIT_SUCCESS;
2559 2592
2560 2593
2561 /* If we get started under a job aware app (like bash
2562 * for example), make sure we are now in charge so we
2563 * don't fight over who gets the foreground */
2564 /* don't pay any attention to this signal; it just confuses
2565 things and isn't really meant for shells anyway */
2566 controlling_tty(0);
2567 signal(SIGTTOU, SIG_IGN);
2568 setpgid(0, getpid());
2569 tcsetpgrp(ctty, getpid());
2570
2571 if (argv[0] && argv[0][0] == '-') { 2594 if (argv[0] && argv[0][0] == '-') {
2572 debug_printf("\nsourcing /etc/profile\n"); 2595 debug_printf("\nsourcing /etc/profile\n");
2573 input = xfopen("/etc/profile", "r"); 2596 input = xfopen("/etc/profile", "r");
@@ -2620,7 +2643,9 @@ int shell_main(int argc, char **argv)
2620 if (interactive) { 2643 if (interactive) {
2621 /* Looks like they want an interactive shell */ 2644 /* Looks like they want an interactive shell */
2622 fprintf(stdout, "\nhush -- the humble shell v0.01 (testing)\n\n"); 2645 fprintf(stdout, "\nhush -- the humble shell v0.01 (testing)\n\n");
2646 setup_job_control();
2623 } 2647 }
2648
2624 if (argv[optind]==NULL) { 2649 if (argv[optind]==NULL) {
2625 opt=parse_file_outer(stdin); 2650 opt=parse_file_outer(stdin);
2626 goto final_return; 2651 goto final_return;