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