diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-06-22 06:49:26 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-06-22 06:49:26 +0000 |
commit | 52a97ca00cf5d290c9beb65ba7c217a5ed69ee42 (patch) | |
tree | d87fec02a954a19653c67025d22ba8ecb8df4123 /shell/hush.c | |
parent | c798b0776264950350b53a0aa58101bb1dfcf6dc (diff) | |
download | busybox-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
Diffstat (limited to '')
-rw-r--r-- | shell/hush.c | 79 |
1 files changed, 52 insertions, 27 deletions
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; | |||
257 | struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 }; | 257 | struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 }; |
258 | struct variables *top_vars = &shell_ver; | 258 | struct 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); | |||
394 | static char *get_local_var(const char *var); | 395 | static char *get_local_var(const char *var); |
395 | static void unset_local_var(const char *name); | 396 | static void unset_local_var(const char *name); |
396 | static int set_local_var(const char *s, int flg_export); | 397 | static int set_local_var(const char *s, int flg_export); |
397 | 398 | static 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 | ||
2531 | static void sigchld_handler(int sig) | ||
2532 | { | ||
2533 | checkjobs(NULL); | ||
2534 | signal(SIGCHLD, sigchld_handler); | ||
2535 | } | ||
2536 | |||
2537 | static 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 | ||
2520 | int shell_main(int argc, char **argv) | 2553 | int 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; |