sbase

suckless unix tools
git clone git://git.2f30.org/sbase.git
Log | Files | Refs | README | LICENSE

commit 360a63769ccb3068070ed004c3522f880dff9392
parent 856c79e242a3567d91ef89fd8fcafa7c89d331c2
Author: FRIGN <dev@frign.de>
Date:   Mon Feb  9 22:21:23 +0100

Use strtonum and libutf in test(1), refactor code and manpage

and mark it as finished in README.

Diffstat:
README | 2+-
libutil/strtonum.c | 10++++++++--
test.1 | 131++++++++++++++++++++++++++++++++++++++++---------------------------------------
test.c | 57++++++++++++++++++++++++---------------------------------
util.h | 1+
5 files changed, 100 insertions(+), 101 deletions(-)
diff --git a/README b/README @@ -67,7 +67,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support, =* tail yes none =* tar non-posix none =* tee yes none - test yes none +#* test yes none =* touch yes none #* tr yes none =* true yes none diff --git a/libutil/strtonum.c b/libutil/strtonum.c @@ -67,13 +67,19 @@ strtonum(const char *numstr, long long minval, long long maxval, } long long -estrtonum(const char *numstr, long long minval, long long maxval) +enstrtonum(int status, const char *numstr, long long minval, long long maxval) { const char *errstr; long long ll; ll = strtonum(numstr, minval, maxval, &errstr); if (errstr) - eprintf("strtonum %s: %s\n", numstr, errstr); + enprintf(status, "strtonum %s: %s\n", numstr, errstr); return ll; } + +long long +estrtonum(const char *numstr, long long minval, long long maxval) +{ + return enstrtonum(1, numstr, minval, maxval); +} diff --git a/test.1 b/test.1 @@ -1,75 +1,76 @@ -.Dd January 30, 2015 +.Dd February 9, 2015 .Dt TEST 1 .Os sbase .Sh NAME .Nm test -.Nd check file types and compare values +.Nd evaluate expression .Sh SYNOPSIS .Nm -.Ar EXPRESSION +.Ar expression .Sh DESCRIPTION -Exit with the status determined by -.Ar EXPRESSION . +.Nm +returns the status of the +.Ar expression . .Sh OPTIONS .Bl -tag -width Ds -.It ! Ar EXPRESSION -invert EXPRESSION -.It Fl b Ar FILE -FILE exists and is block special -.It Fl c Ar FILE -FILE exists and is character special -.It Fl d Ar FILE -FILE exists and is a directory -.It Fl e Ar FILE -FILE exists -.It Fl f Ar FILE -FILE exists and is a regular file -.It Fl g Ar FILE -FILE exists and is set-group-ID -.It Fl h Ar FILE -FILE exists and is a symbolic link (same as -.Fl L ) -.It Fl k Ar FILE -FILE exists and its sticky bit is set -.It Fl L Ar FILE -FILE exists and is a symbolic link (same as -.Fl h ) -.It Fl n Ar STRING -the length of STRING is nonzero -.It Fl p Ar FILE -FILE exists and is a named pipe -.It Fl r Ar FILE -FILE exists and read permission is granted -.It Fl S Ar FILE -FILE exists and is a socket -.It Fl s Ar FILE -FILE exists and has a size greater than zero -.It Fl t Ar FD -file descriptor FD is opened on a terminal -.It Fl u Ar FILE -exists and its set-user-ID bit is set -.It Fl w Ar FILE -FILE exists and write permission is granted -.It Fl x Ar FILE -FILE exists and execute (or search) permission is granted -.It Fl z Ar STRING -the length of STRING is zero -.It s1 = s2 -True if the strings s1 and s2 are identical -.It s1 != s2 -True if the strings s1 and s2 are not identical -.It s1 -True if s1 is not the null string -.It n1 -eq n2 -True if the integers n1 and n2 are equal -.It n1 -ne n2 -True if the integers n1 and n2 are not equal -.It n1 -gt n2 -True if the integer n1 is greater than the integer n2 -.It n1 -ge n2 -True if the integer n1 is great than or equal to the integer n2 -.It n1 -lt n2 -True if the integer n1 is less than the integer n2 -.It n1 -le n2 -True if the integer n1 is less than or equal to the integer n2 +.It Sy ! Ar expression +.Sy invert +.Ar expression . +.It Sy -(e | s) Ar file +.Ar file +.Sy exists +and has +.Sy arbitrary size | size greater than zero . +.It Sy -(f | d | p | hL | S | b | c) Ar file +.Ar file +.Sy exists +and is +.Sy regular file | directory | named pipe | symbolic link | socket | block special | character special . +.It Sy -(k | g | u | r | w | x) Ar file +.Ar file +.Sy exists +and is +.Sy sticky(1) | setgid(2) | setuid(4) | readable | writable | executable (or searchable) . +.It Fl t Ar fd +.Ar fd +as a file descriptor is +.Sy associated with a terminal . +.It Ar string +True if +.Ar string +is +.Sy not the null string . +.It Sy -(z | n) Ar string +True if +.Ar string +has +.Sy zero | non-zero +length. +.It Ar s1 Sy (= | !=) Ar s2 +True if strings +.Ar s1 +and +.Ar s2 +are +.Sy identical | different . +.It Ar n1 Sy -(eq | ne | gt | ge | le | lt) Ar n2 +True if integers +.Ar n1 +and +.Ar n2 +are +.Sy = | != | > | >= | <= | < . +.Sh EXIT STATUS +.Bl -tag -width Ds +.It 0 +.Ar expression +is true. +.It 1 +.Ar expression +is false. +.It > 1 +An error occurred. .El +.Sh SEE ALSO +.Xr expr 1 +.Sh STANDARDS diff --git a/test.c b/test.c @@ -1,22 +1,14 @@ /* See LICENSE file for copyright and license details. */ -#include <errno.h> +#include <limits.h> #include <stdio.h> -#include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <unistd.h> +#include "utf.h" #include "util.h" -static void -stoi(char *s, int *a) -{ - char *p; - errno = 0; - *a = strtol(s, &p, 0); - if (errno || !*s || *p) - enprintf(2, "bad integer %s\n", s); -} +#define STOI(s) enstrtonum(2, s, LLONG_MIN, LLONG_MAX) static int unary_b(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISBLK (buf.st_mode); } static int unary_c(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISCHR (buf.st_mode); } @@ -29,32 +21,32 @@ static int unary_S(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; ret static int unary_s(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return buf.st_size ; } static int unary_u(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISUID & buf.st_mode ; } -static int unary_n(char *s) { return strlen(s); } -static int unary_z(char *s) { return !strlen(s); } +static int unary_n(char *s) { return utflen(s); } +static int unary_z(char *s) { return !utflen(s); } static int unary_e(char *s) { return access(s, F_OK); } static int unary_r(char *s) { return access(s, R_OK); } static int unary_w(char *s) { return access(s, W_OK); } static int unary_x(char *s) { return access(s, X_OK); } -static int unary_t(char *s) { int fd; stoi(s, &fd); return isatty(fd); } +static int unary_t(char *s) { int fd = enstrtonum(2, s, 0, INT_MAX); return isatty(fd); } static int binary_se(char *s1, char *s2) { return strcmp(s1, s2) == 0; } static int binary_sn(char *s1, char *s2) { return strcmp(s1, s2) != 0; } -static int binary_eq(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a == b; } -static int binary_ne(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a != b; } -static int binary_gt(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a > b; } -static int binary_ge(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a >= b; } -static int binary_lt(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a < b; } -static int binary_le(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a <= b; } +static int binary_eq(char *s1, char *s2) { long long a = STOI(s1), b = STOI(s2); return a == b; } +static int binary_ne(char *s1, char *s2) { long long a = STOI(s1), b = STOI(s2); return a != b; } +static int binary_gt(char *s1, char *s2) { long long a = STOI(s1), b = STOI(s2); return a > b; } +static int binary_ge(char *s1, char *s2) { long long a = STOI(s1), b = STOI(s2); return a >= b; } +static int binary_lt(char *s1, char *s2) { long long a = STOI(s1), b = STOI(s2); return a < b; } +static int binary_le(char *s1, char *s2) { long long a = STOI(s1), b = STOI(s2); return a <= b; } -typedef struct { +struct test { char *name; int (*func)(); -} Test; +}; -static Test unary[] = { +static struct test unary[] = { { "-b", unary_b }, { "-c", unary_c }, { "-d", unary_d }, @@ -77,7 +69,7 @@ static Test unary[] = { { NULL, NULL }, }; -static Test binary[] = { +static struct test binary[] = { { "=" , binary_se }, { "!=" , binary_sn }, { "-eq", binary_eq }, @@ -90,10 +82,10 @@ static Test binary[] = { { NULL, NULL }, }; -static Test * -find_test(Test *tests, char *name) +static struct test * +find_test(struct test *tests, char *name) { - Test *t; + struct test *t; for (t = tests; t->name; ++t) if (strcmp(t->name, name) == 0) @@ -116,7 +108,7 @@ onearg(char **argv) static int twoarg(char **argv) { - Test *t = find_test(unary, *argv); + struct test *t = find_test(unary, *argv); if (strcmp(argv[0], "!") == 0) return !onearg(argv + 1); @@ -130,7 +122,7 @@ twoarg(char **argv) static int threearg(char **argv) { - Test *t = find_test(binary, argv[1]); + struct test *t = find_test(binary, argv[1]); if (t) return t->func(argv[0], argv[2]); @@ -154,11 +146,10 @@ int main(int argc, char **argv) { int (*narg[])(char**) = { noarg, onearg, twoarg, threearg, fourarg }; - int len = strlen(argv[0]); + size_t len = strlen(argv[0]); - if (len && argv[0][len - 1] == '[') - if (strcmp(argv[--argc], "]") != 0) - enprintf(2, "no matching ]\n"); + if (len && argv[0][len - 1] == '[' && strcmp(argv[--argc], "]") != 0) + enprintf(2, "no matching ]\n"); --argc; ++argv; diff --git a/util.h b/util.h @@ -57,5 +57,6 @@ void putword(const char *); void recurse(const char *, void (*)(const char *)); #undef strtonum long long strtonum(const char *, long long, long long, const char **); +long long enstrtonum(int, const char *, long long, long long); long long estrtonum(const char *, long long, long long); size_t unescape(char *);