xref: /illumos-gate/usr/src/cmd/stmfadm/stmfadm.c (revision 8fe96085)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <strings.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31 #include <wchar.h>
32 #include <libintl.h>
33 #include <errno.h>
34 #include <time.h>
35 #include <string.h>
36 #include <assert.h>
37 #include <getopt.h>
38 #include <cmdparse.h>
39 #include <stmfadm.h>
40 #include <libstmf.h>
41 #include <signal.h>
42 #include <pthread.h>
43 #include <locale.h>
44 
45 static int addHostGroupMemberFunc(int, char **, cmdOptions_t *, void *);
46 static int addTargetGroupMemberFunc(int, char **, cmdOptions_t *, void *);
47 static int addViewFunc(int, char **, cmdOptions_t *, void *);
48 static int createHostGroupFunc(int, char **, cmdOptions_t *, void *);
49 static int createLuFunc(int, char **, cmdOptions_t *, void *);
50 static int modifyLuFunc(int, char **, cmdOptions_t *, void *);
51 static int importLuFunc(int, char **, cmdOptions_t *, void *);
52 static int deleteLuFunc(int, char **, cmdOptions_t *, void *);
53 static int createTargetGroupFunc(int, char **, cmdOptions_t *, void *);
54 static int deleteHostGroupFunc(int, char **, cmdOptions_t *, void *);
55 static int deleteTargetGroupFunc(int, char **, cmdOptions_t *, void *);
56 static int listLuFunc(int, char **, cmdOptions_t *, void *);
57 static int listTargetFunc(int, char **, cmdOptions_t *, void *);
58 static int listViewFunc(int, char **, cmdOptions_t *, void *);
59 static int listHostGroupFunc(int, char **, cmdOptions_t *, void *);
60 static int listStateFunc(int, char **, cmdOptions_t *, void *);
61 static int listTargetGroupFunc(int, char **, cmdOptions_t *, void *);
62 static int offlineTargetFunc(int, char **, cmdOptions_t *, void *);
63 static int offlineLuFunc(int, char **, cmdOptions_t *, void *);
64 static int onlineTargetFunc(int, char **, cmdOptions_t *, void *);
65 static int onlineLuFunc(int, char **, cmdOptions_t *, void *);
66 static int onlineOfflineTarget(char *, int);
67 static int onlineOfflineLu(char *, int);
68 static int removeHostGroupMemberFunc(int, char **, cmdOptions_t *, void *);
69 static int removeTargetGroupMemberFunc(int, char **, cmdOptions_t *, void *);
70 static int callModify(char *, stmfGuid *, uint32_t, const char *, const char *);
71 static int removeViewFunc(int, char **, cmdOptions_t *, void *);
72 static char *getExecBasename(char *);
73 static int parseDevid(char *input, stmfDevid *devid);
74 static void printGroupProps(stmfGroupProperties *groupProps);
75 static int checkScsiNameString(wchar_t *, stmfDevid *);
76 static int checkHexUpper(char *);
77 static int checkIscsiName(wchar_t *);
78 static void printLuProps(stmfLogicalUnitProperties *luProps);
79 static int printExtLuProps(stmfGuid *guid);
80 static void printGuid(stmfGuid *guid, FILE *printWhere);
81 static void printTargetProps(stmfTargetProperties *);
82 static void printSessionProps(stmfSessionList *);
83 static int setLuPropFromInput(luResource, char *);
84 static int convertCharToPropId(char *, uint32_t *);
85 
86 
87 
88 /*
89  *  MAJOR - This should only change when there is an incompatible change made
90  *  to the interfaces or the output.
91  *
92  *  MINOR - This should change whenever there is a new command or new feature
93  *  with no incompatible change.
94  */
95 #define	VERSION_STRING_MAJOR	    "1"
96 #define	VERSION_STRING_MINOR	    "0"
97 #define	MAX_DEVID_INPUT		    256
98 #define	GUID_INPUT		    32
99 #define	MAX_LU_NBR		    16383
100 #define	ONLINE_LU		    0
101 #define	OFFLINE_LU		    1
102 #define	ONLINE_TARGET		    2
103 #define	OFFLINE_TARGET		    3
104 #define	PROPS_FORMAT		    "    %-18s: "
105 #define	VIEW_FORMAT		    "    %-13s: "
106 #define	LVL3_FORMAT		    "        %s"
107 #define	LVL4_FORMAT		    "            %s"
108 
109 /* SCSI Name String length definitions */
110 #define	SNS_EUI_16		    16
111 #define	SNS_EUI_24		    24
112 #define	SNS_EUI_32		    32
113 #define	SNS_NAA_16		    16
114 #define	SNS_NAA_32		    32
115 #define	SNS_WWN_16		    16
116 #define	SNS_IQN_223		    223
117 
118 /* LU Property strings */
119 #define	GUID			    "GUID"
120 #define	ALIAS			    "ALIAS"
121 #define	VID			    "VID"
122 #define	PID			    "PID"
123 #define	META_FILE		    "META"
124 #define	WRITE_PROTECT		    "WP"
125 #define	WRITEBACK_CACHE_DISABLE	    "WCD"
126 #define	COMPANY_ID		    "OUI"
127 #define	BLOCK_SIZE		    "BLK"
128 #define	SERIAL_NUMBER		    "SERIAL"
129 
130 #define	MODIFY_HELP "\n"\
131 "Description: Modify properties of a logical unit. \n" \
132 "Valid properties for -p, --lu-prop are: \n" \
133 "     alias - alias for logical unit (up to 255 chars)\n" \
134 "     wcd   - write cache disabled (true, false)\n" \
135 "     wp    - write protect (true, false)\n\n" \
136 "-f alters the meaning of the operand to be a file name\n" \
137 "rather than a LU name. This allows for modification\n" \
138 "of a logical unit that is not yet imported into stmf\n"
139 
140 #define	CREATE_HELP "\n"\
141 "Description: Create a logical unit. \n" \
142 "Valid properties for -p, --lu-prop are: \n" \
143 "     alias - alias for logical unit (up to 255 chars)\n" \
144 "     blk   - block size in bytes in 2^n\n" \
145 "     guid  - 32 ascii hex characters in NAA format \n" \
146 "     meta  - separate meta data file name\n" \
147 "     oui   - organizational unique identifier\n" \
148 "             6 ascii hex characters of valid format\n" \
149 "     pid   - product identifier (up to 16 chars)\n" \
150 "     serial- serial number (up to 252 chars)\n" \
151 "     vid   - vendor identifier (up to 8 chars)\n" \
152 "     wp    - write protect (true, false)\n" \
153 "     wcd   - write cache disabled (true, false)\n"
154 #define	ADD_VIEW_HELP "\n"\
155 "Description: Add a view entry to a logical unit. \n" \
156 "A view entry is comprised of three elements; the \n" \
157 "logical unit number, the target group name and the\n" \
158 "host group name. These three elements combine together\n" \
159 "to form a view for a given COMSTAR logical unit.\n" \
160 "This view is realized by a client, a SCSI initiator,\n" \
161 "via a REPORT LUNS command. \n"
162 
163 
164 
165 /* tables set up based on cmdparse instructions */
166 
167 /* add new options here */
168 optionTbl_t longOptions[] = {
169 	{"all", no_arg, 'a', NULL},
170 	{"group-name", required_arg, 'g', "group-name"},
171 	{"keep-views", no_arg, 'k', NULL},
172 	{"lu-name", required_arg, 'l', "LU-Name"},
173 	{"lun", required_arg, 'n', "logical-unit-number"},
174 	{"lu-prop", required_arg, 'p', "logical-unit-property=value"},
175 	{"file", no_arg, 'f', "filename"},
176 	{"size", required_arg, 's', "size K/M/G/T/P"},
177 	{"target-group", required_arg, 't', "group-name"},
178 	{"host-group", required_arg, 'h', "group-name"},
179 	{"verbose", no_arg, 'v', NULL},
180 	{NULL, 0, 0, 0}
181 };
182 
183 /*
184  * Add new subcommands here
185  */
186 subCommandProps_t subcommands[] = {
187 	{"add-hg-member", addHostGroupMemberFunc, "g", "g", NULL,
188 		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
189 	{"add-tg-member", addTargetGroupMemberFunc, "g", "g", NULL,
190 		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
191 	{"add-view", addViewFunc, "nth", NULL, NULL,
192 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, ADD_VIEW_HELP},
193 	{"create-hg", createHostGroupFunc, NULL, NULL, NULL,
194 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
195 	{"create-tg", createTargetGroupFunc, NULL, NULL, NULL,
196 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
197 	{"create-lu", createLuFunc, "ps", NULL, NULL, OPERAND_MANDATORY_SINGLE,
198 		"lu file", CREATE_HELP},
199 	{"delete-hg", deleteHostGroupFunc, NULL, NULL, NULL,
200 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
201 	{"modify-lu", modifyLuFunc, "psf", NULL, NULL, OPERAND_MANDATORY_SINGLE,
202 		OPERANDSTRING_LU, MODIFY_HELP},
203 	{"delete-lu", deleteLuFunc, "k", NULL, NULL,
204 		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_LU, NULL},
205 	{"delete-tg", deleteTargetGroupFunc, NULL, NULL, NULL,
206 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
207 	{"import-lu", importLuFunc, NULL, NULL, NULL,
208 		OPERAND_MANDATORY_SINGLE, "file name", NULL},
209 	{"list-hg", listHostGroupFunc, "v", NULL, NULL,
210 		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_GROUP_NAME, NULL},
211 	{"list-lu", listLuFunc, "v", NULL, NULL, OPERAND_OPTIONAL_MULTIPLE,
212 		OPERANDSTRING_LU, NULL},
213 	{"list-state", listStateFunc, NULL, NULL, NULL, OPERAND_NONE, NULL},
214 	{"list-target", listTargetFunc, "v", NULL, NULL,
215 		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_TARGET, NULL},
216 	{"list-tg", listTargetGroupFunc, "v", NULL, NULL,
217 		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_GROUP_NAME, NULL},
218 	{"list-view", listViewFunc, "l", "l", NULL,
219 		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_VIEW_ENTRY, NULL},
220 	{"online-lu", onlineLuFunc, NULL, NULL, NULL,
221 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, NULL},
222 	{"offline-lu", offlineLuFunc, NULL, NULL, NULL,
223 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, NULL},
224 	{"online-target", onlineTargetFunc, NULL, NULL, NULL,
225 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_TARGET, NULL},
226 	{"offline-target", offlineTargetFunc, NULL, NULL, NULL,
227 		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_TARGET, NULL},
228 	{"remove-hg-member", removeHostGroupMemberFunc, "g", "g", NULL,
229 		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
230 	{"remove-tg-member", removeTargetGroupMemberFunc, "g", "g", NULL,
231 		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
232 	{"remove-view", removeViewFunc, "la", "l", NULL,
233 		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_VIEW_ENTRY, NULL},
234 	{NULL, 0, NULL, NULL, 0, NULL, 0, NULL, NULL}
235 };
236 
237 /* globals */
238 char *cmdName;
239 
240 /*
241  * addHostGroupMemberFunc
242  *
243  * Add members to a host group
244  *
245  */
246 /*ARGSUSED*/
247 static int
248 addHostGroupMemberFunc(int operandLen, char *operands[], cmdOptions_t *options,
249     void *args)
250 {
251 	int i;
252 	int ret = 0;
253 	int stmfRet;
254 	stmfGroupName groupName = {0};
255 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
256 	stmfDevid devid;
257 
258 	for (; options->optval; options++) {
259 		switch (options->optval) {
260 			/* host group name */
261 			case 'g':
262 				(void) mbstowcs(groupNamePrint, options->optarg,
263 				    sizeof (stmfGroupName) - 1);
264 				bcopy(options->optarg, groupName,
265 				    strlen(options->optarg));
266 				break;
267 			default:
268 				(void) fprintf(stderr, "%s: %c: %s\n",
269 				    cmdName, options->optval,
270 				    gettext("unknown option"));
271 				return (1);
272 		}
273 	}
274 
275 	for (i = 0; i < operandLen; i++) {
276 		if (parseDevid(operands[i], &devid) != 0) {
277 			(void) fprintf(stderr, "%s: %s: %s\n",
278 			    cmdName, operands[i],
279 			    gettext("unrecognized device id"));
280 			ret++;
281 			continue;
282 		}
283 		stmfRet = stmfAddToHostGroup(&groupName, &devid);
284 		switch (stmfRet) {
285 			case STMF_STATUS_SUCCESS:
286 				break;
287 			case STMF_ERROR_EXISTS:
288 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
289 				    operands[i], gettext("already exists"));
290 				ret++;
291 				break;
292 			case STMF_ERROR_GROUP_NOT_FOUND:
293 				(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
294 				    groupNamePrint, gettext("not found"));
295 				ret++;
296 				break;
297 			case STMF_ERROR_PERM:
298 				(void) fprintf(stderr, "%s: %s\n", cmdName,
299 				    gettext("permission denied"));
300 				break;
301 			case STMF_ERROR_BUSY:
302 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
303 				    operands[i], gettext("resource busy"));
304 				ret++;
305 				break;
306 			case STMF_ERROR_SERVICE_NOT_FOUND:
307 				(void) fprintf(stderr, "%s: %s\n", cmdName,
308 				    gettext("STMF service not found"));
309 				ret++;
310 				break;
311 			case STMF_ERROR_SERVICE_DATA_VERSION:
312 				(void) fprintf(stderr, "%s: %s\n", cmdName,
313 				    gettext("STMF service version incorrect"));
314 				ret++;
315 				break;
316 			default:
317 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
318 				    operands[i], gettext("unknown error"));
319 				ret++;
320 				break;
321 		}
322 	}
323 
324 	return (ret);
325 }
326 
327 /*
328  * addTargetGroupMemberFunc
329  *
330  * Add members to a target group
331  *
332  */
333 /*ARGSUSED*/
334 static int
335 addTargetGroupMemberFunc(int operandLen, char *operands[],
336     cmdOptions_t *options, void *args)
337 {
338 	int i;
339 	int ret = 0;
340 	int stmfRet;
341 	stmfGroupName groupName = {0};
342 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
343 	stmfDevid devid;
344 
345 	for (; options->optval; options++) {
346 		switch (options->optval) {
347 			/* target group name */
348 			case 'g':
349 				(void) mbstowcs(groupNamePrint, options->optarg,
350 				    sizeof (stmfGroupName) - 1);
351 				bcopy(options->optarg, groupName,
352 				    strlen(options->optarg));
353 				break;
354 			default:
355 				(void) fprintf(stderr, "%s: %c: %s\n",
356 				    cmdName, options->optval,
357 				    gettext("unknown option"));
358 				return (1);
359 		}
360 	}
361 
362 	for (i = 0; i < operandLen; i++) {
363 		if (parseDevid(operands[i], &devid) != 0) {
364 			(void) fprintf(stderr, "%s: %s: %s\n",
365 			    cmdName, operands[i],
366 			    gettext("unrecognized device id"));
367 			ret++;
368 			continue;
369 		}
370 		stmfRet = stmfAddToTargetGroup(&groupName, &devid);
371 		switch (stmfRet) {
372 			case STMF_STATUS_SUCCESS:
373 				break;
374 			case STMF_ERROR_EXISTS:
375 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
376 				    operands[i], gettext("already exists"));
377 				ret++;
378 				break;
379 			case STMF_ERROR_GROUP_NOT_FOUND:
380 				(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
381 				    groupNamePrint, gettext("not found"));
382 				ret++;
383 				break;
384 			case STMF_ERROR_PERM:
385 				(void) fprintf(stderr, "%s: %s\n", cmdName,
386 				    gettext("permission denied"));
387 				break;
388 			case STMF_ERROR_BUSY:
389 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
390 				    operands[i], gettext("resource busy"));
391 				ret++;
392 				break;
393 			case STMF_ERROR_SERVICE_NOT_FOUND:
394 				(void) fprintf(stderr, "%s: %s\n", cmdName,
395 				    gettext("STMF service not found"));
396 				ret++;
397 				break;
398 			case STMF_ERROR_SERVICE_ONLINE:
399 				(void) fprintf(stderr, "%s: %s\n", cmdName,
400 				    gettext("STMF service must be offline"));
401 				ret++;
402 				break;
403 			case STMF_ERROR_SERVICE_DATA_VERSION:
404 				(void) fprintf(stderr, "%s: %s\n", cmdName,
405 				    gettext("STMF service version incorrect"));
406 				ret++;
407 				break;
408 			default:
409 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
410 				    operands[i], gettext("unknown error"));
411 				ret++;
412 				break;
413 		}
414 	}
415 
416 	return (ret);
417 }
418 
419 /*
420  * parseDevid
421  *
422  * Converts char * input to a stmfDevid
423  *
424  * input - this should be in the following format with either a
425  * wwn. iqn. or eui. representation.
426  * A name string of the format:
427  *	wwn.<WWN> (FC/SAS address)
428  *	iqn.<iSCSI name> (iSCSI iqn)
429  *	eui.<WWN> (iSCSI eui name)
430  *
431  * devid - pointer to stmfDevid structure allocated by the caller.
432  *
433  * Returns:
434  *  0 on success
435  *  non-zero on failure
436  */
437 static int
438 parseDevid(char *input, stmfDevid *devid)
439 {
440 	wchar_t inputWc[MAX_DEVID_INPUT + 1] = {0};
441 
442 	/* convert to wcs */
443 	(void) mbstowcs(inputWc, input, MAX_DEVID_INPUT);
444 
445 	/*
446 	 * Check for known scsi name string formats
447 	 * If one is found, we're done
448 	 * If not, then it's a failure to parse
449 	 */
450 	if (checkScsiNameString(inputWc, devid) == 0) {
451 		return (0);
452 	}
453 
454 	return (-1);
455 }
456 
457 /*
458  * checkScsiNameString
459  *
460  * Validates known SCSI name string formats and converts to stmfDevid
461  * format
462  *
463  * input - input SCSI name string
464  * devid - pointer to stmfDevid structure allocated by the caller
465  *         on successful return, contains the devid based on input
466  *
467  * returns:
468  *         0 on success
469  *         -1 on failure
470  */
471 static int
472 checkScsiNameString(wchar_t *input, stmfDevid *devid)
473 {
474 	char *mbString = NULL;
475 	int mbStringLen;
476 	int len;
477 	int i;
478 
479 	/*
480 	 * Convert to multi-byte string
481 	 *
482 	 * This is used for either eui or naa formats
483 	 */
484 	mbString = calloc(1, (mbStringLen = wcstombs(mbString, input, 0)) + 1);
485 	if (mbString == NULL) {
486 		(void) fprintf(stderr, "%s: %s\n",
487 		    cmdName, "Insufficient memory\n");
488 		return (-1);
489 	}
490 	if (wcstombs(mbString, input, mbStringLen) == (size_t)-1) {
491 		return (-1);
492 	}
493 
494 	/*
495 	 * check for iqn format
496 	 */
497 	if (strncmp(mbString, "iqn.", 4) == 0) {
498 		if ((len = strlen(mbString)) > (SNS_IQN_223)) {
499 			return (-1);
500 		}
501 		for (i = 0; i < len; i++) {
502 			mbString[i] = tolower(mbString[i]);
503 		}
504 		if (checkIscsiName(input + 4) != 0) {
505 			return (-1);
506 		}
507 	} else if (strncmp(mbString, "wwn.", 4) == 0) {
508 		if ((len = strlen(mbString + 4)) != SNS_WWN_16) {
509 			return (-1);
510 		} else if (checkHexUpper(mbString + 4) != 0) {
511 			return (-1);
512 		}
513 	} else if (strncmp(mbString, "eui.", 4) == 0) {
514 		if ((len = strlen(mbString + 4)) != SNS_EUI_16) {
515 			return (-1);
516 		} else if (checkHexUpper(mbString + 4) != 0) {
517 			return (-1);
518 		}
519 	} else {
520 		return (-1);
521 	}
522 
523 	/*
524 	 * We have a validated name string.
525 	 * Go ahead and set the length and copy it.
526 	 */
527 	devid->identLength = strlen(mbString);
528 	bzero(devid->ident, STMF_IDENT_LENGTH);
529 	bcopy(mbString, devid->ident, devid->identLength);
530 
531 	return (0);
532 }
533 
534 
535 /*
536  * Checks whether the entire string is in hex and converts to upper
537  */
538 static int
539 checkHexUpper(char *input)
540 {
541 	int i;
542 
543 	for (i = 0; i < strlen(input); i++) {
544 		if (isxdigit(input[i])) {
545 			input[i] = toupper(input[i]);
546 			continue;
547 		}
548 		return (-1);
549 	}
550 
551 	return (0);
552 }
553 
554 /*
555  * checkIscsiName
556  *
557  * Purpose: Basic string checking on name
558  */
559 static int
560 checkIscsiName(wchar_t *input)
561 {
562 	int i;
563 
564 	for (i = 0; input[i] != 0; i++) {
565 		if (!iswalnum(input[i]) && input[i] != '-' &&
566 		    input[i] != '.' && input[i] != ':') {
567 			return (-1);
568 		}
569 	}
570 
571 	return (0);
572 }
573 
574 
575 /*
576  * addViewFunc
577  *
578  * Adds a view entry to a logical unit
579  *
580  */
581 /*ARGSUSED*/
582 static int
583 addViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
584     void *args)
585 {
586 	stmfViewEntry viewEntry;
587 	stmfGuid inGuid;
588 	unsigned int guid[sizeof (stmfGuid)];
589 	uint16_t inputLuNbr;
590 	int ret = 0;
591 	int stmfRet;
592 	int i;
593 	char sGuid[GUID_INPUT + 1];
594 
595 	bzero(&viewEntry, sizeof (viewEntry));
596 	/* init view entry structure */
597 	viewEntry.allHosts = B_TRUE;
598 	viewEntry.allTargets = B_TRUE;
599 	viewEntry.luNbrValid = B_FALSE;
600 
601 	/* check input length */
602 	if (strlen(operands[0]) != GUID_INPUT) {
603 		(void) fprintf(stderr, "%s: %s: %s%d%s\n", cmdName, operands[0],
604 		    gettext("must be "), GUID_INPUT,
605 		    gettext(" hexadecimal digits"));
606 		return (1);
607 	}
608 
609 	for (; options->optval; options++) {
610 		switch (options->optval) {
611 			/* logical unit number */
612 			case 'n':
613 				viewEntry.luNbrValid = B_TRUE;
614 				inputLuNbr = atoi(options->optarg);
615 				if (inputLuNbr > MAX_LU_NBR) {
616 					(void) fprintf(stderr, "%s: %d: %s\n",
617 					    cmdName, inputLuNbr,
618 					    gettext("Logical unit number"
619 					    " must be less than 16384"));
620 					return (1);
621 				}
622 				viewEntry.luNbr[0] = inputLuNbr >> 8;
623 				viewEntry.luNbr[1] = inputLuNbr & 0xff;
624 				break;
625 			/* host group */
626 			case 'h':
627 				viewEntry.allHosts = B_FALSE;
628 				bcopy(options->optarg, viewEntry.hostGroup,
629 				    strlen(options->optarg));
630 				break;
631 			/* target group */
632 			case 't':
633 				viewEntry.allTargets = B_FALSE;
634 				bcopy(options->optarg, viewEntry.targetGroup,
635 				    strlen(options->optarg));
636 				break;
637 			default:
638 				(void) fprintf(stderr, "%s: %c: %s\n",
639 				    cmdName, options->optval,
640 				    gettext("unknown option"));
641 				return (1);
642 		}
643 	}
644 
645 	/* convert to lower case for scan */
646 	for (i = 0; i < 32; i++)
647 		sGuid[i] = tolower(operands[0][i]);
648 	sGuid[i] = 0;
649 
650 	(void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
651 	    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
652 	    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
653 	    &guid[12], &guid[13], &guid[14], &guid[15]);
654 
655 	for (i = 0; i < sizeof (stmfGuid); i++) {
656 		inGuid.guid[i] = guid[i];
657 	}
658 
659 	/* add the view entry */
660 	stmfRet = stmfAddViewEntry(&inGuid, &viewEntry);
661 	switch (stmfRet) {
662 		case STMF_STATUS_SUCCESS:
663 			break;
664 		case STMF_ERROR_EXISTS:
665 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
666 			    operands[0], gettext("already exists"));
667 			ret++;
668 			break;
669 		case STMF_ERROR_BUSY:
670 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
671 			    operands[0], gettext("resource busy"));
672 			ret++;
673 			break;
674 		case STMF_ERROR_SERVICE_NOT_FOUND:
675 			(void) fprintf(stderr, "%s: %s\n", cmdName,
676 			    gettext("STMF service not found"));
677 			ret++;
678 			break;
679 		case STMF_ERROR_PERM:
680 			(void) fprintf(stderr, "%s: %s\n", cmdName,
681 			    gettext("permission denied"));
682 			ret++;
683 			break;
684 		case STMF_ERROR_LUN_IN_USE:
685 			(void) fprintf(stderr, "%s: %s\n", cmdName,
686 			    gettext("LUN already in use"));
687 			ret++;
688 			break;
689 		case STMF_ERROR_VE_CONFLICT:
690 			(void) fprintf(stderr, "%s: %s\n", cmdName,
691 			    gettext("view entry exists"));
692 			ret++;
693 			break;
694 		case STMF_ERROR_CONFIG_NONE:
695 			(void) fprintf(stderr, "%s: %s\n", cmdName,
696 			    gettext("STMF service is not initialized"));
697 			ret++;
698 			break;
699 		case STMF_ERROR_SERVICE_DATA_VERSION:
700 			(void) fprintf(stderr, "%s: %s\n", cmdName,
701 			    gettext("STMF service version incorrect"));
702 			ret++;
703 			break;
704 		case STMF_ERROR_INVALID_HG:
705 			(void) fprintf(stderr, "%s: %s\n", cmdName,
706 			    gettext("invalid host group"));
707 			ret++;
708 			break;
709 		case STMF_ERROR_INVALID_TG:
710 			(void) fprintf(stderr, "%s: %s\n", cmdName,
711 			    gettext("invalid target group"));
712 			ret++;
713 			break;
714 		default:
715 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
716 			    operands[0], gettext("unknown error"));
717 			ret++;
718 			break;
719 	}
720 
721 	return (ret);
722 }
723 
724 /*
725  * createHostGroupFunc
726  *
727  * Create a host group
728  *
729  */
730 /*ARGSUSED*/
731 static int
732 createHostGroupFunc(int operandLen, char *operands[],
733     cmdOptions_t *options, void *args)
734 {
735 	int ret = 0;
736 	int stmfRet;
737 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
738 	stmfGroupName groupName = {0};
739 
740 	(void) strlcpy(groupName, operands[0], sizeof (groupName));
741 	(void) mbstowcs(groupNamePrint, (char *)groupName,
742 	    sizeof (stmfGroupName) - 1);
743 	/* call create group */
744 	stmfRet = stmfCreateHostGroup(&groupName);
745 	switch (stmfRet) {
746 		case STMF_STATUS_SUCCESS:
747 			break;
748 		case STMF_ERROR_EXISTS:
749 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
750 			    operands[0], gettext("already exists"));
751 			ret++;
752 			break;
753 		case STMF_ERROR_BUSY:
754 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
755 			    operands[0], gettext("resource busy"));
756 			ret++;
757 			break;
758 		case STMF_ERROR_SERVICE_NOT_FOUND:
759 			(void) fprintf(stderr, "%s: %s\n", cmdName,
760 			    gettext("STMF service not found"));
761 			ret++;
762 			break;
763 		case STMF_ERROR_PERM:
764 			(void) fprintf(stderr, "%s: %s\n", cmdName,
765 			    gettext("permission denied"));
766 			ret++;
767 			break;
768 		case STMF_ERROR_SERVICE_DATA_VERSION:
769 			(void) fprintf(stderr, "%s: %s\n", cmdName,
770 			    gettext("STMF service version incorrect"));
771 			ret++;
772 			break;
773 		default:
774 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
775 			    operands[0], gettext("unknown error"));
776 			ret++;
777 			break;
778 	}
779 
780 	return (ret);
781 }
782 
783 /*
784  * createLuFunc
785  *
786  * Create a logical unit
787  *
788  */
789 /*ARGSUSED*/
790 static int
791 createLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
792     void *args)
793 {
794 	luResource hdl = NULL;
795 	int ret = 0;
796 	int stmfRet = 0;
797 	char guidAsciiBuf[33];
798 	stmfGuid createdGuid;
799 
800 	stmfRet = stmfCreateLuResource(STMF_DISK, &hdl);
801 
802 	if (stmfRet != STMF_STATUS_SUCCESS) {
803 		(void) fprintf(stderr, "%s: %s\n",
804 		    cmdName, gettext("Failure to create lu resource\n"));
805 		return (1);
806 	}
807 
808 	for (; options->optval; options++) {
809 		switch (options->optval) {
810 			case 'p':
811 				ret = setLuPropFromInput(hdl, options->optarg);
812 				if (ret != 0) {
813 					(void) stmfFreeLuResource(hdl);
814 					return (1);
815 				}
816 				break;
817 			case 's':
818 				stmfRet = stmfSetLuProp(hdl, STMF_LU_PROP_SIZE,
819 				    options->optarg);
820 				if (stmfRet != STMF_STATUS_SUCCESS) {
821 					(void) fprintf(stderr, "%s: %c: %s\n",
822 					    cmdName, options->optval,
823 					    gettext("size param invalid"));
824 					(void) stmfFreeLuResource(hdl);
825 					return (1);
826 				}
827 				break;
828 			default:
829 				(void) fprintf(stderr, "%s: %c: %s\n",
830 				    cmdName, options->optval,
831 				    gettext("unknown option"));
832 				return (1);
833 		}
834 	}
835 
836 	stmfRet = stmfSetLuProp(hdl, STMF_LU_PROP_FILENAME, operands[0]);
837 
838 	if (stmfRet != STMF_STATUS_SUCCESS) {
839 		(void) fprintf(stderr, "%s: %s\n",
840 		    cmdName, gettext("could not set filename"));
841 		return (1);
842 	}
843 
844 	stmfRet = stmfCreateLu(hdl, &createdGuid);
845 	switch (stmfRet) {
846 		case STMF_STATUS_SUCCESS:
847 			break;
848 		case STMF_ERROR_BUSY:
849 		case STMF_ERROR_LU_BUSY:
850 			(void) fprintf(stderr, "%s: %s\n", cmdName,
851 			    gettext("resource busy"));
852 			ret++;
853 			break;
854 		case STMF_ERROR_PERM:
855 			(void) fprintf(stderr, "%s: %s\n", cmdName,
856 			    gettext("permission denied"));
857 			ret++;
858 			break;
859 		case STMF_ERROR_FILE_IN_USE:
860 			(void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
861 			    operands[0], gettext("in use"));
862 			ret++;
863 			break;
864 		case STMF_ERROR_INVALID_BLKSIZE:
865 			(void) fprintf(stderr, "%s: %s\n", cmdName,
866 			    gettext("invalid block size"));
867 			ret++;
868 			break;
869 		case STMF_ERROR_GUID_IN_USE:
870 			(void) fprintf(stderr, "%s: %s\n", cmdName,
871 			    gettext("guid in use"));
872 			ret++;
873 			break;
874 		case STMF_ERROR_META_FILE_NAME:
875 			(void) fprintf(stderr, "%s: %s\n", cmdName,
876 			    gettext("meta file error"));
877 			ret++;
878 			break;
879 		case STMF_ERROR_DATA_FILE_NAME:
880 			(void) fprintf(stderr, "%s: %s\n", cmdName,
881 			    gettext("data file error"));
882 			ret++;
883 			break;
884 		case STMF_ERROR_FILE_SIZE_INVALID:
885 			(void) fprintf(stderr, "%s: %s\n", cmdName,
886 			    gettext("file size invalid"));
887 			ret++;
888 			break;
889 		case STMF_ERROR_SIZE_OUT_OF_RANGE:
890 			(void) fprintf(stderr, "%s: %s\n", cmdName,
891 			    gettext("invalid size"));
892 			ret++;
893 			break;
894 		case STMF_ERROR_META_CREATION:
895 			(void) fprintf(stderr, "%s: %s\n", cmdName,
896 			    gettext("could not create meta file"));
897 			ret++;
898 			break;
899 		case STMF_ERROR_WRITE_CACHE_SET:
900 			(void) fprintf(stderr, "%s: %s\n", cmdName,
901 			    gettext("could not set write cache"));
902 			ret++;
903 			break;
904 		default:
905 			(void) fprintf(stderr, "%s: %s\n", cmdName,
906 			    gettext("unknown error"));
907 			ret++;
908 			break;
909 	}
910 
911 	if (ret != 0) {
912 		goto done;
913 	}
914 
915 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
916 	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
917 	    "%02X%02X%02X%02X%02X%02X",
918 	    createdGuid.guid[0], createdGuid.guid[1], createdGuid.guid[2],
919 	    createdGuid.guid[3], createdGuid.guid[4], createdGuid.guid[5],
920 	    createdGuid.guid[6], createdGuid.guid[7], createdGuid.guid[8],
921 	    createdGuid.guid[9], createdGuid.guid[10], createdGuid.guid[11],
922 	    createdGuid.guid[12], createdGuid.guid[13], createdGuid.guid[14],
923 	    createdGuid.guid[15]);
924 	(void) printf("Logical unit created: %s\n", guidAsciiBuf);
925 
926 done:
927 	(void) stmfFreeLuResource(hdl);
928 	return (ret);
929 }
930 
931 /*
932  * createLuFunc
933  *
934  * Create a logical unit
935  *
936  */
937 /*ARGSUSED*/
938 static int
939 modifyLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
940     void *args)
941 {
942 	stmfGuid inGuid;
943 	unsigned int guid[sizeof (stmfGuid)];
944 	int ret = 0;
945 	int i;
946 	char *fname = NULL;
947 	char *lasts = NULL;
948 	char sGuid[GUID_INPUT + 1];
949 	char *prop = NULL;
950 	char *propVal = NULL;
951 	boolean_t fnameUsed = B_FALSE;
952 	uint32_t propId;
953 	cmdOptions_t *optionStart = options;
954 
955 
956 	for (; options->optval; options++) {
957 		switch (options->optval) {
958 			case 'f':
959 				fnameUsed = B_TRUE;
960 				fname = operands[0];
961 				break;
962 		}
963 	}
964 	options = optionStart;
965 
966 	/* check input length */
967 	if (!fnameUsed && strlen(operands[0]) != GUID_INPUT) {
968 		(void) fprintf(stderr, "%s: %s: %s%d%s\n", cmdName, operands[0],
969 		    gettext("must be "), GUID_INPUT,
970 		    gettext(" hexadecimal digits"));
971 		return (1);
972 	}
973 
974 	if (!fnameUsed) {
975 		/* convert to lower case for scan */
976 		for (i = 0; i < 32; i++)
977 			sGuid[i] = tolower(operands[0][i]);
978 		sGuid[i] = 0;
979 		(void) sscanf(sGuid,
980 		    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
981 		    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
982 		    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10],
983 		    &guid[11], &guid[12], &guid[13], &guid[14], &guid[15]);
984 
985 		for (i = 0; i < sizeof (stmfGuid); i++) {
986 			inGuid.guid[i] = guid[i];
987 		}
988 	}
989 
990 	for (; options->optval; options++) {
991 		switch (options->optval) {
992 			case 'p':
993 				prop = strtok_r(options->optarg, "=", &lasts);
994 				if ((propVal = strtok_r(NULL, "=", &lasts))
995 				    == NULL) {
996 					(void) fprintf(stderr, "%s: %s: %s\n",
997 					    cmdName, options->optarg,
998 					gettext("invalid property specifier"
999 					    "- prop=val\n"));
1000 					return (1);
1001 				}
1002 				ret = convertCharToPropId(prop, &propId);
1003 				if (ret != 0) {
1004 					(void) fprintf(stderr, "%s: %s: %s\n",
1005 					    cmdName,
1006 					gettext("invalid property specified"),
1007 					    prop);
1008 					return (1);
1009 				}
1010 				if (callModify(fname, &inGuid, propId, propVal,
1011 				    prop) != 0) {
1012 					return (1);
1013 				}
1014 				break;
1015 			case 's':
1016 				if (callModify(fname, &inGuid,
1017 				    STMF_LU_PROP_SIZE, options->optarg,
1018 				    "size") != 0) {
1019 					return (1);
1020 				}
1021 				break;
1022 			case 'f':
1023 				break;
1024 			default:
1025 				(void) fprintf(stderr, "%s: %c: %s\n",
1026 				    cmdName, options->optval,
1027 				    gettext("unknown option"));
1028 				return (1);
1029 		}
1030 	}
1031 	return (ret);
1032 }
1033 
1034 static int
1035 callModify(char *fname, stmfGuid *luGuid, uint32_t prop, const char *propVal,
1036     const char *propString)
1037 {
1038 	int ret = 0;
1039 	int stmfRet = 0;
1040 
1041 	if (!fname) {
1042 		stmfRet = stmfModifyLu(luGuid, prop, propVal);
1043 	} else {
1044 		stmfRet = stmfModifyLuByFname(STMF_DISK, fname, prop,
1045 		    propVal);
1046 	}
1047 	switch (stmfRet) {
1048 		case STMF_STATUS_SUCCESS:
1049 			break;
1050 		case STMF_ERROR_BUSY:
1051 		case STMF_ERROR_LU_BUSY:
1052 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1053 			    gettext("resource busy"));
1054 			ret++;
1055 			break;
1056 		case STMF_ERROR_PERM:
1057 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1058 			    gettext("permission denied"));
1059 			ret++;
1060 			break;
1061 		case STMF_ERROR_INVALID_BLKSIZE:
1062 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1063 			    gettext("invalid block size"));
1064 			ret++;
1065 			break;
1066 		case STMF_ERROR_GUID_IN_USE:
1067 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1068 			    gettext("guid in use"));
1069 			ret++;
1070 			break;
1071 		case STMF_ERROR_META_FILE_NAME:
1072 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1073 			    gettext("meta file error"));
1074 			ret++;
1075 			break;
1076 		case STMF_ERROR_DATA_FILE_NAME:
1077 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1078 			    gettext("data file error"));
1079 			ret++;
1080 			break;
1081 		case STMF_ERROR_FILE_SIZE_INVALID:
1082 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1083 			    gettext("file size invalid"));
1084 			ret++;
1085 			break;
1086 		case STMF_ERROR_SIZE_OUT_OF_RANGE:
1087 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1088 			    gettext("invalid size"));
1089 			ret++;
1090 			break;
1091 		case STMF_ERROR_META_CREATION:
1092 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1093 			    gettext("could not create meta file"));
1094 			ret++;
1095 			break;
1096 		case STMF_ERROR_INVALID_PROP:
1097 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1098 			    gettext("invalid property for modify"));
1099 			ret++;
1100 			break;
1101 		case STMF_ERROR_WRITE_CACHE_SET:
1102 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1103 			    gettext("could not set write cache"));
1104 			ret++;
1105 			break;
1106 		default:
1107 			(void) fprintf(stderr, "%s: %s: %s: %d\n", cmdName,
1108 			    gettext("could not set property"), propString,
1109 			    stmfRet);
1110 			ret++;
1111 			break;
1112 	}
1113 
1114 	return (ret);
1115 }
1116 
1117 
1118 /*
1119  * importLuFunc
1120  *
1121  * Create a logical unit
1122  *
1123  */
1124 /*ARGSUSED*/
1125 static int
1126 importLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
1127     void *args)
1128 {
1129 	int stmfRet = 0;
1130 	int ret = 0;
1131 	char guidAsciiBuf[33];
1132 	stmfGuid createdGuid;
1133 
1134 	stmfRet = stmfImportLu(STMF_DISK, operands[0], &createdGuid);
1135 	switch (stmfRet) {
1136 		case STMF_STATUS_SUCCESS:
1137 			break;
1138 		case STMF_ERROR_BUSY:
1139 		case STMF_ERROR_LU_BUSY:
1140 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1141 			    gettext("resource busy"));
1142 			ret++;
1143 			break;
1144 		case STMF_ERROR_PERM:
1145 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1146 			    gettext("permission denied"));
1147 			ret++;
1148 			break;
1149 		case STMF_ERROR_FILE_IN_USE:
1150 			(void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
1151 			    operands[0], gettext("in use"));
1152 			ret++;
1153 			break;
1154 		case STMF_ERROR_GUID_IN_USE:
1155 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1156 			    gettext("guid in use"));
1157 			ret++;
1158 			break;
1159 		case STMF_ERROR_META_FILE_NAME:
1160 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1161 			    gettext("meta file error"));
1162 			ret++;
1163 			break;
1164 		case STMF_ERROR_DATA_FILE_NAME:
1165 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1166 			    gettext("data file error"));
1167 			ret++;
1168 			break;
1169 		case STMF_ERROR_META_CREATION:
1170 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1171 			    gettext("could not create meta file"));
1172 			ret++;
1173 			break;
1174 		case STMF_ERROR_WRITE_CACHE_SET:
1175 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1176 			    gettext("could not set write cache"));
1177 			ret++;
1178 			break;
1179 		default:
1180 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1181 			    gettext("unknown error"));
1182 			ret++;
1183 			break;
1184 	}
1185 
1186 	if (ret != STMF_STATUS_SUCCESS) {
1187 		goto done;
1188 	}
1189 
1190 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
1191 	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
1192 	    "%02X%02X%02X%02X%02X%02X",
1193 	    createdGuid.guid[0], createdGuid.guid[1], createdGuid.guid[2],
1194 	    createdGuid.guid[3], createdGuid.guid[4], createdGuid.guid[5],
1195 	    createdGuid.guid[6], createdGuid.guid[7], createdGuid.guid[8],
1196 	    createdGuid.guid[9], createdGuid.guid[10], createdGuid.guid[11],
1197 	    createdGuid.guid[12], createdGuid.guid[13], createdGuid.guid[14],
1198 	    createdGuid.guid[15]);
1199 	(void) printf("Logical unit imported: %s\n", guidAsciiBuf);
1200 
1201 done:
1202 	return (ret);
1203 }
1204 
1205 static int
1206 setLuPropFromInput(luResource hdl, char *optarg)
1207 {
1208 	char *prop = NULL;
1209 	char *propVal = NULL;
1210 	char *lasts = NULL;
1211 	uint32_t propId;
1212 	int ret = 0;
1213 
1214 	prop = strtok_r(optarg, "=", &lasts);
1215 	if ((propVal = strtok_r(NULL, "=", &lasts)) == NULL) {
1216 		(void) fprintf(stderr, "%s: %s: %s\n",
1217 		    cmdName, optarg,
1218 		    gettext("invalid property specifier - prop=val\n"));
1219 		return (1);
1220 	}
1221 
1222 	ret = convertCharToPropId(prop, &propId);
1223 	if (ret != 0) {
1224 		(void) fprintf(stderr, "%s: %s: %s\n",
1225 		    cmdName, gettext("invalid property specified"), prop);
1226 		return (1);
1227 	}
1228 
1229 	ret = stmfSetLuProp(hdl, propId, propVal);
1230 	if (ret != STMF_STATUS_SUCCESS) {
1231 		(void) fprintf(stderr, "%s: %s %s: ",
1232 		    cmdName, gettext("unable to set"), prop);
1233 		switch (ret) {
1234 			case STMF_ERROR_INVALID_PROPSIZE:
1235 				(void) fprintf(stderr, "invalid length\n");
1236 				break;
1237 			case STMF_ERROR_INVALID_ARG:
1238 				(void) fprintf(stderr, "bad format\n");
1239 				break;
1240 			default:
1241 				(void) fprintf(stderr, "\n");
1242 				break;
1243 		}
1244 		return (1);
1245 	}
1246 
1247 	return (0);
1248 }
1249 
1250 static int
1251 convertCharToPropId(char *prop, uint32_t *propId)
1252 {
1253 	if (strcasecmp(prop, GUID) == 0) {
1254 		*propId = STMF_LU_PROP_GUID;
1255 	} else if (strcasecmp(prop, ALIAS) == 0) {
1256 		*propId = STMF_LU_PROP_ALIAS;
1257 	} else if (strcasecmp(prop, VID) == 0) {
1258 		*propId = STMF_LU_PROP_VID;
1259 	} else if (strcasecmp(prop, PID) == 0) {
1260 		*propId = STMF_LU_PROP_PID;
1261 	} else if (strcasecmp(prop, WRITE_PROTECT) == 0) {
1262 		*propId = STMF_LU_PROP_WRITE_PROTECT;
1263 	} else if (strcasecmp(prop, WRITEBACK_CACHE_DISABLE) == 0) {
1264 		*propId = STMF_LU_PROP_WRITE_CACHE_DISABLE;
1265 	} else if (strcasecmp(prop, BLOCK_SIZE) == 0) {
1266 		*propId = STMF_LU_PROP_BLOCK_SIZE;
1267 	} else if (strcasecmp(prop, SERIAL_NUMBER) == 0) {
1268 		*propId = STMF_LU_PROP_SERIAL_NUM;
1269 	} else if (strcasecmp(prop, COMPANY_ID) == 0) {
1270 		*propId = STMF_LU_PROP_COMPANY_ID;
1271 	} else if (strcasecmp(prop, META_FILE) == 0) {
1272 		*propId = STMF_LU_PROP_META_FILENAME;
1273 	} else {
1274 		return (1);
1275 	}
1276 	return (0);
1277 }
1278 
1279 /*
1280  * deleteLuFunc
1281  *
1282  * Delete a logical unit
1283  *
1284  */
1285 /*ARGSUSED*/
1286 static int
1287 deleteLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
1288     void *args)
1289 {
1290 	int i, j;
1291 	int ret = 0;
1292 	int stmfRet;
1293 	unsigned int inGuid[sizeof (stmfGuid)];
1294 	stmfGuid delGuid;
1295 	boolean_t keepViews = B_FALSE;
1296 	boolean_t viewEntriesRemoved = B_FALSE;
1297 	boolean_t noLunFound = B_FALSE;
1298 	boolean_t views = B_FALSE;
1299 	char sGuid[GUID_INPUT + 1];
1300 	stmfViewEntryList *viewEntryList = NULL;
1301 
1302 	for (; options->optval; options++) {
1303 		switch (options->optval) {
1304 			/* Keep views for logical unit */
1305 			case 'k':
1306 				keepViews = B_TRUE;
1307 				break;
1308 			default:
1309 				(void) fprintf(stderr, "%s: %c: %s\n",
1310 				    cmdName, options->optval,
1311 				    gettext("unknown option"));
1312 				return (1);
1313 		}
1314 	}
1315 
1316 
1317 	for (i = 0; i < operandLen; i++) {
1318 		for (j = 0; j < GUID_INPUT; j++) {
1319 			if (!isxdigit(operands[i][j])) {
1320 				break;
1321 			}
1322 			sGuid[j] = tolower(operands[i][j]);
1323 		}
1324 		if (j != GUID_INPUT) {
1325 			(void) fprintf(stderr, "%s: %s: %s%d%s\n",
1326 			    cmdName, operands[i], gettext("must be "),
1327 			    GUID_INPUT,
1328 			    gettext(" hexadecimal digits long"));
1329 			continue;
1330 		}
1331 
1332 		sGuid[j] = 0;
1333 
1334 		(void) sscanf(sGuid,
1335 		    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
1336 		    &inGuid[0], &inGuid[1], &inGuid[2], &inGuid[3],
1337 		    &inGuid[4], &inGuid[5], &inGuid[6], &inGuid[7],
1338 		    &inGuid[8], &inGuid[9], &inGuid[10], &inGuid[11],
1339 		    &inGuid[12], &inGuid[13], &inGuid[14], &inGuid[15]);
1340 
1341 		for (j = 0; j < sizeof (stmfGuid); j++) {
1342 			delGuid.guid[j] = inGuid[j];
1343 		}
1344 
1345 		stmfRet = stmfDeleteLu(&delGuid);
1346 		switch (stmfRet) {
1347 			case STMF_STATUS_SUCCESS:
1348 				break;
1349 			case STMF_ERROR_NOT_FOUND:
1350 				noLunFound = B_TRUE;
1351 				break;
1352 			case STMF_ERROR_BUSY:
1353 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1354 				    gettext("resource busy"));
1355 				ret++;
1356 				break;
1357 			case STMF_ERROR_PERM:
1358 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1359 				    gettext("permission denied"));
1360 				ret++;
1361 				break;
1362 			default:
1363 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1364 				    gettext("unknown error"));
1365 				ret++;
1366 				break;
1367 		}
1368 
1369 		if (!keepViews) {
1370 			stmfRet = stmfGetViewEntryList(&delGuid,
1371 			    &viewEntryList);
1372 			if (stmfRet == STMF_STATUS_SUCCESS) {
1373 				for (j = 0; j < viewEntryList->cnt; j++) {
1374 					(void) stmfRemoveViewEntry(&delGuid,
1375 					    viewEntryList->ve[j].veIndex);
1376 				}
1377 				viewEntriesRemoved = B_TRUE;
1378 				stmfFreeMemory(viewEntryList);
1379 			} else if (stmfRet != STMF_ERROR_NOT_FOUND) {
1380 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1381 				    gettext("unable to remove view entries\n"));
1382 				ret++;
1383 			} /* No view entries to remove */
1384 		}
1385 		if (keepViews) {
1386 			stmfRet = stmfGetViewEntryList(&delGuid,
1387 			    &viewEntryList);
1388 			if (stmfRet == STMF_STATUS_SUCCESS) {
1389 				views = B_TRUE;
1390 				stmfFreeMemory(viewEntryList);
1391 			}
1392 		}
1393 
1394 		if ((!viewEntriesRemoved && noLunFound && !views) ||
1395 		    (!views && keepViews && noLunFound)) {
1396 			(void) fprintf(stderr, "%s: %s: %s\n",
1397 			    cmdName, sGuid,
1398 			    gettext("not found"));
1399 			ret++;
1400 		}
1401 		noLunFound = viewEntriesRemoved = views = B_FALSE;
1402 	}
1403 	return (ret);
1404 }
1405 
1406 
1407 /*
1408  * createTargetGroupFunc
1409  *
1410  * Create a target group
1411  *
1412  */
1413 /*ARGSUSED*/
1414 static int
1415 createTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
1416     void *args)
1417 {
1418 	int ret = 0;
1419 	int stmfRet;
1420 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
1421 	stmfGroupName groupName = {0};
1422 
1423 	(void) strlcpy(groupName, operands[0], sizeof (groupName));
1424 	(void) mbstowcs(groupNamePrint, (char *)groupName,
1425 	    sizeof (stmfGroupName) - 1);
1426 	/* call create group */
1427 	stmfRet = stmfCreateTargetGroup(&groupName);
1428 	switch (stmfRet) {
1429 		case STMF_STATUS_SUCCESS:
1430 			break;
1431 		case STMF_ERROR_EXISTS:
1432 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1433 			    groupNamePrint, gettext("already exists"));
1434 			ret++;
1435 			break;
1436 		case STMF_ERROR_BUSY:
1437 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1438 			    groupNamePrint, gettext("resource busy"));
1439 			ret++;
1440 			break;
1441 		case STMF_ERROR_PERM:
1442 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1443 			    gettext("permission denied"));
1444 			ret++;
1445 			break;
1446 		case STMF_ERROR_SERVICE_NOT_FOUND:
1447 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1448 			    gettext("STMF service not found"));
1449 			ret++;
1450 			break;
1451 		case STMF_ERROR_SERVICE_DATA_VERSION:
1452 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1453 			    gettext("STMF service version incorrect"));
1454 			ret++;
1455 			break;
1456 		default:
1457 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1458 			    groupNamePrint, gettext("unknown error"));
1459 			ret++;
1460 			break;
1461 	}
1462 
1463 	return (ret);
1464 }
1465 
1466 /*
1467  * deleteHostGroupFunc
1468  *
1469  * Delete a host group
1470  *
1471  */
1472 /*ARGSUSED*/
1473 static int
1474 deleteHostGroupFunc(int operandLen, char *operands[],
1475     cmdOptions_t *options, void *args)
1476 {
1477 	int ret = 0;
1478 	int stmfRet;
1479 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
1480 	stmfGroupName groupName = {0};
1481 
1482 	(void) strlcpy(groupName, operands[0], sizeof (groupName));
1483 	(void) mbstowcs(groupNamePrint, (char *)groupName,
1484 	    sizeof (stmfGroupName) - 1);
1485 	/* call delete group */
1486 	stmfRet = stmfDeleteHostGroup(&groupName);
1487 	switch (stmfRet) {
1488 		case STMF_STATUS_SUCCESS:
1489 			break;
1490 		case STMF_ERROR_NOT_FOUND:
1491 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1492 			    groupNamePrint, gettext("not found"));
1493 			ret++;
1494 			break;
1495 		case STMF_ERROR_BUSY:
1496 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1497 			    groupNamePrint, gettext("resource busy"));
1498 			ret++;
1499 			break;
1500 		case STMF_ERROR_SERVICE_NOT_FOUND:
1501 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1502 			    gettext("STMF service not found"));
1503 			ret++;
1504 			break;
1505 		case STMF_ERROR_PERM:
1506 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1507 			    gettext("permission denied"));
1508 			ret++;
1509 			break;
1510 		case STMF_ERROR_GROUP_IN_USE:
1511 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1512 			    groupNamePrint,
1513 			    gettext("group is in use by existing view entry"));
1514 			ret++;
1515 			break;
1516 		case STMF_ERROR_SERVICE_DATA_VERSION:
1517 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1518 			    gettext("STMF service version incorrect"));
1519 			ret++;
1520 			break;
1521 		default:
1522 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1523 			    groupNamePrint, gettext("unknown error"));
1524 			ret++;
1525 			break;
1526 	}
1527 
1528 	return (ret);
1529 }
1530 
1531 /*
1532  * deleteTargetGroupFunc
1533  *
1534  * Delete a target group
1535  *
1536  */
1537 /*ARGSUSED*/
1538 static int
1539 deleteTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
1540     void *args)
1541 {
1542 	int ret = 0;
1543 	int stmfRet;
1544 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
1545 	stmfGroupName groupName = {0};
1546 
1547 	(void) strlcpy(groupName, operands[0], sizeof (groupName));
1548 	(void) mbstowcs(groupNamePrint, (char *)groupName,
1549 	    sizeof (stmfGroupName) - 1);
1550 	/* call delete group */
1551 	stmfRet = stmfDeleteTargetGroup(&groupName);
1552 	switch (stmfRet) {
1553 		case STMF_STATUS_SUCCESS:
1554 			break;
1555 		case STMF_ERROR_NOT_FOUND:
1556 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1557 			    groupNamePrint, gettext("not found"));
1558 			ret++;
1559 			break;
1560 		case STMF_ERROR_BUSY:
1561 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1562 			    groupNamePrint, gettext("resource busy"));
1563 			ret++;
1564 			break;
1565 		case STMF_ERROR_SERVICE_NOT_FOUND:
1566 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1567 			    gettext("STMF service not found"));
1568 			ret++;
1569 			break;
1570 		case STMF_ERROR_PERM:
1571 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1572 			    gettext("permission denied"));
1573 			ret++;
1574 			break;
1575 		case STMF_ERROR_GROUP_IN_USE:
1576 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1577 			    groupNamePrint,
1578 			    gettext("group is in use by existing view entry"));
1579 			ret++;
1580 			break;
1581 		case STMF_ERROR_SERVICE_DATA_VERSION:
1582 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1583 			    gettext("STMF service version incorrect"));
1584 			ret++;
1585 			break;
1586 		default:
1587 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1588 			    groupNamePrint, gettext("unknown error"));
1589 			ret++;
1590 			break;
1591 	}
1592 
1593 	return (ret);
1594 }
1595 
1596 /*
1597  * listHostGroupFunc
1598  *
1599  * Lists the specified host groups or all if none are specified
1600  *
1601  */
1602 /*ARGSUSED*/
1603 static int
1604 listHostGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
1605     void *args)
1606 {
1607 	int ret = 0;
1608 	int stmfRet;
1609 	int i, j, outerLoop;
1610 	boolean_t verbose = B_FALSE;
1611 	boolean_t found = B_TRUE;
1612 	boolean_t operandEntered;
1613 	stmfGroupList *groupList;
1614 	stmfGroupProperties *groupProps;
1615 	wchar_t operandName[sizeof (stmfGroupName)];
1616 	wchar_t groupNamePrint[sizeof (stmfGroupName)];
1617 
1618 	for (; options->optval; options++) {
1619 		switch (options->optval) {
1620 			case 'v':
1621 				verbose = B_TRUE;
1622 				break;
1623 			default:
1624 				(void) fprintf(stderr, "%s: %c: %s\n",
1625 				    cmdName, options->optval,
1626 				    gettext("unknown option"));
1627 				return (1);
1628 		}
1629 	}
1630 
1631 	if (operandLen > 0) {
1632 		outerLoop = operandLen;
1633 		operandEntered = B_TRUE;
1634 	} else {
1635 		outerLoop = 1;
1636 		operandEntered = B_FALSE;
1637 	}
1638 
1639 	stmfRet = stmfGetHostGroupList(&groupList);
1640 	if (stmfRet != STMF_STATUS_SUCCESS) {
1641 		switch (stmfRet) {
1642 			case STMF_ERROR_BUSY:
1643 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1644 				    gettext("resource busy"));
1645 				break;
1646 			case STMF_ERROR_SERVICE_NOT_FOUND:
1647 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1648 				    gettext("STMF service not found"));
1649 				break;
1650 			case STMF_ERROR_PERM:
1651 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1652 				    gettext("permission denied"));
1653 				break;
1654 			case STMF_ERROR_SERVICE_DATA_VERSION:
1655 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1656 				    gettext("STMF service version incorrect"));
1657 				break;
1658 			default:
1659 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1660 				    gettext("unknown error"));
1661 				break;
1662 		}
1663 		return (1);
1664 	}
1665 
1666 	for (i = 0; i < outerLoop; i++) {
1667 		for (found = B_FALSE, j = 0; j < groupList->cnt; j++) {
1668 			(void) mbstowcs(groupNamePrint,
1669 			    (char *)groupList->name[j],
1670 			    sizeof (stmfGroupName) - 1);
1671 			groupNamePrint[sizeof (stmfGroupName) - 1] = 0;
1672 			if (operandEntered) {
1673 				(void) mbstowcs(operandName, operands[i],
1674 				    sizeof (stmfGroupName) - 1);
1675 				operandName[sizeof (stmfGroupName) - 1] = 0;
1676 				if (wcscmp(operandName, groupNamePrint)
1677 				    == 0) {
1678 					found = B_TRUE;
1679 				}
1680 			}
1681 			if ((found && operandEntered) || !operandEntered) {
1682 				(void) printf("Host Group: %ws\n",
1683 				    groupNamePrint);
1684 				if (verbose) {
1685 					stmfRet = stmfGetHostGroupMembers(
1686 					    &(groupList->name[j]), &groupProps);
1687 					if (stmfRet != STMF_STATUS_SUCCESS) {
1688 						return (1);
1689 					}
1690 					printGroupProps(groupProps);
1691 				}
1692 				if (found && operandEntered) {
1693 					break;
1694 				}
1695 			}
1696 
1697 		}
1698 		if (operandEntered && !found) {
1699 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
1700 			    operands[i], gettext("not found"));
1701 			ret = 1;
1702 		}
1703 	}
1704 	return (ret);
1705 }
1706 
1707 /*
1708  * printGroupProps
1709  *
1710  * Prints group members for target or host groups
1711  *
1712  */
1713 static void
1714 printGroupProps(stmfGroupProperties *groupProps)
1715 {
1716 	int i;
1717 	wchar_t memberIdent[sizeof (groupProps->name[0].ident) + 1] = {0};
1718 
1719 
1720 	for (i = 0; i < groupProps->cnt; i++) {
1721 		(void) mbstowcs(memberIdent, (char *)groupProps->name[i].ident,
1722 		    sizeof (groupProps->name[0].ident));
1723 		(void) printf("\tMember: %ws\n", memberIdent);
1724 	}
1725 }
1726 
1727 /*
1728  * listTargetGroupFunc
1729  *
1730  * Lists the specified target groups or all if none are specified
1731  *
1732  */
1733 /*ARGSUSED*/
1734 static int
1735 listTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
1736     void *args)
1737 {
1738 	int ret = 0;
1739 	int stmfRet;
1740 	int i, j, outerLoop;
1741 	boolean_t verbose = B_FALSE;
1742 	boolean_t found = B_TRUE;
1743 	boolean_t operandEntered;
1744 	stmfGroupList *groupList;
1745 	stmfGroupProperties *groupProps;
1746 	wchar_t operandName[sizeof (stmfGroupName)];
1747 	wchar_t groupNamePrint[sizeof (stmfGroupName)];
1748 
1749 	for (; options->optval; options++) {
1750 		switch (options->optval) {
1751 			case 'v':
1752 				verbose = B_TRUE;
1753 				break;
1754 			default:
1755 				(void) fprintf(stderr, "%s: %c: %s\n",
1756 				    cmdName, options->optval,
1757 				    gettext("unknown option"));
1758 				return (1);
1759 		}
1760 	}
1761 
1762 	if (operandLen > 0) {
1763 		outerLoop = operandLen;
1764 		operandEntered = B_TRUE;
1765 	} else {
1766 		outerLoop = 1;
1767 		operandEntered = B_FALSE;
1768 	}
1769 
1770 	stmfRet = stmfGetTargetGroupList(&groupList);
1771 	if (stmfRet != STMF_STATUS_SUCCESS) {
1772 		switch (stmfRet) {
1773 			case STMF_ERROR_BUSY:
1774 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1775 				    gettext("resource busy"));
1776 				break;
1777 			case STMF_ERROR_SERVICE_NOT_FOUND:
1778 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1779 				    gettext("STMF service not found"));
1780 				break;
1781 			case STMF_ERROR_SERVICE_DATA_VERSION:
1782 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1783 				    gettext("STMF service version incorrect"));
1784 				break;
1785 			case STMF_ERROR_PERM:
1786 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1787 				    gettext("permission denied"));
1788 				break;
1789 			default:
1790 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1791 				    gettext("unknown error"));
1792 				break;
1793 		}
1794 		return (1);
1795 	}
1796 
1797 	for (i = 0; i < outerLoop; i++) {
1798 		for (found = B_FALSE, j = 0; j < groupList->cnt; j++) {
1799 			(void) mbstowcs(groupNamePrint,
1800 			    (char *)groupList->name[j],
1801 			    sizeof (stmfGroupName) - 1);
1802 			groupNamePrint[sizeof (stmfGroupName) - 1] = 0;
1803 			if (operandEntered) {
1804 				(void) mbstowcs(operandName, operands[i],
1805 				    sizeof (stmfGroupName) - 1);
1806 				operandName[sizeof (stmfGroupName) - 1] = 0;
1807 				if (wcscmp(operandName, groupNamePrint)
1808 				    == 0) {
1809 					found = B_TRUE;
1810 				}
1811 			}
1812 			if ((found && operandEntered) || !operandEntered) {
1813 				(void) printf("Target Group: %ws\n",
1814 				    groupNamePrint);
1815 				if (verbose) {
1816 					stmfRet = stmfGetTargetGroupMembers(
1817 					    &(groupList->name[j]), &groupProps);
1818 					if (stmfRet != STMF_STATUS_SUCCESS) {
1819 						return (1);
1820 					}
1821 					printGroupProps(groupProps);
1822 				}
1823 				if (found && operandEntered) {
1824 					break;
1825 				}
1826 			}
1827 
1828 		}
1829 		if (operandEntered && !found) {
1830 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
1831 			    operands[i], gettext("not found"));
1832 			ret = 1;
1833 		}
1834 	}
1835 	return (ret);
1836 }
1837 
1838 /*
1839  * listLuFunc
1840  *
1841  * List the logical units and optionally the properties
1842  *
1843  */
1844 /*ARGSUSED*/
1845 static int
1846 listLuFunc(int operandLen, char *operands[], cmdOptions_t *options, void *args)
1847 {
1848 	cmdOptions_t *optionList = options;
1849 	boolean_t operandEntered;
1850 	int i, j;
1851 	int ret = 0;
1852 	int stmfRet;
1853 	int outerLoop;
1854 	unsigned int inGuid[sizeof (stmfGuid)];
1855 	stmfGuid cmpGuid;
1856 	boolean_t verbose = B_FALSE;
1857 	boolean_t found;
1858 	char sGuid[GUID_INPUT + 1];
1859 	stmfGuidList *luList;
1860 	stmfLogicalUnitProperties luProps;
1861 	boolean_t invalidInput = B_FALSE;
1862 	stmfViewEntryList *viewEntryList;
1863 
1864 	for (; optionList->optval; optionList++) {
1865 		switch (optionList->optval) {
1866 			case 'v':
1867 				verbose = B_TRUE;
1868 				break;
1869 		}
1870 	}
1871 
1872 	if ((stmfRet = stmfGetLogicalUnitList(&luList))
1873 	    != STMF_STATUS_SUCCESS) {
1874 		switch (stmfRet) {
1875 			case STMF_ERROR_SERVICE_NOT_FOUND:
1876 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1877 				    gettext("STMF service not found"));
1878 				break;
1879 			case STMF_ERROR_BUSY:
1880 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1881 				    gettext("resource busy"));
1882 				break;
1883 			case STMF_ERROR_PERM:
1884 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1885 				    gettext("permission denied"));
1886 				break;
1887 			case STMF_ERROR_SERVICE_DATA_VERSION:
1888 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1889 				    gettext("STMF service version incorrect"));
1890 				break;
1891 			default:
1892 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1893 				    gettext("list failed"));
1894 				break;
1895 		}
1896 		return (1);
1897 	}
1898 
1899 	if (operandLen > 0) {
1900 		operandEntered = B_TRUE;
1901 		outerLoop = operandLen;
1902 	} else {
1903 		operandEntered = B_FALSE;
1904 		outerLoop = 1;
1905 	}
1906 
1907 
1908 	for (invalidInput = B_FALSE, i = 0; i < outerLoop; i++) {
1909 		if (operandEntered) {
1910 			if (strlen(operands[i]) != GUID_INPUT) {
1911 				invalidInput = B_TRUE;
1912 			} else {
1913 				for (j = 0; j < GUID_INPUT; j++) {
1914 					if (!isxdigit(operands[i][j])) {
1915 						invalidInput = B_TRUE;
1916 						break;
1917 					}
1918 				}
1919 			}
1920 			if (invalidInput) {
1921 				(void) fprintf(stderr, "%s: %s: %s%d%s\n",
1922 				    cmdName, operands[i], gettext("must be "),
1923 				    GUID_INPUT,
1924 				    gettext(" hexadecimal digits long"));
1925 				invalidInput = B_FALSE;
1926 				continue;
1927 			}
1928 
1929 			for (j = 0; j < GUID_INPUT; j++) {
1930 				sGuid[j] = tolower(operands[i][j]);
1931 			}
1932 			sGuid[j] = 0;
1933 
1934 			(void) sscanf(sGuid,
1935 			    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
1936 			    &inGuid[0], &inGuid[1], &inGuid[2], &inGuid[3],
1937 			    &inGuid[4], &inGuid[5], &inGuid[6], &inGuid[7],
1938 			    &inGuid[8], &inGuid[9], &inGuid[10], &inGuid[11],
1939 			    &inGuid[12], &inGuid[13], &inGuid[14], &inGuid[15]);
1940 
1941 			for (j = 0; j < sizeof (stmfGuid); j++) {
1942 				cmpGuid.guid[j] = inGuid[j];
1943 			}
1944 		}
1945 
1946 		for (found = B_FALSE, j = 0; j < luList->cnt; j++) {
1947 			if (operandEntered) {
1948 				if (bcmp(luList->guid[j].guid, cmpGuid.guid,
1949 				    sizeof (stmfGuid)) == 0) {
1950 					found = B_TRUE;
1951 				}
1952 			}
1953 			if ((found && operandEntered) || !operandEntered) {
1954 				(void) printf("LU Name: ");
1955 				printGuid(&luList->guid[j], stdout);
1956 				(void) printf("\n");
1957 
1958 				if (verbose) {
1959 					stmfRet = stmfGetLogicalUnitProperties(
1960 					    &(luList->guid[j]), &luProps);
1961 					if (stmfRet == STMF_STATUS_SUCCESS) {
1962 						printLuProps(&luProps);
1963 					} else {
1964 						(void) fprintf(stderr, "%s:",
1965 						    cmdName);
1966 						printGuid(&luList->guid[j],
1967 						    stderr);
1968 						(void) fprintf(stderr, "%s\n",
1969 						    gettext(" get properties "
1970 						    "failed"));
1971 					}
1972 					stmfRet = stmfGetViewEntryList(
1973 					    &(luList->guid[j]),
1974 					    &viewEntryList);
1975 					(void) printf(PROPS_FORMAT,
1976 					    "View Entry Count");
1977 					if (stmfRet == STMF_STATUS_SUCCESS) {
1978 						(void) printf("%d",
1979 						    viewEntryList->cnt);
1980 					} else if (stmfRet ==
1981 					    STMF_ERROR_NOT_FOUND) {
1982 						(void) printf("0");
1983 					} else {
1984 						(void) printf("unknown");
1985 					}
1986 					(void) printf("\n");
1987 					ret = printExtLuProps(
1988 					    &(luList->guid[j]));
1989 				}
1990 				if (found && operandEntered) {
1991 					break;
1992 				}
1993 			}
1994 
1995 		}
1996 		if (operandEntered && !found) {
1997 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
1998 			    operands[i], gettext("not found"));
1999 			ret = 1;
2000 		}
2001 	}
2002 
2003 	return (ret);
2004 }
2005 
2006 static void
2007 printGuid(stmfGuid *guid, FILE *stream)
2008 {
2009 	int i;
2010 	for (i = 0; i < 16; i++) {
2011 		(void) fprintf(stream, "%02X", guid->guid[i]);
2012 	}
2013 }
2014 
2015 static int
2016 printExtLuProps(stmfGuid *guid)
2017 {
2018 	int stmfRet;
2019 	luResource hdl = NULL;
2020 	int ret = 0;
2021 	char propVal[MAXNAMELEN];
2022 	size_t propValSize = sizeof (propVal);
2023 
2024 	if ((stmfRet = stmfGetLuResource(guid, &hdl))
2025 	    != STMF_STATUS_SUCCESS) {
2026 		switch (stmfRet) {
2027 			case STMF_ERROR_BUSY:
2028 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2029 				    gettext("resource busy"));
2030 				break;
2031 			case STMF_ERROR_PERM:
2032 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2033 				    gettext("permission denied"));
2034 				break;
2035 			case STMF_ERROR_NOT_FOUND:
2036 				/* No error here */
2037 				return (0);
2038 				break;
2039 			default:
2040 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2041 				    gettext("get extended properties failed"));
2042 				break;
2043 		}
2044 		return (1);
2045 	}
2046 
2047 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_FILENAME, propVal,
2048 	    &propValSize);
2049 	(void) printf(PROPS_FORMAT, "Data File");
2050 	if (stmfRet == STMF_STATUS_SUCCESS) {
2051 		(void) printf("%s\n", propVal);
2052 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2053 		(void) printf("not set\n");
2054 	} else {
2055 		(void) printf("<error retrieving property>\n");
2056 		ret++;
2057 	}
2058 
2059 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_META_FILENAME, propVal,
2060 	    &propValSize);
2061 	(void) printf(PROPS_FORMAT, "Meta File");
2062 	if (stmfRet == STMF_STATUS_SUCCESS) {
2063 		(void) printf("%s\n", propVal);
2064 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2065 		(void) printf("not set\n");
2066 	} else {
2067 		(void) printf("<error retrieving property>\n");
2068 		ret++;
2069 	}
2070 
2071 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SIZE, propVal,
2072 	    &propValSize);
2073 	(void) printf(PROPS_FORMAT, "Size");
2074 	if (stmfRet == STMF_STATUS_SUCCESS) {
2075 		(void) printf("%s\n", propVal);
2076 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2077 		(void) printf("not set\n");
2078 	} else {
2079 		(void) printf("<error retrieving property>\n");
2080 		ret++;
2081 	}
2082 
2083 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_BLOCK_SIZE, propVal,
2084 	    &propValSize);
2085 	(void) printf(PROPS_FORMAT, "Block Size");
2086 	if (stmfRet == STMF_STATUS_SUCCESS) {
2087 		(void) printf("%s\n", propVal);
2088 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2089 		(void) printf("not set\n");
2090 	} else {
2091 		(void) printf("<error retrieving property>\n");
2092 		ret++;
2093 	}
2094 
2095 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_VID, propVal,
2096 	    &propValSize);
2097 	(void) printf(PROPS_FORMAT, "Vendor ID");
2098 	if (stmfRet == STMF_STATUS_SUCCESS) {
2099 		(void) printf("%s\n", propVal);
2100 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2101 		(void) printf("not set\n");
2102 	} else {
2103 		(void) printf("<error retrieving property>\n");
2104 		ret++;
2105 	}
2106 
2107 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_PID, propVal,
2108 	    &propValSize);
2109 	(void) printf(PROPS_FORMAT, "Product ID");
2110 	if (stmfRet == STMF_STATUS_SUCCESS) {
2111 		(void) printf("%s\n", propVal);
2112 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2113 		(void) printf("not set\n");
2114 	} else {
2115 		(void) printf("<error retrieving property>\n");
2116 		ret++;
2117 	}
2118 
2119 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SERIAL_NUM, propVal,
2120 	    &propValSize);
2121 	(void) printf(PROPS_FORMAT, "Serial Num");
2122 	if (stmfRet == STMF_STATUS_SUCCESS) {
2123 		(void) printf("%s\n", propVal);
2124 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2125 		(void) printf("not set\n");
2126 	} else {
2127 		(void) printf("<error retrieving property>\n");
2128 		ret++;
2129 	}
2130 
2131 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_WRITE_PROTECT, propVal,
2132 	    &propValSize);
2133 	(void) printf(PROPS_FORMAT, "Write Protect");
2134 	if (stmfRet == STMF_STATUS_SUCCESS) {
2135 		(void) printf("%s\n",
2136 		    strcasecmp(propVal, "true") ? "Disabled" : "Enabled");
2137 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2138 		(void) printf("not set\n");
2139 	} else {
2140 		(void) printf("<error retrieving property>\n");
2141 		ret++;
2142 	}
2143 
2144 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_WRITE_CACHE_DISABLE, propVal,
2145 	    &propValSize);
2146 	(void) printf(PROPS_FORMAT, "Writeback Cache");
2147 	if (stmfRet == STMF_STATUS_SUCCESS) {
2148 		(void) printf("%s\n",
2149 		    strcasecmp(propVal, "true") ? "Enabled" : "Disabled");
2150 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2151 		(void) printf("not set\n");
2152 	} else {
2153 		(void) printf("<error retrieving property>\n");
2154 		ret++;
2155 	}
2156 
2157 
2158 	(void) stmfFreeLuResource(hdl);
2159 	return (ret);
2160 
2161 }
2162 
2163 
2164 /*
2165  * printLuProps
2166  *
2167  * Prints the properties for a logical unit
2168  *
2169  */
2170 static void
2171 printLuProps(stmfLogicalUnitProperties *luProps)
2172 {
2173 	(void) printf(PROPS_FORMAT, "Operational Status");
2174 	switch (luProps->status) {
2175 		case STMF_LOGICAL_UNIT_ONLINE:
2176 			(void) printf("Online");
2177 			break;
2178 		case STMF_LOGICAL_UNIT_OFFLINE:
2179 			(void) printf("Offline");
2180 			break;
2181 		case STMF_LOGICAL_UNIT_ONLINING:
2182 			(void) printf("Onlining");
2183 			break;
2184 		case STMF_LOGICAL_UNIT_OFFLINING:
2185 			(void) printf("Offlining");
2186 			break;
2187 		case STMF_LOGICAL_UNIT_UNREGISTERED:
2188 			(void) printf("unregistered");
2189 			(void) strncpy(luProps->providerName, "unregistered",
2190 			    sizeof (luProps->providerName));
2191 			break;
2192 		default:
2193 			(void) printf("unknown");
2194 			break;
2195 	}
2196 	(void) printf("\n");
2197 	(void) printf(PROPS_FORMAT, "Provider Name");
2198 	if (luProps->providerName[0] != 0) {
2199 		(void) printf("%s", luProps->providerName);
2200 	} else {
2201 		(void) printf("unknown");
2202 	}
2203 	(void) printf("\n");
2204 	(void) printf(PROPS_FORMAT, "Alias");
2205 	if (luProps->alias[0] != 0) {
2206 		(void) printf("%s", luProps->alias);
2207 	} else {
2208 		(void) printf("-");
2209 	}
2210 	(void) printf("\n");
2211 }
2212 
2213 /*
2214  * printTargetProps
2215  *
2216  * Prints the properties for a target
2217  *
2218  */
2219 static void
2220 printTargetProps(stmfTargetProperties *targetProps)
2221 {
2222 	(void) printf(PROPS_FORMAT, "Operational Status");
2223 	switch (targetProps->status) {
2224 		case STMF_TARGET_PORT_ONLINE:
2225 			(void) printf("Online");
2226 			break;
2227 		case STMF_TARGET_PORT_OFFLINE:
2228 			(void) printf("Offline");
2229 			break;
2230 		case STMF_TARGET_PORT_ONLINING:
2231 			(void) printf("Onlining");
2232 			break;
2233 		case STMF_TARGET_PORT_OFFLINING:
2234 			(void) printf("Offlining");
2235 			break;
2236 		default:
2237 			(void) printf("unknown");
2238 			break;
2239 	}
2240 	(void) printf("\n");
2241 	(void) printf(PROPS_FORMAT, "Provider Name");
2242 	if (targetProps->providerName[0] != 0) {
2243 		(void) printf("%s", targetProps->providerName);
2244 	}
2245 	(void) printf("\n");
2246 	(void) printf(PROPS_FORMAT, "Alias");
2247 	if (targetProps->alias[0] != 0) {
2248 		(void) printf("%s", targetProps->alias);
2249 	} else {
2250 		(void) printf("-");
2251 	}
2252 	(void) printf("\n");
2253 }
2254 
2255 /*
2256  * printSessionProps
2257  *
2258  * Prints the session data
2259  *
2260  */
2261 static void
2262 printSessionProps(stmfSessionList *sessionList)
2263 {
2264 	int i;
2265 	char *cTime;
2266 	wchar_t initiator[STMF_IDENT_LENGTH + 1];
2267 
2268 	(void) printf(PROPS_FORMAT, "Sessions");
2269 	(void) printf("%d\n", sessionList->cnt);
2270 	for (i = 0; i < sessionList->cnt; i++) {
2271 		(void) mbstowcs(initiator,
2272 		    (char *)sessionList->session[i].initiator.ident,
2273 		    STMF_IDENT_LENGTH);
2274 		initiator[STMF_IDENT_LENGTH] = 0;
2275 		(void) printf(LVL3_FORMAT, "Initiator: ");
2276 		(void) printf("%ws\n", initiator);
2277 		(void) printf(LVL4_FORMAT, "Alias: ");
2278 		if (sessionList->session[i].alias[0] != 0) {
2279 			(void) printf("%s", sessionList->session[i].alias);
2280 		} else {
2281 			(void) printf("-");
2282 		}
2283 		(void) printf("\n");
2284 		(void) printf(LVL4_FORMAT, "Logged in since: ");
2285 		cTime = ctime(&(sessionList->session[i].creationTime));
2286 		if (cTime != NULL) {
2287 			(void) printf("%s", cTime);
2288 		} else {
2289 			(void) printf("unknown\n");
2290 		}
2291 	}
2292 }
2293 
2294 static int
2295 getStmfState(stmfState *state)
2296 {
2297 	int ret;
2298 
2299 	ret = stmfGetState(state);
2300 	switch (ret) {
2301 		case STMF_STATUS_SUCCESS:
2302 			break;
2303 		case STMF_ERROR_PERM:
2304 			(void) fprintf(stderr, "%s: %s\n", cmdName,
2305 			    gettext("permission denied"));
2306 			break;
2307 		case STMF_ERROR_SERVICE_NOT_FOUND:
2308 			(void) fprintf(stderr, "%s: %s\n", cmdName,
2309 			    gettext("STMF service not found"));
2310 			break;
2311 		case STMF_ERROR_BUSY:
2312 			(void) fprintf(stderr, "%s: %s\n", cmdName,
2313 			    gettext("resource busy"));
2314 			break;
2315 		case STMF_ERROR_SERVICE_DATA_VERSION:
2316 			(void) fprintf(stderr, "%s: %s\n", cmdName,
2317 			    gettext("STMF service version incorrect"));
2318 			break;
2319 		default:
2320 			(void) fprintf(stderr, "%s: %s: %d\n", cmdName,
2321 			    gettext("unknown error"), ret);
2322 			break;
2323 	}
2324 	return (ret);
2325 }
2326 
2327 /*
2328  * listStateFunc
2329  *
2330  * List the operational and config state of the stmf service
2331  *
2332  */
2333 /*ARGSUSED*/
2334 static int
2335 listStateFunc(int operandLen, char *operands[], cmdOptions_t *options,
2336     void *args)
2337 {
2338 	int ret;
2339 	stmfState state;
2340 
2341 	if ((ret = getStmfState(&state)) != STMF_STATUS_SUCCESS)
2342 		return (ret);
2343 
2344 	(void) printf("%-18s: ", "Operational Status");
2345 	switch (state.operationalState) {
2346 		case STMF_SERVICE_STATE_ONLINE:
2347 			(void) printf("online");
2348 			break;
2349 		case STMF_SERVICE_STATE_OFFLINE:
2350 			(void) printf("offline");
2351 			break;
2352 		case STMF_SERVICE_STATE_ONLINING:
2353 			(void) printf("onlining");
2354 			break;
2355 		case STMF_SERVICE_STATE_OFFLINING:
2356 			(void) printf("offlining");
2357 			break;
2358 		default:
2359 			(void) printf("unknown");
2360 			break;
2361 	}
2362 	(void) printf("\n");
2363 	(void) printf("%-18s: ", "Config Status");
2364 	switch (state.configState) {
2365 		case STMF_CONFIG_STATE_NONE:
2366 			(void) printf("uninitialized");
2367 			break;
2368 		case STMF_CONFIG_STATE_INIT:
2369 			(void) printf("initializing");
2370 			break;
2371 		case STMF_CONFIG_STATE_INIT_DONE:
2372 			(void) printf("initialized");
2373 			break;
2374 		default:
2375 			(void) printf("unknown");
2376 			break;
2377 	}
2378 	(void) printf("\n");
2379 	return (0);
2380 }
2381 
2382 /*
2383  * listTargetFunc
2384  *
2385  * list the targets and optionally their properties
2386  *
2387  */
2388 /*ARGSUSED*/
2389 static int
2390 listTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
2391     void *args)
2392 {
2393 	cmdOptions_t *optionList = options;
2394 	int ret = 0;
2395 	int stmfRet;
2396 	int i, j;
2397 	int outerLoop;
2398 	stmfSessionList *sessionList;
2399 	stmfDevid devid;
2400 	boolean_t operandEntered, found, verbose = B_FALSE;
2401 	stmfDevidList *targetList;
2402 	wchar_t targetIdent[STMF_IDENT_LENGTH + 1];
2403 	stmfTargetProperties targetProps;
2404 
2405 	if ((stmfRet = stmfGetTargetList(&targetList)) != STMF_STATUS_SUCCESS) {
2406 		switch (stmfRet) {
2407 			case STMF_ERROR_NOT_FOUND:
2408 				ret = 0;
2409 				break;
2410 			case STMF_ERROR_SERVICE_OFFLINE:
2411 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2412 				    gettext("STMF service offline"));
2413 				break;
2414 			case STMF_ERROR_BUSY:
2415 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2416 				    gettext("resource busy"));
2417 				break;
2418 			case STMF_ERROR_SERVICE_DATA_VERSION:
2419 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2420 				    gettext("STMF service version incorrect"));
2421 				break;
2422 			case STMF_ERROR_PERM:
2423 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2424 				    gettext("permission denied"));
2425 				break;
2426 			default:
2427 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2428 				    gettext("unknown error"));
2429 				break;
2430 		}
2431 		return (1);
2432 	}
2433 
2434 	for (; optionList->optval; optionList++) {
2435 		switch (optionList->optval) {
2436 			case 'v':
2437 				verbose = B_TRUE;
2438 				break;
2439 		}
2440 	}
2441 
2442 	if (operandLen > 0) {
2443 		outerLoop = operandLen;
2444 		operandEntered = B_TRUE;
2445 	} else {
2446 		outerLoop = 1;
2447 		operandEntered = B_FALSE;
2448 	}
2449 
2450 	for (i = 0; i < outerLoop; i++) {
2451 		if (operandEntered) {
2452 			bzero(&devid, sizeof (devid));
2453 			(void) parseDevid(operands[i], &devid);
2454 		}
2455 		for (found = B_FALSE, j = 0; j < targetList->cnt; j++) {
2456 			if (operandEntered) {
2457 				if (bcmp(&devid, &(targetList->devid[j]),
2458 				    sizeof (devid)) == 0) {
2459 					found = B_TRUE;
2460 				}
2461 			}
2462 			if ((found && operandEntered) || !operandEntered) {
2463 				(void) mbstowcs(targetIdent,
2464 				    (char *)targetList->devid[j].ident,
2465 				    STMF_IDENT_LENGTH);
2466 				targetIdent[STMF_IDENT_LENGTH] = 0;
2467 				(void) printf("Target: %ws\n", targetIdent);
2468 				if (verbose) {
2469 					stmfRet = stmfGetTargetProperties(
2470 					    &(targetList->devid[j]),
2471 					    &targetProps);
2472 					if (stmfRet == STMF_STATUS_SUCCESS) {
2473 						printTargetProps(&targetProps);
2474 					} else {
2475 						(void) fprintf(stderr, "%s:",
2476 						    cmdName);
2477 						(void) fprintf(stderr, "%s\n",
2478 						    gettext(" get properties"
2479 						    " failed"));
2480 					}
2481 					stmfRet = stmfGetSessionList(
2482 					    &(targetList->devid[j]),
2483 					    &sessionList);
2484 					if (stmfRet == STMF_STATUS_SUCCESS) {
2485 						printSessionProps(sessionList);
2486 					} else {
2487 						(void) fprintf(stderr, "%s:",
2488 						    cmdName);
2489 						(void) fprintf(stderr, "%s\n",
2490 						    gettext(" get session info"
2491 						    " failed"));
2492 					}
2493 				}
2494 				if (found && operandEntered) {
2495 					break;
2496 				}
2497 			}
2498 
2499 		}
2500 		if (operandEntered && !found) {
2501 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2502 			    operands[i], "not found");
2503 			ret = 1;
2504 		}
2505 	}
2506 	return (ret);
2507 }
2508 
2509 /*
2510  * listViewFunc
2511  *
2512  * list the view entries for the specified logical unit
2513  *
2514  */
2515 /*ARGSUSED*/
2516 static int
2517 listViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
2518     void *args)
2519 {
2520 	stmfViewEntryList *viewEntryList;
2521 	stmfGuid inGuid;
2522 	unsigned int guid[sizeof (stmfGuid)];
2523 	int ret = 0;
2524 	int stmfRet;
2525 	int i, j, outerLoop;
2526 	boolean_t found = B_TRUE;
2527 	boolean_t operandEntered;
2528 	uint16_t outputLuNbr;
2529 	wchar_t groupName[sizeof (stmfGroupName)];
2530 	char sGuid[GUID_INPUT + 1];
2531 
2532 
2533 	for (; options->optval; options++) {
2534 		switch (options->optval) {
2535 			case 'l':
2536 				if (strlen(options->optarg) != GUID_INPUT) {
2537 					(void) fprintf(stderr,
2538 					    "%s: %s: %s%d%s\n",
2539 					    cmdName, options->optarg,
2540 					    gettext("must be "), GUID_INPUT,
2541 					    gettext(" hexadecimal digits"
2542 					    " long"));
2543 					return (1);
2544 				}
2545 				bcopy(options->optarg, sGuid, GUID_INPUT);
2546 				break;
2547 			default:
2548 				(void) fprintf(stderr, "%s: %c: %s\n",
2549 				    cmdName, options->optval,
2550 				    gettext("unknown option"));
2551 				return (1);
2552 		}
2553 	}
2554 
2555 	if (operandLen > 0) {
2556 		outerLoop = operandLen;
2557 		operandEntered = B_TRUE;
2558 	} else {
2559 		outerLoop = 1;
2560 		operandEntered = B_FALSE;
2561 	}
2562 
2563 	for (i = 0; i < 32; i++)
2564 		sGuid[i] = tolower(sGuid[i]);
2565 	sGuid[i] = 0;
2566 
2567 	(void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
2568 	    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
2569 	    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
2570 	    &guid[12], &guid[13], &guid[14], &guid[15]);
2571 
2572 	for (i = 0; i < sizeof (stmfGuid); i++) {
2573 		inGuid.guid[i] = guid[i];
2574 	}
2575 
2576 	if ((stmfRet = stmfGetViewEntryList(&inGuid, &viewEntryList))
2577 	    != STMF_STATUS_SUCCESS) {
2578 
2579 		switch (stmfRet) {
2580 			case STMF_ERROR_BUSY:
2581 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2582 				    sGuid, gettext("resource busy"));
2583 				break;
2584 			case STMF_ERROR_NOT_FOUND:
2585 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2586 				    sGuid, gettext("no views found"));
2587 				break;
2588 			case STMF_ERROR_SERVICE_NOT_FOUND:
2589 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2590 				    gettext("STMF service not found"));
2591 				break;
2592 			case STMF_ERROR_SERVICE_DATA_VERSION:
2593 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2594 				    gettext("STMF service version incorrect"));
2595 				break;
2596 			case STMF_ERROR_PERM:
2597 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2598 				    gettext("permission denied"));
2599 				break;
2600 			default:
2601 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2602 				    sGuid, gettext("unknown error"));
2603 				break;
2604 		}
2605 		return (1);
2606 	}
2607 
2608 	for (i = 0; i < outerLoop; i++) {
2609 		for (found = B_FALSE, j = 0; j < viewEntryList->cnt; j++) {
2610 			if (operandEntered) {
2611 				if (atoi(operands[i]) ==
2612 				    viewEntryList->ve[j].veIndex) {
2613 					found = B_TRUE;
2614 				}
2615 			}
2616 			if ((found && operandEntered) || !operandEntered) {
2617 				(void) printf("View Entry: %d\n",
2618 				    viewEntryList->ve[j].veIndex);
2619 				(void) printf(VIEW_FORMAT, "Host group");
2620 				if (viewEntryList->ve[j].allHosts) {
2621 					(void) printf("All\n");
2622 				} else {
2623 					(void) mbstowcs(groupName,
2624 					    viewEntryList->ve[j].hostGroup,
2625 					    sizeof (stmfGroupName) - 1);
2626 					groupName[sizeof (stmfGroupName) - 1]
2627 					    = 0;
2628 					(void) printf("%ws\n", groupName);
2629 				}
2630 				(void) printf(VIEW_FORMAT, "Target group");
2631 				if (viewEntryList->ve[j].allTargets) {
2632 					(void) printf("All\n");
2633 				} else {
2634 					(void) mbstowcs(groupName,
2635 					    viewEntryList->ve[j].targetGroup,
2636 					    sizeof (stmfGroupName) - 1);
2637 					groupName[sizeof (stmfGroupName) - 1]
2638 					    = 0;
2639 					(void) printf("%ws\n", groupName);
2640 				}
2641 				outputLuNbr = ((viewEntryList->ve[j].luNbr[0] &
2642 				    0x3F) << 8) | viewEntryList->ve[j].luNbr[1];
2643 				(void) printf(VIEW_FORMAT, "LUN");
2644 				(void) printf("%d\n", outputLuNbr);
2645 				if (found && operandEntered) {
2646 					break;
2647 				}
2648 			}
2649 		}
2650 		if (operandEntered && !found) {
2651 			(void) fprintf(stderr, "%s: %s, %s: %s\n", cmdName,
2652 			    sGuid, operands[i], gettext("not found"));
2653 			ret = 1;
2654 		}
2655 	}
2656 
2657 	return (ret);
2658 }
2659 
2660 
2661 /*
2662  * onlineOfflineLu
2663  *
2664  * Purpose: Online or offline a logical unit
2665  *
2666  * lu - logical unit to online or offline
2667  *
2668  * state - ONLINE_LU
2669  *         OFFLINE_LU
2670  */
2671 static int
2672 onlineOfflineLu(char *lu, int state)
2673 {
2674 	char sGuid[GUID_INPUT + 1];
2675 	stmfGuid inGuid;
2676 	unsigned int guid[sizeof (stmfGuid)];
2677 	int i;
2678 	int ret = 0;
2679 
2680 	if (strlen(lu) != GUID_INPUT) {
2681 		(void) fprintf(stderr, "%s: %s: %s %d %s\n", cmdName, lu,
2682 		    gettext("must be"), GUID_INPUT,
2683 		    gettext("hexadecimal digits long"));
2684 		return (1);
2685 	}
2686 
2687 	bcopy(lu, sGuid, GUID_INPUT);
2688 
2689 	for (i = 0; i < 32; i++)
2690 		sGuid[i] = tolower(sGuid[i]);
2691 	sGuid[i] = 0;
2692 
2693 	(void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
2694 	    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
2695 	    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
2696 	    &guid[12], &guid[13], &guid[14], &guid[15]);
2697 
2698 	for (i = 0; i < sizeof (stmfGuid); i++) {
2699 		inGuid.guid[i] = guid[i];
2700 	}
2701 
2702 	if (state == ONLINE_LU) {
2703 		ret = stmfOnlineLogicalUnit(&inGuid);
2704 	} else if (state == OFFLINE_LU) {
2705 		ret = stmfOfflineLogicalUnit(&inGuid);
2706 	}
2707 	if (ret != STMF_STATUS_SUCCESS) {
2708 		switch (ret) {
2709 			case STMF_ERROR_PERM:
2710 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2711 				    gettext("permission denied"));
2712 				break;
2713 			case STMF_ERROR_SERVICE_NOT_FOUND:
2714 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2715 				    gettext("STMF service not found"));
2716 				break;
2717 			case STMF_ERROR_NOT_FOUND:
2718 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2719 				    lu, gettext("not found"));
2720 				break;
2721 			case STMF_ERROR_SERVICE_DATA_VERSION:
2722 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2723 				    gettext("STMF service version incorrect"));
2724 				break;
2725 			default:
2726 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2727 				    gettext("unknown error"));
2728 				break;
2729 		}
2730 	}
2731 	return (ret);
2732 }
2733 
2734 /*
2735  * onlineLuFunc
2736  *
2737  * Purpose: Online a logical unit
2738  *
2739  */
2740 /*ARGSUSED*/
2741 static int
2742 onlineLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
2743     void *args)
2744 {
2745 	int ret;
2746 	stmfState state;
2747 
2748 	ret = getStmfState(&state);
2749 	if (ret != STMF_STATUS_SUCCESS)
2750 		return (ret);
2751 	if (state.operationalState == STMF_SERVICE_STATE_OFFLINE ||
2752 	    state.operationalState == STMF_SERVICE_STATE_OFFLINING) {
2753 		(void) fprintf(stderr, "%s: %s\n", cmdName,
2754 		    gettext("STMF service is offline"));
2755 		return (1);
2756 	}
2757 	return (onlineOfflineLu(operands[0], ONLINE_LU));
2758 }
2759 
2760 /*
2761  * offlineLuFunc
2762  *
2763  * Purpose: Offline a logical unit
2764  *
2765  */
2766 /*ARGSUSED*/
2767 static int
2768 offlineLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
2769     void *args)
2770 {
2771 	return (onlineOfflineLu(operands[0], OFFLINE_LU));
2772 }
2773 
2774 /*
2775  * onlineOfflineTarget
2776  *
2777  * Purpose: Online or offline a target
2778  *
2779  * target - target to online or offline
2780  *
2781  * state - ONLINE_TARGET
2782  *         OFFLINE_TARGET
2783  */
2784 static int
2785 onlineOfflineTarget(char *target, int state)
2786 {
2787 	int ret = 0;
2788 	stmfDevid devid;
2789 
2790 	if (parseDevid(target, &devid) != 0) {
2791 		(void) fprintf(stderr, "%s: %s: %s\n",
2792 		    cmdName, target, gettext("unrecognized device id"));
2793 		return (1);
2794 	}
2795 	if (state == ONLINE_TARGET) {
2796 		ret = stmfOnlineTarget(&devid);
2797 	} else if (state == OFFLINE_TARGET) {
2798 		ret = stmfOfflineTarget(&devid);
2799 	}
2800 	if (ret != STMF_STATUS_SUCCESS) {
2801 		switch (ret) {
2802 			case STMF_ERROR_PERM:
2803 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2804 				    gettext("permission denied"));
2805 				break;
2806 			case STMF_ERROR_SERVICE_NOT_FOUND:
2807 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2808 				    gettext("STMF service not found"));
2809 				break;
2810 			case STMF_ERROR_NOT_FOUND:
2811 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2812 				    target, gettext("not found"));
2813 				break;
2814 			case STMF_ERROR_SERVICE_DATA_VERSION:
2815 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2816 				    gettext("STMF service version incorrect"));
2817 				break;
2818 			default:
2819 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2820 				    gettext("unknown error"));
2821 				break;
2822 		}
2823 	}
2824 	return (ret);
2825 }
2826 
2827 /*
2828  * onlineTargetFunc
2829  *
2830  * Purpose: Online a target
2831  *
2832  */
2833 /*ARGSUSED*/
2834 static int
2835 onlineTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
2836     void *args)
2837 {
2838 	int ret;
2839 	stmfState state;
2840 
2841 	ret = getStmfState(&state);
2842 	if (ret != STMF_STATUS_SUCCESS)
2843 		return (ret);
2844 	if (state.operationalState == STMF_SERVICE_STATE_OFFLINE ||
2845 	    state.operationalState == STMF_SERVICE_STATE_OFFLINING) {
2846 		(void) fprintf(stderr, "%s: %s\n", cmdName,
2847 		    gettext("STMF service is offline"));
2848 		return (1);
2849 	}
2850 	return (onlineOfflineTarget(operands[0], ONLINE_TARGET));
2851 }
2852 
2853 /*
2854  * offlineTargetFunc
2855  *
2856  * Purpose: Offline a target
2857  *
2858  */
2859 /*ARGSUSED*/
2860 static int
2861 offlineTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
2862     void *args)
2863 {
2864 	return (onlineOfflineTarget(operands[0], OFFLINE_TARGET));
2865 }
2866 
2867 
2868 /*ARGSUSED*/
2869 static int
2870 removeHostGroupMemberFunc(int operandLen, char *operands[],
2871     cmdOptions_t *options, void *args)
2872 {
2873 	int i;
2874 	int ret = 0;
2875 	int stmfRet;
2876 	stmfGroupName groupName = {0};
2877 	stmfDevid devid;
2878 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
2879 
2880 	for (; options->optval; options++) {
2881 		switch (options->optval) {
2882 			case 'g':
2883 				(void) mbstowcs(groupNamePrint, options->optarg,
2884 				    sizeof (stmfGroupName) - 1);
2885 				bcopy(options->optarg, groupName,
2886 				    strlen(options->optarg));
2887 				break;
2888 			default:
2889 				(void) fprintf(stderr, "%s: %c: %s\n",
2890 				    cmdName, options->optval,
2891 				    gettext("unknown option"));
2892 				return (1);
2893 		}
2894 	}
2895 
2896 	for (i = 0; i < operandLen; i++) {
2897 		if (parseDevid(operands[i], &devid) != 0) {
2898 			(void) fprintf(stderr, "%s: %s: %s\n",
2899 			    cmdName, operands[i],
2900 			    gettext("unrecognized device id"));
2901 			ret++;
2902 			continue;
2903 		}
2904 		stmfRet = stmfRemoveFromHostGroup(&groupName, &devid);
2905 		switch (stmfRet) {
2906 			case STMF_STATUS_SUCCESS:
2907 				break;
2908 			case STMF_ERROR_MEMBER_NOT_FOUND:
2909 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2910 				    operands[i], gettext("not found"));
2911 				ret++;
2912 				break;
2913 			case STMF_ERROR_GROUP_NOT_FOUND:
2914 				(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
2915 				    groupNamePrint, gettext("not found"));
2916 				ret++;
2917 				break;
2918 			case STMF_ERROR_BUSY:
2919 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2920 				    operands[i], "resource busy");
2921 				ret++;
2922 				break;
2923 			case STMF_ERROR_SERVICE_NOT_FOUND:
2924 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2925 				    gettext("STMF service not found"));
2926 				ret++;
2927 				break;
2928 			case STMF_ERROR_SERVICE_DATA_VERSION:
2929 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2930 				    gettext("STMF service version incorrect"));
2931 				ret++;
2932 				break;
2933 			case STMF_ERROR_PERM:
2934 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2935 				    gettext("permission denied"));
2936 				ret++;
2937 				break;
2938 			default:
2939 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2940 				    operands[i], gettext("unknown error"));
2941 				ret++;
2942 				break;
2943 		}
2944 	}
2945 
2946 	return (ret);
2947 }
2948 
2949 /*
2950  * removeTargetGroupMemberFunc
2951  *
2952  * Removes one or more members from a target group
2953  *
2954  */
2955 /*ARGSUSED*/
2956 static int
2957 removeTargetGroupMemberFunc(int operandLen, char *operands[],
2958     cmdOptions_t *options, void *args)
2959 {
2960 	int i;
2961 	int ret = 0;
2962 	int stmfRet;
2963 	stmfGroupName groupName = {0};
2964 	stmfDevid devid;
2965 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
2966 
2967 	for (; options->optval; options++) {
2968 		switch (options->optval) {
2969 			case 'g':
2970 				(void) mbstowcs(groupNamePrint, options->optarg,
2971 				    sizeof (stmfGroupName) - 1);
2972 				bcopy(options->optarg, groupName,
2973 				    strlen(options->optarg));
2974 				break;
2975 			default:
2976 				(void) fprintf(stderr, "%s: %c: %s\n",
2977 				    cmdName, options->optval,
2978 				    gettext("unknown option"));
2979 				return (1);
2980 		}
2981 	}
2982 
2983 	for (i = 0; i < operandLen; i++) {
2984 		if (parseDevid(operands[i], &devid) != 0) {
2985 			(void) fprintf(stderr, "%s: %s: %s\n",
2986 			    cmdName, operands[i],
2987 			    gettext("unrecognized device id"));
2988 			ret++;
2989 			continue;
2990 		}
2991 		stmfRet = stmfRemoveFromTargetGroup(&groupName, &devid);
2992 		switch (stmfRet) {
2993 			case STMF_STATUS_SUCCESS:
2994 				break;
2995 			case STMF_ERROR_MEMBER_NOT_FOUND:
2996 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2997 				    operands[i], gettext("not found"));
2998 				ret++;
2999 				break;
3000 			case STMF_ERROR_GROUP_NOT_FOUND:
3001 				(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
3002 				    groupNamePrint, gettext("not found"));
3003 				ret++;
3004 				break;
3005 			case STMF_ERROR_BUSY:
3006 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3007 				    operands[i], gettext("resource busy"));
3008 				ret++;
3009 				break;
3010 			case STMF_ERROR_SERVICE_NOT_FOUND:
3011 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3012 				    gettext("STMF service not found"));
3013 				ret++;
3014 				break;
3015 			case STMF_ERROR_PERM:
3016 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3017 				    gettext("permission denied"));
3018 				ret++;
3019 				break;
3020 			case STMF_ERROR_SERVICE_DATA_VERSION:
3021 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3022 				    gettext("STMF service version incorrect"));
3023 				ret++;
3024 				break;
3025 			default:
3026 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3027 				    operands[i], gettext("unknown error"));
3028 				ret++;
3029 				break;
3030 		}
3031 	}
3032 
3033 	return (ret);
3034 }
3035 
3036 /*
3037  * removeViewFunc
3038  *
3039  * Removes one or more view entries from a logical unit
3040  *
3041  */
3042 /*ARGSUSED*/
3043 static int
3044 removeViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
3045     void *args)
3046 {
3047 	char sGuid[GUID_INPUT + 1];
3048 	stmfViewEntryList *viewEntryList;
3049 	stmfGuid inGuid;
3050 	uint32_t count;
3051 	unsigned int guid[sizeof (stmfGuid)];
3052 	char *endPtr;
3053 	uint32_t veNbr;
3054 	int i;
3055 	boolean_t all = B_FALSE;
3056 	boolean_t luInput = B_FALSE;
3057 	int ret = 0;
3058 	int stmfRet;
3059 
3060 	/* Note: 'l' is required */
3061 	for (; options->optval; options++) {
3062 		switch (options->optval) {
3063 			case 'l':
3064 				if (strlen(options->optarg) != GUID_INPUT) {
3065 					(void) fprintf(stderr,
3066 					    "%s: %s: %s %d %s\n",
3067 					    cmdName, options->optarg,
3068 					    gettext("must be"), GUID_INPUT,
3069 					    gettext("hexadecimal digits long"));
3070 					return (1);
3071 				}
3072 				bcopy(options->optarg, sGuid, GUID_INPUT);
3073 				luInput = B_TRUE;
3074 				break;
3075 			case 'a':
3076 				/* removing all view entries for this GUID */
3077 				all = B_TRUE;
3078 				break;
3079 			default:
3080 				(void) fprintf(stderr, "%s: %c: %s\n",
3081 				    cmdName, options->optval,
3082 				    "unknown option");
3083 				return (1);
3084 		}
3085 	}
3086 
3087 	if (!all && operandLen == 0) {
3088 		(void) fprintf(stderr, "%s: %s\n", cmdName,
3089 		    gettext("no view entries specified"));
3090 		return (1);
3091 	}
3092 
3093 	if (!luInput) {
3094 		(void) fprintf(stderr, "%s: %s\n", cmdName,
3095 		    gettext("logical unit (-l) not specified"));
3096 		return (1);
3097 	}
3098 
3099 	for (i = 0; i < 32; i++)
3100 		sGuid[i] = tolower(sGuid[i]);
3101 	sGuid[i] = 0;
3102 
3103 	(void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
3104 	    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
3105 	    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
3106 	    &guid[12], &guid[13], &guid[14], &guid[15]);
3107 
3108 	for (i = 0; i < sizeof (stmfGuid); i++) {
3109 		inGuid.guid[i] = guid[i];
3110 	}
3111 
3112 	if ((stmfRet = stmfGetViewEntryList(&inGuid, &viewEntryList))
3113 	    != STMF_STATUS_SUCCESS) {
3114 
3115 		switch (stmfRet) {
3116 			case STMF_ERROR_BUSY:
3117 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3118 				    sGuid, gettext("resource busy"));
3119 				break;
3120 			case STMF_ERROR_NOT_FOUND:
3121 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3122 				    sGuid, gettext("no views found"));
3123 				break;
3124 			case STMF_ERROR_SERVICE_NOT_FOUND:
3125 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3126 				    gettext("STMF service not found"));
3127 				break;
3128 			case STMF_ERROR_SERVICE_DATA_VERSION:
3129 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3130 				    gettext("STMF service version incorrect"));
3131 				break;
3132 			case STMF_ERROR_PERM:
3133 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3134 				    gettext("permission denied"));
3135 				break;
3136 			default:
3137 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3138 				    sGuid, gettext("unknown error"));
3139 				break;
3140 		}
3141 		return (1);
3142 	}
3143 
3144 	if (all) {
3145 		count = viewEntryList->cnt;
3146 	} else {
3147 		count = operandLen;
3148 	}
3149 
3150 	for (i = 0; i < count; i++) {
3151 		if (all) {
3152 			veNbr = viewEntryList->ve[i].veIndex;
3153 		} else {
3154 			endPtr = NULL;
3155 			veNbr = strtol(operands[i], &endPtr, 10);
3156 			if (endPtr && *endPtr != 0) {
3157 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3158 				    operands[i], gettext("invalid input"));
3159 				continue;
3160 			}
3161 		}
3162 		stmfRet = stmfRemoveViewEntry(&inGuid, veNbr);
3163 		switch (stmfRet) {
3164 			case STMF_STATUS_SUCCESS:
3165 				break;
3166 			case STMF_ERROR_NOT_FOUND:
3167 				(void) fprintf(stderr, "%s: %s: %d: %s\n",
3168 				    cmdName, sGuid, veNbr,
3169 				    gettext("not found"));
3170 				ret++;
3171 				break;
3172 			case STMF_ERROR_BUSY:
3173 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3174 				    sGuid, gettext("resource busy"));
3175 				ret++;
3176 				break;
3177 			case STMF_ERROR_SERVICE_NOT_FOUND:
3178 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3179 				    gettext("STMF service not found"));
3180 				ret++;
3181 				break;
3182 			case STMF_ERROR_CONFIG_NONE:
3183 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3184 				    gettext("STMF service is not initialized"));
3185 				ret++;
3186 				break;
3187 			case STMF_ERROR_SERVICE_DATA_VERSION:
3188 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3189 				    gettext("STMF service version incorrect"));
3190 				ret++;
3191 				break;
3192 			default:
3193 				(void) fprintf(stderr, "%s: %s, %d: %s",
3194 				    cmdName, sGuid, veNbr,
3195 				    gettext("unknown error"));
3196 				ret++;
3197 				break;
3198 		}
3199 	}
3200 
3201 	return (ret);
3202 }
3203 
3204 /*
3205  * input:
3206  *  execFullName - exec name of program (argv[0])
3207  *
3208  *  copied from usr/src/cmd/zoneadm/zoneadm.c in OS/Net
3209  *  (changed name to lowerCamelCase to keep consistent with this file)
3210  *
3211  * Returns:
3212  *  command name portion of execFullName
3213  */
3214 static char *
3215 getExecBasename(char *execFullname)
3216 {
3217 	char *lastSlash, *execBasename;
3218 
3219 	/* guard against '/' at end of command invocation */
3220 	for (;;) {
3221 		lastSlash = strrchr(execFullname, '/');
3222 		if (lastSlash == NULL) {
3223 			execBasename = execFullname;
3224 			break;
3225 		} else {
3226 			execBasename = lastSlash + 1;
3227 			if (*execBasename == '\0') {
3228 				*lastSlash = '\0';
3229 				continue;
3230 			}
3231 			break;
3232 		}
3233 	}
3234 	return (execBasename);
3235 }
3236 
3237 int
3238 main(int argc, char *argv[])
3239 {
3240 	synTables_t synTables;
3241 	char versionString[VERSION_STRING_MAX_LEN];
3242 	int ret;
3243 	int funcRet;
3244 	void *subcommandArgs = NULL;
3245 
3246 	(void) setlocale(LC_ALL, "");
3247 	(void) textdomain(TEXT_DOMAIN);
3248 	/* set global command name */
3249 	cmdName = getExecBasename(argv[0]);
3250 
3251 	(void) snprintf(versionString, VERSION_STRING_MAX_LEN, "%s.%s",
3252 	    VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
3253 	synTables.versionString = versionString;
3254 	synTables.longOptionTbl = &longOptions[0];
3255 	synTables.subCommandPropsTbl = &subcommands[0];
3256 
3257 	ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet);
3258 	if (ret != 0) {
3259 		return (ret);
3260 	}
3261 
3262 	return (funcRet);
3263 } /* end main */
3264