xref: /openbsd-src/usr.bin/getcap/getcap.c (revision be07b65e94b18cfa88e86233b6ca62200b90655b)
1*be07b65eSmillert /*	$OpenBSD: getcap.c,v 1.9 2022/02/09 15:53:35 millert Exp $	*/
286976e7dSmillert 
386976e7dSmillert /*
4bf198cc6Smillert  * Copyright (c) 2005 Todd C. Miller <millert@openbsd.org>
586976e7dSmillert  *
686976e7dSmillert  * Permission to use, copy, modify, and distribute this software for any
786976e7dSmillert  * purpose with or without fee is hereby granted, provided that the above
886976e7dSmillert  * copyright notice and this permission notice appear in all copies.
986976e7dSmillert  *
1086976e7dSmillert  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1186976e7dSmillert  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1286976e7dSmillert  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1386976e7dSmillert  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1486976e7dSmillert  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1586976e7dSmillert  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1686976e7dSmillert  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1786976e7dSmillert  */
1886976e7dSmillert 
1986976e7dSmillert #include <err.h>
2086976e7dSmillert #include <stdio.h>
2186976e7dSmillert #include <stdlib.h>
2286976e7dSmillert #include <string.h>
238929f197Smillert #include <unistd.h>
2486976e7dSmillert 
2586976e7dSmillert enum captype {
2686976e7dSmillert 	boolean,
2786976e7dSmillert 	number,
2886976e7dSmillert 	string,
2986976e7dSmillert 	raw
3086976e7dSmillert };
3186976e7dSmillert 
3286976e7dSmillert void lookup_cap(char *, char *, enum captype, int);
3386976e7dSmillert __dead void usage(void);
3486976e7dSmillert 
3586976e7dSmillert int
main(int argc,char * argv[])3686976e7dSmillert main(int argc, char *argv[])
3786976e7dSmillert {
3886976e7dSmillert 	int ch, aflag;
3986976e7dSmillert 	enum captype type;
4086976e7dSmillert 	char *cp, *buf, *cap = NULL, **pathvec = NULL;
4186976e7dSmillert 	size_t n;
4286976e7dSmillert 
43126d42f1Sderaadt 	if (pledge("stdio rpath", NULL) == -1)
44126d42f1Sderaadt 		err(1, "pledge");
45126d42f1Sderaadt 
4686976e7dSmillert 	aflag = type = 0;
4786976e7dSmillert 	while ((ch = getopt(argc, argv, "ab:c:f:n:s:")) != -1) {
4886976e7dSmillert 		switch (ch) {
4986976e7dSmillert 		case 'a':
5086976e7dSmillert 			aflag = 1;
5186976e7dSmillert 			break;
5286976e7dSmillert 		case 'b':
5386976e7dSmillert 			if (*optarg == '\0')
5486976e7dSmillert 				usage();
5586976e7dSmillert 			cap = optarg;
5686976e7dSmillert 			type = boolean;
5786976e7dSmillert 			break;
5886976e7dSmillert 		case 'n':
5986976e7dSmillert 			if (*optarg == '\0')
6086976e7dSmillert 				usage();
6186976e7dSmillert 			cap = optarg;
6286976e7dSmillert 			type = number;
6386976e7dSmillert 			break;
6486976e7dSmillert 		case 's':
6586976e7dSmillert 			if (*optarg == '\0')
6686976e7dSmillert 				usage();
6786976e7dSmillert 			cap = optarg;
6886976e7dSmillert 			type = string;
6986976e7dSmillert 			break;
7086976e7dSmillert 		case 'c':
7186976e7dSmillert 			if (*optarg == '\0')
7286976e7dSmillert 				usage();
7386976e7dSmillert 			cap = optarg;
7486976e7dSmillert 			type = raw;
7586976e7dSmillert 			break;
7686976e7dSmillert 		case 'f':
7786976e7dSmillert 			if (pathvec != NULL)
7886976e7dSmillert 				errx(1, "only one -f option may be specified");
7986976e7dSmillert 			for (n = 1, cp = optarg; (cp = strchr(cp, ':')); n++)
80*be07b65eSmillert 				cp++;
8186976e7dSmillert 			pathvec = calloc(n + 1, sizeof(char *));
8286976e7dSmillert 			for (n = 0; (pathvec[n] = strsep(&optarg, ":"));) {
8386976e7dSmillert 				if (*pathvec[n] != '\0')
8486976e7dSmillert 					n++;
8586976e7dSmillert 			}
8686976e7dSmillert 			break;
8786976e7dSmillert 		default:
8886976e7dSmillert 			usage();
8986976e7dSmillert 		}
9086976e7dSmillert 	}
9186976e7dSmillert 	argc -= optind;
9286976e7dSmillert 	argv += optind;
9386976e7dSmillert 
9486976e7dSmillert 	if (pathvec == NULL) {
9586976e7dSmillert 		warnx("no path specified");
9686976e7dSmillert 		usage();
9786976e7dSmillert 	}
9886976e7dSmillert 	if (!aflag && !argc) {
9986976e7dSmillert 		warnx("must specify -a or a record name");
10086976e7dSmillert 		usage();
10186976e7dSmillert 	}
10286976e7dSmillert 
10386976e7dSmillert 	if (aflag) {
10486976e7dSmillert 		while (cgetnext(&buf, pathvec) > 0) {
10586976e7dSmillert 			lookup_cap(buf, cap, type, 1);
10686976e7dSmillert 			free(buf);
10786976e7dSmillert 		}
10886976e7dSmillert 	} else {
10986976e7dSmillert 		while (*argv != NULL) {
11086976e7dSmillert 		    if (cgetent(&buf, pathvec, *argv) != 0)
11186976e7dSmillert 			    errx(1, "unable to lookup %s", *argv); /* XXX */
11286976e7dSmillert 		    lookup_cap(buf, cap, type, argc > 1);
11386976e7dSmillert 		    free(buf);
11486976e7dSmillert 		    argv++;
11586976e7dSmillert 		}
11686976e7dSmillert 	}
11786976e7dSmillert 	exit(0);
11886976e7dSmillert }
11986976e7dSmillert 
12086976e7dSmillert void
lookup_cap(char * buf,char * cap,enum captype type,int useprefix)12186976e7dSmillert lookup_cap(char *buf, char *cap, enum captype type, int useprefix)
12286976e7dSmillert {
12386976e7dSmillert 	char *cp, *endp;
12486976e7dSmillert 	long l;
12586976e7dSmillert 	int ch, n, prefixlen;
12686976e7dSmillert 
12786976e7dSmillert 	if (cap == NULL) {
12886976e7dSmillert 		puts(buf);
12986976e7dSmillert 		return;
13086976e7dSmillert 	}
13186976e7dSmillert 
13286976e7dSmillert 	prefixlen = useprefix ? strcspn(buf, "|:") : 0;
13386976e7dSmillert 
13486976e7dSmillert 	switch (type) {
13586976e7dSmillert 	case boolean:
13686976e7dSmillert 		if (cgetcap(buf, cap, ':') == NULL)
13786976e7dSmillert 			return;
13886976e7dSmillert 		printf("%.*s%s%s\n", prefixlen, buf,
13986976e7dSmillert 		    useprefix ? ": " : "", cap);
14086976e7dSmillert 		break;
14186976e7dSmillert 	case number:
14286976e7dSmillert 		if (cgetnum(buf, cap, &l) == -1)
14386976e7dSmillert 			return;
14486976e7dSmillert 		printf("%.*s%s%ld\n", prefixlen, buf,
14586976e7dSmillert 		    useprefix ? ": " : "", l);
14686976e7dSmillert 		break;
14786976e7dSmillert 	case string:
14886976e7dSmillert 		if ((n = cgetstr(buf, cap, &cp)) == -1)
14986976e7dSmillert 			return;
15086976e7dSmillert 		else if (n == -2)
15186976e7dSmillert 			err(1, NULL);	/* ENOMEM */
15286976e7dSmillert 		printf("%.*s%s%s\n", prefixlen, buf,
15386976e7dSmillert 		    useprefix ? ": " : "", cp);
15486976e7dSmillert 		break;
15586976e7dSmillert 	case raw:
15686976e7dSmillert 		n = strlen(cap) - 1;
15786976e7dSmillert 		ch = cap[n];
15886976e7dSmillert 		cap[n] = '\0';
15986976e7dSmillert 		cp = cgetcap(buf, cap, ch);
16086976e7dSmillert 		cap[n] = ch;
16186976e7dSmillert 		if (cp != NULL) {
16286976e7dSmillert 			if ((endp = strchr(cp, ':')) != NULL)
16386976e7dSmillert 				printf("%.*s%s%.*s\n", prefixlen, buf,
1644b162b99Skrw 				    useprefix ? ": " : "", (int)(endp - cp),
1654b162b99Skrw 				    cp);
16686976e7dSmillert 			else
16786976e7dSmillert 				printf("%.*s%s%s\n", prefixlen, buf,
16886976e7dSmillert 				    useprefix ? ": " : "", cp);
16986976e7dSmillert 		}
17086976e7dSmillert 		break;
17186976e7dSmillert 	}
17286976e7dSmillert }
17386976e7dSmillert 
17486976e7dSmillert __dead void
usage(void)17586976e7dSmillert usage(void)
17686976e7dSmillert {
17786976e7dSmillert 	extern char *__progname;
17886976e7dSmillert 
179fbfb0fafSschwarze 	fprintf(stderr, "usage: %s [-b boolean | -c capability | "
180fbfb0fafSschwarze 	    "-n number | -s string] -f path\n"
181fbfb0fafSschwarze 	    "              -a | record ...\n",
182fbfb0fafSschwarze 	    __progname);
18386976e7dSmillert 	exit(1);
18486976e7dSmillert }
185