stest.c - dmenu - dynamic menu | |
git clone git://git.suckless.org/dmenu | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
stest.c (3224B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include <sys/stat.h> | |
3 | |
4 #include <dirent.h> | |
5 #include <limits.h> | |
6 #include <stdio.h> | |
7 #include <stdlib.h> | |
8 #include <string.h> | |
9 #include <unistd.h> | |
10 | |
11 #include "arg.h" | |
12 char *argv0; | |
13 | |
14 #define FLAG(x) (flag[(x)-'a']) | |
15 | |
16 static void test(const char *, const char *); | |
17 static void usage(void); | |
18 | |
19 static int match = 0; | |
20 static int flag[26]; | |
21 static struct stat old, new; | |
22 | |
23 static void | |
24 test(const char *path, const char *name) | |
25 { | |
26 struct stat st, ln; | |
27 | |
28 if ((!stat(path, &st) && (FLAG('a') || name[0] != '.') /*… | |
29 && (!FLAG('b') || S_ISBLK(st.st_mode)) /*… | |
30 && (!FLAG('c') || S_ISCHR(st.st_mode)) /*… | |
31 && (!FLAG('d') || S_ISDIR(st.st_mode)) /*… | |
32 && (!FLAG('e') || access(path, F_OK) == 0) /*… | |
33 && (!FLAG('f') || S_ISREG(st.st_mode)) /*… | |
34 && (!FLAG('g') || st.st_mode & S_ISGID) /*… | |
35 && (!FLAG('h') || (!lstat(path, &ln) && S_ISLNK(ln.st_mode))) /*… | |
36 && (!FLAG('n') || st.st_mtime > new.st_mtime) /*… | |
37 && (!FLAG('o') || st.st_mtime < old.st_mtime) /*… | |
38 && (!FLAG('p') || S_ISFIFO(st.st_mode)) /*… | |
39 && (!FLAG('r') || access(path, R_OK) == 0) /*… | |
40 && (!FLAG('s') || st.st_size > 0) /*… | |
41 && (!FLAG('u') || st.st_mode & S_ISUID) /*… | |
42 && (!FLAG('w') || access(path, W_OK) == 0) /*… | |
43 && (!FLAG('x') || access(path, X_OK) == 0)) != FLAG('v')) { /*… | |
44 if (FLAG('q')) | |
45 exit(0); | |
46 match = 1; | |
47 puts(name); | |
48 } | |
49 } | |
50 | |
51 static void | |
52 usage(void) | |
53 { | |
54 fprintf(stderr, "usage: %s [-abcdefghlpqrsuvwx] " | |
55 "[-n file] [-o file] [file...]\n", argv0); | |
56 exit(2); /* like test(1) return > 1 on error */ | |
57 } | |
58 | |
59 int | |
60 main(int argc, char *argv[]) | |
61 { | |
62 struct dirent *d; | |
63 char path[PATH_MAX], *line = NULL, *file; | |
64 size_t linesiz = 0; | |
65 ssize_t n; | |
66 DIR *dir; | |
67 int r; | |
68 | |
69 ARGBEGIN { | |
70 case 'n': /* newer than file */ | |
71 case 'o': /* older than file */ | |
72 file = EARGF(usage()); | |
73 if (!(FLAG(ARGC()) = !stat(file, (ARGC() == 'n' ? &new :… | |
74 perror(file); | |
75 break; | |
76 default: | |
77 /* miscellaneous operators */ | |
78 if (strchr("abcdefghlpqrsuvwx", ARGC())) | |
79 FLAG(ARGC()) = 1; | |
80 else | |
81 usage(); /* unknown flag */ | |
82 } ARGEND; | |
83 | |
84 if (!argc) { | |
85 /* read list from stdin */ | |
86 while ((n = getline(&line, &linesiz, stdin)) > 0) { | |
87 if (line[n - 1] == '\n') | |
88 line[n - 1] = '\0'; | |
89 test(line, line); | |
90 } | |
91 free(line); | |
92 } else { | |
93 for (; argc; argc--, argv++) { | |
94 if (FLAG('l') && (dir = opendir(*argv))) { | |
95 /* test directory contents */ | |
96 while ((d = readdir(dir))) { | |
97 r = snprintf(path, sizeof path, … | |
98 *argv, d->d_name); | |
99 if (r >= 0 && (size_t)r < sizeof… | |
100 test(path, d->d_name); | |
101 } | |
102 closedir(dir); | |
103 } else { | |
104 test(*argv, *argv); | |
105 } | |
106 } | |
107 } | |
108 return match ? 0 : 1; | |
109 } |