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