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]
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.
43 static int run_command(char *, int, char **, sa_handle_t
);
44 static void sub_command_help(char *proto
);
49 (void) printf(gettext("usage: sharectl <subcommand> [<options>]\n"));
50 sub_command_help(NULL
);
54 main(int argc
, char *argv
[])
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
) {
77 (void) printf(gettext("Invalid option: %c\n"), c
);
80 if (optind
== argc
|| help
) {
88 * now have enough to parse rest of command line
90 command
= argv
[optind
];
91 rval
= run_command(command
, argc
- optind
, argv
+ optind
, handle
);
98 sc_get_usage(sc_usage_t index
)
103 case USAGE_CTL_DELSECT
:
104 ret
= gettext("delsect\t<section> <proto>");
107 ret
= gettext("get\t[-p <property>]... <proto>");
110 ret
= gettext("set\t{-p <property>=<value>}... <proto>");
112 case USAGE_CTL_STATUS
:
113 ret
= gettext("status\t[<proto>]...");
121 sc_get(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
124 struct options
*optlist
= NULL
;
127 sa_protocol_properties_t propset
, propsect
;
129 char *section
, *value
, *name
;
132 while ((c
= getopt(argc
, argv
, "?hp:")) != EOF
) {
135 ret
= add_opt(&optlist
, optarg
, 1);
137 (void) printf(gettext(
138 "Problem with property: %s\n"), optarg
);
139 return (SA_NO_MEMORY
);
143 (void) printf(gettext("usage: %s\n"),
144 sc_get_usage(USAGE_CTL_GET
));
145 return (SA_SYNTAX_ERR
);
148 (void) printf(gettext("usage: %s\n"),
149 sc_get_usage(USAGE_CTL_GET
));
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"),
165 return (SA_INVALID_PROTOCOL
);
167 propset
= sa_proto_get_properties(proto
);
171 if (optlist
== NULL
) {
172 /* Display all known properties for this protocol */
173 for (propsect
= sa_get_protocol_section(propset
, NULL
);
175 propsect
= sa_get_next_protocol_section(propsect
, NULL
)) {
176 section
= sa_get_property_attr(propsect
,
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
) {
187 (void) printf("[%s]\n",
188 section
!= NULL
? section
: "");
191 sa_free_attr_string(section
);
193 /* Display properties for this section */
194 for (prop
= sa_get_protocol_property(propsect
, 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");
201 value
= sa_get_property_attr(prop
,
203 (void) printf(gettext("%s=%s\n"), name
,
204 value
!= NULL
? value
: "");
207 sa_free_attr_string(value
);
209 sa_free_attr_string(name
);
215 /* list the specified option(s) */
216 for (opt
= optlist
; opt
!= NULL
; opt
= opt
->next
) {
219 for (propsect
= sa_get_protocol_section(propset
, NULL
);
221 propsect
= sa_get_next_protocol_section(propsect
,
224 section
= sa_get_property_attr(propsect
,
226 for (prop
= sa_get_protocol_property(propsect
,
229 prop
= sa_get_next_protocol_property(
230 propsect
, opt
->optname
)) {
231 value
= sa_get_property_attr(prop
,
233 if (sa_proto_get_featureset(proto
) &
234 SA_FEATURE_HAS_SECTIONS
) {
236 gettext("[%s] %s=%s\n"),
238 section
: "", opt
->optname
,
239 value
!= NULL
? value
: "");
244 value
!= NULL
? value
: "");
247 sa_free_attr_string(value
);
251 sa_free_attr_string(section
);
254 (void) printf(gettext("%s: not defined\n"),
256 ret
= SA_NO_SUCH_PROP
;
265 sc_set(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
268 struct options
*optlist
= NULL
;
269 sa_protocol_properties_t propsect
;
273 sa_protocol_properties_t propset
;
276 while ((c
= getopt(argc
, argv
, "?hp:")) != EOF
) {
279 ret
= add_opt(&optlist
, optarg
, 0);
281 (void) printf(gettext(
282 "Problem with property: %s\n"), optarg
);
283 return (SA_NO_MEMORY
);
287 (void) printf(gettext("usage: %s\n"),
288 sc_get_usage(USAGE_CTL_SET
));
289 return (SA_SYNTAX_ERR
);
292 (void) printf(gettext("usage: %s\n"),
293 sc_get_usage(USAGE_CTL_SET
));
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"),
309 return (SA_INVALID_PROTOCOL
);
311 propset
= sa_proto_get_properties(proto
);
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"));
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) {
328 section
= strdup(opt
->optvalue
);
331 if (sa_proto_get_featureset(proto
) &
332 SA_FEATURE_HAS_SECTIONS
) {
333 propsect
= sa_get_protocol_section(propset
,
335 prop
= sa_get_protocol_property(propsect
,
338 prop
= sa_get_protocol_property(propset
,
341 if (prop
== NULL
&& sa_proto_get_featureset(proto
) &
342 SA_FEATURE_ADD_PROPERTIES
) {
344 sect
= sa_create_section(section
, NULL
);
345 sa_set_section_attr(sect
, "type", proto
);
346 (void) sa_add_protocol_property(propset
, sect
);
347 prop
= sa_create_property(
348 opt
->optname
, opt
->optvalue
);
349 (void) sa_add_protocol_property(sect
, prop
);
353 * "err" is used in order to prevent
354 * setting ret to SA_OK if there has
355 * been a real error. We want to be
356 * able to return an error status on
357 * exit in that case. Error messages
358 * are printed for each error, so we
359 * only care on exit that there was an
360 * error and not the specific error
363 err
= sa_set_protocol_property(prop
, section
,
366 (void) printf(gettext(
367 "Could not set property"
369 opt
->optname
, sa_errorstr(err
));
373 (void) printf(gettext("%s: not defined\n"),
375 ret
= SA_NO_SUCH_PROP
;
383 show_status(char *proto
)
388 status
= sa_get_protocol_status(proto
);
389 features
= sa_proto_get_featureset(proto
);
390 (void) printf("%s\t%s", proto
, status
? gettext(status
) : "-");
393 * Need to flag a client only protocol so test suites can
394 * remove it from consideration.
396 if (!(features
& SA_FEATURE_SERVER
))
397 (void) printf(" client");
402 valid_proto(char **protos
, int num
, char *proto
)
405 for (i
= 0; i
< num
; i
++)
406 if (strcmp(protos
[i
], proto
) == 0)
413 sc_status(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
422 while ((c
= getopt(argc
, argv
, "?hv")) != EOF
) {
429 (void) printf(gettext("usage: %s\n"),
430 sc_get_usage(USAGE_CTL_STATUS
));
433 (void) printf(gettext("usage: %s\n"),
434 sc_get_usage(USAGE_CTL_STATUS
));
435 return (SA_SYNTAX_ERR
);
439 num_proto
= sa_get_protocols(&protos
);
440 if (optind
== argc
) {
441 /* status for all protocols */
442 for (i
= 0; i
< num_proto
; i
++) {
443 show_status(protos
[i
]);
446 for (i
= optind
; i
< argc
; i
++) {
447 if (valid_proto(protos
, num_proto
, argv
[i
])) {
448 show_status(argv
[i
]);
450 (void) printf(gettext("Invalid protocol: %s\n"),
452 ret
= SA_INVALID_PROTOCOL
;
462 sc_delsect(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
465 char *section
= NULL
;
466 sa_protocol_properties_t propset
;
467 sa_protocol_properties_t propsect
;
471 while ((c
= getopt(argc
, argv
, "?h")) != EOF
) {
478 (void) printf(gettext("usage: %s\n"),
479 sc_get_usage(USAGE_CTL_DELSECT
));
485 section
= argv
[optind
++];
487 if (optind
>= argc
) {
488 (void) printf(gettext("usage: %s\n"),
489 sc_get_usage(USAGE_CTL_DELSECT
));
490 (void) printf(gettext(
491 "\tsection and protocol must be specified.\n"));
492 return (SA_INVALID_PROTOCOL
);
495 proto
= argv
[optind
];
496 if (!sa_valid_protocol(proto
)) {
497 (void) printf(gettext("Invalid protocol specified: %s\n"),
499 return (SA_INVALID_PROTOCOL
);
502 if ((sa_proto_get_featureset(proto
) & SA_FEATURE_HAS_SECTIONS
) == 0) {
503 (void) printf(gettext("Protocol %s does not have sections\n"),
505 return (SA_NOT_SUPPORTED
);
508 propset
= sa_proto_get_properties(proto
);
509 if (propset
== NULL
) {
510 (void) printf(gettext("Cannot get properties for %s\n"),
512 return (SA_NO_PROPERTIES
);
515 propsect
= sa_get_protocol_section(propset
, section
);
516 if (propsect
== NULL
) {
517 (void) printf(gettext("Cannot find section %s for proto %s\n"),
519 return (SA_NO_SUCH_SECTION
);
522 ret
= sa_proto_delete_section(proto
, section
);
527 static sa_command_t commands
[] = {
528 {"delsect", 0, sc_delsect
, USAGE_CTL_DELSECT
},
529 {"get", 0, sc_get
, USAGE_CTL_GET
},
530 {"set", 0, sc_set
, USAGE_CTL_SET
},
531 {"status", 0, sc_status
, USAGE_CTL_STATUS
},
537 sub_command_help(char *proto
)
541 for (i
= 0; commands
[i
].cmdname
!= NULL
; i
++) {
542 if (!(commands
[i
].flags
& (CMD_ALIAS
|CMD_NODISPLAY
)))
543 (void) printf("\t%s\n",
544 sc_get_usage((sc_usage_t
)commands
[i
].cmdidx
));
555 for (i
= 0; commands
[i
].cmdname
!= NULL
; i
++) {
556 if (strncmp(cmd
, commands
[i
].cmdname
, len
) == 0)
557 return (&commands
[i
]);
563 run_command(char *command
, int argc
, char *argv
[], sa_handle_t handle
)
565 sa_command_t
*cmdvec
;
569 * To get here, we know there should be a command due to the
570 * preprocessing done earlier. Need to find the protocol
571 * that is being affected. If no protocol, then it is ALL
574 * ??? do we really need the protocol at this level? it may be
575 * sufficient to let the commands look it up if needed since
576 * not all commands do proto specific things
578 * Known sub-commands are handled at this level. An unknown
579 * command will be passed down to the shared object that
580 * actually implements it. We can do this since the semantics
581 * of the common sub-commands is well defined.
584 cmdvec
= sa_lookup(command
);
585 if (cmdvec
== NULL
) {
586 (void) printf(gettext("command %s not found\n"), command
);
590 * need to check priviledges and restrict what can be done
591 * based on least priviledge and sub-command.
593 ret
= cmdvec
->cmdfunc(handle
, 0, argc
, argv
);