From cb291cc39432a71be76d6de2a1a730bc3bad2df9 Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Tue, 8 Nov 2011 19:35:38 +0100 Subject: [PATCH] add test.c (thanks Random832) --- Makefile | 1 + config.mk | 2 +- test.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 test.c diff --git a/Makefile b/Makefile index 5e6386f..e84e3f7 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,7 @@ SRC = \ sort.c \ tail.c \ tee.c \ + test.c \ touch.c \ true.c \ tty.c \ diff --git a/config.mk b/config.mk index 238a5f3..21080f7 100644 --- a/config.mk +++ b/config.mk @@ -9,7 +9,7 @@ MANPREFIX = $(PREFIX)/share/man #CC = musl-gcc LD = $(CC) CPPFLAGS = -D_POSIX_C_SOURCE=200112L -CFLAGS = -Os -ansi -Wall -Wextra -pedantic $(CPPFLAGS) +CFLAGS = -Os -ansi -Wall -pedantic $(CPPFLAGS) LDFLAGS = -static #-s #CC = tcc diff --git a/test.c b/test.c new file mode 100644 index 0000000..716f5e6 --- /dev/null +++ b/test.c @@ -0,0 +1,123 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include +#include "util.h" + +static bool unary(const char *, const char *); +static void usage(void); +static bool binary(const char *, const char *, const char *); + +static const char *progname; + +int +main(int argc, char *argv[]) +{ + bool ret, not = false; + + progname = argv[0]; + + /* [ ... ] alias */ + if(!strcmp(argv[0], "[")) { + if(strcmp(argv[argc-1], "]") != 0) + usage(); + argc--; + } + if(argc > 1 && !strcmp(argv[1], "!")) { + not = true; + argv++; + argc--; + } + switch(argc) { + case 2: + ret = *argv[1] != '\0'; + break; + case 3: + ret = unary(argv[1], argv[2]); + break; + case 4: + ret = binary(argv[1], argv[2], argv[3]); + break; + default: + usage(); + } + if(not) + ret = !ret; + return ret ? EXIT_SUCCESS : EXIT_FAILURE; +} + +bool +unary(const char *op, const char *arg) +{ + struct stat st; + int r; + + if(op[0] != '-' || op[1] == '\0' || op[2] != '\0') + usage(); + switch(op[1]) { + case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'p': case 'S': case 's': case 'u': + if((r = stat(arg, &st)) == -1) + return false; /* -e */ + switch(op[1]) { + case 'b': + return S_ISBLK(st.st_mode); + case 'c': + return S_ISCHR(st.st_mode); + case 'd': + return S_ISDIR(st.st_mode); + case 'e': + return true; + case 'f': + return S_ISREG(st.st_mode); + case 'g': + return st.st_mode & S_ISGID; + case 'p': + return S_ISFIFO(st.st_mode); + case 'S': + return S_ISSOCK(st.st_mode); + case 's': + return st.st_size > 0; + case 'u': + return st.st_mode & S_ISUID; + } + case 'h': case 'L': + return lstat(arg, &st) == 0 && S_ISLNK(st.st_mode); + case 'n': + return arg[0] != '\0'; + case 't': + return isatty((int)estrtol(arg, 0)); + case 'r': + return access(arg, R_OK) == 0; + case 'w': + return access(arg, W_OK) == 0; + case 'x': + return access(arg, X_OK) == 0; + case 'z': + return arg[0] == '\0'; + default: + usage(); + } + return false; /* should not reach */ +} + +void +usage(void) +{ + const char *ket = (progname[0] == '[') ? " ]" : ""; + + fprintf(stderr, "usage: %s string%s\n", progname, ket); + fprintf(stderr, " %s [!] [-bcdefghLnprSstuwxz] string%s\n", progname, ket); + fprintf(stderr, " %s [!] string1 comparison-op string2%s\n", progname, ket); + exit(EXIT_FAILURE); +} + +bool +binary(const char *arg1, const char *op, const char *arg2) +{ + eprintf("not yet implemented\n"); + return false; +}