sh: accept fc options grouped behind one '-'

As per Utility Syntax Guidelines, accept both forms: -l -n and -ln.

To do that, anticipate the source string for the next option that will
be parsed by nextopt(). It's not always *argptr, sometimes it is
nextopt_optptr.

To simplify the check for not_fcnumber, slightly modify nextopt() to
always nullify nextopt_optptr in cases where it would have been set
to point to a NUL character.

Reviewed by:	jilles
Differential Revision:	https://reviews.freebsd.org/D35836
This commit is contained in:
Piotr Pawel Stefaniak 2022-08-20 12:15:05 +02:00
parent 497240def8
commit 755a1be6d0
6 changed files with 41 additions and 21 deletions

View File

@ -255,7 +255,6 @@ setterm(const char *term)
int
histcmd(int argc, char **argv __unused)
{
int ch;
const char *editor = NULL;
HistEvent he;
int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
@ -277,25 +276,29 @@ histcmd(int argc, char **argv __unused)
if (argc == 1)
error("missing history argument");
while (not_fcnumber(*argptr) && (ch = nextopt("e:lnrs")) != '\0')
switch ((char)ch) {
case 'e':
editor = shoptarg;
break;
case 'l':
lflg = 1;
break;
case 'n':
nflg = 1;
break;
case 'r':
rflg = 1;
break;
case 's':
sflg = 1;
break;
}
while (not_fcnumber(*argptr))
do {
switch (nextopt("e:lnrs")) {
case 'e':
editor = shoptarg;
break;
case 'l':
lflg = 1;
break;
case 'n':
nflg = 1;
break;
case 'r':
rflg = 1;
break;
case 's':
sflg = 1;
break;
case '\0':
goto operands;
}
} while (nextopt_optptr != NULL);
operands:
savehandler = handler;
/*
* If executing...

View File

@ -589,6 +589,9 @@ nextopt(const char *optstring)
shoptarg = p;
p = NULL;
}
nextopt_optptr = p;
if (p != NULL && *p != '\0')
nextopt_optptr = p;
else
nextopt_optptr = NULL;
return c;
}

View File

@ -94,6 +94,7 @@ ${PACKAGE}FILES+= exit3.0
${PACKAGE}FILES+= export1.0
${PACKAGE}FILES+= fc1.0
${PACKAGE}FILES+= fc2.0
${PACKAGE}FILES+= fc3.0 fc3.0.stdout fc3.0.stderr
${PACKAGE}FILES+= for1.0
${PACKAGE}FILES+= for2.0
${PACKAGE}FILES+= for3.0

View File

@ -0,0 +1,9 @@
export PS1='_ ' # cannot predict whether ran by root or not
echo ': command1
: command2
: command3
: command4
fc -l -n -1
fc -ln 2 3
' | ENV= HISTFILE=/dev/null ${SH} +m -i

View File

@ -0,0 +1 @@
_ _ _ _ _ _ _ _

View File

@ -0,0 +1,3 @@
: command4
: command2
: command3