From c9885518de2f8c1da3530130cbd3a5ed88f09a28 Mon Sep 17 00:00:00 2001 From: Garrett Wollman Date: Mon, 28 Oct 2002 00:15:43 +0000 Subject: [PATCH] Create a small library function, check_utility_compat(3), to determine whether a named utility should behave in FreeBSD 4.x-compatible mode or in a standard mode (default standard). The configuration is done malloc(3)-style, with either an environment variable or a symlink. Update expr(1) to use this new interface. --- bin/expr/expr.1 | 63 ++++++++++---------- bin/expr/expr.y | 3 +- include/unistd.h | 1 + lib/libc/gen/Makefile.inc | 4 +- lib/libc/gen/check_utility_compat.3 | 89 +++++++++++++++++++++++++++++ lib/libc/gen/check_utility_compat.c | 75 ++++++++++++++++++++++++ 6 files changed, 201 insertions(+), 34 deletions(-) create mode 100644 lib/libc/gen/check_utility_compat.3 create mode 100644 lib/libc/gen/check_utility_compat.c diff --git a/bin/expr/expr.1 b/bin/expr/expr.1 index 080bb60d7d96..1808f0db6d3f 100644 --- a/bin/expr/expr.1 +++ b/bin/expr/expr.1 @@ -121,9 +121,23 @@ otherwise 0. .Pp Parentheses are used for grouping in the usual manner. .Pp -Unless the -.Ev EXPR_COMPAT -variable is defined in the process environment, this version of +The +.Nm +utility makes no lexical distinction between arguments which may be +operators and arguments which may be operands. +An operand which is lexically identical to an operator will be considered a +syntax error. +See the examples below for a work-around. +.Pp +The syntax of the +.Nm +command in general is historic and inconvenient. +New applications are advised to use shell arithmetic rather than +.Nm . +.Ss Compatibility with previous implementations +Unless +.Fx 4.x +compatibility is enabled, this version of .Nm adheres to the \*[Px] @@ -140,43 +154,31 @@ will not permit this syntax. See the examples below for portable ways to guarantee the correct interpretation. The -.Ev EXPR_COMPAT -variable is intended for use as a transition and debugging aid, when +.Xr check_utility_compat 3 +function (with a +.Fa utility +argument of +.Dq Li expr ) +is used to determine whether compatibility mode should be enabled. +This feature is intended for use as a transition and debugging aid, when .Nm is used in complex scripts which cannot easily be recast to avoid the non-portable usage. -Defining -.Ev EXPR_COMPAT +Enabling compatibility mode also implicitly enables the .Fl e option, since this matches the historic behavior of .Nm in .Fx . +For historical reasons, defining the environment variable +.Ev EXPR_COMPAT +also enables compatibility mode. .Pp -The -.Nm -utility makes no lexical distinction between arguments which may be -operators and arguments which may be operands. -An operand which is lexically identical to an operator will be considered a -syntax error. -See the examples below for a work-around. -.Pp -The syntax of the -.Nm -command in general is historic and inconvenient. -New applications are advised to use shell arithmetic rather than -.Nm . .Sh ENVIRONMENT .Bl -tag -width ".Ev EXPR_COMPAT" .It Ev EXPR_COMPAT -If set, -.Nm -will emulate historic -.Nm -implementations which did not obey the Utility Syntax Guidelines. -Implies -.Fl e . +If set, enables compatibility mode. .El .Sh EXAMPLES .Bl -bullet @@ -248,15 +250,14 @@ the expression is invalid. .El .Sh SEE ALSO .Xr sh 1 , -.Xr test 1 +.Xr test 1 , +.Xr check_utility_compat 3 .Sh STANDARDS The .Nm utility conforms to .St -p1003.1-2001 , -provided that the -.Ev EXPR_COMPAT -environment variable is not defined. +provided that compatibility mode is not enabled. The .Fl e flag is an extension. diff --git a/bin/expr/expr.y b/bin/expr/expr.y index c73d85360deb..74a33033d222 100644 --- a/bin/expr/expr.y +++ b/bin/expr/expr.y @@ -278,7 +278,8 @@ main(int argc, char *argv[]) int c; setlocale (LC_ALL, ""); - if (getenv("EXPR_COMPAT") != NULL) { + if (getenv("EXPR_COMPAT") != NULL + || check_utility_compat("expr")) { av = argv + 1; eflag = 1; } else { diff --git a/include/unistd.h b/include/unistd.h index c101a1ed222d..2fd898e31d49 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -437,6 +437,7 @@ struct timeval; /* select(2) */ int acct(const char *); int async_daemon(void); int brk(const void *); +int check_utility_compat(const char *); int chroot(const char *); const char * crypt_get_format(void); diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index 55e5ce30b63d..d038b813a346 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -5,7 +5,7 @@ .PATH: ${.CURDIR}/../libc/${MACHINE_ARCH}/gen ${.CURDIR}/../libc/gen SRCS+= __xuname.c _pthread_stubs.c _rand48.c _spinlock_stub.c _thread_init.c \ - alarm.c arc4random.c assert.c basename.c \ + alarm.c arc4random.c assert.c basename.c check_utility_compat.c \ clock.c closedir.c confstr.c \ crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \ dlfcn.c dlfunc.c drand48.c erand48.c err.c errlst.c errno.c \ @@ -38,7 +38,7 @@ SRCS+= __xuname.c _pthread_stubs.c _rand48.c _spinlock_stub.c _thread_init.c \ .if ${LIB} == "c" MAN+= alarm.3 arc4random.3 \ - basename.3 clock.3 \ + basename.3 check_utility_compat.3 clock.3 \ confstr.3 ctermid.3 daemon.3 \ devname.3 directory.3 dirname.3 dladdr.3 dllockinit.3 dlopen.3 \ err.3 exec.3 fmtcheck.3 fmtmsg.3 fnmatch.3 frexp.3 ftok.3 fts.3 \ diff --git a/lib/libc/gen/check_utility_compat.3 b/lib/libc/gen/check_utility_compat.3 new file mode 100644 index 000000000000..c84c5dd8230f --- /dev/null +++ b/lib/libc/gen/check_utility_compat.3 @@ -0,0 +1,89 @@ +.\" +.\" Copyright 2002 Massachusetts Institute of Technology +.\" +.\" Permission to use, copy, modify, and distribute this software and +.\" its documentation for any purpose and without fee is hereby +.\" granted, provided that both the above copyright notice and this +.\" permission notice appear in all copies, that both the above +.\" copyright notice and this permission notice appear in all +.\" supporting documentation, and that the name of M.I.T. not be used +.\" in advertising or publicity pertaining to distribution of the +.\" software without specific, written prior permission. M.I.T. makes +.\" no representations about the suitability of this software for any +.\" purpose. It is provided "as is" without express or implied +.\" warranty. +.\" +.\" THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS +.\" ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT +.\" SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd October 27, 2002 +.Dt CHECK_UTILITY_COMPAT 3 +.Os +.Sh MAME +.Nm check_utility_compat +.Nd "determine whether a utility should be compatible" +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In unistd.h +.Ft int +.Fn check_utility_compat "const char *utility" +.Sh DESCRIPTION +The +.Nm +function checks whether +.Fa utility +should behave in a traditional +.Pq Fx 4.7 -compatible +manner, or in accordance with +.St -p1003.1-2001 . +The configuration is given as a comma-separated list of utility names; +if the list is present but empty, all supported utilities assume their +most compatible mode. +The +.Nm +function first checks for an environment variable named +.Ev _COMPAT_FreeBSD_4 . +If that environment variable does not exist, then +.Nm +will attempt to read the contents of a symbolic link named +.Pa /etc/compat-FreeBSD-4-util . +If no configuration is found, compatibility mode is disabled. +.Sh RETURN VALUES +The +.Nm +function returns zero if +.Fa utility +should implement strict +.St -p1003.1-2001 +behavior, and nonzero otherwise. +.Sh ERRORS +No errors are detected. +.Sh FILES +.Bl -tag -offset indent -width Pa +.It Pa /etc/compat-FreeBSD-4-util +If present, a symbolic link whose expansion gives system-wide default settings +for the +.Nm +function. +.El +.Sh HISTORY +The +.Nm +function first appeared in +.Fx 5.0 . +.Sh AUTHOR +This manual page was written by +.An Garrett Wollman Aq wollman@FreeBSD.org . diff --git a/lib/libc/gen/check_utility_compat.c b/lib/libc/gen/check_utility_compat.c new file mode 100644 index 000000000000..0ccdec115a87 --- /dev/null +++ b/lib/libc/gen/check_utility_compat.c @@ -0,0 +1,75 @@ +/* + * Copyright 2002 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * I din't use "namespace.h" here because none of the relevant utilities + * are threaded, so I'm not concerned about cancellation points or other + * niceties. + */ +#include +#include +#include +#include + +#ifndef LINE_MAX +#define LINE_MAX _POSIX2_LINE_MAX +#endif + +#define _PATH_UTIL_COMPAT "/etc/compat-FreeBSD-4-util" +#define _ENV_UTIL_COMPAT "_COMPAT_FreeBSD_4" + +int +check_utility_compat(const char *utility) +{ + char buf[LINE_MAX]; + char *p, *bp; + int len; + + if ((p = getenv(_ENV_UTIL_COMPAT)) != NULL) { + strlcpy(buf, p, sizeof buf); + } else { + if ((len = readlink(_PATH_UTIL_COMPAT, buf, sizeof buf)) < 0) + return 0; + if (len > sizeof buf) + len = sizeof buf; + buf[len] = '\0'; + } + if (buf[0] == '\0') + return 1; + + bp = buf; + while ((p = strsep(&bp, ",")) != NULL) { + if (strcmp(p, utility) == 0) + return 1; + } + return 0; +}