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 /shell | |
| 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
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/lash.c | 61 |
1 files changed, 46 insertions, 15 deletions
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 */ |
