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