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