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:
parent
61e0f90460
commit
f28bce61a7
8 changed files with 76 additions and 22 deletions
9
NEWS
9
NEWS
|
@ -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
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue