xref: /onnv-gate/usr/src/cmd/dfs.cmds/sharectl/sharectl.c (revision 3393:660717ce3a70)
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 /*
23*3393Sdougm  * 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 
433034Sdougm static int run_command(char *, int, char **);
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;
603034Sdougm 
613034Sdougm 	/*
623034Sdougm 	 * make sure locale and gettext domain is setup
633034Sdougm 	 */
643034Sdougm 	(void) setlocale(LC_ALL, "");
653034Sdougm 	(void) textdomain(TEXT_DOMAIN);
663034Sdougm 
673034Sdougm 	sa_init(SA_INIT_CONTROL_API);
683034Sdougm 
693034Sdougm 	while ((c = getopt(argc, argv, "h?")) != EOF) {
703034Sdougm 	    switch (c) {
713034Sdougm 	    case '?':
723034Sdougm 	    case 'h':
733034Sdougm 		help = 1;
743034Sdougm 		break;
753034Sdougm 	    default:
763034Sdougm 		(void) printf(gettext("Invalid option: %c\n"), c);
773034Sdougm 	    }
783034Sdougm 	}
793034Sdougm 	if (optind == argc || help) {
803034Sdougm 	    /* no subcommand */
813034Sdougm 	    global_help();
823034Sdougm 	    exit(0);
833034Sdougm 	}
843034Sdougm 	optind = 1;
853034Sdougm 
863034Sdougm 	/*
873034Sdougm 	 * now have enough to parse rest of command line
883034Sdougm 	 */
893034Sdougm 	command = argv[optind];
903034Sdougm 	rval = run_command(command, argc - optind, argv + optind);
913034Sdougm 
923034Sdougm 	sa_fini();
933034Sdougm 	return (rval);
943034Sdougm }
953034Sdougm 
963034Sdougm char *
973034Sdougm sc_get_usage(sc_usage_t index)
983034Sdougm {
993034Sdougm 	char *ret = NULL;
1003034Sdougm 
1013034Sdougm 	switch (index) {
1023034Sdougm 	case USAGE_CTL_GET:
103*3393Sdougm 	    ret = gettext("get [-h | -p property ...] proto");
1043034Sdougm 	    break;
1053034Sdougm 	case USAGE_CTL_SET:
1063034Sdougm 	    ret = gettext("set [-h] -p property=value ... proto");
1073034Sdougm 	    break;
1083034Sdougm 	case USAGE_CTL_STATUS:
109*3393Sdougm 	    ret = gettext("status [-h | proto ...]");
1103034Sdougm 	    break;
1113034Sdougm 	}
1123034Sdougm 	return (ret);
1133034Sdougm }
1143034Sdougm 
1153034Sdougm static int
1163034Sdougm sc_get(int flags, int argc, char *argv[])
1173034Sdougm {
1183034Sdougm 	char *proto = NULL;
1193034Sdougm 	struct options *optlist = NULL;
1203034Sdougm 	int ret = SA_OK;
1213034Sdougm 	int c;
1223034Sdougm #ifdef lint
1233034Sdougm 	flags = flags;
1243034Sdougm #endif
1253034Sdougm 
1263034Sdougm 	while ((c = getopt(argc, argv, "?hp:")) != EOF) {
1273034Sdougm 	    switch (c) {
1283034Sdougm 	    case 'p':
1293034Sdougm 		ret = add_opt(&optlist, optarg, 1);
1303034Sdougm 		if (ret != SA_OK) {
1313034Sdougm 		    (void) printf(gettext("Problem with property: %s\n"),
1323034Sdougm 						optarg);
1333034Sdougm 		    return (SA_NO_MEMORY);
1343034Sdougm 		}
1353034Sdougm 		break;
1363034Sdougm 	    default:
1373034Sdougm 		(void) printf(gettext("usage: %s\n"),
1383034Sdougm 				sc_get_usage(USAGE_CTL_GET));
1393034Sdougm 		return (SA_SYNTAX_ERR);
1403034Sdougm 	    case '?':
1413034Sdougm 	    case 'h':
1423034Sdougm 		(void) printf(gettext("usage: %s\n"),
1433034Sdougm 				sc_get_usage(USAGE_CTL_GET));
1443034Sdougm 		return (SA_OK);
1453034Sdougm 		break;
1463034Sdougm 	    }
1473034Sdougm 	}
1483034Sdougm 
1493034Sdougm 	if (optind >= argc) {
1503034Sdougm 	    (void) printf(gettext("usage: %s\n"), sc_get_usage(USAGE_CTL_GET));
1513034Sdougm 	    (void) printf(gettext("\tprotocol must be specified.\n"));
1523034Sdougm 	    return (SA_INVALID_PROTOCOL);
1533034Sdougm 	}
1543034Sdougm 
1553034Sdougm 	proto = argv[optind];
1563034Sdougm 	if (sa_valid_protocol(proto)) {
1573034Sdougm 	    sa_protocol_properties_t propset;
1583034Sdougm 	    propset = sa_proto_get_properties(proto);
1593034Sdougm 	    if (propset != NULL) {
1603034Sdougm 		sa_property_t prop;
1613034Sdougm 		char *value;
1623034Sdougm 		char *name;
1633034Sdougm 		if (optlist == NULL) {
1643034Sdougm 		    /* display all known properties for this protocol */
1653034Sdougm 		    for (prop = sa_get_protocol_property(propset, NULL);
1663034Sdougm 			prop != NULL;
1673034Sdougm 			prop = sa_get_next_protocol_property(prop)) {
1683034Sdougm 
1693034Sdougm 			/* get and display the property and value */
1703034Sdougm 			name = sa_get_property_attr(prop, "type");
1713034Sdougm 			if (name != NULL) {
1723034Sdougm 			    value = sa_get_property_attr(prop, "value");
1733034Sdougm 			    (void) printf(gettext("%s=%s\n"), name,
1743034Sdougm 						value != NULL ? value : "");
1753034Sdougm 			}
1763034Sdougm 			if (value != NULL)
1773034Sdougm 			    sa_free_attr_string(value);
1783034Sdougm 			if (name != NULL)
1793034Sdougm 			    sa_free_attr_string(name);
1803034Sdougm 		    }
1813034Sdougm 		} else {
1823034Sdougm 		    struct options *opt;
1833034Sdougm 		    /* list the specified option(s) */
1843034Sdougm 		    for (opt = optlist; opt != NULL; opt = opt->next) {
1853034Sdougm 			prop = sa_get_protocol_property(propset, opt->optname);
1863034Sdougm 			if (prop != NULL) {
1873034Sdougm 			    value = sa_get_property_attr(prop, "value");
1883034Sdougm 			    (void) printf(gettext("%s=%s\n"), opt->optname,
1893034Sdougm 					value != NULL ? value : "");
1903034Sdougm 			    sa_free_attr_string(value);
1913034Sdougm 			} else {
1923034Sdougm 			    (void) printf(gettext("%s: not defined\n"),
1933034Sdougm 						opt->optname);
194*3393Sdougm 			    ret = SA_NO_SUCH_PROP;
1953034Sdougm 			}
1963034Sdougm 		    }
1973034Sdougm 		}
1983034Sdougm 	    }
1993034Sdougm 	} else {
2003034Sdougm 	    (void) printf(gettext("Invalid protocol specified: %s\n"), proto);
2013034Sdougm 	    ret = SA_INVALID_PROTOCOL;
2023034Sdougm 	}
2033034Sdougm 	return (ret);
2043034Sdougm }
2053034Sdougm 
2063034Sdougm static int
2073034Sdougm sc_set(int flags, int argc, char *argv[])
2083034Sdougm {
2093034Sdougm 	char *proto = NULL;
2103034Sdougm 	struct options *optlist = NULL;
2113034Sdougm 	int ret = SA_OK;
2123034Sdougm 	int c;
2133034Sdougm #ifdef lint
2143034Sdougm 	flags = flags;
2153034Sdougm #endif
2163034Sdougm 
2173034Sdougm 	while ((c = getopt(argc, argv, "?hp:")) != EOF) {
2183034Sdougm 	    switch (c) {
2193034Sdougm 	    case 'p':
2203034Sdougm 		ret = add_opt(&optlist, optarg, 0);
2213034Sdougm 		if (ret != SA_OK) {
2223034Sdougm 		    (void) printf(gettext("Problem with property: %s\n"),
2233034Sdougm 					optarg);
2243034Sdougm 		    return (SA_NO_MEMORY);
2253034Sdougm 		}
2263034Sdougm 		break;
2273034Sdougm 	    default:
2283034Sdougm 		(void) printf(gettext("usage: %s\n"),
2293034Sdougm 				sc_get_usage(USAGE_CTL_SET));
2303034Sdougm 		return (SA_SYNTAX_ERR);
2313034Sdougm 	    case '?':
2323034Sdougm 	    case 'h':
2333034Sdougm 		(void) printf(gettext("usage: %s\n"),
2343034Sdougm 				sc_get_usage(USAGE_CTL_SET));
2353034Sdougm 		return (SA_OK);
2363034Sdougm 		break;
2373034Sdougm 	    }
2383034Sdougm 	}
2393034Sdougm 
2403034Sdougm 	if (optind >= argc) {
2413034Sdougm 	    (void) printf(gettext("usage: %s\n"),
2423034Sdougm 				sc_get_usage(USAGE_CTL_SET));
2433034Sdougm 	    (void) printf(gettext("\tprotocol must be specified.\n"));
2443034Sdougm 	    return (SA_INVALID_PROTOCOL);
2453034Sdougm 	}
2463034Sdougm 
2473034Sdougm 	proto = argv[optind];
2483034Sdougm 	if (sa_valid_protocol(proto)) {
2493034Sdougm 	    sa_protocol_properties_t propset;
2503034Sdougm 	    propset = sa_proto_get_properties(proto);
2513034Sdougm 	    if (propset != NULL) {
2523034Sdougm 		sa_property_t prop;
253*3393Sdougm 		int err;
2543034Sdougm 
2553034Sdougm 		if (optlist == NULL) {
2563034Sdougm 		    (void) printf(gettext("usage: %s\n"),
2573034Sdougm 				sc_get_usage(USAGE_CTL_SET));
2583034Sdougm 		    (void) printf(gettext("\tat least one property and value "
2593034Sdougm 				    "must be specified\n"));
2603034Sdougm 		} else {
2613034Sdougm 		    struct options *opt;
2623034Sdougm 		    /* list the specified option(s) */
2633034Sdougm 		    for (opt = optlist; opt != NULL; opt = opt->next) {
2643034Sdougm 			prop = sa_get_protocol_property(propset, opt->optname);
2653034Sdougm 			if (prop != NULL) {
266*3393Sdougm 				/*
267*3393Sdougm 				 * "err" is used in order to prevent
268*3393Sdougm 				 * setting ret to SA_OK if there has
269*3393Sdougm 				 * been a real error. We want to be
270*3393Sdougm 				 * able to return an error status on
271*3393Sdougm 				 * exit in that case. Error messages
272*3393Sdougm 				 * are printed for each error, so we
273*3393Sdougm 				 * only care on exit that there was an
274*3393Sdougm 				 * error and not the specific error
275*3393Sdougm 				 * value.
276*3393Sdougm 				 */
277*3393Sdougm 			    err = sa_set_protocol_property(prop, opt->optvalue);
278*3393Sdougm 			    if (err != SA_OK) {
2793034Sdougm 				(void) printf(gettext("Could not set property"
280*3393Sdougm 							" %s: %s\n"),
281*3393Sdougm 					opt->optname, sa_errorstr(err));
282*3393Sdougm 				ret = err;
2833034Sdougm 			    }
2843034Sdougm 			} else {
2853034Sdougm 			    (void) printf(gettext("%s: not defined\n"),
2863034Sdougm 						opt->optname);
287*3393Sdougm 			    ret = SA_NO_SUCH_PROP;
2883034Sdougm 			}
2893034Sdougm 		    }
2903034Sdougm 		}
2913034Sdougm 	    }
2923034Sdougm 	} else {
2933034Sdougm 	    (void) printf(gettext("Invalid protocol specified: %s\n"), proto);
2943034Sdougm 	    ret = SA_INVALID_PROTOCOL;
2953034Sdougm 	}
2963034Sdougm 	return (ret);
2973034Sdougm }
2983034Sdougm 
2993034Sdougm static void
3003034Sdougm show_status(char *proto)
3013034Sdougm {
3023034Sdougm 	char *status;
3033034Sdougm 	status = sa_get_protocol_status(proto);
3043034Sdougm 	(void) printf("%s\t%s\n", proto, status ? gettext(status) : "-");
3053034Sdougm 	if (status != NULL)
3063034Sdougm 	    free(status);
3073034Sdougm }
3083034Sdougm 
3093034Sdougm static int
3103034Sdougm valid_proto(char **protos, int num, char *proto)
3113034Sdougm {
3123034Sdougm 	int i;
3133034Sdougm 	for (i = 0; i < num; i++)
3143034Sdougm 	    if (strcmp(protos[i], proto) == 0)
3153034Sdougm 		return (1);
3163034Sdougm 	return (0);
3173034Sdougm }
3183034Sdougm 
3193034Sdougm static int
3203034Sdougm sc_status(int flags, int argc, char *argv[])
3213034Sdougm {
3223034Sdougm 	char **protos;
3233034Sdougm 	int ret = SA_OK;
3243034Sdougm 	int c;
3253034Sdougm 	int i;
3263034Sdougm 	int num_proto;
3273034Sdougm 	int verbose = 0;
3283034Sdougm #ifdef lint
3293034Sdougm 	flags = flags;
3303034Sdougm #endif
3313034Sdougm 
3323034Sdougm 	while ((c = getopt(argc, argv, "?hv")) != EOF) {
3333034Sdougm 	    switch (c) {
3343034Sdougm 	    case 'v':
3353034Sdougm 		verbose++;
3363034Sdougm 		break;
3373034Sdougm 	    case '?':
3383034Sdougm 	    case 'h':
3393034Sdougm 		(void) printf(gettext("usage: %s\n"),
340*3393Sdougm 				sc_get_usage(USAGE_CTL_STATUS));
3413034Sdougm 		return (SA_OK);
3423034Sdougm 	    default:
3433034Sdougm 		(void) printf(gettext("usage: %s\n"),
344*3393Sdougm 				sc_get_usage(USAGE_CTL_STATUS));
3453034Sdougm 		return (SA_SYNTAX_ERR);
3463034Sdougm 	    }
3473034Sdougm 	}
3483034Sdougm 
3493034Sdougm 	num_proto = sa_get_protocols(&protos);
3503034Sdougm 	if (optind == argc) {
3513034Sdougm 	    /* status for all protocols */
3523034Sdougm 	    for (i = 0; i < num_proto; i++) {
3533034Sdougm 		show_status(protos[i]);
3543034Sdougm 	    }
3553034Sdougm 	} else {
3563034Sdougm 	    for (i = optind; i < argc; i++) {
3573034Sdougm 		if (valid_proto(protos, num_proto, argv[i])) {
3583034Sdougm 		    show_status(argv[i]);
3593034Sdougm 		} else {
3603034Sdougm 		    (void) printf(gettext("Invalid protocol: %s\n"), argv[i]);
3613034Sdougm 		    ret = SA_INVALID_PROTOCOL;
3623034Sdougm 		}
3633034Sdougm 	    }
3643034Sdougm 	}
3653034Sdougm 	if (protos != NULL)
3663034Sdougm 	    free(protos);
3673034Sdougm 	return (ret);
3683034Sdougm }
3693034Sdougm 
3703034Sdougm static sa_command_t commands[] = {
3713034Sdougm 	{"get", 0, sc_get, USAGE_CTL_GET},
3723034Sdougm 	{"set", 0, sc_set, USAGE_CTL_SET},
3733034Sdougm 	{"status", 0, sc_status, USAGE_CTL_STATUS},
3743034Sdougm 	{NULL, 0, NULL, 0},
3753034Sdougm };
3763034Sdougm 
3773034Sdougm void
3783034Sdougm sub_command_help(char *proto)
3793034Sdougm {
3803034Sdougm 	int i;
3813034Sdougm #ifdef lint
3823034Sdougm 	proto = proto;
3833034Sdougm #endif
3843034Sdougm 
3853034Sdougm 	(void) printf("\tsub-commands:\n");
3863034Sdougm 	for (i = 0; commands[i].cmdname != NULL; i++) {
3873034Sdougm 		if (!(commands[i].flags & (CMD_ALIAS|CMD_NODISPLAY)))
3883034Sdougm 			(void) printf("\t%s\n",
3893034Sdougm 				sc_get_usage((sc_usage_t)commands[i].cmdidx));
3903034Sdougm 	}
3913034Sdougm }
3923034Sdougm 
3933034Sdougm sa_command_t *
3943034Sdougm sa_lookup(char *cmd)
3953034Sdougm {
3963034Sdougm 	int i;
3973034Sdougm 	size_t len;
3983034Sdougm 
3993034Sdougm 	len = strlen(cmd);
4003034Sdougm 	for (i = 0; commands[i].cmdname != NULL; i++) {
4013034Sdougm 		if (strncmp(cmd, commands[i].cmdname, len) == 0)
4023034Sdougm 			return (&commands[i]);
4033034Sdougm 	}
4043034Sdougm 	return (NULL);
4053034Sdougm }
4063034Sdougm 
4073034Sdougm static int
4083034Sdougm run_command(char *command, int argc, char *argv[])
4093034Sdougm {
4103034Sdougm 	sa_command_t *cmdvec;
4113034Sdougm 	int ret;
4123034Sdougm 
4133034Sdougm 	/*
4143034Sdougm 	 * To get here, we know there should be a command due to the
4153034Sdougm 	 * preprocessing done earlier.  Need to find the protocol
4163034Sdougm 	 * that is being affected. If no protocol, then it is ALL
4173034Sdougm 	 * protocols.
4183034Sdougm 	 *
4193034Sdougm 	 * ??? do we really need the protocol at this level? it may be
4203034Sdougm 	 * sufficient to let the commands look it up if needed since
4213034Sdougm 	 * not all commands do proto specific things
4223034Sdougm 	 *
4233034Sdougm 	 * Known sub-commands are handled at this level. An unknown
4243034Sdougm 	 * command will be passed down to the shared object that
4253034Sdougm 	 * actually implements it. We can do this since the semantics
4263034Sdougm 	 * of the common sub-commands is well defined.
4273034Sdougm 	 */
4283034Sdougm 
4293034Sdougm 	cmdvec = sa_lookup(command);
4303034Sdougm 	if (cmdvec == NULL) {
4313034Sdougm 		(void) printf(gettext("command %s not found\n"), command);
4323034Sdougm 		exit(1);
4333034Sdougm 	}
4343034Sdougm 	/*
4353034Sdougm 	 * need to check priviledges and restrict what can be done
4363034Sdougm 	 * based on least priviledge and sub-command.
4373034Sdougm 	 */
4383034Sdougm 	ret = cmdvec->cmdfunc(NULL, argc, argv);
4393034Sdougm 	return (ret);
4403034Sdougm }
441