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 43*549ec3ffSdougm 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; 60*549ec3ffSdougm 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 68*549ec3ffSdougm 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]; 91*549ec3ffSdougm rval = run_command(command, argc - optind, argv + optind, handle); 926185db85Sdougm 93*549ec3ffSdougm 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 116*549ec3ffSdougm /*ARGSUSED*/ 1176185db85Sdougm static int 118*549ec3ffSdougm 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) { 1306185db85Sdougm (void) printf(gettext("Problem with property: %s\n"), 1316185db85Sdougm 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) { 1496185db85Sdougm (void) printf(gettext("usage: %s\n"), sc_get_usage(USAGE_CTL_GET)); 1506185db85Sdougm (void) printf(gettext("\tprotocol must be specified.\n")); 1516185db85Sdougm return (SA_INVALID_PROTOCOL); 1526185db85Sdougm } 1536185db85Sdougm 1546185db85Sdougm proto = argv[optind]; 1556185db85Sdougm if (sa_valid_protocol(proto)) { 1566185db85Sdougm sa_protocol_properties_t propset; 1576185db85Sdougm propset = sa_proto_get_properties(proto); 1586185db85Sdougm if (propset != NULL) { 1596185db85Sdougm sa_property_t prop; 1606185db85Sdougm char *value; 1616185db85Sdougm char *name; 1626185db85Sdougm if (optlist == NULL) { 1636185db85Sdougm /* display all known properties for this protocol */ 1646185db85Sdougm for (prop = sa_get_protocol_property(propset, NULL); 1656185db85Sdougm prop != NULL; 1666185db85Sdougm prop = sa_get_next_protocol_property(prop)) { 1676185db85Sdougm 1686185db85Sdougm /* get and display the property and value */ 1696185db85Sdougm name = sa_get_property_attr(prop, "type"); 1706185db85Sdougm if (name != NULL) { 1716185db85Sdougm value = sa_get_property_attr(prop, "value"); 1726185db85Sdougm (void) printf(gettext("%s=%s\n"), name, 1736185db85Sdougm value != NULL ? value : ""); 1746185db85Sdougm } 1756185db85Sdougm if (value != NULL) 1766185db85Sdougm sa_free_attr_string(value); 1776185db85Sdougm if (name != NULL) 1786185db85Sdougm sa_free_attr_string(name); 1796185db85Sdougm } 1806185db85Sdougm } else { 1816185db85Sdougm struct options *opt; 1826185db85Sdougm /* list the specified option(s) */ 1836185db85Sdougm for (opt = optlist; opt != NULL; opt = opt->next) { 1846185db85Sdougm prop = sa_get_protocol_property(propset, opt->optname); 1856185db85Sdougm if (prop != NULL) { 1866185db85Sdougm value = sa_get_property_attr(prop, "value"); 1876185db85Sdougm (void) printf(gettext("%s=%s\n"), opt->optname, 1886185db85Sdougm value != NULL ? value : ""); 1896185db85Sdougm sa_free_attr_string(value); 1906185db85Sdougm } else { 1916185db85Sdougm (void) printf(gettext("%s: not defined\n"), 1926185db85Sdougm opt->optname); 1933472f5dcSdougm ret = SA_NO_SUCH_PROP; 1946185db85Sdougm } 1956185db85Sdougm } 1966185db85Sdougm } 1976185db85Sdougm } 1986185db85Sdougm } else { 1996185db85Sdougm (void) printf(gettext("Invalid protocol specified: %s\n"), proto); 2006185db85Sdougm ret = SA_INVALID_PROTOCOL; 2016185db85Sdougm } 2026185db85Sdougm return (ret); 2036185db85Sdougm } 2046185db85Sdougm 205*549ec3ffSdougm /*ARGSUSED*/ 2066185db85Sdougm static int 207*549ec3ffSdougm sc_set(sa_handle_t handle, 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 2146185db85Sdougm while ((c = getopt(argc, argv, "?hp:")) != EOF) { 2156185db85Sdougm switch (c) { 2166185db85Sdougm case 'p': 2176185db85Sdougm ret = add_opt(&optlist, optarg, 0); 2186185db85Sdougm if (ret != SA_OK) { 2196185db85Sdougm (void) printf(gettext("Problem with property: %s\n"), 2206185db85Sdougm optarg); 2216185db85Sdougm return (SA_NO_MEMORY); 2226185db85Sdougm } 2236185db85Sdougm break; 2246185db85Sdougm default: 2256185db85Sdougm (void) printf(gettext("usage: %s\n"), 2266185db85Sdougm sc_get_usage(USAGE_CTL_SET)); 2276185db85Sdougm return (SA_SYNTAX_ERR); 2286185db85Sdougm case '?': 2296185db85Sdougm case 'h': 2306185db85Sdougm (void) printf(gettext("usage: %s\n"), 2316185db85Sdougm sc_get_usage(USAGE_CTL_SET)); 2326185db85Sdougm return (SA_OK); 2336185db85Sdougm break; 2346185db85Sdougm } 2356185db85Sdougm } 2366185db85Sdougm 2376185db85Sdougm if (optind >= argc) { 2386185db85Sdougm (void) printf(gettext("usage: %s\n"), 2396185db85Sdougm sc_get_usage(USAGE_CTL_SET)); 2406185db85Sdougm (void) printf(gettext("\tprotocol must be specified.\n")); 2416185db85Sdougm return (SA_INVALID_PROTOCOL); 2426185db85Sdougm } 2436185db85Sdougm 2446185db85Sdougm proto = argv[optind]; 2456185db85Sdougm if (sa_valid_protocol(proto)) { 2466185db85Sdougm sa_protocol_properties_t propset; 2476185db85Sdougm propset = sa_proto_get_properties(proto); 2486185db85Sdougm if (propset != NULL) { 2496185db85Sdougm sa_property_t prop; 2503472f5dcSdougm int err; 2516185db85Sdougm 2526185db85Sdougm if (optlist == NULL) { 2536185db85Sdougm (void) printf(gettext("usage: %s\n"), 2546185db85Sdougm sc_get_usage(USAGE_CTL_SET)); 2556185db85Sdougm (void) printf(gettext("\tat least one property and value " 2566185db85Sdougm "must be specified\n")); 2576185db85Sdougm } else { 2586185db85Sdougm struct options *opt; 2596185db85Sdougm /* list the specified option(s) */ 2606185db85Sdougm for (opt = optlist; opt != NULL; opt = opt->next) { 2616185db85Sdougm prop = sa_get_protocol_property(propset, opt->optname); 2626185db85Sdougm if (prop != NULL) { 2633472f5dcSdougm /* 2643472f5dcSdougm * "err" is used in order to prevent 2653472f5dcSdougm * setting ret to SA_OK if there has 2663472f5dcSdougm * been a real error. We want to be 2673472f5dcSdougm * able to return an error status on 2683472f5dcSdougm * exit in that case. Error messages 2693472f5dcSdougm * are printed for each error, so we 2703472f5dcSdougm * only care on exit that there was an 2713472f5dcSdougm * error and not the specific error 2723472f5dcSdougm * value. 2733472f5dcSdougm */ 2743472f5dcSdougm err = sa_set_protocol_property(prop, opt->optvalue); 2753472f5dcSdougm if (err != SA_OK) { 2766185db85Sdougm (void) printf(gettext("Could not set property" 2776185db85Sdougm " %s: %s\n"), 2783472f5dcSdougm opt->optname, sa_errorstr(err)); 2793472f5dcSdougm ret = err; 2806185db85Sdougm } 2816185db85Sdougm } else { 2826185db85Sdougm (void) printf(gettext("%s: not defined\n"), 2836185db85Sdougm opt->optname); 2843472f5dcSdougm ret = SA_NO_SUCH_PROP; 2856185db85Sdougm } 2866185db85Sdougm } 2876185db85Sdougm } 2886185db85Sdougm } 2896185db85Sdougm } else { 2906185db85Sdougm (void) printf(gettext("Invalid protocol specified: %s\n"), proto); 2916185db85Sdougm ret = SA_INVALID_PROTOCOL; 2926185db85Sdougm } 2936185db85Sdougm return (ret); 2946185db85Sdougm } 2956185db85Sdougm 2966185db85Sdougm static void 2976185db85Sdougm show_status(char *proto) 2986185db85Sdougm { 2996185db85Sdougm char *status; 3006185db85Sdougm status = sa_get_protocol_status(proto); 3016185db85Sdougm (void) printf("%s\t%s\n", proto, status ? gettext(status) : "-"); 3026185db85Sdougm if (status != NULL) 3036185db85Sdougm free(status); 3046185db85Sdougm } 3056185db85Sdougm 3066185db85Sdougm static int 3076185db85Sdougm valid_proto(char **protos, int num, char *proto) 3086185db85Sdougm { 3096185db85Sdougm int i; 3106185db85Sdougm for (i = 0; i < num; i++) 3116185db85Sdougm if (strcmp(protos[i], proto) == 0) 3126185db85Sdougm return (1); 3136185db85Sdougm return (0); 3146185db85Sdougm } 3156185db85Sdougm 316*549ec3ffSdougm /*ARGSUSED*/ 3176185db85Sdougm static int 318*549ec3ffSdougm sc_status(sa_handle_t handle, int flags, int argc, char *argv[]) 3196185db85Sdougm { 3206185db85Sdougm char **protos; 3216185db85Sdougm int ret = SA_OK; 3226185db85Sdougm int c; 3236185db85Sdougm int i; 3246185db85Sdougm int num_proto; 3256185db85Sdougm int verbose = 0; 3266185db85Sdougm 3276185db85Sdougm while ((c = getopt(argc, argv, "?hv")) != EOF) { 3286185db85Sdougm switch (c) { 3296185db85Sdougm case 'v': 3306185db85Sdougm verbose++; 3316185db85Sdougm break; 3326185db85Sdougm case '?': 3336185db85Sdougm case 'h': 3346185db85Sdougm (void) printf(gettext("usage: %s\n"), 3353472f5dcSdougm sc_get_usage(USAGE_CTL_STATUS)); 3366185db85Sdougm return (SA_OK); 3376185db85Sdougm default: 3386185db85Sdougm (void) printf(gettext("usage: %s\n"), 3393472f5dcSdougm sc_get_usage(USAGE_CTL_STATUS)); 3406185db85Sdougm return (SA_SYNTAX_ERR); 3416185db85Sdougm } 3426185db85Sdougm } 3436185db85Sdougm 3446185db85Sdougm num_proto = sa_get_protocols(&protos); 3456185db85Sdougm if (optind == argc) { 3466185db85Sdougm /* status for all protocols */ 3476185db85Sdougm for (i = 0; i < num_proto; i++) { 3486185db85Sdougm show_status(protos[i]); 3496185db85Sdougm } 3506185db85Sdougm } else { 3516185db85Sdougm for (i = optind; i < argc; i++) { 3526185db85Sdougm if (valid_proto(protos, num_proto, argv[i])) { 3536185db85Sdougm show_status(argv[i]); 3546185db85Sdougm } else { 3556185db85Sdougm (void) printf(gettext("Invalid protocol: %s\n"), argv[i]); 3566185db85Sdougm ret = SA_INVALID_PROTOCOL; 3576185db85Sdougm } 3586185db85Sdougm } 3596185db85Sdougm } 3606185db85Sdougm if (protos != NULL) 3616185db85Sdougm free(protos); 3626185db85Sdougm return (ret); 3636185db85Sdougm } 3646185db85Sdougm 3656185db85Sdougm static sa_command_t commands[] = { 3666185db85Sdougm {"get", 0, sc_get, USAGE_CTL_GET}, 3676185db85Sdougm {"set", 0, sc_set, USAGE_CTL_SET}, 3686185db85Sdougm {"status", 0, sc_status, USAGE_CTL_STATUS}, 3696185db85Sdougm {NULL, 0, NULL, 0}, 3706185db85Sdougm }; 3716185db85Sdougm 372*549ec3ffSdougm /*ARGSUSED*/ 3736185db85Sdougm void 3746185db85Sdougm sub_command_help(char *proto) 3756185db85Sdougm { 3766185db85Sdougm int i; 3776185db85Sdougm 3786185db85Sdougm (void) printf("\tsub-commands:\n"); 3796185db85Sdougm for (i = 0; commands[i].cmdname != NULL; i++) { 3806185db85Sdougm if (!(commands[i].flags & (CMD_ALIAS|CMD_NODISPLAY))) 3816185db85Sdougm (void) printf("\t%s\n", 3826185db85Sdougm sc_get_usage((sc_usage_t)commands[i].cmdidx)); 3836185db85Sdougm } 3846185db85Sdougm } 3856185db85Sdougm 3866185db85Sdougm sa_command_t * 3876185db85Sdougm sa_lookup(char *cmd) 3886185db85Sdougm { 3896185db85Sdougm int i; 3906185db85Sdougm size_t len; 3916185db85Sdougm 3926185db85Sdougm len = strlen(cmd); 3936185db85Sdougm for (i = 0; commands[i].cmdname != NULL; i++) { 3946185db85Sdougm if (strncmp(cmd, commands[i].cmdname, len) == 0) 3956185db85Sdougm return (&commands[i]); 3966185db85Sdougm } 3976185db85Sdougm return (NULL); 3986185db85Sdougm } 3996185db85Sdougm 4006185db85Sdougm static int 401*549ec3ffSdougm run_command(char *command, int argc, char *argv[], sa_handle_t handle) 4026185db85Sdougm { 4036185db85Sdougm sa_command_t *cmdvec; 4046185db85Sdougm int ret; 4056185db85Sdougm 4066185db85Sdougm /* 4076185db85Sdougm * To get here, we know there should be a command due to the 4086185db85Sdougm * preprocessing done earlier. Need to find the protocol 4096185db85Sdougm * that is being affected. If no protocol, then it is ALL 4106185db85Sdougm * protocols. 4116185db85Sdougm * 4126185db85Sdougm * ??? do we really need the protocol at this level? it may be 4136185db85Sdougm * sufficient to let the commands look it up if needed since 4146185db85Sdougm * not all commands do proto specific things 4156185db85Sdougm * 4166185db85Sdougm * Known sub-commands are handled at this level. An unknown 4176185db85Sdougm * command will be passed down to the shared object that 4186185db85Sdougm * actually implements it. We can do this since the semantics 4196185db85Sdougm * of the common sub-commands is well defined. 4206185db85Sdougm */ 4216185db85Sdougm 4226185db85Sdougm cmdvec = sa_lookup(command); 4236185db85Sdougm if (cmdvec == NULL) { 4246185db85Sdougm (void) printf(gettext("command %s not found\n"), command); 4256185db85Sdougm exit(1); 4266185db85Sdougm } 4276185db85Sdougm /* 4286185db85Sdougm * need to check priviledges and restrict what can be done 4296185db85Sdougm * based on least priviledge and sub-command. 4306185db85Sdougm */ 431*549ec3ffSdougm ret = cmdvec->cmdfunc(handle, NULL, argc, argv); 4326185db85Sdougm return (ret); 4336185db85Sdougm } 434