aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/expr/expr.163
-rw-r--r--bin/expr/expr.y3
-rw-r--r--include/unistd.h1
-rw-r--r--lib/libc/gen/Makefile.inc4
-rw-r--r--lib/libc/gen/check_utility_compat.389
-rw-r--r--lib/libc/gen/check_utility_compat.c75
6 files changed, 201 insertions, 34 deletions
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 <sys/cdefs.h>
+__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 <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#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;
+}