xref: /openbsd/usr.bin/getcap/getcap.c (revision be07b65e)
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