diff options
author | stefanf <stefanf@FreeBSD.org> | 2006-04-29 12:57:53 +0000 |
---|---|---|
committer | stefanf <stefanf@FreeBSD.org> | 2006-04-29 12:57:53 +0000 |
commit | ac3eb05d71b3f6ce3588c6baf390403ab84d6ba4 (patch) | |
tree | 46b9d7095fc66e8ee35724b30c26992f34f72cec | |
parent | f2c5013e89cb7741bd6f283d5d97ba567a882973 (diff) | |
download | FreeBSD-src-ac3eb05d71b3f6ce3588c6baf390403ab84d6ba4.zip FreeBSD-src-ac3eb05d71b3f6ce3588c6baf390403ab84d6ba4.tar.gz |
POSIX demands that set's output (when invoked without arguments) should be
sorted. Sort the variables before printing.
PR: 96415
-rw-r--r-- | bin/sh/var.c | 56 |
1 files changed, 47 insertions, 9 deletions
diff --git a/bin/sh/var.c b/bin/sh/var.c index c7c7bff..4dc54b0 100644 --- a/bin/sh/var.c +++ b/bin/sh/var.c @@ -479,6 +479,21 @@ shprocvar(void) } +static int +var_compare(const void *a, const void *b) +{ + const char *const *sa, *const *sb; + + sa = a; + sb = b; + /* + * This compares two var=value strings which creates a different + * order from what you would probably expect. POSIX is somewhat + * ambiguous on what should be sorted exactly. + */ + return strcoll(*sa, *sb); +} + /* * Command to list all variables which are set. Currently this command @@ -492,18 +507,41 @@ showvarscmd(int argc __unused, char **argv __unused) struct var **vpp; struct var *vp; const char *s; + const char **vars; + int i, n; - for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { - for (vp = *vpp ; vp ; vp = vp->next) { - if (vp->flags & VUNSET) - continue; - for (s = vp->text; *s != '='; s++) - out1c(*s); - out1c('='); - out1qstr(s + 1); - out1c('\n'); + /* + * POSIX requires us to sort the variables. + */ + n = 0; + for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) { + for (vp = *vpp; vp; vp = vp->next) { + if (!(vp->flags & VUNSET)) + n++; } } + + INTON; + vars = ckmalloc(n * sizeof(*vars)); + i = 0; + for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) { + for (vp = *vpp; vp; vp = vp->next) { + if (!(vp->flags & VUNSET)) + vars[i++] = vp->text; + } + } + + qsort(vars, n, sizeof(*vars), var_compare); + for (i = 0; i < n; i++) { + for (s = vars[i]; *s != '='; s++) + out1c(*s); + out1c('='); + out1qstr(s + 1); + out1c('\n'); + } + ckfree(vars); + INTOFF; + return 0; } |