xref: /titanic_50/usr/src/cmd/dfs.cmds/sharectl/sharectl.c (revision 25a68471b9ababbc21cfdbbb2866014f34f419ec)
16185db85Sdougm /*
26185db85Sdougm  * CDDL HEADER START
36185db85Sdougm  *
46185db85Sdougm  * The contents of this file are subject to the terms of the
56185db85Sdougm  * Common Development and Distribution License (the "License").
66185db85Sdougm  * You may not use this file except in compliance with the License.
76185db85Sdougm  *
86185db85Sdougm  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96185db85Sdougm  * or http://www.opensolaris.org/os/licensing.
106185db85Sdougm  * See the License for the specific language governing permissions
116185db85Sdougm  * and limitations under the License.
126185db85Sdougm  *
136185db85Sdougm  * When distributing Covered Code, include this CDDL HEADER in each
146185db85Sdougm  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156185db85Sdougm  * If applicable, add the following below this CDDL HEADER, with the
166185db85Sdougm  * fields enclosed by brackets "[]" replaced with your own identifying
176185db85Sdougm  * information: Portions Copyright [yyyy] [name of copyright owner]
186185db85Sdougm  *
196185db85Sdougm  * CDDL HEADER END
206185db85Sdougm  */
216185db85Sdougm 
226185db85Sdougm /*
233472f5dcSdougm  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
246185db85Sdougm  * Use is subject to license terms.
256185db85Sdougm  */
266185db85Sdougm 
276185db85Sdougm #pragma ident	"%Z%%M%	%I%	%E% SMI"
286185db85Sdougm 
296185db85Sdougm #include <stdlib.h>
306185db85Sdougm #include <stdio.h>
316185db85Sdougm #include <string.h>
326185db85Sdougm #include <ctype.h>
336185db85Sdougm #include <unistd.h>
346185db85Sdougm #include <getopt.h>
356185db85Sdougm #include <libgen.h>
366185db85Sdougm 
376185db85Sdougm #include "libshare.h"
386185db85Sdougm #include <sharemgr.h>
396185db85Sdougm 
406185db85Sdougm #include <libintl.h>
416185db85Sdougm #include <locale.h>
426185db85Sdougm 
43549ec3ffSdougm static int run_command(char *, int, char **, sa_handle_t);
446185db85Sdougm static void sub_command_help(char *proto);
456185db85Sdougm 
466185db85Sdougm static void
476185db85Sdougm global_help()
486185db85Sdougm {
496185db85Sdougm 	(void) printf(gettext("usage: sharectl <command> [options]\n"));
506185db85Sdougm 	sub_command_help(NULL);
516185db85Sdougm }
526185db85Sdougm 
536185db85Sdougm int
546185db85Sdougm main(int argc, char *argv[])
556185db85Sdougm {
566185db85Sdougm 	int c;
576185db85Sdougm 	int help = 0;
586185db85Sdougm 	int rval;
596185db85Sdougm 	char *command;
60549ec3ffSdougm 	sa_handle_t handle;
616185db85Sdougm 
626185db85Sdougm 	/*
636185db85Sdougm 	 * make sure locale and gettext domain is setup
646185db85Sdougm 	 */
656185db85Sdougm 	(void) setlocale(LC_ALL, "");
666185db85Sdougm 	(void) textdomain(TEXT_DOMAIN);
676185db85Sdougm 
68549ec3ffSdougm 	handle = sa_init(SA_INIT_CONTROL_API);
696185db85Sdougm 
706185db85Sdougm 	while ((c = getopt(argc, argv, "h?")) != EOF) {
716185db85Sdougm 		switch (c) {
726185db85Sdougm 		case '?':
736185db85Sdougm 		case 'h':
746185db85Sdougm 			help = 1;
756185db85Sdougm 			break;
766185db85Sdougm 		default:
776185db85Sdougm 			(void) printf(gettext("Invalid option: %c\n"), c);
786185db85Sdougm 		}
796185db85Sdougm 	}
806185db85Sdougm 	if (optind == argc || help) {
816185db85Sdougm 		/* no subcommand */
826185db85Sdougm 		global_help();
836185db85Sdougm 		exit(0);
846185db85Sdougm 	}
856185db85Sdougm 	optind = 1;
866185db85Sdougm 
876185db85Sdougm 	/*
886185db85Sdougm 	 * now have enough to parse rest of command line
896185db85Sdougm 	 */
906185db85Sdougm 	command = argv[optind];
91549ec3ffSdougm 	rval = run_command(command, argc - optind, argv + optind, handle);
926185db85Sdougm 
93549ec3ffSdougm 	sa_fini(handle);
946185db85Sdougm 	return (rval);
956185db85Sdougm }
966185db85Sdougm 
976185db85Sdougm char *
986185db85Sdougm sc_get_usage(sc_usage_t index)
996185db85Sdougm {
1006185db85Sdougm 	char *ret = NULL;
1016185db85Sdougm 
1026185db85Sdougm 	switch (index) {
1036185db85Sdougm 	case USAGE_CTL_GET:
1043472f5dcSdougm 		ret = gettext("get [-h | -p property ...] proto");
1056185db85Sdougm 		break;
1066185db85Sdougm 	case USAGE_CTL_SET:
1076185db85Sdougm 		ret = gettext("set [-h] -p property=value ... proto");
1086185db85Sdougm 		break;
1096185db85Sdougm 	case USAGE_CTL_STATUS:
1103472f5dcSdougm 		ret = gettext("status [-h | proto ...]");
1116185db85Sdougm 		break;
1126185db85Sdougm 	}
1136185db85Sdougm 	return (ret);
1146185db85Sdougm }
1156185db85Sdougm 
116549ec3ffSdougm /*ARGSUSED*/
1176185db85Sdougm static int
118549ec3ffSdougm sc_get(sa_handle_t handle, int flags, int argc, char *argv[])
1196185db85Sdougm {
1206185db85Sdougm 	char *proto = NULL;
1216185db85Sdougm 	struct options *optlist = NULL;
1226185db85Sdougm 	int ret = SA_OK;
1236185db85Sdougm 	int c;
1246185db85Sdougm 
1256185db85Sdougm 	while ((c = getopt(argc, argv, "?hp:")) != EOF) {
1266185db85Sdougm 		switch (c) {
1276185db85Sdougm 		case 'p':
1286185db85Sdougm 			ret = add_opt(&optlist, optarg, 1);
1296185db85Sdougm 			if (ret != SA_OK) {
130*25a68471Sdougm 				(void) printf(gettext(
131*25a68471Sdougm 				    "Problem with property: %s\n"), optarg);
1326185db85Sdougm 				return (SA_NO_MEMORY);
1336185db85Sdougm 			}
1346185db85Sdougm 			break;
1356185db85Sdougm 		default:
1366185db85Sdougm 			(void) printf(gettext("usage: %s\n"),
1376185db85Sdougm 			    sc_get_usage(USAGE_CTL_GET));
1386185db85Sdougm 			return (SA_SYNTAX_ERR);
1396185db85Sdougm 		case '?':
1406185db85Sdougm 		case 'h':
1416185db85Sdougm 			(void) printf(gettext("usage: %s\n"),
1426185db85Sdougm 			    sc_get_usage(USAGE_CTL_GET));
1436185db85Sdougm 			return (SA_OK);
1446185db85Sdougm 			break;
1456185db85Sdougm 		}
1466185db85Sdougm 	}
1476185db85Sdougm 
1486185db85Sdougm 	if (optind >= argc) {
149*25a68471Sdougm 		(void) printf(gettext("usage: %s\n"),
150*25a68471Sdougm 		    sc_get_usage(USAGE_CTL_GET));
1516185db85Sdougm 		(void) printf(gettext("\tprotocol must be specified.\n"));
1526185db85Sdougm 		return (SA_INVALID_PROTOCOL);
1536185db85Sdougm 	}
1546185db85Sdougm 
1556185db85Sdougm 	proto = argv[optind];
1566185db85Sdougm 	if (sa_valid_protocol(proto)) {
1576185db85Sdougm 		sa_protocol_properties_t propset;
1586185db85Sdougm 		propset = sa_proto_get_properties(proto);
1596185db85Sdougm 		if (propset != NULL) {
1606185db85Sdougm 			sa_property_t prop;
1616185db85Sdougm 			char *value;
1626185db85Sdougm 			char *name;
1636185db85Sdougm 
164*25a68471Sdougm 			if (optlist == NULL) {
165*25a68471Sdougm 				/*
166*25a68471Sdougm 				 * Display all known properties for
167*25a68471Sdougm 				 * this protocol.
168*25a68471Sdougm 				 */
169*25a68471Sdougm 				for (prop = sa_get_protocol_property(propset,
170*25a68471Sdougm 				    NULL);
171*25a68471Sdougm 				    prop != NULL;
172*25a68471Sdougm 				    prop = sa_get_next_protocol_property(
173*25a68471Sdougm 				    prop)) {
174*25a68471Sdougm 
175*25a68471Sdougm 					/*
176*25a68471Sdougm 					 * Get and display the
177*25a68471Sdougm 					 * property and value.
178*25a68471Sdougm 					 */
179*25a68471Sdougm 					name = sa_get_property_attr(prop,
180*25a68471Sdougm 					    "type");
1816185db85Sdougm 					if (name != NULL) {
182*25a68471Sdougm 						value = sa_get_property_attr(
183*25a68471Sdougm 						    prop, "value");
184*25a68471Sdougm 						(void) printf(gettext(
185*25a68471Sdougm 						    "%s=%s\n"), name,
1866185db85Sdougm 						    value != NULL ? value : "");
1876185db85Sdougm 					}
1886185db85Sdougm 					if (value != NULL)
1896185db85Sdougm 						sa_free_attr_string(value);
1906185db85Sdougm 					if (name != NULL)
1916185db85Sdougm 						sa_free_attr_string(name);
1926185db85Sdougm 				}
1936185db85Sdougm 			} else {
1946185db85Sdougm 				struct options *opt;
1956185db85Sdougm 				/* list the specified option(s) */
196*25a68471Sdougm 				for (opt = optlist;
197*25a68471Sdougm 				    opt != NULL;
198*25a68471Sdougm 				    opt = opt->next) {
199*25a68471Sdougm 					prop = sa_get_protocol_property(
200*25a68471Sdougm 					    propset, opt->optname);
2016185db85Sdougm 					if (prop != NULL) {
202*25a68471Sdougm 						value = sa_get_property_attr(
203*25a68471Sdougm 						    prop, "value");
204*25a68471Sdougm 						(void) printf(gettext(
205*25a68471Sdougm 						    "%s=%s\n"),
206*25a68471Sdougm 						    opt->optname,
207*25a68471Sdougm 						    value != NULL ?
208*25a68471Sdougm 						    value : "");
2096185db85Sdougm 						sa_free_attr_string(value);
2106185db85Sdougm 					} else {
211*25a68471Sdougm 						(void) printf(gettext(
212*25a68471Sdougm 						    "%s: not defined\n"),
2136185db85Sdougm 						    opt->optname);
2143472f5dcSdougm 						ret = SA_NO_SUCH_PROP;
2156185db85Sdougm 					}
2166185db85Sdougm 				}
2176185db85Sdougm 			}
2186185db85Sdougm 		}
2196185db85Sdougm 	} else {
220*25a68471Sdougm 		(void) printf(gettext("Invalid protocol specified: %s\n"),
221*25a68471Sdougm 		    proto);
2226185db85Sdougm 		ret = SA_INVALID_PROTOCOL;
2236185db85Sdougm 	}
2246185db85Sdougm 	return (ret);
2256185db85Sdougm }
2266185db85Sdougm 
227549ec3ffSdougm /*ARGSUSED*/
2286185db85Sdougm static int
229549ec3ffSdougm sc_set(sa_handle_t handle, int flags, int argc, char *argv[])
2306185db85Sdougm {
2316185db85Sdougm 	char *proto = NULL;
2326185db85Sdougm 	struct options *optlist = NULL;
2336185db85Sdougm 	int ret = SA_OK;
2346185db85Sdougm 	int c;
235*25a68471Sdougm 	sa_protocol_properties_t propset;
2366185db85Sdougm 
2376185db85Sdougm 	while ((c = getopt(argc, argv, "?hp:")) != EOF) {
2386185db85Sdougm 		switch (c) {
2396185db85Sdougm 		case 'p':
2406185db85Sdougm 			ret = add_opt(&optlist, optarg, 0);
2416185db85Sdougm 			if (ret != SA_OK) {
242*25a68471Sdougm 				(void) printf(gettext(
243*25a68471Sdougm 				    "Problem with property: %s\n"), optarg);
2446185db85Sdougm 				return (SA_NO_MEMORY);
2456185db85Sdougm 			}
2466185db85Sdougm 			break;
2476185db85Sdougm 		default:
2486185db85Sdougm 			(void) printf(gettext("usage: %s\n"),
2496185db85Sdougm 			    sc_get_usage(USAGE_CTL_SET));
2506185db85Sdougm 			return (SA_SYNTAX_ERR);
2516185db85Sdougm 		case '?':
2526185db85Sdougm 		case 'h':
2536185db85Sdougm 			(void) printf(gettext("usage: %s\n"),
2546185db85Sdougm 			    sc_get_usage(USAGE_CTL_SET));
2556185db85Sdougm 			return (SA_OK);
2566185db85Sdougm 			break;
2576185db85Sdougm 		}
2586185db85Sdougm 	}
2596185db85Sdougm 
2606185db85Sdougm 	if (optind >= argc) {
2616185db85Sdougm 		(void) printf(gettext("usage: %s\n"),
2626185db85Sdougm 		    sc_get_usage(USAGE_CTL_SET));
2636185db85Sdougm 		(void) printf(gettext("\tprotocol must be specified.\n"));
2646185db85Sdougm 		return (SA_INVALID_PROTOCOL);
2656185db85Sdougm 	}
2666185db85Sdougm 
2676185db85Sdougm 	proto = argv[optind];
268*25a68471Sdougm 	if (!sa_valid_protocol(proto)) {
269*25a68471Sdougm 		(void) printf(gettext("Invalid protocol specified: %s\n"),
270*25a68471Sdougm 		    proto);
271*25a68471Sdougm 		return (SA_INVALID_PROTOCOL);
272*25a68471Sdougm 	}
2736185db85Sdougm 	propset = sa_proto_get_properties(proto);
2746185db85Sdougm 	if (propset != NULL) {
2756185db85Sdougm 		sa_property_t prop;
2763472f5dcSdougm 		int err;
2776185db85Sdougm 		if (optlist == NULL) {
2786185db85Sdougm 			(void) printf(gettext("usage: %s\n"),
2796185db85Sdougm 			    sc_get_usage(USAGE_CTL_SET));
280*25a68471Sdougm 			(void) printf(gettext(
281*25a68471Sdougm 			    "\tat least one property and value "
2826185db85Sdougm 			    "must be specified\n"));
2836185db85Sdougm 		} else {
2846185db85Sdougm 			struct options *opt;
2856185db85Sdougm 			/* list the specified option(s) */
286*25a68471Sdougm 			for (opt = optlist;
287*25a68471Sdougm 			    opt != NULL;
288*25a68471Sdougm 			    opt = opt->next) {
289*25a68471Sdougm 				prop = sa_get_protocol_property(
290*25a68471Sdougm 				    propset, opt->optname);
2916185db85Sdougm 				if (prop != NULL) {
2923472f5dcSdougm 					/*
293*25a68471Sdougm 					 * "err" is used in order to
294*25a68471Sdougm 					 * prevent setting ret to
295*25a68471Sdougm 					 * SA_OK if there has been a
296*25a68471Sdougm 					 * real error. We want to be
297*25a68471Sdougm 					 * able to return an error
298*25a68471Sdougm 					 * status on exit in that
299*25a68471Sdougm 					 * case. Error messages are
300*25a68471Sdougm 					 * printed for each error, so
301*25a68471Sdougm 					 * we only care on exit that
302*25a68471Sdougm 					 * there was an error and not
303*25a68471Sdougm 					 * the specific error value.
3043472f5dcSdougm 					 */
305*25a68471Sdougm 					err = sa_set_protocol_property(
306*25a68471Sdougm 					    prop, opt->optvalue);
3073472f5dcSdougm 					if (err != SA_OK) {
308*25a68471Sdougm 						(void) printf(gettext(
309*25a68471Sdougm 						    "Could not set property"
3106185db85Sdougm 						    " %s: %s\n"),
311*25a68471Sdougm 						    opt->optname,
312*25a68471Sdougm 						    sa_errorstr(err));
3133472f5dcSdougm 						ret = err;
3146185db85Sdougm 					}
3156185db85Sdougm 				} else {
316*25a68471Sdougm 					(void) printf(gettext(
317*25a68471Sdougm 					    "%s: not defined\n"),
3186185db85Sdougm 					    opt->optname);
3193472f5dcSdougm 					ret = SA_NO_SUCH_PROP;
3206185db85Sdougm 				}
3216185db85Sdougm 			}
3226185db85Sdougm 		}
3236185db85Sdougm 	}
3246185db85Sdougm 	return (ret);
3256185db85Sdougm }
3266185db85Sdougm 
3276185db85Sdougm static void
3286185db85Sdougm show_status(char *proto)
3296185db85Sdougm {
3306185db85Sdougm 	char *status;
331*25a68471Sdougm 
3326185db85Sdougm 	status = sa_get_protocol_status(proto);
3336185db85Sdougm 	(void) printf("%s\t%s\n", proto, status ? gettext(status) : "-");
3346185db85Sdougm 	if (status != NULL)
3356185db85Sdougm 		free(status);
3366185db85Sdougm }
3376185db85Sdougm 
3386185db85Sdougm static int
3396185db85Sdougm valid_proto(char **protos, int num, char *proto)
3406185db85Sdougm {
3416185db85Sdougm 	int i;
3426185db85Sdougm 	for (i = 0; i < num; i++)
3436185db85Sdougm 		if (strcmp(protos[i], proto) == 0)
3446185db85Sdougm 			return (1);
3456185db85Sdougm 	return (0);
3466185db85Sdougm }
3476185db85Sdougm 
348549ec3ffSdougm /*ARGSUSED*/
3496185db85Sdougm static int
350549ec3ffSdougm sc_status(sa_handle_t handle, int flags, int argc, char *argv[])
3516185db85Sdougm {
3526185db85Sdougm 	char **protos;
3536185db85Sdougm 	int ret = SA_OK;
3546185db85Sdougm 	int c;
3556185db85Sdougm 	int i;
3566185db85Sdougm 	int num_proto;
3576185db85Sdougm 	int verbose = 0;
3586185db85Sdougm 
3596185db85Sdougm 	while ((c = getopt(argc, argv, "?hv")) != EOF) {
3606185db85Sdougm 		switch (c) {
3616185db85Sdougm 		case 'v':
3626185db85Sdougm 			verbose++;
3636185db85Sdougm 			break;
3646185db85Sdougm 		case '?':
3656185db85Sdougm 		case 'h':
3666185db85Sdougm 			(void) printf(gettext("usage: %s\n"),
3673472f5dcSdougm 			    sc_get_usage(USAGE_CTL_STATUS));
3686185db85Sdougm 			return (SA_OK);
3696185db85Sdougm 		default:
3706185db85Sdougm 			(void) printf(gettext("usage: %s\n"),
3713472f5dcSdougm 			    sc_get_usage(USAGE_CTL_STATUS));
3726185db85Sdougm 			return (SA_SYNTAX_ERR);
3736185db85Sdougm 		}
3746185db85Sdougm 	}
3756185db85Sdougm 
3766185db85Sdougm 	num_proto = sa_get_protocols(&protos);
3776185db85Sdougm 	if (optind == argc) {
3786185db85Sdougm 		/* status for all protocols */
3796185db85Sdougm 		for (i = 0; i < num_proto; i++) {
3806185db85Sdougm 			show_status(protos[i]);
3816185db85Sdougm 		}
3826185db85Sdougm 	} else {
3836185db85Sdougm 		for (i = optind; i < argc; i++) {
3846185db85Sdougm 			if (valid_proto(protos, num_proto, argv[i])) {
3856185db85Sdougm 				show_status(argv[i]);
3866185db85Sdougm 			} else {
387*25a68471Sdougm 				(void) printf(gettext("Invalid protocol: %s\n"),
388*25a68471Sdougm 				    argv[i]);
3896185db85Sdougm 				ret = SA_INVALID_PROTOCOL;
3906185db85Sdougm 			}
3916185db85Sdougm 		}
3926185db85Sdougm 	}
3936185db85Sdougm 	if (protos != NULL)
3946185db85Sdougm 		free(protos);
3956185db85Sdougm 	return (ret);
3966185db85Sdougm }
3976185db85Sdougm 
3986185db85Sdougm static sa_command_t commands[] = {
3996185db85Sdougm 	{"get", 0, sc_get, USAGE_CTL_GET},
4006185db85Sdougm 	{"set", 0, sc_set, USAGE_CTL_SET},
4016185db85Sdougm 	{"status", 0, sc_status, USAGE_CTL_STATUS},
4026185db85Sdougm 	{NULL, 0, NULL, 0},
4036185db85Sdougm };
4046185db85Sdougm 
405549ec3ffSdougm /*ARGSUSED*/
4066185db85Sdougm void
4076185db85Sdougm sub_command_help(char *proto)
4086185db85Sdougm {
4096185db85Sdougm 	int i;
4106185db85Sdougm 
4116185db85Sdougm 	(void) printf("\tsub-commands:\n");
4126185db85Sdougm 	for (i = 0; commands[i].cmdname != NULL; i++) {
4136185db85Sdougm 		if (!(commands[i].flags & (CMD_ALIAS|CMD_NODISPLAY)))
4146185db85Sdougm 			(void) printf("\t%s\n",
4156185db85Sdougm 			    sc_get_usage((sc_usage_t)commands[i].cmdidx));
4166185db85Sdougm 	}
4176185db85Sdougm }
4186185db85Sdougm 
4196185db85Sdougm sa_command_t *
4206185db85Sdougm sa_lookup(char *cmd)
4216185db85Sdougm {
4226185db85Sdougm 	int i;
4236185db85Sdougm 	size_t len;
4246185db85Sdougm 
4256185db85Sdougm 	len = strlen(cmd);
4266185db85Sdougm 	for (i = 0; commands[i].cmdname != NULL; i++) {
4276185db85Sdougm 		if (strncmp(cmd, commands[i].cmdname, len) == 0)
4286185db85Sdougm 			return (&commands[i]);
4296185db85Sdougm 	}
4306185db85Sdougm 	return (NULL);
4316185db85Sdougm }
4326185db85Sdougm 
4336185db85Sdougm static int
434549ec3ffSdougm run_command(char *command, int argc, char *argv[], sa_handle_t handle)
4356185db85Sdougm {
4366185db85Sdougm 	sa_command_t *cmdvec;
4376185db85Sdougm 	int ret;
4386185db85Sdougm 
4396185db85Sdougm 	/*
4406185db85Sdougm 	 * To get here, we know there should be a command due to the
4416185db85Sdougm 	 * preprocessing done earlier.  Need to find the protocol
4426185db85Sdougm 	 * that is being affected. If no protocol, then it is ALL
4436185db85Sdougm 	 * protocols.
4446185db85Sdougm 	 *
4456185db85Sdougm 	 * ??? do we really need the protocol at this level? it may be
4466185db85Sdougm 	 * sufficient to let the commands look it up if needed since
4476185db85Sdougm 	 * not all commands do proto specific things
4486185db85Sdougm 	 *
4496185db85Sdougm 	 * Known sub-commands are handled at this level. An unknown
4506185db85Sdougm 	 * command will be passed down to the shared object that
4516185db85Sdougm 	 * actually implements it. We can do this since the semantics
4526185db85Sdougm 	 * of the common sub-commands is well defined.
4536185db85Sdougm 	 */
4546185db85Sdougm 
4556185db85Sdougm 	cmdvec = sa_lookup(command);
4566185db85Sdougm 	if (cmdvec == NULL) {
4576185db85Sdougm 		(void) printf(gettext("command %s not found\n"), command);
4586185db85Sdougm 		exit(1);
4596185db85Sdougm 	}
4606185db85Sdougm 	/*
4616185db85Sdougm 	 * need to check priviledges and restrict what can be done
4626185db85Sdougm 	 * based on least priviledge and sub-command.
4636185db85Sdougm 	 */
464549ec3ffSdougm 	ret = cmdvec->cmdfunc(handle, NULL, argc, argv);
4656185db85Sdougm 	return (ret);
4666185db85Sdougm }
467