xref: /illumos-gate/usr/src/cmd/stmfadm/stmfadm.c (revision 23524732d002da91177f82bdfa44378749661577)
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 		default:
1117 			(void) fprintf(stderr, "%s: %s: %s: %d\n", cmdName,
1118 			    gettext("could not set property"), propString,
1119 			    stmfRet);
1120 			ret++;
1121 			break;
1122 	}
1123 
1124 	return (ret);
1125 }
1126 
1127 
1128 /*
1129  * importLuFunc
1130  *
1131  * Create a logical unit
1132  *
1133  */
1134 /*ARGSUSED*/
1135 static int
1136 importLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
1137     void *args)
1138 {
1139 	int stmfRet = 0;
1140 	int ret = 0;
1141 	char guidAsciiBuf[33];
1142 	stmfGuid createdGuid;
1143 
1144 	stmfRet = stmfImportLu(STMF_DISK, operands[0], &createdGuid);
1145 	switch (stmfRet) {
1146 		case STMF_STATUS_SUCCESS:
1147 			break;
1148 		case STMF_ERROR_BUSY:
1149 		case STMF_ERROR_LU_BUSY:
1150 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1151 			    gettext("resource busy"));
1152 			ret++;
1153 			break;
1154 		case STMF_ERROR_PERM:
1155 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1156 			    gettext("permission denied"));
1157 			ret++;
1158 			break;
1159 		case STMF_ERROR_FILE_IN_USE:
1160 			(void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
1161 			    operands[0], gettext("in use"));
1162 			ret++;
1163 			break;
1164 		case STMF_ERROR_GUID_IN_USE:
1165 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1166 			    gettext("guid in use"));
1167 			ret++;
1168 			break;
1169 		case STMF_ERROR_META_FILE_NAME:
1170 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1171 			    gettext("meta file error"));
1172 			ret++;
1173 			break;
1174 		case STMF_ERROR_DATA_FILE_NAME:
1175 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1176 			    gettext("data file error"));
1177 			ret++;
1178 			break;
1179 		case STMF_ERROR_META_CREATION:
1180 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1181 			    gettext("could not create meta file"));
1182 			ret++;
1183 			break;
1184 		case STMF_ERROR_WRITE_CACHE_SET:
1185 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1186 			    gettext("could not set write cache"));
1187 			ret++;
1188 			break;
1189 		default:
1190 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1191 			    gettext("unknown error"));
1192 			ret++;
1193 			break;
1194 	}
1195 
1196 	if (ret != STMF_STATUS_SUCCESS) {
1197 		goto done;
1198 	}
1199 
1200 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
1201 	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
1202 	    "%02X%02X%02X%02X%02X%02X",
1203 	    createdGuid.guid[0], createdGuid.guid[1], createdGuid.guid[2],
1204 	    createdGuid.guid[3], createdGuid.guid[4], createdGuid.guid[5],
1205 	    createdGuid.guid[6], createdGuid.guid[7], createdGuid.guid[8],
1206 	    createdGuid.guid[9], createdGuid.guid[10], createdGuid.guid[11],
1207 	    createdGuid.guid[12], createdGuid.guid[13], createdGuid.guid[14],
1208 	    createdGuid.guid[15]);
1209 	(void) printf("Logical unit imported: %s\n", guidAsciiBuf);
1210 
1211 done:
1212 	return (ret);
1213 }
1214 
1215 static int
1216 setLuPropFromInput(luResource hdl, char *optarg)
1217 {
1218 	char *prop = NULL;
1219 	char *propVal = NULL;
1220 	char *lasts = NULL;
1221 	uint32_t propId;
1222 	int ret = 0;
1223 
1224 	prop = strtok_r(optarg, "=", &lasts);
1225 	if ((propVal = strtok_r(NULL, "=", &lasts)) == NULL) {
1226 		(void) fprintf(stderr, "%s: %s: %s\n",
1227 		    cmdName, optarg,
1228 		    gettext("invalid property specifier - prop=val\n"));
1229 		return (1);
1230 	}
1231 
1232 	ret = convertCharToPropId(prop, &propId);
1233 	if (ret != 0) {
1234 		(void) fprintf(stderr, "%s: %s: %s\n",
1235 		    cmdName, gettext("invalid property specified"), prop);
1236 		return (1);
1237 	}
1238 
1239 	ret = stmfSetLuProp(hdl, propId, propVal);
1240 	if (ret != STMF_STATUS_SUCCESS) {
1241 		(void) fprintf(stderr, "%s: %s %s: ",
1242 		    cmdName, gettext("unable to set"), prop);
1243 		switch (ret) {
1244 			case STMF_ERROR_INVALID_PROPSIZE:
1245 				(void) fprintf(stderr, "invalid length\n");
1246 				break;
1247 			case STMF_ERROR_INVALID_ARG:
1248 				(void) fprintf(stderr, "bad format\n");
1249 				break;
1250 			default:
1251 				(void) fprintf(stderr, "\n");
1252 				break;
1253 		}
1254 		return (1);
1255 	}
1256 
1257 	return (0);
1258 }
1259 
1260 static int
1261 convertCharToPropId(char *prop, uint32_t *propId)
1262 {
1263 	if (strcasecmp(prop, GUID) == 0) {
1264 		*propId = STMF_LU_PROP_GUID;
1265 	} else if (strcasecmp(prop, ALIAS) == 0) {
1266 		*propId = STMF_LU_PROP_ALIAS;
1267 	} else if (strcasecmp(prop, VID) == 0) {
1268 		*propId = STMF_LU_PROP_VID;
1269 	} else if (strcasecmp(prop, PID) == 0) {
1270 		*propId = STMF_LU_PROP_PID;
1271 	} else if (strcasecmp(prop, WRITE_PROTECT) == 0) {
1272 		*propId = STMF_LU_PROP_WRITE_PROTECT;
1273 	} else if (strcasecmp(prop, WRITEBACK_CACHE_DISABLE) == 0) {
1274 		*propId = STMF_LU_PROP_WRITE_CACHE_DISABLE;
1275 	} else if (strcasecmp(prop, BLOCK_SIZE) == 0) {
1276 		*propId = STMF_LU_PROP_BLOCK_SIZE;
1277 	} else if (strcasecmp(prop, SERIAL_NUMBER) == 0) {
1278 		*propId = STMF_LU_PROP_SERIAL_NUM;
1279 	} else if (strcasecmp(prop, COMPANY_ID) == 0) {
1280 		*propId = STMF_LU_PROP_COMPANY_ID;
1281 	} else if (strcasecmp(prop, META_FILE) == 0) {
1282 		*propId = STMF_LU_PROP_META_FILENAME;
1283 	} else if (strcasecmp(prop, MGMT_URL) == 0) {
1284 		*propId = STMF_LU_PROP_MGMT_URL;
1285 	} else {
1286 		return (1);
1287 	}
1288 	return (0);
1289 }
1290 
1291 /*
1292  * deleteLuFunc
1293  *
1294  * Delete a logical unit
1295  *
1296  */
1297 /*ARGSUSED*/
1298 static int
1299 deleteLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
1300     void *args)
1301 {
1302 	int i, j;
1303 	int ret = 0;
1304 	int stmfRet;
1305 	unsigned int inGuid[sizeof (stmfGuid)];
1306 	stmfGuid delGuid;
1307 	boolean_t keepViews = B_FALSE;
1308 	boolean_t viewEntriesRemoved = B_FALSE;
1309 	boolean_t noLunFound = B_FALSE;
1310 	boolean_t views = B_FALSE;
1311 	char sGuid[GUID_INPUT + 1];
1312 	stmfViewEntryList *viewEntryList = NULL;
1313 
1314 	for (; options->optval; options++) {
1315 		switch (options->optval) {
1316 			/* Keep views for logical unit */
1317 			case 'k':
1318 				keepViews = B_TRUE;
1319 				break;
1320 			default:
1321 				(void) fprintf(stderr, "%s: %c: %s\n",
1322 				    cmdName, options->optval,
1323 				    gettext("unknown option"));
1324 				return (1);
1325 		}
1326 	}
1327 
1328 
1329 	for (i = 0; i < operandLen; i++) {
1330 		for (j = 0; j < GUID_INPUT; j++) {
1331 			if (!isxdigit(operands[i][j])) {
1332 				break;
1333 			}
1334 			sGuid[j] = tolower(operands[i][j]);
1335 		}
1336 		if (j != GUID_INPUT) {
1337 			(void) fprintf(stderr, "%s: %s: %s%d%s\n",
1338 			    cmdName, operands[i], gettext("must be "),
1339 			    GUID_INPUT,
1340 			    gettext(" hexadecimal digits long"));
1341 			continue;
1342 		}
1343 
1344 		sGuid[j] = 0;
1345 
1346 		(void) sscanf(sGuid,
1347 		    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
1348 		    &inGuid[0], &inGuid[1], &inGuid[2], &inGuid[3],
1349 		    &inGuid[4], &inGuid[5], &inGuid[6], &inGuid[7],
1350 		    &inGuid[8], &inGuid[9], &inGuid[10], &inGuid[11],
1351 		    &inGuid[12], &inGuid[13], &inGuid[14], &inGuid[15]);
1352 
1353 		for (j = 0; j < sizeof (stmfGuid); j++) {
1354 			delGuid.guid[j] = inGuid[j];
1355 		}
1356 
1357 		stmfRet = stmfDeleteLu(&delGuid);
1358 		switch (stmfRet) {
1359 			case STMF_STATUS_SUCCESS:
1360 				break;
1361 			case STMF_ERROR_NOT_FOUND:
1362 				noLunFound = B_TRUE;
1363 				break;
1364 			case STMF_ERROR_BUSY:
1365 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1366 				    gettext("resource busy"));
1367 				ret++;
1368 				break;
1369 			case STMF_ERROR_PERM:
1370 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1371 				    gettext("permission denied"));
1372 				ret++;
1373 				break;
1374 			default:
1375 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1376 				    gettext("unknown error"));
1377 				ret++;
1378 				break;
1379 		}
1380 
1381 		if (!keepViews) {
1382 			stmfRet = stmfGetViewEntryList(&delGuid,
1383 			    &viewEntryList);
1384 			if (stmfRet == STMF_STATUS_SUCCESS) {
1385 				for (j = 0; j < viewEntryList->cnt; j++) {
1386 					(void) stmfRemoveViewEntry(&delGuid,
1387 					    viewEntryList->ve[j].veIndex);
1388 				}
1389 				viewEntriesRemoved = B_TRUE;
1390 				stmfFreeMemory(viewEntryList);
1391 			} else if (stmfRet != STMF_ERROR_NOT_FOUND) {
1392 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1393 				    gettext("unable to remove view entries\n"));
1394 				ret++;
1395 			} /* No view entries to remove */
1396 		}
1397 		if (keepViews) {
1398 			stmfRet = stmfGetViewEntryList(&delGuid,
1399 			    &viewEntryList);
1400 			if (stmfRet == STMF_STATUS_SUCCESS) {
1401 				views = B_TRUE;
1402 				stmfFreeMemory(viewEntryList);
1403 			}
1404 		}
1405 
1406 		if ((!viewEntriesRemoved && noLunFound && !views) ||
1407 		    (!views && keepViews && noLunFound)) {
1408 			(void) fprintf(stderr, "%s: %s: %s\n",
1409 			    cmdName, sGuid,
1410 			    gettext("not found"));
1411 			ret++;
1412 		}
1413 		noLunFound = viewEntriesRemoved = views = B_FALSE;
1414 	}
1415 	return (ret);
1416 }
1417 
1418 
1419 /*
1420  * createTargetGroupFunc
1421  *
1422  * Create a target group
1423  *
1424  */
1425 /*ARGSUSED*/
1426 static int
1427 createTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
1428     void *args)
1429 {
1430 	int ret = 0;
1431 	int stmfRet;
1432 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
1433 	stmfGroupName groupName = {0};
1434 
1435 	(void) strlcpy(groupName, operands[0], sizeof (groupName));
1436 	(void) mbstowcs(groupNamePrint, (char *)groupName,
1437 	    sizeof (stmfGroupName) - 1);
1438 	/* call create group */
1439 	stmfRet = stmfCreateTargetGroup(&groupName);
1440 	switch (stmfRet) {
1441 		case STMF_STATUS_SUCCESS:
1442 			break;
1443 		case STMF_ERROR_EXISTS:
1444 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1445 			    groupNamePrint, gettext("already exists"));
1446 			ret++;
1447 			break;
1448 		case STMF_ERROR_BUSY:
1449 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1450 			    groupNamePrint, gettext("resource busy"));
1451 			ret++;
1452 			break;
1453 		case STMF_ERROR_PERM:
1454 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1455 			    gettext("permission denied"));
1456 			ret++;
1457 			break;
1458 		case STMF_ERROR_SERVICE_NOT_FOUND:
1459 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1460 			    gettext("STMF service not found"));
1461 			ret++;
1462 			break;
1463 		case STMF_ERROR_SERVICE_DATA_VERSION:
1464 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1465 			    gettext("STMF service version incorrect"));
1466 			ret++;
1467 			break;
1468 		default:
1469 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1470 			    groupNamePrint, gettext("unknown error"));
1471 			ret++;
1472 			break;
1473 	}
1474 
1475 	return (ret);
1476 }
1477 
1478 /*
1479  * deleteHostGroupFunc
1480  *
1481  * Delete a host group
1482  *
1483  */
1484 /*ARGSUSED*/
1485 static int
1486 deleteHostGroupFunc(int operandLen, char *operands[],
1487     cmdOptions_t *options, void *args)
1488 {
1489 	int ret = 0;
1490 	int stmfRet;
1491 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
1492 	stmfGroupName groupName = {0};
1493 
1494 	(void) strlcpy(groupName, operands[0], sizeof (groupName));
1495 	(void) mbstowcs(groupNamePrint, (char *)groupName,
1496 	    sizeof (stmfGroupName) - 1);
1497 	/* call delete group */
1498 	stmfRet = stmfDeleteHostGroup(&groupName);
1499 	switch (stmfRet) {
1500 		case STMF_STATUS_SUCCESS:
1501 			break;
1502 		case STMF_ERROR_NOT_FOUND:
1503 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1504 			    groupNamePrint, gettext("not found"));
1505 			ret++;
1506 			break;
1507 		case STMF_ERROR_BUSY:
1508 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1509 			    groupNamePrint, gettext("resource busy"));
1510 			ret++;
1511 			break;
1512 		case STMF_ERROR_SERVICE_NOT_FOUND:
1513 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1514 			    gettext("STMF service not found"));
1515 			ret++;
1516 			break;
1517 		case STMF_ERROR_PERM:
1518 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1519 			    gettext("permission denied"));
1520 			ret++;
1521 			break;
1522 		case STMF_ERROR_GROUP_IN_USE:
1523 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1524 			    groupNamePrint,
1525 			    gettext("group is in use by existing view entry"));
1526 			ret++;
1527 			break;
1528 		case STMF_ERROR_SERVICE_DATA_VERSION:
1529 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1530 			    gettext("STMF service version incorrect"));
1531 			ret++;
1532 			break;
1533 		default:
1534 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1535 			    groupNamePrint, gettext("unknown error"));
1536 			ret++;
1537 			break;
1538 	}
1539 
1540 	return (ret);
1541 }
1542 
1543 /*
1544  * deleteTargetGroupFunc
1545  *
1546  * Delete a target group
1547  *
1548  */
1549 /*ARGSUSED*/
1550 static int
1551 deleteTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
1552     void *args)
1553 {
1554 	int ret = 0;
1555 	int stmfRet;
1556 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
1557 	stmfGroupName groupName = {0};
1558 
1559 	(void) strlcpy(groupName, operands[0], sizeof (groupName));
1560 	(void) mbstowcs(groupNamePrint, (char *)groupName,
1561 	    sizeof (stmfGroupName) - 1);
1562 	/* call delete group */
1563 	stmfRet = stmfDeleteTargetGroup(&groupName);
1564 	switch (stmfRet) {
1565 		case STMF_STATUS_SUCCESS:
1566 			break;
1567 		case STMF_ERROR_NOT_FOUND:
1568 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1569 			    groupNamePrint, gettext("not found"));
1570 			ret++;
1571 			break;
1572 		case STMF_ERROR_BUSY:
1573 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1574 			    groupNamePrint, gettext("resource busy"));
1575 			ret++;
1576 			break;
1577 		case STMF_ERROR_SERVICE_NOT_FOUND:
1578 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1579 			    gettext("STMF service not found"));
1580 			ret++;
1581 			break;
1582 		case STMF_ERROR_PERM:
1583 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1584 			    gettext("permission denied"));
1585 			ret++;
1586 			break;
1587 		case STMF_ERROR_GROUP_IN_USE:
1588 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1589 			    groupNamePrint,
1590 			    gettext("group is in use by existing view entry"));
1591 			ret++;
1592 			break;
1593 		case STMF_ERROR_SERVICE_DATA_VERSION:
1594 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1595 			    gettext("STMF service version incorrect"));
1596 			ret++;
1597 			break;
1598 		default:
1599 			(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1600 			    groupNamePrint, gettext("unknown error"));
1601 			ret++;
1602 			break;
1603 	}
1604 
1605 	return (ret);
1606 }
1607 
1608 /*
1609  * listHostGroupFunc
1610  *
1611  * Lists the specified host groups or all if none are specified
1612  *
1613  */
1614 /*ARGSUSED*/
1615 static int
1616 listHostGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
1617     void *args)
1618 {
1619 	int ret = 0;
1620 	int stmfRet;
1621 	int i, j, outerLoop;
1622 	boolean_t verbose = B_FALSE;
1623 	boolean_t found = B_TRUE;
1624 	boolean_t operandEntered;
1625 	stmfGroupList *groupList;
1626 	stmfGroupProperties *groupProps;
1627 	wchar_t operandName[sizeof (stmfGroupName)];
1628 	wchar_t groupNamePrint[sizeof (stmfGroupName)];
1629 
1630 	for (; options->optval; options++) {
1631 		switch (options->optval) {
1632 			case 'v':
1633 				verbose = B_TRUE;
1634 				break;
1635 			default:
1636 				(void) fprintf(stderr, "%s: %c: %s\n",
1637 				    cmdName, options->optval,
1638 				    gettext("unknown option"));
1639 				return (1);
1640 		}
1641 	}
1642 
1643 	if (operandLen > 0) {
1644 		outerLoop = operandLen;
1645 		operandEntered = B_TRUE;
1646 	} else {
1647 		outerLoop = 1;
1648 		operandEntered = B_FALSE;
1649 	}
1650 
1651 	stmfRet = stmfGetHostGroupList(&groupList);
1652 	if (stmfRet != STMF_STATUS_SUCCESS) {
1653 		switch (stmfRet) {
1654 			case STMF_ERROR_BUSY:
1655 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1656 				    gettext("resource busy"));
1657 				break;
1658 			case STMF_ERROR_SERVICE_NOT_FOUND:
1659 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1660 				    gettext("STMF service not found"));
1661 				break;
1662 			case STMF_ERROR_PERM:
1663 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1664 				    gettext("permission denied"));
1665 				break;
1666 			case STMF_ERROR_SERVICE_DATA_VERSION:
1667 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1668 				    gettext("STMF service version incorrect"));
1669 				break;
1670 			default:
1671 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1672 				    gettext("unknown error"));
1673 				break;
1674 		}
1675 		return (1);
1676 	}
1677 
1678 	for (i = 0; i < outerLoop; i++) {
1679 		for (found = B_FALSE, j = 0; j < groupList->cnt; j++) {
1680 			(void) mbstowcs(groupNamePrint,
1681 			    (char *)groupList->name[j],
1682 			    sizeof (stmfGroupName) - 1);
1683 			groupNamePrint[sizeof (stmfGroupName) - 1] = 0;
1684 			if (operandEntered) {
1685 				(void) mbstowcs(operandName, operands[i],
1686 				    sizeof (stmfGroupName) - 1);
1687 				operandName[sizeof (stmfGroupName) - 1] = 0;
1688 				if (wcscmp(operandName, groupNamePrint)
1689 				    == 0) {
1690 					found = B_TRUE;
1691 				}
1692 			}
1693 			if ((found && operandEntered) || !operandEntered) {
1694 				(void) printf("Host Group: %ws\n",
1695 				    groupNamePrint);
1696 				if (verbose) {
1697 					stmfRet = stmfGetHostGroupMembers(
1698 					    &(groupList->name[j]), &groupProps);
1699 					if (stmfRet != STMF_STATUS_SUCCESS) {
1700 						return (1);
1701 					}
1702 					printGroupProps(groupProps);
1703 				}
1704 				if (found && operandEntered) {
1705 					break;
1706 				}
1707 			}
1708 
1709 		}
1710 		if (operandEntered && !found) {
1711 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
1712 			    operands[i], gettext("not found"));
1713 			ret = 1;
1714 		}
1715 	}
1716 	return (ret);
1717 }
1718 
1719 /*
1720  * printGroupProps
1721  *
1722  * Prints group members for target or host groups
1723  *
1724  */
1725 static void
1726 printGroupProps(stmfGroupProperties *groupProps)
1727 {
1728 	int i;
1729 	wchar_t memberIdent[sizeof (groupProps->name[0].ident) + 1] = {0};
1730 
1731 
1732 	for (i = 0; i < groupProps->cnt; i++) {
1733 		(void) mbstowcs(memberIdent, (char *)groupProps->name[i].ident,
1734 		    sizeof (groupProps->name[0].ident));
1735 		(void) printf("\tMember: %ws\n", memberIdent);
1736 	}
1737 }
1738 
1739 /*
1740  * listTargetGroupFunc
1741  *
1742  * Lists the specified target groups or all if none are specified
1743  *
1744  */
1745 /*ARGSUSED*/
1746 static int
1747 listTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
1748     void *args)
1749 {
1750 	int ret = 0;
1751 	int stmfRet;
1752 	int i, j, outerLoop;
1753 	boolean_t verbose = B_FALSE;
1754 	boolean_t found = B_TRUE;
1755 	boolean_t operandEntered;
1756 	stmfGroupList *groupList;
1757 	stmfGroupProperties *groupProps;
1758 	wchar_t operandName[sizeof (stmfGroupName)];
1759 	wchar_t groupNamePrint[sizeof (stmfGroupName)];
1760 
1761 	for (; options->optval; options++) {
1762 		switch (options->optval) {
1763 			case 'v':
1764 				verbose = B_TRUE;
1765 				break;
1766 			default:
1767 				(void) fprintf(stderr, "%s: %c: %s\n",
1768 				    cmdName, options->optval,
1769 				    gettext("unknown option"));
1770 				return (1);
1771 		}
1772 	}
1773 
1774 	if (operandLen > 0) {
1775 		outerLoop = operandLen;
1776 		operandEntered = B_TRUE;
1777 	} else {
1778 		outerLoop = 1;
1779 		operandEntered = B_FALSE;
1780 	}
1781 
1782 	stmfRet = stmfGetTargetGroupList(&groupList);
1783 	if (stmfRet != STMF_STATUS_SUCCESS) {
1784 		switch (stmfRet) {
1785 			case STMF_ERROR_BUSY:
1786 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1787 				    gettext("resource busy"));
1788 				break;
1789 			case STMF_ERROR_SERVICE_NOT_FOUND:
1790 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1791 				    gettext("STMF service not found"));
1792 				break;
1793 			case STMF_ERROR_SERVICE_DATA_VERSION:
1794 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1795 				    gettext("STMF service version incorrect"));
1796 				break;
1797 			case STMF_ERROR_PERM:
1798 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1799 				    gettext("permission denied"));
1800 				break;
1801 			default:
1802 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1803 				    gettext("unknown error"));
1804 				break;
1805 		}
1806 		return (1);
1807 	}
1808 
1809 	for (i = 0; i < outerLoop; i++) {
1810 		for (found = B_FALSE, j = 0; j < groupList->cnt; j++) {
1811 			(void) mbstowcs(groupNamePrint,
1812 			    (char *)groupList->name[j],
1813 			    sizeof (stmfGroupName) - 1);
1814 			groupNamePrint[sizeof (stmfGroupName) - 1] = 0;
1815 			if (operandEntered) {
1816 				(void) mbstowcs(operandName, operands[i],
1817 				    sizeof (stmfGroupName) - 1);
1818 				operandName[sizeof (stmfGroupName) - 1] = 0;
1819 				if (wcscmp(operandName, groupNamePrint)
1820 				    == 0) {
1821 					found = B_TRUE;
1822 				}
1823 			}
1824 			if ((found && operandEntered) || !operandEntered) {
1825 				(void) printf("Target Group: %ws\n",
1826 				    groupNamePrint);
1827 				if (verbose) {
1828 					stmfRet = stmfGetTargetGroupMembers(
1829 					    &(groupList->name[j]), &groupProps);
1830 					if (stmfRet != STMF_STATUS_SUCCESS) {
1831 						return (1);
1832 					}
1833 					printGroupProps(groupProps);
1834 				}
1835 				if (found && operandEntered) {
1836 					break;
1837 				}
1838 			}
1839 
1840 		}
1841 		if (operandEntered && !found) {
1842 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
1843 			    operands[i], gettext("not found"));
1844 			ret = 1;
1845 		}
1846 	}
1847 	return (ret);
1848 }
1849 
1850 /*
1851  * listLuFunc
1852  *
1853  * List the logical units and optionally the properties
1854  *
1855  */
1856 /*ARGSUSED*/
1857 static int
1858 listLuFunc(int operandLen, char *operands[], cmdOptions_t *options, void *args)
1859 {
1860 	cmdOptions_t *optionList = options;
1861 	boolean_t operandEntered;
1862 	int i, j;
1863 	int ret = 0;
1864 	int stmfRet;
1865 	int outerLoop;
1866 	unsigned int inGuid[sizeof (stmfGuid)];
1867 	stmfGuid cmpGuid;
1868 	boolean_t verbose = B_FALSE;
1869 	boolean_t found;
1870 	char sGuid[GUID_INPUT + 1];
1871 	stmfGuidList *luList;
1872 	stmfLogicalUnitProperties luProps;
1873 	boolean_t invalidInput = B_FALSE;
1874 	stmfViewEntryList *viewEntryList;
1875 
1876 	for (; optionList->optval; optionList++) {
1877 		switch (optionList->optval) {
1878 			case 'v':
1879 				verbose = B_TRUE;
1880 				break;
1881 		}
1882 	}
1883 
1884 	if ((stmfRet = stmfGetLogicalUnitList(&luList))
1885 	    != STMF_STATUS_SUCCESS) {
1886 		switch (stmfRet) {
1887 			case STMF_ERROR_SERVICE_NOT_FOUND:
1888 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1889 				    gettext("STMF service not found"));
1890 				break;
1891 			case STMF_ERROR_BUSY:
1892 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1893 				    gettext("resource busy"));
1894 				break;
1895 			case STMF_ERROR_PERM:
1896 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1897 				    gettext("permission denied"));
1898 				break;
1899 			case STMF_ERROR_SERVICE_DATA_VERSION:
1900 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1901 				    gettext("STMF service version incorrect"));
1902 				break;
1903 			default:
1904 				(void) fprintf(stderr, "%s: %s\n", cmdName,
1905 				    gettext("list failed"));
1906 				break;
1907 		}
1908 		return (1);
1909 	}
1910 
1911 	if (operandLen > 0) {
1912 		operandEntered = B_TRUE;
1913 		outerLoop = operandLen;
1914 	} else {
1915 		operandEntered = B_FALSE;
1916 		outerLoop = 1;
1917 	}
1918 
1919 
1920 	for (invalidInput = B_FALSE, i = 0; i < outerLoop; i++) {
1921 		if (operandEntered) {
1922 			if (strlen(operands[i]) != GUID_INPUT) {
1923 				invalidInput = B_TRUE;
1924 			} else {
1925 				for (j = 0; j < GUID_INPUT; j++) {
1926 					if (!isxdigit(operands[i][j])) {
1927 						invalidInput = B_TRUE;
1928 						break;
1929 					}
1930 				}
1931 			}
1932 			if (invalidInput) {
1933 				(void) fprintf(stderr, "%s: %s: %s%d%s\n",
1934 				    cmdName, operands[i], gettext("must be "),
1935 				    GUID_INPUT,
1936 				    gettext(" hexadecimal digits long"));
1937 				invalidInput = B_FALSE;
1938 				continue;
1939 			}
1940 
1941 			for (j = 0; j < GUID_INPUT; j++) {
1942 				sGuid[j] = tolower(operands[i][j]);
1943 			}
1944 			sGuid[j] = 0;
1945 
1946 			(void) sscanf(sGuid,
1947 			    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
1948 			    &inGuid[0], &inGuid[1], &inGuid[2], &inGuid[3],
1949 			    &inGuid[4], &inGuid[5], &inGuid[6], &inGuid[7],
1950 			    &inGuid[8], &inGuid[9], &inGuid[10], &inGuid[11],
1951 			    &inGuid[12], &inGuid[13], &inGuid[14], &inGuid[15]);
1952 
1953 			for (j = 0; j < sizeof (stmfGuid); j++) {
1954 				cmpGuid.guid[j] = inGuid[j];
1955 			}
1956 		}
1957 
1958 		for (found = B_FALSE, j = 0; j < luList->cnt; j++) {
1959 			if (operandEntered) {
1960 				if (bcmp(luList->guid[j].guid, cmpGuid.guid,
1961 				    sizeof (stmfGuid)) == 0) {
1962 					found = B_TRUE;
1963 				}
1964 			}
1965 			if ((found && operandEntered) || !operandEntered) {
1966 				(void) printf("LU Name: ");
1967 				printGuid(&luList->guid[j], stdout);
1968 				(void) printf("\n");
1969 
1970 				if (verbose) {
1971 					stmfRet = stmfGetLogicalUnitProperties(
1972 					    &(luList->guid[j]), &luProps);
1973 					if (stmfRet == STMF_STATUS_SUCCESS) {
1974 						printLuProps(&luProps);
1975 					} else {
1976 						(void) fprintf(stderr, "%s:",
1977 						    cmdName);
1978 						printGuid(&luList->guid[j],
1979 						    stderr);
1980 						(void) fprintf(stderr, "%s\n",
1981 						    gettext(" get properties "
1982 						    "failed"));
1983 					}
1984 					stmfRet = stmfGetViewEntryList(
1985 					    &(luList->guid[j]),
1986 					    &viewEntryList);
1987 					(void) printf(PROPS_FORMAT,
1988 					    "View Entry Count");
1989 					if (stmfRet == STMF_STATUS_SUCCESS) {
1990 						(void) printf("%d",
1991 						    viewEntryList->cnt);
1992 					} else if (stmfRet ==
1993 					    STMF_ERROR_NOT_FOUND) {
1994 						(void) printf("0");
1995 					} else {
1996 						(void) printf("unknown");
1997 					}
1998 					(void) printf("\n");
1999 					ret = printExtLuProps(
2000 					    &(luList->guid[j]));
2001 				}
2002 				if (found && operandEntered) {
2003 					break;
2004 				}
2005 			}
2006 
2007 		}
2008 		if (operandEntered && !found) {
2009 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2010 			    operands[i], gettext("not found"));
2011 			ret = 1;
2012 		}
2013 	}
2014 
2015 	return (ret);
2016 }
2017 
2018 static void
2019 printGuid(stmfGuid *guid, FILE *stream)
2020 {
2021 	int i;
2022 	for (i = 0; i < 16; i++) {
2023 		(void) fprintf(stream, "%02X", guid->guid[i]);
2024 	}
2025 }
2026 
2027 static int
2028 printExtLuProps(stmfGuid *guid)
2029 {
2030 	int stmfRet;
2031 	luResource hdl = NULL;
2032 	int ret = 0;
2033 	char propVal[MAXNAMELEN];
2034 	size_t propValSize = sizeof (propVal);
2035 
2036 	if ((stmfRet = stmfGetLuResource(guid, &hdl))
2037 	    != STMF_STATUS_SUCCESS) {
2038 		switch (stmfRet) {
2039 			case STMF_ERROR_BUSY:
2040 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2041 				    gettext("resource busy"));
2042 				break;
2043 			case STMF_ERROR_PERM:
2044 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2045 				    gettext("permission denied"));
2046 				break;
2047 			case STMF_ERROR_NOT_FOUND:
2048 				/* No error here */
2049 				return (0);
2050 				break;
2051 			default:
2052 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2053 				    gettext("get extended properties failed"));
2054 				break;
2055 		}
2056 		return (1);
2057 	}
2058 
2059 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_FILENAME, propVal,
2060 	    &propValSize);
2061 	(void) printf(PROPS_FORMAT, "Data File");
2062 	if (stmfRet == STMF_STATUS_SUCCESS) {
2063 		(void) printf("%s\n", propVal);
2064 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2065 		(void) printf("not set\n");
2066 	} else {
2067 		(void) printf("<error retrieving property>\n");
2068 		ret++;
2069 	}
2070 
2071 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_META_FILENAME, propVal,
2072 	    &propValSize);
2073 	(void) printf(PROPS_FORMAT, "Meta File");
2074 	if (stmfRet == STMF_STATUS_SUCCESS) {
2075 		(void) printf("%s\n", propVal);
2076 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2077 		(void) printf("not set\n");
2078 	} else {
2079 		(void) printf("<error retrieving property>\n");
2080 		ret++;
2081 	}
2082 
2083 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SIZE, propVal,
2084 	    &propValSize);
2085 	(void) printf(PROPS_FORMAT, "Size");
2086 	if (stmfRet == STMF_STATUS_SUCCESS) {
2087 		(void) printf("%s\n", propVal);
2088 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2089 		(void) printf("not set\n");
2090 	} else {
2091 		(void) printf("<error retrieving property>\n");
2092 		ret++;
2093 	}
2094 
2095 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_BLOCK_SIZE, propVal,
2096 	    &propValSize);
2097 	(void) printf(PROPS_FORMAT, "Block Size");
2098 	if (stmfRet == STMF_STATUS_SUCCESS) {
2099 		(void) printf("%s\n", propVal);
2100 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2101 		(void) printf("not set\n");
2102 	} else {
2103 		(void) printf("<error retrieving property>\n");
2104 		ret++;
2105 	}
2106 
2107 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_MGMT_URL, propVal,
2108 	    &propValSize);
2109 	(void) printf(PROPS_FORMAT, "Management URL");
2110 	if (stmfRet == STMF_STATUS_SUCCESS) {
2111 		(void) printf("%s\n", propVal);
2112 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2113 		(void) printf("not set\n");
2114 	} else {
2115 		(void) printf("<error retrieving property>\n");
2116 		ret++;
2117 	}
2118 
2119 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_VID, propVal,
2120 	    &propValSize);
2121 	(void) printf(PROPS_FORMAT, "Vendor ID");
2122 	if (stmfRet == STMF_STATUS_SUCCESS) {
2123 		(void) printf("%s\n", propVal);
2124 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2125 		(void) printf("not set\n");
2126 	} else {
2127 		(void) printf("<error retrieving property>\n");
2128 		ret++;
2129 	}
2130 
2131 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_PID, propVal,
2132 	    &propValSize);
2133 	(void) printf(PROPS_FORMAT, "Product ID");
2134 	if (stmfRet == STMF_STATUS_SUCCESS) {
2135 		(void) printf("%s\n", propVal);
2136 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2137 		(void) printf("not set\n");
2138 	} else {
2139 		(void) printf("<error retrieving property>\n");
2140 		ret++;
2141 	}
2142 
2143 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SERIAL_NUM, propVal,
2144 	    &propValSize);
2145 	(void) printf(PROPS_FORMAT, "Serial Num");
2146 	if (stmfRet == STMF_STATUS_SUCCESS) {
2147 		(void) printf("%s\n", propVal);
2148 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2149 		(void) printf("not set\n");
2150 	} else {
2151 		(void) printf("<error retrieving property>\n");
2152 		ret++;
2153 	}
2154 
2155 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_WRITE_PROTECT, propVal,
2156 	    &propValSize);
2157 	(void) printf(PROPS_FORMAT, "Write Protect");
2158 	if (stmfRet == STMF_STATUS_SUCCESS) {
2159 		(void) printf("%s\n",
2160 		    strcasecmp(propVal, "true") ? "Disabled" : "Enabled");
2161 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2162 		(void) printf("not set\n");
2163 	} else {
2164 		(void) printf("<error retrieving property>\n");
2165 		ret++;
2166 	}
2167 
2168 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_WRITE_CACHE_DISABLE, propVal,
2169 	    &propValSize);
2170 	(void) printf(PROPS_FORMAT, "Writeback Cache");
2171 	if (stmfRet == STMF_STATUS_SUCCESS) {
2172 		(void) printf("%s\n",
2173 		    strcasecmp(propVal, "true") ? "Enabled" : "Disabled");
2174 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
2175 		(void) printf("not set\n");
2176 	} else {
2177 		(void) printf("<error retrieving property>\n");
2178 		ret++;
2179 	}
2180 
2181 
2182 	(void) stmfFreeLuResource(hdl);
2183 	return (ret);
2184 
2185 }
2186 
2187 
2188 /*
2189  * printLuProps
2190  *
2191  * Prints the properties for a logical unit
2192  *
2193  */
2194 static void
2195 printLuProps(stmfLogicalUnitProperties *luProps)
2196 {
2197 	(void) printf(PROPS_FORMAT, "Operational Status");
2198 	switch (luProps->status) {
2199 		case STMF_LOGICAL_UNIT_ONLINE:
2200 			(void) printf("Online");
2201 			break;
2202 		case STMF_LOGICAL_UNIT_OFFLINE:
2203 			(void) printf("Offline");
2204 			break;
2205 		case STMF_LOGICAL_UNIT_ONLINING:
2206 			(void) printf("Onlining");
2207 			break;
2208 		case STMF_LOGICAL_UNIT_OFFLINING:
2209 			(void) printf("Offlining");
2210 			break;
2211 		case STMF_LOGICAL_UNIT_UNREGISTERED:
2212 			(void) printf("unregistered");
2213 			(void) strncpy(luProps->providerName, "unregistered",
2214 			    sizeof (luProps->providerName));
2215 			break;
2216 		default:
2217 			(void) printf("unknown");
2218 			break;
2219 	}
2220 	(void) printf("\n");
2221 	(void) printf(PROPS_FORMAT, "Provider Name");
2222 	if (luProps->providerName[0] != 0) {
2223 		(void) printf("%s", luProps->providerName);
2224 	} else {
2225 		(void) printf("unknown");
2226 	}
2227 	(void) printf("\n");
2228 	(void) printf(PROPS_FORMAT, "Alias");
2229 	if (luProps->alias[0] != 0) {
2230 		(void) printf("%s", luProps->alias);
2231 	} else {
2232 		(void) printf("-");
2233 	}
2234 	(void) printf("\n");
2235 }
2236 
2237 /*
2238  * printTargetProps
2239  *
2240  * Prints the properties for a target
2241  *
2242  */
2243 static void
2244 printTargetProps(stmfTargetProperties *targetProps)
2245 {
2246 	(void) printf(PROPS_FORMAT, "Operational Status");
2247 	switch (targetProps->status) {
2248 		case STMF_TARGET_PORT_ONLINE:
2249 			(void) printf("Online");
2250 			break;
2251 		case STMF_TARGET_PORT_OFFLINE:
2252 			(void) printf("Offline");
2253 			break;
2254 		case STMF_TARGET_PORT_ONLINING:
2255 			(void) printf("Onlining");
2256 			break;
2257 		case STMF_TARGET_PORT_OFFLINING:
2258 			(void) printf("Offlining");
2259 			break;
2260 		default:
2261 			(void) printf("unknown");
2262 			break;
2263 	}
2264 	(void) printf("\n");
2265 	(void) printf(PROPS_FORMAT, "Provider Name");
2266 	if (targetProps->providerName[0] != 0) {
2267 		(void) printf("%s", targetProps->providerName);
2268 	}
2269 	(void) printf("\n");
2270 	(void) printf(PROPS_FORMAT, "Alias");
2271 	if (targetProps->alias[0] != 0) {
2272 		(void) printf("%s", targetProps->alias);
2273 	} else {
2274 		(void) printf("-");
2275 	}
2276 	(void) printf("\n");
2277 }
2278 
2279 /*
2280  * printSessionProps
2281  *
2282  * Prints the session data
2283  *
2284  */
2285 static void
2286 printSessionProps(stmfSessionList *sessionList)
2287 {
2288 	int i;
2289 	char *cTime;
2290 	wchar_t initiator[STMF_IDENT_LENGTH + 1];
2291 
2292 	(void) printf(PROPS_FORMAT, "Sessions");
2293 	(void) printf("%d\n", sessionList->cnt);
2294 	for (i = 0; i < sessionList->cnt; i++) {
2295 		(void) mbstowcs(initiator,
2296 		    (char *)sessionList->session[i].initiator.ident,
2297 		    STMF_IDENT_LENGTH);
2298 		initiator[STMF_IDENT_LENGTH] = 0;
2299 		(void) printf(LVL3_FORMAT, "Initiator: ");
2300 		(void) printf("%ws\n", initiator);
2301 		(void) printf(LVL4_FORMAT, "Alias: ");
2302 		if (sessionList->session[i].alias[0] != 0) {
2303 			(void) printf("%s", sessionList->session[i].alias);
2304 		} else {
2305 			(void) printf("-");
2306 		}
2307 		(void) printf("\n");
2308 		(void) printf(LVL4_FORMAT, "Logged in since: ");
2309 		cTime = ctime(&(sessionList->session[i].creationTime));
2310 		if (cTime != NULL) {
2311 			(void) printf("%s", cTime);
2312 		} else {
2313 			(void) printf("unknown\n");
2314 		}
2315 	}
2316 }
2317 
2318 static int
2319 getStmfState(stmfState *state)
2320 {
2321 	int ret;
2322 
2323 	ret = stmfGetState(state);
2324 	switch (ret) {
2325 		case STMF_STATUS_SUCCESS:
2326 			break;
2327 		case STMF_ERROR_PERM:
2328 			(void) fprintf(stderr, "%s: %s\n", cmdName,
2329 			    gettext("permission denied"));
2330 			break;
2331 		case STMF_ERROR_SERVICE_NOT_FOUND:
2332 			(void) fprintf(stderr, "%s: %s\n", cmdName,
2333 			    gettext("STMF service not found"));
2334 			break;
2335 		case STMF_ERROR_BUSY:
2336 			(void) fprintf(stderr, "%s: %s\n", cmdName,
2337 			    gettext("resource busy"));
2338 			break;
2339 		case STMF_ERROR_SERVICE_DATA_VERSION:
2340 			(void) fprintf(stderr, "%s: %s\n", cmdName,
2341 			    gettext("STMF service version incorrect"));
2342 			break;
2343 		default:
2344 			(void) fprintf(stderr, "%s: %s: %d\n", cmdName,
2345 			    gettext("unknown error"), ret);
2346 			break;
2347 	}
2348 	return (ret);
2349 }
2350 
2351 /*
2352  * listStateFunc
2353  *
2354  * List the operational and config state of the stmf service
2355  *
2356  */
2357 /*ARGSUSED*/
2358 static int
2359 listStateFunc(int operandLen, char *operands[], cmdOptions_t *options,
2360     void *args)
2361 {
2362 	int ret;
2363 	stmfState state;
2364 
2365 	if ((ret = getStmfState(&state)) != STMF_STATUS_SUCCESS)
2366 		return (ret);
2367 
2368 	(void) printf("%-18s: ", "Operational Status");
2369 	switch (state.operationalState) {
2370 		case STMF_SERVICE_STATE_ONLINE:
2371 			(void) printf("online");
2372 			break;
2373 		case STMF_SERVICE_STATE_OFFLINE:
2374 			(void) printf("offline");
2375 			break;
2376 		case STMF_SERVICE_STATE_ONLINING:
2377 			(void) printf("onlining");
2378 			break;
2379 		case STMF_SERVICE_STATE_OFFLINING:
2380 			(void) printf("offlining");
2381 			break;
2382 		default:
2383 			(void) printf("unknown");
2384 			break;
2385 	}
2386 	(void) printf("\n");
2387 	(void) printf("%-18s: ", "Config Status");
2388 	switch (state.configState) {
2389 		case STMF_CONFIG_STATE_NONE:
2390 			(void) printf("uninitialized");
2391 			break;
2392 		case STMF_CONFIG_STATE_INIT:
2393 			(void) printf("initializing");
2394 			break;
2395 		case STMF_CONFIG_STATE_INIT_DONE:
2396 			(void) printf("initialized");
2397 			break;
2398 		default:
2399 			(void) printf("unknown");
2400 			break;
2401 	}
2402 	(void) printf("\n");
2403 	return (0);
2404 }
2405 
2406 /*
2407  * listTargetFunc
2408  *
2409  * list the targets and optionally their properties
2410  *
2411  */
2412 /*ARGSUSED*/
2413 static int
2414 listTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
2415     void *args)
2416 {
2417 	cmdOptions_t *optionList = options;
2418 	int ret = 0;
2419 	int stmfRet;
2420 	int i, j;
2421 	int outerLoop;
2422 	stmfSessionList *sessionList;
2423 	stmfDevid devid;
2424 	boolean_t operandEntered, found, verbose = B_FALSE;
2425 	stmfDevidList *targetList;
2426 	wchar_t targetIdent[STMF_IDENT_LENGTH + 1];
2427 	stmfTargetProperties targetProps;
2428 
2429 	if ((stmfRet = stmfGetTargetList(&targetList)) != STMF_STATUS_SUCCESS) {
2430 		switch (stmfRet) {
2431 			case STMF_ERROR_NOT_FOUND:
2432 				ret = 0;
2433 				break;
2434 			case STMF_ERROR_SERVICE_OFFLINE:
2435 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2436 				    gettext("STMF service offline"));
2437 				break;
2438 			case STMF_ERROR_BUSY:
2439 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2440 				    gettext("resource busy"));
2441 				break;
2442 			case STMF_ERROR_SERVICE_DATA_VERSION:
2443 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2444 				    gettext("STMF service version incorrect"));
2445 				break;
2446 			case STMF_ERROR_PERM:
2447 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2448 				    gettext("permission denied"));
2449 				break;
2450 			default:
2451 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2452 				    gettext("unknown error"));
2453 				break;
2454 		}
2455 		return (1);
2456 	}
2457 
2458 	for (; optionList->optval; optionList++) {
2459 		switch (optionList->optval) {
2460 			case 'v':
2461 				verbose = B_TRUE;
2462 				break;
2463 		}
2464 	}
2465 
2466 	if (operandLen > 0) {
2467 		outerLoop = operandLen;
2468 		operandEntered = B_TRUE;
2469 	} else {
2470 		outerLoop = 1;
2471 		operandEntered = B_FALSE;
2472 	}
2473 
2474 	for (i = 0; i < outerLoop; i++) {
2475 		if (operandEntered) {
2476 			bzero(&devid, sizeof (devid));
2477 			(void) parseDevid(operands[i], &devid);
2478 		}
2479 		for (found = B_FALSE, j = 0; j < targetList->cnt; j++) {
2480 			if (operandEntered) {
2481 				if (bcmp(&devid, &(targetList->devid[j]),
2482 				    sizeof (devid)) == 0) {
2483 					found = B_TRUE;
2484 				}
2485 			}
2486 			if ((found && operandEntered) || !operandEntered) {
2487 				(void) mbstowcs(targetIdent,
2488 				    (char *)targetList->devid[j].ident,
2489 				    STMF_IDENT_LENGTH);
2490 				targetIdent[STMF_IDENT_LENGTH] = 0;
2491 				(void) printf("Target: %ws\n", targetIdent);
2492 				if (verbose) {
2493 					stmfRet = stmfGetTargetProperties(
2494 					    &(targetList->devid[j]),
2495 					    &targetProps);
2496 					if (stmfRet == STMF_STATUS_SUCCESS) {
2497 						printTargetProps(&targetProps);
2498 					} else {
2499 						(void) fprintf(stderr, "%s:",
2500 						    cmdName);
2501 						(void) fprintf(stderr, "%s\n",
2502 						    gettext(" get properties"
2503 						    " failed"));
2504 					}
2505 					stmfRet = stmfGetSessionList(
2506 					    &(targetList->devid[j]),
2507 					    &sessionList);
2508 					if (stmfRet == STMF_STATUS_SUCCESS) {
2509 						printSessionProps(sessionList);
2510 					} else {
2511 						(void) fprintf(stderr, "%s:",
2512 						    cmdName);
2513 						(void) fprintf(stderr, "%s\n",
2514 						    gettext(" get session info"
2515 						    " failed"));
2516 					}
2517 				}
2518 				if (found && operandEntered) {
2519 					break;
2520 				}
2521 			}
2522 
2523 		}
2524 		if (operandEntered && !found) {
2525 			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2526 			    operands[i], "not found");
2527 			ret = 1;
2528 		}
2529 	}
2530 	return (ret);
2531 }
2532 
2533 /*
2534  * listViewFunc
2535  *
2536  * list the view entries for the specified logical unit
2537  *
2538  */
2539 /*ARGSUSED*/
2540 static int
2541 listViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
2542     void *args)
2543 {
2544 	stmfViewEntryList *viewEntryList;
2545 	stmfGuid inGuid;
2546 	unsigned int guid[sizeof (stmfGuid)];
2547 	int ret = 0;
2548 	int stmfRet;
2549 	int i, j, outerLoop;
2550 	boolean_t found = B_TRUE;
2551 	boolean_t operandEntered;
2552 	uint16_t outputLuNbr;
2553 	wchar_t groupName[sizeof (stmfGroupName)];
2554 	char sGuid[GUID_INPUT + 1];
2555 
2556 
2557 	for (; options->optval; options++) {
2558 		switch (options->optval) {
2559 			case 'l':
2560 				if (strlen(options->optarg) != GUID_INPUT) {
2561 					(void) fprintf(stderr,
2562 					    "%s: %s: %s%d%s\n",
2563 					    cmdName, options->optarg,
2564 					    gettext("must be "), GUID_INPUT,
2565 					    gettext(" hexadecimal digits"
2566 					    " long"));
2567 					return (1);
2568 				}
2569 				bcopy(options->optarg, sGuid, GUID_INPUT);
2570 				break;
2571 			default:
2572 				(void) fprintf(stderr, "%s: %c: %s\n",
2573 				    cmdName, options->optval,
2574 				    gettext("unknown option"));
2575 				return (1);
2576 		}
2577 	}
2578 
2579 	if (operandLen > 0) {
2580 		outerLoop = operandLen;
2581 		operandEntered = B_TRUE;
2582 	} else {
2583 		outerLoop = 1;
2584 		operandEntered = B_FALSE;
2585 	}
2586 
2587 	for (i = 0; i < 32; i++)
2588 		sGuid[i] = tolower(sGuid[i]);
2589 	sGuid[i] = 0;
2590 
2591 	(void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
2592 	    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
2593 	    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
2594 	    &guid[12], &guid[13], &guid[14], &guid[15]);
2595 
2596 	for (i = 0; i < sizeof (stmfGuid); i++) {
2597 		inGuid.guid[i] = guid[i];
2598 	}
2599 
2600 	if ((stmfRet = stmfGetViewEntryList(&inGuid, &viewEntryList))
2601 	    != STMF_STATUS_SUCCESS) {
2602 
2603 		switch (stmfRet) {
2604 			case STMF_ERROR_BUSY:
2605 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2606 				    sGuid, gettext("resource busy"));
2607 				break;
2608 			case STMF_ERROR_NOT_FOUND:
2609 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2610 				    sGuid, gettext("no views found"));
2611 				break;
2612 			case STMF_ERROR_SERVICE_NOT_FOUND:
2613 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2614 				    gettext("STMF service not found"));
2615 				break;
2616 			case STMF_ERROR_SERVICE_DATA_VERSION:
2617 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2618 				    gettext("STMF service version incorrect"));
2619 				break;
2620 			case STMF_ERROR_PERM:
2621 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2622 				    gettext("permission denied"));
2623 				break;
2624 			default:
2625 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2626 				    sGuid, gettext("unknown error"));
2627 				break;
2628 		}
2629 		return (1);
2630 	}
2631 
2632 	for (i = 0; i < outerLoop; i++) {
2633 		for (found = B_FALSE, j = 0; j < viewEntryList->cnt; j++) {
2634 			if (operandEntered) {
2635 				if (atoi(operands[i]) ==
2636 				    viewEntryList->ve[j].veIndex) {
2637 					found = B_TRUE;
2638 				}
2639 			}
2640 			if ((found && operandEntered) || !operandEntered) {
2641 				(void) printf("View Entry: %d\n",
2642 				    viewEntryList->ve[j].veIndex);
2643 				(void) printf(VIEW_FORMAT, "Host group");
2644 				if (viewEntryList->ve[j].allHosts) {
2645 					(void) printf("All\n");
2646 				} else {
2647 					(void) mbstowcs(groupName,
2648 					    viewEntryList->ve[j].hostGroup,
2649 					    sizeof (stmfGroupName) - 1);
2650 					groupName[sizeof (stmfGroupName) - 1]
2651 					    = 0;
2652 					(void) printf("%ws\n", groupName);
2653 				}
2654 				(void) printf(VIEW_FORMAT, "Target group");
2655 				if (viewEntryList->ve[j].allTargets) {
2656 					(void) printf("All\n");
2657 				} else {
2658 					(void) mbstowcs(groupName,
2659 					    viewEntryList->ve[j].targetGroup,
2660 					    sizeof (stmfGroupName) - 1);
2661 					groupName[sizeof (stmfGroupName) - 1]
2662 					    = 0;
2663 					(void) printf("%ws\n", groupName);
2664 				}
2665 				outputLuNbr = ((viewEntryList->ve[j].luNbr[0] &
2666 				    0x3F) << 8) | viewEntryList->ve[j].luNbr[1];
2667 				(void) printf(VIEW_FORMAT, "LUN");
2668 				(void) printf("%d\n", outputLuNbr);
2669 				if (found && operandEntered) {
2670 					break;
2671 				}
2672 			}
2673 		}
2674 		if (operandEntered && !found) {
2675 			(void) fprintf(stderr, "%s: %s, %s: %s\n", cmdName,
2676 			    sGuid, operands[i], gettext("not found"));
2677 			ret = 1;
2678 		}
2679 	}
2680 
2681 	return (ret);
2682 }
2683 
2684 
2685 /*
2686  * onlineOfflineLu
2687  *
2688  * Purpose: Online or offline a logical unit
2689  *
2690  * lu - logical unit to online or offline
2691  *
2692  * state - ONLINE_LU
2693  *         OFFLINE_LU
2694  */
2695 static int
2696 onlineOfflineLu(char *lu, int state)
2697 {
2698 	char sGuid[GUID_INPUT + 1];
2699 	stmfGuid inGuid;
2700 	unsigned int guid[sizeof (stmfGuid)];
2701 	int i;
2702 	int ret = 0;
2703 
2704 	if (strlen(lu) != GUID_INPUT) {
2705 		(void) fprintf(stderr, "%s: %s: %s %d %s\n", cmdName, lu,
2706 		    gettext("must be"), GUID_INPUT,
2707 		    gettext("hexadecimal digits long"));
2708 		return (1);
2709 	}
2710 
2711 	bcopy(lu, sGuid, GUID_INPUT);
2712 
2713 	for (i = 0; i < 32; i++)
2714 		sGuid[i] = tolower(sGuid[i]);
2715 	sGuid[i] = 0;
2716 
2717 	(void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
2718 	    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
2719 	    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
2720 	    &guid[12], &guid[13], &guid[14], &guid[15]);
2721 
2722 	for (i = 0; i < sizeof (stmfGuid); i++) {
2723 		inGuid.guid[i] = guid[i];
2724 	}
2725 
2726 	if (state == ONLINE_LU) {
2727 		ret = stmfOnlineLogicalUnit(&inGuid);
2728 	} else if (state == OFFLINE_LU) {
2729 		ret = stmfOfflineLogicalUnit(&inGuid);
2730 	}
2731 	if (ret != STMF_STATUS_SUCCESS) {
2732 		switch (ret) {
2733 			case STMF_ERROR_PERM:
2734 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2735 				    gettext("permission denied"));
2736 				break;
2737 			case STMF_ERROR_SERVICE_NOT_FOUND:
2738 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2739 				    gettext("STMF service not found"));
2740 				break;
2741 			case STMF_ERROR_NOT_FOUND:
2742 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2743 				    lu, gettext("not found"));
2744 				break;
2745 			case STMF_ERROR_SERVICE_DATA_VERSION:
2746 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2747 				    gettext("STMF service version incorrect"));
2748 				break;
2749 			default:
2750 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2751 				    gettext("unknown error"));
2752 				break;
2753 		}
2754 	}
2755 	return (ret);
2756 }
2757 
2758 /*
2759  * onlineLuFunc
2760  *
2761  * Purpose: Online a logical unit
2762  *
2763  */
2764 /*ARGSUSED*/
2765 static int
2766 onlineLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
2767     void *args)
2768 {
2769 	int ret;
2770 	stmfState state;
2771 
2772 	ret = getStmfState(&state);
2773 	if (ret != STMF_STATUS_SUCCESS)
2774 		return (ret);
2775 	if (state.operationalState == STMF_SERVICE_STATE_OFFLINE ||
2776 	    state.operationalState == STMF_SERVICE_STATE_OFFLINING) {
2777 		(void) fprintf(stderr, "%s: %s\n", cmdName,
2778 		    gettext("STMF service is offline"));
2779 		return (1);
2780 	}
2781 	return (onlineOfflineLu(operands[0], ONLINE_LU));
2782 }
2783 
2784 /*
2785  * offlineLuFunc
2786  *
2787  * Purpose: Offline a logical unit
2788  *
2789  */
2790 /*ARGSUSED*/
2791 static int
2792 offlineLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
2793     void *args)
2794 {
2795 	return (onlineOfflineLu(operands[0], OFFLINE_LU));
2796 }
2797 
2798 /*
2799  * onlineOfflineTarget
2800  *
2801  * Purpose: Online or offline a target
2802  *
2803  * target - target to online or offline
2804  *
2805  * state - ONLINE_TARGET
2806  *         OFFLINE_TARGET
2807  */
2808 static int
2809 onlineOfflineTarget(char *target, int state)
2810 {
2811 	int ret = 0;
2812 	stmfDevid devid;
2813 
2814 	if (parseDevid(target, &devid) != 0) {
2815 		(void) fprintf(stderr, "%s: %s: %s\n",
2816 		    cmdName, target, gettext("unrecognized device id"));
2817 		return (1);
2818 	}
2819 	if (state == ONLINE_TARGET) {
2820 		ret = stmfOnlineTarget(&devid);
2821 	} else if (state == OFFLINE_TARGET) {
2822 		ret = stmfOfflineTarget(&devid);
2823 	}
2824 	if (ret != STMF_STATUS_SUCCESS) {
2825 		switch (ret) {
2826 			case STMF_ERROR_PERM:
2827 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2828 				    gettext("permission denied"));
2829 				break;
2830 			case STMF_ERROR_SERVICE_NOT_FOUND:
2831 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2832 				    gettext("STMF service not found"));
2833 				break;
2834 			case STMF_ERROR_NOT_FOUND:
2835 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2836 				    target, gettext("not found"));
2837 				break;
2838 			case STMF_ERROR_SERVICE_DATA_VERSION:
2839 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2840 				    gettext("STMF service version incorrect"));
2841 				break;
2842 			default:
2843 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2844 				    gettext("unknown error"));
2845 				break;
2846 		}
2847 	}
2848 	return (ret);
2849 }
2850 
2851 /*
2852  * onlineTargetFunc
2853  *
2854  * Purpose: Online a target
2855  *
2856  */
2857 /*ARGSUSED*/
2858 static int
2859 onlineTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
2860     void *args)
2861 {
2862 	int ret;
2863 	stmfState state;
2864 
2865 	ret = getStmfState(&state);
2866 	if (ret != STMF_STATUS_SUCCESS)
2867 		return (ret);
2868 	if (state.operationalState == STMF_SERVICE_STATE_OFFLINE ||
2869 	    state.operationalState == STMF_SERVICE_STATE_OFFLINING) {
2870 		(void) fprintf(stderr, "%s: %s\n", cmdName,
2871 		    gettext("STMF service is offline"));
2872 		return (1);
2873 	}
2874 	return (onlineOfflineTarget(operands[0], ONLINE_TARGET));
2875 }
2876 
2877 /*
2878  * offlineTargetFunc
2879  *
2880  * Purpose: Offline a target
2881  *
2882  */
2883 /*ARGSUSED*/
2884 static int
2885 offlineTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
2886     void *args)
2887 {
2888 	return (onlineOfflineTarget(operands[0], OFFLINE_TARGET));
2889 }
2890 
2891 
2892 /*ARGSUSED*/
2893 static int
2894 removeHostGroupMemberFunc(int operandLen, char *operands[],
2895     cmdOptions_t *options, void *args)
2896 {
2897 	int i;
2898 	int ret = 0;
2899 	int stmfRet;
2900 	stmfGroupName groupName = {0};
2901 	stmfDevid devid;
2902 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
2903 
2904 	for (; options->optval; options++) {
2905 		switch (options->optval) {
2906 			case 'g':
2907 				(void) mbstowcs(groupNamePrint, options->optarg,
2908 				    sizeof (stmfGroupName) - 1);
2909 				bcopy(options->optarg, groupName,
2910 				    strlen(options->optarg));
2911 				break;
2912 			default:
2913 				(void) fprintf(stderr, "%s: %c: %s\n",
2914 				    cmdName, options->optval,
2915 				    gettext("unknown option"));
2916 				return (1);
2917 		}
2918 	}
2919 
2920 	for (i = 0; i < operandLen; i++) {
2921 		if (parseDevid(operands[i], &devid) != 0) {
2922 			(void) fprintf(stderr, "%s: %s: %s\n",
2923 			    cmdName, operands[i],
2924 			    gettext("unrecognized device id"));
2925 			ret++;
2926 			continue;
2927 		}
2928 		stmfRet = stmfRemoveFromHostGroup(&groupName, &devid);
2929 		switch (stmfRet) {
2930 			case STMF_STATUS_SUCCESS:
2931 				break;
2932 			case STMF_ERROR_MEMBER_NOT_FOUND:
2933 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2934 				    operands[i], gettext("not found"));
2935 				ret++;
2936 				break;
2937 			case STMF_ERROR_GROUP_NOT_FOUND:
2938 				(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
2939 				    groupNamePrint, gettext("not found"));
2940 				ret++;
2941 				break;
2942 			case STMF_ERROR_BUSY:
2943 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2944 				    operands[i], "resource busy");
2945 				ret++;
2946 				break;
2947 			case STMF_ERROR_SERVICE_NOT_FOUND:
2948 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2949 				    gettext("STMF service not found"));
2950 				ret++;
2951 				break;
2952 			case STMF_ERROR_SERVICE_DATA_VERSION:
2953 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2954 				    gettext("STMF service version incorrect"));
2955 				ret++;
2956 				break;
2957 			case STMF_ERROR_PERM:
2958 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2959 				    gettext("permission denied"));
2960 				ret++;
2961 				break;
2962 			default:
2963 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2964 				    operands[i], gettext("unknown error"));
2965 				ret++;
2966 				break;
2967 		}
2968 	}
2969 
2970 	return (ret);
2971 }
2972 
2973 /*
2974  * removeTargetGroupMemberFunc
2975  *
2976  * Removes one or more members from a target group
2977  *
2978  */
2979 /*ARGSUSED*/
2980 static int
2981 removeTargetGroupMemberFunc(int operandLen, char *operands[],
2982     cmdOptions_t *options, void *args)
2983 {
2984 	int i;
2985 	int ret = 0;
2986 	int stmfRet;
2987 	stmfGroupName groupName = {0};
2988 	stmfDevid devid;
2989 	wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
2990 
2991 	for (; options->optval; options++) {
2992 		switch (options->optval) {
2993 			case 'g':
2994 				(void) mbstowcs(groupNamePrint, options->optarg,
2995 				    sizeof (stmfGroupName) - 1);
2996 				bcopy(options->optarg, groupName,
2997 				    strlen(options->optarg));
2998 				break;
2999 			default:
3000 				(void) fprintf(stderr, "%s: %c: %s\n",
3001 				    cmdName, options->optval,
3002 				    gettext("unknown option"));
3003 				return (1);
3004 		}
3005 	}
3006 
3007 	for (i = 0; i < operandLen; i++) {
3008 		if (parseDevid(operands[i], &devid) != 0) {
3009 			(void) fprintf(stderr, "%s: %s: %s\n",
3010 			    cmdName, operands[i],
3011 			    gettext("unrecognized device id"));
3012 			ret++;
3013 			continue;
3014 		}
3015 		stmfRet = stmfRemoveFromTargetGroup(&groupName, &devid);
3016 		switch (stmfRet) {
3017 			case STMF_STATUS_SUCCESS:
3018 				break;
3019 			case STMF_ERROR_MEMBER_NOT_FOUND:
3020 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3021 				    operands[i], gettext("not found"));
3022 				ret++;
3023 				break;
3024 			case STMF_ERROR_GROUP_NOT_FOUND:
3025 				(void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
3026 				    groupNamePrint, gettext("not found"));
3027 				ret++;
3028 				break;
3029 			case STMF_ERROR_BUSY:
3030 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3031 				    operands[i], gettext("resource busy"));
3032 				ret++;
3033 				break;
3034 			case STMF_ERROR_SERVICE_NOT_FOUND:
3035 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3036 				    gettext("STMF service not found"));
3037 				ret++;
3038 				break;
3039 			case STMF_ERROR_PERM:
3040 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3041 				    gettext("permission denied"));
3042 				ret++;
3043 				break;
3044 			case STMF_ERROR_SERVICE_DATA_VERSION:
3045 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3046 				    gettext("STMF service version incorrect"));
3047 				ret++;
3048 				break;
3049 			case STMF_ERROR_TG_ONLINE:
3050 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3051 				    gettext("STMF target must be offline"));
3052 				ret++;
3053 				break;
3054 			default:
3055 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3056 				    operands[i], gettext("unknown error"));
3057 				ret++;
3058 				break;
3059 		}
3060 	}
3061 
3062 	return (ret);
3063 }
3064 
3065 /*
3066  * removeViewFunc
3067  *
3068  * Removes one or more view entries from a logical unit
3069  *
3070  */
3071 /*ARGSUSED*/
3072 static int
3073 removeViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
3074     void *args)
3075 {
3076 	char sGuid[GUID_INPUT + 1];
3077 	stmfViewEntryList *viewEntryList;
3078 	stmfGuid inGuid;
3079 	uint32_t count;
3080 	unsigned int guid[sizeof (stmfGuid)];
3081 	char *endPtr;
3082 	uint32_t veNbr;
3083 	int i;
3084 	boolean_t all = B_FALSE;
3085 	boolean_t luInput = B_FALSE;
3086 	int ret = 0;
3087 	int stmfRet;
3088 
3089 	/* Note: 'l' is required */
3090 	for (; options->optval; options++) {
3091 		switch (options->optval) {
3092 			case 'l':
3093 				if (strlen(options->optarg) != GUID_INPUT) {
3094 					(void) fprintf(stderr,
3095 					    "%s: %s: %s %d %s\n",
3096 					    cmdName, options->optarg,
3097 					    gettext("must be"), GUID_INPUT,
3098 					    gettext("hexadecimal digits long"));
3099 					return (1);
3100 				}
3101 				bcopy(options->optarg, sGuid, GUID_INPUT);
3102 				luInput = B_TRUE;
3103 				break;
3104 			case 'a':
3105 				/* removing all view entries for this GUID */
3106 				all = B_TRUE;
3107 				break;
3108 			default:
3109 				(void) fprintf(stderr, "%s: %c: %s\n",
3110 				    cmdName, options->optval,
3111 				    "unknown option");
3112 				return (1);
3113 		}
3114 	}
3115 
3116 	if (!all && operandLen == 0) {
3117 		(void) fprintf(stderr, "%s: %s\n", cmdName,
3118 		    gettext("no view entries specified"));
3119 		return (1);
3120 	}
3121 
3122 	if (!luInput) {
3123 		(void) fprintf(stderr, "%s: %s\n", cmdName,
3124 		    gettext("logical unit (-l) not specified"));
3125 		return (1);
3126 	}
3127 
3128 	for (i = 0; i < 32; i++)
3129 		sGuid[i] = tolower(sGuid[i]);
3130 	sGuid[i] = 0;
3131 
3132 	(void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
3133 	    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
3134 	    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
3135 	    &guid[12], &guid[13], &guid[14], &guid[15]);
3136 
3137 	for (i = 0; i < sizeof (stmfGuid); i++) {
3138 		inGuid.guid[i] = guid[i];
3139 	}
3140 
3141 	if ((stmfRet = stmfGetViewEntryList(&inGuid, &viewEntryList))
3142 	    != STMF_STATUS_SUCCESS) {
3143 
3144 		switch (stmfRet) {
3145 			case STMF_ERROR_BUSY:
3146 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3147 				    sGuid, gettext("resource busy"));
3148 				break;
3149 			case STMF_ERROR_NOT_FOUND:
3150 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3151 				    sGuid, gettext("no views found"));
3152 				break;
3153 			case STMF_ERROR_SERVICE_NOT_FOUND:
3154 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3155 				    gettext("STMF service not found"));
3156 				break;
3157 			case STMF_ERROR_SERVICE_DATA_VERSION:
3158 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3159 				    gettext("STMF service version incorrect"));
3160 				break;
3161 			case STMF_ERROR_PERM:
3162 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3163 				    gettext("permission denied"));
3164 				break;
3165 			default:
3166 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3167 				    sGuid, gettext("unknown error"));
3168 				break;
3169 		}
3170 		return (1);
3171 	}
3172 
3173 	if (all) {
3174 		count = viewEntryList->cnt;
3175 	} else {
3176 		count = operandLen;
3177 	}
3178 
3179 	for (i = 0; i < count; i++) {
3180 		if (all) {
3181 			veNbr = viewEntryList->ve[i].veIndex;
3182 		} else {
3183 			endPtr = NULL;
3184 			veNbr = strtol(operands[i], &endPtr, 10);
3185 			if (endPtr && *endPtr != 0) {
3186 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3187 				    operands[i], gettext("invalid input"));
3188 				continue;
3189 			}
3190 		}
3191 		stmfRet = stmfRemoveViewEntry(&inGuid, veNbr);
3192 		switch (stmfRet) {
3193 			case STMF_STATUS_SUCCESS:
3194 				break;
3195 			case STMF_ERROR_NOT_FOUND:
3196 				(void) fprintf(stderr, "%s: %s: %d: %s\n",
3197 				    cmdName, sGuid, veNbr,
3198 				    gettext("not found"));
3199 				ret++;
3200 				break;
3201 			case STMF_ERROR_BUSY:
3202 				(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3203 				    sGuid, gettext("resource busy"));
3204 				ret++;
3205 				break;
3206 			case STMF_ERROR_SERVICE_NOT_FOUND:
3207 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3208 				    gettext("STMF service not found"));
3209 				ret++;
3210 				break;
3211 			case STMF_ERROR_CONFIG_NONE:
3212 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3213 				    gettext("STMF service is not initialized"));
3214 				ret++;
3215 				break;
3216 			case STMF_ERROR_SERVICE_DATA_VERSION:
3217 				(void) fprintf(stderr, "%s: %s\n", cmdName,
3218 				    gettext("STMF service version incorrect"));
3219 				ret++;
3220 				break;
3221 			default:
3222 				(void) fprintf(stderr, "%s: %s, %d: %s",
3223 				    cmdName, sGuid, veNbr,
3224 				    gettext("unknown error"));
3225 				ret++;
3226 				break;
3227 		}
3228 	}
3229 
3230 	return (ret);
3231 }
3232 
3233 /*
3234  * input:
3235  *  execFullName - exec name of program (argv[0])
3236  *
3237  *  copied from usr/src/cmd/zoneadm/zoneadm.c in OS/Net
3238  *  (changed name to lowerCamelCase to keep consistent with this file)
3239  *
3240  * Returns:
3241  *  command name portion of execFullName
3242  */
3243 static char *
3244 getExecBasename(char *execFullname)
3245 {
3246 	char *lastSlash, *execBasename;
3247 
3248 	/* guard against '/' at end of command invocation */
3249 	for (;;) {
3250 		lastSlash = strrchr(execFullname, '/');
3251 		if (lastSlash == NULL) {
3252 			execBasename = execFullname;
3253 			break;
3254 		} else {
3255 			execBasename = lastSlash + 1;
3256 			if (*execBasename == '\0') {
3257 				*lastSlash = '\0';
3258 				continue;
3259 			}
3260 			break;
3261 		}
3262 	}
3263 	return (execBasename);
3264 }
3265 
3266 int
3267 main(int argc, char *argv[])
3268 {
3269 	synTables_t synTables;
3270 	char versionString[VERSION_STRING_MAX_LEN];
3271 	int ret;
3272 	int funcRet;
3273 	void *subcommandArgs = NULL;
3274 
3275 	(void) setlocale(LC_ALL, "");
3276 	(void) textdomain(TEXT_DOMAIN);
3277 	/* set global command name */
3278 	cmdName = getExecBasename(argv[0]);
3279 
3280 	(void) snprintf(versionString, VERSION_STRING_MAX_LEN, "%s.%s",
3281 	    VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
3282 	synTables.versionString = versionString;
3283 	synTables.longOptionTbl = &longOptions[0];
3284 	synTables.subCommandPropsTbl = &subcommands[0];
3285 
3286 	ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet);
3287 	if (ret != 0) {
3288 		return (ret);
3289 	}
3290 
3291 	return (funcRet);
3292 } /* end main */
3293