diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-06-25 17:11:54 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-06-25 17:11:54 +0000 |
commit | 2d848a476ac212046bcda453c8bc3da5fcaff5d3 (patch) | |
tree | 10d660a6497b2854c1846de302a2cef05d621d9c | |
parent | 2e6d3cfa82eb64fffe53ccb5669aa7146228cf8f (diff) | |
download | busybox-w32-2d848a476ac212046bcda453c8bc3da5fcaff5d3.tar.gz busybox-w32-2d848a476ac212046bcda453c8bc3da5fcaff5d3.tar.bz2 busybox-w32-2d848a476ac212046bcda453c8bc3da5fcaff5d3.zip |
This should finish off the job control issues with lash. Make certain
we have a controlling terminal...
-Erik
-rw-r--r-- | lash.c | 61 | ||||
-rw-r--r-- | shell/lash.c | 61 |
2 files changed, 92 insertions, 30 deletions
@@ -44,6 +44,7 @@ | |||
44 | #include <sys/wait.h> | 44 | #include <sys/wait.h> |
45 | #include <unistd.h> | 45 | #include <unistd.h> |
46 | #include <getopt.h> | 46 | #include <getopt.h> |
47 | #include <termios.h> | ||
47 | #include "busybox.h" | 48 | #include "busybox.h" |
48 | #include "cmdedit.h" | 49 | #include "cmdedit.h" |
49 | 50 | ||
@@ -181,7 +182,8 @@ static int argc; | |||
181 | static char **argv; | 182 | static char **argv; |
182 | static struct close_me *close_me_head; | 183 | static struct close_me *close_me_head; |
183 | static unsigned int last_jobid; | 184 | static unsigned int last_jobid; |
184 | 185 | static int shell_terminal; | |
186 | static pid_t shell_pgrp; | ||
185 | static char *PS1; | 187 | static char *PS1; |
186 | static char *PS2 = "> "; | 188 | static char *PS2 = "> "; |
187 | 189 | ||
@@ -299,10 +301,9 @@ static int builtin_fg_bg(struct child_prog *child) | |||
299 | } | 301 | } |
300 | 302 | ||
301 | if (*child->argv[0] == 'f') { | 303 | if (*child->argv[0] == 'f') { |
302 | /* Make this job the foreground job */ | 304 | /* Put the job into the foreground. */ |
303 | /* suppress messages when run from /linuxrc mag@sysgo.de */ | 305 | tcsetpgrp(shell_terminal, job->pgrp); |
304 | if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY) | 306 | |
305 | perror_msg("tcsetpgrp"); | ||
306 | child->family->job_list->fg = job; | 307 | child->family->job_list->fg = job; |
307 | } | 308 | } |
308 | 309 | ||
@@ -310,10 +311,11 @@ static int builtin_fg_bg(struct child_prog *child) | |||
310 | for (i = 0; i < job->num_progs; i++) | 311 | for (i = 0; i < job->num_progs; i++) |
311 | job->progs[i].is_stopped = 0; | 312 | job->progs[i].is_stopped = 0; |
312 | 313 | ||
313 | kill(-job->pgrp, SIGCONT); | ||
314 | |||
315 | job->stopped_progs = 0; | 314 | job->stopped_progs = 0; |
316 | 315 | ||
316 | if (kill(- job->pgrp, SIGCONT) < 0) | ||
317 | perror_msg("kill (SIGCONT)"); | ||
318 | |||
317 | return EXIT_SUCCESS; | 319 | return EXIT_SUCCESS; |
318 | } | 320 | } |
319 | 321 | ||
@@ -1081,7 +1083,7 @@ static void insert_job(struct job *newjob, int inbg) | |||
1081 | 1083 | ||
1082 | /* move the new process group into the foreground */ | 1084 | /* move the new process group into the foreground */ |
1083 | /* suppress messages when run from /linuxrc mag@sysgo.de */ | 1085 | /* suppress messages when run from /linuxrc mag@sysgo.de */ |
1084 | if (tcsetpgrp(0, newjob->pgrp) && errno != ENOTTY) | 1086 | if (tcsetpgrp(shell_terminal, newjob->pgrp) && errno != ENOTTY) |
1085 | perror_msg("tcsetpgrp"); | 1087 | perror_msg("tcsetpgrp"); |
1086 | } | 1088 | } |
1087 | } | 1089 | } |
@@ -1131,7 +1133,13 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2]) | |||
1131 | } | 1133 | } |
1132 | 1134 | ||
1133 | if (!(child->pid = fork())) { | 1135 | if (!(child->pid = fork())) { |
1136 | /* Set the handling for job control signals back to the default. */ | ||
1137 | signal(SIGINT, SIG_DFL); | ||
1138 | signal(SIGQUIT, SIG_DFL); | ||
1139 | signal(SIGTSTP, SIG_DFL); | ||
1140 | signal(SIGTTIN, SIG_DFL); | ||
1134 | signal(SIGTTOU, SIG_DFL); | 1141 | signal(SIGTTOU, SIG_DFL); |
1142 | signal(SIGCHLD, SIG_DFL); | ||
1135 | 1143 | ||
1136 | close_all(); | 1144 | close_all(); |
1137 | 1145 | ||
@@ -1192,14 +1200,10 @@ static int busy_loop(FILE * input) | |||
1192 | newjob.job_context = DEFAULT_CONTEXT; | 1200 | newjob.job_context = DEFAULT_CONTEXT; |
1193 | 1201 | ||
1194 | /* save current owner of TTY so we can restore it on exit */ | 1202 | /* save current owner of TTY so we can restore it on exit */ |
1195 | parent_pgrp = tcgetpgrp(0); | 1203 | parent_pgrp = tcgetpgrp(shell_terminal); |
1196 | 1204 | ||
1197 | command = (char *) xcalloc(BUFSIZ, sizeof(char)); | 1205 | command = (char *) xcalloc(BUFSIZ, sizeof(char)); |
1198 | 1206 | ||
1199 | /* don't pay any attention to this signal; it just confuses | ||
1200 | things and isn't really meant for shells anyway */ | ||
1201 | signal(SIGTTOU, SIG_IGN); | ||
1202 | |||
1203 | while (1) { | 1207 | while (1) { |
1204 | if (!job_list.fg) { | 1208 | if (!job_list.fg) { |
1205 | /* no job is in the foreground */ | 1209 | /* no job is in the foreground */ |
@@ -1266,7 +1270,7 @@ static int busy_loop(FILE * input) | |||
1266 | if (!job_list.fg) { | 1270 | if (!job_list.fg) { |
1267 | /* move the shell to the foreground */ | 1271 | /* move the shell to the foreground */ |
1268 | /* suppress messages when run from /linuxrc mag@sysgo.de */ | 1272 | /* suppress messages when run from /linuxrc mag@sysgo.de */ |
1269 | if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY) | 1273 | if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY) |
1270 | perror_msg("tcsetpgrp"); | 1274 | perror_msg("tcsetpgrp"); |
1271 | } | 1275 | } |
1272 | } | 1276 | } |
@@ -1274,7 +1278,7 @@ static int busy_loop(FILE * input) | |||
1274 | free(command); | 1278 | free(command); |
1275 | 1279 | ||
1276 | /* return controlling TTY back to parent process group before exiting */ | 1280 | /* return controlling TTY back to parent process group before exiting */ |
1277 | if (tcsetpgrp(0, parent_pgrp)) | 1281 | if (tcsetpgrp(shell_terminal, parent_pgrp)) |
1278 | perror_msg("tcsetpgrp"); | 1282 | perror_msg("tcsetpgrp"); |
1279 | 1283 | ||
1280 | /* return exit status if called with "-c" */ | 1284 | /* return exit status if called with "-c" */ |
@@ -1300,6 +1304,32 @@ void free_memory(void) | |||
1300 | } | 1304 | } |
1301 | #endif | 1305 | #endif |
1302 | 1306 | ||
1307 | /* Make sure we have a controlling tty. If we get started under a job | ||
1308 | * aware app (like bash for example), make sure we are now in charge so | ||
1309 | * we don't fight over who gets the foreground */ | ||
1310 | static void setup_job_control() | ||
1311 | { | ||
1312 | /* Loop until we are in the foreground. */ | ||
1313 | while (tcgetpgrp (shell_terminal) != (shell_pgrp = getpgrp ())) | ||
1314 | kill (- shell_pgrp, SIGTTIN); | ||
1315 | |||
1316 | /* Ignore interactive and job-control signals. */ | ||
1317 | signal(SIGINT, SIG_IGN); | ||
1318 | signal(SIGQUIT, SIG_IGN); | ||
1319 | signal(SIGTSTP, SIG_IGN); | ||
1320 | signal(SIGTTIN, SIG_IGN); | ||
1321 | signal(SIGTTOU, SIG_IGN); | ||
1322 | signal(SIGCHLD, SIG_IGN); | ||
1323 | |||
1324 | /* Put ourselves in our own process group. */ | ||
1325 | shell_pgrp = getpid (); | ||
1326 | if (setpgid (shell_pgrp, shell_pgrp) < 0) { | ||
1327 | perror_msg_and_die("Couldn't put the shell in its own process group"); | ||
1328 | } | ||
1329 | |||
1330 | /* Grab control of the terminal. */ | ||
1331 | tcsetpgrp(shell_terminal, shell_pgrp); | ||
1332 | } | ||
1303 | 1333 | ||
1304 | int shell_main(int argc_l, char **argv_l) | 1334 | int shell_main(int argc_l, char **argv_l) |
1305 | { | 1335 | { |
@@ -1359,6 +1389,7 @@ int shell_main(int argc_l, char **argv_l) | |||
1359 | isatty(fileno(stdin)) && isatty(fileno(stdout))) { | 1389 | isatty(fileno(stdin)) && isatty(fileno(stdout))) { |
1360 | interactive=TRUE; | 1390 | interactive=TRUE; |
1361 | } | 1391 | } |
1392 | setup_job_control(); | ||
1362 | if (interactive==TRUE) { | 1393 | if (interactive==TRUE) { |
1363 | //printf( "optind=%d argv[optind]='%s'\n", optind, argv[optind]); | 1394 | //printf( "optind=%d argv[optind]='%s'\n", optind, argv[optind]); |
1364 | /* Looks like they want an interactive shell */ | 1395 | /* Looks like they want an interactive shell */ |
diff --git a/shell/lash.c b/shell/lash.c index 689c720f6..68f673539 100644 --- a/shell/lash.c +++ b/shell/lash.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <sys/wait.h> | 44 | #include <sys/wait.h> |
45 | #include <unistd.h> | 45 | #include <unistd.h> |
46 | #include <getopt.h> | 46 | #include <getopt.h> |
47 | #include <termios.h> | ||
47 | #include "busybox.h" | 48 | #include "busybox.h" |
48 | #include "cmdedit.h" | 49 | #include "cmdedit.h" |
49 | 50 | ||
@@ -181,7 +182,8 @@ static int argc; | |||
181 | static char **argv; | 182 | static char **argv; |
182 | static struct close_me *close_me_head; | 183 | static struct close_me *close_me_head; |
183 | static unsigned int last_jobid; | 184 | static unsigned int last_jobid; |
184 | 185 | static int shell_terminal; | |
186 | static pid_t shell_pgrp; | ||
185 | static char *PS1; | 187 | static char *PS1; |
186 | static char *PS2 = "> "; | 188 | static char *PS2 = "> "; |
187 | 189 | ||
@@ -299,10 +301,9 @@ static int builtin_fg_bg(struct child_prog *child) | |||
299 | } | 301 | } |
300 | 302 | ||
301 | if (*child->argv[0] == 'f') { | 303 | if (*child->argv[0] == 'f') { |
302 | /* Make this job the foreground job */ | 304 | /* Put the job into the foreground. */ |
303 | /* suppress messages when run from /linuxrc mag@sysgo.de */ | 305 | tcsetpgrp(shell_terminal, job->pgrp); |
304 | if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY) | 306 | |
305 | perror_msg("tcsetpgrp"); | ||
306 | child->family->job_list->fg = job; | 307 | child->family->job_list->fg = job; |
307 | } | 308 | } |
308 | 309 | ||
@@ -310,10 +311,11 @@ static int builtin_fg_bg(struct child_prog *child) | |||
310 | for (i = 0; i < job->num_progs; i++) | 311 | for (i = 0; i < job->num_progs; i++) |
311 | job->progs[i].is_stopped = 0; | 312 | job->progs[i].is_stopped = 0; |
312 | 313 | ||
313 | kill(-job->pgrp, SIGCONT); | ||
314 | |||
315 | job->stopped_progs = 0; | 314 | job->stopped_progs = 0; |
316 | 315 | ||
316 | if (kill(- job->pgrp, SIGCONT) < 0) | ||
317 | perror_msg("kill (SIGCONT)"); | ||
318 | |||
317 | return EXIT_SUCCESS; | 319 | return EXIT_SUCCESS; |
318 | } | 320 | } |
319 | 321 | ||
@@ -1081,7 +1083,7 @@ static void insert_job(struct job *newjob, int inbg) | |||
1081 | 1083 | ||
1082 | /* move the new process group into the foreground */ | 1084 | /* move the new process group into the foreground */ |
1083 | /* suppress messages when run from /linuxrc mag@sysgo.de */ | 1085 | /* suppress messages when run from /linuxrc mag@sysgo.de */ |
1084 | if (tcsetpgrp(0, newjob->pgrp) && errno != ENOTTY) | 1086 | if (tcsetpgrp(shell_terminal, newjob->pgrp) && errno != ENOTTY) |
1085 | perror_msg("tcsetpgrp"); | 1087 | perror_msg("tcsetpgrp"); |
1086 | } | 1088 | } |
1087 | } | 1089 | } |
@@ -1131,7 +1133,13 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2]) | |||
1131 | } | 1133 | } |
1132 | 1134 | ||
1133 | if (!(child->pid = fork())) { | 1135 | if (!(child->pid = fork())) { |
1136 | /* Set the handling for job control signals back to the default. */ | ||
1137 | signal(SIGINT, SIG_DFL); | ||
1138 | signal(SIGQUIT, SIG_DFL); | ||
1139 | signal(SIGTSTP, SIG_DFL); | ||
1140 | signal(SIGTTIN, SIG_DFL); | ||
1134 | signal(SIGTTOU, SIG_DFL); | 1141 | signal(SIGTTOU, SIG_DFL); |
1142 | signal(SIGCHLD, SIG_DFL); | ||
1135 | 1143 | ||
1136 | close_all(); | 1144 | close_all(); |
1137 | 1145 | ||
@@ -1192,14 +1200,10 @@ static int busy_loop(FILE * input) | |||
1192 | newjob.job_context = DEFAULT_CONTEXT; | 1200 | newjob.job_context = DEFAULT_CONTEXT; |
1193 | 1201 | ||
1194 | /* save current owner of TTY so we can restore it on exit */ | 1202 | /* save current owner of TTY so we can restore it on exit */ |
1195 | parent_pgrp = tcgetpgrp(0); | 1203 | parent_pgrp = tcgetpgrp(shell_terminal); |
1196 | 1204 | ||
1197 | command = (char *) xcalloc(BUFSIZ, sizeof(char)); | 1205 | command = (char *) xcalloc(BUFSIZ, sizeof(char)); |
1198 | 1206 | ||
1199 | /* don't pay any attention to this signal; it just confuses | ||
1200 | things and isn't really meant for shells anyway */ | ||
1201 | signal(SIGTTOU, SIG_IGN); | ||
1202 | |||
1203 | while (1) { | 1207 | while (1) { |
1204 | if (!job_list.fg) { | 1208 | if (!job_list.fg) { |
1205 | /* no job is in the foreground */ | 1209 | /* no job is in the foreground */ |
@@ -1266,7 +1270,7 @@ static int busy_loop(FILE * input) | |||
1266 | if (!job_list.fg) { | 1270 | if (!job_list.fg) { |
1267 | /* move the shell to the foreground */ | 1271 | /* move the shell to the foreground */ |
1268 | /* suppress messages when run from /linuxrc mag@sysgo.de */ | 1272 | /* suppress messages when run from /linuxrc mag@sysgo.de */ |
1269 | if (tcsetpgrp(0, getpgrp()) && errno != ENOTTY) | 1273 | if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY) |
1270 | perror_msg("tcsetpgrp"); | 1274 | perror_msg("tcsetpgrp"); |
1271 | } | 1275 | } |
1272 | } | 1276 | } |
@@ -1274,7 +1278,7 @@ static int busy_loop(FILE * input) | |||
1274 | free(command); | 1278 | free(command); |
1275 | 1279 | ||
1276 | /* return controlling TTY back to parent process group before exiting */ | 1280 | /* return controlling TTY back to parent process group before exiting */ |
1277 | if (tcsetpgrp(0, parent_pgrp)) | 1281 | if (tcsetpgrp(shell_terminal, parent_pgrp)) |
1278 | perror_msg("tcsetpgrp"); | 1282 | perror_msg("tcsetpgrp"); |
1279 | 1283 | ||
1280 | /* return exit status if called with "-c" */ | 1284 | /* return exit status if called with "-c" */ |
@@ -1300,6 +1304,32 @@ void free_memory(void) | |||
1300 | } | 1304 | } |
1301 | #endif | 1305 | #endif |
1302 | 1306 | ||
1307 | /* Make sure we have a controlling tty. If we get started under a job | ||
1308 | * aware app (like bash for example), make sure we are now in charge so | ||
1309 | * we don't fight over who gets the foreground */ | ||
1310 | static void setup_job_control() | ||
1311 | { | ||
1312 | /* Loop until we are in the foreground. */ | ||
1313 | while (tcgetpgrp (shell_terminal) != (shell_pgrp = getpgrp ())) | ||
1314 | kill (- shell_pgrp, SIGTTIN); | ||
1315 | |||
1316 | /* Ignore interactive and job-control signals. */ | ||
1317 | signal(SIGINT, SIG_IGN); | ||
1318 | signal(SIGQUIT, SIG_IGN); | ||
1319 | signal(SIGTSTP, SIG_IGN); | ||
1320 | signal(SIGTTIN, SIG_IGN); | ||
1321 | signal(SIGTTOU, SIG_IGN); | ||
1322 | signal(SIGCHLD, SIG_IGN); | ||
1323 | |||
1324 | /* Put ourselves in our own process group. */ | ||
1325 | shell_pgrp = getpid (); | ||
1326 | if (setpgid (shell_pgrp, shell_pgrp) < 0) { | ||
1327 | perror_msg_and_die("Couldn't put the shell in its own process group"); | ||
1328 | } | ||
1329 | |||
1330 | /* Grab control of the terminal. */ | ||
1331 | tcsetpgrp(shell_terminal, shell_pgrp); | ||
1332 | } | ||
1303 | 1333 | ||
1304 | int shell_main(int argc_l, char **argv_l) | 1334 | int shell_main(int argc_l, char **argv_l) |
1305 | { | 1335 | { |
@@ -1359,6 +1389,7 @@ int shell_main(int argc_l, char **argv_l) | |||
1359 | isatty(fileno(stdin)) && isatty(fileno(stdout))) { | 1389 | isatty(fileno(stdin)) && isatty(fileno(stdout))) { |
1360 | interactive=TRUE; | 1390 | interactive=TRUE; |
1361 | } | 1391 | } |
1392 | setup_job_control(); | ||
1362 | if (interactive==TRUE) { | 1393 | if (interactive==TRUE) { |
1363 | //printf( "optind=%d argv[optind]='%s'\n", optind, argv[optind]); | 1394 | //printf( "optind=%d argv[optind]='%s'\n", optind, argv[optind]); |
1364 | /* Looks like they want an interactive shell */ | 1395 | /* Looks like they want an interactive shell */ |