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