xref: /titanic_52/usr/src/cmd/dfs.cmds/sharectl/sharectl.c (revision 3472f5dc5f31b4385e87145cddb24ae3c94de14b)
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 /*
23*3472f5dcSdougm  * 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 
436185db85Sdougm static int run_command(char *, int, char **);
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;
606185db85Sdougm 
616185db85Sdougm 	/*
626185db85Sdougm 	 * make sure locale and gettext domain is setup
636185db85Sdougm 	 */
646185db85Sdougm 	(void) setlocale(LC_ALL, "");
656185db85Sdougm 	(void) textdomain(TEXT_DOMAIN);
666185db85Sdougm 
676185db85Sdougm 	sa_init(SA_INIT_CONTROL_API);
686185db85Sdougm 
696185db85Sdougm 	while ((c = getopt(argc, argv, "h?")) != EOF) {
706185db85Sdougm 	    switch (c) {
716185db85Sdougm 	    case '?':
726185db85Sdougm 	    case 'h':
736185db85Sdougm 		help = 1;
746185db85Sdougm 		break;
756185db85Sdougm 	    default:
766185db85Sdougm 		(void) printf(gettext("Invalid option: %c\n"), c);
776185db85Sdougm 	    }
786185db85Sdougm 	}
796185db85Sdougm 	if (optind == argc || help) {
806185db85Sdougm 	    /* no subcommand */
816185db85Sdougm 	    global_help();
826185db85Sdougm 	    exit(0);
836185db85Sdougm 	}
846185db85Sdougm 	optind = 1;
856185db85Sdougm 
866185db85Sdougm 	/*
876185db85Sdougm 	 * now have enough to parse rest of command line
886185db85Sdougm 	 */
896185db85Sdougm 	command = argv[optind];
906185db85Sdougm 	rval = run_command(command, argc - optind, argv + optind);
916185db85Sdougm 
926185db85Sdougm 	sa_fini();
936185db85Sdougm 	return (rval);
946185db85Sdougm }
956185db85Sdougm 
966185db85Sdougm char *
976185db85Sdougm sc_get_usage(sc_usage_t index)
986185db85Sdougm {
996185db85Sdougm 	char *ret = NULL;
1006185db85Sdougm 
1016185db85Sdougm 	switch (index) {
1026185db85Sdougm 	case USAGE_CTL_GET:
103*3472f5dcSdougm 	    ret = gettext("get [-h | -p property ...] proto");
1046185db85Sdougm 	    break;
1056185db85Sdougm 	case USAGE_CTL_SET:
1066185db85Sdougm 	    ret = gettext("set [-h] -p property=value ... proto");
1076185db85Sdougm 	    break;
1086185db85Sdougm 	case USAGE_CTL_STATUS:
109*3472f5dcSdougm 	    ret = gettext("status [-h | proto ...]");
1106185db85Sdougm 	    break;
1116185db85Sdougm 	}
1126185db85Sdougm 	return (ret);
1136185db85Sdougm }
1146185db85Sdougm 
1156185db85Sdougm static int
1166185db85Sdougm sc_get(int flags, int argc, char *argv[])
1176185db85Sdougm {
1186185db85Sdougm 	char *proto = NULL;
1196185db85Sdougm 	struct options *optlist = NULL;
1206185db85Sdougm 	int ret = SA_OK;
1216185db85Sdougm 	int c;
1226185db85Sdougm #ifdef lint
1236185db85Sdougm 	flags = flags;
1246185db85Sdougm #endif
1256185db85Sdougm 
1266185db85Sdougm 	while ((c = getopt(argc, argv, "?hp:")) != EOF) {
1276185db85Sdougm 	    switch (c) {
1286185db85Sdougm 	    case 'p':
1296185db85Sdougm 		ret = add_opt(&optlist, optarg, 1);
1306185db85Sdougm 		if (ret != SA_OK) {
1316185db85Sdougm 		    (void) printf(gettext("Problem with property: %s\n"),
1326185db85Sdougm 						optarg);
1336185db85Sdougm 		    return (SA_NO_MEMORY);
1346185db85Sdougm 		}
1356185db85Sdougm 		break;
1366185db85Sdougm 	    default:
1376185db85Sdougm 		(void) printf(gettext("usage: %s\n"),
1386185db85Sdougm 				sc_get_usage(USAGE_CTL_GET));
1396185db85Sdougm 		return (SA_SYNTAX_ERR);
1406185db85Sdougm 	    case '?':
1416185db85Sdougm 	    case 'h':
1426185db85Sdougm 		(void) printf(gettext("usage: %s\n"),
1436185db85Sdougm 				sc_get_usage(USAGE_CTL_GET));
1446185db85Sdougm 		return (SA_OK);
1456185db85Sdougm 		break;
1466185db85Sdougm 	    }
1476185db85Sdougm 	}
1486185db85Sdougm 
1496185db85Sdougm 	if (optind >= argc) {
1506185db85Sdougm 	    (void) printf(gettext("usage: %s\n"), 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 		if (optlist == NULL) {
1646185db85Sdougm 		    /* display all known properties for this protocol */
1656185db85Sdougm 		    for (prop = sa_get_protocol_property(propset, NULL);
1666185db85Sdougm 			prop != NULL;
1676185db85Sdougm 			prop = sa_get_next_protocol_property(prop)) {
1686185db85Sdougm 
1696185db85Sdougm 			/* get and display the property and value */
1706185db85Sdougm 			name = sa_get_property_attr(prop, "type");
1716185db85Sdougm 			if (name != NULL) {
1726185db85Sdougm 			    value = sa_get_property_attr(prop, "value");
1736185db85Sdougm 			    (void) printf(gettext("%s=%s\n"), name,
1746185db85Sdougm 						value != NULL ? value : "");
1756185db85Sdougm 			}
1766185db85Sdougm 			if (value != NULL)
1776185db85Sdougm 			    sa_free_attr_string(value);
1786185db85Sdougm 			if (name != NULL)
1796185db85Sdougm 			    sa_free_attr_string(name);
1806185db85Sdougm 		    }
1816185db85Sdougm 		} else {
1826185db85Sdougm 		    struct options *opt;
1836185db85Sdougm 		    /* list the specified option(s) */
1846185db85Sdougm 		    for (opt = optlist; opt != NULL; opt = opt->next) {
1856185db85Sdougm 			prop = sa_get_protocol_property(propset, opt->optname);
1866185db85Sdougm 			if (prop != NULL) {
1876185db85Sdougm 			    value = sa_get_property_attr(prop, "value");
1886185db85Sdougm 			    (void) printf(gettext("%s=%s\n"), opt->optname,
1896185db85Sdougm 					value != NULL ? value : "");
1906185db85Sdougm 			    sa_free_attr_string(value);
1916185db85Sdougm 			} else {
1926185db85Sdougm 			    (void) printf(gettext("%s: not defined\n"),
1936185db85Sdougm 						opt->optname);
194*3472f5dcSdougm 			    ret = SA_NO_SUCH_PROP;
1956185db85Sdougm 			}
1966185db85Sdougm 		    }
1976185db85Sdougm 		}
1986185db85Sdougm 	    }
1996185db85Sdougm 	} else {
2006185db85Sdougm 	    (void) printf(gettext("Invalid protocol specified: %s\n"), proto);
2016185db85Sdougm 	    ret = SA_INVALID_PROTOCOL;
2026185db85Sdougm 	}
2036185db85Sdougm 	return (ret);
2046185db85Sdougm }
2056185db85Sdougm 
2066185db85Sdougm static int
2076185db85Sdougm sc_set(int flags, int argc, char *argv[])
2086185db85Sdougm {
2096185db85Sdougm 	char *proto = NULL;
2106185db85Sdougm 	struct options *optlist = NULL;
2116185db85Sdougm 	int ret = SA_OK;
2126185db85Sdougm 	int c;
2136185db85Sdougm #ifdef lint
2146185db85Sdougm 	flags = flags;
2156185db85Sdougm #endif
2166185db85Sdougm 
2176185db85Sdougm 	while ((c = getopt(argc, argv, "?hp:")) != EOF) {
2186185db85Sdougm 	    switch (c) {
2196185db85Sdougm 	    case 'p':
2206185db85Sdougm 		ret = add_opt(&optlist, optarg, 0);
2216185db85Sdougm 		if (ret != SA_OK) {
2226185db85Sdougm 		    (void) printf(gettext("Problem with property: %s\n"),
2236185db85Sdougm 					optarg);
2246185db85Sdougm 		    return (SA_NO_MEMORY);
2256185db85Sdougm 		}
2266185db85Sdougm 		break;
2276185db85Sdougm 	    default:
2286185db85Sdougm 		(void) printf(gettext("usage: %s\n"),
2296185db85Sdougm 				sc_get_usage(USAGE_CTL_SET));
2306185db85Sdougm 		return (SA_SYNTAX_ERR);
2316185db85Sdougm 	    case '?':
2326185db85Sdougm 	    case 'h':
2336185db85Sdougm 		(void) printf(gettext("usage: %s\n"),
2346185db85Sdougm 				sc_get_usage(USAGE_CTL_SET));
2356185db85Sdougm 		return (SA_OK);
2366185db85Sdougm 		break;
2376185db85Sdougm 	    }
2386185db85Sdougm 	}
2396185db85Sdougm 
2406185db85Sdougm 	if (optind >= argc) {
2416185db85Sdougm 	    (void) printf(gettext("usage: %s\n"),
2426185db85Sdougm 				sc_get_usage(USAGE_CTL_SET));
2436185db85Sdougm 	    (void) printf(gettext("\tprotocol must be specified.\n"));
2446185db85Sdougm 	    return (SA_INVALID_PROTOCOL);
2456185db85Sdougm 	}
2466185db85Sdougm 
2476185db85Sdougm 	proto = argv[optind];
2486185db85Sdougm 	if (sa_valid_protocol(proto)) {
2496185db85Sdougm 	    sa_protocol_properties_t propset;
2506185db85Sdougm 	    propset = sa_proto_get_properties(proto);
2516185db85Sdougm 	    if (propset != NULL) {
2526185db85Sdougm 		sa_property_t prop;
253*3472f5dcSdougm 		int err;
2546185db85Sdougm 
2556185db85Sdougm 		if (optlist == NULL) {
2566185db85Sdougm 		    (void) printf(gettext("usage: %s\n"),
2576185db85Sdougm 				sc_get_usage(USAGE_CTL_SET));
2586185db85Sdougm 		    (void) printf(gettext("\tat least one property and value "
2596185db85Sdougm 				    "must be specified\n"));
2606185db85Sdougm 		} else {
2616185db85Sdougm 		    struct options *opt;
2626185db85Sdougm 		    /* list the specified option(s) */
2636185db85Sdougm 		    for (opt = optlist; opt != NULL; opt = opt->next) {
2646185db85Sdougm 			prop = sa_get_protocol_property(propset, opt->optname);
2656185db85Sdougm 			if (prop != NULL) {
266*3472f5dcSdougm 				/*
267*3472f5dcSdougm 				 * "err" is used in order to prevent
268*3472f5dcSdougm 				 * setting ret to SA_OK if there has
269*3472f5dcSdougm 				 * been a real error. We want to be
270*3472f5dcSdougm 				 * able to return an error status on
271*3472f5dcSdougm 				 * exit in that case. Error messages
272*3472f5dcSdougm 				 * are printed for each error, so we
273*3472f5dcSdougm 				 * only care on exit that there was an
274*3472f5dcSdougm 				 * error and not the specific error
275*3472f5dcSdougm 				 * value.
276*3472f5dcSdougm 				 */
277*3472f5dcSdougm 			    err = sa_set_protocol_property(prop, opt->optvalue);
278*3472f5dcSdougm 			    if (err != SA_OK) {
2796185db85Sdougm 				(void) printf(gettext("Could not set property"
2806185db85Sdougm 							" %s: %s\n"),
281*3472f5dcSdougm 					opt->optname, sa_errorstr(err));
282*3472f5dcSdougm 				ret = err;
2836185db85Sdougm 			    }
2846185db85Sdougm 			} else {
2856185db85Sdougm 			    (void) printf(gettext("%s: not defined\n"),
2866185db85Sdougm 						opt->optname);
287*3472f5dcSdougm 			    ret = SA_NO_SUCH_PROP;
2886185db85Sdougm 			}
2896185db85Sdougm 		    }
2906185db85Sdougm 		}
2916185db85Sdougm 	    }
2926185db85Sdougm 	} else {
2936185db85Sdougm 	    (void) printf(gettext("Invalid protocol specified: %s\n"), proto);
2946185db85Sdougm 	    ret = SA_INVALID_PROTOCOL;
2956185db85Sdougm 	}
2966185db85Sdougm 	return (ret);
2976185db85Sdougm }
2986185db85Sdougm 
2996185db85Sdougm static void
3006185db85Sdougm show_status(char *proto)
3016185db85Sdougm {
3026185db85Sdougm 	char *status;
3036185db85Sdougm 	status = sa_get_protocol_status(proto);
3046185db85Sdougm 	(void) printf("%s\t%s\n", proto, status ? gettext(status) : "-");
3056185db85Sdougm 	if (status != NULL)
3066185db85Sdougm 	    free(status);
3076185db85Sdougm }
3086185db85Sdougm 
3096185db85Sdougm static int
3106185db85Sdougm valid_proto(char **protos, int num, char *proto)
3116185db85Sdougm {
3126185db85Sdougm 	int i;
3136185db85Sdougm 	for (i = 0; i < num; i++)
3146185db85Sdougm 	    if (strcmp(protos[i], proto) == 0)
3156185db85Sdougm 		return (1);
3166185db85Sdougm 	return (0);
3176185db85Sdougm }
3186185db85Sdougm 
3196185db85Sdougm static int
3206185db85Sdougm sc_status(int flags, int argc, char *argv[])
3216185db85Sdougm {
3226185db85Sdougm 	char **protos;
3236185db85Sdougm 	int ret = SA_OK;
3246185db85Sdougm 	int c;
3256185db85Sdougm 	int i;
3266185db85Sdougm 	int num_proto;
3276185db85Sdougm 	int verbose = 0;
3286185db85Sdougm #ifdef lint
3296185db85Sdougm 	flags = flags;
3306185db85Sdougm #endif
3316185db85Sdougm 
3326185db85Sdougm 	while ((c = getopt(argc, argv, "?hv")) != EOF) {
3336185db85Sdougm 	    switch (c) {
3346185db85Sdougm 	    case 'v':
3356185db85Sdougm 		verbose++;
3366185db85Sdougm 		break;
3376185db85Sdougm 	    case '?':
3386185db85Sdougm 	    case 'h':
3396185db85Sdougm 		(void) printf(gettext("usage: %s\n"),
340*3472f5dcSdougm 				sc_get_usage(USAGE_CTL_STATUS));
3416185db85Sdougm 		return (SA_OK);
3426185db85Sdougm 	    default:
3436185db85Sdougm 		(void) printf(gettext("usage: %s\n"),
344*3472f5dcSdougm 				sc_get_usage(USAGE_CTL_STATUS));
3456185db85Sdougm 		return (SA_SYNTAX_ERR);
3466185db85Sdougm 	    }
3476185db85Sdougm 	}
3486185db85Sdougm 
3496185db85Sdougm 	num_proto = sa_get_protocols(&protos);
3506185db85Sdougm 	if (optind == argc) {
3516185db85Sdougm 	    /* status for all protocols */
3526185db85Sdougm 	    for (i = 0; i < num_proto; i++) {
3536185db85Sdougm 		show_status(protos[i]);
3546185db85Sdougm 	    }
3556185db85Sdougm 	} else {
3566185db85Sdougm 	    for (i = optind; i < argc; i++) {
3576185db85Sdougm 		if (valid_proto(protos, num_proto, argv[i])) {
3586185db85Sdougm 		    show_status(argv[i]);
3596185db85Sdougm 		} else {
3606185db85Sdougm 		    (void) printf(gettext("Invalid protocol: %s\n"), argv[i]);
3616185db85Sdougm 		    ret = SA_INVALID_PROTOCOL;
3626185db85Sdougm 		}
3636185db85Sdougm 	    }
3646185db85Sdougm 	}
3656185db85Sdougm 	if (protos != NULL)
3666185db85Sdougm 	    free(protos);
3676185db85Sdougm 	return (ret);
3686185db85Sdougm }
3696185db85Sdougm 
3706185db85Sdougm static sa_command_t commands[] = {
3716185db85Sdougm 	{"get", 0, sc_get, USAGE_CTL_GET},
3726185db85Sdougm 	{"set", 0, sc_set, USAGE_CTL_SET},
3736185db85Sdougm 	{"status", 0, sc_status, USAGE_CTL_STATUS},
3746185db85Sdougm 	{NULL, 0, NULL, 0},
3756185db85Sdougm };
3766185db85Sdougm 
3776185db85Sdougm void
3786185db85Sdougm sub_command_help(char *proto)
3796185db85Sdougm {
3806185db85Sdougm 	int i;
3816185db85Sdougm #ifdef lint
3826185db85Sdougm 	proto = proto;
3836185db85Sdougm #endif
3846185db85Sdougm 
3856185db85Sdougm 	(void) printf("\tsub-commands:\n");
3866185db85Sdougm 	for (i = 0; commands[i].cmdname != NULL; i++) {
3876185db85Sdougm 		if (!(commands[i].flags & (CMD_ALIAS|CMD_NODISPLAY)))
3886185db85Sdougm 			(void) printf("\t%s\n",
3896185db85Sdougm 				sc_get_usage((sc_usage_t)commands[i].cmdidx));
3906185db85Sdougm 	}
3916185db85Sdougm }
3926185db85Sdougm 
3936185db85Sdougm sa_command_t *
3946185db85Sdougm sa_lookup(char *cmd)
3956185db85Sdougm {
3966185db85Sdougm 	int i;
3976185db85Sdougm 	size_t len;
3986185db85Sdougm 
3996185db85Sdougm 	len = strlen(cmd);
4006185db85Sdougm 	for (i = 0; commands[i].cmdname != NULL; i++) {
4016185db85Sdougm 		if (strncmp(cmd, commands[i].cmdname, len) == 0)
4026185db85Sdougm 			return (&commands[i]);
4036185db85Sdougm 	}
4046185db85Sdougm 	return (NULL);
4056185db85Sdougm }
4066185db85Sdougm 
4076185db85Sdougm static int
4086185db85Sdougm run_command(char *command, int argc, char *argv[])
4096185db85Sdougm {
4106185db85Sdougm 	sa_command_t *cmdvec;
4116185db85Sdougm 	int ret;
4126185db85Sdougm 
4136185db85Sdougm 	/*
4146185db85Sdougm 	 * To get here, we know there should be a command due to the
4156185db85Sdougm 	 * preprocessing done earlier.  Need to find the protocol
4166185db85Sdougm 	 * that is being affected. If no protocol, then it is ALL
4176185db85Sdougm 	 * protocols.
4186185db85Sdougm 	 *
4196185db85Sdougm 	 * ??? do we really need the protocol at this level? it may be
4206185db85Sdougm 	 * sufficient to let the commands look it up if needed since
4216185db85Sdougm 	 * not all commands do proto specific things
4226185db85Sdougm 	 *
4236185db85Sdougm 	 * Known sub-commands are handled at this level. An unknown
4246185db85Sdougm 	 * command will be passed down to the shared object that
4256185db85Sdougm 	 * actually implements it. We can do this since the semantics
4266185db85Sdougm 	 * of the common sub-commands is well defined.
4276185db85Sdougm 	 */
4286185db85Sdougm 
4296185db85Sdougm 	cmdvec = sa_lookup(command);
4306185db85Sdougm 	if (cmdvec == NULL) {
4316185db85Sdougm 		(void) printf(gettext("command %s not found\n"), command);
4326185db85Sdougm 		exit(1);
4336185db85Sdougm 	}
4346185db85Sdougm 	/*
4356185db85Sdougm 	 * need to check priviledges and restrict what can be done
4366185db85Sdougm 	 * based on least priviledge and sub-command.
4376185db85Sdougm 	 */
4386185db85Sdougm 	ret = cmdvec->cmdfunc(NULL, argc, argv);
4396185db85Sdougm 	return (ret);
4406185db85Sdougm }
441