xref: /openbsd/usr.bin/getcap/getcap.c (revision 898184e3)
1 /*	$OpenBSD: getcap.c,v 1.3 2009/10/27 23:59:38 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 
24 enum captype {
25 	boolean,
26 	number,
27 	string,
28 	raw
29 };
30 
31 void lookup_cap(char *, char *, enum captype, int);
32 __dead void usage(void);
33 
34 int
35 main(int argc, char *argv[])
36 {
37 	int ch, aflag;
38 	enum captype type;
39 	char *cp, *buf, *cap = NULL, **pathvec = NULL;
40 	size_t n;
41 
42 	aflag = type = 0;
43 	while ((ch = getopt(argc, argv, "ab:c:f:n:s:")) != -1) {
44 		switch (ch) {
45 		case 'a':
46 			aflag = 1;
47 			break;
48 		case 'b':
49 			if (*optarg == '\0')
50 				usage();
51 			cap = optarg;
52 			type = boolean;
53 			break;
54 		case 'n':
55 			if (*optarg == '\0')
56 				usage();
57 			cap = optarg;
58 			type = number;
59 			break;
60 		case 's':
61 			if (*optarg == '\0')
62 				usage();
63 			cap = optarg;
64 			type = string;
65 			break;
66 		case 'c':
67 			if (*optarg == '\0')
68 				usage();
69 			cap = optarg;
70 			type = raw;
71 			break;
72 		case 'f':
73 			if (pathvec != NULL)
74 				errx(1, "only one -f option may be specified");
75 			for (n = 1, cp = optarg; (cp = strchr(cp, ':')); n++)
76 				continue;
77 			pathvec = calloc(n + 1, sizeof(char *));
78 			for (n = 0; (pathvec[n] = strsep(&optarg, ":"));) {
79 				if (*pathvec[n] != '\0')
80 					n++;
81 			}
82 			break;
83 		default:
84 			usage();
85 		}
86 	}
87 	argc -= optind;
88 	argv += optind;
89 
90 	if (pathvec == NULL) {
91 		warnx("no path specified");
92 		usage();
93 	}
94 	if (!aflag && !argc) {
95 		warnx("must specify -a or a record name");
96 		usage();
97 	}
98 
99 	if (aflag) {
100 		while (cgetnext(&buf, pathvec) > 0) {
101 			lookup_cap(buf, cap, type, 1);
102 			free(buf);
103 		}
104 	} else {
105 		while (*argv != NULL) {
106 		    if (cgetent(&buf, pathvec, *argv) != 0)
107 			    errx(1, "unable to lookup %s", *argv); /* XXX */
108 		    lookup_cap(buf, cap, type, argc > 1);
109 		    free(buf);
110 		    argv++;
111 		}
112 	}
113 	exit(0);
114 }
115 
116 void
117 lookup_cap(char *buf, char *cap, enum captype type, int useprefix)
118 {
119 	char *cp, *endp;
120 	long l;
121 	int ch, n, prefixlen;
122 
123 	if (cap == NULL) {
124 		puts(buf);
125 		return;
126 	}
127 
128 	prefixlen = useprefix ? strcspn(buf, "|:") : 0;
129 
130 	switch (type) {
131 	case boolean:
132 		if (cgetcap(buf, cap, ':') == NULL)
133 			return;
134 		printf("%.*s%s%s\n", prefixlen, buf,
135 		    useprefix ? ": " : "", cap);
136 		break;
137 	case number:
138 		if (cgetnum(buf, cap, &l) == -1)
139 			return;
140 		printf("%.*s%s%ld\n", prefixlen, buf,
141 		    useprefix ? ": " : "", l);
142 		break;
143 	case string:
144 		if ((n = cgetstr(buf, cap, &cp)) == -1)
145 			return;
146 		else if (n == -2)
147 			err(1, NULL);	/* ENOMEM */
148 		printf("%.*s%s%s\n", prefixlen, buf,
149 		    useprefix ? ": " : "", cp);
150 		break;
151 	case raw:
152 		n = strlen(cap) - 1;
153 		ch = cap[n];
154 		cap[n] = '\0';
155 		cp = cgetcap(buf, cap, ch);
156 		cap[n] = ch;
157 		if (cp != NULL) {
158 			if ((endp = strchr(cp, ':')) != NULL)
159 				printf("%.*s%s%.*s\n", prefixlen, buf,
160 				    useprefix ? ": " : "", endp - cp, cp);
161 			else
162 				printf("%.*s%s%s\n", prefixlen, buf,
163 				    useprefix ? ": " : "", cp);
164 		}
165 		break;
166 	}
167 }
168 
169 __dead void
170 usage(void)
171 {
172 	extern char *__progname;
173 
174 	fprintf(stderr, "usage: %s [-b boolean | -c capability | -n number | -s string] -a -f path\n"
175 	    "       %s [-b boolean | -c capability | -n number | -s string] -f path record ...\n",
176 	    __progname, __progname);
177 	exit(1);
178 }
179