From ca96022d6edaaf619324db5a481698231d74d1df Mon Sep 17 00:00:00 2001 From: Sören Tempel Date: Tue, 8 Feb 2022 20:29:30 +0100 Subject: ed: don't use memcpy with overlapping memory regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The memcpy invocations in the subCommand function, modified by this commit, previously used memcpy with overlapping memory regions. This is undefined behavior. On Alpine Linux, it causes BusyBox ed to crash since we compile BusyBox with -D_FORTIFY_SOURCE=2 and our fortify-headers implementation catches this source of undefined behavior [0]. The issue can only be triggered if the replacement string is the same size or shorter than the old string. Looking at the code, it seems to me that a memmove(3) is what was actually intended here, this commit modifies the code accordingly. [0]: https://gitlab.alpinelinux.org/alpine/aports/-/issues/13504 Signed-off-by: Sören Tempel Signed-off-by: Denys Vlasenko --- editors/ed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/ed.c b/editors/ed.c index 209ce9942..4a84f7433 100644 --- a/editors/ed.c +++ b/editors/ed.c @@ -720,7 +720,7 @@ static void subCommand(const char *cmd, int num1, int num2) if (deltaLen <= 0) { memcpy(&lp->data[offset], newStr, newLen); if (deltaLen) { - memcpy(&lp->data[offset + newLen], + memmove(&lp->data[offset + newLen], &lp->data[offset + oldLen], lp->len - offset - oldLen); -- cgit v1.2.3-55-g6feb From 85acf71d2579ebe4eec05c6f31901adffa700adc Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Fri, 16 Sep 2022 15:06:36 +0200 Subject: ntpd: make NTP client and server Y2036/2038-ready The 32-bit integer part of the NTP timestamp overflows in year 2036, which starts the second NTP era. Modify the timestamp conversion to shift values between 1900-1970 (in the first era) to the second era to enable the client to measure its offset correctly until year 2106 (assuming 64-bit time_t). Also update the conversion from double used when stepping the clock to work with 64-bit time_t after reaching the maximum 32-bit value in 2038 and the server conversion to work correctly in the next NTP era. function old new delta lfp_to_d 51 64 +13 step_time 326 332 +6 .rodata 105260 105264 +4 d_to_lfp 100 86 -14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/1 up/down: 23/-14) Total: 9 bytes Signed-off-by: Miroslav Lichvar Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 204e1d7c2..4365166ff 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -554,7 +554,7 @@ gettime1900d(void) static void d_to_tv(struct timeval *tv, double d) { - tv->tv_sec = (long)d; + tv->tv_sec = (time_t)d; tv->tv_usec = (d - tv->tv_sec) * 1000000; } @@ -565,6 +565,14 @@ lfp_to_d(l_fixedpt_t lfp) lfp.int_partl = ntohl(lfp.int_partl); lfp.fractionl = ntohl(lfp.fractionl); ret = (double)lfp.int_partl + ((double)lfp.fractionl / UINT_MAX); + /* + * Shift timestamps before 1970 to the second NTP era (2036-2106): + * int_partl value of OFFSET_1900_1970 (2208988800) is interpreted as + * the start of year 1970 and it is the minimal representable time, + * all values form the sequence 2208988800..0xffffffff,0..2208988799. + */ + if (lfp.int_partl < OFFSET_1900_1970) + ret += (double)(1ULL << 32); /* because int_partl is 32-bit wide */ return ret; } static NOINLINE double @@ -582,8 +590,8 @@ d_to_lfp(l_fixedpt_t *lfp, double d) { uint32_t intl; uint32_t frac; - intl = (uint32_t)d; - frac = (uint32_t)((d - intl) * UINT_MAX); + intl = (uint32_t)(time_t)d; + frac = (uint32_t)((d - (time_t)d) * UINT_MAX); lfp->int_partl = htonl(intl); lfp->fractionl = htonl(frac); } -- cgit v1.2.3-55-g6feb From c344ca6c7f5d8468624ae518d2912d1d9612cb91 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 17 Jan 2023 17:01:05 +0100 Subject: ntpd: correct fixed->float conversions of fractions Need to divide by (1<<32), not by (1<<32)-1. Fraction of 0xffffffff is not 1 whole second. function old new delta .rodata 105264 105268 +4 Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 4365166ff..ff49550e9 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -564,7 +564,7 @@ lfp_to_d(l_fixedpt_t lfp) double ret; lfp.int_partl = ntohl(lfp.int_partl); lfp.fractionl = ntohl(lfp.fractionl); - ret = (double)lfp.int_partl + ((double)lfp.fractionl / UINT_MAX); + ret = (double)lfp.int_partl + ((double)lfp.fractionl / (1ULL << 32)); /* * Shift timestamps before 1970 to the second NTP era (2036-2106): * int_partl value of OFFSET_1900_1970 (2208988800) is interpreted as @@ -581,7 +581,7 @@ sfp_to_d(s_fixedpt_t sfp) double ret; sfp.int_parts = ntohs(sfp.int_parts); sfp.fractions = ntohs(sfp.fractions); - ret = (double)sfp.int_parts + ((double)sfp.fractions / USHRT_MAX); + ret = (double)sfp.int_parts + ((double)sfp.fractions / (1 << 16)); return ret; } #if ENABLE_FEATURE_NTPD_SERVER @@ -591,7 +591,7 @@ d_to_lfp(l_fixedpt_t *lfp, double d) uint32_t intl; uint32_t frac; intl = (uint32_t)(time_t)d; - frac = (uint32_t)((d - (time_t)d) * UINT_MAX); + frac = (uint32_t)((d - (time_t)d) * 0xffffffff); lfp->int_partl = htonl(intl); lfp->fractionl = htonl(frac); } @@ -601,7 +601,7 @@ d_to_sfp(s_fixedpt_t *sfp, double d) uint16_t ints; uint16_t frac; ints = (uint16_t)d; - frac = (uint16_t)((d - ints) * USHRT_MAX); + frac = (uint16_t)((d - ints) * 0xffff); sfp->int_parts = htons(ints); sfp->fractions = htons(frac); } -- cgit v1.2.3-55-g6feb From 479bd7af0d24d123326c1ceb447e015e9e2955d7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 18 Jan 2023 17:42:17 +0100 Subject: ntpd: fold d_to_tv() into its only caller Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index ff49550e9..db04eb272 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -551,13 +551,6 @@ gettime1900d(void) return G.cur_time; } -static void -d_to_tv(struct timeval *tv, double d) -{ - tv->tv_sec = (time_t)d; - tv->tv_usec = (d - tv->tv_sec) * 1000000; -} - static NOINLINE double lfp_to_d(l_fixedpt_t lfp) { @@ -1044,8 +1037,17 @@ step_time(double offset) time_t tval; xgettimeofday(&tvc); + /* This code adds floating point value on the order of 1.0 + * to a value of ~4 billion (as of years 203x). + * With 52-bit mantissa, "only" 20 bits of offset's precision + * are used (0.01 attosecond), the rest is lost. + * Some 200 billion years later, when tvc.tv_sec would have + * 63 significant bits, the precision loss would be catastrophic, + * a more complex code would be needed. + */ dtime = tvc.tv_sec + (1.0e-6 * tvc.tv_usec) + offset; - d_to_tv(&tvn, dtime); + tvn.tv_sec = (time_t)dtime; + tvn.tv_usec = (dtime - tvn.tv_sec) * 1000000; xsettimeofday(&tvn); VERB2 { -- cgit v1.2.3-55-g6feb From 1040f78176c7dad57aadbbd023e8ac094606ac25 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 18 Jan 2023 18:04:22 +0100 Subject: ntpd: correct comment: 2^-20 is ~1 microsecond (confused with 10^-20) Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index db04eb272..c7519b8fb 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -1040,7 +1040,7 @@ step_time(double offset) /* This code adds floating point value on the order of 1.0 * to a value of ~4 billion (as of years 203x). * With 52-bit mantissa, "only" 20 bits of offset's precision - * are used (0.01 attosecond), the rest is lost. + * are used (~1 microsecond), the rest is lost. * Some 200 billion years later, when tvc.tv_sec would have * 63 significant bits, the precision loss would be catastrophic, * a more complex code would be needed. -- cgit v1.2.3-55-g6feb From c2739e11dee92770839ac9b2dbf020459baec7b9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 24 Jan 2023 12:47:32 +0100 Subject: nmeter: increase maximum /proc file size (needed for large machines) function old new delta get_file 185 201 +16 Signed-off-by: Denys Vlasenko --- procps/nmeter.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/procps/nmeter.c b/procps/nmeter.c index 68e6f3325..e52c868df 100644 --- a/procps/nmeter.c +++ b/procps/nmeter.c @@ -59,9 +59,9 @@ typedef unsigned long long ullong; -enum { /* Preferably use powers of 2 */ +enum { PROC_MIN_FILE_SIZE = 256, - PROC_MAX_FILE_SIZE = 16 * 1024, + PROC_MAX_FILE_SIZE = 64 * 1024, /* 16k was a bit too small for a 128-CPU machine */ }; typedef struct proc_file { @@ -176,7 +176,10 @@ static void readfile_z(proc_file *pf, const char* fname) close(fd); if (rdsz > 0) { if (rdsz == sz-1 && sz < PROC_MAX_FILE_SIZE) { - sz *= 2; + if (sz < 4 * 1024) + sz *= 2; + else + sz += 4 * 1024; buf = xrealloc(buf, sz); goto again; } -- cgit v1.2.3-55-g6feb From 93e0898c663a533082b5f3c2e7dcce93ec47076d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 26 Jan 2023 12:56:33 +0100 Subject: shell: fix SIGWINCH and SIGCHLD (in hush) interrupting line input, closes 15256 function old new delta record_pending_signo 32 63 +31 lineedit_read_key 231 224 -7 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 31/-7) Total: 24 bytes Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 17 ++++++++++------- shell/ash.c | 3 ++- shell/hush.c | 10 ++++++++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index d6b2e76ff..b942f540a 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -2180,7 +2180,8 @@ static int lineedit_read_key(char *read_key_buffer, int timeout) * "\xff\n",pause,"ls\n" invalid and thus won't lose "ls". * * If LI_INTERRUPTIBLE, return -1 if got EINTR in poll() - * inside read_key, or if bb_got_signal != 0 (IOW: if signal + * inside read_key and bb_got_signal became != 0, + * or if bb_got_signal != 0 (IOW: if signal * arrived before poll() is reached). * * Note: read_key sets errno to 0 on success. @@ -2197,14 +2198,16 @@ static int lineedit_read_key(char *read_key_buffer, int timeout) IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 0;) if (errno != EINTR) break; + /* It was EINTR. Repeat read_key() unless... */ if (state->flags & LI_INTERRUPTIBLE) { - /* LI_INTERRUPTIBLE bails out on EINTR, - * but nothing really guarantees that bb_got_signal - * is nonzero. Follow the least surprise principle: + /* LI_INTERRUPTIBLE bails out on EINTR + * if bb_got_signal became nonzero. + * (It may stay zero: for example, our SIGWINCH + * handler does not set it. This is used for signals + * which should not interrupt line editing). */ - if (bb_got_signal == 0) - bb_got_signal = 255; - goto ret; + if (bb_got_signal != 0) + goto ret; /* will return -1 */ } } diff --git a/shell/ash.c b/shell/ash.c index 18ccc1329..5f8c8ea19 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -10821,7 +10821,8 @@ preadfd(void) again: /* For shell, LI_INTERRUPTIBLE is set: * read_line_input will abort on either - * getting EINTR in poll(), or if it sees bb_got_signal != 0 + * getting EINTR in poll() and bb_got_signal became != 0, + * or if it sees bb_got_signal != 0 * (IOW: if signal arrives before poll() is reached). * Interactive testcases: * (while kill -INT $$; do sleep 1; done) & diff --git a/shell/hush.c b/shell/hush.c index d111f0cc5..f064b8fd2 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1946,7 +1946,12 @@ static void record_pending_signo(int sig) { sigaddset(&G.pending_set, sig); #if ENABLE_FEATURE_EDITING - bb_got_signal = sig; /* for read_line_input: "we got a signal" */ + if (sig != SIGCHLD + || (G_traps && G_traps[SIGCHLD] && G_traps[SIGCHLD][0]) + /* ^^^ if SIGCHLD, interrupt line reading only if it has a trap */ + ) { + bb_got_signal = sig; /* for read_line_input: "we got a signal" */ + } #endif #if ENABLE_HUSH_FAST if (sig == SIGCHLD) { @@ -2669,7 +2674,8 @@ static int get_user_input(struct in_str *i) } else { /* For shell, LI_INTERRUPTIBLE is set: * read_line_input will abort on either - * getting EINTR in poll(), or if it sees bb_got_signal != 0 + * getting EINTR in poll() and bb_got_signal became != 0, + * or if it sees bb_got_signal != 0 * (IOW: if signal arrives before poll() is reached). * Interactive testcases: * (while kill -INT $$; do sleep 1; done) & -- cgit v1.2.3-55-g6feb From 6101b6d3eaa0fe5096c43d4fc648d49a532ee9c0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 30 Jan 2023 15:57:04 +0100 Subject: hush: remove special handling of SIGHUP Kernel should do the right thing. (ash and dash do not have special SIGHUP handling.) function old new delta check_and_run_traps 278 214 -64 Signed-off-by: Denys Vlasenko --- shell/hush.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index f064b8fd2..9b87e28cf 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1830,6 +1830,8 @@ static void restore_G_args(save_arg_t *sv, char **argv) * SIGTERM (interactive): ignore * SIGHUP (interactive): * send SIGCONT to stopped jobs, send SIGHUP to all jobs and exit +//HUP: we don't need to do this, kernel does this for us +//HUP: ("orphaned process group" handling according to POSIX) * SIGTTIN, SIGTTOU, SIGTSTP (if job control is on): ignore * Note that ^Z is handled not by trapping SIGTSTP, but by seeing * that all pipe members are stopped. Try this in bash: @@ -1931,7 +1933,7 @@ enum { SPECIAL_INTERACTIVE_SIGS = 0 | (1 << SIGTERM) | (1 << SIGINT) - | (1 << SIGHUP) +//HUP | (1 << SIGHUP) , SPECIAL_JOBSTOP_SIGS = 0 #if ENABLE_HUSH_JOB @@ -2177,23 +2179,23 @@ static int check_and_run_traps(void) last_sig = sig; break; #if ENABLE_HUSH_JOB - case SIGHUP: { -//TODO: why are we doing this? ash and dash don't do this, -//they have no handler for SIGHUP at all, -//they rely on kernel to send SIGHUP+SIGCONT to orphaned process groups - struct pipe *job; - debug_printf_exec("%s: sig:%d default SIGHUP handler\n", __func__, sig); - /* bash is observed to signal whole process groups, - * not individual processes */ - for (job = G.job_list; job; job = job->next) { - if (job->pgrp <= 0) - continue; - debug_printf_exec("HUPing pgrp %d\n", job->pgrp); - if (kill(- job->pgrp, SIGHUP) == 0) - kill(- job->pgrp, SIGCONT); - } - sigexit(SIGHUP); - } +//HUP case SIGHUP: { +//HUP//TODO: why are we doing this? ash and dash don't do this, +//HUP//they have no handler for SIGHUP at all, +//HUP//they rely on kernel to send SIGHUP+SIGCONT to orphaned process groups +//HUP struct pipe *job; +//HUP debug_printf_exec("%s: sig:%d default SIGHUP handler\n", __func__, sig); +//HUP /* bash is observed to signal whole process groups, +//HUP * not individual processes */ +//HUP for (job = G.job_list; job; job = job->next) { +//HUP if (job->pgrp <= 0) +//HUP continue; +//HUP debug_printf_exec("HUPing pgrp %d\n", job->pgrp); +//HUP if (kill(- job->pgrp, SIGHUP) == 0) +//HUP kill(- job->pgrp, SIGCONT); +//HUP } +//HUP sigexit(SIGHUP); +//HUP } #endif #if ENABLE_HUSH_FAST case SIGCHLD: -- cgit v1.2.3-55-g6feb From 1fdb33bd07e52cea832a6584c79e9aa11987da1f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 30 Jan 2023 16:49:48 +0100 Subject: hush: restore tty pgrp on SIGHUP Found one case where SIGHUP does need some handling. ash does not restore tty pgrp when killed by SIGHUP, and this means process which started ash needs to restore it, or it would get backgrounded when trying to use tty. function old new delta check_and_run_traps 214 229 +15 Signed-off-by: Denys Vlasenko --- shell/hush.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 9b87e28cf..80a39925f 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1831,7 +1831,10 @@ static void restore_G_args(save_arg_t *sv, char **argv) * SIGHUP (interactive): * send SIGCONT to stopped jobs, send SIGHUP to all jobs and exit //HUP: we don't need to do this, kernel does this for us -//HUP: ("orphaned process group" handling according to POSIX) +//HUP: ("orphaned process group" handling according to POSIX). +//HUP: We still have a SIGHUP handler, just to have tty pgrp restored +//HUP: (otherwise e.g. Midnight Commander backgrounds when hush +//HUP: started from it gets killed by SIGHUP). * SIGTTIN, SIGTTOU, SIGTSTP (if job control is on): ignore * Note that ^Z is handled not by trapping SIGTSTP, but by seeing * that all pipe members are stopped. Try this in bash: @@ -1933,7 +1936,7 @@ enum { SPECIAL_INTERACTIVE_SIGS = 0 | (1 << SIGTERM) | (1 << SIGINT) -//HUP | (1 << SIGHUP) + | (1 << SIGHUP) , SPECIAL_JOBSTOP_SIGS = 0 #if ENABLE_HUSH_JOB @@ -2179,7 +2182,7 @@ static int check_and_run_traps(void) last_sig = sig; break; #if ENABLE_HUSH_JOB -//HUP case SIGHUP: { + case SIGHUP: { //HUP//TODO: why are we doing this? ash and dash don't do this, //HUP//they have no handler for SIGHUP at all, //HUP//they rely on kernel to send SIGHUP+SIGCONT to orphaned process groups @@ -2194,8 +2197,8 @@ static int check_and_run_traps(void) //HUP if (kill(- job->pgrp, SIGHUP) == 0) //HUP kill(- job->pgrp, SIGCONT); //HUP } -//HUP sigexit(SIGHUP); -//HUP } + sigexit(SIGHUP); + } #endif #if ENABLE_HUSH_FAST case SIGCHLD: -- cgit v1.2.3-55-g6feb From 93ae7464e6e460f25b73e4ffefd2d9a6499eae30 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 30 Jan 2023 18:47:18 +0100 Subject: hush: restore SIGHUP handling, this time explain why we do what we do function old new delta check_and_run_traps 229 278 +49 Signed-off-by: Denys Vlasenko --- shell/hush.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 80a39925f..e6be70078 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1829,12 +1829,13 @@ static void restore_G_args(save_arg_t *sv, char **argv) * SIGQUIT: ignore * SIGTERM (interactive): ignore * SIGHUP (interactive): - * send SIGCONT to stopped jobs, send SIGHUP to all jobs and exit -//HUP: we don't need to do this, kernel does this for us -//HUP: ("orphaned process group" handling according to POSIX). -//HUP: We still have a SIGHUP handler, just to have tty pgrp restored -//HUP: (otherwise e.g. Midnight Commander backgrounds when hush -//HUP: started from it gets killed by SIGHUP). + * Send SIGCONT to stopped jobs, send SIGHUP to all jobs and exit. + * Kernel would do this for us ("orphaned process group" handling + * according to POSIX) if we are a session leader and thus our death + * frees the controlling tty, but to be bash-compatible, we also do it + * for every interactive shell's death by SIGHUP. + * (Also, we need to restore tty pgrp, otherwise e.g. Midnight Commander + * backgrounds when hush started from it gets killed by SIGHUP). * SIGTTIN, SIGTTOU, SIGTSTP (if job control is on): ignore * Note that ^Z is handled not by trapping SIGTSTP, but by seeing * that all pipe members are stopped. Try this in bash: @@ -2183,20 +2184,27 @@ static int check_and_run_traps(void) break; #if ENABLE_HUSH_JOB case SIGHUP: { -//HUP//TODO: why are we doing this? ash and dash don't do this, -//HUP//they have no handler for SIGHUP at all, -//HUP//they rely on kernel to send SIGHUP+SIGCONT to orphaned process groups -//HUP struct pipe *job; -//HUP debug_printf_exec("%s: sig:%d default SIGHUP handler\n", __func__, sig); -//HUP /* bash is observed to signal whole process groups, -//HUP * not individual processes */ -//HUP for (job = G.job_list; job; job = job->next) { -//HUP if (job->pgrp <= 0) -//HUP continue; -//HUP debug_printf_exec("HUPing pgrp %d\n", job->pgrp); -//HUP if (kill(- job->pgrp, SIGHUP) == 0) -//HUP kill(- job->pgrp, SIGCONT); -//HUP } + /* if (G_interactive_fd) - no need to check, the handler + * is only installed if we *are* interactive */ + { + /* bash compat: "Before exiting, an interactive + * shell resends the SIGHUP to all jobs, running + * or stopped. Stopped jobs are sent SIGCONT + * to ensure that they receive the SIGHUP." + */ + struct pipe *job; + debug_printf_exec("%s: sig:%d default SIGHUP handler\n", __func__, sig); + /* bash is observed to signal whole process groups, + * not individual processes */ + for (job = G.job_list; job; job = job->next) { + if (job->pgrp <= 0) + continue; + debug_printf_exec("HUPing pgrp %d\n", job->pgrp); + if (kill(- job->pgrp, SIGHUP) == 0) + kill(- job->pgrp, SIGCONT); + } + } + /* this restores tty pgrp, then kills us with SIGHUP */ sigexit(SIGHUP); } #endif -- cgit v1.2.3-55-g6feb