1*6185db85Sdougm /* 2*6185db85Sdougm * CDDL HEADER START 3*6185db85Sdougm * 4*6185db85Sdougm * The contents of this file are subject to the terms of the 5*6185db85Sdougm * Common Development and Distribution License (the "License"). 6*6185db85Sdougm * You may not use this file except in compliance with the License. 7*6185db85Sdougm * 8*6185db85Sdougm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6185db85Sdougm * or http://www.opensolaris.org/os/licensing. 10*6185db85Sdougm * See the License for the specific language governing permissions 11*6185db85Sdougm * and limitations under the License. 12*6185db85Sdougm * 13*6185db85Sdougm * When distributing Covered Code, include this CDDL HEADER in each 14*6185db85Sdougm * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6185db85Sdougm * If applicable, add the following below this CDDL HEADER, with the 16*6185db85Sdougm * fields enclosed by brackets "[]" replaced with your own identifying 17*6185db85Sdougm * information: Portions Copyright [yyyy] [name of copyright owner] 18*6185db85Sdougm * 19*6185db85Sdougm * CDDL HEADER END 20*6185db85Sdougm */ 21*6185db85Sdougm 22*6185db85Sdougm /* 23*6185db85Sdougm * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*6185db85Sdougm * Use is subject to license terms. 25*6185db85Sdougm */ 26*6185db85Sdougm 27*6185db85Sdougm #pragma ident "%Z%%M% %I% %E% SMI" 28*6185db85Sdougm 29*6185db85Sdougm #include <stdlib.h> 30*6185db85Sdougm #include <stdio.h> 31*6185db85Sdougm #include <string.h> 32*6185db85Sdougm #include <ctype.h> 33*6185db85Sdougm #include <unistd.h> 34*6185db85Sdougm #include <getopt.h> 35*6185db85Sdougm #include <libgen.h> 36*6185db85Sdougm 37*6185db85Sdougm #include "libshare.h" 38*6185db85Sdougm #include <sharemgr.h> 39*6185db85Sdougm 40*6185db85Sdougm #include <libintl.h> 41*6185db85Sdougm #include <locale.h> 42*6185db85Sdougm 43*6185db85Sdougm static int run_command(char *, int, char **); 44*6185db85Sdougm static void sub_command_help(char *proto); 45*6185db85Sdougm 46*6185db85Sdougm static void 47*6185db85Sdougm global_help() 48*6185db85Sdougm { 49*6185db85Sdougm (void) printf(gettext("usage: sharectl <command> [options]\n")); 50*6185db85Sdougm sub_command_help(NULL); 51*6185db85Sdougm } 52*6185db85Sdougm 53*6185db85Sdougm int 54*6185db85Sdougm main(int argc, char *argv[]) 55*6185db85Sdougm { 56*6185db85Sdougm int c; 57*6185db85Sdougm int help = 0; 58*6185db85Sdougm int rval; 59*6185db85Sdougm char *command; 60*6185db85Sdougm 61*6185db85Sdougm /* 62*6185db85Sdougm * make sure locale and gettext domain is setup 63*6185db85Sdougm */ 64*6185db85Sdougm (void) setlocale(LC_ALL, ""); 65*6185db85Sdougm (void) textdomain(TEXT_DOMAIN); 66*6185db85Sdougm 67*6185db85Sdougm sa_init(SA_INIT_CONTROL_API); 68*6185db85Sdougm 69*6185db85Sdougm while ((c = getopt(argc, argv, "h?")) != EOF) { 70*6185db85Sdougm switch (c) { 71*6185db85Sdougm case '?': 72*6185db85Sdougm case 'h': 73*6185db85Sdougm help = 1; 74*6185db85Sdougm break; 75*6185db85Sdougm default: 76*6185db85Sdougm (void) printf(gettext("Invalid option: %c\n"), c); 77*6185db85Sdougm } 78*6185db85Sdougm } 79*6185db85Sdougm if (optind == argc || help) { 80*6185db85Sdougm /* no subcommand */ 81*6185db85Sdougm global_help(); 82*6185db85Sdougm exit(0); 83*6185db85Sdougm } 84*6185db85Sdougm optind = 1; 85*6185db85Sdougm 86*6185db85Sdougm /* 87*6185db85Sdougm * now have enough to parse rest of command line 88*6185db85Sdougm */ 89*6185db85Sdougm command = argv[optind]; 90*6185db85Sdougm rval = run_command(command, argc - optind, argv + optind); 91*6185db85Sdougm 92*6185db85Sdougm sa_fini(); 93*6185db85Sdougm return (rval); 94*6185db85Sdougm } 95*6185db85Sdougm 96*6185db85Sdougm char * 97*6185db85Sdougm sc_get_usage(sc_usage_t index) 98*6185db85Sdougm { 99*6185db85Sdougm char *ret = NULL; 100*6185db85Sdougm 101*6185db85Sdougm switch (index) { 102*6185db85Sdougm case USAGE_CTL_GET: 103*6185db85Sdougm ret = gettext("get [-h] -p property ... proto"); 104*6185db85Sdougm break; 105*6185db85Sdougm case USAGE_CTL_SET: 106*6185db85Sdougm ret = gettext("set [-h] -p property=value ... proto"); 107*6185db85Sdougm break; 108*6185db85Sdougm case USAGE_CTL_STATUS: 109*6185db85Sdougm ret = gettext("status -h | proto..."); 110*6185db85Sdougm break; 111*6185db85Sdougm } 112*6185db85Sdougm return (ret); 113*6185db85Sdougm } 114*6185db85Sdougm 115*6185db85Sdougm static int 116*6185db85Sdougm sc_get(int flags, int argc, char *argv[]) 117*6185db85Sdougm { 118*6185db85Sdougm char *proto = NULL; 119*6185db85Sdougm struct options *optlist = NULL; 120*6185db85Sdougm int ret = SA_OK; 121*6185db85Sdougm int c; 122*6185db85Sdougm #ifdef lint 123*6185db85Sdougm flags = flags; 124*6185db85Sdougm #endif 125*6185db85Sdougm 126*6185db85Sdougm while ((c = getopt(argc, argv, "?hp:")) != EOF) { 127*6185db85Sdougm switch (c) { 128*6185db85Sdougm case 'p': 129*6185db85Sdougm ret = add_opt(&optlist, optarg, 1); 130*6185db85Sdougm if (ret != SA_OK) { 131*6185db85Sdougm (void) printf(gettext("Problem with property: %s\n"), 132*6185db85Sdougm optarg); 133*6185db85Sdougm return (SA_NO_MEMORY); 134*6185db85Sdougm } 135*6185db85Sdougm break; 136*6185db85Sdougm default: 137*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 138*6185db85Sdougm sc_get_usage(USAGE_CTL_GET)); 139*6185db85Sdougm return (SA_SYNTAX_ERR); 140*6185db85Sdougm case '?': 141*6185db85Sdougm case 'h': 142*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 143*6185db85Sdougm sc_get_usage(USAGE_CTL_GET)); 144*6185db85Sdougm return (SA_OK); 145*6185db85Sdougm break; 146*6185db85Sdougm } 147*6185db85Sdougm } 148*6185db85Sdougm 149*6185db85Sdougm if (optind >= argc) { 150*6185db85Sdougm (void) printf(gettext("usage: %s\n"), sc_get_usage(USAGE_CTL_GET)); 151*6185db85Sdougm (void) printf(gettext("\tprotocol must be specified.\n")); 152*6185db85Sdougm return (SA_INVALID_PROTOCOL); 153*6185db85Sdougm } 154*6185db85Sdougm 155*6185db85Sdougm proto = argv[optind]; 156*6185db85Sdougm if (sa_valid_protocol(proto)) { 157*6185db85Sdougm sa_protocol_properties_t propset; 158*6185db85Sdougm propset = sa_proto_get_properties(proto); 159*6185db85Sdougm if (propset != NULL) { 160*6185db85Sdougm sa_property_t prop; 161*6185db85Sdougm char *value; 162*6185db85Sdougm char *name; 163*6185db85Sdougm if (optlist == NULL) { 164*6185db85Sdougm /* display all known properties for this protocol */ 165*6185db85Sdougm for (prop = sa_get_protocol_property(propset, NULL); 166*6185db85Sdougm prop != NULL; 167*6185db85Sdougm prop = sa_get_next_protocol_property(prop)) { 168*6185db85Sdougm 169*6185db85Sdougm /* get and display the property and value */ 170*6185db85Sdougm name = sa_get_property_attr(prop, "type"); 171*6185db85Sdougm if (name != NULL) { 172*6185db85Sdougm value = sa_get_property_attr(prop, "value"); 173*6185db85Sdougm (void) printf(gettext("%s=%s\n"), name, 174*6185db85Sdougm value != NULL ? value : ""); 175*6185db85Sdougm } 176*6185db85Sdougm if (value != NULL) 177*6185db85Sdougm sa_free_attr_string(value); 178*6185db85Sdougm if (name != NULL) 179*6185db85Sdougm sa_free_attr_string(name); 180*6185db85Sdougm } 181*6185db85Sdougm } else { 182*6185db85Sdougm struct options *opt; 183*6185db85Sdougm /* list the specified option(s) */ 184*6185db85Sdougm for (opt = optlist; opt != NULL; opt = opt->next) { 185*6185db85Sdougm prop = sa_get_protocol_property(propset, opt->optname); 186*6185db85Sdougm if (prop != NULL) { 187*6185db85Sdougm value = sa_get_property_attr(prop, "value"); 188*6185db85Sdougm (void) printf(gettext("%s=%s\n"), opt->optname, 189*6185db85Sdougm value != NULL ? value : ""); 190*6185db85Sdougm sa_free_attr_string(value); 191*6185db85Sdougm } else { 192*6185db85Sdougm (void) printf(gettext("%s: not defined\n"), 193*6185db85Sdougm opt->optname); 194*6185db85Sdougm } 195*6185db85Sdougm } 196*6185db85Sdougm } 197*6185db85Sdougm } 198*6185db85Sdougm } else { 199*6185db85Sdougm (void) printf(gettext("Invalid protocol specified: %s\n"), proto); 200*6185db85Sdougm ret = SA_INVALID_PROTOCOL; 201*6185db85Sdougm } 202*6185db85Sdougm return (ret); 203*6185db85Sdougm } 204*6185db85Sdougm 205*6185db85Sdougm static int 206*6185db85Sdougm sc_set(int flags, int argc, char *argv[]) 207*6185db85Sdougm { 208*6185db85Sdougm char *proto = NULL; 209*6185db85Sdougm struct options *optlist = NULL; 210*6185db85Sdougm int ret = SA_OK; 211*6185db85Sdougm int c; 212*6185db85Sdougm #ifdef lint 213*6185db85Sdougm flags = flags; 214*6185db85Sdougm #endif 215*6185db85Sdougm 216*6185db85Sdougm while ((c = getopt(argc, argv, "?hp:")) != EOF) { 217*6185db85Sdougm switch (c) { 218*6185db85Sdougm case 'p': 219*6185db85Sdougm ret = add_opt(&optlist, optarg, 0); 220*6185db85Sdougm if (ret != SA_OK) { 221*6185db85Sdougm (void) printf(gettext("Problem with property: %s\n"), 222*6185db85Sdougm optarg); 223*6185db85Sdougm return (SA_NO_MEMORY); 224*6185db85Sdougm } 225*6185db85Sdougm break; 226*6185db85Sdougm default: 227*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 228*6185db85Sdougm sc_get_usage(USAGE_CTL_SET)); 229*6185db85Sdougm return (SA_SYNTAX_ERR); 230*6185db85Sdougm case '?': 231*6185db85Sdougm case 'h': 232*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 233*6185db85Sdougm sc_get_usage(USAGE_CTL_SET)); 234*6185db85Sdougm return (SA_OK); 235*6185db85Sdougm break; 236*6185db85Sdougm } 237*6185db85Sdougm } 238*6185db85Sdougm 239*6185db85Sdougm if (optind >= argc) { 240*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 241*6185db85Sdougm sc_get_usage(USAGE_CTL_SET)); 242*6185db85Sdougm (void) printf(gettext("\tprotocol must be specified.\n")); 243*6185db85Sdougm return (SA_INVALID_PROTOCOL); 244*6185db85Sdougm } 245*6185db85Sdougm 246*6185db85Sdougm proto = argv[optind]; 247*6185db85Sdougm if (sa_valid_protocol(proto)) { 248*6185db85Sdougm sa_protocol_properties_t propset; 249*6185db85Sdougm propset = sa_proto_get_properties(proto); 250*6185db85Sdougm if (propset != NULL) { 251*6185db85Sdougm sa_property_t prop; 252*6185db85Sdougm 253*6185db85Sdougm if (optlist == NULL) { 254*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 255*6185db85Sdougm sc_get_usage(USAGE_CTL_SET)); 256*6185db85Sdougm (void) printf(gettext("\tat least one property and value " 257*6185db85Sdougm "must be specified\n")); 258*6185db85Sdougm } else { 259*6185db85Sdougm struct options *opt; 260*6185db85Sdougm /* list the specified option(s) */ 261*6185db85Sdougm for (opt = optlist; opt != NULL; opt = opt->next) { 262*6185db85Sdougm prop = sa_get_protocol_property(propset, opt->optname); 263*6185db85Sdougm if (prop != NULL) { 264*6185db85Sdougm ret = sa_set_protocol_property(prop, opt->optvalue); 265*6185db85Sdougm if (ret != SA_OK) { 266*6185db85Sdougm (void) printf(gettext("Could not set property" 267*6185db85Sdougm " %s: %s\n"), 268*6185db85Sdougm opt->optname, sa_errorstr(ret)); 269*6185db85Sdougm } 270*6185db85Sdougm } else { 271*6185db85Sdougm (void) printf(gettext("%s: not defined\n"), 272*6185db85Sdougm opt->optname); 273*6185db85Sdougm } 274*6185db85Sdougm } 275*6185db85Sdougm } 276*6185db85Sdougm } 277*6185db85Sdougm } else { 278*6185db85Sdougm (void) printf(gettext("Invalid protocol specified: %s\n"), proto); 279*6185db85Sdougm ret = SA_INVALID_PROTOCOL; 280*6185db85Sdougm } 281*6185db85Sdougm return (ret); 282*6185db85Sdougm } 283*6185db85Sdougm 284*6185db85Sdougm static void 285*6185db85Sdougm show_status(char *proto) 286*6185db85Sdougm { 287*6185db85Sdougm char *status; 288*6185db85Sdougm status = sa_get_protocol_status(proto); 289*6185db85Sdougm (void) printf("%s\t%s\n", proto, status ? gettext(status) : "-"); 290*6185db85Sdougm if (status != NULL) 291*6185db85Sdougm free(status); 292*6185db85Sdougm } 293*6185db85Sdougm 294*6185db85Sdougm static int 295*6185db85Sdougm valid_proto(char **protos, int num, char *proto) 296*6185db85Sdougm { 297*6185db85Sdougm int i; 298*6185db85Sdougm for (i = 0; i < num; i++) 299*6185db85Sdougm if (strcmp(protos[i], proto) == 0) 300*6185db85Sdougm return (1); 301*6185db85Sdougm return (0); 302*6185db85Sdougm } 303*6185db85Sdougm 304*6185db85Sdougm static int 305*6185db85Sdougm sc_status(int flags, int argc, char *argv[]) 306*6185db85Sdougm { 307*6185db85Sdougm char **protos; 308*6185db85Sdougm int ret = SA_OK; 309*6185db85Sdougm int c; 310*6185db85Sdougm int i; 311*6185db85Sdougm int num_proto; 312*6185db85Sdougm int verbose = 0; 313*6185db85Sdougm #ifdef lint 314*6185db85Sdougm flags = flags; 315*6185db85Sdougm #endif 316*6185db85Sdougm 317*6185db85Sdougm while ((c = getopt(argc, argv, "?hv")) != EOF) { 318*6185db85Sdougm switch (c) { 319*6185db85Sdougm case 'v': 320*6185db85Sdougm verbose++; 321*6185db85Sdougm break; 322*6185db85Sdougm case '?': 323*6185db85Sdougm case 'h': 324*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 325*6185db85Sdougm sc_get_usage(USAGE_CTL_SET)); 326*6185db85Sdougm return (SA_OK); 327*6185db85Sdougm default: 328*6185db85Sdougm (void) printf(gettext("usage: %s\n"), 329*6185db85Sdougm sc_get_usage(USAGE_CTL_SET)); 330*6185db85Sdougm return (SA_SYNTAX_ERR); 331*6185db85Sdougm } 332*6185db85Sdougm } 333*6185db85Sdougm 334*6185db85Sdougm num_proto = sa_get_protocols(&protos); 335*6185db85Sdougm if (optind == argc) { 336*6185db85Sdougm /* status for all protocols */ 337*6185db85Sdougm for (i = 0; i < num_proto; i++) { 338*6185db85Sdougm show_status(protos[i]); 339*6185db85Sdougm } 340*6185db85Sdougm } else { 341*6185db85Sdougm for (i = optind; i < argc; i++) { 342*6185db85Sdougm if (valid_proto(protos, num_proto, argv[i])) { 343*6185db85Sdougm show_status(argv[i]); 344*6185db85Sdougm } else { 345*6185db85Sdougm (void) printf(gettext("Invalid protocol: %s\n"), argv[i]); 346*6185db85Sdougm ret = SA_INVALID_PROTOCOL; 347*6185db85Sdougm } 348*6185db85Sdougm } 349*6185db85Sdougm } 350*6185db85Sdougm if (protos != NULL) 351*6185db85Sdougm free(protos); 352*6185db85Sdougm return (ret); 353*6185db85Sdougm } 354*6185db85Sdougm 355*6185db85Sdougm static sa_command_t commands[] = { 356*6185db85Sdougm {"get", 0, sc_get, USAGE_CTL_GET}, 357*6185db85Sdougm {"set", 0, sc_set, USAGE_CTL_SET}, 358*6185db85Sdougm {"status", 0, sc_status, USAGE_CTL_STATUS}, 359*6185db85Sdougm {NULL, 0, NULL, 0}, 360*6185db85Sdougm }; 361*6185db85Sdougm 362*6185db85Sdougm void 363*6185db85Sdougm sub_command_help(char *proto) 364*6185db85Sdougm { 365*6185db85Sdougm int i; 366*6185db85Sdougm #ifdef lint 367*6185db85Sdougm proto = proto; 368*6185db85Sdougm #endif 369*6185db85Sdougm 370*6185db85Sdougm (void) printf("\tsub-commands:\n"); 371*6185db85Sdougm for (i = 0; commands[i].cmdname != NULL; i++) { 372*6185db85Sdougm if (!(commands[i].flags & (CMD_ALIAS|CMD_NODISPLAY))) 373*6185db85Sdougm (void) printf("\t%s\n", 374*6185db85Sdougm sc_get_usage((sc_usage_t)commands[i].cmdidx)); 375*6185db85Sdougm } 376*6185db85Sdougm } 377*6185db85Sdougm 378*6185db85Sdougm sa_command_t * 379*6185db85Sdougm sa_lookup(char *cmd) 380*6185db85Sdougm { 381*6185db85Sdougm int i; 382*6185db85Sdougm size_t len; 383*6185db85Sdougm 384*6185db85Sdougm len = strlen(cmd); 385*6185db85Sdougm for (i = 0; commands[i].cmdname != NULL; i++) { 386*6185db85Sdougm if (strncmp(cmd, commands[i].cmdname, len) == 0) 387*6185db85Sdougm return (&commands[i]); 388*6185db85Sdougm } 389*6185db85Sdougm return (NULL); 390*6185db85Sdougm } 391*6185db85Sdougm 392*6185db85Sdougm static int 393*6185db85Sdougm run_command(char *command, int argc, char *argv[]) 394*6185db85Sdougm { 395*6185db85Sdougm sa_command_t *cmdvec; 396*6185db85Sdougm int ret; 397*6185db85Sdougm 398*6185db85Sdougm /* 399*6185db85Sdougm * To get here, we know there should be a command due to the 400*6185db85Sdougm * preprocessing done earlier. Need to find the protocol 401*6185db85Sdougm * that is being affected. If no protocol, then it is ALL 402*6185db85Sdougm * protocols. 403*6185db85Sdougm * 404*6185db85Sdougm * ??? do we really need the protocol at this level? it may be 405*6185db85Sdougm * sufficient to let the commands look it up if needed since 406*6185db85Sdougm * not all commands do proto specific things 407*6185db85Sdougm * 408*6185db85Sdougm * Known sub-commands are handled at this level. An unknown 409*6185db85Sdougm * command will be passed down to the shared object that 410*6185db85Sdougm * actually implements it. We can do this since the semantics 411*6185db85Sdougm * of the common sub-commands is well defined. 412*6185db85Sdougm */ 413*6185db85Sdougm 414*6185db85Sdougm cmdvec = sa_lookup(command); 415*6185db85Sdougm if (cmdvec == NULL) { 416*6185db85Sdougm (void) printf(gettext("command %s not found\n"), command); 417*6185db85Sdougm exit(1); 418*6185db85Sdougm } 419*6185db85Sdougm /* 420*6185db85Sdougm * need to check priviledges and restrict what can be done 421*6185db85Sdougm * based on least priviledge and sub-command. 422*6185db85Sdougm */ 423*6185db85Sdougm ret = cmdvec->cmdfunc(NULL, argc, argv); 424*6185db85Sdougm return (ret); 425*6185db85Sdougm } 426