/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2012 Milan Jurik. All rights reserved.
* Copyright 2016 Nexenta Systems, Inc.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <getopt.h>
#include <libgen.h>
#include "libshare.h"
#include <sharemgr.h>
#include <libintl.h>
#include <locale.h>
static int run_command(char *, int, char **, sa_handle_t);
static void sub_command_help(char *proto);
static void
{
}
int
{
int c;
int help = 0;
int rval;
char *command;
/*
* make sure locale and gettext domain is setup
*/
(void) textdomain(TEXT_DOMAIN);
switch (c) {
case '?':
case 'h':
help = 1;
break;
default:
}
}
/* no subcommand */
global_help();
exit(0);
}
optind = 1;
/*
* now have enough to parse rest of command line
*/
return (rval);
}
char *
{
switch (index) {
case USAGE_CTL_DELSECT:
break;
case USAGE_CTL_GET:
break;
case USAGE_CTL_SET:
break;
case USAGE_CTL_STATUS:
break;
}
return (ret);
}
/*ARGSUSED*/
static int
{
int c;
switch (c) {
case 'p':
"Problem with property: %s\n"), optarg);
return (SA_NO_MEMORY);
}
break;
default:
return (SA_SYNTAX_ERR);
case '?':
case 'h':
return (SA_OK);
}
}
return (SA_INVALID_PROTOCOL);
}
if (!sa_valid_protocol(proto)) {
proto);
return (SA_INVALID_PROTOCOL);
}
return (ret);
/* Display all known properties for this protocol */
"name");
/*
* If properties are organized into sections, as
* in the SMB client, print the section name.
*/
if (sa_proto_get_featureset(proto) &
if (!first)
(void) printf("\n");
first = 0;
(void) printf("[%s]\n",
}
/* Display properties for this section */
/* get and display the property and value */
"value");
}
}
}
} else {
/* list the specified option(s) */
int printed = 0;
NULL)) {
"name");
"value");
if (sa_proto_get_featureset(proto) &
(void) printf(
gettext("[%s] %s=%s\n"),
} else {
(void) printf(
gettext("%s=%s\n"),
}
printed = 1;
}
}
if (!printed) {
}
}
}
return (ret);
}
/*ARGSUSED*/
static int
{
int c;
int err;
switch (c) {
case 'p':
"Problem with property: %s\n"), optarg);
return (SA_NO_MEMORY);
}
break;
default:
return (SA_SYNTAX_ERR);
case '?':
case 'h':
return (SA_OK);
}
}
return (SA_INVALID_PROTOCOL);
}
if (!sa_valid_protocol(proto)) {
proto);
return (SA_INVALID_PROTOCOL);
}
return (ret);
"\tat least one property and value "
"must be specified\n"));
} else {
/* fetch and change the specified option(s) */
continue;
}
if (sa_proto_get_featureset(proto) &
section);
} else {
}
}
/*
* "err" is used in order to prevent
* setting ret to SA_OK if there has
* been a real error. We want to be
* able to return an error status on
* exit in that case. Error messages
* are printed for each error, so we
* only care on exit that there was an
* error and not the specific error
* value.
*/
"Could not set property"
" %s: %s\n"),
}
} else {
}
}
}
return (ret);
}
static void
{
char *status;
/*
* Need to flag a client only protocol so test suites can
* remove it from consideration.
*/
if (!(features & SA_FEATURE_SERVER))
(void) printf(" client");
(void) printf("\n");
}
static int
{
int i;
for (i = 0; i < num; i++)
return (1);
return (0);
}
/*ARGSUSED*/
static int
{
char **protos;
int c;
int i;
int num_proto;
int verbose = 0;
switch (c) {
case 'v':
verbose++;
break;
case '?':
case 'h':
return (SA_OK);
default:
return (SA_SYNTAX_ERR);
}
}
/* status for all protocols */
for (i = 0; i < num_proto; i++) {
show_status(protos[i]);
}
} else {
show_status(argv[i]);
} else {
argv[i]);
}
}
}
return (ret);
}
/*ARGSUSED*/
static int
{
int c;
switch (c) {
default:
ret = SA_SYNTAX_ERR;
/*FALLTHROUGH*/
case '?':
case 'h':
return (ret);
}
/*NOTREACHED*/
}
"\tsection and protocol must be specified.\n"));
return (SA_INVALID_PROTOCOL);
}
if (!sa_valid_protocol(proto)) {
proto);
return (SA_INVALID_PROTOCOL);
}
proto);
return (SA_NOT_SUPPORTED);
}
proto);
return (SA_NO_PROPERTIES);
}
return (SA_NO_SUCH_SECTION);
}
return (ret);
}
};
/*ARGSUSED*/
void
{
int i;
(void) printf("\t%s\n",
}
}
{
int i;
return (&commands[i]);
}
return (NULL);
}
static int
{
int ret;
/*
* To get here, we know there should be a command due to the
* preprocessing done earlier. Need to find the protocol
* that is being affected. If no protocol, then it is ALL
* protocols.
*
* ??? do we really need the protocol at this level? it may be
* sufficient to let the commands look it up if needed since
* not all commands do proto specific things
*
* Known sub-commands are handled at this level. An unknown
* command will be passed down to the shared object that
* actually implements it. We can do this since the semantics
* of the common sub-commands is well defined.
*/
exit(1);
}
/*
* need to check priviledges and restrict what can be done
* based on least priviledge and sub-command.
*/
return (ret);
}