Fix sh(1) changing foreground group when non-interactive.

This commit is contained in:
Jonas 'Sortie' Termansen 2022-11-05 20:37:43 +01:00
parent 0f348c192b
commit 07dd21146b
1 changed files with 21 additions and 15 deletions

36
sh/sh.c
View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen. * Copyright (c) 2011-2016, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -1295,7 +1295,7 @@ struct execute_result execute(char** tokens,
// foreground process group, but bar dies prior to foo's tcsetpgrp // foreground process group, but bar dies prior to foo's tcsetpgrp
// call, because then the shell would run tcsetpgrp to take back // call, because then the shell would run tcsetpgrp to take back
// control, and only then would foo do its tcsetpgrp call. // control, and only then would foo do its tcsetpgrp call.
while ( foreground_shell && pgid == -1 && tcgetpgrp(0) != childpid ) while ( interactive && pgid == -1 && tcgetpgrp(0) != childpid )
sched_yield(); sched_yield();
struct execute_result result; struct execute_result result;
@ -1306,7 +1306,7 @@ struct execute_result execute(char** tokens,
} }
setpgid(0, pgid != -1 ? pgid : 0); setpgid(0, pgid != -1 ? pgid : 0);
if ( foreground_shell && pgid == -1 ) if ( interactive && pgid == -1 )
{ {
sigset_t oldset, sigttou; sigset_t oldset, sigttou;
sigemptyset(&sigttou); sigemptyset(&sigttou);
@ -1491,12 +1491,15 @@ readcmd:
// as that may have side effects if a process checks for this // as that may have side effects if a process checks for this
// behavior and then unexpectedly the shell takes back support // behavior and then unexpectedly the shell takes back support
// without the usual ^Z mechanism. // without the usual ^Z mechanism.
sigset_t oldset, sigttou; if ( interactive )
sigemptyset(&sigttou); {
sigaddset(&sigttou, SIGTTOU); sigset_t oldset, sigttou;
sigprocmask(SIG_BLOCK, &sigttou, &oldset); sigemptyset(&sigttou);
tcsetpgrp(0, getpgid(0)); sigaddset(&sigttou, SIGTTOU);
sigprocmask(SIG_SETMASK, &oldset, NULL); sigprocmask(SIG_BLOCK, &sigttou, &oldset);
tcsetpgrp(0, getpgid(0));
sigprocmask(SIG_SETMASK, &oldset, NULL);
}
pgid = -1; pgid = -1;
status = 0; status = 0;
goto readcmd; goto readcmd;
@ -1520,12 +1523,15 @@ readcmd:
status = 1; status = 1;
return status; return status;
} }
sigset_t oldset, sigttou; if ( interactive )
sigemptyset(&sigttou); {
sigaddset(&sigttou, SIGTTOU); sigset_t oldset, sigttou;
sigprocmask(SIG_BLOCK, &sigttou, &oldset); sigemptyset(&sigttou);
tcsetpgrp(0, getpgid(0)); sigaddset(&sigttou, SIGTTOU);
sigprocmask(SIG_SETMASK, &oldset, NULL); sigprocmask(SIG_BLOCK, &sigttou, &oldset);
tcsetpgrp(0, getpgid(0));
sigprocmask(SIG_SETMASK, &oldset, NULL);
}
if ( WIFSIGNALED(exitstatus) && WTERMSIG(exitstatus) == SIGINT ) if ( WIFSIGNALED(exitstatus) && WTERMSIG(exitstatus) == SIGINT )
printf("^C\n"); printf("^C\n");
else if ( WIFSIGNALED(exitstatus) && WTERMSIG(exitstatus) != SIGPIPE ) else if ( WIFSIGNALED(exitstatus) && WTERMSIG(exitstatus) != SIGPIPE )