1 |
|
|
/* $OpenBSD: getcap.c,v 1.6 2015/10/10 05:43:48 deraadt Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 2005 Todd C. Miller <Todd.Miller@courtesan.com> |
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 |
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 wpath cpath", 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 |
|
|
continue; |
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 |
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 ? ": " : "", endp - cp, cp); |
165 |
|
|
else |
166 |
|
|
printf("%.*s%s%s\n", prefixlen, buf, |
167 |
|
|
useprefix ? ": " : "", cp); |
168 |
|
|
} |
169 |
|
|
break; |
170 |
|
|
} |
171 |
|
|
} |
172 |
|
|
|
173 |
|
|
__dead void |
174 |
|
|
usage(void) |
175 |
|
|
{ |
176 |
|
|
extern char *__progname; |
177 |
|
|
|
178 |
|
|
fprintf(stderr, "usage: %s [-b boolean | -c capability | " |
179 |
|
|
"-n number | -s string] -f path\n" |
180 |
|
|
" -a | record ...\n", |
181 |
|
|
__progname); |
182 |
|
|
exit(1); |
183 |
|
|
} |