Introduction
Introduction Statistics Contact Development Disclaimer Help
test.c - sbase - suckless unix tools
git clone git://git.suckless.org/sbase
Log
Files
Refs
README
LICENSE
---
test.c (6472B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <sys/stat.h>
3
4 #include <ctype.h>
5 #include <fcntl.h>
6 #include <string.h>
7 #include <unistd.h>
8
9 #include "util.h"
10
11 static int
12 intcmp(char *a, char *b)
13 {
14 char *s;
15 int asign = *a == '-' ? -1 : 1;
16 int bsign = *b == '-' ? -1 : 1;
17
18 if (*a == '-' || *a == '+') a += 1;
19 if (*b == '-' || *b == '+') b += 1;
20
21 if (!*a || !*b)
22 goto noint;
23 for (s = a; *s; s++)
24 if (!isdigit(*s))
25 goto noint;
26 for (s = b; *s; s++)
27 if (!isdigit(*s))
28 goto noint;
29
30 while (*a == '0') a++;
31 while (*b == '0') b++;
32 asign *= !!*a;
33 bsign *= !!*b;
34
35 if (asign != bsign)
36 return asign < bsign ? -1 : 1;
37 else if (strlen(a) != strlen(b))
38 return asign * (strlen(a) < strlen(b) ? -1 : 1);
39 else
40 return asign * strcmp(a, b);
41
42 noint:
43 enprintf(2, "expected integer operands\n");
44
45 return 0; /* not reached */
46 }
47
48 static int
49 mtimecmp(struct stat *buf1, struct stat *buf2)
50 {
51 if (buf1->st_mtime < buf2->st_mtime) return -1;
52 if (buf1->st_mtime > buf2->st_mtime) return +1;
53 #ifdef st_mtime
54 if (buf1->st_mtim.tv_nsec < buf2->st_mtim.tv_nsec) return -1;
55 if (buf1->st_mtim.tv_nsec > buf2->st_mtim.tv_nsec) return +1;
56 #endif
57 return 0;
58 }
59
60 static int unary_b(char *s) { struct stat buf; if ( stat(s, &buf)) retur…
61 static int unary_c(char *s) { struct stat buf; if ( stat(s, &buf)) retur…
62 static int unary_d(char *s) { struct stat buf; if ( stat(s, &buf)) retur…
63 static int unary_f(char *s) { struct stat buf; if ( stat(s, &buf)) retur…
64 static int unary_g(char *s) { struct stat buf; if ( stat(s, &buf)) retur…
65 static int unary_h(char *s) { struct stat buf; if (lstat(s, &buf)) retur…
66 static int unary_k(char *s) { struct stat buf; if ( stat(s, &buf)) retur…
67 static int unary_p(char *s) { struct stat buf; if ( stat(s, &buf)) retur…
68 static int unary_S(char *s) { struct stat buf; if ( stat(s, &buf)) retur…
69 static int unary_s(char *s) { struct stat buf; if ( stat(s, &buf)) retur…
70 static int unary_u(char *s) { struct stat buf; if ( stat(s, &buf)) retur…
71
72 static int unary_n(char *s) { return *s; }
73 static int unary_z(char *s) { return !*s; }
74
75 static int unary_e(char *s) { return !faccessat(AT_FDCWD, s, F_OK, AT_EA…
76 static int unary_r(char *s) { return !faccessat(AT_FDCWD, s, R_OK, AT_EA…
77 static int unary_w(char *s) { return !faccessat(AT_FDCWD, s, W_OK, AT_EA…
78 static int unary_x(char *s) { return !faccessat(AT_FDCWD, s, X_OK, AT_EA…
79
80 static int unary_t(char *s) { int fd = enstrtonum(2, s, 0, INT_MAX); ret…
81
82 static int binary_se(char *s1, char *s2) { return !strcmp(s1, s2); }
83 static int binary_sn(char *s1, char *s2) { return strcmp(s1, s2); }
84
85 static int binary_eq(char *s1, char *s2) { return intcmp(s1, s2) == 0; }
86 static int binary_ne(char *s1, char *s2) { return intcmp(s1, s2) != 0; }
87 static int binary_gt(char *s1, char *s2) { return intcmp(s1, s2) > 0; }
88 static int binary_ge(char *s1, char *s2) { return intcmp(s1, s2) >= 0; }
89 static int binary_lt(char *s1, char *s2) { return intcmp(s1, s2) < 0; }
90 static int binary_le(char *s1, char *s2) { return intcmp(s1, s2) <= 0; }
91
92 static int
93 binary_ef(char *s1, char *s2)
94 {
95 struct stat buf1, buf2;
96 if (stat(s1, &buf1) || stat(s2, &buf2)) return 0;
97 return buf1.st_dev == buf2.st_dev && buf1.st_ino == buf2.st_ino;
98 }
99
100 static int
101 binary_ot(char *s1, char *s2)
102 {
103 struct stat buf1, buf2;
104 if (stat(s1, &buf1) || stat(s2, &buf2)) return 0;
105 return mtimecmp(&buf1, &buf2) < 0;
106 }
107
108 static int
109 binary_nt(char *s1, char *s2)
110 {
111 struct stat buf1, buf2;
112 if (stat(s1, &buf1) || stat(s2, &buf2)) return 0;
113 return mtimecmp(&buf1, &buf2) > 0;
114 }
115
116 struct test {
117 char *name;
118 union {
119 int (*u)(char *);
120 int (*b)(char *, char *);
121 } func;
122 };
123
124 static struct test unary[] = {
125 { "-b", { .u = unary_b } },
126 { "-c", { .u = unary_c } },
127 { "-d", { .u = unary_d } },
128 { "-e", { .u = unary_e } },
129 { "-f", { .u = unary_f } },
130 { "-g", { .u = unary_g } },
131 { "-h", { .u = unary_h } },
132 { "-k", { .u = unary_k } },
133 { "-L", { .u = unary_h } },
134 { "-n", { .u = unary_n } },
135 { "-p", { .u = unary_p } },
136 { "-r", { .u = unary_r } },
137 { "-S", { .u = unary_S } },
138 { "-s", { .u = unary_s } },
139 { "-t", { .u = unary_t } },
140 { "-u", { .u = unary_u } },
141 { "-w", { .u = unary_w } },
142 { "-x", { .u = unary_x } },
143 { "-z", { .u = unary_z } },
144
145 { NULL },
146 };
147
148 static struct test binary[] = {
149 { "=" , { .b = binary_se } },
150 { "!=" , { .b = binary_sn } },
151 { "-eq", { .b = binary_eq } },
152 { "-ne", { .b = binary_ne } },
153 { "-gt", { .b = binary_gt } },
154 { "-ge", { .b = binary_ge } },
155 { "-lt", { .b = binary_lt } },
156 { "-le", { .b = binary_le } },
157 { "-ef", { .b = binary_ef } },
158 { "-ot", { .b = binary_ot } },
159 { "-nt", { .b = binary_nt } },
160
161 { NULL },
162 };
163
164 static struct test *
165 find_test(struct test *tests, char *name)
166 {
167 struct test *t;
168
169 for (t = tests; t->name; t++)
170 if (!strcmp(t->name, name))
171 return t;
172
173 return NULL;
174 }
175
176 static int
177 noarg(char *argv[])
178 {
179 return 0;
180 }
181
182 static int
183 onearg(char *argv[])
184 {
185 return unary_n(argv[0]);
186 }
187
188 static int
189 twoarg(char *argv[])
190 {
191 struct test *t;
192
193 if (!strcmp(argv[0], "!"))
194 return !onearg(argv + 1);
195
196 if ((t = find_test(unary, *argv)))
197 return t->func.u(argv[1]);
198
199 enprintf(2, "bad unary test %s\n", argv[0]);
200
201 return 0; /* not reached */
202 }
203
204 static int
205 threearg(char *argv[])
206 {
207 struct test *t = find_test(binary, argv[1]);
208
209 if (t)
210 return t->func.b(argv[0], argv[2]);
211
212 if (!strcmp(argv[0], "!"))
213 return !twoarg(argv + 1);
214
215 enprintf(2, "bad binary test %s\n", argv[1]);
216
217 return 0; /* not reached */
218 }
219
220 static int
221 fourarg(char *argv[])
222 {
223 if (!strcmp(argv[0], "!"))
224 return !threearg(argv + 1);
225
226 enprintf(2, "too many arguments\n");
227
228 return 0; /* not reached */
229 }
230
231 int
232 main(int argc, char *argv[])
233 {
234 int (*narg[])(char *[]) = { noarg, onearg, twoarg, threearg, fou…
235 size_t len;
236
237 argv0 = *argv, argv0 ? (argc--, argv++) : (void *)0;
238
239 len = argv0 ? strlen(argv0) : 0;
240 if (len && argv0[--len] == '[' && (!len || argv0[--len] == '/') …
241 enprintf(2, "no matching ]\n");
242
243 if (argc > 4)
244 enprintf(2, "too many arguments\n");
245
246 return !narg[argc](argv);
247 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.