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