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