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