1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate *
26*7c478bd9Sstevel@tonic-gate * Device policy specific subroutines. We cannot merge them with
27*7c478bd9Sstevel@tonic-gate * drvsubr.c because of static linking requirements.
28*7c478bd9Sstevel@tonic-gate */
29*7c478bd9Sstevel@tonic-gate
30*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
31*7c478bd9Sstevel@tonic-gate
32*7c478bd9Sstevel@tonic-gate #include <stdio.h>
33*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
34*7c478bd9Sstevel@tonic-gate #include <unistd.h>
35*7c478bd9Sstevel@tonic-gate #include <string.h>
36*7c478bd9Sstevel@tonic-gate #include <ctype.h>
37*7c478bd9Sstevel@tonic-gate #include <priv.h>
38*7c478bd9Sstevel@tonic-gate #include <string.h>
39*7c478bd9Sstevel@tonic-gate #include <libgen.h>
40*7c478bd9Sstevel@tonic-gate #include <libintl.h>
41*7c478bd9Sstevel@tonic-gate #include <errno.h>
42*7c478bd9Sstevel@tonic-gate #include <alloca.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/devpolicy.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
47*7c478bd9Sstevel@tonic-gate
48*7c478bd9Sstevel@tonic-gate #include "addrem.h"
49*7c478bd9Sstevel@tonic-gate #include "errmsg.h"
50*7c478bd9Sstevel@tonic-gate #include "plcysubr.h"
51*7c478bd9Sstevel@tonic-gate
52*7c478bd9Sstevel@tonic-gate size_t devplcysys_sz;
53*7c478bd9Sstevel@tonic-gate const priv_impl_info_t *privimplinfo;
54*7c478bd9Sstevel@tonic-gate
55*7c478bd9Sstevel@tonic-gate /*
56*7c478bd9Sstevel@tonic-gate * New token types should be parsed in parse_plcy_entry.
57*7c478bd9Sstevel@tonic-gate */
58*7c478bd9Sstevel@tonic-gate #define PSET 0
59*7c478bd9Sstevel@tonic-gate
60*7c478bd9Sstevel@tonic-gate typedef struct token {
61*7c478bd9Sstevel@tonic-gate const char *token;
62*7c478bd9Sstevel@tonic-gate int type;
63*7c478bd9Sstevel@tonic-gate ptrdiff_t off;
64*7c478bd9Sstevel@tonic-gate } token_t;
65*7c478bd9Sstevel@tonic-gate
66*7c478bd9Sstevel@tonic-gate static token_t toktab[] = {
67*7c478bd9Sstevel@tonic-gate { DEVPLCY_TKN_RDP, PSET /* offsetof(devplcysys_t, dps_rdp) */ },
68*7c478bd9Sstevel@tonic-gate { DEVPLCY_TKN_WRP, PSET /* offsetof(devplcysys_t, dps_wrp) */ },
69*7c478bd9Sstevel@tonic-gate };
70*7c478bd9Sstevel@tonic-gate
71*7c478bd9Sstevel@tonic-gate #define RDPOL 0
72*7c478bd9Sstevel@tonic-gate #define WRPOL 1
73*7c478bd9Sstevel@tonic-gate
74*7c478bd9Sstevel@tonic-gate #define NTOK (sizeof (toktab)/sizeof (token_t))
75*7c478bd9Sstevel@tonic-gate
76*7c478bd9Sstevel@tonic-gate /*
77*7c478bd9Sstevel@tonic-gate * Compute the size of the datastructures needed.
78*7c478bd9Sstevel@tonic-gate */
79*7c478bd9Sstevel@tonic-gate void
devplcy_init(void)80*7c478bd9Sstevel@tonic-gate devplcy_init(void)
81*7c478bd9Sstevel@tonic-gate {
82*7c478bd9Sstevel@tonic-gate if ((privimplinfo = getprivimplinfo()) == NULL) {
83*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_PRIVIMPL));
84*7c478bd9Sstevel@tonic-gate exit(1);
85*7c478bd9Sstevel@tonic-gate }
86*7c478bd9Sstevel@tonic-gate
87*7c478bd9Sstevel@tonic-gate devplcysys_sz = DEVPLCYSYS_SZ(privimplinfo);
88*7c478bd9Sstevel@tonic-gate
89*7c478bd9Sstevel@tonic-gate toktab[RDPOL].off =
90*7c478bd9Sstevel@tonic-gate (char *)DEVPLCYSYS_RDP((devplcysys_t *)0, privimplinfo) -
91*7c478bd9Sstevel@tonic-gate (char *)0;
92*7c478bd9Sstevel@tonic-gate toktab[WRPOL].off =
93*7c478bd9Sstevel@tonic-gate (char *)DEVPLCYSYS_WRP((devplcysys_t *)0, privimplinfo) -
94*7c478bd9Sstevel@tonic-gate (char *)0;
95*7c478bd9Sstevel@tonic-gate }
96*7c478bd9Sstevel@tonic-gate
97*7c478bd9Sstevel@tonic-gate /*
98*7c478bd9Sstevel@tonic-gate * Read a configuration file line and return a static buffer pointing to it.
99*7c478bd9Sstevel@tonic-gate * It returns a static struct fileentry which has several fields:
100*7c478bd9Sstevel@tonic-gate * - rawbuf, which includes the lines including empty lines and comments
101*7c478bd9Sstevel@tonic-gate * leading up to the file and the entry as found in the file
102*7c478bd9Sstevel@tonic-gate * - orgentry, pointer in rawbuf to the start of the entry proper.
103*7c478bd9Sstevel@tonic-gate * - entry, a pre-parsed entry, escaped newlines removed.
104*7c478bd9Sstevel@tonic-gate * - startline, the line number of the first line in the file
105*7c478bd9Sstevel@tonic-gate */
106*7c478bd9Sstevel@tonic-gate fileentry_t *
fgetline(FILE * fp)107*7c478bd9Sstevel@tonic-gate fgetline(FILE *fp)
108*7c478bd9Sstevel@tonic-gate {
109*7c478bd9Sstevel@tonic-gate static size_t sz = BUFSIZ;
110*7c478bd9Sstevel@tonic-gate static struct fileentry fe;
111*7c478bd9Sstevel@tonic-gate static int linecnt = 1;
112*7c478bd9Sstevel@tonic-gate
113*7c478bd9Sstevel@tonic-gate char *buf = fe.rawbuf;
114*7c478bd9Sstevel@tonic-gate ptrdiff_t off;
115*7c478bd9Sstevel@tonic-gate char *p;
116*7c478bd9Sstevel@tonic-gate int c, lastc, i;
117*7c478bd9Sstevel@tonic-gate
118*7c478bd9Sstevel@tonic-gate if (buf == NULL) {
119*7c478bd9Sstevel@tonic-gate fe.rawbuf = buf = malloc(sz);
120*7c478bd9Sstevel@tonic-gate if (buf == NULL)
121*7c478bd9Sstevel@tonic-gate return (NULL);
122*7c478bd9Sstevel@tonic-gate }
123*7c478bd9Sstevel@tonic-gate if (fe.entry != NULL) {
124*7c478bd9Sstevel@tonic-gate free(fe.entry);
125*7c478bd9Sstevel@tonic-gate fe.orgentry = fe.entry = NULL;
126*7c478bd9Sstevel@tonic-gate }
127*7c478bd9Sstevel@tonic-gate
128*7c478bd9Sstevel@tonic-gate i = 0;
129*7c478bd9Sstevel@tonic-gate off = -1;
130*7c478bd9Sstevel@tonic-gate c = '\n';
131*7c478bd9Sstevel@tonic-gate
132*7c478bd9Sstevel@tonic-gate while (lastc = c, (c = getc(fp)) != EOF) {
133*7c478bd9Sstevel@tonic-gate buf[i++] = c;
134*7c478bd9Sstevel@tonic-gate
135*7c478bd9Sstevel@tonic-gate if (i == sz) {
136*7c478bd9Sstevel@tonic-gate sz *= 2;
137*7c478bd9Sstevel@tonic-gate fe.rawbuf = buf = realloc(buf, sz);
138*7c478bd9Sstevel@tonic-gate if (buf == NULL)
139*7c478bd9Sstevel@tonic-gate return (NULL);
140*7c478bd9Sstevel@tonic-gate }
141*7c478bd9Sstevel@tonic-gate
142*7c478bd9Sstevel@tonic-gate if (c == '\n') {
143*7c478bd9Sstevel@tonic-gate linecnt++;
144*7c478bd9Sstevel@tonic-gate /* Newline, escaped or not yet processing an entry */
145*7c478bd9Sstevel@tonic-gate if (off == -1 || lastc == '\\')
146*7c478bd9Sstevel@tonic-gate continue;
147*7c478bd9Sstevel@tonic-gate } else if (lastc == '\n' && off == -1) {
148*7c478bd9Sstevel@tonic-gate /* Start of more comments */
149*7c478bd9Sstevel@tonic-gate if (c == '#')
150*7c478bd9Sstevel@tonic-gate continue;
151*7c478bd9Sstevel@tonic-gate /* Found start of entry */
152*7c478bd9Sstevel@tonic-gate off = i - 1;
153*7c478bd9Sstevel@tonic-gate fe.startline = linecnt;
154*7c478bd9Sstevel@tonic-gate continue;
155*7c478bd9Sstevel@tonic-gate } else
156*7c478bd9Sstevel@tonic-gate continue;
157*7c478bd9Sstevel@tonic-gate
158*7c478bd9Sstevel@tonic-gate buf[i] = '\0';
159*7c478bd9Sstevel@tonic-gate fe.orgentry = buf + off;
160*7c478bd9Sstevel@tonic-gate p = fe.entry = strdup(fe.orgentry);
161*7c478bd9Sstevel@tonic-gate
162*7c478bd9Sstevel@tonic-gate if (p == NULL)
163*7c478bd9Sstevel@tonic-gate return (NULL);
164*7c478bd9Sstevel@tonic-gate
165*7c478bd9Sstevel@tonic-gate /* Remove <backslash><newline> */
166*7c478bd9Sstevel@tonic-gate if ((p = strchr(p, '\\')) != NULL) {
167*7c478bd9Sstevel@tonic-gate for (off = 0; (p[-off] = p[0]) != '\0'; p++)
168*7c478bd9Sstevel@tonic-gate if (p[0] == '\\' && p[1] == '\n') {
169*7c478bd9Sstevel@tonic-gate off += 2;
170*7c478bd9Sstevel@tonic-gate p++;
171*7c478bd9Sstevel@tonic-gate }
172*7c478bd9Sstevel@tonic-gate }
173*7c478bd9Sstevel@tonic-gate return (&fe);
174*7c478bd9Sstevel@tonic-gate }
175*7c478bd9Sstevel@tonic-gate if (lastc != '\n' || off != -1)
176*7c478bd9Sstevel@tonic-gate return (NULL);
177*7c478bd9Sstevel@tonic-gate buf[i] = '\0';
178*7c478bd9Sstevel@tonic-gate linecnt = 1;
179*7c478bd9Sstevel@tonic-gate return (&fe);
180*7c478bd9Sstevel@tonic-gate }
181*7c478bd9Sstevel@tonic-gate
182*7c478bd9Sstevel@tonic-gate /*
183*7c478bd9Sstevel@tonic-gate * Parse minor number ranges:
184*7c478bd9Sstevel@tonic-gate * (minor) or (lowminor-highminor)
185*7c478bd9Sstevel@tonic-gate * Return 0 for success, -1 for failure.
186*7c478bd9Sstevel@tonic-gate */
187*7c478bd9Sstevel@tonic-gate int
parse_minor_range(const char * range,minor_t * lo,minor_t * hi,char * type)188*7c478bd9Sstevel@tonic-gate parse_minor_range(const char *range, minor_t *lo, minor_t *hi, char *type)
189*7c478bd9Sstevel@tonic-gate {
190*7c478bd9Sstevel@tonic-gate unsigned long tmp;
191*7c478bd9Sstevel@tonic-gate char *p;
192*7c478bd9Sstevel@tonic-gate
193*7c478bd9Sstevel@tonic-gate if (*range++ != '(')
194*7c478bd9Sstevel@tonic-gate return (-1);
195*7c478bd9Sstevel@tonic-gate
196*7c478bd9Sstevel@tonic-gate errno = 0;
197*7c478bd9Sstevel@tonic-gate tmp = strtoul(range, &p, 0);
198*7c478bd9Sstevel@tonic-gate if (tmp > L_MAXMIN32 || (tmp == 0 && errno != 0) ||
199*7c478bd9Sstevel@tonic-gate (*p != '-' && *p != ')'))
200*7c478bd9Sstevel@tonic-gate return (-1);
201*7c478bd9Sstevel@tonic-gate *lo = tmp;
202*7c478bd9Sstevel@tonic-gate if (*p == '-') {
203*7c478bd9Sstevel@tonic-gate errno = 0;
204*7c478bd9Sstevel@tonic-gate tmp = strtoul(p + 1, &p, 0);
205*7c478bd9Sstevel@tonic-gate if (tmp > L_MAXMIN32 || (tmp == 0 && errno != 0) || *p != ')')
206*7c478bd9Sstevel@tonic-gate return (-1);
207*7c478bd9Sstevel@tonic-gate }
208*7c478bd9Sstevel@tonic-gate *hi = tmp;
209*7c478bd9Sstevel@tonic-gate if (*lo > *hi)
210*7c478bd9Sstevel@tonic-gate return (-1);
211*7c478bd9Sstevel@tonic-gate
212*7c478bd9Sstevel@tonic-gate switch (p[1]) {
213*7c478bd9Sstevel@tonic-gate case '\0':
214*7c478bd9Sstevel@tonic-gate *type = '\0';
215*7c478bd9Sstevel@tonic-gate break;
216*7c478bd9Sstevel@tonic-gate case 'c':
217*7c478bd9Sstevel@tonic-gate case 'C':
218*7c478bd9Sstevel@tonic-gate *type = 'c';
219*7c478bd9Sstevel@tonic-gate break;
220*7c478bd9Sstevel@tonic-gate case 'b':
221*7c478bd9Sstevel@tonic-gate case 'B':
222*7c478bd9Sstevel@tonic-gate *type = 'b';
223*7c478bd9Sstevel@tonic-gate break;
224*7c478bd9Sstevel@tonic-gate default:
225*7c478bd9Sstevel@tonic-gate return (-1);
226*7c478bd9Sstevel@tonic-gate }
227*7c478bd9Sstevel@tonic-gate return (0);
228*7c478bd9Sstevel@tonic-gate }
229*7c478bd9Sstevel@tonic-gate
230*7c478bd9Sstevel@tonic-gate static void
put_minor_range(FILE * fp,fileentry_t * old,const char * devn,const char * tail,minor_t lo,minor_t hi,char type)231*7c478bd9Sstevel@tonic-gate put_minor_range(FILE *fp, fileentry_t *old, const char *devn, const char *tail,
232*7c478bd9Sstevel@tonic-gate minor_t lo, minor_t hi, char type)
233*7c478bd9Sstevel@tonic-gate {
234*7c478bd9Sstevel@tonic-gate /* Preserve preceeding comments */
235*7c478bd9Sstevel@tonic-gate if (old != NULL && old->rawbuf != old->orgentry)
236*7c478bd9Sstevel@tonic-gate (void) fwrite(old->rawbuf, 1, old->orgentry - old->rawbuf, fp);
237*7c478bd9Sstevel@tonic-gate
238*7c478bd9Sstevel@tonic-gate if (type == '\0') {
239*7c478bd9Sstevel@tonic-gate put_minor_range(fp, NULL, devn, tail, lo, hi, 'b');
240*7c478bd9Sstevel@tonic-gate put_minor_range(fp, NULL, devn, tail, lo, hi, 'c');
241*7c478bd9Sstevel@tonic-gate } else if (lo == hi) {
242*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s:(%d)%c%s", devn, (int)lo, type, tail);
243*7c478bd9Sstevel@tonic-gate } else {
244*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s:(%d-%d)%c%s", devn, (int)lo, (int)hi,
245*7c478bd9Sstevel@tonic-gate type, tail);
246*7c478bd9Sstevel@tonic-gate }
247*7c478bd9Sstevel@tonic-gate }
248*7c478bd9Sstevel@tonic-gate
249*7c478bd9Sstevel@tonic-gate static int
delete_one_entry(const char * filename,const char * entry)250*7c478bd9Sstevel@tonic-gate delete_one_entry(const char *filename, const char *entry)
251*7c478bd9Sstevel@tonic-gate {
252*7c478bd9Sstevel@tonic-gate char tfile[MAXPATHLEN];
253*7c478bd9Sstevel@tonic-gate char ofile[MAXPATHLEN];
254*7c478bd9Sstevel@tonic-gate char *nfile;
255*7c478bd9Sstevel@tonic-gate FILE *old, *new;
256*7c478bd9Sstevel@tonic-gate fileentry_t *fep;
257*7c478bd9Sstevel@tonic-gate struct stat buf;
258*7c478bd9Sstevel@tonic-gate int newfd;
259*7c478bd9Sstevel@tonic-gate char *mpart;
260*7c478bd9Sstevel@tonic-gate boolean_t delall;
261*7c478bd9Sstevel@tonic-gate boolean_t delrange;
262*7c478bd9Sstevel@tonic-gate minor_t rlo, rhi;
263*7c478bd9Sstevel@tonic-gate char rtype;
264*7c478bd9Sstevel@tonic-gate
265*7c478bd9Sstevel@tonic-gate mpart = strchr(entry, ':');
266*7c478bd9Sstevel@tonic-gate if (mpart == NULL) {
267*7c478bd9Sstevel@tonic-gate delall = B_TRUE;
268*7c478bd9Sstevel@tonic-gate delrange = B_FALSE;
269*7c478bd9Sstevel@tonic-gate } else {
270*7c478bd9Sstevel@tonic-gate delall = B_FALSE;
271*7c478bd9Sstevel@tonic-gate mpart++;
272*7c478bd9Sstevel@tonic-gate if (*mpart == '(') {
273*7c478bd9Sstevel@tonic-gate if (parse_minor_range(mpart, &rlo, &rhi, &rtype) != 0)
274*7c478bd9Sstevel@tonic-gate return (-1);
275*7c478bd9Sstevel@tonic-gate delrange = B_TRUE;
276*7c478bd9Sstevel@tonic-gate } else {
277*7c478bd9Sstevel@tonic-gate delrange = B_FALSE;
278*7c478bd9Sstevel@tonic-gate }
279*7c478bd9Sstevel@tonic-gate }
280*7c478bd9Sstevel@tonic-gate
281*7c478bd9Sstevel@tonic-gate if (strlen(filename) + sizeof (XEND) > sizeof (tfile))
282*7c478bd9Sstevel@tonic-gate return (-1);
283*7c478bd9Sstevel@tonic-gate
284*7c478bd9Sstevel@tonic-gate old = fopen(filename, "r");
285*7c478bd9Sstevel@tonic-gate
286*7c478bd9Sstevel@tonic-gate if (old == NULL)
287*7c478bd9Sstevel@tonic-gate return (-1);
288*7c478bd9Sstevel@tonic-gate
289*7c478bd9Sstevel@tonic-gate (void) snprintf(tfile, sizeof (tfile), "%s%s", filename, XEND);
290*7c478bd9Sstevel@tonic-gate (void) snprintf(ofile, sizeof (ofile), "%s%s", filename, ".old");
291*7c478bd9Sstevel@tonic-gate
292*7c478bd9Sstevel@tonic-gate nfile = mktemp(tfile);
293*7c478bd9Sstevel@tonic-gate
294*7c478bd9Sstevel@tonic-gate new = fopen(nfile, "w");
295*7c478bd9Sstevel@tonic-gate if (new == NULL) {
296*7c478bd9Sstevel@tonic-gate (void) fclose(old);
297*7c478bd9Sstevel@tonic-gate return (ERROR);
298*7c478bd9Sstevel@tonic-gate }
299*7c478bd9Sstevel@tonic-gate
300*7c478bd9Sstevel@tonic-gate newfd = fileno(new);
301*7c478bd9Sstevel@tonic-gate
302*7c478bd9Sstevel@tonic-gate /* Copy permissions, ownership */
303*7c478bd9Sstevel@tonic-gate if (fstat(fileno(old), &buf) == 0) {
304*7c478bd9Sstevel@tonic-gate (void) fchown(newfd, buf.st_uid, buf.st_gid);
305*7c478bd9Sstevel@tonic-gate (void) fchmod(newfd, buf.st_mode);
306*7c478bd9Sstevel@tonic-gate } else {
307*7c478bd9Sstevel@tonic-gate (void) fchown(newfd, 0, 3); /* root:sys */
308*7c478bd9Sstevel@tonic-gate (void) fchmod(newfd, 0644);
309*7c478bd9Sstevel@tonic-gate }
310*7c478bd9Sstevel@tonic-gate
311*7c478bd9Sstevel@tonic-gate while ((fep = fgetline(old))) {
312*7c478bd9Sstevel@tonic-gate char *tok;
313*7c478bd9Sstevel@tonic-gate char *min;
314*7c478bd9Sstevel@tonic-gate char *tail;
315*7c478bd9Sstevel@tonic-gate char tc;
316*7c478bd9Sstevel@tonic-gate int len;
317*7c478bd9Sstevel@tonic-gate
318*7c478bd9Sstevel@tonic-gate /* Trailing comments */
319*7c478bd9Sstevel@tonic-gate if (fep->entry == NULL) {
320*7c478bd9Sstevel@tonic-gate (void) fputs(fep->rawbuf, new);
321*7c478bd9Sstevel@tonic-gate break;
322*7c478bd9Sstevel@tonic-gate }
323*7c478bd9Sstevel@tonic-gate
324*7c478bd9Sstevel@tonic-gate tok = fep->entry;
325*7c478bd9Sstevel@tonic-gate while (*tok && isspace(*tok))
326*7c478bd9Sstevel@tonic-gate tok++;
327*7c478bd9Sstevel@tonic-gate
328*7c478bd9Sstevel@tonic-gate if (*tok == '\0') {
329*7c478bd9Sstevel@tonic-gate (void) fputs(fep->rawbuf, new);
330*7c478bd9Sstevel@tonic-gate break;
331*7c478bd9Sstevel@tonic-gate }
332*7c478bd9Sstevel@tonic-gate
333*7c478bd9Sstevel@tonic-gate /* Make sure we can recover the remainder incl. whitespace */
334*7c478bd9Sstevel@tonic-gate tail = strpbrk(tok, "\t\n ");
335*7c478bd9Sstevel@tonic-gate if (tail == NULL)
336*7c478bd9Sstevel@tonic-gate tail = tok + strlen(tok);
337*7c478bd9Sstevel@tonic-gate tc = *tail;
338*7c478bd9Sstevel@tonic-gate *tail = '\0';
339*7c478bd9Sstevel@tonic-gate
340*7c478bd9Sstevel@tonic-gate if (delall || delrange) {
341*7c478bd9Sstevel@tonic-gate min = strchr(tok, ':');
342*7c478bd9Sstevel@tonic-gate if (min)
343*7c478bd9Sstevel@tonic-gate *min++ = '\0';
344*7c478bd9Sstevel@tonic-gate }
345*7c478bd9Sstevel@tonic-gate
346*7c478bd9Sstevel@tonic-gate len = strlen(tok);
347*7c478bd9Sstevel@tonic-gate if (delrange) {
348*7c478bd9Sstevel@tonic-gate minor_t lo, hi;
349*7c478bd9Sstevel@tonic-gate char type;
350*7c478bd9Sstevel@tonic-gate
351*7c478bd9Sstevel@tonic-gate /*
352*7c478bd9Sstevel@tonic-gate * Delete or shrink overlapping ranges.
353*7c478bd9Sstevel@tonic-gate */
354*7c478bd9Sstevel@tonic-gate if (strncmp(entry, tok, len) == 0 &&
355*7c478bd9Sstevel@tonic-gate entry[len] == ':' &&
356*7c478bd9Sstevel@tonic-gate min != NULL &&
357*7c478bd9Sstevel@tonic-gate parse_minor_range(min, &lo, &hi, &type) == 0 &&
358*7c478bd9Sstevel@tonic-gate (type == rtype || rtype == '\0') &&
359*7c478bd9Sstevel@tonic-gate lo <= rhi && hi >= rlo) {
360*7c478bd9Sstevel@tonic-gate minor_t newlo, newhi;
361*7c478bd9Sstevel@tonic-gate
362*7c478bd9Sstevel@tonic-gate /* Complete overlap, then drop it. */
363*7c478bd9Sstevel@tonic-gate if (lo >= rlo && hi <= rhi)
364*7c478bd9Sstevel@tonic-gate continue;
365*7c478bd9Sstevel@tonic-gate
366*7c478bd9Sstevel@tonic-gate /* Partial overlap, shrink range */
367*7c478bd9Sstevel@tonic-gate if (lo < rlo)
368*7c478bd9Sstevel@tonic-gate newhi = rlo - 1;
369*7c478bd9Sstevel@tonic-gate else
370*7c478bd9Sstevel@tonic-gate newhi = hi;
371*7c478bd9Sstevel@tonic-gate if (hi > rhi)
372*7c478bd9Sstevel@tonic-gate newlo = rhi + 1;
373*7c478bd9Sstevel@tonic-gate else
374*7c478bd9Sstevel@tonic-gate newlo = lo;
375*7c478bd9Sstevel@tonic-gate
376*7c478bd9Sstevel@tonic-gate /* restore NULed character */
377*7c478bd9Sstevel@tonic-gate *tail = tc;
378*7c478bd9Sstevel@tonic-gate
379*7c478bd9Sstevel@tonic-gate /* Split range? */
380*7c478bd9Sstevel@tonic-gate if (newlo > newhi) {
381*7c478bd9Sstevel@tonic-gate /*
382*7c478bd9Sstevel@tonic-gate * We have two ranges:
383*7c478bd9Sstevel@tonic-gate * lo ... newhi (== rlo - 1)
384*7c478bd9Sstevel@tonic-gate * newlo (== rhi + 1) .. hi
385*7c478bd9Sstevel@tonic-gate */
386*7c478bd9Sstevel@tonic-gate put_minor_range(new, fep, tok, tail,
387*7c478bd9Sstevel@tonic-gate lo, newhi, type);
388*7c478bd9Sstevel@tonic-gate put_minor_range(new, NULL, tok, tail,
389*7c478bd9Sstevel@tonic-gate newlo, hi, type);
390*7c478bd9Sstevel@tonic-gate } else {
391*7c478bd9Sstevel@tonic-gate put_minor_range(new, fep, tok, tail,
392*7c478bd9Sstevel@tonic-gate newlo, newhi, type);
393*7c478bd9Sstevel@tonic-gate }
394*7c478bd9Sstevel@tonic-gate continue;
395*7c478bd9Sstevel@tonic-gate }
396*7c478bd9Sstevel@tonic-gate } else if (strcmp(entry, tok) == 0 ||
397*7c478bd9Sstevel@tonic-gate (strncmp(entry, tok, len) == 0 &&
398*7c478bd9Sstevel@tonic-gate entry[len] == ':' &&
399*7c478bd9Sstevel@tonic-gate entry[len+1] == '*' &&
400*7c478bd9Sstevel@tonic-gate entry[len+2] == '\0')) {
401*7c478bd9Sstevel@tonic-gate /*
402*7c478bd9Sstevel@tonic-gate * Delete exact match.
403*7c478bd9Sstevel@tonic-gate */
404*7c478bd9Sstevel@tonic-gate continue;
405*7c478bd9Sstevel@tonic-gate }
406*7c478bd9Sstevel@tonic-gate
407*7c478bd9Sstevel@tonic-gate /* Copy unaffected entry. */
408*7c478bd9Sstevel@tonic-gate (void) fputs(fep->rawbuf, new);
409*7c478bd9Sstevel@tonic-gate }
410*7c478bd9Sstevel@tonic-gate (void) fclose(old);
411*7c478bd9Sstevel@tonic-gate (void) fflush(new);
412*7c478bd9Sstevel@tonic-gate (void) fsync(newfd);
413*7c478bd9Sstevel@tonic-gate if (ferror(new) == 0 && fclose(new) == 0 && fep != NULL) {
414*7c478bd9Sstevel@tonic-gate if (rename(filename, ofile) != 0) {
415*7c478bd9Sstevel@tonic-gate perror(NULL);
416*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), ofile);
417*7c478bd9Sstevel@tonic-gate (void) unlink(ofile);
418*7c478bd9Sstevel@tonic-gate (void) unlink(nfile);
419*7c478bd9Sstevel@tonic-gate return (ERROR);
420*7c478bd9Sstevel@tonic-gate } else if (rename(nfile, filename) != 0) {
421*7c478bd9Sstevel@tonic-gate perror(NULL);
422*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), ofile);
423*7c478bd9Sstevel@tonic-gate (void) rename(ofile, filename);
424*7c478bd9Sstevel@tonic-gate (void) unlink(nfile);
425*7c478bd9Sstevel@tonic-gate return (ERROR);
426*7c478bd9Sstevel@tonic-gate }
427*7c478bd9Sstevel@tonic-gate (void) unlink(ofile);
428*7c478bd9Sstevel@tonic-gate } else
429*7c478bd9Sstevel@tonic-gate (void) unlink(nfile);
430*7c478bd9Sstevel@tonic-gate return (0);
431*7c478bd9Sstevel@tonic-gate }
432*7c478bd9Sstevel@tonic-gate
433*7c478bd9Sstevel@tonic-gate
434*7c478bd9Sstevel@tonic-gate int
delete_plcy_entry(const char * filename,const char * entry)435*7c478bd9Sstevel@tonic-gate delete_plcy_entry(const char *filename, const char *entry)
436*7c478bd9Sstevel@tonic-gate {
437*7c478bd9Sstevel@tonic-gate char *p, *single;
438*7c478bd9Sstevel@tonic-gate char *copy;
439*7c478bd9Sstevel@tonic-gate int ret = 0;
440*7c478bd9Sstevel@tonic-gate
441*7c478bd9Sstevel@tonic-gate copy = strdup(entry);
442*7c478bd9Sstevel@tonic-gate if (copy == NULL)
443*7c478bd9Sstevel@tonic-gate return (ERROR);
444*7c478bd9Sstevel@tonic-gate
445*7c478bd9Sstevel@tonic-gate for (single = strtok_r(copy, " \t\n", &p);
446*7c478bd9Sstevel@tonic-gate single != NULL;
447*7c478bd9Sstevel@tonic-gate single = strtok_r(NULL, " \t\n", &p)) {
448*7c478bd9Sstevel@tonic-gate if ((ret = delete_one_entry(filename, single)) != 0) {
449*7c478bd9Sstevel@tonic-gate free(copy);
450*7c478bd9Sstevel@tonic-gate return (ret);
451*7c478bd9Sstevel@tonic-gate }
452*7c478bd9Sstevel@tonic-gate }
453*7c478bd9Sstevel@tonic-gate free(copy);
454*7c478bd9Sstevel@tonic-gate return (0);
455*7c478bd9Sstevel@tonic-gate }
456*7c478bd9Sstevel@tonic-gate
457*7c478bd9Sstevel@tonic-gate /*
458*7c478bd9Sstevel@tonic-gate * Analyze the device policy token; new tokens should be added to
459*7c478bd9Sstevel@tonic-gate * toktab; new token types should be coded here.
460*7c478bd9Sstevel@tonic-gate */
461*7c478bd9Sstevel@tonic-gate int
parse_plcy_token(char * token,devplcysys_t * dp)462*7c478bd9Sstevel@tonic-gate parse_plcy_token(char *token, devplcysys_t *dp)
463*7c478bd9Sstevel@tonic-gate {
464*7c478bd9Sstevel@tonic-gate char *val = strchr(token, '=');
465*7c478bd9Sstevel@tonic-gate const char *perr;
466*7c478bd9Sstevel@tonic-gate int i;
467*7c478bd9Sstevel@tonic-gate priv_set_t *pset;
468*7c478bd9Sstevel@tonic-gate
469*7c478bd9Sstevel@tonic-gate if (val == NULL) {
470*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_EQUALS), token);
471*7c478bd9Sstevel@tonic-gate return (1);
472*7c478bd9Sstevel@tonic-gate }
473*7c478bd9Sstevel@tonic-gate *val++ = '\0';
474*7c478bd9Sstevel@tonic-gate
475*7c478bd9Sstevel@tonic-gate for (i = 0; i < NTOK; i++) {
476*7c478bd9Sstevel@tonic-gate if (strcmp(token, toktab[i].token) == 0) {
477*7c478bd9Sstevel@tonic-gate /* standard pointer computation for tokens */
478*7c478bd9Sstevel@tonic-gate void *item = (char *)dp + toktab[i].off;
479*7c478bd9Sstevel@tonic-gate
480*7c478bd9Sstevel@tonic-gate switch (toktab[i].type) {
481*7c478bd9Sstevel@tonic-gate case PSET:
482*7c478bd9Sstevel@tonic-gate pset = priv_str_to_set(val, ",", &perr);
483*7c478bd9Sstevel@tonic-gate if (pset == NULL) {
484*7c478bd9Sstevel@tonic-gate if (perr == NULL)
485*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
486*7c478bd9Sstevel@tonic-gate gettext(ERR_NO_MEM));
487*7c478bd9Sstevel@tonic-gate else
488*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
489*7c478bd9Sstevel@tonic-gate gettext(ERR_BAD_PRIVS),
490*7c478bd9Sstevel@tonic-gate perr - val, val, perr);
491*7c478bd9Sstevel@tonic-gate return (1);
492*7c478bd9Sstevel@tonic-gate }
493*7c478bd9Sstevel@tonic-gate priv_copyset(pset, item);
494*7c478bd9Sstevel@tonic-gate priv_freeset(pset);
495*7c478bd9Sstevel@tonic-gate break;
496*7c478bd9Sstevel@tonic-gate default:
497*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
498*7c478bd9Sstevel@tonic-gate "Internal Error: bad token type: %d\n",
499*7c478bd9Sstevel@tonic-gate toktab[i].type);
500*7c478bd9Sstevel@tonic-gate return (1);
501*7c478bd9Sstevel@tonic-gate }
502*7c478bd9Sstevel@tonic-gate /* Standard cleanup & return for good tokens */
503*7c478bd9Sstevel@tonic-gate val[-1] = '=';
504*7c478bd9Sstevel@tonic-gate return (0);
505*7c478bd9Sstevel@tonic-gate }
506*7c478bd9Sstevel@tonic-gate }
507*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_TOKEN), token);
508*7c478bd9Sstevel@tonic-gate return (1);
509*7c478bd9Sstevel@tonic-gate }
510*7c478bd9Sstevel@tonic-gate
511*7c478bd9Sstevel@tonic-gate static int
add2str(char ** dstp,const char * str,size_t * sz)512*7c478bd9Sstevel@tonic-gate add2str(char **dstp, const char *str, size_t *sz)
513*7c478bd9Sstevel@tonic-gate {
514*7c478bd9Sstevel@tonic-gate char *p = *dstp;
515*7c478bd9Sstevel@tonic-gate size_t len = strlen(p) + strlen(str) + 1;
516*7c478bd9Sstevel@tonic-gate
517*7c478bd9Sstevel@tonic-gate if (len > *sz) {
518*7c478bd9Sstevel@tonic-gate *sz *= 2;
519*7c478bd9Sstevel@tonic-gate if (*sz < len)
520*7c478bd9Sstevel@tonic-gate *sz = len;
521*7c478bd9Sstevel@tonic-gate *dstp = p = realloc(p, *sz);
522*7c478bd9Sstevel@tonic-gate if (p == NULL) {
523*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
524*7c478bd9Sstevel@tonic-gate return (-1);
525*7c478bd9Sstevel@tonic-gate }
526*7c478bd9Sstevel@tonic-gate }
527*7c478bd9Sstevel@tonic-gate (void) strcat(p, str);
528*7c478bd9Sstevel@tonic-gate return (0);
529*7c478bd9Sstevel@tonic-gate }
530*7c478bd9Sstevel@tonic-gate
531*7c478bd9Sstevel@tonic-gate /*
532*7c478bd9Sstevel@tonic-gate * Verify that the policy entry is valid and return the canonical entry.
533*7c478bd9Sstevel@tonic-gate */
534*7c478bd9Sstevel@tonic-gate char *
check_plcy_entry(char * entry,const char * driver,boolean_t todel)535*7c478bd9Sstevel@tonic-gate check_plcy_entry(char *entry, const char *driver, boolean_t todel)
536*7c478bd9Sstevel@tonic-gate {
537*7c478bd9Sstevel@tonic-gate char *res;
538*7c478bd9Sstevel@tonic-gate devplcysys_t *ds;
539*7c478bd9Sstevel@tonic-gate char *tok;
540*7c478bd9Sstevel@tonic-gate size_t sz = strlen(entry) * 2 + strlen(driver) + 3;
541*7c478bd9Sstevel@tonic-gate boolean_t tokseen = B_FALSE;
542*7c478bd9Sstevel@tonic-gate
543*7c478bd9Sstevel@tonic-gate devplcy_init();
544*7c478bd9Sstevel@tonic-gate
545*7c478bd9Sstevel@tonic-gate res = malloc(sz);
546*7c478bd9Sstevel@tonic-gate ds = alloca(devplcysys_sz);
547*7c478bd9Sstevel@tonic-gate
548*7c478bd9Sstevel@tonic-gate if (res == NULL || ds == NULL) {
549*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
550*7c478bd9Sstevel@tonic-gate return (NULL);
551*7c478bd9Sstevel@tonic-gate }
552*7c478bd9Sstevel@tonic-gate
553*7c478bd9Sstevel@tonic-gate *res = '\0';
554*7c478bd9Sstevel@tonic-gate
555*7c478bd9Sstevel@tonic-gate while ((tok = strtok(entry, " \t\n")) != NULL) {
556*7c478bd9Sstevel@tonic-gate entry = NULL;
557*7c478bd9Sstevel@tonic-gate
558*7c478bd9Sstevel@tonic-gate /* It's not a token */
559*7c478bd9Sstevel@tonic-gate if (strchr(tok, '=') == NULL) {
560*7c478bd9Sstevel@tonic-gate if (strchr(tok, ':') != NULL) {
561*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_MINOR));
562*7c478bd9Sstevel@tonic-gate free(res);
563*7c478bd9Sstevel@tonic-gate return (NULL);
564*7c478bd9Sstevel@tonic-gate }
565*7c478bd9Sstevel@tonic-gate if (*res != '\0' && add2str(&res, "\n", &sz) != 0)
566*7c478bd9Sstevel@tonic-gate return (NULL);
567*7c478bd9Sstevel@tonic-gate
568*7c478bd9Sstevel@tonic-gate if (*tok == '(') {
569*7c478bd9Sstevel@tonic-gate char type;
570*7c478bd9Sstevel@tonic-gate if (parse_minor_range(tok, &ds->dps_lomin,
571*7c478bd9Sstevel@tonic-gate &ds->dps_himin, &type) != 0 ||
572*7c478bd9Sstevel@tonic-gate (!todel && type == '\0')) {
573*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
574*7c478bd9Sstevel@tonic-gate gettext(ERR_BAD_MINOR));
575*7c478bd9Sstevel@tonic-gate free(res);
576*7c478bd9Sstevel@tonic-gate return (NULL);
577*7c478bd9Sstevel@tonic-gate }
578*7c478bd9Sstevel@tonic-gate } else {
579*7c478bd9Sstevel@tonic-gate char *tmp = strchr(tok, '*');
580*7c478bd9Sstevel@tonic-gate
581*7c478bd9Sstevel@tonic-gate if (tmp != NULL &&
582*7c478bd9Sstevel@tonic-gate strchr(tmp + 1, '*') != NULL) {
583*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
584*7c478bd9Sstevel@tonic-gate gettext(ERR_BAD_MINOR));
585*7c478bd9Sstevel@tonic-gate free(res);
586*7c478bd9Sstevel@tonic-gate }
587*7c478bd9Sstevel@tonic-gate }
588*7c478bd9Sstevel@tonic-gate
589*7c478bd9Sstevel@tonic-gate if (add2str(&res, driver, &sz) != 0)
590*7c478bd9Sstevel@tonic-gate return (NULL);
591*7c478bd9Sstevel@tonic-gate if (add2str(&res, ":", &sz) != 0)
592*7c478bd9Sstevel@tonic-gate return (NULL);
593*7c478bd9Sstevel@tonic-gate if (add2str(&res, tok, &sz) != 0)
594*7c478bd9Sstevel@tonic-gate return (NULL);
595*7c478bd9Sstevel@tonic-gate tokseen = B_FALSE;
596*7c478bd9Sstevel@tonic-gate } else {
597*7c478bd9Sstevel@tonic-gate if (*res == '\0') {
598*7c478bd9Sstevel@tonic-gate if (add2str(&res, driver, &sz) != 0)
599*7c478bd9Sstevel@tonic-gate return (NULL);
600*7c478bd9Sstevel@tonic-gate if (add2str(&res, ":*", &sz) != 0)
601*7c478bd9Sstevel@tonic-gate return (NULL);
602*7c478bd9Sstevel@tonic-gate }
603*7c478bd9Sstevel@tonic-gate if (parse_plcy_token(tok, ds) != 0) {
604*7c478bd9Sstevel@tonic-gate free(res);
605*7c478bd9Sstevel@tonic-gate return (NULL);
606*7c478bd9Sstevel@tonic-gate }
607*7c478bd9Sstevel@tonic-gate
608*7c478bd9Sstevel@tonic-gate if (add2str(&res, "\t", &sz) != 0)
609*7c478bd9Sstevel@tonic-gate return (NULL);
610*7c478bd9Sstevel@tonic-gate if (add2str(&res, tok, &sz) != 0)
611*7c478bd9Sstevel@tonic-gate return (NULL);
612*7c478bd9Sstevel@tonic-gate tokseen = B_TRUE;
613*7c478bd9Sstevel@tonic-gate }
614*7c478bd9Sstevel@tonic-gate }
615*7c478bd9Sstevel@tonic-gate if (todel && tokseen || *res == '\0' || !todel && !tokseen) {
616*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_INVALID_PLCY));
617*7c478bd9Sstevel@tonic-gate free(res);
618*7c478bd9Sstevel@tonic-gate return (NULL);
619*7c478bd9Sstevel@tonic-gate }
620*7c478bd9Sstevel@tonic-gate if (!todel)
621*7c478bd9Sstevel@tonic-gate if (add2str(&res, "\n", &sz) != 0)
622*7c478bd9Sstevel@tonic-gate return (NULL);
623*7c478bd9Sstevel@tonic-gate return (res);
624*7c478bd9Sstevel@tonic-gate }
625*7c478bd9Sstevel@tonic-gate
626*7c478bd9Sstevel@tonic-gate int
update_device_policy(const char * filename,const char * entry,boolean_t repl)627*7c478bd9Sstevel@tonic-gate update_device_policy(const char *filename, const char *entry, boolean_t repl)
628*7c478bd9Sstevel@tonic-gate {
629*7c478bd9Sstevel@tonic-gate FILE *fp;
630*7c478bd9Sstevel@tonic-gate
631*7c478bd9Sstevel@tonic-gate if (repl) {
632*7c478bd9Sstevel@tonic-gate char *dup, *tok, *s1;
633*7c478bd9Sstevel@tonic-gate
634*7c478bd9Sstevel@tonic-gate dup = strdup(entry);
635*7c478bd9Sstevel@tonic-gate if (dup == NULL) {
636*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
637*7c478bd9Sstevel@tonic-gate return (ERROR);
638*7c478bd9Sstevel@tonic-gate }
639*7c478bd9Sstevel@tonic-gate
640*7c478bd9Sstevel@tonic-gate /*
641*7c478bd9Sstevel@tonic-gate * Split the entry in lines; then get the first token
642*7c478bd9Sstevel@tonic-gate * of each line.
643*7c478bd9Sstevel@tonic-gate */
644*7c478bd9Sstevel@tonic-gate for (tok = strtok_r(dup, "\n", &s1); tok != NULL;
645*7c478bd9Sstevel@tonic-gate tok = strtok_r(NULL, "\n", &s1)) {
646*7c478bd9Sstevel@tonic-gate
647*7c478bd9Sstevel@tonic-gate tok = strtok(tok, " \n\t");
648*7c478bd9Sstevel@tonic-gate
649*7c478bd9Sstevel@tonic-gate if (delete_one_entry(filename, tok) != 0) {
650*7c478bd9Sstevel@tonic-gate free(dup);
651*7c478bd9Sstevel@tonic-gate return (ERROR);
652*7c478bd9Sstevel@tonic-gate }
653*7c478bd9Sstevel@tonic-gate }
654*7c478bd9Sstevel@tonic-gate
655*7c478bd9Sstevel@tonic-gate free(dup);
656*7c478bd9Sstevel@tonic-gate }
657*7c478bd9Sstevel@tonic-gate
658*7c478bd9Sstevel@tonic-gate fp = fopen(filename, "a");
659*7c478bd9Sstevel@tonic-gate if (fp == NULL)
660*7c478bd9Sstevel@tonic-gate return (ERROR);
661*7c478bd9Sstevel@tonic-gate
662*7c478bd9Sstevel@tonic-gate (void) fputs(entry, fp);
663*7c478bd9Sstevel@tonic-gate
664*7c478bd9Sstevel@tonic-gate if (fflush(fp) != 0 || fsync(fileno(fp)) != 0 || fclose(fp) != 0)
665*7c478bd9Sstevel@tonic-gate return (ERROR);
666*7c478bd9Sstevel@tonic-gate
667*7c478bd9Sstevel@tonic-gate return (NOERR);
668*7c478bd9Sstevel@tonic-gate }
669*7c478bd9Sstevel@tonic-gate
670*7c478bd9Sstevel@tonic-gate
671*7c478bd9Sstevel@tonic-gate /*
672*7c478bd9Sstevel@tonic-gate * We need to allocate the privileges now or the privilege set
673*7c478bd9Sstevel@tonic-gate * parsing code will not allow them.
674*7c478bd9Sstevel@tonic-gate */
675*7c478bd9Sstevel@tonic-gate int
check_priv_entry(const char * privlist,boolean_t add)676*7c478bd9Sstevel@tonic-gate check_priv_entry(const char *privlist, boolean_t add)
677*7c478bd9Sstevel@tonic-gate {
678*7c478bd9Sstevel@tonic-gate char *l = strdup(privlist);
679*7c478bd9Sstevel@tonic-gate char *pr;
680*7c478bd9Sstevel@tonic-gate
681*7c478bd9Sstevel@tonic-gate if (l == NULL) {
682*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
683*7c478bd9Sstevel@tonic-gate return (ERROR);
684*7c478bd9Sstevel@tonic-gate }
685*7c478bd9Sstevel@tonic-gate
686*7c478bd9Sstevel@tonic-gate while ((pr = strtok_r(l, ",", &l)) != NULL) {
687*7c478bd9Sstevel@tonic-gate /* Privilege already exists */
688*7c478bd9Sstevel@tonic-gate if (priv_getbyname(pr) != -1)
689*7c478bd9Sstevel@tonic-gate continue;
690*7c478bd9Sstevel@tonic-gate
691*7c478bd9Sstevel@tonic-gate if (add && modctl(MODALLOCPRIV, pr) != 0) {
692*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_PRIV), pr,
693*7c478bd9Sstevel@tonic-gate strerror(errno));
694*7c478bd9Sstevel@tonic-gate return (ERROR);
695*7c478bd9Sstevel@tonic-gate }
696*7c478bd9Sstevel@tonic-gate }
697*7c478bd9Sstevel@tonic-gate return (NOERR);
698*7c478bd9Sstevel@tonic-gate }
699