diff --git a/NEWS b/NEWS index fb7608c23..92ce30a42 100644 --- a/NEWS +++ b/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. +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: - Fixed a bug in emacs mode: after using tab completion to complete the name diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index 14bb9d529..f7ff7143e 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -20,7 +20,7 @@ #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_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 /* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */ diff --git a/src/cmd/ksh93/tests/builtins.sh b/src/cmd/ksh93/tests/builtins.sh index bd70f010d..5abf949d3 100755 --- a/src/cmd/ksh93/tests/builtins.sh +++ b/src/cmd/ksh93/tests/builtins.sh @@ -22,8 +22,34 @@ bincat=$(whence -p cat) -# test shell builtin commands +# ====== +# These are regression tests for the getconf builtin. 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 ": side effects failed" set -- - foobar diff --git a/src/lib/libast/comp/conf.sh b/src/lib/libast/comp/conf.sh index f4dd68fa7..33fb59c13 100644 --- a/src/lib/libast/comp/conf.sh +++ b/src/lib/libast/comp/conf.sh @@ -367,7 +367,7 @@ IFS=$ifs; set +f export CONF_getconf CONF_getconf_a 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 { echo "#include $systeminfo diff --git a/src/lib/libast/man/ast.3 b/src/lib/libast/man/ast.3 index aab7ca90a..912d53ab8 100644 --- a/src/lib/libast/man/ast.3 +++ b/src/lib/libast/man/ast.3 @@ -52,10 +52,10 @@ int astquery(int \fIfd\fP, const char* \fIformat\fP , ...); .SH DESCRIPTION .L astconf is a string interface to the -.IR confstr (2), +.IR confstr (3), .IR pathconf (2), and -.IR sysconf (2) +.IR sysconf (3) calls. If .I value @@ -269,4 +269,4 @@ and the environment variable is used to set .IR *cols . .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) diff --git a/src/lib/libast/port/astconf.c b/src/lib/libast/port/astconf.c index b69b77546..b17b1188e 100644 --- a/src/lib/libast/port/astconf.c +++ b/src/lib/libast/port/astconf.c @@ -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->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 sfprintf(sp, "L[%I*d] ", sizeof(p->limit.number), p->limit.number); } if (p->flags & CONF_MINMAX_DEF) { 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 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) { 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) sfprintf(sp, "%I*d", sizeof(v), v); else @@ -1297,7 +1297,7 @@ print(Sfio_t* sp, register Lookup_t* look, const char* name, const char* path, i else if (defined) { 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) sfprintf(sp, "%I*d", sizeof(v), v); else @@ -1636,6 +1636,25 @@ astconflist(Sfio_t* sp, const char* path, int flags, const char* pattern) for (*s++ = 0; isspace(*s); s++); 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 (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); } 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 - 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); @@ -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); } 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 - 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) diff --git a/src/lib/libcmd/getconf.c b/src/lib/libcmd/getconf.c index 780fd3c54..06ab3aed3 100644 --- a/src/lib/libcmd/getconf.c +++ b/src/lib/libcmd/getconf.c @@ -27,7 +27,7 @@ */ 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 "]" "[+NAME?getconf - get configuration values]" "[+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." " 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" -" \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." " Invalid options and/or names not supported by \bastgetconf\b(3) cause" " 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.]" "[c:call?Display variables with call prefix that matches \aRE\a. The call" " prefixes are:]:[RE]{" -" [+CS?\bconfstr\b(2)]" +" [+CS?\bconfstr\b(3)]" " [+PC?\bpathconf\b(2)]" -" [+SC?\bsysconf\b(2)]" +" [+SC?\bsysconf\b(3)]" " [+SI?\bsysinfo\b(2)]" " [+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" " can be directly executed by \bsh\b(1) to set the values. If \aname\a" " 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." " If \aname\a is omitted then all \breadonly\b variables are listed.]" "[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 " "change or vanish in the future; don't rely on it.]" "}" -"[+SEE ALSO?\bpathchk\b(1), \bconfstr\b(2), \bpathconf\b(2)," -" \bsysconf\b(2), \bastgetconf\b(3)]" +"[+SEE ALSO?\bpathchk\b(1), \bconfstr\b(3), \bpathconf\b(2)," +" \bsysconf\b(3), \bastgetconf\b(3)]" ; #include diff --git a/src/lib/libcmd/uname.c b/src/lib/libcmd/uname.c index 4e6574b71..155ac9b3d 100644 --- a/src/lib/libcmd/uname.c +++ b/src/lib/libcmd/uname.c @@ -66,7 +66,7 @@ static const char usage[] = "\n[ name ... ]\n" "\n" "[+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)