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