1*f875b4ebSrica /* 2*f875b4ebSrica * CDDL HEADER START 3*f875b4ebSrica * 4*f875b4ebSrica * The contents of this file are subject to the terms of the 5*f875b4ebSrica * Common Development and Distribution License (the "License"). 6*f875b4ebSrica * You may not use this file except in compliance with the License. 7*f875b4ebSrica * 8*f875b4ebSrica * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*f875b4ebSrica * or http://www.opensolaris.org/os/licensing. 10*f875b4ebSrica * See the License for the specific language governing permissions 11*f875b4ebSrica * and limitations under the License. 12*f875b4ebSrica * 13*f875b4ebSrica * When distributing Covered Code, include this CDDL HEADER in each 14*f875b4ebSrica * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*f875b4ebSrica * If applicable, add the following below this CDDL HEADER, with the 16*f875b4ebSrica * fields enclosed by brackets "[]" replaced with your own identifying 17*f875b4ebSrica * information: Portions Copyright [yyyy] [name of copyright owner] 18*f875b4ebSrica * 19*f875b4ebSrica * CDDL HEADER END 20*f875b4ebSrica */ 21*f875b4ebSrica 22*f875b4ebSrica /* 23*f875b4ebSrica * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*f875b4ebSrica * Use is subject to license terms. 25*f875b4ebSrica */ 26*f875b4ebSrica 27*f875b4ebSrica #pragma ident "%Z%%M% %I% %E% SMI" 28*f875b4ebSrica 29*f875b4ebSrica /* 30*f875b4ebSrica * add_allocatable - 31*f875b4ebSrica * a command-line interface to add device to device_allocate and 32*f875b4ebSrica * device_maps. 33*f875b4ebSrica */ 34*f875b4ebSrica 35*f875b4ebSrica #ifndef __EXTENSIONS__ 36*f875b4ebSrica #define __EXTENSIONS__ /* needed for _strtok_r */ 37*f875b4ebSrica #endif 38*f875b4ebSrica 39*f875b4ebSrica #include <sys/types.h> 40*f875b4ebSrica #include <unistd.h> 41*f875b4ebSrica #include <stdlib.h> 42*f875b4ebSrica #include <strings.h> 43*f875b4ebSrica #include <string.h> 44*f875b4ebSrica #include <locale.h> 45*f875b4ebSrica #include <libintl.h> 46*f875b4ebSrica #include <pwd.h> 47*f875b4ebSrica #include <nss_dbdefs.h> 48*f875b4ebSrica #include <auth_attr.h> 49*f875b4ebSrica #include <auth_list.h> 50*f875b4ebSrica #include <zone.h> 51*f875b4ebSrica #include <tsol/label.h> 52*f875b4ebSrica #include <bsm/devices.h> 53*f875b4ebSrica #include <bsm/devalloc.h> 54*f875b4ebSrica 55*f875b4ebSrica #define NO_OVERRIDE -1 56*f875b4ebSrica 57*f875b4ebSrica int check_args(da_args *); 58*f875b4ebSrica int process_args(int, char **, da_args *, char *); 59*f875b4ebSrica int scan_label(char *, char *); 60*f875b4ebSrica void usage(da_args *, char *); 61*f875b4ebSrica 62*f875b4ebSrica int system_labeled = 0; 63*f875b4ebSrica 64*f875b4ebSrica int 65*f875b4ebSrica main(int argc, char *argv[]) 66*f875b4ebSrica { 67*f875b4ebSrica int rc; 68*f875b4ebSrica uid_t uid; 69*f875b4ebSrica char *progname; 70*f875b4ebSrica char pwbuf[NSS_LINELEN_PASSWD]; 71*f875b4ebSrica struct passwd pwd; 72*f875b4ebSrica da_args dargs; 73*f875b4ebSrica devinfo_t devinfo; 74*f875b4ebSrica 75*f875b4ebSrica (void) setlocale(LC_ALL, ""); 76*f875b4ebSrica #if !defined(TEXT_DOMAIN) 77*f875b4ebSrica #define TEXT_DOMAIN "SYS_TEST" 78*f875b4ebSrica #endif 79*f875b4ebSrica (void) textdomain(TEXT_DOMAIN); 80*f875b4ebSrica if ((progname = strrchr(argv[0], '/')) == NULL) 81*f875b4ebSrica progname = argv[0]; 82*f875b4ebSrica else 83*f875b4ebSrica progname++; 84*f875b4ebSrica 85*f875b4ebSrica system_labeled = is_system_labeled(); 86*f875b4ebSrica if (system_labeled) { 87*f875b4ebSrica /* 88*f875b4ebSrica * this command can be run only in the global zone. 89*f875b4ebSrica */ 90*f875b4ebSrica if (getzoneid() != GLOBAL_ZONEID) { 91*f875b4ebSrica (void) fprintf(stderr, "%s%s", progname, 92*f875b4ebSrica gettext(" : must be run in global zone\n")); 93*f875b4ebSrica exit(1); 94*f875b4ebSrica } 95*f875b4ebSrica } else { 96*f875b4ebSrica /* 97*f875b4ebSrica * this command works in Trusted Extensions only. 98*f875b4ebSrica */ 99*f875b4ebSrica (void) fprintf(stderr, "%s%s", progname, 100*f875b4ebSrica gettext(" : need to install Trusted Extensions\n")); 101*f875b4ebSrica exit(1); 102*f875b4ebSrica } 103*f875b4ebSrica 104*f875b4ebSrica dargs.optflag = 0; 105*f875b4ebSrica dargs.rootdir = NULL; 106*f875b4ebSrica dargs.devnames = NULL; 107*f875b4ebSrica dargs.devinfo = &devinfo; 108*f875b4ebSrica 109*f875b4ebSrica if (strcmp(progname, "add_allocatable") == 0) { 110*f875b4ebSrica dargs.optflag |= DA_ADD; 111*f875b4ebSrica } else if (strcmp(progname, "remove_allocatable") == 0) { 112*f875b4ebSrica dargs.optflag |= DA_REMOVE; 113*f875b4ebSrica } else { 114*f875b4ebSrica usage(&dargs, progname); 115*f875b4ebSrica exit(1); 116*f875b4ebSrica } 117*f875b4ebSrica 118*f875b4ebSrica uid = getuid(); 119*f875b4ebSrica if ((getpwuid_r(uid, &pwd, pwbuf, sizeof (pwbuf))) == NULL) { 120*f875b4ebSrica (void) fprintf(stderr, "%s%s", progname, 121*f875b4ebSrica gettext(" : getpwuid_r failed: ")); 122*f875b4ebSrica (void) fprintf(stderr, "%s\n", strerror(errno)); 123*f875b4ebSrica exit(2); 124*f875b4ebSrica } 125*f875b4ebSrica 126*f875b4ebSrica if (chkauthattr(DEVICE_CONFIG_AUTH, pwd.pw_name) != 1) { 127*f875b4ebSrica (void) fprintf(stderr, "%s%s%s", progname, 128*f875b4ebSrica gettext(" : user lacks authorization: \n"), 129*f875b4ebSrica DEVICE_CONFIG_AUTH); 130*f875b4ebSrica exit(4); 131*f875b4ebSrica } 132*f875b4ebSrica 133*f875b4ebSrica if (process_args(argc, argv, &dargs, progname) != 0) { 134*f875b4ebSrica usage(&dargs, progname); 135*f875b4ebSrica exit(1); 136*f875b4ebSrica } 137*f875b4ebSrica 138*f875b4ebSrica if (dargs.optflag & DA_ADD) { 139*f875b4ebSrica if (check_args(&dargs) == NO_OVERRIDE) { 140*f875b4ebSrica (void) fprintf(stderr, "%s%s%s%s", progname, 141*f875b4ebSrica gettext(" : entry exists for "), 142*f875b4ebSrica dargs.devinfo->devname, gettext("\n")); 143*f875b4ebSrica usage(&dargs, progname); 144*f875b4ebSrica exit(3); 145*f875b4ebSrica } 146*f875b4ebSrica } 147*f875b4ebSrica 148*f875b4ebSrica if (dargs.optflag & DA_DEFATTRS) 149*f875b4ebSrica rc = da_update_defattrs(&dargs); 150*f875b4ebSrica else 151*f875b4ebSrica rc = da_update_device(&dargs); 152*f875b4ebSrica 153*f875b4ebSrica if ((rc != 0) && (!(dargs.optflag & DA_SILENT))) { 154*f875b4ebSrica if (rc == -2) 155*f875b4ebSrica (void) fprintf(stderr, "%s%s", progname, 156*f875b4ebSrica gettext(" : device name/type/list missing\n")); 157*f875b4ebSrica else if (dargs.optflag & DA_ADD) 158*f875b4ebSrica (void) fprintf(stderr, "%s%s", progname, 159*f875b4ebSrica gettext(" : error adding/updating device\n")); 160*f875b4ebSrica else if (dargs.optflag & DA_REMOVE) 161*f875b4ebSrica (void) fprintf(stderr, "%s%s", progname, 162*f875b4ebSrica gettext(" : error removing device\n")); 163*f875b4ebSrica rc = 2; /* exit code for 'Unknown system error' in man page */ 164*f875b4ebSrica } 165*f875b4ebSrica 166*f875b4ebSrica return (rc); 167*f875b4ebSrica } 168*f875b4ebSrica 169*f875b4ebSrica int 170*f875b4ebSrica process_args(int argc, char **argv, da_args *dargs, char *progname) 171*f875b4ebSrica { 172*f875b4ebSrica int c; 173*f875b4ebSrica int aflag, cflag, dflag, fflag, lflag, nflag, oflag, tflag; 174*f875b4ebSrica extern char *optarg; 175*f875b4ebSrica devinfo_t *devinfo; 176*f875b4ebSrica 177*f875b4ebSrica devinfo = dargs->devinfo; 178*f875b4ebSrica aflag = cflag = dflag = fflag = lflag = nflag = oflag = tflag = 0; 179*f875b4ebSrica devinfo->devname = devinfo->devtype = devinfo->devauths = 180*f875b4ebSrica devinfo->devexec = devinfo->devopts = devinfo->devlist = NULL; 181*f875b4ebSrica devinfo->instance = 0; 182*f875b4ebSrica 183*f875b4ebSrica while ((c = getopt(argc, argv, "a:c:dfl:n:o:st:")) != EOF) { 184*f875b4ebSrica switch (c) { 185*f875b4ebSrica case 'a': 186*f875b4ebSrica devinfo->devauths = optarg; 187*f875b4ebSrica aflag++; 188*f875b4ebSrica break; 189*f875b4ebSrica case 'c': 190*f875b4ebSrica devinfo->devexec = optarg; 191*f875b4ebSrica if (strlen(devinfo->devexec) == 0) { 192*f875b4ebSrica if (!(dargs->optflag & DA_SILENT)) 193*f875b4ebSrica (void) fprintf(stderr, "%s%s", progname, 194*f875b4ebSrica gettext(" : device clean program" 195*f875b4ebSrica " name not found\n")); 196*f875b4ebSrica return (1); 197*f875b4ebSrica } 198*f875b4ebSrica cflag++; 199*f875b4ebSrica break; 200*f875b4ebSrica case 'd': 201*f875b4ebSrica dargs->optflag |= DA_DEFATTRS; 202*f875b4ebSrica dflag++; 203*f875b4ebSrica break; 204*f875b4ebSrica case 'l': 205*f875b4ebSrica devinfo->devlist = optarg; 206*f875b4ebSrica if (strlen(devinfo->devlist) == 0) { 207*f875b4ebSrica if (!(dargs->optflag & DA_SILENT)) 208*f875b4ebSrica (void) fprintf(stderr, "%s%s", progname, 209*f875b4ebSrica gettext(" : device file list" 210*f875b4ebSrica " not found\n")); 211*f875b4ebSrica return (1); 212*f875b4ebSrica } 213*f875b4ebSrica lflag++; 214*f875b4ebSrica break; 215*f875b4ebSrica case 'f': 216*f875b4ebSrica dargs->optflag |= DA_FORCE; 217*f875b4ebSrica fflag++; 218*f875b4ebSrica break; 219*f875b4ebSrica case 'n': 220*f875b4ebSrica devinfo->devname = optarg; 221*f875b4ebSrica if (strlen(devinfo->devname) == 0) { 222*f875b4ebSrica if (!(dargs->optflag & DA_SILENT)) 223*f875b4ebSrica (void) fprintf(stderr, "%s%s", progname, 224*f875b4ebSrica gettext(" : device name " 225*f875b4ebSrica "not found\n")); 226*f875b4ebSrica return (1); 227*f875b4ebSrica } 228*f875b4ebSrica nflag++; 229*f875b4ebSrica break; 230*f875b4ebSrica case 'o': 231*f875b4ebSrica /* check for field delimiters in the option */ 232*f875b4ebSrica if (strpbrk(optarg, ":;=") == NULL) { 233*f875b4ebSrica if (!(dargs->optflag & DA_SILENT)) { 234*f875b4ebSrica (void) fprintf(stderr, "%s%s%s", 235*f875b4ebSrica progname, 236*f875b4ebSrica gettext(" : invalid " 237*f875b4ebSrica "key=val string: "), 238*f875b4ebSrica optarg); 239*f875b4ebSrica (void) fprintf(stderr, "%s", 240*f875b4ebSrica gettext("\n")); 241*f875b4ebSrica } 242*f875b4ebSrica return (1); 243*f875b4ebSrica } 244*f875b4ebSrica devinfo->devopts = optarg; 245*f875b4ebSrica if (dargs->optflag & DA_ADD) { 246*f875b4ebSrica if (scan_label(devinfo->devopts, progname) != 0) 247*f875b4ebSrica return (1); 248*f875b4ebSrica } 249*f875b4ebSrica oflag++; 250*f875b4ebSrica break; 251*f875b4ebSrica case 's': 252*f875b4ebSrica dargs->optflag |= DA_SILENT; 253*f875b4ebSrica break; 254*f875b4ebSrica case 't': 255*f875b4ebSrica devinfo->devtype = optarg; 256*f875b4ebSrica if (strlen(devinfo->devtype) == 0) { 257*f875b4ebSrica if (!(dargs->optflag & DA_SILENT)) 258*f875b4ebSrica (void) fprintf(stderr, "%s%s", progname, 259*f875b4ebSrica gettext(" : device type " 260*f875b4ebSrica "not found\n")); 261*f875b4ebSrica return (1); 262*f875b4ebSrica } 263*f875b4ebSrica tflag++; 264*f875b4ebSrica break; 265*f875b4ebSrica default : 266*f875b4ebSrica return (1); 267*f875b4ebSrica } 268*f875b4ebSrica } 269*f875b4ebSrica 270*f875b4ebSrica 271*f875b4ebSrica if (dargs->optflag & DA_ADD) { 272*f875b4ebSrica if (dflag) { 273*f875b4ebSrica /* -d requires -t, but does not like -n */ 274*f875b4ebSrica if (nflag || tflag == 0) 275*f875b4ebSrica return (1); 276*f875b4ebSrica } else if (nflag == 0 && tflag == 0 && lflag == 0) { 277*f875b4ebSrica /* require at least -n or -t or -l to be specified */ 278*f875b4ebSrica if (!(dargs->optflag & DA_SILENT)) 279*f875b4ebSrica (void) fprintf(stderr, "%s%s", progname, 280*f875b4ebSrica gettext(" : required options missing\n")); 281*f875b4ebSrica return (1); 282*f875b4ebSrica } 283*f875b4ebSrica } else if (dargs->optflag & DA_REMOVE) { 284*f875b4ebSrica if (dflag) { 285*f875b4ebSrica /* -d requires -t, but does not like -n */ 286*f875b4ebSrica if (nflag || tflag == 0) 287*f875b4ebSrica return (1); 288*f875b4ebSrica } else if (nflag == 0 && tflag == 0) { 289*f875b4ebSrica /* require at least -n or -t to be specified */ 290*f875b4ebSrica if (!(dargs->optflag & DA_SILENT)) 291*f875b4ebSrica (void) fprintf(stderr, "%s%s", progname, 292*f875b4ebSrica gettext(" : required options missing\n")); 293*f875b4ebSrica return (1); 294*f875b4ebSrica } 295*f875b4ebSrica /* there's a bunch not accepted by remove_allocatable */ 296*f875b4ebSrica if (aflag || cflag || lflag || oflag) 297*f875b4ebSrica return (1); 298*f875b4ebSrica } else { 299*f875b4ebSrica return (1); 300*f875b4ebSrica } 301*f875b4ebSrica 302*f875b4ebSrica /* check for option specified more than once */ 303*f875b4ebSrica if (aflag > 1 || cflag > 1 || lflag > 1 || fflag > 1 || 304*f875b4ebSrica nflag > 1 || tflag > 1) { 305*f875b4ebSrica if (!(dargs->optflag & DA_SILENT)) 306*f875b4ebSrica (void) fprintf(stderr, "%s%s", progname, 307*f875b4ebSrica gettext(" : multiple-defined options\n")); 308*f875b4ebSrica return (1); 309*f875b4ebSrica } 310*f875b4ebSrica 311*f875b4ebSrica return (0); 312*f875b4ebSrica } 313*f875b4ebSrica 314*f875b4ebSrica int 315*f875b4ebSrica verify_label(char *token, char *progname) 316*f875b4ebSrica { 317*f875b4ebSrica int error = 0; 318*f875b4ebSrica char *p, *val, *str; 319*f875b4ebSrica 320*f875b4ebSrica if ((strstr(token, DAOPT_MINLABEL) == NULL) && 321*f875b4ebSrica (strstr(token, DAOPT_MAXLABEL) == NULL)) { 322*f875b4ebSrica /* no label specified */ 323*f875b4ebSrica return (0); 324*f875b4ebSrica } 325*f875b4ebSrica if ((val = strchr(token, '=')) == NULL) 326*f875b4ebSrica return (1); 327*f875b4ebSrica val++; 328*f875b4ebSrica /* 329*f875b4ebSrica * if non-default labels are specified, check if they are correct 330*f875b4ebSrica */ 331*f875b4ebSrica if ((strcmp(val, DA_DEFAULT_MIN) != 0) && 332*f875b4ebSrica (strcmp(val, DA_DEFAULT_MAX) != 0)) { 333*f875b4ebSrica m_label_t *slabel = NULL; 334*f875b4ebSrica 335*f875b4ebSrica str = strdup(val); 336*f875b4ebSrica /* get rid of double quotes if they exist */ 337*f875b4ebSrica while (*str == '"') 338*f875b4ebSrica str++; 339*f875b4ebSrica if ((p = strchr(str, '"')) != NULL) 340*f875b4ebSrica *p = '\0'; 341*f875b4ebSrica if (str_to_label(str, &slabel, MAC_LABEL, L_NO_CORRECTION, 342*f875b4ebSrica &error) == -1) { 343*f875b4ebSrica (void) fprintf(stderr, "%s%s%s", progname, 344*f875b4ebSrica gettext(" : bad label input: "), 345*f875b4ebSrica val); 346*f875b4ebSrica (void) fprintf(stderr, "%s", gettext("\n")); 347*f875b4ebSrica free(str); 348*f875b4ebSrica m_label_free(slabel); 349*f875b4ebSrica return (1); 350*f875b4ebSrica } 351*f875b4ebSrica free(str); 352*f875b4ebSrica m_label_free(slabel); 353*f875b4ebSrica } 354*f875b4ebSrica 355*f875b4ebSrica return (0); 356*f875b4ebSrica } 357*f875b4ebSrica 358*f875b4ebSrica int 359*f875b4ebSrica scan_label(char *devopts, char *progname) 360*f875b4ebSrica { 361*f875b4ebSrica char *tok = NULL; 362*f875b4ebSrica char *lasts, *optsarg; 363*f875b4ebSrica 364*f875b4ebSrica if (devopts == NULL) 365*f875b4ebSrica return (0); 366*f875b4ebSrica 367*f875b4ebSrica if ((optsarg = strdup(devopts)) == NULL) 368*f875b4ebSrica return (1); 369*f875b4ebSrica 370*f875b4ebSrica if ((tok = strtok_r(optsarg, KV_TOKEN_DELIMIT, &lasts)) == NULL) 371*f875b4ebSrica return (1); 372*f875b4ebSrica 373*f875b4ebSrica if (verify_label(tok, progname) != 0) { 374*f875b4ebSrica free(optsarg); 375*f875b4ebSrica return (1); 376*f875b4ebSrica } 377*f875b4ebSrica 378*f875b4ebSrica while ((tok = strtok_r(NULL, KV_TOKEN_DELIMIT, &lasts)) != NULL) { 379*f875b4ebSrica if (verify_label(tok, progname) != 0) { 380*f875b4ebSrica free(optsarg); 381*f875b4ebSrica return (1); 382*f875b4ebSrica } 383*f875b4ebSrica } 384*f875b4ebSrica 385*f875b4ebSrica return (0); 386*f875b4ebSrica } 387*f875b4ebSrica 388*f875b4ebSrica int 389*f875b4ebSrica check_args(da_args *dargs) 390*f875b4ebSrica { 391*f875b4ebSrica int nlen; 392*f875b4ebSrica char *kval, *nopts, *ntok, *nstr, 393*f875b4ebSrica *defmin, *defmax, *defauths, *defexec; 394*f875b4ebSrica kva_t *kva; 395*f875b4ebSrica devinfo_t *devinfo; 396*f875b4ebSrica devalloc_t *da = NULL; 397*f875b4ebSrica da_defs_t *da_defs = NULL; 398*f875b4ebSrica 399*f875b4ebSrica devinfo = dargs->devinfo; 400*f875b4ebSrica /* 401*f875b4ebSrica * check if we're updating an existing entry without -f 402*f875b4ebSrica */ 403*f875b4ebSrica setdaent(); 404*f875b4ebSrica da = getdanam(devinfo->devname); 405*f875b4ebSrica enddaent(); 406*f875b4ebSrica if (da && !(dargs->optflag & DA_FORCE)) { 407*f875b4ebSrica freedaent(da); 408*f875b4ebSrica return (NO_OVERRIDE); 409*f875b4ebSrica } 410*f875b4ebSrica if ((devinfo->devopts == NULL) || 411*f875b4ebSrica (strstr(devinfo->devopts, DAOPT_MINLABEL) == NULL) || 412*f875b4ebSrica (strstr(devinfo->devopts, DAOPT_MAXLABEL) == NULL) || 413*f875b4ebSrica (devinfo->devauths == NULL) || 414*f875b4ebSrica (devinfo->devexec == NULL)) { 415*f875b4ebSrica /* fill in defaults as required */ 416*f875b4ebSrica defmin = DA_DEFAULT_MIN; 417*f875b4ebSrica defmax = DA_DEFAULT_MAX; 418*f875b4ebSrica defauths = DEFAULT_DEV_ALLOC_AUTH; 419*f875b4ebSrica defexec = DA_DEFAULT_CLEAN; 420*f875b4ebSrica setdadefent(); 421*f875b4ebSrica if (da_defs = getdadeftype(devinfo->devtype)) { 422*f875b4ebSrica kva = da_defs->devopts; 423*f875b4ebSrica if ((kval = kva_match(kva, DAOPT_MINLABEL)) != NULL) 424*f875b4ebSrica defmin = strdup(kval); 425*f875b4ebSrica if ((kval = kva_match(kva, DAOPT_MAXLABEL)) != NULL) 426*f875b4ebSrica defmax = strdup(kval); 427*f875b4ebSrica if ((kval = kva_match(kva, DAOPT_AUTHS)) != NULL) 428*f875b4ebSrica defauths = strdup(kval); 429*f875b4ebSrica if ((kval = kva_match(kva, DAOPT_CSCRIPT)) != NULL) 430*f875b4ebSrica defexec = strdup(kval); 431*f875b4ebSrica freedadefent(da_defs); 432*f875b4ebSrica } 433*f875b4ebSrica enddadefent(); 434*f875b4ebSrica if (devinfo->devauths == NULL) 435*f875b4ebSrica devinfo->devauths = defauths; 436*f875b4ebSrica if (devinfo->devexec == NULL) 437*f875b4ebSrica devinfo->devexec = defexec; 438*f875b4ebSrica if (devinfo->devopts == NULL) { 439*f875b4ebSrica /* add default minlabel and maxlabel */ 440*f875b4ebSrica nlen = strlen(DAOPT_MINLABEL) + strlen(KV_ASSIGN) + 441*f875b4ebSrica strlen(defmin) + strlen(KV_TOKEN_DELIMIT) + 442*f875b4ebSrica strlen(DAOPT_MAXLABEL) + strlen(KV_ASSIGN) + 443*f875b4ebSrica strlen(defmax) + 1; /* +1 for terminator */ 444*f875b4ebSrica if (nopts = (char *)malloc(nlen)) { 445*f875b4ebSrica (void) snprintf(nopts, nlen, "%s%s%s%s%s%s%s", 446*f875b4ebSrica DAOPT_MINLABEL, KV_ASSIGN, defmin, 447*f875b4ebSrica KV_TOKEN_DELIMIT, 448*f875b4ebSrica DAOPT_MAXLABEL, KV_ASSIGN, defmax); 449*f875b4ebSrica devinfo->devopts = nopts; 450*f875b4ebSrica } 451*f875b4ebSrica } else { 452*f875b4ebSrica if (strstr(devinfo->devopts, DAOPT_MINLABEL) == NULL) { 453*f875b4ebSrica /* add default minlabel */ 454*f875b4ebSrica ntok = DAOPT_MINLABEL; 455*f875b4ebSrica nstr = defmin; 456*f875b4ebSrica nlen = strlen(devinfo->devopts) + 457*f875b4ebSrica strlen(KV_TOKEN_DELIMIT) + 458*f875b4ebSrica strlen(ntok) + strlen(KV_ASSIGN) + 459*f875b4ebSrica strlen(nstr) + 1; 460*f875b4ebSrica if (nopts = (char *)malloc(nlen)) { 461*f875b4ebSrica (void) snprintf(nopts, nlen, 462*f875b4ebSrica "%s%s%s%s%s", 463*f875b4ebSrica devinfo->devopts, KV_TOKEN_DELIMIT, 464*f875b4ebSrica ntok, KV_ASSIGN, nstr); 465*f875b4ebSrica devinfo->devopts = nopts; 466*f875b4ebSrica } 467*f875b4ebSrica } 468*f875b4ebSrica if (strstr(devinfo->devopts, DAOPT_MAXLABEL) == NULL) { 469*f875b4ebSrica /* add default maxlabel */ 470*f875b4ebSrica ntok = DAOPT_MAXLABEL; 471*f875b4ebSrica nstr = defmax; 472*f875b4ebSrica nlen = strlen(devinfo->devopts) + 473*f875b4ebSrica strlen(KV_TOKEN_DELIMIT) + 474*f875b4ebSrica strlen(ntok) + strlen(KV_ASSIGN) + 475*f875b4ebSrica strlen(nstr) + 1; 476*f875b4ebSrica if (nopts = (char *)malloc(nlen)) { 477*f875b4ebSrica (void) snprintf(nopts, nlen, 478*f875b4ebSrica "%s%s%s%s%s", 479*f875b4ebSrica devinfo->devopts, KV_TOKEN_DELIMIT, 480*f875b4ebSrica ntok, KV_ASSIGN, nstr); 481*f875b4ebSrica devinfo->devopts = nopts; 482*f875b4ebSrica } 483*f875b4ebSrica } 484*f875b4ebSrica } 485*f875b4ebSrica } 486*f875b4ebSrica 487*f875b4ebSrica return (0); 488*f875b4ebSrica } 489*f875b4ebSrica 490*f875b4ebSrica void 491*f875b4ebSrica usage(da_args *dargs, char *progname) 492*f875b4ebSrica { 493*f875b4ebSrica if (dargs->optflag & DA_SILENT) 494*f875b4ebSrica return; 495*f875b4ebSrica if (dargs->optflag & DA_ADD) 496*f875b4ebSrica (void) fprintf(stderr, "%s%s%s", gettext("Usage: "), progname, 497*f875b4ebSrica gettext(" [-f][-s][-d] -n name -t type -l device-list" 498*f875b4ebSrica "\n\t[-a authorization] [-c cleaning program] " 499*f875b4ebSrica "[-o key=value]\n")); 500*f875b4ebSrica else if (dargs->optflag & DA_REMOVE) 501*f875b4ebSrica (void) fprintf(stderr, "%s%s%s", gettext("Usage: "), progname, 502*f875b4ebSrica gettext(" [-f][-s][-d] [-n name|-t type]\n")); 503*f875b4ebSrica else 504*f875b4ebSrica (void) fprintf(stderr, gettext("Invalid usage\n"), progname); 505*f875b4ebSrica } 506