morpheus-base

morpheus base system
git clone git://git.2f30.org/morpheus-base
Log | Files | Refs

test.c (4503B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <errno.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 #include <sys/stat.h>
      7 #include <unistd.h>
      8 
      9 #include "util.h"
     10 
     11 static void
     12 stoi(char *s, int *a)
     13 {
     14 	char *p;
     15 	errno = 0;
     16 	*a = strtol(s, &p, 0);
     17 	if (errno || !*s || *p)
     18 		enprintf(2, "bad integer %s\n", s);
     19 }
     20 
     21 static int unary_b(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISBLK  (buf.st_mode); }
     22 static int unary_c(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISCHR  (buf.st_mode); }
     23 static int unary_d(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISDIR  (buf.st_mode); }
     24 static int unary_f(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISREG  (buf.st_mode); }
     25 static int unary_g(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISGID & buf.st_mode ; }
     26 static int unary_h(char *s) { struct stat buf; if (lstat(s, &buf)) return 0; return S_ISLNK  (buf.st_mode); }
     27 static int unary_p(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISFIFO (buf.st_mode); }
     28 static int unary_S(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISSOCK (buf.st_mode); }
     29 static int unary_s(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return           buf.st_size ; }
     30 static int unary_u(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISUID & buf.st_mode ; }
     31 
     32 static int unary_n(char *s) { return  strlen(s); }
     33 static int unary_z(char *s) { return !strlen(s); }
     34 
     35 static int unary_e(char *s) { return access(s, F_OK); }
     36 static int unary_r(char *s) { return access(s, R_OK); }
     37 static int unary_w(char *s) { return access(s, W_OK); }
     38 static int unary_x(char *s) { return access(s, X_OK); }
     39 
     40 static int unary_t(char *s) { int fd; stoi(s, &fd); return isatty(fd); }
     41 
     42 static int binary_se(char *s1, char *s2) { return strcmp(s1, s2) == 0; }
     43 static int binary_sn(char *s1, char *s2) { return strcmp(s1, s2) != 0; }
     44 
     45 static int binary_eq(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a == b; }
     46 static int binary_ne(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a != b; }
     47 static int binary_gt(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a >  b; }
     48 static int binary_ge(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a >= b; }
     49 static int binary_lt(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a <  b; }
     50 static int binary_le(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a <= b; }
     51 
     52 typedef struct {
     53 	char *name;
     54 	int (*func)();
     55 } Test;
     56 
     57 static Test unary[] = {
     58 	{ "-b", unary_b },
     59 	{ "-c", unary_c },
     60 	{ "-d", unary_d },
     61 	{ "-e", unary_e },
     62 	{ "-f", unary_f },
     63 	{ "-g", unary_g },
     64 	{ "-h", unary_h },
     65 	{ "-L", unary_h },
     66 	{ "-n", unary_n },
     67 	{ "-p", unary_p },
     68 	{ "-r", unary_r },
     69 	{ "-S", unary_S },
     70 	{ "-s", unary_s },
     71 	{ "-t", unary_t },
     72 	{ "-u", unary_u },
     73 	{ "-w", unary_w },
     74 	{ "-x", unary_x },
     75 	{ "-z", unary_z },
     76 
     77 	{ NULL, NULL },
     78 };
     79 
     80 static Test binary[] = {
     81 	{ "="  , binary_se },
     82 	{ "!=" , binary_sn },
     83 	{ "-eq", binary_eq },
     84 	{ "-ne", binary_ne },
     85 	{ "-gt", binary_gt },
     86 	{ "-ge", binary_ge },
     87 	{ "-lt", binary_lt },
     88 	{ "-le", binary_le },
     89 
     90 	{ NULL, NULL },
     91 };
     92 
     93 static Test *
     94 find_test(Test *tests, char *name)
     95 {
     96 	Test *t;
     97 
     98 	for (t = tests; t->name; ++t)
     99 		if (strcmp(t->name, name) == 0)
    100 			return t;
    101 	return NULL;
    102 }
    103 
    104 static int
    105 noarg(char **argv)
    106 {
    107 	return 0;
    108 }
    109 
    110 static int
    111 onearg(char **argv)
    112 {
    113 	return strlen(argv[0]);
    114 }
    115 
    116 static int
    117 twoarg(char **argv)
    118 {
    119 	Test *t = find_test(unary, *argv);
    120 
    121 	if (strcmp(argv[0], "!") == 0)
    122 		return !onearg(argv + 1);
    123 
    124 	if (t)
    125 		return t->func(argv[1]);
    126 
    127 	return enprintf(2, "bad unary test %s\n", argv[0]), 0;
    128 }
    129 
    130 static int
    131 threearg(char **argv)
    132 {
    133 	Test *t = find_test(binary, argv[1]);
    134 
    135 	if (t)
    136 		return t->func(argv[0], argv[2]);
    137 
    138 	if (strcmp(argv[0], "!") == 0)
    139 		return !twoarg(argv + 1);
    140 
    141 	return enprintf(2, "bad binary test %s\n", argv[1]), 0;
    142 }
    143 
    144 static int
    145 fourarg(char **argv)
    146 {
    147 	if (strcmp(argv[0], "!") == 0)
    148 		return !threearg(argv + 1);
    149 
    150 	return enprintf(2, "too many arguments\n"), 0;
    151 }
    152 
    153 int
    154 main(int argc, char **argv)
    155 {
    156 	int (*narg[])(char**) = { noarg, onearg, twoarg, threearg, fourarg };
    157 	int len = strlen(argv[0]);
    158 
    159 	if (len && argv[0][len - 1] == '[')
    160 		if (strcmp(argv[--argc], "]") != 0)
    161 			enprintf(2, "no matching ]\n");
    162 
    163 	--argc; ++argv;
    164 
    165 	if (argc > 4)
    166 		enprintf(2, "too many arguments\n");
    167 
    168 	return !narg[argc](argv);
    169 }