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