xref: /illumos-gate/usr/src/lib/libc/port/gen/psecflags.c (revision cd277642e0bdc71a7f57c550df1279b0c091d6e2)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /* Copyright 2015, Richard Lowe. */
13 
14 #include "lint.h"
15 
16 #include <errno.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <strings.h>
21 
22 #include <sys/proc.h>
23 #include <sys/procset.h>
24 #include <sys/syscall.h>
25 #include <sys/secflags.h>
26 
27 extern int __psecflagsset(procset_t *, psecflagwhich_t, secflagdelta_t *);
28 
29 int
30 psecflags(idtype_t idtype, id_t id, psecflagwhich_t which,
31     secflagdelta_t *delta)
32 {
33 	procset_t procset;
34 
35 	setprocset(&procset, POP_AND, idtype, id, P_ALL, 0);
36 
37 	return (__psecflagsset(&procset, which, delta));
38 }
39 
40 int
41 secflags_parse(const secflagset_t *defaults, const char *flags,
42     secflagdelta_t *ret)
43 {
44 	char *flag;
45 	char *s, *ss;
46 	boolean_t current = B_FALSE;
47 
48 	/* Guarantee a clean base */
49 	bzero(ret, sizeof (*ret));
50 
51 	if ((ss = s = strdup(flags)) == NULL)
52 		return (-1);	/* errno set for us */
53 
54 
55 	while ((flag = strsep(&s, ",")) != NULL) {
56 		secflag_t sf = 0;
57 		boolean_t del = B_FALSE;
58 
59 		if (strcasecmp(flag, "default") == 0) {
60 			if (defaults != NULL) {
61 				secflags_union(&ret->psd_add, defaults);
62 			} else {
63 				free(ss);
64 				errno = EINVAL;
65 				return (-1);
66 			}
67 			continue;
68 		} else if (strcasecmp(flag, "all") == 0) {
69 			secflags_fullset(&ret->psd_add);
70 			continue;
71 		} else if (strcasecmp(flag, "none") == 0) {
72 			secflags_fullset(&ret->psd_rem);
73 			continue;
74 		} else if (strcasecmp(flag, "current") == 0) {
75 			current = B_TRUE;
76 			continue;
77 		}
78 
79 		if ((flag[0] == '-') || (flag[0] == '!')) {
80 			flag++;
81 			del = B_TRUE;
82 		} else if (flag[0] == '+') {
83 			flag++;
84 		}
85 
86 		if ((secflag_by_name(flag, &sf)) != B_TRUE) {
87 			free(ss);
88 			errno = EINVAL;
89 			return (-1);
90 		}
91 
92 		if (del)
93 			secflag_set(&(ret->psd_rem), sf);
94 		else
95 			secflag_set(&(ret->psd_add), sf);
96 	}
97 
98 	/*
99 	 * If we're not using the current flags, this is strict assignment.
100 	 * Negatives "win".
101 	 */
102 	if (!current) {
103 		secflags_copy(&ret->psd_assign, &ret->psd_add);
104 		secflags_difference(&ret->psd_assign, &ret->psd_rem);
105 		ret->psd_ass_active = B_TRUE;
106 		secflags_zero(&ret->psd_add);
107 		secflags_zero(&ret->psd_rem);
108 	}
109 
110 	free(ss);
111 	return (0);
112 }
113