mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-09-28 18:54:51 +00:00
Initial checkin and release for test(1), version 1.0.
This is taken from NetBSD.
This commit is contained in:
parent
e81ffa659a
commit
d23148604d
22
bin/test/README
Normal file
22
bin/test/README
Normal file
@ -0,0 +1,22 @@
|
||||
This is test(1) for GNO/ME. For those of you familiar with it
|
||||
from other platforms, it is a minimal BSD version, not a code-bloated
|
||||
GNU version. For those not familiar with it, read the man page.
|
||||
|
||||
I admit that this has limited functionality with gsh, but it will
|
||||
become more useful when sh(1) comes out ...
|
||||
|
||||
For copying info, see the legalese at the beginning of the file
|
||||
test.c, or the man page (you have to view the file directly rather
|
||||
than than via nroff(1) to see it).
|
||||
|
||||
Also, regarding the GNO binary:
|
||||
|
||||
This program contains material from the ORCA/C Run-Time
|
||||
Libraries, copyright 1987-1996 by Byte Works, Inc. Used
|
||||
with permission.
|
||||
|
||||
If you have problems with this, let me know. It was a two-hour port.
|
||||
|
||||
Devin Reade
|
||||
February, 1996
|
||||
<gdr@myrias.com>
|
147
bin/test/TEST.csh
Normal file
147
bin/test/TEST.csh
Normal file
@ -0,0 +1,147 @@
|
||||
# @(#)TEST.csh 5.1 (Berkeley) 6/8/92
|
||||
|
||||
alias t './test \!*; echo $status'
|
||||
#alias t 'test \!*; echo $status'
|
||||
|
||||
echo 't -b /dev/ttyp2'
|
||||
t -b /dev/ttyp2
|
||||
echo 't -b /dev/jb1a'
|
||||
t -b /dev/jb1a
|
||||
|
||||
echo 't -c test.c'
|
||||
t -c test.c
|
||||
echo 't -c /dev/tty'
|
||||
t -c /dev/tty
|
||||
|
||||
echo 't -d test.c'
|
||||
t -d test.c
|
||||
echo 't -d /etc'
|
||||
t -d /etc
|
||||
|
||||
echo 't -e noexist'
|
||||
t -e noexist
|
||||
echo 't -e test.c'
|
||||
t -e test.c
|
||||
|
||||
echo 't -f noexist'
|
||||
t -f noexist
|
||||
echo 't -f /dev/tty'
|
||||
t -f /dev/tty
|
||||
echo 't -f test.c'
|
||||
t -f test.c
|
||||
|
||||
echo 't -g test.c'
|
||||
t -g test.c
|
||||
echo 't -g /bin/ps'
|
||||
t -g /bin/ps
|
||||
|
||||
echo 't -n ""'
|
||||
t -n ""
|
||||
echo 't -n "hello"'
|
||||
t -n "hello"
|
||||
|
||||
echo 't -p test.c'
|
||||
t -p test.c
|
||||
|
||||
echo 't -r noexist'
|
||||
t -r noexist
|
||||
echo 't -r /etc/master.passwd'
|
||||
t -r /etc/master.passwd
|
||||
echo 't -r test.c'
|
||||
t -r test.c
|
||||
|
||||
echo 't -s noexist'
|
||||
t -s noexist
|
||||
echo 't -s /dev/null'
|
||||
t -s /dev/null
|
||||
echo 't -s test.c'
|
||||
t -s test.c
|
||||
|
||||
echo 't -t 20'
|
||||
t -t 20
|
||||
echo 't -t 0'
|
||||
t -t 0
|
||||
|
||||
echo 't -u test.c'
|
||||
t -u test.c
|
||||
echo 't -u /bin/rcp'
|
||||
t -u /bin/rcp
|
||||
|
||||
echo 't -w noexist'
|
||||
t -w noexist
|
||||
echo 't -w /etc/master.passwd'
|
||||
t -w /etc/master.passwd
|
||||
echo 't -w /dev/null'
|
||||
t -w /dev/null
|
||||
|
||||
echo 't -x noexist'
|
||||
t -x noexist
|
||||
echo 't -x /bin/ps'
|
||||
t -x /bin/ps
|
||||
echo 't -x /etc/motd'
|
||||
t -x /etc/motd
|
||||
|
||||
echo 't -z ""'
|
||||
t -z ""
|
||||
echo 't -z "foo"'
|
||||
t -z "foo"
|
||||
|
||||
echo 't "foo"'
|
||||
t "foo"
|
||||
echo 't ""'
|
||||
t ""
|
||||
|
||||
echo 't "hello" = "hello"'
|
||||
t "hello" = "hello"
|
||||
echo 't "hello" = "goodbye"'
|
||||
t "hello" = "goodbye"
|
||||
|
||||
echo 't "hello" != "hello"'
|
||||
t "hello" != "hello"
|
||||
echo 't "hello" != "goodbye"'
|
||||
t "hello" != "goodbye"
|
||||
|
||||
echo 't 200 -eq 200'
|
||||
t 200 -eq 200
|
||||
echo 't 34 -eq 222'
|
||||
t 34 -eq 222
|
||||
|
||||
echo 't 200 -ne 200'
|
||||
t 200 -ne 200
|
||||
echo 't 34 -ne 222'
|
||||
t 34 -ne 222
|
||||
|
||||
echo 't 200 -gt 200'
|
||||
t 200 -gt 200
|
||||
echo 't 340 -gt 222'
|
||||
t 340 -gt 222
|
||||
|
||||
echo 't 200 -ge 200'
|
||||
t 200 -ge 200
|
||||
echo 't 34 -ge 222'
|
||||
t 34 -ge 222
|
||||
|
||||
echo 't 200 -lt 200'
|
||||
t 200 -lt 200
|
||||
echo 't 34 -lt 222'
|
||||
t 34 -lt 222
|
||||
|
||||
echo 't 200 -le 200'
|
||||
t 200 -le 200
|
||||
echo 't 340 -le 222'
|
||||
t 340 -le 222
|
||||
|
||||
echo 't 700 -le 1000 -a -n "1" -a "20" = "20"'
|
||||
t 700 -le 1000 -a -n "1" -a "20" = "20"
|
||||
echo 't ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \)'
|
||||
t ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \)
|
||||
|
||||
echo 't foo -a ""'
|
||||
t foo -a ""
|
||||
echo 't "" -a foo'
|
||||
t "" -a foo
|
||||
echo 't "" -a ""'
|
||||
t "" -a ""
|
||||
echo 't "" -o ""'
|
||||
t "" -o ""
|
||||
|
56
bin/test/binaryop
Normal file
56
bin/test/binaryop
Normal file
@ -0,0 +1,56 @@
|
||||
# Copyright (c) 1988 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 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.
|
||||
#
|
||||
# @(#)binary_op 1.2 (Berkeley) 6/3/92
|
||||
#
|
||||
|
||||
|
||||
#
|
||||
# List of binary operators used by test
|
||||
#
|
||||
|
||||
|
||||
OR1 -o 1
|
||||
OR2 | 1
|
||||
AND1 -a 2
|
||||
AND2 & 2
|
||||
STREQ = 4 OP_STRING
|
||||
STRNE != 4 OP_STRING
|
||||
EQ -eq 4 OP_INT
|
||||
NE -ne 4 OP_INT
|
||||
GT -gt 4 OP_INT
|
||||
LT -lt 4 OP_INT
|
||||
LE -le 4 OP_INT
|
||||
GE -ge 4 OP_INT
|
||||
|
52
bin/test/makefile.mk
Normal file
52
bin/test/makefile.mk
Normal file
@ -0,0 +1,52 @@
|
||||
#
|
||||
# This file is intended for use with dmake
|
||||
#
|
||||
# $Id: makefile.mk,v 1.1 1996/02/10 08:27:30 gdr Exp $
|
||||
#
|
||||
# VAFLAGS must use an optimization level of at least -O8, and no
|
||||
# -g or -G* flag
|
||||
#
|
||||
# Include -DCHECK_STACK in DEFINES to get stack usage and debug info.
|
||||
# If you use -DCHECK_STACK, you will also have to add the stack checking
|
||||
# library. I keep mine in "/usr/lib/stack".
|
||||
#
|
||||
|
||||
DEFINES = -Dlint -DGNO
|
||||
STACK = -s1280
|
||||
CFLAGS += $(DEFINES) $(STACK) -w -O
|
||||
VAFLAGS += $(DEFINES) $(STACK) -w -O
|
||||
LDFLAGS += -v
|
||||
LDLIBS =
|
||||
OBJS = test.o test2.o operators.o
|
||||
ROOTS = test.root test2.root operators.root
|
||||
|
||||
test: $(OBJS) test.r
|
||||
@purge
|
||||
$(CC) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@
|
||||
copyfork test.r test -r
|
||||
|
||||
test.o: test.c operators.h
|
||||
@purge
|
||||
$(CC) -c $(CFLAGS) -o $@ test.c
|
||||
|
||||
test2.o: test2.c
|
||||
@purge
|
||||
$(CC) -c $(VAFLAGS) -o $@ test2.c
|
||||
|
||||
operators.o: operators.c operators.h
|
||||
@purge
|
||||
$(CC) -c $(CFLAGS) -o $@ operators.c
|
||||
|
||||
operators.c operators.h: unaryop binaryop
|
||||
$(MAKE) make_op
|
||||
|
||||
clean:
|
||||
$(RM) -f $(OBJS) $(ROOTS) test.r
|
||||
|
||||
clobber: clean
|
||||
$(RM) -f test
|
||||
|
||||
# use this rule to if you update binary_ops, or unary_ops
|
||||
make_op:
|
||||
@echo "$(MAKE) make_op invoked"
|
||||
# sh ${.CURDIR}/mkops
|
84
bin/test/mkops
Normal file
84
bin/test/mkops
Normal file
@ -0,0 +1,84 @@
|
||||
# Copyright (c) 1988 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 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.
|
||||
#
|
||||
# @(#)mkops 1.3 (Berkeley) 6/3/92
|
||||
#
|
||||
|
||||
|
||||
#exec > operators.h
|
||||
(
|
||||
awk '/^[^#]/ {printf "#define %s %d\n", $1, n++}' unary_op binary_op
|
||||
awk '/^[^#]/ {n++}
|
||||
END {printf "\n#define FIRST_BINARY_OP %d\n", n}
|
||||
' unary_op
|
||||
echo '
|
||||
#define OP_INT 1 /* arguments to operator are integer */
|
||||
#define OP_STRING 2 /* arguments to operator are string */
|
||||
#define OP_FILE 3 /* argument is a file name */
|
||||
|
||||
extern char *const unary_op[];
|
||||
extern char *const binary_op[];
|
||||
extern const char op_priority[];
|
||||
extern const char op_argflag[];'
|
||||
) >operators.h
|
||||
|
||||
#exec > operators.c
|
||||
(
|
||||
echo '/*
|
||||
* Operators used in the test command.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "operators.h"
|
||||
|
||||
char *const unary_op[] = {'
|
||||
awk '/^[^#]/ {printf " \"%s\",\n", $2}' unary_op
|
||||
echo ' NULL
|
||||
};
|
||||
|
||||
char *const binary_op[] = {'
|
||||
awk '/^[^#]/ {printf " \"%s\",\n", $2}' binary_op
|
||||
echo ' NULL
|
||||
};
|
||||
|
||||
const char op_priority[] = {'
|
||||
awk '/^[^#]/ {printf " %s,\n", $3}' unary_op binary_op
|
||||
echo '};
|
||||
|
||||
const char op_argflag[] = {'
|
||||
awk '/^[^#]/ {if (length($4) > 0) printf " %s,\n", $4
|
||||
else printf " 0,\n"}
|
||||
' unary_op binary_op
|
||||
echo '};'
|
||||
) >operators.c
|
118
bin/test/operators.c
Normal file
118
bin/test/operators.c
Normal file
@ -0,0 +1,118 @@
|
||||
#line 1 ":trenco4:custom.src:test:operators.c"
|
||||
/*
|
||||
* Operators used in the test command.
|
||||
*
|
||||
* $Id: operators.c,v 1.1 1996/02/10 08:27:31 gdr Exp $
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "operators.h"
|
||||
|
||||
char *const unary_op[] = {
|
||||
"!",
|
||||
"-b",
|
||||
"-c",
|
||||
"-d",
|
||||
"-e",
|
||||
"-f",
|
||||
"-g",
|
||||
"-k",
|
||||
"-n",
|
||||
"-p",
|
||||
"-r",
|
||||
"-s",
|
||||
"-t",
|
||||
"-u",
|
||||
"-w",
|
||||
"-x",
|
||||
"-z",
|
||||
NULL
|
||||
};
|
||||
|
||||
char *const binary_op[] = {
|
||||
"-o",
|
||||
"|",
|
||||
"-a",
|
||||
"&",
|
||||
"=",
|
||||
"!=",
|
||||
"-eq",
|
||||
"-ne",
|
||||
"-gt",
|
||||
"-lt",
|
||||
"-le",
|
||||
"-ge",
|
||||
NULL
|
||||
};
|
||||
|
||||
char *const andor_op[] = {
|
||||
"-o",
|
||||
"|",
|
||||
"-a",
|
||||
"&",
|
||||
NULL
|
||||
};
|
||||
|
||||
const char op_priority[] = {
|
||||
3,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
};
|
||||
|
||||
const char op_argflag[] = {
|
||||
0,
|
||||
OP_FILE,
|
||||
OP_FILE,
|
||||
OP_FILE,
|
||||
OP_FILE,
|
||||
OP_FILE,
|
||||
OP_FILE,
|
||||
OP_FILE,
|
||||
OP_STRING,
|
||||
OP_FILE,
|
||||
OP_FILE,
|
||||
OP_FILE,
|
||||
OP_INT,
|
||||
OP_FILE,
|
||||
OP_FILE,
|
||||
OP_FILE,
|
||||
OP_STRING,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
OP_STRING,
|
||||
OP_STRING,
|
||||
OP_INT,
|
||||
OP_INT,
|
||||
OP_INT,
|
||||
OP_INT,
|
||||
OP_INT,
|
||||
OP_INT,
|
||||
};
|
56
bin/test/operators.h
Normal file
56
bin/test/operators.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* $Id: operators.h,v 1.1 1996/02/10 08:27:31 gdr Exp $
|
||||
*/
|
||||
|
||||
#ifndef __P
|
||||
#ifdef __STDC__
|
||||
#define __P(a) a
|
||||
#else
|
||||
#define __P(a) ()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define NOT 0
|
||||
#define ISBLOCK 1
|
||||
#define ISCHAR 2
|
||||
#define ISDIR 3
|
||||
#define ISEXIST 4
|
||||
#define ISFILE 5
|
||||
#define ISSETGID 6
|
||||
#define ISSTICKY 7
|
||||
#define STRLEN 8
|
||||
#define ISFIFO 9
|
||||
#define ISREAD 10
|
||||
#define ISSIZE 11
|
||||
#define ISTTY 12
|
||||
#define ISSETUID 13
|
||||
#define ISWRITE 14
|
||||
#define ISEXEC 15
|
||||
#define NULSTR 16
|
||||
#define OR1 17
|
||||
#define OR2 18
|
||||
#define AND1 19
|
||||
#define AND2 20
|
||||
#define STREQ 21
|
||||
#define STRNE 22
|
||||
#define EQ 23
|
||||
#define NE 24
|
||||
#define GT 25
|
||||
#define LT 26
|
||||
#define LE 27
|
||||
#define GE 28
|
||||
|
||||
#define FIRST_BINARY_OP 17
|
||||
|
||||
#define OP_INT 1 /* arguments to operator are integer */
|
||||
#define OP_STRING 2 /* arguments to operator are string */
|
||||
#define OP_FILE 3 /* argument is a file name */
|
||||
|
||||
extern char *const unary_op[];
|
||||
extern char *const binary_op[];
|
||||
extern char *const andor_op[];
|
||||
extern const char op_priority[];
|
||||
extern const char op_argflag[];
|
||||
|
||||
extern void err __P((const char *, ...));
|
||||
|
275
bin/test/test.1
Normal file
275
bin/test/test.1
Normal file
@ -0,0 +1,275 @@
|
||||
.\" Copyright (c) 1991 Regents of the University of California.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" the Institute of Electrical and Electronics Engineers, Inc.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 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.
|
||||
.\"
|
||||
.\" @(#)test.1 6.6 (Berkeley) 6/8/92
|
||||
.\"
|
||||
.\" $Id: test.1,v 1.1 1996/02/10 08:27:32 gdr Exp $
|
||||
.\"
|
||||
.TH TEST 1 "Commands and Applications" "9 February 1996" "Version 1.0"
|
||||
.SH NAME
|
||||
test \- Condition evaluation utility.
|
||||
.SH SYNOPSIS
|
||||
.B test
|
||||
.I expression
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.B test
|
||||
utility evaluates the expression and, if it evaluates
|
||||
to true, returns a zero (true) exit status; otherwise
|
||||
it returns 1 (false).
|
||||
If there is no expression, test also
|
||||
returns 1 (false).
|
||||
.LP
|
||||
All operators and flags are separate arguments to the
|
||||
.B test
|
||||
utility.
|
||||
.LP
|
||||
The following primaries are used to construct
|
||||
.IR expression :
|
||||
.IP "\fB-b\fR \fIfile\fR"
|
||||
True if
|
||||
.I file
|
||||
exists and is a block special
|
||||
file.
|
||||
.IP "\fB-c\fR \fIfile\fR"
|
||||
True if
|
||||
.I file
|
||||
exists and is a character
|
||||
special file.
|
||||
.IP "\fB-d\fR \fIfile\fR"
|
||||
True if
|
||||
.I file
|
||||
exists and is a directory.
|
||||
.IP "\fB-e\fR \fIfile\fR"
|
||||
True if
|
||||
.I file
|
||||
exists (regardless of type).
|
||||
.IP "\fB-f\fR \fIfile\fR"
|
||||
True if
|
||||
.I file
|
||||
exists and is a regular file.
|
||||
.IP "\fB-g\fR \fIfile\fR"
|
||||
True if
|
||||
.I file
|
||||
exists and its set group ID flag
|
||||
is set.
|
||||
.IP "\fB-n\fR \fIstring\fR"
|
||||
True if the length of
|
||||
.I string
|
||||
is nonzero.
|
||||
.IP "\fB-p\fR \fIfile\fR"
|
||||
True if
|
||||
.I file
|
||||
is a named pipe (FIFO).
|
||||
.IP "\fB-r\fR \fIfile\fR"
|
||||
True if
|
||||
.I file
|
||||
exists and is readable.
|
||||
.IP "\fB-s\fR \fIfile\fR"
|
||||
True if
|
||||
.I file
|
||||
exists and has a size greater
|
||||
than zero.
|
||||
.IP "\fB-t\fR [ \fIfile_descriptor\fR ]"
|
||||
True if the file whose file descriptor number
|
||||
is
|
||||
.I file_descriptor
|
||||
(default 1) is open and is
|
||||
associated with a terminal.
|
||||
.IP "\fB-u\fR \fIfile\fR"
|
||||
True if
|
||||
.I file
|
||||
exists and its set user ID flag
|
||||
is set.
|
||||
.IP "\fB-w\fR \fIfile\fR"
|
||||
True if
|
||||
.I file
|
||||
exists and is writable.
|
||||
True
|
||||
indicates only that the write flag is on.
|
||||
The file is not writable on a read-only file
|
||||
system even if this test indicates true.
|
||||
.IP "\fB-x\fR \fIfile\fR"
|
||||
True if
|
||||
.I file
|
||||
exists and is executable.
|
||||
True
|
||||
indicates only that the execute flag is on.
|
||||
If
|
||||
.I file
|
||||
is a directory, true indicates that
|
||||
.I file
|
||||
can be searched.
|
||||
.IP "\fB-z\fR \fIstring\fR"
|
||||
True if the length of
|
||||
.I string
|
||||
is zero.
|
||||
.IP "\fIstring\fR"
|
||||
True if
|
||||
.I string
|
||||
is not the null
|
||||
string.
|
||||
.IP "\fIs1\fR \fB=\fR \fIs2\fR"
|
||||
True if the strings
|
||||
.I s1
|
||||
and
|
||||
.I s2
|
||||
are identical.
|
||||
.IP "\fIs1\fR \fB!=\fR \fIs2\fR"
|
||||
True if the strings
|
||||
.I s1
|
||||
and
|
||||
.I s2
|
||||
are not identical.
|
||||
.IP "\fIn1\fR \fB-eq\fR \fIn2\fR"
|
||||
True if the integers
|
||||
.I n1
|
||||
and
|
||||
.I n2
|
||||
are algebraically
|
||||
equal.
|
||||
.IP "\fIn1\fR \fB-ne\fR \fIn2\fR"
|
||||
True if the integers
|
||||
.I n1
|
||||
and
|
||||
.I n2
|
||||
are not
|
||||
algebraically equal.
|
||||
.IP "\fIn1\fR \fB-gt\fR \fIn2\fR"
|
||||
True if the integer
|
||||
.I n1
|
||||
is algebraically
|
||||
greater than the integer
|
||||
.I n2 .
|
||||
.IP "\fIn1\fR \fB-ge\fR \fIn2\fR"
|
||||
True if the integer
|
||||
.I n1
|
||||
is algebraically
|
||||
greater than or equal to the integer
|
||||
.I n2 .
|
||||
.IP "\fIn1\fR \fB-lt\fR \fIn2\fR"
|
||||
True if the integer
|
||||
.I n1
|
||||
is algebraically less
|
||||
than the integer
|
||||
.I n2 .
|
||||
.IP "\fIn1\fR \fB-le\fR \fIn2\fR"
|
||||
True if the integer
|
||||
.I n1
|
||||
is algebraically less
|
||||
than or equal to the integer
|
||||
.I n2 .
|
||||
.LP
|
||||
These primaries can be combined with the following operators:
|
||||
.IP "\fB!\fR \fIexpression\fR"
|
||||
True if
|
||||
.I expression
|
||||
is false.
|
||||
.IP "\fIexpression1\fR \fB-a\fR \fIexpression2\fR"
|
||||
True if both
|
||||
.I expression1
|
||||
and
|
||||
.I expression2
|
||||
are true.
|
||||
.IP "\fIexpression1\fR \fB-o\fR \fIexpression2\fR"
|
||||
True if either
|
||||
.I expression1
|
||||
or
|
||||
.I expression2
|
||||
are true.
|
||||
.IP "\fB\&(\fR \fIexpression\fR \fB\&)\fR"
|
||||
True if
|
||||
.I expression
|
||||
is true.
|
||||
.LP
|
||||
The
|
||||
.B -a
|
||||
operator has higher precedence than the
|
||||
.B -o
|
||||
operator.
|
||||
.SH GRAMMAR AMBIGUITY
|
||||
The
|
||||
.B test
|
||||
grammar is inherently ambiguous. In order to assure a degree of consistency,
|
||||
the cases described in the
|
||||
.IR "POSIX 1003.2" ,
|
||||
section D11.2/4.62.4, standard
|
||||
are evaluated consistently according to the rules specified in the
|
||||
standards document. All other cases are subject to the ambiguity in the
|
||||
command semantics.
|
||||
.SH GNO CAVEATS
|
||||
The
|
||||
.BR \-b ,
|
||||
.BR \-c ,
|
||||
.BR \-g ,
|
||||
and
|
||||
.BR \-u
|
||||
operators always cause a false return value (as of GNO v2.0.4)
|
||||
since block- and character-special files, and the setuid and setgid bits
|
||||
are not currently available under GS/OS.
|
||||
.LP
|
||||
Because of the implementation of
|
||||
.BR stat (2)
|
||||
under GNO v2.0.4, the
|
||||
.BR \-x
|
||||
operator will return false if
|
||||
.I file
|
||||
is a directory.
|
||||
.SH RETURN VALUES
|
||||
The
|
||||
.B test
|
||||
utility exits with one of the following values:
|
||||
.IP \fB0\fR
|
||||
.I expression
|
||||
evaluated to true.
|
||||
.IP \fB1\fR
|
||||
.I expression
|
||||
evaluated to false or expression was missing.
|
||||
.IP \fB>1\fR
|
||||
An error occurred.
|
||||
.SH AUTHOR
|
||||
This code is derived from software contributed to Berkeley by
|
||||
Kenneth Almquist, and is based on BSD
|
||||
.BR test
|
||||
version 5.4.
|
||||
.LP
|
||||
The GNO port of
|
||||
.BR test
|
||||
was done by Devin Reade, <gdr@myrias.com>.
|
||||
.SH STANDARDS
|
||||
The
|
||||
.B test
|
||||
function is expected to be
|
||||
.I "POSIX 1003.2"
|
||||
compatible.
|
583
bin/test/test.c
Normal file
583
bin/test/test.c
Normal file
@ -0,0 +1,583 @@
|
||||
#line 1 ":trenco4:custom.src:test:test.c"
|
||||
/*
|
||||
* $Id: test.c,v 1.1 1996/02/10 08:27:32 gdr Exp $
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
char copyright[] =
|
||||
"@(#) Copyright (c) 1992 The Regents of the University of California.\n\
|
||||
All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)test.c 5.4 (Berkeley) 2/12/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "operators.h"
|
||||
|
||||
#define STACKSIZE 12
|
||||
#define NESTINCR 16
|
||||
|
||||
/* data types */
|
||||
#define STRING 0
|
||||
#define INTEGER 1
|
||||
#define BOOLEAN 2
|
||||
|
||||
#define IS_BANG(s) (s[0] == '!' && s[1] == '\0')
|
||||
|
||||
#ifdef CHECK_STACK
|
||||
void begin_stack_check(void);
|
||||
int end_stack_check(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This structure hold a value. The type keyword specifies the type of
|
||||
* the value, and the union u holds the value. The value of a boolean
|
||||
* is stored in u.num (1 = TRUE, 0 = FALSE).
|
||||
*/
|
||||
struct value {
|
||||
int type;
|
||||
union {
|
||||
char *string;
|
||||
long num;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct operator {
|
||||
short op; /* Which operator. */
|
||||
short pri; /* Priority of operator. */
|
||||
};
|
||||
|
||||
struct filestat {
|
||||
char *name; /* Name of file. */
|
||||
int rcode; /* Return code from stat. */
|
||||
struct stat stat; /* Status info on file. */
|
||||
};
|
||||
|
||||
static int expr_is_false __P((struct value *));
|
||||
static void expr_operator __P((int, struct value *, struct filestat *));
|
||||
static long chk_atol __P((char *));
|
||||
static int lookup_op __P((char *, char *const *));
|
||||
static void overflow __P((void));
|
||||
static int posix_binary_op __P((char **));
|
||||
static int posix_unary_op __P((char **));
|
||||
static void syntax __P((void));
|
||||
|
||||
#ifdef CHECK_STACK
|
||||
#define RETURN(val) \
|
||||
{ \
|
||||
int i; \
|
||||
i = (val); \
|
||||
printf("DEBUG: test returning %d\n\n",i); \
|
||||
printf("stack usage: %d bytes\n",end_stack_check()); \
|
||||
return i; \
|
||||
}
|
||||
#else
|
||||
#define RETURN(val) return val
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct operator opstack[STACKSIZE];
|
||||
struct operator *opsp;
|
||||
struct value valstack[STACKSIZE + 1];
|
||||
struct value *valsp;
|
||||
struct filestat fs;
|
||||
char c, **ap, *opname, *p;
|
||||
int binary, nest, op, pri, ret_val, skipping;
|
||||
|
||||
#ifdef CHECK_STACK
|
||||
begin_stack_check();
|
||||
#endif
|
||||
|
||||
if ((p = argv[0]) == NULL) {
|
||||
err("test: argc is zero.\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (*p != '\0' && p[strlen(p) - 1] == '[') {
|
||||
if (strcmp(argv[--argc], "]"))
|
||||
err("missing ]");
|
||||
argv[argc] = NULL;
|
||||
}
|
||||
ap = argv + 1;
|
||||
fs.name = NULL;
|
||||
|
||||
/*
|
||||
* Test(1) implements an inherently ambiguous grammer. In order to
|
||||
* assure some degree of consistency, we special case the POSIX 1003.2
|
||||
* requirements to assure correct evaluation for POSIX scripts. The
|
||||
* following special cases comply with POSIX P1003.2/D11.2 Section
|
||||
* 4.62.4.
|
||||
*/
|
||||
switch(argc - 1) {
|
||||
case 0: /* % test */
|
||||
RETURN(1);
|
||||
break;
|
||||
case 1: /* % test arg */
|
||||
/* MIPS machine returns NULL of '[ ]' is called. */
|
||||
RETURN((argv[1] == NULL || *argv[1] == '\0') ? 1 : 0);
|
||||
break;
|
||||
case 2: /* % test op arg */
|
||||
opname = argv[1];
|
||||
if (IS_BANG(opname)) {
|
||||
RETURN((*argv[2] == '\0') ? 0 : 1);
|
||||
} else {
|
||||
ret_val = posix_unary_op(&argv[1]);
|
||||
if (ret_val >= 0) {
|
||||
RETURN(ret_val);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3: /* % test arg1 op arg2 */
|
||||
if (IS_BANG(argv[1])) {
|
||||
ret_val = posix_unary_op(&argv[1]);
|
||||
if (ret_val >= 0) {
|
||||
RETURN(!ret_val);
|
||||
}
|
||||
} else if (lookup_op(argv[2], andor_op) < 0) {
|
||||
ret_val = posix_binary_op(&argv[1]);
|
||||
if (ret_val >= 0) {
|
||||
RETURN(ret_val);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4: /* % test ! arg1 op arg2 */
|
||||
if (IS_BANG(argv[1]) && lookup_op(argv[3], andor_op) < 0) {
|
||||
ret_val = posix_binary_op(&argv[2]);
|
||||
if (ret_val >= 0) {
|
||||
RETURN(!ret_val);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We use operator precedence parsing, evaluating the expression as
|
||||
* we parse it. Parentheses are handled by bumping up the priority
|
||||
* of operators using the variable "nest." We use the variable
|
||||
* "skipping" to turn off evaluation temporarily for the short
|
||||
* circuit boolean operators. (It is important do the short circuit
|
||||
* evaluation because under NFS a stat operation can take infinitely
|
||||
* long.)
|
||||
*/
|
||||
opsp = opstack + STACKSIZE;
|
||||
valsp = valstack;
|
||||
nest = skipping = 0;
|
||||
if (*ap == NULL) {
|
||||
valstack[0].type = BOOLEAN;
|
||||
valstack[0].u.num = 0;
|
||||
goto done;
|
||||
}
|
||||
for (;;) {
|
||||
opname = *ap++;
|
||||
if (opname == NULL)
|
||||
syntax();
|
||||
if (opname[0] == '(' && opname[1] == '\0') {
|
||||
nest += NESTINCR;
|
||||
continue;
|
||||
} else if (*ap && (op = lookup_op(opname, unary_op)) >= 0) {
|
||||
if (opsp == &opstack[0])
|
||||
overflow();
|
||||
--opsp;
|
||||
opsp->op = op;
|
||||
opsp->pri = op_priority[op] + nest;
|
||||
continue;
|
||||
} else {
|
||||
valsp->type = STRING;
|
||||
valsp->u.string = opname;
|
||||
valsp++;
|
||||
}
|
||||
for (;;) {
|
||||
opname = *ap++;
|
||||
if (opname == NULL) {
|
||||
if (nest != 0)
|
||||
syntax();
|
||||
pri = 0;
|
||||
break;
|
||||
}
|
||||
if (opname[0] != ')' || opname[1] != '\0') {
|
||||
if ((op = lookup_op(opname, binary_op)) < 0)
|
||||
syntax();
|
||||
op += FIRST_BINARY_OP;
|
||||
pri = op_priority[op] + nest;
|
||||
break;
|
||||
}
|
||||
if ((nest -= NESTINCR) < 0)
|
||||
syntax();
|
||||
}
|
||||
while (opsp < &opstack[STACKSIZE] && opsp->pri >= pri) {
|
||||
binary = opsp->op;
|
||||
for (;;) {
|
||||
valsp--;
|
||||
c = op_argflag[opsp->op];
|
||||
if (c == OP_INT) {
|
||||
if (valsp->type == STRING)
|
||||
valsp->u.num =
|
||||
chk_atol(valsp->u.string);
|
||||
valsp->type = INTEGER;
|
||||
} else if (c >= OP_STRING) {
|
||||
/* OP_STRING or OP_FILE */
|
||||
if (valsp->type == INTEGER) {
|
||||
if ((p = malloc(32)) == NULL)
|
||||
err("%s",
|
||||
strerror(errno));
|
||||
#ifdef SHELL
|
||||
#error "gdr: is this supposed to be %ld ? "
|
||||
fmtstr(p, 32, "%d",
|
||||
valsp->u.num);
|
||||
#else
|
||||
(void)sprintf(p,
|
||||
"%ld", valsp->u.num);
|
||||
#endif
|
||||
valsp->u.string = p;
|
||||
} else if (valsp->type == BOOLEAN) {
|
||||
if (valsp->u.num)
|
||||
valsp->u.string =
|
||||
"true";
|
||||
else
|
||||
valsp->u.string = "";
|
||||
}
|
||||
valsp->type = STRING;
|
||||
if (c == OP_FILE && (fs.name == NULL ||
|
||||
strcmp(fs.name, valsp->u.string))) {
|
||||
fs.name = valsp->u.string;
|
||||
fs.rcode =
|
||||
stat(valsp->u.string,
|
||||
&fs.stat);
|
||||
}
|
||||
}
|
||||
if (binary < FIRST_BINARY_OP)
|
||||
break;
|
||||
binary = 0;
|
||||
}
|
||||
if (!skipping)
|
||||
expr_operator(opsp->op, valsp, &fs);
|
||||
else if (opsp->op == AND1 || opsp->op == OR1)
|
||||
skipping--;
|
||||
valsp++; /* push value */
|
||||
opsp++; /* pop operator */
|
||||
}
|
||||
if (opname == NULL)
|
||||
break;
|
||||
if (opsp == &opstack[0])
|
||||
overflow();
|
||||
if (op == AND1 || op == AND2) {
|
||||
op = AND1;
|
||||
if (skipping || expr_is_false(valsp - 1))
|
||||
skipping++;
|
||||
}
|
||||
if (op == OR1 || op == OR2) {
|
||||
op = OR1;
|
||||
if (skipping || !expr_is_false(valsp - 1))
|
||||
skipping++;
|
||||
}
|
||||
opsp--;
|
||||
opsp->op = op;
|
||||
opsp->pri = pri;
|
||||
}
|
||||
done: { RETURN(expr_is_false(&valstack[0])); }
|
||||
}
|
||||
|
||||
static int
|
||||
expr_is_false(struct value *val)
|
||||
{
|
||||
if (val->type == STRING) {
|
||||
if (val->u.string[0] == '\0')
|
||||
return (1);
|
||||
} else { /* INTEGER or BOOLEAN */
|
||||
if (val->u.num == 0)
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Execute an operator. Op is the operator. Sp is the stack pointer;
|
||||
* sp[0] refers to the first operand, sp[1] refers to the second operand
|
||||
* (if any), and the result is placed in sp[0]. The operands are converted
|
||||
* to the type expected by the operator before expr_operator is called.
|
||||
* Fs is a pointer to a structure which holds the value of the last call
|
||||
* to stat, to avoid repeated stat calls on the same file.
|
||||
*/
|
||||
static void
|
||||
expr_operator(int op, struct value *sp, struct filestat *fs)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (op) {
|
||||
case NOT:
|
||||
sp->u.num = expr_is_false(sp);
|
||||
sp->type = BOOLEAN;
|
||||
break;
|
||||
case ISEXIST:
|
||||
if (fs == NULL || fs->rcode == -1)
|
||||
goto false;
|
||||
else
|
||||
goto true;
|
||||
#ifdef GNO
|
||||
case ISREAD:
|
||||
i = S_IREAD;
|
||||
goto filebit; /* true if (stat.st_mode & i) != 0 */
|
||||
case ISWRITE:
|
||||
i = S_IWRITE;
|
||||
goto filebit; /* true if (stat.st_mode & i) != 0 */
|
||||
case ISEXEC:
|
||||
i = S_IEXEC;
|
||||
goto filebit; /* true if (stat.st_mode & i) != 0 */
|
||||
#else
|
||||
case ISREAD:
|
||||
i = S_IROTH;
|
||||
goto permission;
|
||||
case ISWRITE:
|
||||
i = S_IWOTH;
|
||||
goto permission;
|
||||
case ISEXEC:
|
||||
i = S_IXOTH;
|
||||
permission:
|
||||
if (fs->stat.st_uid == geteuid())
|
||||
i <<= 6;
|
||||
else if (fs->stat.st_gid == getegid())
|
||||
i <<= 3;
|
||||
goto filebit; /* true if (stat.st_mode & i) != 0 */
|
||||
#endif /* not GNO */
|
||||
case ISFILE:
|
||||
i = S_IFREG;
|
||||
goto filetype;
|
||||
case ISDIR:
|
||||
i = S_IFDIR;
|
||||
goto filetype;
|
||||
case ISCHAR:
|
||||
i = S_IFCHR;
|
||||
goto filetype;
|
||||
case ISBLOCK:
|
||||
i = S_IFBLK;
|
||||
goto filetype;
|
||||
case ISFIFO:
|
||||
i = S_IFIFO;
|
||||
goto filetype;
|
||||
filetype:
|
||||
if ((fs->stat.st_mode & S_IFMT) == i && fs->rcode >= 0)
|
||||
true: sp->u.num = 1;
|
||||
else
|
||||
false: sp->u.num = 0;
|
||||
sp->type = BOOLEAN;
|
||||
break;
|
||||
case ISSETUID:
|
||||
i = S_ISUID;
|
||||
goto filebit;
|
||||
case ISSETGID:
|
||||
i = S_ISGID;
|
||||
goto filebit;
|
||||
case ISSTICKY:
|
||||
i = S_ISVTX;
|
||||
filebit:
|
||||
if (fs->stat.st_mode & i && fs->rcode >= 0)
|
||||
goto true;
|
||||
goto false;
|
||||
case ISSIZE:
|
||||
sp->u.num = fs->rcode >= 0 ? fs->stat.st_size : 0L;
|
||||
sp->type = INTEGER;
|
||||
break;
|
||||
case ISTTY:
|
||||
sp->u.num = isatty(sp->u.num);
|
||||
sp->type = BOOLEAN;
|
||||
break;
|
||||
case NULSTR:
|
||||
if (sp->u.string[0] == '\0')
|
||||
goto true;
|
||||
goto false;
|
||||
case STRLEN:
|
||||
sp->u.num = strlen(sp->u.string);
|
||||
sp->type = INTEGER;
|
||||
break;
|
||||
case OR1:
|
||||
case AND1:
|
||||
/*
|
||||
* These operators are mostly handled by the parser. If we
|
||||
* get here it means that both operands were evaluated, so
|
||||
* the value is the value of the second operand.
|
||||
*/
|
||||
*sp = *(sp + 1);
|
||||
break;
|
||||
case STREQ:
|
||||
case STRNE:
|
||||
i = 0;
|
||||
if (!strcmp(sp->u.string, (sp + 1)->u.string))
|
||||
i++;
|
||||
if (op == STRNE)
|
||||
i = 1 - i;
|
||||
sp->u.num = i;
|
||||
sp->type = BOOLEAN;
|
||||
break;
|
||||
case EQ:
|
||||
if (sp->u.num == (sp + 1)->u.num)
|
||||
goto true;
|
||||
goto false;
|
||||
case NE:
|
||||
if (sp->u.num != (sp + 1)->u.num)
|
||||
goto true;
|
||||
goto false;
|
||||
case GT:
|
||||
if (sp->u.num > (sp + 1)->u.num)
|
||||
goto true;
|
||||
goto false;
|
||||
case LT:
|
||||
if (sp->u.num < (sp + 1)->u.num)
|
||||
goto true;
|
||||
goto false;
|
||||
case LE:
|
||||
if (sp->u.num <= (sp + 1)->u.num)
|
||||
goto true;
|
||||
goto false;
|
||||
case GE:
|
||||
if (sp->u.num >= (sp + 1)->u.num)
|
||||
goto true;
|
||||
goto false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
lookup_op(char *name, char *const *table)
|
||||
{
|
||||
register char *const * tp;
|
||||
register char const *p;
|
||||
char c;
|
||||
|
||||
c = name[1];
|
||||
for (tp = table; (p = *tp) != NULL; tp++)
|
||||
if (p[1] == c && !strcmp(p, name))
|
||||
return (tp - table);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
posix_unary_op(char **argv)
|
||||
{
|
||||
struct filestat fs;
|
||||
struct value valp;
|
||||
int op, c;
|
||||
char *opname;
|
||||
|
||||
opname = *argv;
|
||||
if ((op = lookup_op(opname, unary_op)) < 0)
|
||||
return (-1);
|
||||
c = op_argflag[op];
|
||||
opname = argv[1];
|
||||
valp.u.string = opname;
|
||||
if (c == OP_FILE) {
|
||||
fs.name = opname;
|
||||
fs.rcode = stat(opname, &fs.stat);
|
||||
} else if (c != OP_STRING)
|
||||
return (-1);
|
||||
|
||||
expr_operator(op, &valp, &fs);
|
||||
return (valp.u.num == 0);
|
||||
}
|
||||
|
||||
static int
|
||||
posix_binary_op(char **argv)
|
||||
{
|
||||
struct value v[2];
|
||||
int op, c;
|
||||
char *opname;
|
||||
|
||||
opname = argv[1];
|
||||
if ((op = lookup_op(opname, binary_op)) < 0)
|
||||
return (-1);
|
||||
op += FIRST_BINARY_OP;
|
||||
c = op_argflag[op];
|
||||
|
||||
if (c == OP_INT) {
|
||||
v[0].u.num = chk_atol(argv[0]);
|
||||
v[1].u.num = chk_atol(argv[2]);
|
||||
} else {
|
||||
v[0].u.string = argv[0];
|
||||
v[1].u.string = argv[2];
|
||||
}
|
||||
expr_operator(op, v, NULL);
|
||||
return (v[0].u.num == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Integer type checking.
|
||||
*/
|
||||
static long
|
||||
chk_atol(char *v)
|
||||
{
|
||||
char *p;
|
||||
long r;
|
||||
|
||||
errno = 0;
|
||||
r = strtol(v, &p, 10);
|
||||
if (errno != 0)
|
||||
err("\"%s\" -- out of range.", v);
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
if (*p != '\0')
|
||||
err("illegal operand \"%s\" -- expected integer.", v);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static void
|
||||
syntax(void)
|
||||
{
|
||||
err("syntax error");
|
||||
}
|
||||
|
||||
static void
|
||||
overflow(void)
|
||||
{
|
||||
err("expression is too complex");
|
||||
}
|
11
bin/test/test.desc
Normal file
11
bin/test/test.desc
Normal file
@ -0,0 +1,11 @@
|
||||
Name: test
|
||||
Version: 1.0 (9 Feb 96)
|
||||
Shell: GNO/ME
|
||||
Author: Devin Reade
|
||||
Contact: gdr@myrias.com
|
||||
Where: /bin
|
||||
FTP: grind.isca.uiowa.edu
|
||||
|
||||
The test utility evaluates string and integer expressions and, if
|
||||
it evaluates to true, returns a zero (true) exit status; otherwise it
|
||||
returns 1 (false). Test is used mainly in shell scripts.
|
18
bin/test/test.rez
Normal file
18
bin/test/test.rez
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* $Id: test.rez,v 1.1 1996/02/10 08:27:33 gdr Exp $
|
||||
*/
|
||||
|
||||
#include "Types.Rez"
|
||||
|
||||
resource rVersion (0x1, purgeable3, nocrossbank) {
|
||||
|
||||
{ 1, 0, 0, /* version 1.0.0 */
|
||||
release, /* development|alpha|beta|final|release */
|
||||
0 /* non-final release number */
|
||||
},
|
||||
verBritain, /* close enough */
|
||||
"test",
|
||||
"Condition evaluation utility\n"
|
||||
"Devin Reade <gdr@myrias.com>\n"
|
||||
"Canada"
|
||||
};
|
37
bin/test/test2.c
Normal file
37
bin/test/test2.c
Normal file
@ -0,0 +1,37 @@
|
||||
#line 1 ":trenco4:custom.src:test:test2.c"
|
||||
/*
|
||||
* $Id: test2.c,v 1.1 1996/02/10 08:27:33 gdr Exp $
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "operators.h"
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
err(const char *fmt, ...)
|
||||
#else
|
||||
err(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
(void)fprintf(stderr, "test: ");
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
exit(2);
|
||||
/* NOTREACHED */
|
||||
}
|
59
bin/test/unaryop
Normal file
59
bin/test/unaryop
Normal file
@ -0,0 +1,59 @@
|
||||
# Copyright (c) 1988 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This code is derived from software contributed to Berkeley by
|
||||
# Kenneth Almquist.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 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.
|
||||
#
|
||||
# @(#)unary_op 1.2 (Berkeley) 6/3/92
|
||||
#
|
||||
|
||||
#
|
||||
# List of unary operators used by test.
|
||||
#
|
||||
|
||||
NOT ! 3
|
||||
ISBLOCK -b 12 OP_FILE
|
||||
ISCHAR -c 12 OP_FILE
|
||||
ISDIR -d 12 OP_FILE
|
||||
ISEXIST -e 12 OP_FILE
|
||||
ISFILE -f 12 OP_FILE
|
||||
ISSETGID -g 12 OP_FILE
|
||||
ISSTICKY -k 12 OP_FILE
|
||||
STRLEN -n 12 OP_STRING
|
||||
ISFIFO -p 12 OP_FILE
|
||||
ISREAD -r 12 OP_FILE
|
||||
ISSIZE -s 12 OP_FILE
|
||||
ISTTY -t 12 OP_INT
|
||||
ISSETUID -u 12 OP_FILE
|
||||
ISWRITE -w 12 OP_FILE
|
||||
ISEXEC -x 12 OP_FILE
|
||||
NULSTR -z 12 OP_STRING
|
||||
|
Loading…
Reference in New Issue
Block a user