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 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 * 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 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 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 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 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 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 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 * 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 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 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