Skip to content

Commit f423bd4

Browse files
committed
ksh -n: Fix spurious warning for --(no)backslashctrl
src/cmd/ksh93/sh/parse.c: simple(): - During noexec, use strmatch() to more precisely identify obsolete options passed to set(1). This fixes a bug where 'ksh -n' would falsely flag --nobackslashctrl as obsolete, and also allows for the detection of other obsolescent options besides just '-k'. Additionally, do this in a loop to check all of the options passed to set (rather than just the first option). - Also check for and warn against the obsolete 'alias -x' (ksh93 has never supported exported aliases). src/cmd/ksh93/{data/builtins.c,include/builtins.h,sh/shcomp.c}: - More clearly document which options to set(1) are obsolete. - Add SYSALIAS offset macro and use that instead of strcmp. - Do not compile in usage information for arrowkeysearch or backslashctrl if the editor modes are not compiled in.
1 parent 15b05e7 commit f423bd4

File tree

10 files changed

+84
-16
lines changed

10 files changed

+84
-16
lines changed

NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ This documents significant changes in the dev branch of ksh 93u+m.
22
For full details, see the git log at: https://github.com/ksh93/ksh
33
Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library.
44

5+
2025-07-14:
6+
7+
- Fixed a bug in 'ksh -n' that caused the shell to overlook many
8+
obsolete options passed to set(1) and alias(1) and incorrectly
9+
flag non-obsolete options as obsolete.
10+
511
2025-07-13:
612

713
- Fixed a bug in most UTF-8 locales that caused the editor modes to

src/cmd/ksh93/Mamfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ make install virtual
325325
done
326326

327327
make sh/shcomp.c
328+
prev include/builtins.h
328329
prev include/terminal.h
329330
prev include/shnodes.h
330331
prev include/path.h

src/cmd/ksh93/data/builtins.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ const struct shtable3 shtab_builtins[] =
7878
"source", NV_BLTIN|BLT_ENV, bltin(dot_cmd),
7979
"return", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(return),
8080
"enum", NV_BLTIN|BLT_ENV|BLT_DCL, bltin(enum),
81+
"alias", NV_BLTIN|BLT_ENV, bltin(alias),
8182
/*
8283
* Builtins without offset macros in include/builtins.h follow.
8384
*/
84-
"alias", NV_BLTIN|BLT_ENV, bltin(alias),
8585
"hash", NV_BLTIN|BLT_ENV, bltin(alias),
8686
"eval", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_EXIT,bltin(eval),
8787
"exit", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(return),
@@ -172,7 +172,7 @@ const char sh_set[] =
172172
"}"
173173
"[f?Pathname expansion is disabled.]"
174174
"[h?Obsolete; no effect.]"
175-
"[k?All arguments of the form \aname\a\b=\b\avalue\a "
175+
"[k?Obsolete. All arguments of the form \aname\a\b=\b\avalue\a "
176176
"are removed and placed in the variable assignment list for "
177177
"the command. Ordinarily, variable assignments must precede "
178178
"command arguments.]"
@@ -196,12 +196,14 @@ const char sh_set[] =
196196
"It must resolve to one of the following:]"
197197
"{"
198198
"[+allexport?Equivalent to \b-a\b.]"
199+
#if SHOPT_ESH || SHOPT_VSH
199200
"[+arrowkeysearch?The up and down arrow keys will do a "
200201
"reverse search based on the current line.]"
201202
"[+backslashctrl?The backslash character \b\\\b escapes the "
202203
"next control character in the \bemacs\b built-in "
203204
"editor and the next \aerase\a or \akill\a character "
204205
"in the \bvi\b built-in editor. On by default.]"
206+
#endif
205207
"[+bgnice?Runs background jobs at lower priorities.]"
206208
#if SHOPT_BRACEPAT
207209
"[+braceexpand?Equivalent to \b-B\b.] "
@@ -249,7 +251,7 @@ const char sh_set[] =
249251
"[+ignoreeof?Prevents an interactive shell from exiting on "
250252
"reading an end-of-file.]"
251253
#endif
252-
"[+keyword?Equivalent to \b-k\b.]"
254+
"[+keyword?Obsolete; equivalent to \b-k\b.]"
253255
"[+letoctal?The \blet\b builtin recognizes octal constants "
254256
"with leading 0.]"
255257
"[+markdirs?A trailing \b/\b is appended to directories "
@@ -272,7 +274,7 @@ const char sh_set[] =
272274
"[+privileged?Equivalent to \b-p\b.]"
273275
"[+showme?Simple commands preceded by a \b;\b will be traced "
274276
"as if \b-x\b were enabled but not executed.]"
275-
"[+trackall?Equivalent to \b-h\b.]"
277+
"[+trackall?Obsolete; equivalent to \b-h\b (no effect).]"
276278
"[+unset?Opposite of \b-u\b.]"
277279
"[+verbose?Equivalent to \b-v\b.]"
278280
#if SHOPT_VSH
@@ -1663,7 +1665,7 @@ const char sh_optksh[] =
16631665
"[+SEE ALSO?\bset\b(1), \bbuiltin\b(1)]"
16641666
;
16651667
const char sh_optset[] =
1666-
"+[-1c?\n@(#)$Id: set (ksh 93u+m) 2023-05-18 $\n]"
1668+
"+[-1c?\n@(#)$Id: set (ksh 93u+m) 2025-07-14 $\n]"
16671669
"[--catalog?" SH_DICT "]"
16681670
"[+NAME?set - set/unset options and positional parameters]"
16691671
"[+DESCRIPTION?\bset\b sets or unsets options and positional parameters. "

src/cmd/ksh93/data/lexstates.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,8 +749,10 @@ const char e_lexobsolete1[] = "line %d: `...` obsolete, use $(...)";
749749
const char e_lexobsolete2[] = "line %d: -a obsolete, use -e";
750750
const char e_lexobsolete3[] = "line %d: '=' obsolete, use '=='";
751751
const char e_lexobsolete4[] = "line %d: [[ ... %s ... ]] obsolete, use ((... %s ...))";
752-
const char e_lexobsolete5[] = "line %d: set %s obsolete";
752+
const char e_lexobsolete5[] = "line %d: 'set %s' obsolete";
753753
const char e_lexobsolete6[] = "line %d: `{' instead of `in' is obsolete";
754+
const char e_lexobsolete7[] = "line %d: 'set %s %s' is obsolete";
755+
const char e_lexobsolete8[] = "line %d: 'alias %s' is obsolete";
754756
const char e_lexusebrace[] = "line %d: use braces to avoid ambiguities with $id[...]";
755757
const char e_lexescape[] = "line %d: escape %c to avoid ambiguities";
756758
const char e_lexquote[] = "line %d: quote %c to avoid ambiguities";

src/cmd/ksh93/include/builtins.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#define SYSSOURCE (sh.bltin_cmds+21) /* source */
5656
#define SYSRETURN (sh.bltin_cmds+22) /* return */
5757
#define SYSENUM (sh.bltin_cmds+23) /* enum */
58+
#define SYSALIAS (sh.bltin_cmds+24) /* alias */
5859

5960
/* entry point for shell special builtins */
6061

src/cmd/ksh93/include/lexstates.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ extern const char e_lexobsolete3[];
147147
extern const char e_lexobsolete4[];
148148
extern const char e_lexobsolete5[];
149149
extern const char e_lexobsolete6[];
150+
extern const char e_lexobsolete7[];
151+
extern const char e_lexobsolete8[];
150152
extern const char e_lexusebrace[];
151153
extern const char e_lexescape[];
152154
extern const char e_lexquote[];

src/cmd/ksh93/include/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include <ast_release.h>
1919
#include "git.h"
2020

21-
#define SH_RELEASE_DATE "2025-07-13" /* must be in this format for $((.sh.version)) */
21+
#define SH_RELEASE_DATE "2025-07-14" /* must be in this format for $((.sh.version)) */
2222
/*
2323
* This comment keeps SH_RELEASE_DATE a few lines away from SH_RELEASE_SVER to avoid
2424
* merge conflicts when cherry-picking dev branch commits onto a release branch.

src/cmd/ksh93/sh/parse.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,7 +1421,7 @@ static struct argnod *process_sub(Lex_t *lexp,int tok)
14211421
static Shnode_t *simple(Lex_t *lexp,nvflag_t flag, struct ionod *io)
14221422
{
14231423
struct comnod *t;
1424-
struct argnod *argp;
1424+
struct argnod *argp, *ap;
14251425
int tok;
14261426
struct argnod **argtail;
14271427
struct argnod **settail;
@@ -1464,7 +1464,7 @@ static Shnode_t *simple(Lex_t *lexp,nvflag_t flag, struct ionod *io)
14641464
lexp->assignok = (flag&SH_ASSIGN)?SH_ASSIGN:1;
14651465
if(assignment)
14661466
{
1467-
struct argnod *ap=argp;
1467+
ap=argp;
14681468
if(assignment==1)
14691469
{
14701470
stkseek(sh.stk,ARGVAL);
@@ -1542,7 +1542,6 @@ static Shnode_t *simple(Lex_t *lexp,nvflag_t flag, struct ionod *io)
15421542
type = NV_COMVAR;
15431543
else if((Namval_t*)t->comnamp >= SYSTYPESET && (Namval_t*)t->comnamp <= SYSTYPESET_END)
15441544
{
1545-
struct argnod *ap;
15461545
for(ap = t->comarg.ap->argnxt.ap; ap; ap = ap->argnxt.ap)
15471546
{
15481547
if(*ap->argval!='-')
@@ -1630,11 +1629,30 @@ static Shnode_t *simple(Lex_t *lexp,nvflag_t flag, struct ionod *io)
16301629
}
16311630
}
16321631
#endif /* SHOPT_KIA */
1633-
/* noexec: warn about set - and set -k */
1634-
if(sh_isoption(SH_NOEXEC) && t->comnamp && (argp = t->comarg.ap->argnxt.ap)
1635-
&& (Namval_t*)t->comnamp==SYSSET && ((tok = *argp->argval)=='-' || tok=='+')
1636-
&& (argp->argval[1]==0 || strchr(argp->argval,'k')))
1637-
errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete5,sh.inlineno-(lexp->token=='\n'),argp->argval);
1632+
/* noexec: warn about obsolescent options passed to set and alias */
1633+
if(sh_isoption(SH_NOEXEC) && t->comnamp)
1634+
{
1635+
int lineno = sh.inlineno - (lexp->token == NL);
1636+
if((Namval_t*)t->comnamp==SYSSET)
1637+
{
1638+
char *prev_argval = NULL;
1639+
for(ap = t->comarg.ap->argnxt.ap; ap; ap = ap->argnxt.ap)
1640+
{
1641+
if(strmatch(ap->argval,"(*eyword|*og|*rackall|*iraw)|([+-][^-]*[hkt]*)|([+-][hkt]*)|([+-])"))
1642+
{
1643+
if(strmatch(prev_argval,"[+-]o"))
1644+
errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete7,lineno,prev_argval,ap->argval);
1645+
else
1646+
errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete5,lineno,ap->argval);
1647+
}
1648+
prev_argval = ap->argval;
1649+
}
1650+
}
1651+
else if((Namval_t*)t->comnamp==SYSALIAS)
1652+
for(ap = t->comarg.ap->argnxt.ap; ap; ap = ap->argnxt.ap)
1653+
if(strmatch(ap->argval, "-*x*"))
1654+
errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete8,lineno,ap->argval);
1655+
}
16381656
/* expand argument list if possible */
16391657
if(argno>0 && !(flag&(SH_ARRAY|NV_APPEND)))
16401658
t->comarg.ap = qscan(t,argno);

src/cmd/ksh93/sh/shcomp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ static const char usage[] =
7373
#include "shnodes.h"
7474
#include "sys/stat.h"
7575
#include "terminal.h"
76+
#include "builtins.h"
7677

7778
#define CNTL(x) ((x)&037)
7879
static const char header[6] = { CNTL('k'),CNTL('s'),CNTL('h'),0,SHCOMP_HDR_VERSION,0 };
@@ -172,7 +173,7 @@ int main(int argc, char *argv[])
172173
stkset(sh.stk,NULL,0);
173174
if(t = (Shnode_t*)sh_parse(in,0))
174175
{
175-
if((t->tre.tretyp&(COMMSK|COMSCAN))==0 && t->com.comnamp && strcmp(nv_name((Namval_t*)t->com.comnamp),"alias")==0)
176+
if((t->tre.tretyp&(COMMSK|COMSCAN))==0 && t->com.comnamp && (Namval_t*)t->com.comnamp==SYSALIAS)
176177
/* Create aliases found in the script to prevent syntax errors */
177178
sh_exec(t,0);
178179
if(!dflag && sh_tdump(out,t) < 0)

src/cmd/ksh93/tests/options.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,41 @@ exp=$'+ true\n+ 1> /dev/null 2>& 1 3>& 1 4>& 3'
679679
got=$(set --pipefail; "$SHELL" -c 'kill -s PIPE $$' | true; echo $?)
680680
exp=$(( ${ kill -l PIPE; } + 256 ))
681681
[[ $got == "$exp" ]] || err_exit "status of signalled process in pipe with pipefail (expected $exp, got $got)"
682+
unset exp got
683+
684+
# ======
685+
# ksh -n should flag all obsolete set(1) and alias(1) arguments
686+
if((SHOPT_VSH)); then
687+
script=$tmp/setscr.$RANDOM.ksh
688+
echo 'set -k -n +t # Obsolete
689+
set --keyword # Obsolete
690+
set --log # Obsolete
691+
set -tn # Obsolete
692+
set --nobackslashctrl # Current
693+
set --trackall # Obsolete
694+
set -be # Current
695+
set --errexit --nolog # Obsolete
696+
set -o keyword # Obsolete
697+
set -o backslashctrl -v # Current
698+
set -o backslashctrl -h # Obsolete
699+
set -o viraw -m # Obsolete
700+
set +o nokeyword +h # Obsolete
701+
alias -x foo # Obsolete
702+
alias -pt -tx # Obsolete
703+
alias -p # Current
704+
alias -t -pxt -xp # Obsolete
705+
set -eku # Obsolete
706+
set -ebku # Obsolete
707+
set -o posix -emu # Current
708+
set - # Obsolete
709+
set + # Obsolete
710+
set -- # Current' > "$script"
711+
exp=20
712+
got=($(wc -l <(set +x; "$SHELL" -n "$script" 2>&1)))
713+
[[ ${got[0]} -eq $exp ]] || err_exit "ksh -n is not flagging all instances of obsolete options to set and alias" \
714+
"(expected $exp warnings, got ${got[0]} warnings)"
715+
unset script exp got
716+
fi
682717

683718
# ======
684719
exit $((Errors<125?Errors:125))

0 commit comments

Comments
 (0)