1 /* $OpenBSD: getcap.c,v 1.9 2022/02/09 15:53:35 millert Exp $ */
2
3 /*
4 * Copyright (c) 2005 Todd C. Miller <millert@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <err.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 enum captype {
26 boolean,
27 number,
28 string,
29 raw
30 };
31
32 void lookup_cap(char *, char *, enum captype, int);
33 __dead void usage(void);
34
35 int
main(int argc,char * argv[])36 main(int argc, char *argv[])
37 {
38 int ch, aflag;
39 enum captype type;
40 char *cp, *buf, *cap = NULL, **pathvec = NULL;
41 size_t n;
42
43 if (pledge("stdio rpath", NULL) == -1)
44 err(1, "pledge");
45
46 aflag = type = 0;
47 while ((ch = getopt(argc, argv, "ab:c:f:n:s:")) != -1) {
48 switch (ch) {
49 case 'a':
50 aflag = 1;
51 break;
52 case 'b':
53 if (*optarg == '\0')
54 usage();
55 cap = optarg;
56 type = boolean;
57 break;
58 case 'n':
59 if (*optarg == '\0')
60 usage();
61 cap = optarg;
62 type = number;
63 break;
64 case 's':
65 if (*optarg == '\0')
66 usage();
67 cap = optarg;
68 type = string;
69 break;
70 case 'c':
71 if (*optarg == '\0')
72 usage();
73 cap = optarg;
74 type = raw;
75 break;
76 case 'f':
77 if (pathvec != NULL)
78 errx(1, "only one -f option may be specified");
79 for (n = 1, cp = optarg; (cp = strchr(cp, ':')); n++)
80 cp++;
81 pathvec = calloc(n + 1, sizeof(char *));
82 for (n = 0; (pathvec[n] = strsep(&optarg, ":"));) {
83 if (*pathvec[n] != '\0')
84 n++;
85 }
86 break;
87 default:
88 usage();
89 }
90 }
91 argc -= optind;
92 argv += optind;
93
94 if (pathvec == NULL) {
95 warnx("no path specified");
96 usage();
97 }
98 if (!aflag && !argc) {
99 warnx("must specify -a or a record name");
100 usage();
101 }
102
103 if (aflag) {
104 while (cgetnext(&buf, pathvec) > 0) {
105 lookup_cap(buf, cap, type, 1);
106 free(buf);
107 }
108 } else {
109 while (*argv != NULL) {
110 if (cgetent(&buf, pathvec, *argv) != 0)
111 errx(1, "unable to lookup %s", *argv); /* XXX */
112 lookup_cap(buf, cap, type, argc > 1);
113 free(buf);
114 argv++;
115 }
116 }
117 exit(0);
118 }
119
120 void
lookup_cap(char * buf,char * cap,enum captype type,int useprefix)121 lookup_cap(char *buf, char *cap, enum captype type, int useprefix)
122 {
123 char *cp, *endp;
124 long l;
125 int ch, n, prefixlen;
126
127 if (cap == NULL) {
128 puts(buf);
129 return;
130 }
131
132 prefixlen = useprefix ? strcspn(buf, "|:") : 0;
133
134 switch (type) {
135 case boolean:
136 if (cgetcap(buf, cap, ':') == NULL)
137 return;
138 printf("%.*s%s%s\n", prefixlen, buf,
139 useprefix ? ": " : "", cap);
140 break;
141 case number:
142 if (cgetnum(buf, cap, &l) == -1)
143 return;
144 printf("%.*s%s%ld\n", prefixlen, buf,
145 useprefix ? ": " : "", l);
146 break;
147 case string:
148 if ((n = cgetstr(buf, cap, &cp)) == -1)
149 return;
150 else if (n == -2)
151 err(1, NULL); /* ENOMEM */
152 printf("%.*s%s%s\n", prefixlen, buf,
153 useprefix ? ": " : "", cp);
154 break;
155 case raw:
156 n = strlen(cap) - 1;
157 ch = cap[n];
158 cap[n] = '\0';
159 cp = cgetcap(buf, cap, ch);
160 cap[n] = ch;
161 if (cp != NULL) {
162 if ((endp = strchr(cp, ':')) != NULL)
163 printf("%.*s%s%.*s\n", prefixlen, buf,
164 useprefix ? ": " : "", (int)(endp - cp),
165 cp);
166 else
167 printf("%.*s%s%s\n", prefixlen, buf,
168 useprefix ? ": " : "", cp);
169 }
170 break;
171 }
172 }
173
174 __dead void
usage(void)175 usage(void)
176 {
177 extern char *__progname;
178
179 fprintf(stderr, "usage: %s [-b boolean | -c capability | "
180 "-n number | -s string] -f path\n"
181 " -a | record ...\n",
182 __progname);
183 exit(1);
184 }
185