aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-05-02 20:12:03 +0000
committerEric Andersen <andersen@codepoet.org>2001-05-02 20:12:03 +0000
commit0fcd447d59fffa2fafe090f0cd76bd115de02add (patch)
tree823273f25fefa1275601b36d290fe749d1914020
parent20a3069ec0d1c242404e089cecfcc5bb7a88df0f (diff)
downloadbusybox-w32-0fcd447d59fffa2fafe090f0cd76bd115de02add.tar.gz
busybox-w32-0fcd447d59fffa2fafe090f0cd76bd115de02add.tar.bz2
busybox-w32-0fcd447d59fffa2fafe090f0cd76bd115de02add.zip
Some more job control updates. It will now sucessfully background
stuff. Good luck getting things back into the foreground though... -Erik
-rw-r--r--hush.c120
-rw-r--r--shell/hush.c120
2 files changed, 148 insertions, 92 deletions
diff --git a/hush.c b/hush.c
index 01fd33486..4a16a3fa6 100644
--- a/hush.c
+++ b/hush.c
@@ -470,48 +470,53 @@ static int builtin_export(struct child_prog *child)
470/* built-in 'fg' and 'bg' handler */ 470/* built-in 'fg' and 'bg' handler */
471static int builtin_fg_bg(struct child_prog *child) 471static int builtin_fg_bg(struct child_prog *child)
472{ 472{
473 int i, jobNum; 473 int i, jobnum;
474 struct pipe *job=NULL; 474 struct pipe *pi=NULL;
475
476 if (!child->argv[1] || child->argv[2]) {
477 error_msg("%s: exactly one argument is expected\n",
478 child->argv[0]);
479 return EXIT_FAILURE;
480 }
481
482 if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) {
483 error_msg("%s: bad argument '%s'\n",
484 child->argv[0], child->argv[1]);
485 return EXIT_FAILURE;
486 }
487 475
488 for (job = job_list->head; job; job = job->next) { 476 /* If they gave us no args, assume they want the last backgrounded task */
489 if (job->jobid == jobNum) { 477 if (!child->argv[1]) {
490 break; 478 for (pi = job_list->head; pi; pi = pi->next) {
479 if (pi->progs && pi->progs->pid == last_bg_pid) {
480 break;
481 }
482 }
483 if (!pi) {
484 error_msg("%s: no current job", child->argv[0]);
485 return EXIT_FAILURE;
486 }
487 } else {
488 if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
489 error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]);
490 return EXIT_FAILURE;
491 } 491 }
492 }
493 492
494 if (!job) { 493 for (pi = job_list->head; pi; pi = pi->next) {
495 error_msg("%s: unknown job %d\n", 494 if (pi->jobid == jobnum) {
496 child->argv[0], jobNum); 495 break;
497 return EXIT_FAILURE; 496 }
497 }
498 if (!pi) {
499 error_msg("%s: %d: no such job", child->argv[0], jobnum);
500 return EXIT_FAILURE;
501 }
498 } 502 }
499
500 if (*child->argv[0] == 'f') { 503 if (*child->argv[0] == 'f') {
501 /* Make this job the foreground job */ 504 /* Make this job the foreground job */
505 signal(SIGTTOU, SIG_IGN);
502 /* suppress messages when run from /linuxrc mag@sysgo.de */ 506 /* suppress messages when run from /linuxrc mag@sysgo.de */
503 if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY) 507 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY)
504 perror_msg("tcsetpgrp"); 508 perror_msg("tcsetpgrp");
505 job_list->fg = job; 509 signal(SIGTTOU, SIG_DFL);
510 job_list->fg = pi;
506 } 511 }
507 512
508 /* Restart the processes in the job */ 513 /* Restart the processes in the job */
509 for (i = 0; i < job->num_progs; i++) 514 for (i = 0; i < pi->num_progs; i++)
510 job->progs[i].is_stopped = 0; 515 pi->progs[i].is_stopped = 0;
511 516
512 kill(-job->pgrp, SIGCONT); 517 kill(-pi->pgrp, SIGCONT);
513 518
514 job->stopped_progs = 0; 519 pi->stopped_progs = 0;
515 return EXIT_SUCCESS; 520 return EXIT_SUCCESS;
516} 521}
517 522
@@ -1055,7 +1060,7 @@ static void insert_bg_job(struct pipe *pi)
1055 } 1060 }
1056 1061
1057 /* physically copy the struct job */ 1062 /* physically copy the struct job */
1058 *thejob = *pi; 1063 memcpy(thejob, pi, sizeof(struct pipe));
1059 thejob->next = NULL; 1064 thejob->next = NULL;
1060 thejob->running_progs = thejob->num_progs; 1065 thejob->running_progs = thejob->num_progs;
1061 thejob->stopped_progs = 0; 1066 thejob->stopped_progs = 0;
@@ -1103,6 +1108,7 @@ static void free_pipe(struct pipe *pi)
1103 memset(pi, 0, sizeof(struct pipe)); 1108 memset(pi, 0, sizeof(struct pipe));
1104} 1109}
1105 1110
1111
1106/* Checks to see if any background processes have exited -- if they 1112/* Checks to see if any background processes have exited -- if they
1107 have, figure out why and see if a job has completed */ 1113 have, figure out why and see if a job has completed */
1108static void checkjobs() 1114static void checkjobs()
@@ -1169,14 +1175,27 @@ static void checkjobs()
1169static int run_pipe_real(struct pipe *pi) 1175static int run_pipe_real(struct pipe *pi)
1170{ 1176{
1171 int i; 1177 int i;
1178 int ctty;
1172 int nextin, nextout; 1179 int nextin, nextout;
1173 int pipefds[2]; /* pipefds[0] is for reading */ 1180 int pipefds[2]; /* pipefds[0] is for reading */
1174 struct child_prog *child; 1181 struct child_prog *child;
1175 struct built_in_command *x; 1182 struct built_in_command *x;
1176 1183
1184 ctty = -1;
1177 nextin = 0; 1185 nextin = 0;
1178 pi->pgrp = 0; 1186 pi->pgrp = 0;
1179 1187
1188 /* Check if we are supposed to run in the foreground */
1189 if (pi->followup!=PIPE_BG) {
1190 if ((pi->pgrp = tcgetpgrp(ctty = 2)) < 0
1191 && (pi->pgrp = tcgetpgrp(ctty = 0)) < 0
1192 && (pi->pgrp = tcgetpgrp(ctty = 1)) < 0)
1193 return errno = ENOTTY, -1;
1194
1195 if (pi->pgrp < 0 && pi->pgrp != getpgrp())
1196 return errno = EPERM, -1;
1197 }
1198
1180 /* Check if this is a simple builtin (not part of a pipe). 1199 /* Check if this is a simple builtin (not part of a pipe).
1181 * Builtins within pipes have to fork anyway, and are handled in 1200 * Builtins within pipes have to fork anyway, and are handled in
1182 * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. 1201 * pseudo_exec. "echo foo | read bar" doesn't work on bash, either.
@@ -1225,6 +1244,7 @@ static int run_pipe_real(struct pipe *pi)
1225 1244
1226 /* XXX test for failed fork()? */ 1245 /* XXX test for failed fork()? */
1227 if (!(child->pid = fork())) { 1246 if (!(child->pid = fork())) {
1247
1228 signal(SIGTTOU, SIG_DFL); 1248 signal(SIGTTOU, SIG_DFL);
1229 1249
1230 close_all(); 1250 close_all();
@@ -1244,22 +1264,33 @@ static int run_pipe_real(struct pipe *pi)
1244 /* Like bash, explicit redirects override pipes, 1264 /* Like bash, explicit redirects override pipes,
1245 * and the pipe fd is available for dup'ing. */ 1265 * and the pipe fd is available for dup'ing. */
1246 setup_redirects(child,NULL); 1266 setup_redirects(child,NULL);
1267
1268 if (pi->followup!=PIPE_BG) {
1269 /* Put our child in the process group whose leader is the
1270 * first process in this pipe. */
1271 if (pi->pgrp < 0) {
1272 pi->pgrp = child->pid;
1273 }
1274 /* Don't check for errors. The child may be dead already,
1275 * in which case setpgid returns error code EACCES. */
1276 if (setpgid(0, pi->pgrp) == 0) {
1277 signal(SIGTTOU, SIG_IGN);
1278 tcsetpgrp(ctty, pi->pgrp);
1279 signal(SIGTTOU, SIG_DFL);
1280 }
1281 }
1247 1282
1248 pseudo_exec(child); 1283 pseudo_exec(child);
1249 } 1284 }
1250 if (interactive) { 1285 /* Put our child in the process group whose leader is the
1251 /* Put our child in the process group whose leader is the 1286 * first process in this pipe. */
1252 * first process in this pipe. */ 1287 if (pi->pgrp < 0) {
1253 if (pi->pgrp==0) { 1288 pi->pgrp = child->pid;
1254 pi->pgrp = child->pid;
1255 }
1256 /* Don't check for errors. The child may be dead already,
1257 * in which case setpgid returns error code EACCES. */
1258 setpgid(child->pid, pi->pgrp);
1259 } 1289 }
1260 /* In the non-interactive case, do nothing. Leave the children 1290 /* Don't check for errors. The child may be dead already,
1261 * with the process group that they inherited from us. */ 1291 * in which case setpgid returns error code EACCES. */
1262 1292 setpgid(child->pid, pi->pgrp);
1293
1263 if (nextin != 0) 1294 if (nextin != 0)
1264 close(nextin); 1295 close(nextin);
1265 if (nextout != 1) 1296 if (nextout != 1)
@@ -1295,13 +1326,10 @@ static int run_list_real(struct pipe *pi)
1295 /* XXX check bash's behavior with nontrivial pipes */ 1326 /* XXX check bash's behavior with nontrivial pipes */
1296 /* XXX compute jobid */ 1327 /* XXX compute jobid */
1297 /* XXX what does bash do with attempts to background builtins? */ 1328 /* XXX what does bash do with attempts to background builtins? */
1298#if 0
1299 printf("[%d] %d\n", pi->jobid, pi->pgrp);
1300 last_bg_pid = pi->pgrp;
1301#endif
1302 insert_bg_job(pi); 1329 insert_bg_job(pi);
1303 rcode = EXIT_SUCCESS; 1330 rcode = EXIT_SUCCESS;
1304 } else { 1331 } else {
1332
1305 if (interactive) { 1333 if (interactive) {
1306 /* move the new process group into the foreground */ 1334 /* move the new process group into the foreground */
1307 /* suppress messages when run from /linuxrc mag@sysgo.de */ 1335 /* suppress messages when run from /linuxrc mag@sysgo.de */
diff --git a/shell/hush.c b/shell/hush.c
index 01fd33486..4a16a3fa6 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -470,48 +470,53 @@ static int builtin_export(struct child_prog *child)
470/* built-in 'fg' and 'bg' handler */ 470/* built-in 'fg' and 'bg' handler */
471static int builtin_fg_bg(struct child_prog *child) 471static int builtin_fg_bg(struct child_prog *child)
472{ 472{
473 int i, jobNum; 473 int i, jobnum;
474 struct pipe *job=NULL; 474 struct pipe *pi=NULL;
475
476 if (!child->argv[1] || child->argv[2]) {
477 error_msg("%s: exactly one argument is expected\n",
478 child->argv[0]);
479 return EXIT_FAILURE;
480 }
481
482 if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) {
483 error_msg("%s: bad argument '%s'\n",
484 child->argv[0], child->argv[1]);
485 return EXIT_FAILURE;
486 }
487 475
488 for (job = job_list->head; job; job = job->next) { 476 /* If they gave us no args, assume they want the last backgrounded task */
489 if (job->jobid == jobNum) { 477 if (!child->argv[1]) {
490 break; 478 for (pi = job_list->head; pi; pi = pi->next) {
479 if (pi->progs && pi->progs->pid == last_bg_pid) {
480 break;
481 }
482 }
483 if (!pi) {
484 error_msg("%s: no current job", child->argv[0]);
485 return EXIT_FAILURE;
486 }
487 } else {
488 if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
489 error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]);
490 return EXIT_FAILURE;
491 } 491 }
492 }
493 492
494 if (!job) { 493 for (pi = job_list->head; pi; pi = pi->next) {
495 error_msg("%s: unknown job %d\n", 494 if (pi->jobid == jobnum) {
496 child->argv[0], jobNum); 495 break;
497 return EXIT_FAILURE; 496 }
497 }
498 if (!pi) {
499 error_msg("%s: %d: no such job", child->argv[0], jobnum);
500 return EXIT_FAILURE;
501 }
498 } 502 }
499
500 if (*child->argv[0] == 'f') { 503 if (*child->argv[0] == 'f') {
501 /* Make this job the foreground job */ 504 /* Make this job the foreground job */
505 signal(SIGTTOU, SIG_IGN);
502 /* suppress messages when run from /linuxrc mag@sysgo.de */ 506 /* suppress messages when run from /linuxrc mag@sysgo.de */
503 if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY) 507 if (tcsetpgrp(0, pi->pgrp) && errno != ENOTTY)
504 perror_msg("tcsetpgrp"); 508 perror_msg("tcsetpgrp");
505 job_list->fg = job; 509 signal(SIGTTOU, SIG_DFL);
510 job_list->fg = pi;
506 } 511 }
507 512
508 /* Restart the processes in the job */ 513 /* Restart the processes in the job */
509 for (i = 0; i < job->num_progs; i++) 514 for (i = 0; i < pi->num_progs; i++)
510 job->progs[i].is_stopped = 0; 515 pi->progs[i].is_stopped = 0;
511 516
512 kill(-job->pgrp, SIGCONT); 517 kill(-pi->pgrp, SIGCONT);
513 518
514 job->stopped_progs = 0; 519 pi->stopped_progs = 0;
515 return EXIT_SUCCESS; 520 return EXIT_SUCCESS;
516} 521}
517 522
@@ -1055,7 +1060,7 @@ static void insert_bg_job(struct pipe *pi)
1055 } 1060 }
1056 1061
1057 /* physically copy the struct job */ 1062 /* physically copy the struct job */
1058 *thejob = *pi; 1063 memcpy(thejob, pi, sizeof(struct pipe));
1059 thejob->next = NULL; 1064 thejob->next = NULL;
1060 thejob->running_progs = thejob->num_progs; 1065 thejob->running_progs = thejob->num_progs;
1061 thejob->stopped_progs = 0; 1066 thejob->stopped_progs = 0;
@@ -1103,6 +1108,7 @@ static void free_pipe(struct pipe *pi)
1103 memset(pi, 0, sizeof(struct pipe)); 1108 memset(pi, 0, sizeof(struct pipe));
1104} 1109}
1105 1110
1111
1106/* Checks to see if any background processes have exited -- if they 1112/* Checks to see if any background processes have exited -- if they
1107 have, figure out why and see if a job has completed */ 1113 have, figure out why and see if a job has completed */
1108static void checkjobs() 1114static void checkjobs()
@@ -1169,14 +1175,27 @@ static void checkjobs()
1169static int run_pipe_real(struct pipe *pi) 1175static int run_pipe_real(struct pipe *pi)
1170{ 1176{
1171 int i; 1177 int i;
1178 int ctty;
1172 int nextin, nextout; 1179 int nextin, nextout;
1173 int pipefds[2]; /* pipefds[0] is for reading */ 1180 int pipefds[2]; /* pipefds[0] is for reading */
1174 struct child_prog *child; 1181 struct child_prog *child;
1175 struct built_in_command *x; 1182 struct built_in_command *x;
1176 1183
1184 ctty = -1;
1177 nextin = 0; 1185 nextin = 0;
1178 pi->pgrp = 0; 1186 pi->pgrp = 0;
1179 1187
1188 /* Check if we are supposed to run in the foreground */
1189 if (pi->followup!=PIPE_BG) {
1190 if ((pi->pgrp = tcgetpgrp(ctty = 2)) < 0
1191 && (pi->pgrp = tcgetpgrp(ctty = 0)) < 0
1192 && (pi->pgrp = tcgetpgrp(ctty = 1)) < 0)
1193 return errno = ENOTTY, -1;
1194
1195 if (pi->pgrp < 0 && pi->pgrp != getpgrp())
1196 return errno = EPERM, -1;
1197 }
1198
1180 /* Check if this is a simple builtin (not part of a pipe). 1199 /* Check if this is a simple builtin (not part of a pipe).
1181 * Builtins within pipes have to fork anyway, and are handled in 1200 * Builtins within pipes have to fork anyway, and are handled in
1182 * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. 1201 * pseudo_exec. "echo foo | read bar" doesn't work on bash, either.
@@ -1225,6 +1244,7 @@ static int run_pipe_real(struct pipe *pi)
1225 1244
1226 /* XXX test for failed fork()? */ 1245 /* XXX test for failed fork()? */
1227 if (!(child->pid = fork())) { 1246 if (!(child->pid = fork())) {
1247
1228 signal(SIGTTOU, SIG_DFL); 1248 signal(SIGTTOU, SIG_DFL);
1229 1249
1230 close_all(); 1250 close_all();
@@ -1244,22 +1264,33 @@ static int run_pipe_real(struct pipe *pi)
1244 /* Like bash, explicit redirects override pipes, 1264 /* Like bash, explicit redirects override pipes,
1245 * and the pipe fd is available for dup'ing. */ 1265 * and the pipe fd is available for dup'ing. */
1246 setup_redirects(child,NULL); 1266 setup_redirects(child,NULL);
1267
1268 if (pi->followup!=PIPE_BG) {
1269 /* Put our child in the process group whose leader is the
1270 * first process in this pipe. */
1271 if (pi->pgrp < 0) {
1272 pi->pgrp = child->pid;
1273 }
1274 /* Don't check for errors. The child may be dead already,
1275 * in which case setpgid returns error code EACCES. */
1276 if (setpgid(0, pi->pgrp) == 0) {
1277 signal(SIGTTOU, SIG_IGN);
1278 tcsetpgrp(ctty, pi->pgrp);
1279 signal(SIGTTOU, SIG_DFL);
1280 }
1281 }
1247 1282
1248 pseudo_exec(child); 1283 pseudo_exec(child);
1249 } 1284 }
1250 if (interactive) { 1285 /* Put our child in the process group whose leader is the
1251 /* Put our child in the process group whose leader is the 1286 * first process in this pipe. */
1252 * first process in this pipe. */ 1287 if (pi->pgrp < 0) {
1253 if (pi->pgrp==0) { 1288 pi->pgrp = child->pid;
1254 pi->pgrp = child->pid;
1255 }
1256 /* Don't check for errors. The child may be dead already,
1257 * in which case setpgid returns error code EACCES. */
1258 setpgid(child->pid, pi->pgrp);
1259 } 1289 }
1260 /* In the non-interactive case, do nothing. Leave the children 1290 /* Don't check for errors. The child may be dead already,
1261 * with the process group that they inherited from us. */ 1291 * in which case setpgid returns error code EACCES. */
1262 1292 setpgid(child->pid, pi->pgrp);
1293
1263 if (nextin != 0) 1294 if (nextin != 0)
1264 close(nextin); 1295 close(nextin);
1265 if (nextout != 1) 1296 if (nextout != 1)
@@ -1295,13 +1326,10 @@ static int run_list_real(struct pipe *pi)
1295 /* XXX check bash's behavior with nontrivial pipes */ 1326 /* XXX check bash's behavior with nontrivial pipes */
1296 /* XXX compute jobid */ 1327 /* XXX compute jobid */
1297 /* XXX what does bash do with attempts to background builtins? */ 1328 /* XXX what does bash do with attempts to background builtins? */
1298#if 0
1299 printf("[%d] %d\n", pi->jobid, pi->pgrp);
1300 last_bg_pid = pi->pgrp;
1301#endif
1302 insert_bg_job(pi); 1329 insert_bg_job(pi);
1303 rcode = EXIT_SUCCESS; 1330 rcode = EXIT_SUCCESS;
1304 } else { 1331 } else {
1332
1305 if (interactive) { 1333 if (interactive) {
1306 /* move the new process group into the foreground */ 1334 /* move the new process group into the foreground */
1307 /* suppress messages when run from /linuxrc mag@sysgo.de */ 1335 /* suppress messages when run from /linuxrc mag@sysgo.de */