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