aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-05-21 16:18:22 +0000
committerEric Andersen <andersen@codepoet.org>2001-05-21 16:18:22 +0000
commitada18ff0f53f1b61073a843959e97c0f4206576e (patch)
treed7b851cf4f91bd6b510ee83d0f8fe18efd79c906
parent8ae319a32228dff15f4b9696deb5883fb242f024 (diff)
downloadbusybox-w32-ada18ff0f53f1b61073a843959e97c0f4206576e.tar.gz
busybox-w32-ada18ff0f53f1b61073a843959e97c0f4206576e.tar.bz2
busybox-w32-ada18ff0f53f1b61073a843959e97c0f4206576e.zip
The latest patch from Larry
-rw-r--r--hush.c92
-rw-r--r--shell/hush.c92
2 files changed, 122 insertions, 62 deletions
diff --git a/hush.c b/hush.c
index a1e65b24e..fc45bb270 100644
--- a/hush.c
+++ b/hush.c
@@ -365,6 +365,7 @@ static int setup_redirects(struct child_prog *prog, int squirrel[]);
365static int pipe_wait(struct pipe *pi); 365static int pipe_wait(struct pipe *pi);
366static int run_list_real(struct pipe *pi); 366static int run_list_real(struct pipe *pi);
367static void pseudo_exec(struct child_prog *child) __attribute__ ((noreturn)); 367static void pseudo_exec(struct child_prog *child) __attribute__ ((noreturn));
368int controlling_tty(int check_pgrp);
368static int run_pipe_real(struct pipe *pi); 369static int run_pipe_real(struct pipe *pi);
369/* extended glob support: */ 370/* extended glob support: */
370static int globhack(const char *src, int flags, glob_t *pglob); 371static int globhack(const char *src, int flags, glob_t *pglob);
@@ -576,7 +577,7 @@ static int builtin_fg_bg(struct child_prog *child)
576 signal(SIGTTOU, SIG_IGN); 577 signal(SIGTTOU, SIG_IGN);
577 /* suppress messages when run from /linuxrc mag@sysgo.de */ 578 /* suppress messages when run from /linuxrc mag@sysgo.de */
578 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY) 579 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY)
579 perror_msg("tcsetpgrp"); 580 perror_msg("tcsetpgrp-1");
580 signal(SIGTTOU, SIG_DFL); 581 signal(SIGTTOU, SIG_DFL);
581 job_list->fg = pi; 582 job_list->fg = pi;
582 } 583 }
@@ -1059,13 +1060,14 @@ static int pipe_wait(struct pipe *pi)
1059 return rcode; 1060 return rcode;
1060} 1061}
1061 1062
1062/* very simple version for testing */ 1063/* never returns */
1063static void pseudo_exec(struct child_prog *child) 1064static void pseudo_exec(struct child_prog *child)
1064{ 1065{
1065 int i, rcode; 1066 int i, rcode;
1066 struct built_in_command *x; 1067 struct built_in_command *x;
1067 if (child->argv) { 1068 if (child->argv) {
1068 for (i=0; is_assignment(child->argv[i]); i++) { 1069 for (i=0; is_assignment(child->argv[i]); i++) {
1070 debug_printf("pid %d environment modification: %s\n",getpid(),child->argv[i]);
1069 putenv(strdup(child->argv[i])); 1071 putenv(strdup(child->argv[i]));
1070 } 1072 }
1071 child->argv+=i; /* XXX this hack isn't so horrible, since we are about 1073 child->argv+=i; /* XXX this hack isn't so horrible, since we are about
@@ -1125,7 +1127,7 @@ static void pseudo_exec(struct child_prog *child)
1125#endif 1127#endif
1126 debug_printf("exec of %s\n",child->argv[0]); 1128 debug_printf("exec of %s\n",child->argv[0]);
1127 execvp(child->argv[0],child->argv); 1129 execvp(child->argv[0],child->argv);
1128 perror("execvp"); 1130 perror_msg("couldn't exec: %s",child->argv[0]);
1129 exit(1); 1131 exit(1);
1130 } else if (child->group) { 1132 } else if (child->group) {
1131 debug_printf("runtime nesting to group\n"); 1133 debug_printf("runtime nesting to group\n");
@@ -1224,7 +1226,7 @@ static void free_pipe(struct pipe *pi)
1224 have, figure out why and see if a job has completed */ 1226 have, figure out why and see if a job has completed */
1225static void checkjobs() 1227static void checkjobs()
1226{ 1228{
1227 int status; 1229 int status, ctty;
1228 int prognum = 0; 1230 int prognum = 0;
1229 struct pipe *pi; 1231 struct pipe *pi;
1230 pid_t childpid; 1232 pid_t childpid;
@@ -1264,8 +1266,31 @@ static void checkjobs()
1264 perror_msg("waitpid"); 1266 perror_msg("waitpid");
1265 1267
1266 /* move the shell to the foreground */ 1268 /* move the shell to the foreground */
1267 if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY) 1269 if (interactive && (ctty=controlling_tty(0))!=-1) {
1268 perror_msg("tcsetpgrp"); 1270 if (tcsetpgrp(ctty, getpgrp()))
1271 perror_msg("tcsetpgrp-2");
1272 }
1273}
1274
1275/* Figure out our controlling tty, checking in order stderr,
1276 * stdin, and stdout. If check_pgrp is set, also check that
1277 * we belong to the foreground process group associated with
1278 * that tty. The value of ctty is needed in order to call
1279 * tcsetpgrp(ctty, ...); */
1280int controlling_tty(int check_pgrp)
1281{
1282 pid_t curpgrp;
1283 int ctty;
1284
1285 if ((curpgrp = tcgetpgrp(ctty = 2)) < 0
1286 && (curpgrp = tcgetpgrp(ctty = 0)) < 0
1287 && (curpgrp = tcgetpgrp(ctty = 1)) < 0)
1288 return errno = ENOTTY, -1;
1289
1290 if (check_pgrp && curpgrp != getpgrp())
1291 return errno = EPERM, -1;
1292
1293 return ctty;
1269} 1294}
1270 1295
1271/* run_pipe_real() starts all the jobs, but doesn't wait for anything 1296/* run_pipe_real() starts all the jobs, but doesn't wait for anything
@@ -1295,17 +1320,11 @@ static int run_pipe_real(struct pipe *pi)
1295 1320
1296 ctty = -1; 1321 ctty = -1;
1297 nextin = 0; 1322 nextin = 0;
1298 pi->pgrp = 0; 1323 pi->pgrp = -1;
1299 1324
1300 /* Check if we are supposed to run in the foreground */ 1325 /* Check if we are supposed to run in the foreground */
1301 if (interactive && pi->followup!=PIPE_BG) { 1326 if (interactive && pi->followup!=PIPE_BG) {
1302 if ((pi->pgrp = tcgetpgrp(ctty = 2)) < 0 1327 if ((ctty = controlling_tty(pi->pgrp<0)) < 0) return -1;
1303 && (pi->pgrp = tcgetpgrp(ctty = 0)) < 0
1304 && (pi->pgrp = tcgetpgrp(ctty = 1)) < 0)
1305 return errno = ENOTTY, -1;
1306
1307 if (pi->pgrp < 0 && pi->pgrp != getpgrp())
1308 return errno = EPERM, -1;
1309 } 1328 }
1310 1329
1311 /* Check if this is a simple builtin (not part of a pipe). 1330 /* Check if this is a simple builtin (not part of a pipe).
@@ -1395,11 +1414,11 @@ static int run_pipe_real(struct pipe *pi)
1395 * and the pipe fd is available for dup'ing. */ 1414 * and the pipe fd is available for dup'ing. */
1396 setup_redirects(child,NULL); 1415 setup_redirects(child,NULL);
1397 1416
1398 if (pi->followup!=PIPE_BG) { 1417 if (interactive && pi->followup!=PIPE_BG) {
1399 /* If we (the child) win the race, put ourselves in the process 1418 /* If we (the child) win the race, put ourselves in the process
1400 * group whose leader is the first process in this pipe. */ 1419 * group whose leader is the first process in this pipe. */
1401 if (pi->pgrp < 0) { 1420 if (pi->pgrp < 0) {
1402 pi->pgrp = child->pid; 1421 pi->pgrp = getpid();
1403 } 1422 }
1404 if (setpgid(0, pi->pgrp) == 0) { 1423 if (setpgid(0, pi->pgrp) == 0) {
1405 signal(SIGTTOU, SIG_IGN); 1424 signal(SIGTTOU, SIG_IGN);
@@ -1461,13 +1480,15 @@ static int run_list_real(struct pipe *pi)
1461 if (interactive) { 1480 if (interactive) {
1462 /* move the new process group into the foreground */ 1481 /* move the new process group into the foreground */
1463 /* suppress messages when run from /linuxrc mag@sysgo.de */ 1482 /* suppress messages when run from /linuxrc mag@sysgo.de */
1483 /* XXX probably this "0" should come from controlling_tty() */
1464 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY) 1484 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY)
1465 perror_msg("tcsetpgrp"); 1485 perror_msg("tcsetpgrp-3");
1466 rcode = pipe_wait(pi); 1486 rcode = pipe_wait(pi);
1467 if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY) 1487 if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY)
1468 perror_msg("tcsetpgrp"); 1488 perror_msg("tcsetpgrp-4");
1469 } else { 1489 } else {
1470 rcode = pipe_wait(pi); 1490 rcode = pipe_wait(pi);
1491 debug_printf("pipe_wait returned %d\n",rcode);
1471 } 1492 }
1472 } 1493 }
1473 last_return_code=rcode; 1494 last_return_code=rcode;
@@ -2484,6 +2505,25 @@ static int parse_file_outer(FILE *f)
2484 return rcode; 2505 return rcode;
2485} 2506}
2486 2507
2508
2509/* I think Erik wrote this. It looks imperfect at best */
2510void grab_tty_control(void)
2511{
2512 pid_t initialpgrp;
2513 do {
2514 initialpgrp = tcgetpgrp(fileno(stderr));
2515 if (initialpgrp < 0) {
2516 error_msg("sh: can't access tty; job control disabled\n");
2517 }
2518 if (initialpgrp == -1)
2519 initialpgrp = getpgrp();
2520 else if (initialpgrp != getpgrp()) {
2521 killpg(initialpgrp, SIGTTIN);
2522 continue;
2523 }
2524 } while (0);
2525}
2526
2487int shell_main(int argc, char **argv) 2527int shell_main(int argc, char **argv)
2488{ 2528{
2489 int opt; 2529 int opt;
@@ -2507,19 +2547,6 @@ int shell_main(int argc, char **argv)
2507 /* If we get started under a job aware app (like bash 2547 /* If we get started under a job aware app (like bash
2508 * for example), make sure we are now in charge so we 2548 * for example), make sure we are now in charge so we
2509 * don't fight over who gets the foreground */ 2549 * don't fight over who gets the foreground */
2510 do {
2511 pid_t initialpgrp;
2512 initialpgrp = tcgetpgrp(fileno(stderr));
2513 if (initialpgrp < 0) {
2514 error_msg_and_die("sh: can't access tty; job control disabled\n");
2515 }
2516 if (initialpgrp == -1)
2517 initialpgrp = getpgrp();
2518 else if (initialpgrp != getpgrp()) {
2519 killpg(initialpgrp, SIGTTIN);
2520 continue;
2521 }
2522 } while (0);
2523 /* don't pay any attention to this signal; it just confuses 2550 /* don't pay any attention to this signal; it just confuses
2524 things and isn't really meant for shells anyway */ 2551 things and isn't really meant for shells anyway */
2525 signal(SIGTTOU, SIG_IGN); 2552 signal(SIGTTOU, SIG_IGN);
@@ -2588,6 +2615,9 @@ int shell_main(int argc, char **argv)
2588 if (interactive) { 2615 if (interactive) {
2589 /* Looks like they want an interactive shell */ 2616 /* Looks like they want an interactive shell */
2590 fprintf(stdout, "\nhush -- the humble shell v0.01 (testing)\n\n"); 2617 fprintf(stdout, "\nhush -- the humble shell v0.01 (testing)\n\n");
2618 grab_tty_control();
2619 }
2620 if (argv[optind]==NULL) {
2591 opt=parse_file_outer(stdin); 2621 opt=parse_file_outer(stdin);
2592 goto final_return; 2622 goto final_return;
2593 } 2623 }
diff --git a/shell/hush.c b/shell/hush.c
index a1e65b24e..fc45bb270 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -365,6 +365,7 @@ static int setup_redirects(struct child_prog *prog, int squirrel[]);
365static int pipe_wait(struct pipe *pi); 365static int pipe_wait(struct pipe *pi);
366static int run_list_real(struct pipe *pi); 366static int run_list_real(struct pipe *pi);
367static void pseudo_exec(struct child_prog *child) __attribute__ ((noreturn)); 367static void pseudo_exec(struct child_prog *child) __attribute__ ((noreturn));
368int controlling_tty(int check_pgrp);
368static int run_pipe_real(struct pipe *pi); 369static int run_pipe_real(struct pipe *pi);
369/* extended glob support: */ 370/* extended glob support: */
370static int globhack(const char *src, int flags, glob_t *pglob); 371static int globhack(const char *src, int flags, glob_t *pglob);
@@ -576,7 +577,7 @@ static int builtin_fg_bg(struct child_prog *child)
576 signal(SIGTTOU, SIG_IGN); 577 signal(SIGTTOU, SIG_IGN);
577 /* suppress messages when run from /linuxrc mag@sysgo.de */ 578 /* suppress messages when run from /linuxrc mag@sysgo.de */
578 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY) 579 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY)
579 perror_msg("tcsetpgrp"); 580 perror_msg("tcsetpgrp-1");
580 signal(SIGTTOU, SIG_DFL); 581 signal(SIGTTOU, SIG_DFL);
581 job_list->fg = pi; 582 job_list->fg = pi;
582 } 583 }
@@ -1059,13 +1060,14 @@ static int pipe_wait(struct pipe *pi)
1059 return rcode; 1060 return rcode;
1060} 1061}
1061 1062
1062/* very simple version for testing */ 1063/* never returns */
1063static void pseudo_exec(struct child_prog *child) 1064static void pseudo_exec(struct child_prog *child)
1064{ 1065{
1065 int i, rcode; 1066 int i, rcode;
1066 struct built_in_command *x; 1067 struct built_in_command *x;
1067 if (child->argv) { 1068 if (child->argv) {
1068 for (i=0; is_assignment(child->argv[i]); i++) { 1069 for (i=0; is_assignment(child->argv[i]); i++) {
1070 debug_printf("pid %d environment modification: %s\n",getpid(),child->argv[i]);
1069 putenv(strdup(child->argv[i])); 1071 putenv(strdup(child->argv[i]));
1070 } 1072 }
1071 child->argv+=i; /* XXX this hack isn't so horrible, since we are about 1073 child->argv+=i; /* XXX this hack isn't so horrible, since we are about
@@ -1125,7 +1127,7 @@ static void pseudo_exec(struct child_prog *child)
1125#endif 1127#endif
1126 debug_printf("exec of %s\n",child->argv[0]); 1128 debug_printf("exec of %s\n",child->argv[0]);
1127 execvp(child->argv[0],child->argv); 1129 execvp(child->argv[0],child->argv);
1128 perror("execvp"); 1130 perror_msg("couldn't exec: %s",child->argv[0]);
1129 exit(1); 1131 exit(1);
1130 } else if (child->group) { 1132 } else if (child->group) {
1131 debug_printf("runtime nesting to group\n"); 1133 debug_printf("runtime nesting to group\n");
@@ -1224,7 +1226,7 @@ static void free_pipe(struct pipe *pi)
1224 have, figure out why and see if a job has completed */ 1226 have, figure out why and see if a job has completed */
1225static void checkjobs() 1227static void checkjobs()
1226{ 1228{
1227 int status; 1229 int status, ctty;
1228 int prognum = 0; 1230 int prognum = 0;
1229 struct pipe *pi; 1231 struct pipe *pi;
1230 pid_t childpid; 1232 pid_t childpid;
@@ -1264,8 +1266,31 @@ static void checkjobs()
1264 perror_msg("waitpid"); 1266 perror_msg("waitpid");
1265 1267
1266 /* move the shell to the foreground */ 1268 /* move the shell to the foreground */
1267 if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY) 1269 if (interactive && (ctty=controlling_tty(0))!=-1) {
1268 perror_msg("tcsetpgrp"); 1270 if (tcsetpgrp(ctty, getpgrp()))
1271 perror_msg("tcsetpgrp-2");
1272 }
1273}
1274
1275/* Figure out our controlling tty, checking in order stderr,
1276 * stdin, and stdout. If check_pgrp is set, also check that
1277 * we belong to the foreground process group associated with
1278 * that tty. The value of ctty is needed in order to call
1279 * tcsetpgrp(ctty, ...); */
1280int controlling_tty(int check_pgrp)
1281{
1282 pid_t curpgrp;
1283 int ctty;
1284
1285 if ((curpgrp = tcgetpgrp(ctty = 2)) < 0
1286 && (curpgrp = tcgetpgrp(ctty = 0)) < 0
1287 && (curpgrp = tcgetpgrp(ctty = 1)) < 0)
1288 return errno = ENOTTY, -1;
1289
1290 if (check_pgrp && curpgrp != getpgrp())
1291 return errno = EPERM, -1;
1292
1293 return ctty;
1269} 1294}
1270 1295
1271/* run_pipe_real() starts all the jobs, but doesn't wait for anything 1296/* run_pipe_real() starts all the jobs, but doesn't wait for anything
@@ -1295,17 +1320,11 @@ static int run_pipe_real(struct pipe *pi)
1295 1320
1296 ctty = -1; 1321 ctty = -1;
1297 nextin = 0; 1322 nextin = 0;
1298 pi->pgrp = 0; 1323 pi->pgrp = -1;
1299 1324
1300 /* Check if we are supposed to run in the foreground */ 1325 /* Check if we are supposed to run in the foreground */
1301 if (interactive && pi->followup!=PIPE_BG) { 1326 if (interactive && pi->followup!=PIPE_BG) {
1302 if ((pi->pgrp = tcgetpgrp(ctty = 2)) < 0 1327 if ((ctty = controlling_tty(pi->pgrp<0)) < 0) return -1;
1303 && (pi->pgrp = tcgetpgrp(ctty = 0)) < 0
1304 && (pi->pgrp = tcgetpgrp(ctty = 1)) < 0)
1305 return errno = ENOTTY, -1;
1306
1307 if (pi->pgrp < 0 && pi->pgrp != getpgrp())
1308 return errno = EPERM, -1;
1309 } 1328 }
1310 1329
1311 /* Check if this is a simple builtin (not part of a pipe). 1330 /* Check if this is a simple builtin (not part of a pipe).
@@ -1395,11 +1414,11 @@ static int run_pipe_real(struct pipe *pi)
1395 * and the pipe fd is available for dup'ing. */ 1414 * and the pipe fd is available for dup'ing. */
1396 setup_redirects(child,NULL); 1415 setup_redirects(child,NULL);
1397 1416
1398 if (pi->followup!=PIPE_BG) { 1417 if (interactive && pi->followup!=PIPE_BG) {
1399 /* If we (the child) win the race, put ourselves in the process 1418 /* If we (the child) win the race, put ourselves in the process
1400 * group whose leader is the first process in this pipe. */ 1419 * group whose leader is the first process in this pipe. */
1401 if (pi->pgrp < 0) { 1420 if (pi->pgrp < 0) {
1402 pi->pgrp = child->pid; 1421 pi->pgrp = getpid();
1403 } 1422 }
1404 if (setpgid(0, pi->pgrp) == 0) { 1423 if (setpgid(0, pi->pgrp) == 0) {
1405 signal(SIGTTOU, SIG_IGN); 1424 signal(SIGTTOU, SIG_IGN);
@@ -1461,13 +1480,15 @@ static int run_list_real(struct pipe *pi)
1461 if (interactive) { 1480 if (interactive) {
1462 /* move the new process group into the foreground */ 1481 /* move the new process group into the foreground */
1463 /* suppress messages when run from /linuxrc mag@sysgo.de */ 1482 /* suppress messages when run from /linuxrc mag@sysgo.de */
1483 /* XXX probably this "0" should come from controlling_tty() */
1464 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY) 1484 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY)
1465 perror_msg("tcsetpgrp"); 1485 perror_msg("tcsetpgrp-3");
1466 rcode = pipe_wait(pi); 1486 rcode = pipe_wait(pi);
1467 if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY) 1487 if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY)
1468 perror_msg("tcsetpgrp"); 1488 perror_msg("tcsetpgrp-4");
1469 } else { 1489 } else {
1470 rcode = pipe_wait(pi); 1490 rcode = pipe_wait(pi);
1491 debug_printf("pipe_wait returned %d\n",rcode);
1471 } 1492 }
1472 } 1493 }
1473 last_return_code=rcode; 1494 last_return_code=rcode;
@@ -2484,6 +2505,25 @@ static int parse_file_outer(FILE *f)
2484 return rcode; 2505 return rcode;
2485} 2506}
2486 2507
2508
2509/* I think Erik wrote this. It looks imperfect at best */
2510void grab_tty_control(void)
2511{
2512 pid_t initialpgrp;
2513 do {
2514 initialpgrp = tcgetpgrp(fileno(stderr));
2515 if (initialpgrp < 0) {
2516 error_msg("sh: can't access tty; job control disabled\n");
2517 }
2518 if (initialpgrp == -1)
2519 initialpgrp = getpgrp();
2520 else if (initialpgrp != getpgrp()) {
2521 killpg(initialpgrp, SIGTTIN);
2522 continue;
2523 }
2524 } while (0);
2525}
2526
2487int shell_main(int argc, char **argv) 2527int shell_main(int argc, char **argv)
2488{ 2528{
2489 int opt; 2529 int opt;
@@ -2507,19 +2547,6 @@ int shell_main(int argc, char **argv)
2507 /* If we get started under a job aware app (like bash 2547 /* If we get started under a job aware app (like bash
2508 * for example), make sure we are now in charge so we 2548 * for example), make sure we are now in charge so we
2509 * don't fight over who gets the foreground */ 2549 * don't fight over who gets the foreground */
2510 do {
2511 pid_t initialpgrp;
2512 initialpgrp = tcgetpgrp(fileno(stderr));
2513 if (initialpgrp < 0) {
2514 error_msg_and_die("sh: can't access tty; job control disabled\n");
2515 }
2516 if (initialpgrp == -1)
2517 initialpgrp = getpgrp();
2518 else if (initialpgrp != getpgrp()) {
2519 killpg(initialpgrp, SIGTTIN);
2520 continue;
2521 }
2522 } while (0);
2523 /* don't pay any attention to this signal; it just confuses 2550 /* don't pay any attention to this signal; it just confuses
2524 things and isn't really meant for shells anyway */ 2551 things and isn't really meant for shells anyway */
2525 signal(SIGTTOU, SIG_IGN); 2552 signal(SIGTTOU, SIG_IGN);
@@ -2588,6 +2615,9 @@ int shell_main(int argc, char **argv)
2588 if (interactive) { 2615 if (interactive) {
2589 /* Looks like they want an interactive shell */ 2616 /* Looks like they want an interactive shell */
2590 fprintf(stdout, "\nhush -- the humble shell v0.01 (testing)\n\n"); 2617 fprintf(stdout, "\nhush -- the humble shell v0.01 (testing)\n\n");
2618 grab_tty_control();
2619 }
2620 if (argv[optind]==NULL) {
2591 opt=parse_file_outer(stdin); 2621 opt=parse_file_outer(stdin);
2592 goto final_return; 2622 goto final_return;
2593 } 2623 }