13034Sdougm /* 23034Sdougm * CDDL HEADER START 33034Sdougm * 43034Sdougm * The contents of this file are subject to the terms of the 53034Sdougm * Common Development and Distribution License (the "License"). 63034Sdougm * You may not use this file except in compliance with the License. 73034Sdougm * 83034Sdougm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93034Sdougm * or http://www.opensolaris.org/os/licensing. 103034Sdougm * See the License for the specific language governing permissions 113034Sdougm * and limitations under the License. 123034Sdougm * 133034Sdougm * When distributing Covered Code, include this CDDL HEADER in each 143034Sdougm * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153034Sdougm * If applicable, add the following below this CDDL HEADER, with the 163034Sdougm * fields enclosed by brackets "[]" replaced with your own identifying 173034Sdougm * information: Portions Copyright [yyyy] [name of copyright owner] 183034Sdougm * 193034Sdougm * CDDL HEADER END 203034Sdougm */ 213034Sdougm 223034Sdougm /* 23*6007Sthurlow * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 243034Sdougm * Use is subject to license terms. 253034Sdougm */ 263034Sdougm 273034Sdougm #pragma ident "%Z%%M% %I% %E% SMI" 283034Sdougm 293034Sdougm #include <stdlib.h> 303034Sdougm #include <stdio.h> 313034Sdougm #include <string.h> 323034Sdougm #include <ctype.h> 333034Sdougm #include <unistd.h> 343034Sdougm #include <getopt.h> 353034Sdougm #include <libgen.h> 363034Sdougm 373034Sdougm #include "libshare.h" 383034Sdougm #include <sharemgr.h> 393034Sdougm 403034Sdougm #include <libintl.h> 413034Sdougm #include <locale.h> 423034Sdougm 433910Sdougm static int run_command(char *, int, char **, sa_handle_t); 443034Sdougm static void sub_command_help(char *proto); 453034Sdougm 463034Sdougm static void 473034Sdougm global_help() 483034Sdougm { 493034Sdougm (void) printf(gettext("usage: sharectl <command> [options]\n")); 503034Sdougm sub_command_help(NULL); 513034Sdougm } 523034Sdougm 533034Sdougm int 543034Sdougm main(int argc, char *argv[]) 553034Sdougm { 563034Sdougm int c; 573034Sdougm int help = 0; 583034Sdougm int rval; 593034Sdougm char *command; 603910Sdougm sa_handle_t handle; 613034Sdougm 623034Sdougm /* 633034Sdougm * make sure locale and gettext domain is setup 643034Sdougm */ 653034Sdougm (void) setlocale(LC_ALL, ""); 663034Sdougm (void) textdomain(TEXT_DOMAIN); 673034Sdougm 683910Sdougm handle = sa_init(SA_INIT_CONTROL_API); 693034Sdougm 703034Sdougm while ((c = getopt(argc, argv, "h?")) != EOF) { 714653Sdougm switch (c) { 724653Sdougm case '?': 734653Sdougm case 'h': 744653Sdougm help = 1; 754653Sdougm break; 764653Sdougm default: 774653Sdougm (void) printf(gettext("Invalid option: %c\n"), c); 784653Sdougm } 793034Sdougm } 803034Sdougm if (optind == argc || help) { 814653Sdougm /* no subcommand */ 824653Sdougm global_help(); 834653Sdougm exit(0); 843034Sdougm } 853034Sdougm optind = 1; 863034Sdougm 873034Sdougm /* 883034Sdougm * now have enough to parse rest of command line 893034Sdougm */ 903034Sdougm command = argv[optind]; 913910Sdougm rval = run_command(command, argc - optind, argv + optind, handle); 923034Sdougm 933910Sdougm sa_fini(handle); 943034Sdougm return (rval); 953034Sdougm } 963034Sdougm 973034Sdougm char * 983034Sdougm sc_get_usage(sc_usage_t index) 993034Sdougm { 1003034Sdougm char *ret = NULL; 1013034Sdougm 1023034Sdougm switch (index) { 1033034Sdougm case USAGE_CTL_GET: 1044653Sdougm ret = gettext("get [-h | -p property ...] proto"); 1054653Sdougm break; 1063034Sdougm case USAGE_CTL_SET: 1074653Sdougm ret = gettext("set [-h] -p property=value ... proto"); 1084653Sdougm break; 1093034Sdougm case USAGE_CTL_STATUS: 1104653Sdougm ret = gettext("status [-h | proto ...]"); 1114653Sdougm break; 112*6007Sthurlow case USAGE_CTL_DELSECT: 113*6007Sthurlow ret = gettext("delsect [-h] section proto"); 114*6007Sthurlow break; 1153034Sdougm } 1163034Sdougm return (ret); 1173034Sdougm } 1183034Sdougm 1193910Sdougm /*ARGSUSED*/ 1203034Sdougm static int 1213910Sdougm sc_get(sa_handle_t handle, int flags, int argc, char *argv[]) 1223034Sdougm { 1233034Sdougm char *proto = NULL; 1243034Sdougm struct options *optlist = NULL; 1253034Sdougm int ret = SA_OK; 1263034Sdougm int c; 127*6007Sthurlow sa_protocol_properties_t propset, propsect; 128*6007Sthurlow sa_property_t prop; 129*6007Sthurlow char *section, *value, *name; 130*6007Sthurlow int first = 1; 1313034Sdougm 1323034Sdougm while ((c = getopt(argc, argv, "?hp:")) != EOF) { 1334653Sdougm switch (c) { 1344653Sdougm case 'p': 1354653Sdougm ret = add_opt(&optlist, optarg, 1); 1364653Sdougm if (ret != SA_OK) { 1374653Sdougm (void) printf(gettext( 1384653Sdougm "Problem with property: %s\n"), optarg); 1394653Sdougm return (SA_NO_MEMORY); 1404653Sdougm } 1414653Sdougm break; 1424653Sdougm default: 1434653Sdougm (void) printf(gettext("usage: %s\n"), 1444653Sdougm sc_get_usage(USAGE_CTL_GET)); 1454653Sdougm return (SA_SYNTAX_ERR); 1464653Sdougm case '?': 1474653Sdougm case 'h': 1484653Sdougm (void) printf(gettext("usage: %s\n"), 1494653Sdougm sc_get_usage(USAGE_CTL_GET)); 1504653Sdougm return (SA_OK); 1514653Sdougm break; 1523034Sdougm } 1533034Sdougm } 1543034Sdougm 1553034Sdougm if (optind >= argc) { 1564653Sdougm (void) printf(gettext("usage: %s\n"), 1574653Sdougm sc_get_usage(USAGE_CTL_GET)); 1584653Sdougm (void) printf(gettext("\tprotocol must be specified.\n")); 1594653Sdougm return (SA_INVALID_PROTOCOL); 1603034Sdougm } 1613034Sdougm 1623034Sdougm proto = argv[optind]; 163*6007Sthurlow if (!sa_valid_protocol(proto)) { 164*6007Sthurlow (void) printf(gettext("Invalid protocol specified: %s\n"), 165*6007Sthurlow proto); 166*6007Sthurlow return (SA_INVALID_PROTOCOL); 167*6007Sthurlow } 168*6007Sthurlow propset = sa_proto_get_properties(proto); 169*6007Sthurlow if (propset == NULL) 170*6007Sthurlow return (ret); 1713034Sdougm 172*6007Sthurlow if (optlist == NULL) { 173*6007Sthurlow /* Display all known properties for this protocol */ 174*6007Sthurlow for (propsect = sa_get_protocol_section(propset, NULL); 175*6007Sthurlow propsect != NULL; 176*6007Sthurlow propsect = sa_get_next_protocol_section(propsect, NULL)) { 177*6007Sthurlow section = sa_get_property_attr(propsect, 178*6007Sthurlow "name"); 179*6007Sthurlow /* 180*6007Sthurlow * If properties are organized into sections, as 181*6007Sthurlow * in the SMB client, print the section name. 182*6007Sthurlow */ 183*6007Sthurlow if (sa_proto_get_featureset(proto) & 184*6007Sthurlow SA_FEATURE_HAS_SECTIONS) { 185*6007Sthurlow if (!first) 186*6007Sthurlow (void) printf("\n"); 187*6007Sthurlow first = 0; 188*6007Sthurlow (void) printf("[%s]\n", section); 189*6007Sthurlow } 190*6007Sthurlow /* Display properties for this section */ 191*6007Sthurlow for (prop = sa_get_protocol_property(propsect, NULL); 192*6007Sthurlow prop != NULL; 193*6007Sthurlow prop = sa_get_next_protocol_property(prop, NULL)) { 194*6007Sthurlow 195*6007Sthurlow /* get and display the property and value */ 196*6007Sthurlow name = sa_get_property_attr(prop, "type"); 197*6007Sthurlow if (name != NULL) { 198*6007Sthurlow value = sa_get_property_attr(prop, 199*6007Sthurlow "value"); 200*6007Sthurlow (void) printf(gettext("%s=%s\n"), name, 201*6007Sthurlow value != NULL ? value : ""); 2024653Sdougm } 203*6007Sthurlow if (value != NULL) 204*6007Sthurlow sa_free_attr_string(value); 205*6007Sthurlow if (name != NULL) 206*6007Sthurlow sa_free_attr_string(name); 2073034Sdougm } 2083034Sdougm } 2093034Sdougm } else { 210*6007Sthurlow struct options *opt; 211*6007Sthurlow 212*6007Sthurlow /* list the specified option(s) */ 213*6007Sthurlow for (opt = optlist; opt != NULL; opt = opt->next) { 214*6007Sthurlow int printed = 0; 215*6007Sthurlow 216*6007Sthurlow for (propsect = sa_get_protocol_section(propset, NULL); 217*6007Sthurlow propsect != NULL; 218*6007Sthurlow propsect = sa_get_next_protocol_section(propsect, 219*6007Sthurlow NULL)) { 220*6007Sthurlow 221*6007Sthurlow section = sa_get_property_attr(propsect, 222*6007Sthurlow "name"); 223*6007Sthurlow for (prop = sa_get_protocol_property(propsect, 224*6007Sthurlow opt->optname); 225*6007Sthurlow prop != NULL; 226*6007Sthurlow prop = sa_get_next_protocol_property( 227*6007Sthurlow propsect, opt->optname)) { 228*6007Sthurlow value = sa_get_property_attr(prop, 229*6007Sthurlow "value"); 230*6007Sthurlow if (sa_proto_get_featureset(proto) & 231*6007Sthurlow SA_FEATURE_HAS_SECTIONS) { 232*6007Sthurlow (void) printf( 233*6007Sthurlow gettext("[%s] %s=%s\n"), 234*6007Sthurlow section, opt->optname, 235*6007Sthurlow value != NULL ? value : ""); 236*6007Sthurlow sa_free_attr_string(section); 237*6007Sthurlow } else { 238*6007Sthurlow (void) printf( 239*6007Sthurlow gettext("%s=%s\n"), 240*6007Sthurlow opt->optname, 241*6007Sthurlow value != NULL ? value : ""); 242*6007Sthurlow } 243*6007Sthurlow sa_free_attr_string(value); 244*6007Sthurlow printed = 1; 245*6007Sthurlow } 246*6007Sthurlow } 247*6007Sthurlow if (!printed) { 248*6007Sthurlow (void) printf(gettext("%s: not defined\n"), 249*6007Sthurlow opt->optname); 250*6007Sthurlow ret = SA_NO_SUCH_PROP; 251*6007Sthurlow } 252*6007Sthurlow } 2533034Sdougm } 2543034Sdougm return (ret); 2553034Sdougm } 2563034Sdougm 2573910Sdougm /*ARGSUSED*/ 2583034Sdougm static int 2593910Sdougm sc_set(sa_handle_t handle, int flags, int argc, char *argv[]) 2603034Sdougm { 2613034Sdougm char *proto = NULL; 2623034Sdougm struct options *optlist = NULL; 263*6007Sthurlow sa_protocol_properties_t propsect; 2643034Sdougm int ret = SA_OK; 2653034Sdougm int c; 266*6007Sthurlow int err; 2674653Sdougm sa_protocol_properties_t propset; 268*6007Sthurlow sa_property_t prop; 2693034Sdougm 2703034Sdougm while ((c = getopt(argc, argv, "?hp:")) != EOF) { 2714653Sdougm switch (c) { 2724653Sdougm case 'p': 2734653Sdougm ret = add_opt(&optlist, optarg, 0); 2744653Sdougm if (ret != SA_OK) { 2754653Sdougm (void) printf(gettext( 2764653Sdougm "Problem with property: %s\n"), optarg); 2774653Sdougm return (SA_NO_MEMORY); 2784653Sdougm } 2794653Sdougm break; 2804653Sdougm default: 2814653Sdougm (void) printf(gettext("usage: %s\n"), 2824653Sdougm sc_get_usage(USAGE_CTL_SET)); 2834653Sdougm return (SA_SYNTAX_ERR); 2844653Sdougm case '?': 2854653Sdougm case 'h': 2864653Sdougm (void) printf(gettext("usage: %s\n"), 2874653Sdougm sc_get_usage(USAGE_CTL_SET)); 2884653Sdougm return (SA_OK); 2894653Sdougm break; 2903034Sdougm } 2913034Sdougm } 2923034Sdougm 2933034Sdougm if (optind >= argc) { 2944653Sdougm (void) printf(gettext("usage: %s\n"), 2954653Sdougm sc_get_usage(USAGE_CTL_SET)); 2964653Sdougm (void) printf(gettext("\tprotocol must be specified.\n")); 2974653Sdougm return (SA_INVALID_PROTOCOL); 2983034Sdougm } 2993034Sdougm 3003034Sdougm proto = argv[optind]; 3014653Sdougm if (!sa_valid_protocol(proto)) { 3024653Sdougm (void) printf(gettext("Invalid protocol specified: %s\n"), 3034653Sdougm proto); 3044653Sdougm return (SA_INVALID_PROTOCOL); 3054653Sdougm } 3064653Sdougm propset = sa_proto_get_properties(proto); 307*6007Sthurlow if (propset == NULL) 308*6007Sthurlow return (ret); 309*6007Sthurlow 310*6007Sthurlow if (optlist == NULL) { 311*6007Sthurlow (void) printf(gettext("usage: %s\n"), 312*6007Sthurlow sc_get_usage(USAGE_CTL_SET)); 313*6007Sthurlow (void) printf(gettext( 314*6007Sthurlow "\tat least one property and value " 315*6007Sthurlow "must be specified\n")); 316*6007Sthurlow } else { 317*6007Sthurlow struct options *opt; 318*6007Sthurlow char *section = NULL; 319*6007Sthurlow /* fetch and change the specified option(s) */ 320*6007Sthurlow for (opt = optlist; opt != NULL; opt = opt->next) { 321*6007Sthurlow if (strncmp("section", opt->optname, 7) == 0) { 322*6007Sthurlow if (section != NULL) 323*6007Sthurlow free(section); 324*6007Sthurlow section = strdup(opt->optvalue); 325*6007Sthurlow continue; 326*6007Sthurlow } 327*6007Sthurlow if (sa_proto_get_featureset(proto) & 328*6007Sthurlow SA_FEATURE_HAS_SECTIONS) { 329*6007Sthurlow propsect = sa_get_protocol_section(propset, 330*6007Sthurlow section); 331*6007Sthurlow prop = sa_get_protocol_property(propsect, 332*6007Sthurlow opt->optname); 333*6007Sthurlow } else { 334*6007Sthurlow prop = sa_get_protocol_property(propset, 335*6007Sthurlow opt->optname); 336*6007Sthurlow } 337*6007Sthurlow if (prop == NULL && sa_proto_get_featureset(proto) & 338*6007Sthurlow SA_FEATURE_ADD_PROPERTIES) { 339*6007Sthurlow sa_property_t sect; 340*6007Sthurlow sect = sa_create_section(section, NULL); 341*6007Sthurlow sa_set_section_attr(sect, "type", proto); 342*6007Sthurlow (void) sa_add_protocol_property(propset, sect); 343*6007Sthurlow prop = sa_create_property( 344*6007Sthurlow opt->optname, opt->optvalue); 345*6007Sthurlow (void) sa_add_protocol_property(sect, prop); 346*6007Sthurlow } 347*6007Sthurlow if (prop != NULL) { 348*6007Sthurlow /* 349*6007Sthurlow * "err" is used in order to prevent 350*6007Sthurlow * setting ret to SA_OK if there has 351*6007Sthurlow * been a real error. We want to be 352*6007Sthurlow * able to return an error status on 353*6007Sthurlow * exit in that case. Error messages 354*6007Sthurlow * are printed for each error, so we 355*6007Sthurlow * only care on exit that there was an 356*6007Sthurlow * error and not the specific error 357*6007Sthurlow * value. 358*6007Sthurlow */ 359*6007Sthurlow err = sa_set_protocol_property(prop, section, 360*6007Sthurlow opt->optvalue); 361*6007Sthurlow if (err != SA_OK) { 3624653Sdougm (void) printf(gettext( 363*6007Sthurlow "Could not set property" 364*6007Sthurlow " %s: %s\n"), 365*6007Sthurlow opt->optname, sa_errorstr(err)); 366*6007Sthurlow ret = err; 3674653Sdougm } 368*6007Sthurlow } else { 369*6007Sthurlow (void) printf(gettext("%s: not defined\n"), 370*6007Sthurlow opt->optname); 371*6007Sthurlow ret = SA_NO_SUCH_PROP; 3723034Sdougm } 3733034Sdougm } 3743034Sdougm } 3753034Sdougm return (ret); 3763034Sdougm } 3773034Sdougm 3783034Sdougm static void 3793034Sdougm show_status(char *proto) 3803034Sdougm { 3813034Sdougm char *status; 3824653Sdougm 3833034Sdougm status = sa_get_protocol_status(proto); 3843034Sdougm (void) printf("%s\t%s\n", proto, status ? gettext(status) : "-"); 3853034Sdougm if (status != NULL) 3864653Sdougm free(status); 3873034Sdougm } 3883034Sdougm 3893034Sdougm static int 3903034Sdougm valid_proto(char **protos, int num, char *proto) 3913034Sdougm { 3923034Sdougm int i; 3933034Sdougm for (i = 0; i < num; i++) 3944653Sdougm if (strcmp(protos[i], proto) == 0) 3954653Sdougm return (1); 3963034Sdougm return (0); 3973034Sdougm } 3983034Sdougm 3993910Sdougm /*ARGSUSED*/ 4003034Sdougm static int 4013910Sdougm sc_status(sa_handle_t handle, int flags, int argc, char *argv[]) 4023034Sdougm { 4033034Sdougm char **protos; 4043034Sdougm int ret = SA_OK; 4053034Sdougm int c; 4063034Sdougm int i; 4073034Sdougm int num_proto; 4083034Sdougm int verbose = 0; 4093034Sdougm 4103034Sdougm while ((c = getopt(argc, argv, "?hv")) != EOF) { 4114653Sdougm switch (c) { 4124653Sdougm case 'v': 4134653Sdougm verbose++; 4144653Sdougm break; 4154653Sdougm case '?': 4164653Sdougm case 'h': 4174653Sdougm (void) printf(gettext("usage: %s\n"), 4184653Sdougm sc_get_usage(USAGE_CTL_STATUS)); 4194653Sdougm return (SA_OK); 4204653Sdougm default: 4214653Sdougm (void) printf(gettext("usage: %s\n"), 4224653Sdougm sc_get_usage(USAGE_CTL_STATUS)); 4234653Sdougm return (SA_SYNTAX_ERR); 4244653Sdougm } 4253034Sdougm } 4263034Sdougm 4273034Sdougm num_proto = sa_get_protocols(&protos); 4283034Sdougm if (optind == argc) { 4294653Sdougm /* status for all protocols */ 4304653Sdougm for (i = 0; i < num_proto; i++) { 4314653Sdougm show_status(protos[i]); 4324653Sdougm } 4333034Sdougm } else { 4344653Sdougm for (i = optind; i < argc; i++) { 4354653Sdougm if (valid_proto(protos, num_proto, argv[i])) { 4364653Sdougm show_status(argv[i]); 4374653Sdougm } else { 4384653Sdougm (void) printf(gettext("Invalid protocol: %s\n"), 4394653Sdougm argv[i]); 4404653Sdougm ret = SA_INVALID_PROTOCOL; 4414653Sdougm } 4423034Sdougm } 4433034Sdougm } 4443034Sdougm if (protos != NULL) 4454653Sdougm free(protos); 4463034Sdougm return (ret); 4473034Sdougm } 4483034Sdougm 449*6007Sthurlow /*ARGSUSED*/ 450*6007Sthurlow static int 451*6007Sthurlow sc_delsect(sa_handle_t handle, int flags, int argc, char *argv[]) 452*6007Sthurlow { 453*6007Sthurlow char *proto = NULL; 454*6007Sthurlow char *section = NULL; 455*6007Sthurlow sa_protocol_properties_t propset; 456*6007Sthurlow sa_protocol_properties_t propsect; 457*6007Sthurlow int ret = SA_OK; 458*6007Sthurlow int c; 459*6007Sthurlow 460*6007Sthurlow while ((c = getopt(argc, argv, "?h")) != EOF) { 461*6007Sthurlow switch (c) { 462*6007Sthurlow default: 463*6007Sthurlow ret = SA_SYNTAX_ERR; 464*6007Sthurlow /*FALLTHROUGH*/ 465*6007Sthurlow case '?': 466*6007Sthurlow case 'h': 467*6007Sthurlow (void) printf(gettext("usage: %s\n"), 468*6007Sthurlow sc_get_usage(USAGE_CTL_DELSECT)); 469*6007Sthurlow return (ret); 470*6007Sthurlow } 471*6007Sthurlow /*NOTREACHED*/ 472*6007Sthurlow } 473*6007Sthurlow 474*6007Sthurlow section = argv[optind++]; 475*6007Sthurlow 476*6007Sthurlow if (optind >= argc) { 477*6007Sthurlow (void) printf(gettext("usage: %s\n"), 478*6007Sthurlow sc_get_usage(USAGE_CTL_DELSECT)); 479*6007Sthurlow (void) printf(gettext( 480*6007Sthurlow "\tsection and protocol must be specified.\n")); 481*6007Sthurlow return (SA_INVALID_PROTOCOL); 482*6007Sthurlow } 483*6007Sthurlow 484*6007Sthurlow proto = argv[optind]; 485*6007Sthurlow if (!sa_valid_protocol(proto)) { 486*6007Sthurlow (void) printf(gettext("Invalid protocol specified: %s\n"), 487*6007Sthurlow proto); 488*6007Sthurlow return (SA_INVALID_PROTOCOL); 489*6007Sthurlow } 490*6007Sthurlow 491*6007Sthurlow if ((sa_proto_get_featureset(proto) & SA_FEATURE_HAS_SECTIONS) == 0) { 492*6007Sthurlow (void) printf(gettext("Protocol %s does not have sections\n"), 493*6007Sthurlow section, proto); 494*6007Sthurlow return (SA_NOT_SUPPORTED); 495*6007Sthurlow } 496*6007Sthurlow 497*6007Sthurlow propset = sa_proto_get_properties(proto); 498*6007Sthurlow if (propset == NULL) { 499*6007Sthurlow (void) printf(gettext("Cannot get properties for %s\n"), 500*6007Sthurlow proto); 501*6007Sthurlow return (SA_NO_PROPERTIES); 502*6007Sthurlow } 503*6007Sthurlow 504*6007Sthurlow propsect = sa_get_protocol_section(propset, section); 505*6007Sthurlow if (propsect == NULL) { 506*6007Sthurlow (void) printf(gettext("Cannot find section %s for proto %s\n"), 507*6007Sthurlow section, proto); 508*6007Sthurlow return (SA_NO_SUCH_SECTION); 509*6007Sthurlow } 510*6007Sthurlow 511*6007Sthurlow ret = sa_proto_delete_section(proto, section); 512*6007Sthurlow 513*6007Sthurlow return (ret); 514*6007Sthurlow } 515*6007Sthurlow 5163034Sdougm static sa_command_t commands[] = { 5173034Sdougm {"get", 0, sc_get, USAGE_CTL_GET}, 5183034Sdougm {"set", 0, sc_set, USAGE_CTL_SET}, 5193034Sdougm {"status", 0, sc_status, USAGE_CTL_STATUS}, 520*6007Sthurlow {"delsect", 0, sc_delsect, USAGE_CTL_DELSECT}, 5213034Sdougm {NULL, 0, NULL, 0}, 5223034Sdougm }; 5233034Sdougm 5243910Sdougm /*ARGSUSED*/ 5253034Sdougm void 5263034Sdougm sub_command_help(char *proto) 5273034Sdougm { 5283034Sdougm int i; 5293034Sdougm 5303034Sdougm (void) printf("\tsub-commands:\n"); 5313034Sdougm for (i = 0; commands[i].cmdname != NULL; i++) { 5323034Sdougm if (!(commands[i].flags & (CMD_ALIAS|CMD_NODISPLAY))) 5333034Sdougm (void) printf("\t%s\n", 5344653Sdougm sc_get_usage((sc_usage_t)commands[i].cmdidx)); 5353034Sdougm } 5363034Sdougm } 5373034Sdougm 5383034Sdougm sa_command_t * 5393034Sdougm sa_lookup(char *cmd) 5403034Sdougm { 5413034Sdougm int i; 5423034Sdougm size_t len; 5433034Sdougm 5443034Sdougm len = strlen(cmd); 5453034Sdougm for (i = 0; commands[i].cmdname != NULL; i++) { 5463034Sdougm if (strncmp(cmd, commands[i].cmdname, len) == 0) 5473034Sdougm return (&commands[i]); 5483034Sdougm } 5493034Sdougm return (NULL); 5503034Sdougm } 5513034Sdougm 5523034Sdougm static int 5533910Sdougm run_command(char *command, int argc, char *argv[], sa_handle_t handle) 5543034Sdougm { 5553034Sdougm sa_command_t *cmdvec; 5563034Sdougm int ret; 5573034Sdougm 5583034Sdougm /* 5593034Sdougm * To get here, we know there should be a command due to the 5603034Sdougm * preprocessing done earlier. Need to find the protocol 5613034Sdougm * that is being affected. If no protocol, then it is ALL 5623034Sdougm * protocols. 5633034Sdougm * 5643034Sdougm * ??? do we really need the protocol at this level? it may be 5653034Sdougm * sufficient to let the commands look it up if needed since 5663034Sdougm * not all commands do proto specific things 5673034Sdougm * 5683034Sdougm * Known sub-commands are handled at this level. An unknown 5693034Sdougm * command will be passed down to the shared object that 5703034Sdougm * actually implements it. We can do this since the semantics 5713034Sdougm * of the common sub-commands is well defined. 5723034Sdougm */ 5733034Sdougm 5743034Sdougm cmdvec = sa_lookup(command); 5753034Sdougm if (cmdvec == NULL) { 5763034Sdougm (void) printf(gettext("command %s not found\n"), command); 5773034Sdougm exit(1); 5783034Sdougm } 5793034Sdougm /* 5803034Sdougm * need to check priviledges and restrict what can be done 5813034Sdougm * based on least priviledge and sub-command. 5823034Sdougm */ 5833910Sdougm ret = cmdvec->cmdfunc(handle, NULL, argc, argv); 5843034Sdougm return (ret); 5853034Sdougm } 586