1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Fix multiple problems with the getconf builtin (#280)

This commit fixes three problems with getconf pathbound builtin:
1. The -l/--lowercase option did not change all variable names to
   lower case.
2. The -q/--quote option now quotes all string values. Previously,
   it only quoted string values that had a space or other
   non-shellsafe character.
3. The -c/--call, -n/--name and -s/--standard options matched all
   variable names provided by 'getconf -a', even if none were
   actual matches.

Additionally, references to the confstr and sysconf functions have
been updated to reference section 3 of the man pages instead of
section 2.

src/lib/libast/port/astconf.c:
- Previously, only values that had spaces in them were quoted. Change
  that behavior to quote all string values by using the FMT_ALWAYS
  flag. Bug report: https://github.com/att/ast/issues/1173
- Not all variable names were printed in lowercase by 'getconf -l'.
  Fix it by adding a few missing instances of fmtlower.
  Bug report: https://github.com/att/ast/issues/1171
- Add the missing code to the '#if _pth_getconf_a' block to handle
  -c/-n/-s while parsing the OS's native 'getconf -a' output. This
  approach reuses code for name matching from other parts of
  astconflist(). Resolves: https://github.com/ksh93/ksh/issues/279

src/lib/libcmd/getconf.c:
- Update the documentation to note the -q flag only quotes strings.

src/cmd/ksh93/tests/bulitins.sh:
- Add regression tests for the getconf bugs fixed in this commit.

Co-authored-by: Martijn Dekker <martijn@inlv.org>
This commit is contained in:
Johnothan King 2021-04-20 19:34:54 -07:00 committed by GitHub
parent 61e0f90460
commit f28bce61a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 76 additions and 22 deletions

9
NEWS
View file

@ -3,6 +3,15 @@ For full details, see the git log at: https://github.com/ksh93/ksh
Any uppercase BUG_* names are modernish shell bug IDs. Any uppercase BUG_* names are modernish shell bug IDs.
2021-04-20:
- Fixed three problems with the /opt/ast/bin/getconf built-in command:
1. The -l/--lowercase option did not change all variable names to lower case.
2. The -q/--quote option now quotes all string values. Previously, it only
quoted string values that had a space or other non-shellsafe character.
3. The -c/--call, -n/--name and -s/--standard options matched all variable
names provided by 'getconf -a', even if none were actual matches.
2021-04-16: 2021-04-16:
- Fixed a bug in emacs mode: after using tab completion to complete the name - Fixed a bug in emacs mode: after using tab completion to complete the name

View file

@ -20,7 +20,7 @@
#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */ #define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
#define SH_RELEASE_SVER "1.0.0-alpha" /* semantic version number: https://semver.org */ #define SH_RELEASE_SVER "1.0.0-alpha" /* semantic version number: https://semver.org */
#define SH_RELEASE_DATE "2021-04-16" /* must be in this format for $((.sh.version)) */ #define SH_RELEASE_DATE "2021-04-20" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_CPYR "(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK #define SH_RELEASE_CPYR "(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */ /* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */

View file

@ -22,8 +22,34 @@
bincat=$(whence -p cat) bincat=$(whence -p cat)
# test shell builtin commands # ======
# These are regression tests for the getconf builtin.
builtin getconf builtin getconf
bingetconf=$(getconf GETCONF)
bad_result=$(getconf --version 2>&1)
# The -l option should convert all variable names to lowercase.
# https://github.com/att/ast/issues/1171
got=$(getconf -l | awk '{ gsub(/=.*/, "") } /[[:upper:]]/ { print }')
[[ -n $got ]] && err_exit "'getconf -l' doesn't convert all variable names to lowercase" \
"(got $(printf %q "$got"))"
# The -q option should quote all string values.
# https://github.com/att/ast/issues/1173
exp="GETCONF=\"$bingetconf\""
got=$(getconf -q | grep 'GETCONF=')
[[ $exp == "$got" ]] || err_exit "'getconf -q' fails to quote string values" \
"(expected $exp, got $got)"
# The -n option should only return matching names.
# https://github.com/ksh93/ksh/issues/279
exp="GETCONF=$bingetconf"
got=$(getconf -n GETCONF)
[[ $exp == "$got" ]] || err_exit "'getconf -n' doesn't match names correctly" \
"(expected $exp, got $got)"
# ======
# Test shell builtin commands
: ${foo=bar} || err_exit ": failed" : ${foo=bar} || err_exit ": failed"
[[ $foo == bar ]] || err_exit ": side effects failed" [[ $foo == bar ]] || err_exit ": side effects failed"
set -- - foobar set -- - foobar

View file

@ -367,7 +367,7 @@ IFS=$ifs; set +f
export CONF_getconf CONF_getconf_a export CONF_getconf CONF_getconf_a
case $verbose in case $verbose in
1) echo "$command: check ${CONF_getconf:+$CONF_getconf(1),}confstr(2),pathconf(2),sysconf(2),sysinfo(2) configuration names" >&2 ;; 1) echo "$command: check ${CONF_getconf:+$CONF_getconf(1),}confstr(3),pathconf(2),sysconf(3),sysinfo(2) configuration names" >&2 ;;
esac esac
{ {
echo "#include <unistd.h>$systeminfo echo "#include <unistd.h>$systeminfo

View file

@ -52,10 +52,10 @@ int astquery(int \fIfd\fP, const char* \fIformat\fP , ...);
.SH DESCRIPTION .SH DESCRIPTION
.L astconf .L astconf
is a string interface to the is a string interface to the
.IR confstr (2), .IR confstr (3),
.IR pathconf (2), .IR pathconf (2),
and and
.IR sysconf (2) .IR sysconf (3)
calls. calls.
If If
.I value .I value
@ -269,4 +269,4 @@ and the environment variable
is used to set is used to set
.IR *cols . .IR *cols .
.SH "SEE ALSO" .SH "SEE ALSO"
getconf(1), confstr(2), mmap(2), pathconf(2), read(2), sysconf(2), write(2) getconf(1), confstr(3), mmap(2), pathconf(2), read(2), sysconf(3), write(2)

View file

@ -1251,14 +1251,14 @@ print(Sfio_t* sp, register Lookup_t* look, const char* name, const char* path, i
if (p->flags & CONF_LIMIT_DEF) if (p->flags & CONF_LIMIT_DEF)
{ {
if (p->limit.string) if (p->limit.string)
sfprintf(sp, "L[%s] ", (listflags & ASTCONF_quote) ? fmtquote(p->limit.string, "\"", "\"", strlen(p->limit.string), FMT_SHELL) : p->limit.string); sfprintf(sp, "L[%s] ", (listflags & ASTCONF_quote) ? fmtquote(p->limit.string, "\"", "\"", strlen(p->limit.string), FMT_SHELL|FMT_ALWAYS) : p->limit.string);
else else
sfprintf(sp, "L[%I*d] ", sizeof(p->limit.number), p->limit.number); sfprintf(sp, "L[%I*d] ", sizeof(p->limit.number), p->limit.number);
} }
if (p->flags & CONF_MINMAX_DEF) if (p->flags & CONF_MINMAX_DEF)
{ {
if (p->minmax.string) if (p->minmax.string)
sfprintf(sp, "M[%s] ", (listflags & ASTCONF_quote) ? fmtquote(p->minmax.string, "\"", "\"", strlen(p->minmax.string), FMT_SHELL) : p->minmax.string); sfprintf(sp, "M[%s] ", (listflags & ASTCONF_quote) ? fmtquote(p->minmax.string, "\"", "\"", strlen(p->minmax.string), FMT_SHELL|FMT_ALWAYS) : p->minmax.string);
else else
sfprintf(sp, "M[%I*d] ", sizeof(p->minmax.number), p->minmax.number); sfprintf(sp, "M[%I*d] ", sizeof(p->minmax.number), p->minmax.number);
} }
@ -1267,7 +1267,7 @@ print(Sfio_t* sp, register Lookup_t* look, const char* name, const char* path, i
else if (defined) else if (defined)
{ {
if (s) if (s)
sfprintf(sp, "%s", (listflags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s); sfprintf(sp, "%s", (listflags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL|FMT_ALWAYS) : s);
else if (v != -1) else if (v != -1)
sfprintf(sp, "%I*d", sizeof(v), v); sfprintf(sp, "%I*d", sizeof(v), v);
else else
@ -1297,7 +1297,7 @@ print(Sfio_t* sp, register Lookup_t* look, const char* name, const char* path, i
else if (defined) else if (defined)
{ {
if (s) if (s)
sfprintf(sp, "%s", (listflags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s); sfprintf(sp, "%s", (listflags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL|FMT_ALWAYS) : s);
else if (v != -1) else if (v != -1)
sfprintf(sp, "%I*d", sizeof(v), v); sfprintf(sp, "%I*d", sizeof(v), v);
else else
@ -1636,6 +1636,25 @@ astconflist(Sfio_t* sp, const char* path, int flags, const char* pattern)
for (*s++ = 0; isspace(*s); s++); for (*s++ = 0; isspace(*s); s++);
if (!lookup(&look, f, flags)) if (!lookup(&look, f, flags))
{ {
if(pattern)
{
if (flags & ASTCONF_matchcall)
{
if (regexec(&re, prefix[look.conf->call + CONF_call].name, 0, NiL, 0))
continue;
}
else if (flags & ASTCONF_matchname)
{
if (regexec(&re, f, 0, NiL, 0))
continue;
}
else if (flags & ASTCONF_matchstandard)
{
if (regexec(&re, prefix[look.standard].name, 0, NiL, 0))
continue;
}
}
if (flags & ASTCONF_table) if (flags & ASTCONF_table)
{ {
if (look.standard < 0) if (look.standard < 0)
@ -1645,9 +1664,9 @@ astconflist(Sfio_t* sp, const char* path, int flags, const char* pattern)
sfprintf(sp, "%*s %*s %d %2s %4d %5s %s\n", sizeof(conf[0].name), f, sizeof(prefix[look.standard].name), prefix[look.standard].name, look.section, call, 0, "N", s); sfprintf(sp, "%*s %*s %d %2s %4d %5s %s\n", sizeof(conf[0].name), f, sizeof(prefix[look.standard].name), prefix[look.standard].name, look.section, call, 0, "N", s);
} }
else if (flags & ASTCONF_parse) else if (flags & ASTCONF_parse)
sfprintf(sp, "%s %s - %s\n", state.id, f, s); sfprintf(sp, "%s %s - %s\n", state.id, (flags & ASTCONF_lower) ? fmtlower(f) : f, fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL|FMT_ALWAYS));
else else
sfprintf(sp, "%s=%s\n", f, (flags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s); sfprintf(sp, "%s=%s\n", (flags & ASTCONF_lower) ? fmtlower(f) : f, (flags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL|FMT_ALWAYS) : s);
} }
} }
sfclose(pp); sfclose(pp);
@ -1693,9 +1712,9 @@ astconflist(Sfio_t* sp, const char* path, int flags, const char* pattern)
sfprintf(sp, "%*s %*s %d %2s %4d %5s %s\n", sizeof(conf[0].name), fp->name, sizeof(prefix[fp->standard].name), prefix[fp->standard].name, 1, call, 0, flg, s); sfprintf(sp, "%*s %*s %d %2s %4d %5s %s\n", sizeof(conf[0].name), fp->name, sizeof(prefix[fp->standard].name), prefix[fp->standard].name, 1, call, 0, flg, s);
} }
else if (flags & ASTCONF_parse) else if (flags & ASTCONF_parse)
sfprintf(sp, "%s %s - %s\n", state.id, (flags & ASTCONF_lower) ? fmtlower(fp->name) : fp->name, fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL)); sfprintf(sp, "%s %s - %s\n", state.id, (flags & ASTCONF_lower) ? fmtlower(fp->name) : fp->name, fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL|FMT_ALWAYS));
else else
sfprintf(sp, "%s=%s\n", (flags & ASTCONF_lower) ? fmtlower(fp->name) : fp->name, (flags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s); sfprintf(sp, "%s=%s\n", (flags & ASTCONF_lower) ? fmtlower(fp->name) : fp->name, (flags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL|FMT_ALWAYS) : s);
} }
} }
if (pattern) if (pattern)

View file

@ -27,7 +27,7 @@
*/ */
static const char usage[] = static const char usage[] =
"[-?\n@(#)$Id: getconf (ksh 93u+m) 2021-04-09 $\n]" "[-?\n@(#)$Id: getconf (ksh 93u+m) 2021-04-20 $\n]"
"[--catalog?" ERROR_CATALOG "]" "[--catalog?" ERROR_CATALOG "]"
"[+NAME?getconf - get configuration values]" "[+NAME?getconf - get configuration values]"
"[+DESCRIPTION?\bgetconf\b displays the system configuration value for" "[+DESCRIPTION?\bgetconf\b displays the system configuration value for"
@ -52,7 +52,7 @@ static const char usage[] =
" \aname\a=\avalue\a form to the standard output, one per line." " \aname\a=\avalue\a form to the standard output, one per line."
" Only one of \b--call\b, \b--name\b or \b--standard\b may be specified.]" " Only one of \b--call\b, \b--name\b or \b--standard\b may be specified.]"
"[+?This implementation uses the \bastgetconf\b(3) string interface to the native" "[+?This implementation uses the \bastgetconf\b(3) string interface to the native"
" \bsysconf\b(2), \bconfstr\b(2), \bpathconf\b(2), and \bsysinfo\b(2)" " \bsysconf\b(3), \bconfstr\b(3), \bpathconf\b(2), and \bsysinfo\b(2)"
" system calls." " system calls."
" Invalid options and/or names not supported by \bastgetconf\b(3) cause" " Invalid options and/or names not supported by \bastgetconf\b(3) cause"
" the default native \bgetconf\b, named by \b$(getconf GETCONF)\b, to" " the default native \bgetconf\b, named by \b$(getconf GETCONF)\b, to"
@ -63,9 +63,9 @@ static const char usage[] =
"[b:base?List base variable name sans call and standard prefixes.]" "[b:base?List base variable name sans call and standard prefixes.]"
"[c:call?Display variables with call prefix that matches \aRE\a. The call" "[c:call?Display variables with call prefix that matches \aRE\a. The call"
" prefixes are:]:[RE]{" " prefixes are:]:[RE]{"
" [+CS?\bconfstr\b(2)]" " [+CS?\bconfstr\b(3)]"
" [+PC?\bpathconf\b(2)]" " [+PC?\bpathconf\b(2)]"
" [+SC?\bsysconf\b(2)]" " [+SC?\bsysconf\b(3)]"
" [+SI?\bsysinfo\b(2)]" " [+SI?\bsysinfo\b(2)]"
" [+XX?Constant value.]" " [+XX?Constant value.]"
"}" "}"
@ -75,7 +75,7 @@ static const char usage[] =
"[p:portable?Display the named \bwritable\b variables and values in a form that" "[p:portable?Display the named \bwritable\b variables and values in a form that"
" can be directly executed by \bsh\b(1) to set the values. If \aname\a" " can be directly executed by \bsh\b(1) to set the values. If \aname\a"
" is omitted then all \bwritable\b variables are listed.]" " is omitted then all \bwritable\b variables are listed.]"
"[q:quote?\"...\" quote values.]" "[q:quote?\"...\" quote string values.]"
"[r:readonly?Display the named \breadonly\b variables in \aname\a=\avalue\a form." "[r:readonly?Display the named \breadonly\b variables in \aname\a=\avalue\a form."
" If \aname\a is omitted then all \breadonly\b variables are listed.]" " If \aname\a is omitted then all \breadonly\b variables are listed.]"
"[s:standard?Display variables with standard prefix that matches \aRE\a." "[s:standard?Display variables with standard prefix that matches \aRE\a."
@ -116,8 +116,8 @@ static const char usage[] =
"is an implementation detail of process inheritance; it may " "is an implementation detail of process inheritance; it may "
"change or vanish in the future; don't rely on it.]" "change or vanish in the future; don't rely on it.]"
"}" "}"
"[+SEE ALSO?\bpathchk\b(1), \bconfstr\b(2), \bpathconf\b(2)," "[+SEE ALSO?\bpathchk\b(1), \bconfstr\b(3), \bpathconf\b(2),"
" \bsysconf\b(2), \bastgetconf\b(3)]" " \bsysconf\b(3), \bastgetconf\b(3)]"
; ;
#include <cmd.h> #include <cmd.h>

View file

@ -66,7 +66,7 @@ static const char usage[] =
"\n[ name ... ]\n" "\n[ name ... ]\n"
"\n" "\n"
"[+SEE ALSO?\bhostname\b(1), \bgetconf\b(1), \buname\b(2)," "[+SEE ALSO?\bhostname\b(1), \bgetconf\b(1), \buname\b(2),"
" \bsysconf\b(2), \bsysinfo\b(2)]" " \bsysconf\b(3), \bsysinfo\b(2)]"
; ;
#if defined(__STDPP__directive) && defined(__STDPP__hide) #if defined(__STDPP__directive) && defined(__STDPP__hide)