aboutsummaryrefslogtreecommitdiff
path: root/progs/getpcaps.c
blob: 7e14c363178786430e5f12ca57d1da92d1494771 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * Copyright (c) 1997-8,2007-8,19,21-22 Andrew G. Morgan  <morgan@kernel.org>
 *
 * This displays the capabilities of given target process(es).
 */

#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/capability.h>

static void usage(int code)
{
    fprintf(stderr,
"usage: getcaps [opts] <pid> [<pid> ...]\n\n"
"  This program displays the capabilities on the queried process(es).\n"
	    "  The capabilities are displayed in the cap_from_text(3) format.\n"
	    "\n"
	    "  Optional arguments:\n"
	    "     --help, -h or --usage display this message.\n"
	    "     --verbose             use a more verbose output format.\n"
	    "     --ugly or --legacy    use the archaic legacy output format.\n"
	    "     --iab                 show IAB of process too.\n"
	    "     --license             display license info\n");
    exit(code);
}

int main(int argc, char **argv)
{
    int retval = 0;
    int verbose = 0;
    int iab = 0;
    cap_iab_t noiab = cap_iab_init();

    if (argc < 2) {
	usage(1);
    }

    for (++argv; --argc > 0; ++argv) {
	long lpid;
	int pid;
	char *endarg;
	cap_t cap_d;
	const char *arg = *argv;

	if (!strcmp(arg, "--help") || !strcmp(arg, "--usage") ||
	    !strcmp(arg, "-h")) {
	    usage(0);
	} else if (!strcmp(arg, "--license")) {
	    printf("%s see LICENSE file for details.\n"
		   "[Copyright (c) 1997-8,2007-8,19,21-22"
		   " Andrew G. Morgan <morgan@kernel.org>]\n",
		   arg);
	    exit(0);
	} else if (!strcmp(arg, "--verbose")) {
	    verbose = 1;
	    continue;
	} else if (!strcmp(arg, "--ugly") || !strcmp(arg, "--legacy")) {
	    verbose = 2;
	    continue;
	} else if (!strcmp(arg, "--iab")) {
	    iab = 1;
	    continue;
	}

	errno = 0;
	lpid = strtol(arg, &endarg, 10);
	if (errno == 0) {
	    if (*endarg != '\0') {
		errno = EINVAL;
	    } else if (lpid < 0 || lpid != (pid_t) lpid) {
		errno = EOVERFLOW;
	    }
	}
	if (errno != 0) {
	    fprintf(stderr, "Cannot parse pid %s: (%s)\n", arg, strerror(errno));
	    retval = 1;
	    continue;
	}
	pid = lpid;

	cap_d = cap_get_pid(pid);
	if (cap_d == NULL) {
		fprintf(stderr, "Failed to get cap's for process %d:"
			" (%s)\n", pid, strerror(errno));
		retval = 1;
		continue;
	}

	char *result = cap_to_text(cap_d, NULL);
	if (iab) {
	    printf("%s:", arg);
	    if (verbose || strcmp("=", result) != 0) {
		printf(" \"%s\"", result);
	    }
	    cap_iab_t iab_val = cap_iab_get_pid(pid);
	    if (iab_val == NULL) {
		fprintf(stderr, " no IAB value for %d\n", pid);
		exit(1);
	    }
	    int cf = cap_iab_compare(noiab, iab_val);
	    if (verbose ||
		CAP_IAB_DIFFERS(cf, CAP_IAB_AMB) ||
		CAP_IAB_DIFFERS(cf, CAP_IAB_BOUND)) {
		char *iab_text = cap_iab_to_text(iab_val);
		if (iab_text == NULL) {
		    perror(" no text for IAB");
		    exit(1);
		}
		printf(" [%s]", iab_text);
		cap_free(iab_text);
	    }
	    cap_free(iab_val);
	    printf("\n");
	} else if (verbose == 1) {
	    printf("Capabilities for '%s': %s\n", arg, result);
	} else if (verbose == 2) {
	    fprintf(stderr, "Capabilities for `%s': %s\n", arg, result);
	} else {
	    printf("%s: %s\n", arg, result);
	}

	cap_free(result);
	result = NULL;
	cap_free(cap_d);
    }

    return retval;
}