xref: /onnv-gate/usr/src/cmd/dfs.cmds/sharectl/sharectl.c (revision 4653:9f76bf2cd971)
13034Sdougm /*
23034Sdougm  * CDDL HEADER START
33034Sdougm  *
43034Sdougm  * The contents of this file are subject to the terms of the
53034Sdougm  * Common Development and Distribution License (the "License").
63034Sdougm  * You may not use this file except in compliance with the License.
73034Sdougm  *
83034Sdougm  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93034Sdougm  * or http://www.opensolaris.org/os/licensing.
103034Sdougm  * See the License for the specific language governing permissions
113034Sdougm  * and limitations under the License.
123034Sdougm  *
133034Sdougm  * When distributing Covered Code, include this CDDL HEADER in each
143034Sdougm  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153034Sdougm  * If applicable, add the following below this CDDL HEADER, with the
163034Sdougm  * fields enclosed by brackets "[]" replaced with your own identifying
173034Sdougm  * information: Portions Copyright [yyyy] [name of copyright owner]
183034Sdougm  *
193034Sdougm  * CDDL HEADER END
203034Sdougm  */
213034Sdougm 
223034Sdougm /*
233393Sdougm  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
243034Sdougm  * Use is subject to license terms.
253034Sdougm  */
263034Sdougm 
273034Sdougm #pragma ident	"%Z%%M%	%I%	%E% SMI"
283034Sdougm 
293034Sdougm #include <stdlib.h>
303034Sdougm #include <stdio.h>
313034Sdougm #include <string.h>
323034Sdougm #include <ctype.h>
333034Sdougm #include <unistd.h>
343034Sdougm #include <getopt.h>
353034Sdougm #include <libgen.h>
363034Sdougm 
373034Sdougm #include "libshare.h"
383034Sdougm #include <sharemgr.h>
393034Sdougm 
403034Sdougm #include <libintl.h>
413034Sdougm #include <locale.h>
423034Sdougm 
433910Sdougm static int run_command(char *, int, char **, sa_handle_t);
443034Sdougm static void sub_command_help(char *proto);
453034Sdougm 
463034Sdougm static void
473034Sdougm global_help()
483034Sdougm {
493034Sdougm 	(void) printf(gettext("usage: sharectl <command> [options]\n"));
503034Sdougm 	sub_command_help(NULL);
513034Sdougm }
523034Sdougm 
533034Sdougm int
543034Sdougm main(int argc, char *argv[])
553034Sdougm {
563034Sdougm 	int c;
573034Sdougm 	int help = 0;
583034Sdougm 	int rval;
593034Sdougm 	char *command;
603910Sdougm 	sa_handle_t handle;
613034Sdougm 
623034Sdougm 	/*
633034Sdougm 	 * make sure locale and gettext domain is setup
643034Sdougm 	 */
653034Sdougm 	(void) setlocale(LC_ALL, "");
663034Sdougm 	(void) textdomain(TEXT_DOMAIN);
673034Sdougm 
683910Sdougm 	handle = sa_init(SA_INIT_CONTROL_API);
693034Sdougm 
703034Sdougm 	while ((c = getopt(argc, argv, "h?")) != EOF) {
71*4653Sdougm 		switch (c) {
72*4653Sdougm 		case '?':
73*4653Sdougm 		case 'h':
74*4653Sdougm 			help = 1;
75*4653Sdougm 			break;
76*4653Sdougm 		default:
77*4653Sdougm 			(void) printf(gettext("Invalid option: %c\n"), c);
78*4653Sdougm 		}
793034Sdougm 	}
803034Sdougm 	if (optind == argc || help) {
81*4653Sdougm 		/* no subcommand */
82*4653Sdougm 		global_help();
83*4653Sdougm 		exit(0);
843034Sdougm 	}
853034Sdougm 	optind = 1;
863034Sdougm 
873034Sdougm 	/*
883034Sdougm 	 * now have enough to parse rest of command line
893034Sdougm 	 */
903034Sdougm 	command = argv[optind];
913910Sdougm 	rval = run_command(command, argc - optind, argv + optind, handle);
923034Sdougm 
933910Sdougm 	sa_fini(handle);
943034Sdougm 	return (rval);
953034Sdougm }
963034Sdougm 
973034Sdougm char *
983034Sdougm sc_get_usage(sc_usage_t index)
993034Sdougm {
1003034Sdougm 	char *ret = NULL;
1013034Sdougm 
1023034Sdougm 	switch (index) {
1033034Sdougm 	case USAGE_CTL_GET:
104*4653Sdougm 		ret = gettext("get [-h | -p property ...] proto");
105*4653Sdougm 		break;
1063034Sdougm 	case USAGE_CTL_SET:
107*4653Sdougm 		ret = gettext("set [-h] -p property=value ... proto");
108*4653Sdougm 		break;
1093034Sdougm 	case USAGE_CTL_STATUS:
110*4653Sdougm 		ret = gettext("status [-h | proto ...]");
111*4653Sdougm 		break;
1123034Sdougm 	}
1133034Sdougm 	return (ret);
1143034Sdougm }
1153034Sdougm 
1163910Sdougm /*ARGSUSED*/
1173034Sdougm static int
1183910Sdougm sc_get(sa_handle_t handle, int flags, int argc, char *argv[])
1193034Sdougm {
1203034Sdougm 	char *proto = NULL;
1213034Sdougm 	struct options *optlist = NULL;
1223034Sdougm 	int ret = SA_OK;
1233034Sdougm 	int c;
1243034Sdougm 
1253034Sdougm 	while ((c = getopt(argc, argv, "?hp:")) != EOF) {
126*4653Sdougm 		switch (c) {
127*4653Sdougm 		case 'p':
128*4653Sdougm 			ret = add_opt(&optlist, optarg, 1);
129*4653Sdougm 			if (ret != SA_OK) {
130*4653Sdougm 				(void) printf(gettext(
131*4653Sdougm 				    "Problem with property: %s\n"), optarg);
132*4653Sdougm 				return (SA_NO_MEMORY);
133*4653Sdougm 			}
134*4653Sdougm 			break;
135*4653Sdougm 		default:
136*4653Sdougm 			(void) printf(gettext("usage: %s\n"),
137*4653Sdougm 			    sc_get_usage(USAGE_CTL_GET));
138*4653Sdougm 			return (SA_SYNTAX_ERR);
139*4653Sdougm 		case '?':
140*4653Sdougm 		case 'h':
141*4653Sdougm 			(void) printf(gettext("usage: %s\n"),
142*4653Sdougm 			    sc_get_usage(USAGE_CTL_GET));
143*4653Sdougm 			return (SA_OK);
144*4653Sdougm 			break;
1453034Sdougm 		}
1463034Sdougm 	}
1473034Sdougm 
1483034Sdougm 	if (optind >= argc) {
149*4653Sdougm 		(void) printf(gettext("usage: %s\n"),
150*4653Sdougm 		    sc_get_usage(USAGE_CTL_GET));
151*4653Sdougm 		(void) printf(gettext("\tprotocol must be specified.\n"));
152*4653Sdougm 		return (SA_INVALID_PROTOCOL);
1533034Sdougm 	}
1543034Sdougm 
1553034Sdougm 	proto = argv[optind];
1563034Sdougm 	if (sa_valid_protocol(proto)) {
157*4653Sdougm 		sa_protocol_properties_t propset;
158*4653Sdougm 		propset = sa_proto_get_properties(proto);
159*4653Sdougm 		if (propset != NULL) {
160*4653Sdougm 			sa_property_t prop;
161*4653Sdougm 			char *value;
162*4653Sdougm 			char *name;
163*4653Sdougm 
164*4653Sdougm 			if (optlist == NULL) {
165*4653Sdougm 				/*
166*4653Sdougm 				 * Display all known properties for
167*4653Sdougm 				 * this protocol.
168*4653Sdougm 				 */
169*4653Sdougm 				for (prop = sa_get_protocol_property(propset,
170*4653Sdougm 				    NULL);
171*4653Sdougm 				    prop != NULL;
172*4653Sdougm 				    prop = sa_get_next_protocol_property(
173*4653Sdougm 				    prop)) {
1743034Sdougm 
175*4653Sdougm 					/*
176*4653Sdougm 					 * Get and display the
177*4653Sdougm 					 * property and value.
178*4653Sdougm 					 */
179*4653Sdougm 					name = sa_get_property_attr(prop,
180*4653Sdougm 					    "type");
181*4653Sdougm 					if (name != NULL) {
182*4653Sdougm 						value = sa_get_property_attr(
183*4653Sdougm 						    prop, "value");
184*4653Sdougm 						(void) printf(gettext(
185*4653Sdougm 						    "%s=%s\n"), name,
186*4653Sdougm 						    value != NULL ? value : "");
187*4653Sdougm 					}
188*4653Sdougm 					if (value != NULL)
189*4653Sdougm 						sa_free_attr_string(value);
190*4653Sdougm 					if (name != NULL)
191*4653Sdougm 						sa_free_attr_string(name);
192*4653Sdougm 				}
193*4653Sdougm 			} else {
194*4653Sdougm 				struct options *opt;
195*4653Sdougm 				/* list the specified option(s) */
196*4653Sdougm 				for (opt = optlist;
197*4653Sdougm 				    opt != NULL;
198*4653Sdougm 				    opt = opt->next) {
199*4653Sdougm 					prop = sa_get_protocol_property(
200*4653Sdougm 					    propset, opt->optname);
201*4653Sdougm 					if (prop != NULL) {
202*4653Sdougm 						value = sa_get_property_attr(
203*4653Sdougm 						    prop, "value");
204*4653Sdougm 						(void) printf(gettext(
205*4653Sdougm 						    "%s=%s\n"),
206*4653Sdougm 						    opt->optname,
207*4653Sdougm 						    value != NULL ?
208*4653Sdougm 						    value : "");
209*4653Sdougm 						sa_free_attr_string(value);
210*4653Sdougm 					} else {
211*4653Sdougm 						(void) printf(gettext(
212*4653Sdougm 						    "%s: not defined\n"),
213*4653Sdougm 						    opt->optname);
214*4653Sdougm 						ret = SA_NO_SUCH_PROP;
215*4653Sdougm 					}
216*4653Sdougm 				}
2173034Sdougm 			}
2183034Sdougm 		}
2193034Sdougm 	} else {
220*4653Sdougm 		(void) printf(gettext("Invalid protocol specified: %s\n"),
221*4653Sdougm 		    proto);
222*4653Sdougm 		ret = SA_INVALID_PROTOCOL;
2233034Sdougm 	}
2243034Sdougm 	return (ret);
2253034Sdougm }
2263034Sdougm 
2273910Sdougm /*ARGSUSED*/
2283034Sdougm static int
2293910Sdougm sc_set(sa_handle_t handle, int flags, int argc, char *argv[])
2303034Sdougm {
2313034Sdougm 	char *proto = NULL;
2323034Sdougm 	struct options *optlist = NULL;
2333034Sdougm 	int ret = SA_OK;
2343034Sdougm 	int c;
235*4653Sdougm 	sa_protocol_properties_t propset;
2363034Sdougm 
2373034Sdougm 	while ((c = getopt(argc, argv, "?hp:")) != EOF) {
238*4653Sdougm 		switch (c) {
239*4653Sdougm 		case 'p':
240*4653Sdougm 			ret = add_opt(&optlist, optarg, 0);
241*4653Sdougm 			if (ret != SA_OK) {
242*4653Sdougm 				(void) printf(gettext(
243*4653Sdougm 				    "Problem with property: %s\n"), optarg);
244*4653Sdougm 				return (SA_NO_MEMORY);
245*4653Sdougm 			}
246*4653Sdougm 			break;
247*4653Sdougm 		default:
248*4653Sdougm 			(void) printf(gettext("usage: %s\n"),
249*4653Sdougm 			    sc_get_usage(USAGE_CTL_SET));
250*4653Sdougm 			return (SA_SYNTAX_ERR);
251*4653Sdougm 		case '?':
252*4653Sdougm 		case 'h':
253*4653Sdougm 			(void) printf(gettext("usage: %s\n"),
254*4653Sdougm 			    sc_get_usage(USAGE_CTL_SET));
255*4653Sdougm 			return (SA_OK);
256*4653Sdougm 			break;
2573034Sdougm 		}
2583034Sdougm 	}
2593034Sdougm 
2603034Sdougm 	if (optind >= argc) {
261*4653Sdougm 		(void) printf(gettext("usage: %s\n"),
262*4653Sdougm 		    sc_get_usage(USAGE_CTL_SET));
263*4653Sdougm 		(void) printf(gettext("\tprotocol must be specified.\n"));
264*4653Sdougm 		return (SA_INVALID_PROTOCOL);
2653034Sdougm 	}
2663034Sdougm 
2673034Sdougm 	proto = argv[optind];
268*4653Sdougm 	if (!sa_valid_protocol(proto)) {
269*4653Sdougm 		(void) printf(gettext("Invalid protocol specified: %s\n"),
270*4653Sdougm 		    proto);
271*4653Sdougm 		return (SA_INVALID_PROTOCOL);
272*4653Sdougm 	}
273*4653Sdougm 	propset = sa_proto_get_properties(proto);
274*4653Sdougm 	if (propset != NULL) {
2753034Sdougm 		sa_property_t prop;
2763393Sdougm 		int err;
2773034Sdougm 		if (optlist == NULL) {
278*4653Sdougm 			(void) printf(gettext("usage: %s\n"),
279*4653Sdougm 			    sc_get_usage(USAGE_CTL_SET));
280*4653Sdougm 			(void) printf(gettext(
281*4653Sdougm 			    "\tat least one property and value "
282*4653Sdougm 			    "must be specified\n"));
2833034Sdougm 		} else {
284*4653Sdougm 			struct options *opt;
285*4653Sdougm 			/* list the specified option(s) */
286*4653Sdougm 			for (opt = optlist;
287*4653Sdougm 			    opt != NULL;
288*4653Sdougm 			    opt = opt->next) {
289*4653Sdougm 				prop = sa_get_protocol_property(
290*4653Sdougm 				    propset, opt->optname);
291*4653Sdougm 				if (prop != NULL) {
292*4653Sdougm 					/*
293*4653Sdougm 					 * "err" is used in order to
294*4653Sdougm 					 * prevent setting ret to
295*4653Sdougm 					 * SA_OK if there has been a
296*4653Sdougm 					 * real error. We want to be
297*4653Sdougm 					 * able to return an error
298*4653Sdougm 					 * status on exit in that
299*4653Sdougm 					 * case. Error messages are
300*4653Sdougm 					 * printed for each error, so
301*4653Sdougm 					 * we only care on exit that
302*4653Sdougm 					 * there was an error and not
303*4653Sdougm 					 * the specific error value.
304*4653Sdougm 					 */
305*4653Sdougm 					err = sa_set_protocol_property(
306*4653Sdougm 					    prop, opt->optvalue);
307*4653Sdougm 					if (err != SA_OK) {
308*4653Sdougm 						(void) printf(gettext(
309*4653Sdougm 						    "Could not set property"
310*4653Sdougm 						    " %s: %s\n"),
311*4653Sdougm 						    opt->optname,
312*4653Sdougm 						    sa_errorstr(err));
313*4653Sdougm 						ret = err;
314*4653Sdougm 					}
315*4653Sdougm 				} else {
316*4653Sdougm 					(void) printf(gettext(
317*4653Sdougm 					    "%s: not defined\n"),
318*4653Sdougm 					    opt->optname);
319*4653Sdougm 					ret = SA_NO_SUCH_PROP;
320*4653Sdougm 				}
3213034Sdougm 			}
3223034Sdougm 		}
3233034Sdougm 	}
3243034Sdougm 	return (ret);
3253034Sdougm }
3263034Sdougm 
3273034Sdougm static void
3283034Sdougm show_status(char *proto)
3293034Sdougm {
3303034Sdougm 	char *status;
331*4653Sdougm 
3323034Sdougm 	status = sa_get_protocol_status(proto);
3333034Sdougm 	(void) printf("%s\t%s\n", proto, status ? gettext(status) : "-");
3343034Sdougm 	if (status != NULL)
335*4653Sdougm 		free(status);
3363034Sdougm }
3373034Sdougm 
3383034Sdougm static int
3393034Sdougm valid_proto(char **protos, int num, char *proto)
3403034Sdougm {
3413034Sdougm 	int i;
3423034Sdougm 	for (i = 0; i < num; i++)
343*4653Sdougm 		if (strcmp(protos[i], proto) == 0)
344*4653Sdougm 			return (1);
3453034Sdougm 	return (0);
3463034Sdougm }
3473034Sdougm 
3483910Sdougm /*ARGSUSED*/
3493034Sdougm static int
3503910Sdougm sc_status(sa_handle_t handle, int flags, int argc, char *argv[])
3513034Sdougm {
3523034Sdougm 	char **protos;
3533034Sdougm 	int ret = SA_OK;
3543034Sdougm 	int c;
3553034Sdougm 	int i;
3563034Sdougm 	int num_proto;
3573034Sdougm 	int verbose = 0;
3583034Sdougm 
3593034Sdougm 	while ((c = getopt(argc, argv, "?hv")) != EOF) {
360*4653Sdougm 		switch (c) {
361*4653Sdougm 		case 'v':
362*4653Sdougm 			verbose++;
363*4653Sdougm 			break;
364*4653Sdougm 		case '?':
365*4653Sdougm 		case 'h':
366*4653Sdougm 			(void) printf(gettext("usage: %s\n"),
367*4653Sdougm 			    sc_get_usage(USAGE_CTL_STATUS));
368*4653Sdougm 			return (SA_OK);
369*4653Sdougm 		default:
370*4653Sdougm 			(void) printf(gettext("usage: %s\n"),
371*4653Sdougm 			    sc_get_usage(USAGE_CTL_STATUS));
372*4653Sdougm 			return (SA_SYNTAX_ERR);
373*4653Sdougm 		}
3743034Sdougm 	}
3753034Sdougm 
3763034Sdougm 	num_proto = sa_get_protocols(&protos);
3773034Sdougm 	if (optind == argc) {
378*4653Sdougm 		/* status for all protocols */
379*4653Sdougm 		for (i = 0; i < num_proto; i++) {
380*4653Sdougm 			show_status(protos[i]);
381*4653Sdougm 		}
3823034Sdougm 	} else {
383*4653Sdougm 		for (i = optind; i < argc; i++) {
384*4653Sdougm 			if (valid_proto(protos, num_proto, argv[i])) {
385*4653Sdougm 				show_status(argv[i]);
386*4653Sdougm 			} else {
387*4653Sdougm 				(void) printf(gettext("Invalid protocol: %s\n"),
388*4653Sdougm 				    argv[i]);
389*4653Sdougm 				ret = SA_INVALID_PROTOCOL;
390*4653Sdougm 			}
3913034Sdougm 		}
3923034Sdougm 	}
3933034Sdougm 	if (protos != NULL)
394*4653Sdougm 		free(protos);
3953034Sdougm 	return (ret);
3963034Sdougm }
3973034Sdougm 
3983034Sdougm static sa_command_t commands[] = {
3993034Sdougm 	{"get", 0, sc_get, USAGE_CTL_GET},
4003034Sdougm 	{"set", 0, sc_set, USAGE_CTL_SET},
4013034Sdougm 	{"status", 0, sc_status, USAGE_CTL_STATUS},
4023034Sdougm 	{NULL, 0, NULL, 0},
4033034Sdougm };
4043034Sdougm 
4053910Sdougm /*ARGSUSED*/
4063034Sdougm void
4073034Sdougm sub_command_help(char *proto)
4083034Sdougm {
4093034Sdougm 	int i;
4103034Sdougm 
4113034Sdougm 	(void) printf("\tsub-commands:\n");
4123034Sdougm 	for (i = 0; commands[i].cmdname != NULL; i++) {
4133034Sdougm 		if (!(commands[i].flags & (CMD_ALIAS|CMD_NODISPLAY)))
4143034Sdougm 			(void) printf("\t%s\n",
415*4653Sdougm 			    sc_get_usage((sc_usage_t)commands[i].cmdidx));
4163034Sdougm 	}
4173034Sdougm }
4183034Sdougm 
4193034Sdougm sa_command_t *
4203034Sdougm sa_lookup(char *cmd)
4213034Sdougm {
4223034Sdougm 	int i;
4233034Sdougm 	size_t len;
4243034Sdougm 
4253034Sdougm 	len = strlen(cmd);
4263034Sdougm 	for (i = 0; commands[i].cmdname != NULL; i++) {
4273034Sdougm 		if (strncmp(cmd, commands[i].cmdname, len) == 0)
4283034Sdougm 			return (&commands[i]);
4293034Sdougm 	}
4303034Sdougm 	return (NULL);
4313034Sdougm }
4323034Sdougm 
4333034Sdougm static int
4343910Sdougm run_command(char *command, int argc, char *argv[], sa_handle_t handle)
4353034Sdougm {
4363034Sdougm 	sa_command_t *cmdvec;
4373034Sdougm 	int ret;
4383034Sdougm 
4393034Sdougm 	/*
4403034Sdougm 	 * To get here, we know there should be a command due to the
4413034Sdougm 	 * preprocessing done earlier.  Need to find the protocol
4423034Sdougm 	 * that is being affected. If no protocol, then it is ALL
4433034Sdougm 	 * protocols.
4443034Sdougm 	 *
4453034Sdougm 	 * ??? do we really need the protocol at this level? it may be
4463034Sdougm 	 * sufficient to let the commands look it up if needed since
4473034Sdougm 	 * not all commands do proto specific things
4483034Sdougm 	 *
4493034Sdougm 	 * Known sub-commands are handled at this level. An unknown
4503034Sdougm 	 * command will be passed down to the shared object that
4513034Sdougm 	 * actually implements it. We can do this since the semantics
4523034Sdougm 	 * of the common sub-commands is well defined.
4533034Sdougm 	 */
4543034Sdougm 
4553034Sdougm 	cmdvec = sa_lookup(command);
4563034Sdougm 	if (cmdvec == NULL) {
4573034Sdougm 		(void) printf(gettext("command %s not found\n"), command);
4583034Sdougm 		exit(1);
4593034Sdougm 	}
4603034Sdougm 	/*
4613034Sdougm 	 * need to check priviledges and restrict what can be done
4623034Sdougm 	 * based on least priviledge and sub-command.
4633034Sdougm 	 */
4643910Sdougm 	ret = cmdvec->cmdfunc(handle, NULL, argc, argv);
4653034Sdougm 	return (ret);
4663034Sdougm }
467