xref: /illumos-gate/usr/src/cmd/ndmpadm/ndmpadm_main.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * BSD 3 Clause License
8  *
9  * Copyright (c) 2007, The Storage Networking Industry Association.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 	- Redistributions of source code must retain the above copyright
15  *	  notice, this list of conditions and the following disclaimer.
16  *
17  * 	- Redistributions in binary form must reproduce the above copyright
18  *	  notice, this list of conditions and the following disclaimer in
19  *	  the documentation and/or other materials provided with the
20  *	  distribution.
21  *
22  *	- Neither the name of The Storage Networking Industry Association (SNIA)
23  *	  nor the names of its contributors may be used to endorse or promote
24  *	  products derived from this software without specific prior written
25  *	  permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 #include <assert.h>
40 #include <ctype.h>
41 #include <libgen.h>
42 #include <libintl.h>
43 #include <locale.h>
44 #include <stddef.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <strings.h>
48 #include <unistd.h>
49 #include <fcntl.h>
50 #include <sys/stat.h>
51 #include <door.h>
52 #include <sys/mman.h>
53 #include <libndmp.h>
54 #include "ndmpadm.h"
55 
56 typedef enum {
57 	HELP_GET_CONFIG,
58 	HELP_SET_CONFIG,
59 	HELP_SHOW_DEVICES,
60 	HELP_SHOW_SESSIONS,
61 	HELP_KILL_SESSIONS,
62 	HELP_ENABLE_AUTH,
63 	HELP_DISABLE_AUTH
64 } ndmp_help_t;
65 
66 typedef struct ndmp_command {
67 	const char	*nc_name;
68 	int		(*func)(int argc, char **argv,
69 			    struct ndmp_command *cur_cmd);
70 	ndmp_help_t	nc_usage;
71 } ndmp_command_t;
72 
73 static int ndmp_get_config(int, char **, ndmp_command_t *);
74 static int ndmp_set_config(int, char **, ndmp_command_t *);
75 static int ndmp_show_devices(int, char **, ndmp_command_t *);
76 static int ndmp_show_sessions(int, char **, ndmp_command_t *);
77 static int ndmp_kill_sessions(int, char **, ndmp_command_t *);
78 static int ndmp_enable_auth(int, char **, ndmp_command_t *);
79 static int ndmp_disable_auth(int, char **, ndmp_command_t *);
80 static void ndmp_get_config_process(char *);
81 static void ndmp_set_config_process(char *arg);
82 static int ndmp_get_password(char **);
83 
84 static ndmp_command_t command_table[] = {
85 	{ "get",		ndmp_get_config,	HELP_GET_CONFIG	},
86 	{ "set",		ndmp_set_config,	HELP_SET_CONFIG	},
87 	{ "show-devices",	ndmp_show_devices,	HELP_SHOW_DEVICES },
88 	{ "show-sessions",	ndmp_show_sessions,	HELP_SHOW_SESSIONS },
89 	{ "kill-sessions",	ndmp_kill_sessions,	HELP_KILL_SESSIONS },
90 	{ "enable",		ndmp_enable_auth,	HELP_ENABLE_AUTH },
91 	{ "disable",		ndmp_disable_auth,	HELP_DISABLE_AUTH }
92 };
93 
94 #define	NCOMMAND	(sizeof (command_table) / sizeof (command_table[0]))
95 
96 static char *prop_table[] = {
97 	"debug-path",
98 	"dump-pathnode",
99 	"tar-pathnode",
100 	"ignore-ctime",
101 	"token-maxseq",
102 	"version",
103 	"dar-support",
104 	"tcp-port",
105 	"backup-quarantine",
106 	"restore-quarantine",
107 	"overwrite-quarantine"
108 };
109 
110 #define	NDMPADM_NPROP	(sizeof (prop_table) / sizeof (prop_table[0]))
111 
112 typedef struct ndmp_auth {
113 	const char *auth_type;
114 	const char *username;
115 	const char *password;
116 } ndmp_auth_t;
117 
118 static ndmp_auth_t ndmp_auth_table[] = {
119 	{ "cram-md5", "cram-md5-username", "cram-md5-password" },
120 	{ "cleartext", "cleartext-username", "cleartext-password" }
121 };
122 #define	NAUTH	(sizeof (ndmp_auth_table) / sizeof (ndmp_auth_table[0]))
123 #define	NDMP_PASSWORD_RETRIES	3
124 
125 #if !defined(TEXT_DOMAIN)
126 #define	TEXT_DOMAIN	"SYS_TEST"
127 #endif
128 
129 static const char *
130 get_usage(ndmp_help_t idx)
131 {
132 	switch (idx) {
133 	case HELP_SET_CONFIG:
134 		return ("\tset [-p] <property=value> [[-p] property=value] "
135 		    "...\n");
136 	case HELP_GET_CONFIG:
137 		return ("\tget [-p] [property] [[-p] property] ...\n");
138 	case HELP_SHOW_DEVICES:
139 		return ("\tshow-devices\n");
140 	case HELP_SHOW_SESSIONS:
141 		return ("\tshow-sessions [-i tape,scsi,data,mover] [id] ...\n");
142 	case HELP_KILL_SESSIONS:
143 		return ("\tkill-sessions <id ...>\n");
144 	case HELP_ENABLE_AUTH:
145 		return ("\tenable <-a auth-type> <-u username>\n");
146 	case HELP_DISABLE_AUTH:
147 		return ("\tdisable <-a auth-type>\n");
148 	}
149 
150 	return (NULL);
151 }
152 
153 /*
154  * Display usage message.  If we're inside a command, display only the usage for
155  * that command.  Otherwise, iterate over the entire command table and display
156  * a complete usage message.
157  */
158 static void
159 usage(boolean_t requested, ndmp_command_t *current_command)
160 {
161 	int i;
162 	boolean_t show_properties = B_FALSE;
163 	FILE *fp = requested ? stdout : stderr;
164 
165 	if (current_command == NULL) {
166 		(void) fprintf(fp,
167 		    gettext("Usage: ndmpadm subcommand args ...\n"));
168 		(void) fprintf(fp,
169 		    gettext("where 'command' is one of the following:\n\n"));
170 
171 		for (i = 0; i < NCOMMAND; i++) {
172 			(void) fprintf(fp, "%s",
173 			    get_usage(command_table[i].nc_usage));
174 		}
175 		(void) fprintf(fp, gettext("\t\twhere %s can be either "
176 		    "%s or %s\n"), "'auth-type'", "'cram-md5'", "'cleartext'");
177 	} else {
178 		(void) fprintf(fp, gettext("Usage:\n"));
179 		(void) fprintf(fp, "%s", get_usage(current_command->nc_usage));
180 		if ((current_command->nc_usage == HELP_ENABLE_AUTH) ||
181 		    (current_command->nc_usage == HELP_DISABLE_AUTH))
182 			(void) fprintf(fp, gettext("\t\twhere %s can be either "
183 			    "%s or %s\n"),
184 			    "'auth-type'", "'cram-md5'", "'cleartext'");
185 	}
186 
187 	if (current_command != NULL &&
188 	    (strcmp(current_command->nc_name, "set") == 0))
189 		show_properties = B_TRUE;
190 
191 	if (show_properties) {
192 		(void) fprintf(fp,
193 		    gettext("\nThe following properties are supported:\n"));
194 
195 		(void) fprintf(fp, gettext("\n\tPROPERTY"));
196 		(void) fprintf(fp, "\n\t%s", "-------------");
197 		for (i = 0; i < NDMPADM_NPROP; i++)
198 			(void) fprintf(fp, "\n\t%s", prop_table[i]);
199 		(void) fprintf(fp, "\n");
200 	}
201 
202 	exit(requested ? 0 : 2);
203 }
204 
205 /*ARGSUSED*/
206 static int
207 ndmp_get_config(int argc, char **argv, ndmp_command_t *cur_cmd)
208 {
209 	char *propval;
210 	int i, c;
211 
212 	if (argc == 1) {
213 		/*
214 		 * Get all the properties and variables ndmpadm is allowed
215 		 * to see.
216 		 */
217 		for (i = 0; i < NDMPADM_NPROP; i++) {
218 			if (ndmp_get_prop(prop_table[i], &propval)) {
219 				(void) fprintf(stdout, "\t%s=\n",
220 				    prop_table[i]);
221 			} else {
222 				(void) fprintf(stdout, "\t%s=%s\n",
223 				    prop_table[i], propval);
224 				free(propval);
225 			}
226 		}
227 	} else if (argc > 1) {
228 		while ((c = getopt(argc, argv, ":p:")) != -1) {
229 			switch (c) {
230 			case 'p':
231 				ndmp_get_config_process(optarg);
232 				break;
233 			case ':':
234 				(void) fprintf(stderr, gettext("Option -%c "
235 				    "requires an operand\n"), optopt);
236 				break;
237 			case '?':
238 				(void) fprintf(stderr, gettext("Unrecognized "
239 				    "option: -%c\n"), optopt);
240 			}
241 		}
242 		/*
243 		 * optind is initialized to 1 if the -p option is not used,
244 		 * otherwise index to argv.
245 		 */
246 		argc -= optind;
247 		argv += optind;
248 
249 		for (i = 0; i < argc; i++) {
250 			if (strncmp(argv[i], "-p", 2) == 0)
251 				continue;
252 
253 			ndmp_get_config_process(argv[i]);
254 		}
255 	}
256 	return (0);
257 }
258 
259 static void
260 ndmp_get_config_process(char *arg)
261 {
262 	int j;
263 	char *propval;
264 
265 	for (j = 0; j < NDMPADM_NPROP; j++) {
266 		if (strcmp(arg, prop_table[j]) == 0) {
267 			if (ndmp_get_prop(arg, &propval)) {
268 				(void) fprintf(stdout, "\t%s=\n", arg);
269 			} else {
270 				(void) fprintf(stdout, "\t%s=%s\n",
271 				    arg, propval);
272 				free(propval);
273 			}
274 			break;
275 		}
276 	}
277 	if (j == NDMPADM_NPROP) {
278 		(void) fprintf(stdout, gettext("\t%s is invalid property "
279 		    "or variable\n"), arg);
280 	}
281 }
282 
283 /*ARGSUSED*/
284 static int
285 ndmp_set_config(int argc, char **argv, ndmp_command_t *cur_cmd)
286 {
287 	int c, i;
288 
289 	if (argc < 2) {
290 		(void) fprintf(stderr, gettext("Missing property=value "
291 		    "argument\n"));
292 		usage(B_FALSE, cur_cmd);
293 	}
294 	while ((c = getopt(argc, argv, ":p:")) != -1) {
295 		switch (c) {
296 		case 'p':
297 			ndmp_set_config_process(optarg);
298 			break;
299 		case ':':
300 			(void) fprintf(stderr, gettext("Option -%c "
301 			    "requires an operand\n"), optopt);
302 			break;
303 		case '?':
304 			(void) fprintf(stderr, gettext("Unrecognized "
305 			    "option: -%c\n"), optopt);
306 		}
307 	}
308 	/*
309 	 * optind is initialized to 1 if the -p option is not used,
310 	 * otherwise index to argv.
311 	 */
312 	argc -= optind;
313 	argv += optind;
314 
315 	for (i = 0; i < argc; i++) {
316 		if (strncmp(argv[i], "-p", 2) == 0)
317 			continue;
318 
319 		ndmp_set_config_process(argv[i]);
320 	}
321 	return (0);
322 }
323 
324 static void
325 ndmp_set_config_process(char *propname)
326 {
327 	char *propvalue;
328 	int ret, j;
329 
330 	if ((propvalue = strchr(propname, '=')) == NULL) {
331 		(void) fprintf(stderr, gettext("Missing value in "
332 		    "property=value argument for %s\n"), propname);
333 			return;
334 	}
335 	*propvalue = '\0';
336 	propvalue++;
337 
338 	if (*propname == '\0') {
339 		(void) fprintf(stderr, gettext("Missing property in "
340 		    "property=value argument for %s\n"), propname);
341 			return;
342 	}
343 	for (j = 0; j < NDMPADM_NPROP; j++) {
344 		if (strcmp(propname, prop_table[j]) == 0)
345 			break;
346 	}
347 	if (j == NDMPADM_NPROP) {
348 		(void) fprintf(stdout, gettext("%s is invalid property or "
349 		    "variable\n"), propname);
350 		return;
351 	}
352 	ret = ndmp_set_prop(propname, propvalue);
353 	if (ret != -1) {
354 		if (!ndmp_door_status()) {
355 			if (ndmp_service_refresh() == -1)
356 				(void) fprintf(stdout, gettext("Could not "
357 				    "refesh property of service ndmpd\n"));
358 		}
359 	} else {
360 		(void) fprintf(stdout, gettext("Could not set property for "
361 		    "%s - %s\n"), propname, ndmp_strerror(ndmp_errno));
362 	}
363 }
364 
365 /*ARGSUSED*/
366 static int
367 ndmp_show_devices(int argc, char **argv, ndmp_command_t *cur_cmd)
368 {
369 	int ret;
370 	ndmp_devinfo_t *dip = NULL;
371 	size_t size;
372 
373 	if (ndmp_door_status()) {
374 		(void) fprintf(stdout,
375 		    gettext("Service ndmpd not running\n"));
376 		return (-1);
377 	}
378 
379 	ret = ndmp_get_devinfo(&dip, &size);
380 
381 	if (ret == -1)
382 		(void) fprintf(stdout,
383 		    gettext("Could not get device information\n"));
384 	else
385 		ndmp_devinfo_print(dip, size);
386 
387 	ndmp_get_devinfo_free(dip, size);
388 	return (0);
389 }
390 
391 static int
392 ndmp_show_sessions(int argc, char **argv, ndmp_command_t *cur_cmd)
393 {
394 	ndmp_session_info_t *sinfo = NULL;
395 	ndmp_session_info_t *sp = NULL;
396 	uint_t num;
397 	int c, ret, i, j;
398 	int statarg = 0;
399 	char *value;
400 	char *type_subopts[] = { "tape", "scsi", "data", "mover", NULL };
401 
402 	if (ndmp_door_status()) {
403 		(void) fprintf(stdout,
404 		    gettext("Service ndmpd not running\n"));
405 		return (-1);
406 	}
407 
408 	/* Detail output if no option is specified */
409 	if (argc == 1) {
410 		statarg = NDMP_CAT_ALL;
411 	} else {
412 		statarg = 0;
413 		while ((c = getopt(argc, argv, ":i:")) != -1) {
414 			switch (c) {
415 			case 'i':
416 				while (*optarg != '\0') {
417 					switch (getsubopt(&optarg, type_subopts,
418 					    &value)) {
419 					case 0:
420 						statarg |= NDMP_CAT_TAPE;
421 						break;
422 					case 1:
423 						statarg |= NDMP_CAT_SCSI;
424 						break;
425 					case 2:
426 						statarg |= NDMP_CAT_DATA;
427 						break;
428 					case 3:
429 						statarg |= NDMP_CAT_MOVER;
430 						break;
431 					default:
432 						(void) fprintf(stderr,
433 						    gettext("Invalid object "
434 						    "type '%s'\n"), value);
435 						usage(B_FALSE, cur_cmd);
436 					}
437 				}
438 				break;
439 			case ':':
440 				(void) fprintf(stderr,
441 				    gettext("Missing argument for "
442 				    "'%c' option\n"), optopt);
443 				usage(B_FALSE, cur_cmd);
444 				break;
445 			case '?':
446 				(void) fprintf(stderr,
447 				    gettext("Invalid option '%c'\n"), optopt);
448 				usage(B_FALSE, cur_cmd);
449 			}
450 		}
451 		/* if -i and its argument are not specified, display all */
452 		if (statarg == 0)
453 			statarg = NDMP_CAT_ALL;
454 	}
455 	/*
456 	 * optind is initialized to 1 if the -i option is not used, otherwise
457 	 * index to argv.
458 	 */
459 	argc -= optind;
460 	argv += optind;
461 
462 	ret = ndmp_get_session_info(&sinfo, &num);
463 	if (ret == -1) {
464 		(void) fprintf(stdout,
465 		    gettext("Could not get session information\n"));
466 	} else {
467 		if (argc == 0) {
468 			ndmp_session_all_print(statarg, sinfo, num);
469 		} else {
470 			for (i = 0; i < argc; i++) {
471 				sp = sinfo;
472 				for (j = 0; j < num; j++, sp++) {
473 					if (sp->nsi_sid == atoi(argv[i])) {
474 						ndmp_session_print(statarg, sp);
475 						(void) fprintf(stdout, "\n");
476 						break;
477 					}
478 				}
479 				if (j == num) {
480 					(void) fprintf(stdout,
481 					    gettext("Session %d not "
482 					    "found\n"), atoi(argv[i]));
483 				}
484 			}
485 		}
486 		ndmp_get_session_info_free(sinfo, num);
487 	}
488 	return (0);
489 }
490 
491 /*ARGSUSED*/
492 static int
493 ndmp_kill_sessions(int argc, char **argv, ndmp_command_t *cur_cmd)
494 {
495 	int ret, i;
496 
497 	if (ndmp_door_status()) {
498 		(void) fprintf(stdout,
499 		    gettext("Service ndmpd not running.\n"));
500 		return (-1);
501 	}
502 
503 	/* If no arg is specified, print the usage and exit */
504 	if (argc == 1)
505 		usage(B_FALSE, cur_cmd);
506 
507 	for (i = 1; i < argc; i++) {
508 		if (atoi(argv[i]) > 0) {
509 			ret = ndmp_terminate_session(atoi(argv[i]));
510 		} else {
511 			(void) fprintf(stderr,
512 			    gettext("Invalid argument %s\n"), argv[i]);
513 				continue;
514 		}
515 		if (ret == -1)
516 			(void) fprintf(stdout,
517 			    gettext("Session id %d not found.\n"),
518 			    atoi(argv[i]));
519 	}
520 	return (0);
521 }
522 
523 static int
524 ndmp_get_password(char **password)
525 {
526 	char *pw1, pw2[257];
527 	int i;
528 
529 	for (i = 0; i < NDMP_PASSWORD_RETRIES; i++) {
530 		/*
531 		 * getpassphrase use the same buffer to return password, so
532 		 * copy the result in different buffer, before calling the
533 		 * getpassphrase again.
534 		 */
535 		if ((pw1 =
536 		    getpassphrase(gettext("Enter new password: "))) != NULL) {
537 			(void) strlcpy(pw2, pw1, sizeof (pw2));
538 			if ((pw1 =
539 			    getpassphrase(gettext("Re-enter  password: ")))
540 			    != NULL) {
541 				if (strncmp(pw1, pw2, strlen(pw1)) == 0) {
542 					*password = pw1;
543 					return (0);
544 				} else {
545 					(void) fprintf(stderr,
546 					    gettext("Both password did not "
547 					    "match.\n"));
548 				}
549 			}
550 		}
551 	}
552 	return (-1);
553 }
554 
555 static int
556 ndmp_enable_auth(int argc, char **argv, ndmp_command_t *cur_cmd)
557 {
558 	char *auth_type, *username, *password;
559 	int c, i, auth_type_flag = 0;
560 	char *enc_password;
561 
562 	/* enable <-a auth-type> <-u username> */
563 	if (argc != 5) {
564 		usage(B_FALSE, cur_cmd);
565 	}
566 
567 	while ((c = getopt(argc, argv, ":a:u:")) != -1) {
568 		switch (c) {
569 		case 'a':
570 			auth_type = strdup(optarg);
571 			break;
572 		case 'u':
573 			username = strdup(optarg);
574 			break;
575 		case ':':
576 			(void) fprintf(stderr, gettext("Option -%c "
577 			    "requires an operand\n"), optopt);
578 			usage(B_FALSE, cur_cmd);
579 			break;
580 		case '?':
581 			(void) fprintf(stderr, gettext("Unrecognized "
582 			    "option: -%c\n"), optopt);
583 			usage(B_FALSE, cur_cmd);
584 		}
585 	}
586 
587 	if ((auth_type) && (username)) {
588 		if (ndmp_get_password(&password)) {
589 			(void) fprintf(stderr, gettext("Could not get correct "
590 			    "password, exiting..."));
591 			free(auth_type);
592 			free(username);
593 			exit(-1);
594 		}
595 	} else {
596 		(void) fprintf(stderr, gettext("%s or %s can not be blank"),
597 		    "'auth-type'", "'username'");
598 		free(auth_type);
599 		free(username);
600 		exit(-1);
601 	}
602 
603 	if ((enc_password = ndmp_base64_encode(password)) == NULL) {
604 		(void) fprintf(stdout,
605 		    gettext("Could not encode password - %s\n"),
606 		    ndmp_strerror(ndmp_errno));
607 		free(auth_type);
608 		free(username);
609 		exit(-1);
610 	}
611 
612 	for (i = 0; i < NAUTH; i++) {
613 		if (strncmp(auth_type, ndmp_auth_table[i].auth_type,
614 		    strlen(ndmp_auth_table[i].auth_type)) == 0) {
615 			auth_type_flag = 1;
616 			if ((ndmp_set_prop((char *)ndmp_auth_table[i].username,
617 			    username)) == -1) {
618 				(void) fprintf(stdout,
619 				    gettext("Could not set username - %s\n"),
620 				    ndmp_strerror(ndmp_errno));
621 				continue;
622 			}
623 			if ((ndmp_set_prop((char *)ndmp_auth_table[i].password,
624 			    enc_password)) == -1) {
625 				(void) fprintf(stdout,
626 				    gettext("Could not set password - %s\n"),
627 				    ndmp_strerror(ndmp_errno));
628 				continue;
629 			}
630 			if (!ndmp_door_status() &&
631 			    (ndmp_service_refresh()) == -1) {
632 				(void) fprintf(stdout,
633 				    gettext("Could not refesh ndmpd service "
634 				    "properties\n"));
635 			}
636 		}
637 	}
638 	free(auth_type);
639 	free(username);
640 	free(enc_password);
641 
642 	if (!auth_type_flag)
643 		usage(B_FALSE, cur_cmd);
644 
645 	return (0);
646 }
647 
648 static int
649 ndmp_disable_auth(int argc, char **argv, ndmp_command_t *cur_cmd)
650 {
651 	char *auth_type;
652 	int c, i, auth_type_flag = 0;
653 
654 	/* disable <-a auth-type> */
655 	if (argc != 3) {
656 		usage(B_FALSE, cur_cmd);
657 	}
658 
659 	while ((c = getopt(argc, argv, ":a:")) != -1) {
660 		switch (c) {
661 		case 'a':
662 			auth_type = strdup(optarg);
663 			break;
664 		case ':':
665 			(void) fprintf(stderr, gettext("Option -%c "
666 			    "requires an operand\n"), optopt);
667 			break;
668 		case '?':
669 			(void) fprintf(stderr, gettext("Unrecognized "
670 			    "option: -%c\n"), optopt);
671 		}
672 	}
673 	for (i = 0; i < NAUTH; i++) {
674 		if (strncmp(auth_type, ndmp_auth_table[i].auth_type,
675 		    strlen(ndmp_auth_table[i].auth_type)) == 0) {
676 			auth_type_flag = 1;
677 			if ((ndmp_set_prop((char *)ndmp_auth_table[i].username,
678 			    "")) == -1) {
679 				(void) fprintf(stdout,
680 				    gettext("Could not clear username - %s\n"),
681 				    ndmp_strerror(ndmp_errno));
682 				continue;
683 			}
684 			if ((ndmp_set_prop((char *)ndmp_auth_table[i].password,
685 			    "")) == -1) {
686 				(void) fprintf(stdout,
687 				    gettext("Could not clear password - %s\n"),
688 				    ndmp_strerror(ndmp_errno));
689 				continue;
690 			}
691 			if (!ndmp_door_status() &&
692 			    (ndmp_service_refresh()) == -1) {
693 				(void) fprintf(stdout, gettext("Could not "
694 				    "refesh ndmpd service properties\n"));
695 			}
696 		}
697 	}
698 	free(auth_type);
699 
700 	if (!auth_type_flag)
701 		usage(B_FALSE, cur_cmd);
702 
703 	return (0);
704 }
705 
706 int
707 main(int argc, char **argv)
708 {
709 	int ret;
710 	int i;
711 	char *cmdname;
712 	ndmp_command_t	*current_command = NULL;
713 
714 	(void) setlocale(LC_ALL, "");
715 	(void) textdomain(TEXT_DOMAIN);
716 
717 	opterr = 0;
718 
719 	/* Make sure the user has specified some command. */
720 	if (argc < 2) {
721 		(void) fprintf(stderr, gettext("Missing command.\n"));
722 		usage(B_FALSE, current_command);
723 	}
724 
725 	cmdname = argv[1];
726 
727 	/*
728 	 * Special case '-?'
729 	 */
730 	if (strcmp(cmdname, "-?") == 0)
731 		usage(B_TRUE, current_command);
732 
733 	/*
734 	 * Run the appropriate sub-command.
735 	 */
736 	for (i = 0; i < NCOMMAND; i++) {
737 		if (strcmp(cmdname, command_table[i].nc_name) == 0) {
738 			current_command = &command_table[i];
739 			ret = command_table[i].func(argc - 1, argv + 1,
740 			    current_command);
741 			break;
742 		}
743 	}
744 
745 	if (i == NCOMMAND) {
746 		(void) fprintf(stderr, gettext("Unrecognized "
747 		    "command '%s'\n"), cmdname);
748 		usage(B_FALSE, current_command);
749 	}
750 
751 	return (ret);
752 }
753