File: [local] / src / usr.bin / getcap / getcap.c (download)
Revision 1.9, Wed Feb 9 15:53:35 2022 UTC (2 years, 4 months ago) by millert
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1, HEAD Changes since 1.8: +2 -2 lines
Fix the -f option when passed multiple files.
Found by robert@
|
/* $OpenBSD: getcap.c,v 1.9 2022/02/09 15:53:35 millert Exp $ */
/*
* Copyright (c) 2005 Todd C. Miller <millert@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
enum captype {
boolean,
number,
string,
raw
};
void lookup_cap(char *, char *, enum captype, int);
__dead void usage(void);
int
main(int argc, char *argv[])
{
int ch, aflag;
enum captype type;
char *cp, *buf, *cap = NULL, **pathvec = NULL;
size_t n;
if (pledge("stdio rpath", NULL) == -1)
err(1, "pledge");
aflag = type = 0;
while ((ch = getopt(argc, argv, "ab:c:f:n:s:")) != -1) {
switch (ch) {
case 'a':
aflag = 1;
break;
case 'b':
if (*optarg == '\0')
usage();
cap = optarg;
type = boolean;
break;
case 'n':
if (*optarg == '\0')
usage();
cap = optarg;
type = number;
break;
case 's':
if (*optarg == '\0')
usage();
cap = optarg;
type = string;
break;
case 'c':
if (*optarg == '\0')
usage();
cap = optarg;
type = raw;
break;
case 'f':
if (pathvec != NULL)
errx(1, "only one -f option may be specified");
for (n = 1, cp = optarg; (cp = strchr(cp, ':')); n++)
cp++;
pathvec = calloc(n + 1, sizeof(char *));
for (n = 0; (pathvec[n] = strsep(&optarg, ":"));) {
if (*pathvec[n] != '\0')
n++;
}
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (pathvec == NULL) {
warnx("no path specified");
usage();
}
if (!aflag && !argc) {
warnx("must specify -a or a record name");
usage();
}
if (aflag) {
while (cgetnext(&buf, pathvec) > 0) {
lookup_cap(buf, cap, type, 1);
free(buf);
}
} else {
while (*argv != NULL) {
if (cgetent(&buf, pathvec, *argv) != 0)
errx(1, "unable to lookup %s", *argv); /* XXX */
lookup_cap(buf, cap, type, argc > 1);
free(buf);
argv++;
}
}
exit(0);
}
void
lookup_cap(char *buf, char *cap, enum captype type, int useprefix)
{
char *cp, *endp;
long l;
int ch, n, prefixlen;
if (cap == NULL) {
puts(buf);
return;
}
prefixlen = useprefix ? strcspn(buf, "|:") : 0;
switch (type) {
case boolean:
if (cgetcap(buf, cap, ':') == NULL)
return;
printf("%.*s%s%s\n", prefixlen, buf,
useprefix ? ": " : "", cap);
break;
case number:
if (cgetnum(buf, cap, &l) == -1)
return;
printf("%.*s%s%ld\n", prefixlen, buf,
useprefix ? ": " : "", l);
break;
case string:
if ((n = cgetstr(buf, cap, &cp)) == -1)
return;
else if (n == -2)
err(1, NULL); /* ENOMEM */
printf("%.*s%s%s\n", prefixlen, buf,
useprefix ? ": " : "", cp);
break;
case raw:
n = strlen(cap) - 1;
ch = cap[n];
cap[n] = '\0';
cp = cgetcap(buf, cap, ch);
cap[n] = ch;
if (cp != NULL) {
if ((endp = strchr(cp, ':')) != NULL)
printf("%.*s%s%.*s\n", prefixlen, buf,
useprefix ? ": " : "", (int)(endp - cp),
cp);
else
printf("%.*s%s%s\n", prefixlen, buf,
useprefix ? ": " : "", cp);
}
break;
}
}
__dead void
usage(void)
{
extern char *__progname;
fprintf(stderr, "usage: %s [-b boolean | -c capability | "
"-n number | -s string] -f path\n"
" -a | record ...\n",
__progname);
exit(1);
}