Import from AlmaLinux stable repository

This commit is contained in:
eabdullin 2025-12-04 11:43:10 +00:00
parent 07bb6bb3ad
commit 968888d3d2
8 changed files with 1521 additions and 16 deletions

View File

@ -0,0 +1,194 @@
From a1fcad4bf65fe26a3f9a386b63732ab151ce03ec Mon Sep 17 00:00:00 2001
From: Martijn Dekker <martijn@inlv.org>
Date: Thu, 5 Dec 2024 02:24:39 +0000
Subject: [PATCH] vi: Fix recalling lines starting with whitespace (re:
5eeeed06)
@jghub reports:
> if for some reason a command is entered with leading whitespace,
> the leading whitespace is preserved in the history file (in
> ksh93u+, too). such commands can be recalled from history in 93u+
> without problem, both, in vi and emacs mode.
>
> but in 93u+m such entries are simply ignored when using vi-mode
> (set -o vi), i.e. the k and j commands skip over such entries.
> emacs mode still works just fine.
Analysis: the blankline() function in vi.c and emacs.c is used to
check for whitespace up to the cursor position. This is used for
tab completion and fullscreen editor invocation, where that is
okay, and for history recall, where that should be checking the
entire line instead.
In emacs.c this was not really a problem because arrowing up (or
^P) positions the cursor to the end of the line anyway. But in vi,
arrowing up (or 'k') positions the cursor at the beginning.
src/cmd/ksh93/edit/vi.c:
- Amend blankline() with an 'uptocursor' argument. If nonzero, it
checks the current line for whitespace up to the cursor position,
otherwise it checks the entire line.
- Pass uptocursor==0 to blankline() for history recall and 1 for
tab completion.
src/cmd/ksh93/edit/emacs.c:
- Apply the same change here for consistency, even though it's
perhaps not really necessary. If ever a form of recall is added
that doesn't position the cursor at the end, then that won't
introduce this bug there.
Thanks to @pghvlaans for input into the fix.
Resolves: https://github.com/ksh93/ksh/issues/799
---
src/cmd/ksh93/edit/emacs.c | 14 +++++++-------
src/cmd/ksh93/edit/vi.c | 16 ++++++++--------
src/cmd/ksh93/tests/pty.sh | 12 ++++++++++++
3 files changed, 27 insertions(+), 15 deletions(-)
diff --git a/src/cmd/ksh93/edit/emacs.c b/src/cmd/ksh93/edit/emacs.c
index 128e592..408f6e7 100644
--- a/src/cmd/ksh93/edit/emacs.c
+++ b/src/cmd/ksh93/edit/emacs.c
@@ -178,7 +178,7 @@ static void search(Emacs_t*,genchar*,int);
static void setcursor(Emacs_t*,int, int);
static void show_info(Emacs_t*,const char*);
static void xcommands(Emacs_t*,int);
-static char blankline(Emacs_t*, genchar*);
+static int blankline(Emacs_t*, genchar*, int);
int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
{
@@ -720,9 +720,9 @@ update:
cur = eol;
draw(ep,UPDATE);
/* skip blank lines when going up/down in history */
- if(c==cntl('N') && hline != histlines && blankline(ep,out))
+ if(c==cntl('N') && hline != histlines && blankline(ep,out,0))
ed_ungetchar(ep->ed,cntl('N'));
- else if(c==cntl('P') && hline != hismin && blankline(ep,out))
+ else if(c==cntl('P') && hline != hismin && blankline(ep,out,0))
ed_ungetchar(ep->ed,cntl('P'));
continue;
}
@@ -1023,7 +1023,7 @@ static int escape(Emacs_t* ep,genchar *out,int count)
case '*': /* filename expansion */
case '=': /* escape = - list all matching file names */
{
- if(cur<1 || blankline(ep,out))
+ if(cur<1 || blankline(ep,out,1))
{
beep();
return -1;
@@ -1312,7 +1312,7 @@ static void xcommands(Emacs_t *ep,int count)
case cntl('E'): /* invoke emacs on current command */
if(eol>=0 && sh.hist_ptr)
{
- if(blankline(ep,drawbuff))
+ if(blankline(ep,drawbuff,1))
{
cur = 0;
eol = 1;
@@ -1785,11 +1785,11 @@ static int _isword(int c)
/*
* determine if the command line is blank (empty or all whitespace)
*/
-static char blankline(Emacs_t *ep, genchar *out)
+static int blankline(Emacs_t *ep, genchar *out, int uptocursor)
{
int x;
ep->mark = cur;
- for(x=0; x < cur; x++)
+ for(x=0; uptocursor ? (x < cur) : (x <= eol); x++)
{
#if SHOPT_MULTIBYTE
if(!iswspace((wchar_t)out[x]))
diff --git a/src/cmd/ksh93/edit/vi.c b/src/cmd/ksh93/edit/vi.c
index fac40ee..852613c 100644
--- a/src/cmd/ksh93/edit/vi.c
+++ b/src/cmd/ksh93/edit/vi.c
@@ -176,7 +176,7 @@ typedef struct _vi_
static const char paren_chars[] = "([{)]}"; /* for % command */
-static char blankline(Vi_t*);
+static int blankline(Vi_t*, int);
static void cursor(Vi_t*, int);
static void del_line(Vi_t*,int);
static int getcount(Vi_t*,int);
@@ -667,9 +667,9 @@ static int cntlmode(Vi_t *vp)
}
#endif /* SHOPT_EDPREDICT */
/* skip blank lines when going up/down in history */
- if((c=='k' || c=='-') && curhline != histmin && blankline(vp))
+ if((c=='k' || c=='-') && curhline != histmin && blankline(vp,0))
ed_ungetchar(vp->ed,'k');
- else if((c=='j' || c=='+') && curhline != histmax && blankline(vp))
+ else if((c=='j' || c=='+') && curhline != histmax && blankline(vp,0))
ed_ungetchar(vp->ed,'j');
break;
@@ -693,7 +693,7 @@ static int cntlmode(Vi_t *vp)
case 'v':
if(vp->repeat_set==0)
{
- if(blankline(vp) || cur_virt == INVALID)
+ if(blankline(vp,1) || cur_virt == INVALID)
{
cur_virt = 0;
last_virt = cur_virt;
@@ -1294,7 +1294,7 @@ static void getline(Vi_t* vp,int mode)
case '\t': /** command completion **/
{
- if(blankline(vp))
+ if(blankline(vp,1))
{
ed_ringbell();
break;
@@ -2317,7 +2317,7 @@ addin:
case '\\': /** do file name completion in place **/
case '=': /** list file name expansions **/
{
- if(cur_virt == INVALID || blankline(vp))
+ if(cur_virt == INVALID || blankline(vp,1))
return BAD;
/* FALLTHROUGH */
save_v(vp);
@@ -2673,10 +2673,10 @@ yankeol:
/*
* determine if the command line is blank (empty or all whitespace)
*/
-static char blankline(Vi_t *vp)
+static int blankline(Vi_t *vp, int uptocursor)
{
int x;
- for(x=0; x <= cur_virt; x++)
+ for(x=0; x <= (uptocursor ? cur_virt : last_virt); x++)
{
#if SHOPT_MULTIBYTE
if(!iswspace((wchar_t)virtual[x]))
diff --git a/src/cmd/ksh93/tests/pty.sh b/src/cmd/ksh93/tests/pty.sh
index b4f8e28..ea0c616 100755
--- a/src/cmd/ksh93/tests/pty.sh
+++ b/src/cmd/ksh93/tests/pty.sh
@@ -1269,5 +1269,17 @@ w print Exit status $?
u ^Exit status 0\r\n$
!
+((SHOPT_VSH)) && tst $LINENO <<"!"
+L 'k' skips over history entries starting with whitespace
+# https://github.com/ksh93/ksh/issues/799
+
+d 40
+p :test-1:
+w true
+p :test-2:
+c \Ek
+r :test-2: true
+!
+
# ======
exit $((Errors<125?Errors:125))
--
2.49.0

View File

@ -0,0 +1,101 @@
From 685f18d36e162c6f6baf44e1c2c8c762ee41466d Mon Sep 17 00:00:00 2001
From: Vincent Mihalkovic <vmihalko@redhat.com>
Date: Sat, 13 Jul 2024 23:45:07 +0200
Subject: [PATCH] jobs: change p_job variable type from short to int (#763)
This change addresses an issue where ksh has undefined behavior
when the number of jobs exceeds `2^15 - 1` (32767), which is the
maximum value for a `short`. The short integer overflow happened in
jobs.c, line 1210.
---
src/cmd/ksh93/include/jobs.h | 5 +++--
src/cmd/ksh93/sh/jobs.c | 11 ++++++-----
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/cmd/ksh93/include/jobs.h b/src/cmd/ksh93/include/jobs.h
index 4ae48d70fb7a..758804118f30 100644
--- a/src/cmd/ksh93/include/jobs.h
+++ b/src/cmd/ksh93/include/jobs.h
@@ -2,7 +2,7 @@
* *
* This software is part of the ast package *
* Copyright (c) 1982-2011 AT&T Intellectual Property *
-* Copyright (c) 2020-2023 Contributors to ksh 93u+m *
+* Copyright (c) 2020-2024 Contributors to ksh 93u+m *
* and is licensed under the *
* Eclipse Public License, Version 2.0 *
* *
@@ -14,6 +14,7 @@
* Martijn Dekker <martijn@inlv.org> *
* Johnothan King <johnothanking@protonmail.com> *
* Anuradha Weeraman <anuradha@debian.org> *
+* Vincent Mihalkovic <vmihalko@redhat.com> *
* *
***********************************************************************/
#ifndef JOB_NFLAG
@@ -51,7 +52,7 @@ struct process
pid_t p_pid; /* process ID */
pid_t p_pgrp; /* process group */
pid_t p_fgrp; /* process group when stopped */
- short p_job; /* job number of process */
+ int p_job; /* job number of process */
unsigned short p_exit; /* exit value or signal number */
unsigned short p_exitmin; /* minimum exit value for xargs */
unsigned short p_flag; /* flags - see below */
diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c
index 871658256f15..86bbe5a9c949 100644
--- a/src/cmd/ksh93/sh/jobs.c
+++ b/src/cmd/ksh93/sh/jobs.c
@@ -13,6 +13,7 @@
* David Korn <dgk@research.att.com> *
* Martijn Dekker <martijn@inlv.org> *
* Johnothan King <johnothanking@protonmail.com> *
+* Vincent Mihalkovic <vmihalko@redhat.com> *
* *
***********************************************************************/
/*
@@ -437,7 +438,7 @@ int job_reap(int sig)
pw->p_flag &= ~P_NOTIFY;
if(job.jobcontrol && pid==pw->p_fgrp && pid==tcgetpgrp(JOBTTY))
{
- px = job_byjid((int)pw->p_job);
+ px = job_byjid(pw->p_job);
for(; px && (px->p_flag&P_DONE); px=px->p_nxtproc);
if(!px)
tcsetpgrp(JOBTTY,job.mypid);
@@ -1528,7 +1529,7 @@ int job_switch(struct process *pw,int bgflag)
{
const char *msg;
job_lock();
- if(!pw || !(pw=job_byjid((int)pw->p_job)))
+ if(!pw || !(pw=job_byjid(pw->p_job)))
{
job_unlock();
return 1;
@@ -1542,7 +1543,7 @@ int job_switch(struct process *pw,int bgflag)
}
if(bgflag=='b')
{
- sfprintf(outfile,"[%d]\t",(int)pw->p_job);
+ sfprintf(outfile,"[%d]\t",pw->p_job);
sh.bckpid = pw->p_pid;
pw->p_flag |= P_BG;
msg = "&";
@@ -1623,7 +1624,7 @@ static struct process *job_unpost(struct process *pwtop,int notify)
sfprintf(sfstderr,"ksh: job line %4d: drop PID=%lld critical=%d PID=%d env=%u\n",__LINE__,(Sflong_t)sh.current_pid,job.in_critical,pwtop->p_pid,pwtop->p_env);
sfsync(sfstderr);
#endif /* DEBUG */
- pwtop = pw = job_byjid((int)pwtop->p_job);
+ pwtop = pw = job_byjid(pwtop->p_job);
if(!pw)
return NULL;
#if SHOPT_BGX
@@ -1664,7 +1665,7 @@ static struct process *job_unpost(struct process *pwtop,int notify)
sfprintf(sfstderr,"ksh: job line %4d: free PID=%lld critical=%d job=%d\n",__LINE__,(Sflong_t)sh.current_pid,job.in_critical,pwtop->p_job);
sfsync(sfstderr);
#endif /* DEBUG */
- job_free((int)pwtop->p_job);
+ job_free(pwtop->p_job);
return NULL;
}

View File

@ -0,0 +1,38 @@
From bc56018765163a8059600f5205e9e2b1f4059873 Mon Sep 17 00:00:00 2001
From: Martijn Dekker <martijn@inlv.org>
Date: Sat, 20 Jul 2024 01:40:35 +0100
Subject: [PATCH] Re-fix SIGPIPE subshell regression (re: 227c6379, 4df6d674)
It was committed prematurely and still broken on most systems.
src/cmd/ksh93/sh/fault.c: sh_done():
- Revert changes.
src/cmd/ksh93/sh/jobs.c: job_wait():
- Do not set sh.chldexitsig in the first place if the signal is
SIGPIPE and we're in a real subshell.
This workaround passes all the tests I can throw at it.
Resolves: https://github.com/ksh93/ksh/issues/765
---
src/cmd/ksh93/sh/jobs.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c
index f8c4d5f..580dae0 100644
--- a/src/cmd/ksh93/sh/jobs.c
+++ b/src/cmd/ksh93/sh/jobs.c
@@ -1447,7 +1447,8 @@ int job_wait(pid_t pid)
if(px->p_flag&P_SIGNALLED)
{
sh.exitval |= SH_EXITSIG;
- sh.chldexitsig = 1;
+ if(!(sh.realsubshell && px->p_exit==SIGPIPE))
+ sh.chldexitsig = 1;
}
if(intr)
px->p_flag &= ~P_EXITSAVE;
--
2.50.0

View File

@ -0,0 +1,264 @@
From b533bc2feb9a1b58b9cdb3a9f5bc94f4ff060a84 Mon Sep 17 00:00:00 2001
From: Martijn Dekker <martijn@inlv.org>
Date: Fri, 28 Mar 2025 02:59:46 +0000
Subject: [PATCH] Fix segfault upon SIGWINCH after 'stty -echo' (re: 83630f9d)
After disabling terminal echo (stty -echo), ksh either crashes or
writes garbage to the terminal upon resizing the terminal window.
This also affects the use of ksh for 'M-x shell' in emacs.
Analysis: The ed_viread and ed_emacsread functions declare buffers
as local (automatic) variables that are destroyed when the function
exits, but other functions then access then using globally declared
pointers in structs of type Edit_t, Emacs_t and Vi_t.
However, upon 'stty -echo', the terminal cannot be set to raw mode,
so the tty_raw call fails in these two functions. At this point,
they fall back to ed_read and return, never initialising those
pointers. But the SIGWINCH handling routine in edit.c calls redraw
routines that depend on those pointers being valid -- and crash.
src/cmd/ksh93/edit/emacs.c: ed_emacsread():
- Attempt to set raw mode before doing or initialising anything
else: move the tty_raw call and ed_read fallback to the start.
This avoids superfluous init and makes more sense.
- Before returning, reset all global pointers that point to this
function call's local variables to NULL. (To aid with this, use a
'done' goto label and an 'r' variable for the return code.) This
ensures these pointers will be either valid or NULL, making
debugging easier, as well as allowing the code to check for this.
src/cmd/ksh93/edit/vi.c: ed_viread():
- Same changes as for emacs.
src/cmd/ksh93/edit/edit.c: ed_read():
- If e_prompt is NULL, that is now an indication that ed_emacsread
or ed_viread are not being used because the tty_raw call failed;
therefore, skip SIGWINCH handling, except for flushing the notify
buffer (see 667034ff). This fixes the crash.
Thanks to @nickpapadonis for the report.
Resolves: https://github.com/ksh93/ksh/issues/827
---
src/cmd/ksh93/edit/edit.c | 22 ++++++++++++++++++----
src/cmd/ksh93/edit/emacs.c | 27 ++++++++++++++++-----------
src/cmd/ksh93/edit/vi.c | 38 +++++++++++++++-----------------------
3 files changed, 49 insertions(+), 38 deletions(-)
diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c
index 1dcef1b..846c0d8 100644
--- a/src/cmd/ksh93/edit/edit.c
+++ b/src/cmd/ksh93/edit/edit.c
@@ -690,6 +690,16 @@ static void ed_nputchar(Edit_t *ep, int n, int c)
}
#endif /* SHOPT_ESH || SHOPT_VSH */
+/*
+ * Show any buffered 'set -b' job notification(s)
+ */
+static void flush_notifybuf(void)
+{
+ char *cp;
+ if(sh.notifybuf && (cp = sfstruse(sh.notifybuf)) && *cp)
+ sfputr(sfstderr, cp, -1);
+}
+
/*
* Do read, restart on interrupt unless SH_SIGSET or SH_SIGTRAP is set
* Use select(2) (via sfpkrd()) to wait for input if possible
@@ -729,7 +739,12 @@ int ed_read(void *context, int fd, char *buff, int size, int reedit)
if(sh.winch && sh_editor_active() && sh_isstate(SH_INTERACTIVE))
{
int n, newsize;
- char *cp;
+ if(!ep->e_prompt)
+ {
+ /* ed_emacsread or ed_viread was unable to put the tty in raw mode */
+ flush_notifybuf();
+ goto skipwinch;
+ }
sh_winsize(NULL,&newsize);
ed_putchar(ep,'\r');
/*
@@ -751,9 +766,7 @@ int ed_read(void *context, int fd, char *buff, int size, int reedit)
ed_putchar(ep,'\r');
}
ed_flush(ep);
- /* show any buffered 'set -b' job notification(s) */
- if(sh.notifybuf && (cp = sfstruse(sh.notifybuf)) && *cp)
- sfputr(sfstderr, cp, -1);
+ flush_notifybuf();
/* update window size */
ep->e_winsz = newsize-1;
if(ep->e_winsz < MINWINDOW)
@@ -777,6 +790,7 @@ int ed_read(void *context, int fd, char *buff, int size, int reedit)
emacs_redraw(ep->e_emacs);
#endif /* SHOPT_ESH && SHOPT_VSH */
}
+ skipwinch:
#endif /* SHOPT_ESH || SHOPT_VSH */
sh.winch = 0;
/* an interrupt that should be ignored */
diff --git a/src/cmd/ksh93/edit/emacs.c b/src/cmd/ksh93/edit/emacs.c
index 1dd6023..128e592 100644
--- a/src/cmd/ksh93/edit/emacs.c
+++ b/src/cmd/ksh93/edit/emacs.c
@@ -185,6 +185,7 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
Edit_t *ed = (Edit_t*)context;
int c;
int i;
+ int r = -1; /* return code */
genchar *out;
int count;
Emacs_t *ep = ed->e_emacs;
@@ -194,6 +195,10 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
genchar *kptr;
char prompt[PRSIZE];
genchar Screen[MAXLINE];
+ /* Set raw mode */
+ if(tty_raw(ERRIO,0) < 0)
+ return reedit ? reedit : ed_read(context, fd, buff, scend, 0);
+ /* Initialize some things */
memset(Screen,0,sizeof(Screen));
if(!ep)
{
@@ -206,10 +211,6 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
ep->screen = Screen;
ep->lastdraw = FINAL;
ep->ehist = 0;
- if(tty_raw(ERRIO,0) < 0)
- {
- return reedit ? reedit : ed_read(context,fd,buff,scend,0);
- }
raw = 1;
/* This mess in case the read system call fails */
ed_setup(ep->ed,fd,reedit);
@@ -240,6 +241,7 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
}
ep->in_mult = hloff; /* save pos in last command */
#endif /* ESH_NFIRST */
+ /* Handle user interrupt, user quit, or EOF */
i = sigsetjmp(env,0);
if (i !=0)
{
@@ -251,10 +253,8 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
}
tty_cooked(ERRIO);
if (i == UEOF)
- {
- return 0; /* EOF */
- }
- return -1; /* some other error */
+ r = 0; /* EOF */
+ goto done;
}
out[reedit] = 0;
if(scend+plen > (MAXLINE-2))
@@ -349,7 +349,8 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
case EOFCHAR:
ed_flush(ep->ed);
tty_cooked(ERRIO);
- return 0;
+ r = 0;
+ goto done;
#ifdef u370
case cntl('S') :
case cntl('Q') :
@@ -754,8 +755,12 @@ process:
#endif /* SHOPT_MULTIBYTE */
i = (int)strlen(buff);
if (i)
- return i;
- return -1;
+ r = i;
+done:
+ /* avoid leaving invalid pointers to destroyed automatic variables */
+ Prompt = NULL;
+ drawbuff = ep->screen = ep->cursor = NULL;
+ return r;
}
static void show_info(Emacs_t *ep,const char *str)
diff --git a/src/cmd/ksh93/edit/vi.c b/src/cmd/ksh93/edit/vi.c
index 0e878df..fac40ee 100644
--- a/src/cmd/ksh93/edit/vi.c
+++ b/src/cmd/ksh93/edit/vi.c
@@ -208,6 +208,7 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit)
{
Edit_t *ed = (Edit_t*)context;
int i; /* general variable */
+ int r = -1; /* return value */
int term_char=0; /* read() termination character */
Vi_t *vp = ed->e_vi;
char prompt[PRSIZE+2]; /* prompt */
@@ -218,6 +219,10 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit)
int Globals[9]; /* local global variables */
int esc_or_hang=0; /* <ESC> or hangup */
char cntl_char=0; /* TRUE if control character present */
+
+ if( tty_raw(ERRIO,0) < 0 )
+ return reedit ? reedit : ed_read(context, fd, shbuf, nchar, 0);
+
if(!vp)
{
ed->e_vi = vp = sh_newof(0,Vi_t,1,0);
@@ -232,16 +237,9 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit)
ed_setup(vp->ed,fd, reedit);
shbuf[reedit] = 0;
- {
- /*** Set raw mode ***/
-
- if(tty_raw(ERRIO,0) < 0 )
- return reedit ? reedit : ed_read(context, fd, shbuf, nchar,0);
- i = last_virt-1;
- }
-
/*** Initialize some things ***/
+ i = last_virt-1;
virtual = (genchar*)shbuf;
#if SHOPT_MULTIBYTE
virtual = (genchar*)roundof((char*)virtual-(char*)0,sizeof(genchar));
@@ -307,18 +305,9 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit)
}
virtual[0] = '\0';
tty_cooked(ERRIO);
-
- switch(i)
- {
- case UEOF:
- /*** EOF ***/
- return 0;
-
- case UINTR:
- /** interrupt **/
- return -1;
- }
- return -1;
+ if (i == UEOF)
+ r = 0; /* EOF */
+ goto done;
}
/*** Get a line from the terminal ***/
@@ -363,10 +352,13 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit)
if(vp->ed->nhlist)
ed_histlist(vp->ed,0);
#endif /* SHOPT_EDPREDICT */
- return last_virt;
+ r = last_virt;
}
- else
- return -1;
+done:
+ /* avoid leaving invalid pointers to destroyed automatic variables */
+ Prompt = NULL;
+ virtual = physical = window = vp->U_space = vp->u_space = NULL;
+ return r;
}
--
2.49.0

View File

@ -1,4 +1,4 @@
From e8554b5131fc32b26a6a0b0ab5cf24839e30161a Mon Sep 17 00:00:00 2001
From 4350174a5d4acabf78f97b28c6d0ae68ec703e78 Mon Sep 17 00:00:00 2001
From: Martijn Dekker <martijn@inlv.org>
Date: Sun, 30 Mar 2025 00:14:35 +0000
Subject: [PATCH] Fix 'stty -echo' in scripts (re: 41ebb55a)
@ -56,14 +56,14 @@ src/cmd/ksh93/sh/jobs.c: job_wait():
Resolves: https://github.com/ksh93/ksh/issues/836
---
src/cmd/ksh93/sh/jobs.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
src/cmd/ksh93/sh/jobs.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c
index be333b2..081e73a 100644
index c65bc6e66094..513afb5582ab 100644
--- a/src/cmd/ksh93/sh/jobs.c
+++ b/src/cmd/ksh93/sh/jobs.c
@@ -1492,9 +1492,9 @@ int job_wait(pid_t pid)
@@ -1420,9 +1420,9 @@ int job_wait(pid_t pid)
kill(sh.current_pid,SIGTSTP);
}
}
@ -75,6 +75,3 @@ index be333b2..081e73a 100644
{
if(pw->p_pgrp==0)
pw->p_pgrp = pw->p_pid;
--
2.47.3

View File

@ -0,0 +1,807 @@
From 970812e39c236ff385e440ac6d458d196c237667 Mon Sep 17 00:00:00 2001
From: Johnothan King <johnothanking@protonmail.com>
Date: Fri, 13 Jun 2025 16:29:15 -0700
Subject: [PATCH] Fix arbitrary command execution/code injection bugs (#866)
* Security patch part 1
Never use $SHELL or sh.shpath when executing shebang-less scripts
- sh_ntfork(): Removed a misguided optimization that causes ksh to
run scripts without a shebang using the binary pointed to by
either $SHELL or sh.shpath. This has a few problems:
- The shell in sh.shpath or more disastrously in $SHELL has
no guarantee of being identical to the currently running
copy of ksh93 or even existing at all, so using either is
not only bogus, but potentially dangerous.
- The optimization has no ability to pass down the current
POSIX mode status to the script.
- It's only activated for virtual subshells, resulting in
arbitrarily different behavior depending on whether or
not we're in a virtual subshell.
- It does some weird stuff with /dev/fd that seems superfluous,
and also lacks any SHOPT_DEVFD if directive. (Additionally,
if it did have one, that stat(2) would likely become mere
dead code and a waste of context switches.)
The optimization was probably intended to be used for running a
shebang-less script via posix_spawn, which is ostensibly faster
than fork. But this simply isn't possible without risking running
the shebang-less script in a shell environment different from
the current one. (If ksh were updated by the package manager
while ksh is still running, this optimization would cause the
script to run via the new version, rather than the currently
running older version.) The optimization is unfixable by design,
and as such must be removed to ensure correct behavior.
* Security patch part 2 (re: bae02c39)
rm setuid script code leading to arbitrary command execution
Changes:
- Delete code for setuid scripts on "Solaris 2.5+" because it
allows for arbitrary command execution. One millisecond you think
you're launching ksh, the next you're at the mercy of a hijacker.
Example:
SHELL=/bin/ppmflash /bin/ksh -l /dev/fd/0 < <(true)
MANPATH: usage: MANPATH flashfactor [ppmfile]
flashfactor: 0.0 = original picture, 1.0 = total whiteout
The pathshell() code doesn't *seem* to be vulnerable to privilege
escalation, but who knows (cf. CVE-2019-14868; this might need its
own CVE 2025. Maybe pathshell() should be scrapped entirely???)
- Add fickle but functional regression test (you may need to pass
KSH=/bin/ksh or some such to get it to fail against vulnerable
versions of ksh). The test uses a login shell via the -l option,
but the bug *does not* need a login shell. See:
https://github.com/ksh93/ksh/issues/874#issue-3128739066
Modify the execveat reproducer to pass along environ (which
could include a hijacked SHELL), and you're in for a BAD time.
Maybe the deleted code (introduced sometime within the period of 1995
and 1999) was relevant to some Solaris-specific use case or something.
Maybe the erasure even causes an incompatibility. But that code must
go; it's far too dangerous to execv whatever the hell pathshell gives
us during **init**. (Need I bring CVE-2019-14868 back to remembrance
again? This bug has similarities to that one.)
FWIW, all of the regression tests in the ksh and modernish suites pass
with this patch applied.
* Security patch part 3
Delete pathshell() and replace uses of it with safer equivalents
This function is a dangerous attack vector that ought not remain
in the code base. The value returned by astconf() is doubtless
safer than what is returned by pathshell().
* Other changes
The libast pathprog function and prog feature test are now unused,
and are removed.
---
src/cmd/ksh93/include/shell.h | 3 -
src/cmd/ksh93/sh/init.c | 33 +--------
src/cmd/ksh93/sh/main.c | 21 ------
src/cmd/ksh93/sh/path.c | 2 -
src/cmd/ksh93/sh/xec.c | 20 ------
src/cmd/ksh93/tests/basic.sh | 28 ++++++++
src/lib/libast/Mamfile | 29 +-------
src/lib/libast/comp/omitted.c | 2 +-
src/lib/libast/comp/system.c | 48 -------------
src/lib/libast/features/prog | 12 ----
src/lib/libast/include/ast.h | 2 -
src/lib/libast/man/compat.3 | 1 -
src/lib/libast/man/path.3 | 13 ----
src/lib/libast/man/proc.3 | 5 +-
src/lib/libast/misc/cmdarg.c | 2 +-
src/lib/libast/misc/procopen.c | 2 +-
src/lib/libast/path/pathprog.c | 124 --------------------------------
src/lib/libast/path/pathshell.c | 115 -----------------------------
18 files changed, 37 insertions(+), 425 deletions(-)
delete mode 100644 src/lib/libast/comp/system.c
delete mode 100644 src/lib/libast/features/prog
delete mode 100644 src/lib/libast/path/pathprog.c
delete mode 100644 src/lib/libast/path/pathshell.c
diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h
index 0613ceb..9a1b00e 100644
--- a/src/cmd/ksh93/include/shell.h
+++ b/src/cmd/ksh93/include/shell.h
@@ -213,8 +213,6 @@ struct sh_scoped
char **otrapcom; /* save parent EXIT and signals for v=$(trap) */
void *timetrap;
struct Ufunction *real_fun; /* current 'function name' function */
- int repl_index;
- char *repl_arg;
};
struct limits
@@ -255,7 +253,6 @@ struct Shell_s
Namval_t *bltin_nodes;
Namval_t *bltin_cmds;
History_t *hist_ptr;
- char *shpath;
char *user;
char **sigmsg;
char **login_files;
diff --git a/src/cmd/ksh93/sh/init.c b/src/cmd/ksh93/sh/init.c
index f4daaac..58c4e09 100644
--- a/src/cmd/ksh93/sh/init.c
+++ b/src/cmd/ksh93/sh/init.c
@@ -1355,33 +1355,6 @@ Shell_t *sh_init(int argc,char *argv[], Shinit_f userinit)
}
sh.shlvl++;
nv_offattr(SHLVL,NV_IMPORT);
-#if SHOPT_SPAWN
- {
- /*
- * try to find the pathname for this interpreter
- * try using environment variable _ or argv[0]
- */
- char *cp=nv_getval(L_ARGNOD);
- char buff[PATH_MAX+1];
- sh.shpath = 0;
- if((n = pathprog(NULL, buff, sizeof(buff))) > 0 && n <= sizeof(buff))
- sh.shpath = sh_strdup(buff);
- else if((cp && (sh_type(cp)&SH_TYPE_SH)) || (argc>0 && strchr(cp= *argv,'/')))
- {
- if(*cp=='/')
- sh.shpath = sh_strdup(cp);
- else if(cp = nv_getval(PWDNOD))
- {
- int offset = stktell(sh.stk);
- sfputr(sh.stk,cp,'/');
- sfputr(sh.stk,argv[0],-1);
- pathcanon(stkptr(sh.stk,offset),PATH_DOTDOT);
- sh.shpath = sh_strdup(stkptr(sh.stk,offset));
- stkseek(sh.stk,offset);
- }
- }
- }
-#endif
nv_putval(IFSNOD,(char*)e_sptbnl,NV_RDONLY);
astconfdisc(newconf);
#if SHOPT_TIMEOUT
@@ -1394,7 +1367,6 @@ Shell_t *sh_init(int argc,char *argv[], Shinit_f userinit)
#endif
if(argc>0)
{
- int dolv_index;
/* check for restricted shell */
if(type&SH_TYPE_RESTRICTED)
sh_onoption(SH_RESTRICTED);
@@ -1406,10 +1378,7 @@ Shell_t *sh_init(int argc,char *argv[], Shinit_f userinit)
sh_done(0);
}
opt_info.disc = 0;
- dolv_index = (argc - 1) - sh.st.dolc;
- sh.st.dolv = argv + dolv_index;
- sh.st.repl_index = dolv_index;
- sh.st.repl_arg = argv[dolv_index];
+ sh.st.dolv = argv + (argc - 1) - sh.st.dolc;
sh.st.dolv[0] = argv[0];
if(sh.st.dolc < 1)
{
diff --git a/src/cmd/ksh93/sh/main.c b/src/cmd/ksh93/sh/main.c
index 38ae366..712310e 100644
--- a/src/cmd/ksh93/sh/main.c
+++ b/src/cmd/ksh93/sh/main.c
@@ -247,33 +247,12 @@ int sh_main(int ac, char *av[], Shinit_f userinit)
/* open stream should have been passed into shell */
if(strmatch(name,e_devfdNN))
{
-#if !_WINIX
- char *cp;
- int type;
-#endif
fdin = (int)strtol(name+8, NULL, 10);
if(fstat(fdin,&statb)<0)
{
errormsg(SH_DICT,ERROR_system(1),e_open,name);
UNREACHABLE();
}
-#if !_WINIX
- /*
- * try to undo effect of Solaris 2.5+
- * change for argv for setuid scripts
- */
- if(sh.st.repl_index > 0)
- av[sh.st.repl_index] = sh.st.repl_arg;
- if(((type = sh_type(cp = av[0])) & SH_TYPE_SH) && (name = nv_getval(L_ARGNOD)) && (!((type = sh_type(cp = name)) & SH_TYPE_SH)))
- {
- av[0] = (type & SH_TYPE_LOGIN) ? cp : path_basename(cp);
- /* exec to change $0 for ps */
- execv(pathshell(),av);
- /* exec fails */
- sh.st.dolv[0] = av[0];
- fixargs(sh.st.dolv,1);
- }
-#endif
name = av[0];
sh_offoption(SH_VERBOSE);
sh_offoption(SH_XTRACE);
diff --git a/src/cmd/ksh93/sh/path.c b/src/cmd/ksh93/sh/path.c
index 85f44b5..7728df0 100644
--- a/src/cmd/ksh93/sh/path.c
+++ b/src/cmd/ksh93/sh/path.c
@@ -1195,8 +1195,6 @@ pid_t path_spawn(const char *opath,char **argv, char **envp, Pathcomp_t *libpath
errno = ENOEXEC;
if(spawn)
{
- if(sh.subshell)
- return -1;
do
{
if((pid=fork())>0)
diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c
index ca67142..003a93c 100644
--- a/src/cmd/ksh93/sh/xec.c
+++ b/src/cmd/ksh93/sh/xec.c
@@ -3417,26 +3417,6 @@ static pid_t sh_ntfork(const Shnode_t *t,char *argv[],int *jobid,int topfd)
job_fork(-1);
jobfork = 1;
spawnpid = path_spawn(path,argv,arge,pp,(grp<<1)|1);
- if(spawnpid < 0 && errno==ENOEXEC)
- {
- char *devfd;
- int fd = open(path,O_RDONLY);
- argv[-1] = argv[0];
- argv[0] = path;
- if(fd>=0)
- {
- struct stat statb;
- sfprintf(sh.strbuf,"/dev/fd/%d",fd);
- if(stat(devfd=sfstruse(sh.strbuf),&statb)>=0)
- argv[0] = devfd;
- }
- if(!sh.shpath)
- sh.shpath = pathshell();
- spawnpid = path_spawn(sh.shpath,&argv[-1],arge,pp,(grp<<1)|1);
- if(fd>=0)
- close(fd);
- argv[0] = argv[-1];
- }
fail:
if(jobfork && spawnpid<0)
job_fork(-2);
diff --git a/src/cmd/ksh93/tests/basic.sh b/src/cmd/ksh93/tests/basic.sh
index ea83b6b..0b02f7c 100755
--- a/src/cmd/ksh93/tests/basic.sh
+++ b/src/cmd/ksh93/tests/basic.sh
@@ -1019,5 +1019,33 @@ do
done
unset testcode
+# ======
+# Hijacking ksh93 via $SHELL for arbitrary command execution during initialization.
+# https://github.com/ksh93/ksh/issues/874
+bindir=$tmp/dir.$RANDOM/bin
+mkdir -p "$bindir"
+echo $'#!/bin/sh\necho "CODE INJECTION"' > "$bindir"/hijack_sh
+chmod +x "$bindir"/hijack_sh
+got=$(set +x; SHELL="$bindir"/hijack_sh "$SHELL" -l <(echo) 2>&1)
+[[ $got =~ "CODE INJECTION" ]] && err_exit 'ksh93 is vulnerable to being hijacked during init via $SHELL' \
+ "(got $(printf %q "$got"))"
+
+# Hijacking ksh93 shebang-less scripts for arbitrary command execution.
+# https://github.com/ksh93/ksh/pull/866
+export bindir
+print 'echo GOOD' > "$bindir/dummy.sh"
+chmod +x "$bindir/dummy.sh"
+cp "$SHELL" "$bindir/hijack_sh"
+exp=$'GOOD\nGOOD'
+got=$("$bindir/hijack_sh" -c $'print $\'\#!/bin/sh\necho HIJACKED\' > "$bindir/hijack_shell"
+chmod +x "$bindir/hijack_shell"
+rm "$bindir/hijack_sh"
+cp "$bindir/hijack_shell" "$bindir/hijack_sh"
+("$bindir/dummy.sh"); "$bindir/dummy.sh"; :')
+rm -r "$bindir"
+unset bindir
+[[ $exp == $got ]] || err_exit 'ksh93 shebang-less scripts are vulnerable to being hijacked for arbitrary code execution' \
+ "(exp $(printf %q "$exp"), got $(printf %q "$got"))"
+
# ======
exit $((Errors<125?Errors:125))
diff --git a/src/lib/libast/Mamfile b/src/lib/libast/Mamfile
index 0a35576..047ab0c 100644
--- a/src/lib/libast/Mamfile
+++ b/src/lib/libast/Mamfile
@@ -972,12 +972,6 @@ make install
done path/pathbin.c
exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c path/pathbin.c
done pathbin.o generated
- make pathshell.o
- make path/pathshell.c
- prev include/ast.h
- done path/pathshell.c
- exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c path/pathshell.c
- done pathshell.o generated
make pathcd.o
make path/pathcd.c
make include/stk.h implicit
@@ -988,17 +982,6 @@ make install
done path/pathcd.c
exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c path/pathcd.c
done pathcd.o generated
- make pathprog.o
- make path/pathprog.c
- make FEATURE/prog implicit
- prev features/prog
- exec - iffe ${IFFEFLAGS} -v -X ast -X std -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" run features/prog
- done FEATURE/prog generated
- prev include/ast_windows.h
- prev include/ast.h
- done path/pathprog.c
- exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c path/pathprog.c
- done pathprog.o generated
make ftwalk.o
make misc/ftwalk.c
make include/ftwalk.h implicit
@@ -2574,14 +2557,6 @@ make install
done comp/mount.c
exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c comp/mount.c
done mount.o generated
- make system.o
- make comp/system.c
- prev ast_map.h
- prev include/proc.h
- prev include/ast.h
- done comp/system.c
- exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c comp/system.c
- done system.o generated
make iblocks.o
make port/iblocks.c
prev include/ls.h
@@ -4425,9 +4400,9 @@ make install
exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c vmalloc/vmgetmem.c
done vmgetmem.o generated
exec - ${AR} rc libast.a state.o opendir.o readdir.o rewinddir.o seekdir.o telldir.o getcwd.o fastfind.o hashalloc.o hashdump.o hashfree.o hashlast.o hashlook.o hashscan.o hashsize.o hashview.o hashwalk.o memhash.o memsum.o strhash.o strkey.o strsum.o stracmp.o strnacmp.o ccmap.o ccmapid.o ccnative.o chresc.o chrtoi.o
- exec - ${AR} rc libast.a streval.o strexpr.o strmatch.o strcopy.o modei.o modex.o strmode.o strlcat.o strlcpy.o strlook.o strncopy.o strsearch.o strpsearch.o stresc.o stropt.o strtape.o strpcmp.o strnpcmp.o strvcmp.o strnvcmp.o tok.o tokline.o tokscan.o pathaccess.o pathcat.o pathcanon.o pathcheck.o pathpath.o pathexists.o pathfind.o pathicase.o pathkey.o pathprobe.o pathrepl.o pathnative.o pathposix.o pathtemp.o pathtmp.o pathstat.o pathgetlink.o pathsetlink.o pathbin.o pathshell.o pathcd.o pathprog.o ftwalk.o ftwflags.o fts.o astintercept.o conformance.o getenv.o setenviron.o optget.o optjoin.o optesc.o optctx.o strsort.o struniq.o magic.o mime.o mimetype.o signal.o sigflag.o systrace.o error.o errorf.o errormsg.o errorx.o localeconv.o setlocale.o translate.o catopen.o iconv.o lc.o lctab.o mc.o base64.o recfmt.o recstr.o reclen.o fmtrec.o fmtbase.o fmtbuf.o fmtclock.o fmtdev.o fmtelapsed.o fmterror.o fmtesc.o fmtfmt.o fmtfs.o fmtident.o fmtint.o fmtip4.o fmtip6.o fmtls.o fmtmatch.o fmtmode.o fmtnum.o fmtperm.o fmtre.o fmttime.o
+ exec - ${AR} rc libast.a streval.o strexpr.o strmatch.o strcopy.o modei.o modex.o strmode.o strlcat.o strlcpy.o strlook.o strncopy.o strsearch.o strpsearch.o stresc.o stropt.o strtape.o strpcmp.o strnpcmp.o strvcmp.o strnvcmp.o tok.o tokline.o tokscan.o pathaccess.o pathcat.o pathcanon.o pathcheck.o pathpath.o pathexists.o pathfind.o pathicase.o pathkey.o pathprobe.o pathrepl.o pathnative.o pathposix.o pathtemp.o pathtmp.o pathstat.o pathgetlink.o pathsetlink.o pathbin.o pathcd.o ftwalk.o ftwflags.o fts.o astintercept.o conformance.o getenv.o setenviron.o optget.o optjoin.o optesc.o optctx.o strsort.o struniq.o magic.o mime.o mimetype.o signal.o sigflag.o systrace.o error.o errorf.o errormsg.o errorx.o localeconv.o setlocale.o translate.o catopen.o iconv.o lc.o lctab.o mc.o base64.o recfmt.o recstr.o reclen.o fmtrec.o fmtbase.o fmtbuf.o fmtclock.o fmtdev.o fmtelapsed.o fmterror.o fmtesc.o fmtfmt.o fmtfs.o fmtident.o fmtint.o fmtip4.o fmtip6.o fmtls.o fmtmatch.o fmtmode.o fmtnum.o fmtperm.o fmtre.o fmttime.o
exec - ${AR} rc libast.a fmtuid.o fmtgid.o fmtsignal.o fmtscale.o fmttmx.o fmttv.o fmtversion.o strelapsed.o strperm.o struid.o strgid.o strtoip4.o strtoip6.o stack.o stk.o swapget.o swapmem.o swapop.o swapput.o sigdata.o sigcrit.o sigunblock.o procopen.o procclose.o procrun.o procfree.o tmdate.o tmequiv.o tmfix.o tmfmt.o tmform.o tmgoff.o tminit.o tmleap.o tmlex.o tmlocale.o tmmake.o tmpoff.o tmscan.o tmsleep.o tmtime.o tmtype.o tmweek.o tmword.o tmzone.o tmxdate.o tmxduration.o tmxfmt.o tmxgettime.o tmxleap.o tmxmake.o tmxscan.o tmxsettime.o tmxsleep.o tmxtime.o tmxtouch.o tvcmp.o tvgettime.o tvsettime.o tvsleep.o tvtouch.o cmdarg.o vecargs.o vecfile.o vecfree.o vecload.o vecstring.o univdata.o touch.o mnt.o debug.o memccpy.o memchr.o memcmp.o memcpy.o memdup.o memmove.o memset.o mkdir.o mkfifo.o mknod.o rmdir.o remove.o rename.o link.o unlink.o strdup.o strchr.o strrchr.o strstr.o strtod.o strtold.o strtol.o strtoll.o strtoul.o strtoull.o strton.o strtonll.o strntod.o strntold.o strnton.o
- exec - ${AR} rc libast.a strntonll.o strntol.o strntoll.o strntoul.o strntoull.o strcasecmp.o strncasecmp.o strerror.o mktemp.o tmpnam.o fsync.o execlp.o execve.o execvp.o execvpe.o spawnveg.o killpg.o getlogin.o putenv.o setenv.o unsetenv.o lstat.o statvfs.o eaccess.o gross.o omitted.o readlink.o symlink.o getpgrp.o setpgid.o setsid.o fcntl.o open.o atexit.o getdents.o getwd.o dup2.o errno.o getgroups.o mount.o system.o iblocks.o modedata.o tmdata.o memfatal.o sfkeyprintf.o sfdcdio.o sfdcdos.o sfdcfilter.o sfdcseekable.o sfdcslow.o sfdcsubstr.o sfdctee.o sfdcunion.o sfdcmore.o sfdcprefix.o wc.o wc2utf8.o basename.o closelog.o dirname.o fmtmsglib.o fnmatch.o ftw.o getdate.o getsubopt.o glob.o nftw.o openlog.o re_comp.o resolvepath.o realpath.o regcmp.o regexp.o setlogmask.o strftime.o strptime.o swab.o syslog.o tempnam.o wordexp.o mktime.o regalloc.o regclass.o regcoll.o regcomp.o regcache.o regdecomp.o regerror.o regexec.o regfatal.o reginit.o
+ exec - ${AR} rc libast.a strntonll.o strntol.o strntoll.o strntoul.o strntoull.o strcasecmp.o strncasecmp.o strerror.o mktemp.o tmpnam.o fsync.o execlp.o execve.o execvp.o execvpe.o spawnveg.o killpg.o getlogin.o putenv.o setenv.o unsetenv.o lstat.o statvfs.o eaccess.o gross.o omitted.o readlink.o symlink.o getpgrp.o setpgid.o setsid.o fcntl.o open.o atexit.o getdents.o getwd.o dup2.o errno.o getgroups.o mount.o iblocks.o modedata.o tmdata.o memfatal.o sfkeyprintf.o sfdcdio.o sfdcdos.o sfdcfilter.o sfdcseekable.o sfdcslow.o sfdcsubstr.o sfdctee.o sfdcunion.o sfdcmore.o sfdcprefix.o wc.o wc2utf8.o basename.o closelog.o dirname.o fmtmsglib.o fnmatch.o ftw.o getdate.o getsubopt.o glob.o nftw.o openlog.o re_comp.o resolvepath.o realpath.o regcmp.o regexp.o setlogmask.o strftime.o strptime.o swab.o syslog.o tempnam.o wordexp.o mktime.o regalloc.o regclass.o regcoll.o regcomp.o regcache.o regdecomp.o regerror.o regexec.o regfatal.o reginit.o
exec - ${AR} rc libast.a regnexec.o regsubcomp.o regsubexec.o regsub.o regrecord.o regrexec.o regstat.o dtclose.o dtdisc.o dthash.o dtlist.o dtmethod.o dtopen.o dtstat.o dtstrhash.o dttree.o dtuser.o dtview.o dtwalk.o dtnew.o dtcomp.o sfclose.o sfclrlock.o sfdisc.o sfdlen.o sfexcept.o sfgetl.o sfgetu.o sfcvt.o sfecvt.o sffcvt.o sfextern.o sffilbuf.o sfflsbuf.o sfprints.o sfgetd.o sfgetr.o sfllen.o sfmode.o sfmove.o sfnew.o sfpkrd.o sfnotify.o sfnputc.o sfopen.o sfpeek.o sfpoll.o sfpool.o sfpopen.o sfprintf.o sfputd.o sfputl.o sfputr.o sfputu.o sfrd.o sfread.o sfreserve.o sfscanf.o sfseek.o sfset.o sfsetbuf.o sfsetfd.o sfsize.o sfsk.o sfstack.o sfstrtod.o sfsync.o sfswap.o sftable.o sftell.o sftmp.o sfungetc.o sfvprintf.o sfvscanf.o sfwr.o sfwrite.o sfpurge.o sfraise.o sfwalk.o sfgetm.o sfputm.o sfresize.o _sfclrerr.o _sfeof.o _sferror.o _sffileno.o _sfopen.o _sfstacked.o _sfvalue.o _sfgetc.o _sfgetl.o _sfgetl2.o _sfgetu.o _sfgetu2.o _sfdlen.o _sfllen.o _sfslen.o _sfulen.o _sfputc.o _sfputd.o _sfputl.o _sfputm.o
exec - ${AR} rc libast.a _sfputu.o clearerr.o fclose.o fdopen.o fflush.o fgetc.o fgetpos.o fgets.o fopen.o fprintf.o fpurge.o fputs.o fread.o freopen.o fscanf.o fseek.o fseeko.o fsetpos.o ftell.o ftello.o fwrite.o getw.o pclose.o popen.o printf.o putchar.o puts.o putw.o rewind.o scanf.o setbuf.o setbuffer.o setlinebuf.o setvbuf.o snprintf.o sprintf.o sscanf.o asprintf.o vasprintf.o tmpfile.o ungetc.o vfprintf.o vfscanf.o vprintf.o vscanf.o vsnprintf.o vsprintf.o vsscanf.o _doprnt.o _doscan.o _filbuf.o _flsbuf.o _stdopen.o _stdprintf.o _stdscanf.o _stdsprnt.o _stdvbuf.o _stdvsnprnt.o _stdvsprnt.o _stdvsscn.o fgetwc.o fwprintf.o putwchar.o vfwscanf.o wprintf.o fgetws.o fwscanf.o swprintf.o vswprintf.o wscanf.o fputwc.o getwc.o swscanf.o vswscanf.o fputws.o getwchar.o ungetwc.o vwprintf.o fwide.o putwc.o vfwprintf.o vwscanf.o stdio_c99.o fcloseall.o fmemopen.o getdelim.o getline.o frexp.o frexpl.o astcopy.o
exec - ${AR} rc libast.a astconf.o astdynamic.o astquery.o astwinsize.o conftab.o aststatic.o getopt.o getoptl.o aso.o asolock.o asometh.o asorelax.o aso-sem.o aso-fcntl.o vmbest.o vmclear.o vmclose.o vmdcheap.o vmdebug.o vmdisc.o vmlast.o vmopen.o vmpool.o vmprivate.o vmprofile.o vmregion.o vmsegment.o vmset.o vmstat.o vmstrdup.o vmtrace.o vmwalk.o vmmopen.o malloc.o vmgetmem.o
diff --git a/src/lib/libast/comp/omitted.c b/src/lib/libast/comp/omitted.c
index 447990d..3631d39 100644
--- a/src/lib/libast/comp/omitted.c
+++ b/src/lib/libast/comp/omitted.c
@@ -504,7 +504,7 @@ runve(int mode, const char* path, char* const* argv, char* const* envv)
p = v;
*p++ = (char*)path;
*p++ = (char*)path;
- path = (const char*)pathshell();
+ path = "/bin/sh.exe";
if (*argv)
argv++;
while (*p++ = (char*)*argv++);
diff --git a/src/lib/libast/comp/system.c b/src/lib/libast/comp/system.c
deleted file mode 100644
index 64fa7e7..0000000
--- a/src/lib/libast/comp/system.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/***********************************************************************
-* *
-* This software is part of the ast package *
-* Copyright (c) 1985-2011 AT&T Intellectual Property *
-* Copyright (c) 2020-2023 Contributors to ksh 93u+m *
-* and is licensed under the *
-* Eclipse Public License, Version 2.0 *
-* *
-* A copy of the License is available at *
-* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html *
-* (with md5 checksum 84283fa8859daf213bdda5a9f8d1be1d) *
-* *
-* Glenn Fowler <gsf@research.att.com> *
-* David Korn <dgk@research.att.com> *
-* Phong Vo <kpv@research.att.com> *
-* Martijn Dekker <martijn@inlv.org> *
-* Johnothan King <johnothanking@protonmail.com> *
-* *
-***********************************************************************/
-/*
- * AST library system(3)
- */
-
-#define system ______system
-
-#define _STDLIB_H_ 1 /* UWIN workaround */
-
-#include <ast.h>
-#include <proc.h>
-
-#undef system
-
-#undef _def_map_ast
-#include <ast_map.h>
-
-extern int
-system(const char* cmd)
-{
- char* sh[4];
-
- if (!cmd)
- return !eaccess(pathshell(), X_OK);
- sh[0] = "sh";
- sh[1] = "-c";
- sh[2] = (char*)cmd;
- sh[3] = 0;
- return procrun(NULL, sh, 0);
-}
diff --git a/src/lib/libast/features/prog b/src/lib/libast/features/prog
deleted file mode 100644
index 365ce88..0000000
--- a/src/lib/libast/features/prog
+++ /dev/null
@@ -1,12 +0,0 @@
-lib getexecname,_NSGetExecutablePath
-
-tst run{
- for p in /proc/self/exe /proc/self/path/a.out
- do if test -e $p
- then echo "#define _PROC_PROG \"$p\""
- break
- fi
- done
-}end
-
-_hdr_macho_o_dyld = hdr mach-o/dyld
diff --git a/src/lib/libast/include/ast.h b/src/lib/libast/include/ast.h
index 5ec170b..6271677 100644
--- a/src/lib/libast/include/ast.h
+++ b/src/lib/libast/include/ast.h
@@ -373,11 +373,9 @@ extern char* pathpath_20100601(const char*, const char*, int, char*, size_t);
extern size_t pathposix(const char*, char*, size_t);
extern char* pathprobe(char*, char*, const char*, const char*, const char*, int);
extern char* pathprobe_20100601(const char*, const char*, const char*, int, char*, size_t, char*, size_t);
-extern size_t pathprog(const char*, char*, size_t);
extern char* pathrepl(char*, const char*, const char*);
extern char* pathrepl_20100601(char*, size_t, const char*, const char*);
extern int pathsetlink(const char*, const char*);
-extern char* pathshell(void);
extern char* pathtemp(char*, size_t, const char*, const char*, int*);
extern char* pathtmp(char*, const char*, const char*, int*);
extern char* setenviron(const char*);
diff --git a/src/lib/libast/man/compat.3 b/src/lib/libast/man/compat.3
index 7baf287..47c344f 100644
--- a/src/lib/libast/man/compat.3
+++ b/src/lib/libast/man/compat.3
@@ -77,7 +77,6 @@ double strtod(const char*, char**);
long strtol(const char*, char**, int);
int symlink(const char*, const char*);
long sysconf(int);
-int system(const char*);
char* tmpnam(char*);
int unlink(const char*);
int waitpid(pid_t, int*, int);
diff --git a/src/lib/libast/man/path.3 b/src/lib/libast/man/path.3
index 8060763..b9fdacf 100644
--- a/src/lib/libast/man/path.3
+++ b/src/lib/libast/man/path.3
@@ -57,7 +57,6 @@ char* pathpath(char* \fIpath\fP, const char* \fIp\fP, const char* \fIa\fP, i
char* pathprobe(char* \fIpath\fP, char* \fIattr\fP, const char* \fIlang\fP, const char* \fItool\fP, const char* \fIproc\fP, int \fIop\fP);
char* pathrepl(char* \fIpath\fP, const char* \fImatch\fP, const char* \fIreplace\fP);
int pathsetlink(const char* \fItext\fP, char* \fIname\fP);
-char* pathshell(void);
int pathstat(const char* \fIpath\fP, struct stat* \fIst\fP);
char* pathtemp(char* \fIpath\fP, const char* \fIdir\fP, const char* \fIpfx\fP);
.EE
@@ -361,18 +360,6 @@ above for weird
.IR universe (1)
interactions hidden by this routine.
.PP
-.L pathshell
-returns a pointer to the pathname for the shell for the current process.
-The
-.L SHELL
-environment variable is first consulted, but is rejected under suspicious
-ownership/setuid conditions of if it seems to point to
-.IR csh (1) ;
-otherwise
-.L confstr(_CS_SHELL,...)
-is used.
-A valid string is always returned.
-.PP
.L pathstat
first tries
.LI stat( path,st )
diff --git a/src/lib/libast/man/proc.3 b/src/lib/libast/man/proc.3
index a338130..9aa66e9 100644
--- a/src/lib/libast/man/proc.3
+++ b/src/lib/libast/man/proc.3
@@ -80,8 +80,9 @@ If
.I command
is
.L 0
-then the current shell is used (see
-.IR pathshell (3)).
+then the shell returned by
+.IR astconf (3)
+is used.
If
.I envv
is not
diff --git a/src/lib/libast/misc/cmdarg.c b/src/lib/libast/misc/cmdarg.c
index bb4a4e3..6f8b24f 100644
--- a/src/lib/libast/misc/cmdarg.c
+++ b/src/lib/libast/misc/cmdarg.c
@@ -128,7 +128,7 @@ cmdopen_20120411(char** argv, int argmax, int size, const char* argpat, Cmddisc_
x = ARG_MAX;
if (size <= 0 || size > x)
size = x;
- sh = pathshell();
+ sh = astconf("SH", NULL, NULL);
m = n + (argc + 4) * sizeof(char**) + strlen(sh) + 1;
m = roundof(m, sizeof(char**));
if (size < m)
diff --git a/src/lib/libast/misc/procopen.c b/src/lib/libast/misc/procopen.c
index 444f612..7482fcf 100644
--- a/src/lib/libast/misc/procopen.c
+++ b/src/lib/libast/misc/procopen.c
@@ -722,7 +722,7 @@ procopen(const char* cmd, char** argv, char** envv, long* modv, int flags)
*p = path;
*--p = "sh";
}
- strcpy(env + 2, (flags & PROC_PARANOID) ? astconf("SH", NULL, NULL) : pathshell());
+ strcpy(env + 2, astconf("SH", NULL, NULL));
if (forked || (flags & PROC_OVERLAY))
execve(env + 2, p, environ);
#if _use_spawnveg
diff --git a/src/lib/libast/path/pathprog.c b/src/lib/libast/path/pathprog.c
deleted file mode 100644
index 09a6148..0000000
--- a/src/lib/libast/path/pathprog.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/***********************************************************************
-* *
-* This software is part of the ast package *
-* Copyright (c) 1985-2012 AT&T Intellectual Property *
-* Copyright (c) 2020-2023 Contributors to ksh 93u+m *
-* and is licensed under the *
-* Eclipse Public License, Version 2.0 *
-* *
-* A copy of the License is available at *
-* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html *
-* (with md5 checksum 84283fa8859daf213bdda5a9f8d1be1d) *
-* *
-* Glenn Fowler <gsf@research.att.com> *
-* David Korn <dgk@research.att.com> *
-* Phong Vo <kpv@research.att.com> *
-* Martijn Dekker <martijn@inlv.org> *
-* *
-***********************************************************************/
-/*
- * Glenn Fowler
- * AT&T Research
- *
- * return the full path of the current program in path
- * command!=0 is used as a default
- */
-
-#include <ast.h>
-
-#if _WINIX
-#include <ast_windows.h>
-#include <ctype.h>
-#endif
-
-#include "FEATURE/prog"
-
-#if _hdr_macho_o_dyld && _lib__NSGetExecutablePath
-#include <mach-o/dyld.h>
-#else
-#undef _lib__NSGetExecutablePath
-#endif
-
-static size_t
-prog(const char* command, char* path, size_t size)
-{
- ssize_t n;
- char* s;
-#if _WINIX
- char* t;
- char* e;
- int c;
- int q;
-#endif
-#if _lib__NSGetExecutablePath
- uint32_t z;
-#endif
-
-#ifdef _PROC_PROG
- if ((n = readlink(_PROC_PROG, path, size)) > 0 && *path == '/')
- {
- if (n < size)
- path[n] = 0;
- return n;
- }
-#endif
-#if _lib_getexecname
- if ((s = (char*)getexecname()) && *s == '/')
- goto found;
-#endif
-#if _lib__NSGetExecutablePath
- z = size;
- if (!_NSGetExecutablePath(path, &z) && *path == '/')
- return strlen(path);
-#endif
-#if _WINIX
- if (s = GetCommandLine())
- {
- n = 0;
- q = 0;
- t = path;
- e = path + size - 1;
- while (c = *s++)
- {
- if (c == q)
- q = 0;
- else if (!q && c == '"')
- q = c;
- else if (!q && isspace(c))
- break;
- else if (t < e)
- *t++ = c == '\\' ? '/' : c;
- else
- n++;
- }
- if (t < e)
- *t = 0;
- return (t - path) + n;
- }
-#endif
- if (command)
- {
- s = (char*)command;
- goto found;
- }
- return 0;
- found:
- n = strlen(s);
- if (n < size)
- memcpy(path, s, n + 1);
- return n;
-}
-
-size_t
-pathprog(const char* command, char* path, size_t size)
-{
- char* rel;
- ssize_t n;
-
- if ((n = prog(command, path, size)) > 0 && n < size && *path != '/' && (rel = strdup(path)))
- {
- n = pathpath(rel, NULL, PATH_REGULAR|PATH_EXECUTE, path, size) ? strlen(path) : 0;
- free(rel);
- }
- return n;
-}
diff --git a/src/lib/libast/path/pathshell.c b/src/lib/libast/path/pathshell.c
deleted file mode 100644
index 7537c53..0000000
--- a/src/lib/libast/path/pathshell.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/***********************************************************************
-* *
-* This software is part of the ast package *
-* Copyright (c) 1985-2011 AT&T Intellectual Property *
-* Copyright (c) 2020-2023 Contributors to ksh 93u+m *
-* and is licensed under the *
-* Eclipse Public License, Version 2.0 *
-* *
-* A copy of the License is available at *
-* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html *
-* (with md5 checksum 84283fa8859daf213bdda5a9f8d1be1d) *
-* *
-* Glenn Fowler <gsf@research.att.com> *
-* David Korn <dgk@research.att.com> *
-* Phong Vo <kpv@research.att.com> *
-* Martijn Dekker <martijn@inlv.org> *
-* Johnothan King <johnothanking@protonmail.com> *
-* *
-***********************************************************************/
-/*
- * G. S. Fowler
- * D. G. Korn
- * AT&T Bell Laboratories
- *
- * shell library support
- */
-
-#include <ast.h>
-#include <sys/stat.h>
-
-/*
- * return pointer to the full path name of the shell
- *
- * SHELL is read from the environment and must start with /
- *
- * if setuid or setgid then the executable and its containing
- * directory must not be owned by the real user/group
- *
- * root/administrator has its own test
- *
- * astconf("SH",NULL,NULL) is returned by default
- *
- * NOTE: csh is rejected because the bsh/csh differentiation is
- * not done for `csh script arg ...'
- */
-
-#ifdef _WINIX
-# define EXE "?(.exe)"
-#else
-# define EXE
-#endif
-
-char*
-pathshell(void)
-{
- char* sh;
- int ru;
- int eu;
- int rg;
- int eg;
- struct stat st;
-
- static char* val;
-
- if ((sh = getenv("SHELL")) && *sh == '/' && strmatch(sh, "*/(sh|*[!cC]sh)*([[:digit:]])?(-+([.[:alnum:]]))" EXE))
- {
- if (!(ru = getuid()) || !eaccess("/bin", W_OK))
- {
- if (stat(sh, &st))
- goto defshell;
- if (ru != st.st_uid && !strmatch(sh, "?(/usr)?(/local)/?([ls])bin/?([[:lower:]])sh" EXE))
- goto defshell;
- }
- else
- {
- eu = geteuid();
- rg = getgid();
- eg = getegid();
- if (ru != eu || rg != eg)
- {
- char* s;
- char dir[PATH_MAX];
-
- s = sh;
- for (;;)
- {
- if (stat(s, &st))
- goto defshell;
- if (ru != eu && st.st_uid == ru)
- goto defshell;
- if (rg != eg && st.st_gid == rg)
- goto defshell;
- if (s != sh)
- break;
- if (strlen(s) >= sizeof(dir))
- goto defshell;
- strcpy(dir, s);
- if (!(s = strrchr(dir, '/')))
- break;
- *s = 0;
- s = dir;
- }
- }
- }
- return sh;
- }
- defshell:
- if (!(sh = val))
- {
- if (!*(sh = astconf("SH", NULL, NULL)) || *sh != '/' || eaccess(sh, X_OK) || !(sh = strdup(sh)))
- sh = "/bin/sh";
- val = sh;
- }
- return sh;
-}
--
2.50.1

View File

@ -0,0 +1,59 @@
From 26eec44e33ed4a48cb7ba34706d96387385d1980 Mon Sep 17 00:00:00 2001
From: Johnothan King <johnothanking@protonmail.com>
Date: Thu, 22 Feb 2024 15:26:57 -0800
Subject: [PATCH] Fix segfault on starting ksh with no TERM env var (#723)
This commit fixes a crash that prevented ksh from starting up in
single user mode on DragonFlyBSD and NetBSD.
src/cmd/ksh93/edit/edit.c:
- Make sure the np node for $TERM is not null before checking for
an export attribute.
Co-authored-by: Martijn Dekker <martijn@inlv.org>
Resolves: https://github.com/ksh93/ksh/issues/722
---
src/cmd/ksh93/edit/edit.c | 2 +-
src/cmd/ksh93/tests/pty.sh | 14 ++++++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c
index 32e1e83..0ac54ba 100644
--- a/src/cmd/ksh93/edit/edit.c
+++ b/src/cmd/ksh93/edit/edit.c
@@ -614,7 +614,7 @@ void ed_setup(Edit_t *ep, int fd, int reedit)
static char *oldterm;
Namval_t *np = nv_search("TERM",sh.var_tree,0);
char *term = NULL;
- if(nv_isattr(np,NV_EXPORT))
+ if(np && nv_isattr(np,NV_EXPORT))
term = nv_getval(np);
if(!term)
term = "";
diff --git a/src/cmd/ksh93/tests/pty.sh b/src/cmd/ksh93/tests/pty.sh
index 5dbdf6c..b4f8e28 100755
--- a/src/cmd/ksh93/tests/pty.sh
+++ b/src/cmd/ksh93/tests/pty.sh
@@ -1255,5 +1255,19 @@ w _ksh_93u_m_cmdcompl\t
r :test-2: _ksh_93u_m_cmdcomplete_test_ \r\n$
!
+((multiline && (SHOPT_VSH || SHOPT_ESH))) && TERM=vt100 tst $LINENO <<"!"
+L crash when TERM is undefined
+# https://github.com/ksh93/ksh/issues/722
+
+d 40
+p :test-1:
+w unset TERM
+p :test-2:
+w "$SHELL"
+p :test-3:
+w print Exit status $?
+u ^Exit status 0\r\n$
+!
+
# ======
exit $((Errors<125?Errors:125))
--
2.49.0

View File

@ -4,7 +4,7 @@ URL: http://www.kornshell.com/
License: EPL-1.0
Epoch: 3
Version: 1.0.6
Release: 7%{?dist}.2
Release: 14%{?dist}
Source0: https://github.com/ksh93/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz
Source1: kshcomp.conf
Source2: kshrc.rhs
@ -35,9 +35,30 @@ Patch6: ksh-1.0.11-SHLVL.patch
#upstream commit: https://github.com/ksh93/ksh/commit/5def43983de3ecfa38c805c02a1f0d6f1581160c
Patch7: ksh-1.0.11-redir.patch
#upstream commit: https://github.com/ksh93/ksh/commit/6668c3eb0bdc48335120e7c48590ab46af0ef0f3
Patch8: ksh-1.0.10-pjob.patch
#upstream commit: https://github.com/ksh93/ksh/commit/b15f63284bcd656729be61be6434376876be5bfc
#upstream commit: https://github.com/ksh93/ksh/commit/5e3a169785139809f1f733314f5660769c86d10c (test fix)
Patch9: ksh-1.0.9-no-TERM-env-segfault.patch
# upstream commit: https://github.com/ksh93/ksh/commit/4350174a5d4acabf78f97b28c6d0ae68ec703e78
Patch10: ksh-1.0.11-stty-noecho.patch
# upstream commit: https://github.com/ksh93/ksh/commit/96d73c08a2786806f3def1fda66641b81e0af988
Patch8: ksh-1.0.11-ssh-multibyte-long-paste.patch
Patch9: RHEL-112564.patch
Patch11: ksh-1.0.11-ssh-multibyte-long-paste.patch
# upstream commit: https://github.com/ksh93/ksh/commit/9f03b3bdb577ce74be3122d533c02830e3038e54
Patch12: ksh-1.0.11-segfault-sigwinch.patch
# upstream commit: https://github.com/ksh93/ksh/commit/a1fcad4bf65fe26a3f9a386b63732ab151ce03ec
Patch13: ksh-1.0.10-blankline.patch
# upstream commit: https://github.com/ksh93/ksh/commit/bc56018765163a8059600f5205e9e2b1f4059873
Patch14: ksh-1.0.10-sigpipe.patch
# https://github.com/ksh93/ksh/commit/970812e39c236ff385e440ac6d458d196c237667
Patch15: ksh-1.0.12-security.patch
Conflicts: pdksh
Requires: coreutils, diffutils
@ -160,13 +181,37 @@ fi
%config(noreplace) %{_sysconfdir}/binfmt.d/kshcomp.conf
%changelog
* Wed Oct 01 2025 RHEL Packaging Agent <jotnar@redhat.com> - 3:1.0.6-7.2
- Fix 'stty -echo' in scripts
- Resolves: RHEL-112564
* Wed Aug 06 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-14
- Fix arbitrary command execution/code injection bugs
Resolves: RHEL-99063
* Tue Apr 22 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-7
* Wed Jul 09 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-13
- Fix SIGPIPE subshell regression
Resolves: RHEL-92646
* Mon Jun 02 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-12
- Fix recalling lines starting with whitespace
Resolves: RHEL-74464
* Mon May 19 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-11
- Fix segfault upon SIGWINCH after 'stty -echo'
Resolves: RHEL-91097
* Wed Apr 16 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-10
- Fix long multibyte characters paste issue via ssh
Resolves: RHEL-87336
Resolves: RHEL-87561
* Mon Mar 31 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-9
- Fix 'stty -echo' in scripts
Resolves: RHEL-83043
* Sat Mar 29 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-8
- Fix segfault on starting ksh with no TERM env var
Resolves: RHEL-83283
* Mon Feb 17 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-7
- Change p_job variable type from short to int
Resolves: RHEL-64299
* Wed Jan 22 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-6
- Add forking workaround for block stdout redir