4935 sharectl(1m): Missing documentation for delsect subcommand
[unleashed.git] / usr / src / cmd / dfs.cmds / sharectl / sharectl.c
blob9698a8a14767ee1d240791464cdaff9a247f612d
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2012 Milan Jurik. All rights reserved.
26 * Copyright 2016 Nexenta Systems, Inc.
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>
37 #include "libshare.h"
38 #include <sharemgr.h>
40 #include <libintl.h>
41 #include <locale.h>
43 static int run_command(char *, int, char **, sa_handle_t);
44 static void sub_command_help(char *proto);
46 static void
47 global_help()
49 (void) printf(gettext("usage: sharectl <subcommand> [<options>]\n"));
50 sub_command_help(NULL);
53 int
54 main(int argc, char *argv[])
56 int c;
57 int help = 0;
58 int rval;
59 char *command;
60 sa_handle_t handle;
63 * make sure locale and gettext domain is setup
65 (void) setlocale(LC_ALL, "");
66 (void) textdomain(TEXT_DOMAIN);
68 handle = sa_init(SA_INIT_CONTROL_API);
70 while ((c = getopt(argc, argv, "h?")) != EOF) {
71 switch (c) {
72 case '?':
73 case 'h':
74 help = 1;
75 break;
76 default:
77 (void) printf(gettext("Invalid option: %c\n"), c);
80 if (optind == argc || help) {
81 /* no subcommand */
82 global_help();
83 exit(0);
85 optind = 1;
88 * now have enough to parse rest of command line
90 command = argv[optind];
91 rval = run_command(command, argc - optind, argv + optind, handle);
93 sa_fini(handle);
94 return (rval);
97 char *
98 sc_get_usage(sc_usage_t index)
100 char *ret = NULL;
102 switch (index) {
103 case USAGE_CTL_DELSECT:
104 ret = gettext("delsect\t<section> <proto>");
105 break;
106 case USAGE_CTL_GET:
107 ret = gettext("get\t[-p <property>]... <proto>");
108 break;
109 case USAGE_CTL_SET:
110 ret = gettext("set\t{-p <property>=<value>}... <proto>");
111 break;
112 case USAGE_CTL_STATUS:
113 ret = gettext("status\t[<proto>]...");
114 break;
116 return (ret);
119 /*ARGSUSED*/
120 static int
121 sc_get(sa_handle_t handle, int flags, int argc, char *argv[])
123 char *proto = NULL;
124 struct options *optlist = NULL;
125 int ret = SA_OK;
126 int c;
127 sa_protocol_properties_t propset, propsect;
128 sa_property_t prop;
129 char *section, *value, *name;
130 int first = 1;
132 while ((c = getopt(argc, argv, "?hp:")) != EOF) {
133 switch (c) {
134 case 'p':
135 ret = add_opt(&optlist, optarg, 1);
136 if (ret != SA_OK) {
137 (void) printf(gettext(
138 "Problem with property: %s\n"), optarg);
139 return (SA_NO_MEMORY);
141 break;
142 default:
143 (void) printf(gettext("usage: %s\n"),
144 sc_get_usage(USAGE_CTL_GET));
145 return (SA_SYNTAX_ERR);
146 case '?':
147 case 'h':
148 (void) printf(gettext("usage: %s\n"),
149 sc_get_usage(USAGE_CTL_GET));
150 return (SA_OK);
154 if (optind >= argc) {
155 (void) printf(gettext("usage: %s\n"),
156 sc_get_usage(USAGE_CTL_GET));
157 (void) printf(gettext("\tprotocol must be specified.\n"));
158 return (SA_INVALID_PROTOCOL);
161 proto = argv[optind];
162 if (!sa_valid_protocol(proto)) {
163 (void) printf(gettext("Invalid protocol specified: %s\n"),
164 proto);
165 return (SA_INVALID_PROTOCOL);
167 propset = sa_proto_get_properties(proto);
168 if (propset == NULL)
169 return (ret);
171 if (optlist == NULL) {
172 /* Display all known properties for this protocol */
173 for (propsect = sa_get_protocol_section(propset, NULL);
174 propsect != NULL;
175 propsect = sa_get_next_protocol_section(propsect, NULL)) {
176 section = sa_get_property_attr(propsect,
177 "name");
179 * If properties are organized into sections, as
180 * in the SMB client, print the section name.
182 if (sa_proto_get_featureset(proto) &
183 SA_FEATURE_HAS_SECTIONS) {
184 if (!first)
185 (void) printf("\n");
186 first = 0;
187 (void) printf("[%s]\n",
188 section != NULL ? section : "");
190 if (section != NULL)
191 sa_free_attr_string(section);
193 /* Display properties for this section */
194 for (prop = sa_get_protocol_property(propsect, NULL);
195 prop != NULL;
196 prop = sa_get_next_protocol_property(prop, NULL)) {
198 /* get and display the property and value */
199 name = sa_get_property_attr(prop, "type");
200 if (name != NULL) {
201 value = sa_get_property_attr(prop,
202 "value");
203 (void) printf(gettext("%s=%s\n"), name,
204 value != NULL ? value : "");
206 if (value != NULL)
207 sa_free_attr_string(value);
208 if (name != NULL)
209 sa_free_attr_string(name);
212 } else {
213 struct options *opt;
215 /* list the specified option(s) */
216 for (opt = optlist; opt != NULL; opt = opt->next) {
217 int printed = 0;
219 for (propsect = sa_get_protocol_section(propset, NULL);
220 propsect != NULL;
221 propsect = sa_get_next_protocol_section(propsect,
222 NULL)) {
224 section = sa_get_property_attr(propsect,
225 "name");
226 for (prop = sa_get_protocol_property(propsect,
227 opt->optname);
228 prop != NULL;
229 prop = sa_get_next_protocol_property(
230 propsect, opt->optname)) {
231 value = sa_get_property_attr(prop,
232 "value");
233 if (sa_proto_get_featureset(proto) &
234 SA_FEATURE_HAS_SECTIONS) {
235 (void) printf(
236 gettext("[%s] %s=%s\n"),
237 section != NULL ?
238 section : "", opt->optname,
239 value != NULL ? value : "");
240 } else {
241 (void) printf(
242 gettext("%s=%s\n"),
243 opt->optname,
244 value != NULL ? value : "");
246 if (value != NULL)
247 sa_free_attr_string(value);
248 printed = 1;
250 if (section != NULL)
251 sa_free_attr_string(section);
253 if (!printed) {
254 (void) printf(gettext("%s: not defined\n"),
255 opt->optname);
256 ret = SA_NO_SUCH_PROP;
260 return (ret);
263 /*ARGSUSED*/
264 static int
265 sc_set(sa_handle_t handle, int flags, int argc, char *argv[])
267 char *proto = NULL;
268 struct options *optlist = NULL;
269 sa_protocol_properties_t propsect;
270 int ret = SA_OK;
271 int c;
272 int err;
273 sa_protocol_properties_t propset;
274 sa_property_t prop;
276 while ((c = getopt(argc, argv, "?hp:")) != EOF) {
277 switch (c) {
278 case 'p':
279 ret = add_opt(&optlist, optarg, 0);
280 if (ret != SA_OK) {
281 (void) printf(gettext(
282 "Problem with property: %s\n"), optarg);
283 return (SA_NO_MEMORY);
285 break;
286 default:
287 (void) printf(gettext("usage: %s\n"),
288 sc_get_usage(USAGE_CTL_SET));
289 return (SA_SYNTAX_ERR);
290 case '?':
291 case 'h':
292 (void) printf(gettext("usage: %s\n"),
293 sc_get_usage(USAGE_CTL_SET));
294 return (SA_OK);
298 if (optind >= argc) {
299 (void) printf(gettext("usage: %s\n"),
300 sc_get_usage(USAGE_CTL_SET));
301 (void) printf(gettext("\tprotocol must be specified.\n"));
302 return (SA_INVALID_PROTOCOL);
305 proto = argv[optind];
306 if (!sa_valid_protocol(proto)) {
307 (void) printf(gettext("Invalid protocol specified: %s\n"),
308 proto);
309 return (SA_INVALID_PROTOCOL);
311 propset = sa_proto_get_properties(proto);
312 if (propset == NULL)
313 return (ret);
315 if (optlist == NULL) {
316 (void) printf(gettext("usage: %s\n"),
317 sc_get_usage(USAGE_CTL_SET));
318 (void) printf(gettext(
319 "\tat least one property and value "
320 "must be specified\n"));
321 } else {
322 struct options *opt;
323 char *section = NULL;
324 /* fetch and change the specified option(s) */
325 for (opt = optlist; opt != NULL; opt = opt->next) {
326 if (strncmp("section", opt->optname, 7) == 0) {
327 if (section != NULL)
328 free(section);
329 section = strdup(opt->optvalue);
330 continue;
332 if (sa_proto_get_featureset(proto) &
333 SA_FEATURE_HAS_SECTIONS) {
334 propsect = sa_get_protocol_section(propset,
335 section);
336 prop = sa_get_protocol_property(propsect,
337 opt->optname);
338 } else {
339 prop = sa_get_protocol_property(propset,
340 opt->optname);
342 if (prop == NULL && sa_proto_get_featureset(proto) &
343 SA_FEATURE_ADD_PROPERTIES) {
344 sa_property_t sect;
345 sect = sa_create_section(section, NULL);
346 sa_set_section_attr(sect, "type", proto);
347 (void) sa_add_protocol_property(propset, sect);
348 prop = sa_create_property(
349 opt->optname, opt->optvalue);
350 (void) sa_add_protocol_property(sect, prop);
352 if (prop != NULL) {
354 * "err" is used in order to prevent
355 * setting ret to SA_OK if there has
356 * been a real error. We want to be
357 * able to return an error status on
358 * exit in that case. Error messages
359 * are printed for each error, so we
360 * only care on exit that there was an
361 * error and not the specific error
362 * value.
364 err = sa_set_protocol_property(prop, section,
365 opt->optvalue);
366 if (err != SA_OK) {
367 (void) printf(gettext(
368 "Could not set property"
369 " %s: %s\n"),
370 opt->optname, sa_errorstr(err));
371 ret = err;
373 } else {
374 (void) printf(gettext("%s: not defined\n"),
375 opt->optname);
376 ret = SA_NO_SUCH_PROP;
380 return (ret);
383 static void
384 show_status(char *proto)
386 char *status;
387 uint64_t features;
389 status = sa_get_protocol_status(proto);
390 features = sa_proto_get_featureset(proto);
391 (void) printf("%s\t%s", proto, status ? gettext(status) : "-");
392 if (status != NULL)
393 free(status);
395 * Need to flag a client only protocol so test suites can
396 * remove it from consideration.
398 if (!(features & SA_FEATURE_SERVER))
399 (void) printf(" client");
400 (void) printf("\n");
403 static int
404 valid_proto(char **protos, int num, char *proto)
406 int i;
407 for (i = 0; i < num; i++)
408 if (strcmp(protos[i], proto) == 0)
409 return (1);
410 return (0);
413 /*ARGSUSED*/
414 static int
415 sc_status(sa_handle_t handle, int flags, int argc, char *argv[])
417 char **protos;
418 int ret = SA_OK;
419 int c;
420 int i;
421 int num_proto;
422 int verbose = 0;
424 while ((c = getopt(argc, argv, "?hv")) != EOF) {
425 switch (c) {
426 case 'v':
427 verbose++;
428 break;
429 case '?':
430 case 'h':
431 (void) printf(gettext("usage: %s\n"),
432 sc_get_usage(USAGE_CTL_STATUS));
433 return (SA_OK);
434 default:
435 (void) printf(gettext("usage: %s\n"),
436 sc_get_usage(USAGE_CTL_STATUS));
437 return (SA_SYNTAX_ERR);
441 num_proto = sa_get_protocols(&protos);
442 if (optind == argc) {
443 /* status for all protocols */
444 for (i = 0; i < num_proto; i++) {
445 show_status(protos[i]);
447 } else {
448 for (i = optind; i < argc; i++) {
449 if (valid_proto(protos, num_proto, argv[i])) {
450 show_status(argv[i]);
451 } else {
452 (void) printf(gettext("Invalid protocol: %s\n"),
453 argv[i]);
454 ret = SA_INVALID_PROTOCOL;
458 if (protos != NULL)
459 free(protos);
460 return (ret);
463 /*ARGSUSED*/
464 static int
465 sc_delsect(sa_handle_t handle, int flags, int argc, char *argv[])
467 char *proto = NULL;
468 char *section = NULL;
469 sa_protocol_properties_t propset;
470 sa_protocol_properties_t propsect;
471 int ret = SA_OK;
472 int c;
474 while ((c = getopt(argc, argv, "?h")) != EOF) {
475 switch (c) {
476 default:
477 ret = SA_SYNTAX_ERR;
478 /*FALLTHROUGH*/
479 case '?':
480 case 'h':
481 (void) printf(gettext("usage: %s\n"),
482 sc_get_usage(USAGE_CTL_DELSECT));
483 return (ret);
485 /*NOTREACHED*/
488 section = argv[optind++];
490 if (optind >= argc) {
491 (void) printf(gettext("usage: %s\n"),
492 sc_get_usage(USAGE_CTL_DELSECT));
493 (void) printf(gettext(
494 "\tsection and protocol must be specified.\n"));
495 return (SA_INVALID_PROTOCOL);
498 proto = argv[optind];
499 if (!sa_valid_protocol(proto)) {
500 (void) printf(gettext("Invalid protocol specified: %s\n"),
501 proto);
502 return (SA_INVALID_PROTOCOL);
505 if ((sa_proto_get_featureset(proto) & SA_FEATURE_HAS_SECTIONS) == 0) {
506 (void) printf(gettext("Protocol %s does not have sections\n"),
507 section, proto);
508 return (SA_NOT_SUPPORTED);
511 propset = sa_proto_get_properties(proto);
512 if (propset == NULL) {
513 (void) printf(gettext("Cannot get properties for %s\n"),
514 proto);
515 return (SA_NO_PROPERTIES);
518 propsect = sa_get_protocol_section(propset, section);
519 if (propsect == NULL) {
520 (void) printf(gettext("Cannot find section %s for proto %s\n"),
521 section, proto);
522 return (SA_NO_SUCH_SECTION);
525 ret = sa_proto_delete_section(proto, section);
527 return (ret);
530 static sa_command_t commands[] = {
531 {"delsect", 0, sc_delsect, USAGE_CTL_DELSECT},
532 {"get", 0, sc_get, USAGE_CTL_GET},
533 {"set", 0, sc_set, USAGE_CTL_SET},
534 {"status", 0, sc_status, USAGE_CTL_STATUS},
535 {NULL, 0, NULL, 0},
538 /*ARGSUSED*/
539 void
540 sub_command_help(char *proto)
542 int i;
544 for (i = 0; commands[i].cmdname != NULL; i++) {
545 if (!(commands[i].flags & (CMD_ALIAS|CMD_NODISPLAY)))
546 (void) printf("\t%s\n",
547 sc_get_usage((sc_usage_t)commands[i].cmdidx));
551 sa_command_t *
552 sa_lookup(char *cmd)
554 int i;
555 size_t len;
557 len = strlen(cmd);
558 for (i = 0; commands[i].cmdname != NULL; i++) {
559 if (strncmp(cmd, commands[i].cmdname, len) == 0)
560 return (&commands[i]);
562 return (NULL);
565 static int
566 run_command(char *command, int argc, char *argv[], sa_handle_t handle)
568 sa_command_t *cmdvec;
569 int ret;
572 * To get here, we know there should be a command due to the
573 * preprocessing done earlier. Need to find the protocol
574 * that is being affected. If no protocol, then it is ALL
575 * protocols.
577 * ??? do we really need the protocol at this level? it may be
578 * sufficient to let the commands look it up if needed since
579 * not all commands do proto specific things
581 * Known sub-commands are handled at this level. An unknown
582 * command will be passed down to the shared object that
583 * actually implements it. We can do this since the semantics
584 * of the common sub-commands is well defined.
587 cmdvec = sa_lookup(command);
588 if (cmdvec == NULL) {
589 (void) printf(gettext("command %s not found\n"), command);
590 exit(1);
593 * need to check priviledges and restrict what can be done
594 * based on least priviledge and sub-command.
596 ret = cmdvec->cmdfunc(handle, NULL, argc, argv);
597 return (ret);