8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.sbin / nwamcfg / nwamcfg.c
blobe4896f565dd451297a8054e808e324c394639446
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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
27 * nwamcfg is a lex/yacc based command interpreter used to manage network
28 * configurations. The lexer (see nwamcfg_lex.l) builds up tokens, which
29 * the grammar (see nwamcfg_grammar.y) builds up into commands, some of
30 * which takes resources and/or properties as arguments.
33 #include <arpa/inet.h>
34 #include <assert.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <libnwam.h>
38 #include <libtecla.h>
39 #include <locale.h>
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <sys/stat.h>
44 #include <sys/sysmacros.h>
45 #include <sys/types.h>
46 #include <unistd.h>
48 #include "nwamcfg.h"
50 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
51 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
52 #endif
54 struct help {
55 uint_t cmd_num;
56 const char *cmd_name;
57 const char *cmd_usage;
60 extern int yyparse(void);
61 extern int lex_lineno;
63 #define MAX_LINE_LEN 1024
64 #define MAX_CMD_HIST 1024
66 /* usage of commands */
67 #define SHELP_CANCEL "cancel"
68 #define SHELP_CLEAR "clear <prop-name>"
69 #define SHELP_COMMIT "commit"
70 #define SHELP_CREATE "create [-t <template>] <object-type> [<class>] " \
71 "<object-name>"
72 #define SHELP_DESTROY "destroy {-a | <object-type> [<class>] <object-name>}"
73 #define SHELP_END "end"
74 #define SHELP_EXIT "exit"
75 #define SHELP_EXPORT "export [-d] [-f <output-file>] " \
76 "[<object-type> [<class>] <object-name>]"
77 #define SHELP_GET "get [-V] <prop-name>"
78 #define SHELP_HELP "help [command-name]"
79 #define SHELP_LIST "list [-a] [<object-type> [<class>] <object-name>]"
80 #define SHELP_REVERT "revert"
81 #define SHELP_SELECT "select <object-type> [<class>] <object-name>"
82 #define SHELP_SET "set <prop-name>=<value1>[,<value2>...]"
83 #define SHELP_VERIFY "verify"
84 #define SHELP_WALK "walkprop [-a]"
87 * Scope Definitions:
88 * Locations, ENMs, NCPs and Known WLANs are one scope level below global (GBL).
89 * NCUs are one more level beneath the NCP scope.
90 * Because the commands in Locations/ENM/Known WLAN and NCP level are different,
91 * the scope are divided accordingly.
92 * GBL->LOC, GBL->ENM, GBL->WLAN or GBL->NCP->NCU
94 #define NWAM_SCOPE_GBL 0
95 #define NWAM_SCOPE_LOC 1
96 #define NWAM_SCOPE_ENM 2
97 #define NWAM_SCOPE_WLAN 3
98 #define NWAM_SCOPE_NCP 4
99 #define NWAM_SCOPE_NCU 5
101 /* delimiter used for list of values */
102 #define NWAM_VALUE_DELIMITER_CHAR ','
103 #define NWAM_VALUE_DELIMITER_STR ","
105 /* the max number of values for an enum used by some properties in libnwam */
108 * All arrays/tables are null-terminated, rather than defining the length of
109 * the array. When looping, check for NULL rather than using the size.
112 static struct help helptab[] = {
113 { CMD_CANCEL, "cancel", SHELP_CANCEL },
114 { CMD_CLEAR, "clear", SHELP_CLEAR },
115 { CMD_COMMIT, "commit", SHELP_COMMIT },
116 { CMD_CREATE, "create", SHELP_CREATE },
117 { CMD_DESTROY, "destroy", SHELP_DESTROY },
118 { CMD_END, "end", SHELP_END },
119 { CMD_EXIT, "exit", SHELP_EXIT },
120 { CMD_EXPORT, "export", SHELP_EXPORT },
121 { CMD_GET, "get", SHELP_GET },
122 { CMD_HELP, "help", SHELP_HELP },
123 { CMD_LIST, "list", SHELP_LIST },
124 { CMD_REVERT, "revert", SHELP_REVERT },
125 { CMD_SELECT, "select", SHELP_SELECT },
126 { CMD_SET, "set", SHELP_SET },
127 { CMD_VERIFY, "verify", SHELP_VERIFY },
128 { CMD_WALKPROP, "walkprop", SHELP_WALK },
129 { 0, NULL, NULL }
132 /* These *must* match the order of the RT1_ define's from nwamcfg.h */
133 static char *res1_types[] = {
134 "unknown",
135 "loc",
136 "ncp",
137 "enm",
138 "wlan",
139 NULL
142 /* These *must* match the order of the RT2_ define's from nwamcfg.h */
143 static char *res2_types[] = {
144 "unknown",
145 "ncu",
146 NULL
150 * No array for NCU_CLASS_. The #define's in nwamcfg.h matches the
151 * enum nwam_ncu_class_t in libnwam and thus uses libnwam functions to
152 * retrieve the string representation.
155 /* These *MUST* match the order of the PT_ define's from nwamcfg.h */
156 static char *pt_types[] = {
157 "unknown",
158 NWAM_NCU_PROP_ACTIVATION_MODE,
159 NWAM_NCU_PROP_ENABLED,
160 NWAM_NCU_PROP_TYPE,
161 NWAM_NCU_PROP_CLASS,
162 NWAM_NCU_PROP_PARENT_NCP,
163 NWAM_NCU_PROP_PRIORITY_GROUP,
164 NWAM_NCU_PROP_PRIORITY_MODE,
165 NWAM_NCU_PROP_LINK_MAC_ADDR,
166 NWAM_NCU_PROP_LINK_AUTOPUSH,
167 NWAM_NCU_PROP_LINK_MTU,
168 NWAM_NCU_PROP_IP_VERSION,
169 NWAM_NCU_PROP_IPV4_ADDRSRC,
170 NWAM_NCU_PROP_IPV4_ADDR,
171 NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE,
172 NWAM_NCU_PROP_IPV6_ADDRSRC,
173 NWAM_NCU_PROP_IPV6_ADDR,
174 NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE,
175 NWAM_LOC_PROP_CONDITIONS,
176 NWAM_ENM_PROP_FMRI,
177 NWAM_ENM_PROP_START,
178 NWAM_ENM_PROP_STOP,
179 NWAM_LOC_PROP_NAMESERVICES,
180 NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE,
181 NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
182 NWAM_LOC_PROP_DNS_NAMESERVICE_DOMAIN,
183 NWAM_LOC_PROP_DNS_NAMESERVICE_SERVERS,
184 NWAM_LOC_PROP_DNS_NAMESERVICE_SEARCH,
185 NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC,
186 NWAM_LOC_PROP_NIS_NAMESERVICE_SERVERS,
187 NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
188 NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS,
189 NWAM_LOC_PROP_DEFAULT_DOMAIN,
190 NWAM_LOC_PROP_NFSV4_DOMAIN,
191 NWAM_LOC_PROP_IPFILTER_CONFIG_FILE,
192 NWAM_LOC_PROP_IPFILTER_V6_CONFIG_FILE,
193 NWAM_LOC_PROP_IPNAT_CONFIG_FILE,
194 NWAM_LOC_PROP_IPPOOL_CONFIG_FILE,
195 NWAM_LOC_PROP_IKE_CONFIG_FILE,
196 NWAM_LOC_PROP_IPSECPOLICY_CONFIG_FILE,
197 NWAM_KNOWN_WLAN_PROP_BSSIDS,
198 NWAM_KNOWN_WLAN_PROP_PRIORITY,
199 NWAM_KNOWN_WLAN_PROP_KEYNAME,
200 NWAM_KNOWN_WLAN_PROP_KEYSLOT,
201 NWAM_KNOWN_WLAN_PROP_SECURITY_MODE
204 /* properties table: maps PT_* constants to property names */
205 typedef struct prop_table_entry {
206 int pte_type;
207 const char *pte_name;
208 } prop_table_entry_t;
210 /* NCU properties table */
211 static prop_table_entry_t ncu_prop_table[] = {
212 { PT_TYPE, NWAM_NCU_PROP_TYPE },
213 { PT_CLASS, NWAM_NCU_PROP_CLASS },
214 { PT_PARENT, NWAM_NCU_PROP_PARENT_NCP },
215 { PT_ACTIVATION_MODE, NWAM_NCU_PROP_ACTIVATION_MODE },
216 { PT_ENABLED, NWAM_NCU_PROP_ENABLED },
217 { PT_PRIORITY_GROUP, NWAM_NCU_PROP_PRIORITY_GROUP },
218 { PT_PRIORITY_MODE, NWAM_NCU_PROP_PRIORITY_MODE },
219 { PT_LINK_MACADDR, NWAM_NCU_PROP_LINK_MAC_ADDR },
220 { PT_LINK_AUTOPUSH, NWAM_NCU_PROP_LINK_AUTOPUSH },
221 { PT_LINK_MTU, NWAM_NCU_PROP_LINK_MTU },
222 { PT_IP_VERSION, NWAM_NCU_PROP_IP_VERSION },
223 { PT_IPV4_ADDRSRC, NWAM_NCU_PROP_IPV4_ADDRSRC },
224 { PT_IPV4_ADDR, NWAM_NCU_PROP_IPV4_ADDR },
225 { PT_IPV4_DEFAULT_ROUTE, NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE },
226 { PT_IPV6_ADDRSRC, NWAM_NCU_PROP_IPV6_ADDRSRC },
227 { PT_IPV6_ADDR, NWAM_NCU_PROP_IPV6_ADDR },
228 { PT_IPV6_DEFAULT_ROUTE, NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE },
229 { 0, NULL }
232 /* ENM properties table */
233 static prop_table_entry_t enm_prop_table[] = {
234 { PT_ENM_FMRI, NWAM_ENM_PROP_FMRI },
235 { PT_ENM_START, NWAM_ENM_PROP_START },
236 { PT_ENM_STOP, NWAM_ENM_PROP_STOP },
237 { PT_ACTIVATION_MODE, NWAM_ENM_PROP_ACTIVATION_MODE },
238 { PT_CONDITIONS, NWAM_ENM_PROP_CONDITIONS },
239 { PT_ENABLED, NWAM_ENM_PROP_ENABLED },
240 { 0, NULL }
243 /* LOCation properties table */
244 static prop_table_entry_t loc_prop_table[] = {
245 { PT_ACTIVATION_MODE, NWAM_LOC_PROP_ACTIVATION_MODE },
246 { PT_CONDITIONS, NWAM_LOC_PROP_CONDITIONS },
247 { PT_ENABLED, NWAM_LOC_PROP_ENABLED },
248 { PT_LOC_NAMESERVICES, NWAM_LOC_PROP_NAMESERVICES },
249 { PT_LOC_NAMESERVICES_CONFIG, NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE },
250 { PT_LOC_DNS_CONFIGSRC, NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC },
251 { PT_LOC_DNS_DOMAIN, NWAM_LOC_PROP_DNS_NAMESERVICE_DOMAIN },
252 { PT_LOC_DNS_SERVERS, NWAM_LOC_PROP_DNS_NAMESERVICE_SERVERS },
253 { PT_LOC_DNS_SEARCH, NWAM_LOC_PROP_DNS_NAMESERVICE_SEARCH },
254 { PT_LOC_NIS_CONFIGSRC, NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC },
255 { PT_LOC_NIS_SERVERS, NWAM_LOC_PROP_NIS_NAMESERVICE_SERVERS },
256 { PT_LOC_LDAP_CONFIGSRC, NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC },
257 { PT_LOC_LDAP_SERVERS, NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS },
258 { PT_LOC_DEFAULT_DOMAIN, NWAM_LOC_PROP_DEFAULT_DOMAIN },
259 { PT_LOC_NFSV4_DOMAIN, NWAM_LOC_PROP_NFSV4_DOMAIN },
260 { PT_LOC_IPF_CONFIG, NWAM_LOC_PROP_IPFILTER_CONFIG_FILE },
261 { PT_LOC_IPF_V6_CONFIG, NWAM_LOC_PROP_IPFILTER_V6_CONFIG_FILE },
262 { PT_LOC_IPNAT_CONFIG, NWAM_LOC_PROP_IPNAT_CONFIG_FILE },
263 { PT_LOC_IPPOOL_CONFIG, NWAM_LOC_PROP_IPPOOL_CONFIG_FILE },
264 { PT_LOC_IKE_CONFIG, NWAM_LOC_PROP_IKE_CONFIG_FILE },
265 { PT_LOC_IPSECPOL_CONFIG, NWAM_LOC_PROP_IPSECPOLICY_CONFIG_FILE },
266 { 0, NULL }
269 /* Known WLAN properties table */
270 static prop_table_entry_t wlan_prop_table[] = {
271 { PT_WLAN_BSSIDS, NWAM_KNOWN_WLAN_PROP_BSSIDS },
272 { PT_WLAN_PRIORITY, NWAM_KNOWN_WLAN_PROP_PRIORITY },
273 { PT_WLAN_KEYNAME, NWAM_KNOWN_WLAN_PROP_KEYNAME },
274 { PT_WLAN_KEYSLOT, NWAM_KNOWN_WLAN_PROP_KEYSLOT },
275 { PT_WLAN_SECURITY_MODE, NWAM_KNOWN_WLAN_PROP_SECURITY_MODE },
276 { 0, NULL }
279 /* Returns the appropriate properties table for the given object type */
280 static prop_table_entry_t *
281 get_prop_table(nwam_object_type_t object_type)
283 switch (object_type) {
284 case NWAM_OBJECT_TYPE_NCU:
285 return (ncu_prop_table);
286 case NWAM_OBJECT_TYPE_LOC:
287 return (loc_prop_table);
288 case NWAM_OBJECT_TYPE_ENM:
289 return (enm_prop_table);
290 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
291 return (wlan_prop_table);
293 return (NULL);
296 /* Global variables */
298 /* set early in main(), never modified thereafter, used all over the place */
299 static char *execname;
301 /* set in modifying functions, checked in read_input() */
302 boolean_t saw_error = B_FALSE;
304 /* set in yacc parser, checked in read_input() */
305 boolean_t newline_terminated;
307 /* set in main(), checked in lex error handler */
308 boolean_t cmd_file_mode = B_FALSE;
310 /* set in exit_func(), checked in read_input() */
311 static boolean_t time_to_exit = B_FALSE;
313 /* used in nerr() and nwamerr() */
314 static char *cmd_file_name = NULL;
316 /* used with cmd_file to destroy all configurations */
317 static boolean_t remove_all_configurations = B_FALSE;
319 /* checked in read_input() and other places */
320 static boolean_t ok_to_prompt = B_FALSE;
322 /* initialized in do_interactive(), checked in initialize() */
323 static boolean_t interactive_mode;
325 static boolean_t need_to_commit = B_FALSE;
327 /* The gl_get_line() resource object */
328 static GetLine *gl;
330 /* set when create or read objects, used by other func */
331 static nwam_loc_handle_t loc_h = NULL;
332 static nwam_enm_handle_t enm_h = NULL;
333 static nwam_known_wlan_handle_t wlan_h = NULL;
334 static nwam_ncu_handle_t ncu_h = NULL;
335 static nwam_ncp_handle_t ncp_h = NULL;
337 static int current_scope = NWAM_SCOPE_GBL;
339 /* obj1_* are used in NWAM_SCOPE_{NCP,LOC,ENM,WLAN} */
340 static int obj1_type;
341 static char obj1_name[NWAM_MAX_NAME_LEN + 1];
343 /* obj2_* are used in NWAM_SCOPE_NCU only */
344 static int obj2_type;
345 static char obj2_name[NWAM_MAX_NAME_LEN + 1];
347 /* arrays for tab-completion */
348 /* commands at NWAM_SCOPE_GBL */
349 static const char *global_scope_cmds[] = {
350 "create ",
351 "destroy ",
352 "end ",
353 "exit ",
354 "export ",
355 "help ",
356 "list ",
357 "select ",
358 NULL
361 static const char *global_create_cmds[] = {
362 "create loc ",
363 "create enm ",
364 "create ncp ",
365 "create wlan ",
366 "create -t ", /* template */
367 NULL
370 static const char *global_destroy_cmds[] = {
371 "destroy -a ",
372 "destroy loc ",
373 "destroy enm ",
374 "destroy ncp ",
375 "destroy wlan ",
376 NULL
379 static const char *global_export_cmds[] = {
380 "export ",
381 "export -d ", /* add destroy -a */
382 "export -f ", /* to file */
383 "export -d -f ", /* add destroy -a to file */
384 "export loc ",
385 "export enm ",
386 "export ncp ",
387 "export wlan ",
388 NULL
391 static const char *global_list_cmds[] = {
392 "list ",
393 "list loc ",
394 "list enm ",
395 "list ncp ",
396 "list wlan ",
397 "list -a loc ",
398 "list -a enm ",
399 "list -a wlan ",
400 NULL
403 static const char *global_select_cmds[] = {
404 "select loc ",
405 "select enm ",
406 "select ncp ",
407 "select wlan ",
408 NULL
411 /* commands at NWAM_SCOPE_LOC, _ENM, _WLAN and _NCU */
412 static const char *non_ncp_scope_cmds[] = {
413 "cancel ",
414 "clear ",
415 "commit ",
416 "end ",
417 "exit ",
418 "export ",
419 "export -f ",
420 "get ",
421 "get -V ", /* value only */
422 "help ",
423 "list ",
424 "list -a ", /* all properties */
425 "revert ",
426 "set ",
427 "verify ",
428 "walkprop ",
429 "walkprop -a ", /* all properties */
430 NULL
433 /* commands at NWAM_SCOPE_NCP */
434 static const char *ncp_scope_cmds[] = {
435 "cancel ",
436 "create ",
437 "destroy ",
438 "end ",
439 "exit ",
440 "export ",
441 "help ",
442 "list ",
443 "select ",
444 NULL
447 static const char *ncp_create_cmds[] = {
448 "create ncu ip ",
449 "create ncu phys ",
450 "create -t ", /* template */
451 NULL
454 static const char *ncp_destroy_cmds[] = {
455 "destroy ncu ",
456 "destroy ncu ip ",
457 "destroy ncu phys ",
458 NULL
461 static const char *ncp_export_cmds[] = {
462 "export ",
463 "export -f ", /* to file */
464 "export ncu ",
465 "export ncu ip ",
466 "export ncu phys ",
467 NULL
470 static const char *ncp_list_cmds[] = {
471 "list ",
472 "list ncu ",
473 "list ncu ip ",
474 "list ncu phys ",
475 "list -a ncu ",
476 "list -a ncu ip ",
477 "list -a ncu phys ",
478 NULL
481 static const char *ncp_select_cmds[] = {
482 "select ncu ",
483 "select ncu ip ",
484 "select ncu phys ",
485 NULL
488 /* Functions begin here */
490 cmd_t *
491 alloc_cmd(void)
493 cmd_t *cmd = calloc(1, sizeof (cmd_t));
494 if (cmd == NULL) {
495 nerr("Out of memory");
496 return (NULL);
498 cmd->cmd_argc = 0;
499 cmd->cmd_argv[0] = NULL;
501 return (cmd);
504 void
505 free_cmd(cmd_t *cmd)
507 int i;
509 for (i = 0; i < cmd->cmd_argc; i++)
510 free(cmd->cmd_argv[i]);
511 free(cmd);
514 void
515 array_free(void **array, int nelem)
517 int i;
518 for (i = 0; i < nelem; i++)
519 free(array[i]);
520 free(array);
523 static boolean_t
524 initial_match(const char *line1, const char *line2, int word_end)
526 if (word_end <= 0)
527 return (B_TRUE);
528 return (strncmp(line1, line2, word_end) == 0);
531 static int
532 add_stuff(WordCompletion *cpl, const char *line1, const char **list,
533 int word_end)
535 int i, err;
537 for (i = 0; list[i] != NULL; i++) {
538 if (initial_match(line1, list[i], word_end)) {
539 err = cpl_add_completion(cpl, line1, 0, word_end,
540 list[i] + word_end, "", "");
541 if (err != 0)
542 return (err);
545 return (0);
549 * To fill in the rest of a string when user types the tab key.
550 * First digital number is the length of the string, the second digital number
551 * is the min number of chars that is needed to uniquely identify a string.
553 #define MINI_STR(l, s, m, n) strncmp(l, s, MAX(MIN(sizeof (s) - 1, m), n))
555 /* ARGSUSED */
556 static
557 CPL_MATCH_FN(cmd_cpl_fn)
559 /* tab-complete according to the current scope */
560 switch (current_scope) {
561 case NWAM_SCOPE_GBL:
562 if (MINI_STR(line, "create ", word_end, 2) == 0)
563 return (add_stuff(cpl, line, global_create_cmds,
564 word_end));
565 if (MINI_STR(line, "destroy ", word_end, 1) == 0)
566 return (add_stuff(cpl, line, global_destroy_cmds,
567 word_end));
568 if (MINI_STR(line, "export ", word_end, 3) == 0)
569 return (add_stuff(cpl, line, global_export_cmds,
570 word_end));
571 if (MINI_STR(line, "list ", word_end, 1) == 0)
572 return (add_stuff(cpl, line, global_list_cmds,
573 word_end));
574 if (MINI_STR(line, "select ", word_end, 1) == 0)
575 return (add_stuff(cpl, line, global_select_cmds,
576 word_end));
577 return (add_stuff(cpl, line, global_scope_cmds, word_end));
578 case NWAM_SCOPE_LOC:
579 case NWAM_SCOPE_ENM:
580 case NWAM_SCOPE_WLAN:
581 case NWAM_SCOPE_NCU:
582 return (add_stuff(cpl, line, non_ncp_scope_cmds, word_end));
583 case NWAM_SCOPE_NCP:
584 if (MINI_STR(line, "create ", word_end, 2) == 0)
585 return (add_stuff(cpl, line, ncp_create_cmds,
586 word_end));
587 if (MINI_STR(line, "destroy ", word_end, 1) == 0)
588 return (add_stuff(cpl, line, ncp_destroy_cmds,
589 word_end));
590 if (MINI_STR(line, "export ", word_end, 3) == 0)
591 return (add_stuff(cpl, line, ncp_export_cmds,
592 word_end));
593 if (MINI_STR(line, "list ", word_end, 1) == 0)
594 return (add_stuff(cpl, line, ncp_list_cmds, word_end));
595 if (MINI_STR(line, "select ", word_end, 1) == 0)
596 return (add_stuff(cpl, line, ncp_select_cmds,
597 word_end));
598 return (add_stuff(cpl, line, ncp_scope_cmds, word_end));
600 /* should never get here */
601 return (NULL);
604 const char *
605 cmd_to_str(int cmd_num)
607 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
608 return (helptab[cmd_num].cmd_name);
611 /* Returns "loc", "enm", "wlan" or "ncp" as string */
612 static const char *
613 rt1_to_str(int res_type)
615 assert(res_type >= RT1_MIN && res_type <= RT1_MAX);
616 return (res1_types[res_type]);
619 /* Returns "ncu" as string */
620 static const char *
621 rt2_to_str(int res_type)
623 assert(res_type >= RT2_MIN && res_type <= RT2_MAX);
624 return (res2_types[res_type]);
627 /* Returns "ncp, "ncu", "loc", "enm", or "wlan" according to the scope */
628 static const char *
629 scope_to_str(int scope) {
630 switch (scope) {
631 case NWAM_SCOPE_GBL:
632 return ("global");
633 case NWAM_SCOPE_NCP:
634 return ("ncp");
635 case NWAM_SCOPE_NCU:
636 return ("ncu");
637 case NWAM_SCOPE_LOC:
638 return ("loc");
639 case NWAM_SCOPE_ENM:
640 return ("enm");
641 case NWAM_SCOPE_WLAN:
642 return ("wlan");
643 default:
644 return ("invalid");
648 /* Given an enm property and value, returns it as a string */
649 static const char *
650 propval_to_str(const char *propname, uint64_t value)
652 const char *str;
654 if (nwam_uint64_get_value_string(propname, value, &str) == NWAM_SUCCESS)
655 return (str);
656 return (NULL);
659 /* Given an int for a prop, returns it as string */
660 static const char *
661 pt_to_str(int prop_type)
663 assert(prop_type >= PT_MIN && prop_type <= PT_MAX);
664 return (pt_types[prop_type]);
667 /* Return B_TRUE if string starts with "t" or is 1, B_FALSE otherwise */
668 static boolean_t
669 str_to_boolean(const char *str)
671 if (strncasecmp(str, "t", 1) == 0 || atoi(str) == 1)
672 return (B_TRUE);
673 else
674 return (B_FALSE);
678 * This is a separate function rather than a set of define's because of the
679 * gettext() wrapping.
683 * TRANSLATION_NOTE
684 * Each string below should have \t follow \n whenever needed; the
685 * initial \t and the terminal \n will be provided by the calling function.
688 static const char *
689 long_help(int cmd_num)
691 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
692 switch (cmd_num) {
693 case CMD_CANCEL:
694 return (gettext("Cancels the current configuration "
695 "changes."));
696 case CMD_CLEAR:
697 return (gettext("Clears the value for the specified "
698 "property."));
699 case CMD_COMMIT:
700 return (gettext("Commits the current configuration."));
701 case CMD_CREATE:
702 return (gettext("Creates a new profile or resource."));
703 case CMD_DESTROY:
704 return (gettext("Destroys the specified profile or "
705 "resource."));
706 case CMD_END:
707 return (gettext("Ends specification of a resource."));
708 case CMD_EXIT:
709 return (gettext("Exits the program."));
710 case CMD_EXPORT:
711 return (gettext("Exports the configuration."));
712 case CMD_GET:
713 return (gettext("Gets the value of the specified "
714 "property."));
715 case CMD_HELP:
716 return (gettext("Prints help message."));
717 case CMD_LIST:
718 return (gettext("Lists existing objects."));
719 case CMD_REVERT:
720 return (gettext("Reverts to the previous "
721 "configuration."));
722 case CMD_SELECT:
723 return (gettext("Selects a resource to modify."));
724 case CMD_SET:
725 return (gettext("Sets the value of the specified "
726 "property."));
727 case CMD_VERIFY:
728 return (gettext("Verifies an object."));
729 case CMD_WALKPROP:
730 return (gettext("Iterates over properties."));
731 default:
732 return (gettext("Unknown command."));
736 void
737 command_usage(int command)
739 if (command < CMD_MIN || command > CMD_MAX) {
740 nerr("Unknown command");
741 } else {
742 nerr("%s: %s: %s", gettext("Error"), gettext("usage"),
743 helptab[command].cmd_usage);
747 static void
748 long_usage(uint_t cmd_num)
750 (void) printf("%s: %s\n", gettext("usage"),
751 helptab[cmd_num].cmd_usage);
752 (void) printf("\t%s\n", long_help(cmd_num));
755 /* Prints usage for command line options */
756 static void
757 cmd_line_usage()
759 (void) printf("%s:\t%s\t\t\t\t(%s)\n", gettext("usage"), execname,
760 gettext("interactive-mode"));
761 (void) printf("\t%s <%s> [%s...]\n", execname, gettext("command"),
762 gettext("options"));
763 (void) printf("\t%s [-d] -f <%s>\n", execname, gettext("command-file"));
764 (void) printf("\t%s %s [<%s>]\n", execname, cmd_to_str(CMD_HELP),
765 gettext("command"));
768 /* Prints the line number of the current command if in command-file mode */
769 static void
770 print_lineno()
772 static int last_lineno;
774 /* lex_lineno has already been incremented in the lexer; compensate */
775 if (cmd_file_mode && lex_lineno > last_lineno) {
776 if (strcmp(cmd_file_name, "-") == 0)
777 (void) fprintf(stderr, gettext("On line %d:\n"),
778 lex_lineno - 1);
779 else
780 (void) fprintf(stderr, gettext("On line %d of %s:\n"),
781 lex_lineno - 1, cmd_file_name);
782 last_lineno = lex_lineno;
786 /* PRINTFLIKE1 */
787 void
788 nerr(const char *format, ...)
790 va_list alist;
792 print_lineno();
794 format = gettext(format);
795 va_start(alist, format);
796 (void) vfprintf(stderr, format, alist);
797 va_end(alist);
798 (void) fprintf(stderr, "\n");
800 saw_error = B_TRUE;
803 /* PRINTFLIKE2 */
804 static void
805 nwamerr(nwam_error_t err, const char *format, ...)
807 va_list alist;
809 print_lineno();
811 format = gettext(format);
812 va_start(alist, format);
813 (void) vfprintf(stderr, format, alist);
814 va_end(alist);
815 (void) fprintf(stderr, ": %s\n", nwam_strerror(err));
817 saw_error = B_TRUE;
820 void
821 properr(const char *prop)
823 nerr("Invalid property: '%s'", prop);
827 * If free_ncu_only == B_TRUE, only ncu handle is freed, ncp handle remains the
828 * same. Since nwam_ncp_free() takes care of its ncus, no need to explicitly
829 * call nwam_ncu_free() afterwards.
831 static void
832 free_handle(boolean_t free_ncu_only)
834 if (ncp_h != NULL) {
835 if (!free_ncu_only) {
836 nwam_ncp_free(ncp_h);
837 ncp_h = NULL;
838 ncu_h = NULL;
839 } else if (ncu_h != NULL) {
840 nwam_ncu_free(ncu_h);
841 ncu_h = NULL;
845 if (enm_h != NULL) {
846 nwam_enm_free(enm_h);
847 enm_h = NULL;
850 if (loc_h != NULL) {
851 nwam_loc_free(loc_h);
852 loc_h = NULL;
855 if (wlan_h != NULL) {
856 nwam_known_wlan_free(wlan_h);
857 wlan_h = NULL;
862 * On input, TRUE => yes, FALSE => no.
863 * On return, TRUE => 1, FALSE => no, could not ask => -1.
865 static int
866 ask_yesno(boolean_t default_answer, const char *question)
868 char line[64]; /* should be enough to answer yes or no */
870 if (!ok_to_prompt) {
871 saw_error = B_TRUE;
872 return (-1);
874 for (;;) {
875 if (printf("%s (%s)? ", gettext(question),
876 default_answer ? "[y]/n" : "y/[n]") < 0)
877 return (-1);
878 if (fgets(line, sizeof (line), stdin) == NULL)
879 return (-1);
881 if (line[0] == '\n')
882 return (default_answer ? 1 : 0);
883 if (tolower(line[0]) == 'y')
884 return (1);
885 if (tolower(line[0]) == 'n')
886 return (0);
890 /* This is the back-end helper function for read_input() below. */
891 static int
892 cleanup()
894 int answer;
896 if (!interactive_mode && !cmd_file_mode) {
898 * If we're not in interactive mode, and we're not in command
899 * file mode, then we must be in commands-from-the-command-line
900 * mode. As such, we can't loop back and ask for more input.
901 * It was OK to prompt for such things as whether or not to
902 * really delete something in the command handler called from
903 * yyparse() above, but "really quit?" makes no sense in this
904 * context. So disable prompting.
906 ok_to_prompt = B_FALSE;
908 if (need_to_commit) {
909 answer = ask_yesno(B_FALSE,
910 "Configuration not saved; really quit");
911 switch (answer) {
912 case -1:
913 /* issue error here */
914 return (NWAM_ERR);
915 case 1:
917 * don't want to save, just exit. handles are freed at
918 * end_func() or exit_func().
920 return (NWAM_OK);
921 default:
922 /* loop back to read input */
923 time_to_exit = B_FALSE;
924 yyin = stdin;
925 return (NWAM_REPEAT);
928 return (saw_error ? NWAM_ERR : NWAM_OK);
931 static int
932 string_to_yyin(char *string)
934 if ((yyin = tmpfile()) == NULL)
935 goto error;
936 if (fwrite(string, strlen(string), 1, yyin) != 1)
937 goto error;
938 if (fseek(yyin, 0, SEEK_SET) != 0)
939 goto error;
941 return (NWAM_OK);
943 error:
944 nerr("problem creating temporary file");
945 return (NWAM_ERR);
949 * read_input() is the driver of this program. It is a wrapper around
950 * yyparse(), printing appropriate prompts when needed, checking for
951 * exit conditions and reacting appropriately. This function is
952 * called when in interactive mode or command-file mode.
954 static int
955 read_input(void)
957 boolean_t yyin_is_a_tty = isatty(fileno(yyin));
959 * The prompt is "e> " or "e:t1:o1> " or "e:t1:o1:t2:o2> " where e is
960 * execname, t is resource type, o is object name.
962 char prompt[MAXPATHLEN + (2 * (NWAM_MAX_TYPE_LEN + NWAM_MAX_NAME_LEN))
963 + sizeof ("::::> ")];
964 char *line;
966 /* yyin should have been set to the appropriate (FILE *) if not stdin */
967 newline_terminated = B_TRUE;
968 for (;;) {
969 if (yyin_is_a_tty) {
970 if (newline_terminated) {
971 switch (current_scope) {
972 case NWAM_SCOPE_GBL:
973 (void) snprintf(prompt, sizeof (prompt),
974 "%s> ", execname);
975 break;
976 case NWAM_SCOPE_LOC:
977 case NWAM_SCOPE_ENM:
978 case NWAM_SCOPE_WLAN:
979 case NWAM_SCOPE_NCP:
980 (void) snprintf(prompt, sizeof (prompt),
981 "%s:%s:%s> ", execname,
982 rt1_to_str(obj1_type), obj1_name);
984 break;
985 case NWAM_SCOPE_NCU:
986 (void) snprintf(prompt, sizeof (prompt),
987 "%s:%s:%s:%s:%s> ", execname,
988 rt1_to_str(obj1_type), obj1_name,
989 rt2_to_str(obj2_type), obj2_name);
993 * If the user hits ^C then we want to catch it and
994 * start over. If the user hits EOF then we want to
995 * bail out.
997 line = gl_get_line(gl, prompt, NULL, -1);
998 if (gl_return_status(gl) == GLR_SIGNAL) {
999 gl_abandon_line(gl);
1000 continue;
1002 if (line == NULL)
1003 break;
1004 if (string_to_yyin(line) != NWAM_OK)
1005 break;
1006 while (!feof(yyin)) {
1007 yyparse();
1010 * If any command on a list of commands
1011 * give an error, don't continue with the
1012 * remaining commands.
1014 if (saw_error || time_to_exit)
1015 break;
1017 } else {
1018 yyparse();
1021 /* Bail out on an error in command-file mode. */
1022 if (saw_error && cmd_file_mode && !interactive_mode)
1023 time_to_exit = B_TRUE;
1024 if (time_to_exit || (!yyin_is_a_tty && feof(yyin)))
1025 break;
1027 return (cleanup());
1031 * This function is used in the interactive-mode scenario: it just calls
1032 * read_input() until we are done.
1034 static int
1035 do_interactive(void)
1037 int err;
1039 interactive_mode = B_TRUE;
1040 do {
1041 err = read_input();
1042 } while (err == NWAM_REPEAT);
1043 return (err);
1046 /* Calls the help_func() to print the usage of all commands */
1047 void
1048 help_wrap()
1050 cmd_t *help_cmd;
1052 if ((help_cmd = alloc_cmd()) == NULL)
1053 exit(NWAM_ERR);
1054 help_func(help_cmd);
1055 free_cmd(help_cmd);
1058 /* Check if the given command is allowed in the current scope */
1059 boolean_t
1060 check_scope(int cmd)
1062 /* allowed in all scopes */
1063 switch (cmd) {
1064 case CMD_END:
1065 case CMD_EXIT:
1066 case CMD_HELP:
1067 case CMD_LIST:
1068 case CMD_EXPORT:
1069 return (B_TRUE);
1071 /* scope-specific */
1072 switch (current_scope) {
1073 case NWAM_SCOPE_GBL:
1074 switch (cmd) {
1075 case CMD_CREATE:
1076 case CMD_DESTROY:
1077 case CMD_SELECT:
1078 return (B_TRUE);
1080 break;
1081 case NWAM_SCOPE_LOC:
1082 case NWAM_SCOPE_ENM:
1083 case NWAM_SCOPE_WLAN:
1084 case NWAM_SCOPE_NCU:
1085 switch (cmd) {
1086 case CMD_CANCEL:
1087 case CMD_CLEAR:
1088 case CMD_COMMIT:
1089 case CMD_GET:
1090 case CMD_REVERT:
1091 case CMD_SET:
1092 case CMD_VERIFY:
1093 case CMD_WALKPROP:
1094 return (B_TRUE);
1096 break;
1097 case NWAM_SCOPE_NCP:
1098 switch (cmd) {
1099 case CMD_CANCEL:
1100 case CMD_CREATE:
1101 case CMD_DESTROY:
1102 case CMD_SELECT:
1103 return (B_TRUE);
1105 break;
1106 default:
1107 nerr("Invalid scope");
1109 nerr("'%s' is not allowed at this scope", cmd_to_str(cmd));
1110 return (B_FALSE);
1113 /* Returns the active object type depending on which handle is not NULL */
1114 static nwam_object_type_t
1115 active_object_type()
1117 /* Check ncu_h before ncp_h, ncp_h must be loaded before ncu_h */
1118 if (ncu_h != NULL)
1119 return (NWAM_OBJECT_TYPE_NCU);
1120 else if (ncp_h != NULL)
1121 return (NWAM_OBJECT_TYPE_NCP);
1122 else if (loc_h != NULL)
1123 return (NWAM_OBJECT_TYPE_LOC);
1124 else if (enm_h != NULL)
1125 return (NWAM_OBJECT_TYPE_ENM);
1126 else if (wlan_h != NULL)
1127 return (NWAM_OBJECT_TYPE_KNOWN_WLAN);
1128 else
1129 return (NWAM_OBJECT_TYPE_UNKNOWN);
1132 /* Retrive the name of the object from its handle */
1133 static nwam_error_t
1134 object_name_from_handle(nwam_object_type_t object_type, void *handle,
1135 char **namep)
1137 switch (object_type) {
1138 case NWAM_OBJECT_TYPE_NCP:
1139 return (nwam_ncp_get_name(handle, namep));
1140 case NWAM_OBJECT_TYPE_NCU:
1141 return (nwam_ncu_get_name(handle, namep));
1142 case NWAM_OBJECT_TYPE_LOC:
1143 return (nwam_loc_get_name(handle, namep));
1144 case NWAM_OBJECT_TYPE_ENM:
1145 return (nwam_enm_get_name(handle, namep));
1146 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
1147 return (nwam_known_wlan_get_name(handle, namep));
1149 return (NWAM_INVALID_ARG);
1152 static void
1153 do_commit()
1155 nwam_error_t ret = NWAM_SUCCESS;
1156 const char *errprop;
1158 if (!need_to_commit)
1159 return;
1161 switch (active_object_type()) {
1162 case NWAM_OBJECT_TYPE_NCU:
1163 ret = nwam_ncu_commit(ncu_h, 0);
1164 break;
1165 case NWAM_OBJECT_TYPE_ENM:
1166 ret = nwam_enm_commit(enm_h, 0);
1167 break;
1168 case NWAM_OBJECT_TYPE_LOC:
1169 ret = nwam_loc_commit(loc_h, 0);
1170 break;
1171 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
1172 ret = nwam_known_wlan_commit(wlan_h, 0);
1173 break;
1176 if (ret == NWAM_SUCCESS) {
1177 need_to_commit = B_FALSE;
1178 if (interactive_mode)
1179 (void) printf(gettext("Committed changes\n"));
1180 } else {
1181 nwam_error_t verr;
1183 /* Find property that caused failure */
1184 switch (active_object_type()) {
1185 case NWAM_OBJECT_TYPE_NCU:
1186 verr = nwam_ncu_validate(ncu_h, &errprop);
1187 break;
1188 case NWAM_OBJECT_TYPE_ENM:
1189 verr = nwam_enm_validate(enm_h, &errprop);
1190 break;
1191 case NWAM_OBJECT_TYPE_LOC:
1192 verr = nwam_loc_validate(loc_h, &errprop);
1193 break;
1194 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
1195 verr = nwam_known_wlan_validate(wlan_h, &errprop);
1196 break;
1199 if (verr != NWAM_SUCCESS)
1200 nwamerr(ret, "Commit error on property '%s'", errprop);
1201 else
1202 nwamerr(ret, "Commit error");
1207 * Saves the current configuration to persistent storage.
1209 /* ARGSUSED */
1210 void
1211 commit_func(cmd_t *cmd)
1213 if (!need_to_commit) {
1214 if (interactive_mode)
1215 (void) printf(gettext("Nothing to commit\n"));
1216 } else {
1217 do_commit();
1221 static void
1222 do_cancel()
1224 switch (current_scope) {
1225 case NWAM_SCOPE_NCU:
1226 current_scope = NWAM_SCOPE_NCP;
1227 obj2_type = 0;
1228 free_handle(B_TRUE);
1229 break;
1230 case NWAM_SCOPE_NCP:
1231 case NWAM_SCOPE_ENM:
1232 case NWAM_SCOPE_WLAN:
1233 case NWAM_SCOPE_LOC:
1234 current_scope = NWAM_SCOPE_GBL;
1235 obj1_type = 0;
1236 free_handle(B_FALSE);
1237 break;
1238 case NWAM_SCOPE_GBL:
1239 free_handle(B_FALSE);
1240 break;
1241 default:
1242 nerr("Invalid scope");
1243 return;
1245 need_to_commit = B_FALSE;
1249 * End operation on current scope and go up one scope.
1250 * Changes are not saved, no prompt either.
1252 /* ARGSUSED */
1253 void
1254 cancel_func(cmd_t *cmd)
1256 do_cancel();
1260 * Removes leading and trailing quotes from a string.
1261 * Caller must free returned string.
1263 static char *
1264 trim_quotes(const char *quoted_str)
1266 char *str;
1267 int end;
1269 /* export_func() and list_func() can pass NULL here */
1270 if (quoted_str == NULL)
1271 return (NULL);
1273 /* remove leading quote */
1274 if (quoted_str[0] == '"')
1275 str = strdup(quoted_str + 1);
1276 else
1277 str = strdup(quoted_str);
1278 if (str == NULL)
1279 return (NULL);
1281 /* remove trailing quote and newline */
1282 end = strlen(str) - 1;
1283 while (end >= 0 && (str[end] == '"' || str[end] == '\n'))
1284 end--;
1285 str[end+1] = 0;
1287 return (str);
1291 * Creates a new resource and enters the scope of that resource.
1292 * The new resource can also be a copy of an existing resource (-t option).
1293 * If in interactive mode, then after creation call walkprop_func()
1294 * to do walk the properties for the new object.
1296 void
1297 create_func(cmd_t *cmd)
1299 nwam_error_t ret = NWAM_SUCCESS;
1300 int c;
1301 boolean_t template = B_FALSE;
1302 char *newname = NULL, *oldname = NULL;
1303 cmd_t *walkprop_cmd;
1305 /* make sure right command at the right scope */
1306 if (current_scope == NWAM_SCOPE_GBL &&
1307 cmd->cmd_res2_type == RT2_NCU) {
1308 nerr("cannot create ncu at global scope");
1309 return;
1311 if (current_scope == NWAM_SCOPE_NCP &&
1312 cmd->cmd_res2_type != RT2_NCU) {
1313 nerr("Cannot create given object at this scope");
1314 return;
1317 assert(cmd->cmd_argc > 0);
1318 optind = 0;
1319 while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "t:")) != EOF) {
1320 switch (c) {
1321 case 't':
1322 template = B_TRUE;
1323 break;
1324 default:
1325 command_usage(CMD_CREATE);
1326 return;
1330 if (!template) {
1331 /* no template given */
1332 /* argv[0] is name */
1333 newname = trim_quotes(cmd->cmd_argv[0]);
1334 if (cmd->cmd_res1_type == RT1_ENM) {
1335 ret = nwam_enm_create(newname, NULL, &enm_h);
1336 } else if (cmd->cmd_res1_type == RT1_LOC) {
1337 ret = nwam_loc_create(newname, &loc_h);
1338 } else if (cmd->cmd_res1_type == RT1_WLAN) {
1339 ret = nwam_known_wlan_create(newname, &wlan_h);
1340 } else if (cmd->cmd_res1_type == RT1_NCP &&
1341 current_scope == NWAM_SCOPE_GBL) {
1342 ret = nwam_ncp_create(newname, 0, &ncp_h);
1343 } else if (cmd->cmd_res2_type == RT2_NCU) {
1344 nwam_ncu_type_t ncu_type;
1345 nwam_ncu_class_t ncu_class;
1347 /* ncp must already be read */
1348 if (ncp_h == NULL) {
1349 nerr("Create error: NCP has not been read");
1350 goto done;
1353 ncu_class = (nwam_ncu_class_t)cmd->cmd_ncu_class_type;
1354 ncu_type = nwam_ncu_class_to_type(ncu_class);
1355 ret = nwam_ncu_create(ncp_h, newname, ncu_type,
1356 ncu_class, &ncu_h);
1359 if (ret != NWAM_SUCCESS) {
1360 nwamerr(ret, "Create error");
1361 goto done;
1364 } else {
1365 /* template given */
1366 /* argv[0] is -t, argv[1] is old name, argv[2] is new name */
1367 oldname = trim_quotes(cmd->cmd_argv[1]);
1368 newname = trim_quotes(cmd->cmd_argv[2]);
1369 if (cmd->cmd_res1_type == RT1_ENM) {
1370 nwam_enm_handle_t oldenm_h;
1372 ret = nwam_enm_read(oldname, 0, &oldenm_h);
1373 if (ret != NWAM_SUCCESS)
1374 goto read_error;
1375 ret = nwam_enm_copy(oldenm_h, newname, &enm_h);
1376 nwam_enm_free(oldenm_h);
1377 } else if (cmd->cmd_res1_type == RT1_LOC) {
1378 nwam_loc_handle_t oldloc_h;
1380 ret = nwam_loc_read(oldname, 0, &oldloc_h);
1381 if (ret != NWAM_SUCCESS)
1382 goto read_error;
1383 ret = nwam_loc_copy(oldloc_h, newname, &loc_h);
1384 nwam_loc_free(oldloc_h);
1385 } else if (cmd->cmd_res1_type == RT1_WLAN) {
1386 nwam_known_wlan_handle_t oldwlan_h;
1388 ret = nwam_known_wlan_read(oldname, 0, &oldwlan_h);
1389 if (ret != NWAM_SUCCESS)
1390 goto read_error;
1391 ret = nwam_known_wlan_copy(oldwlan_h, newname, &wlan_h);
1392 nwam_known_wlan_free(oldwlan_h);
1393 } else if (cmd->cmd_res1_type == RT1_NCP &&
1394 current_scope == NWAM_SCOPE_GBL) {
1395 nwam_ncp_handle_t oldncp_h;
1397 ret = nwam_ncp_read(oldname, 0, &oldncp_h);
1398 if (ret != NWAM_SUCCESS)
1399 goto read_error;
1400 ret = nwam_ncp_copy(oldncp_h, newname, &ncp_h);
1401 nwam_ncp_free(oldncp_h);
1402 } else if (cmd->cmd_res2_type == RT2_NCU) {
1403 nwam_ncu_handle_t oldncu_h;
1404 nwam_ncu_type_t ncu_type;
1405 nwam_ncu_class_t ncu_class;
1407 /* ncp must already be read */
1408 if (ncp_h == NULL) {
1409 nerr("Copy error: NCP has not been read");
1410 goto done;
1412 ncu_class = (nwam_ncu_class_t)cmd->cmd_ncu_class_type;
1413 ncu_type = nwam_ncu_class_to_type(ncu_class);
1414 ret = nwam_ncu_read(ncp_h, oldname, ncu_type, 0,
1415 &oldncu_h);
1416 if (ret != NWAM_SUCCESS)
1417 goto read_error;
1418 ret = nwam_ncu_copy(oldncu_h, newname, &ncu_h);
1419 nwam_ncu_free(oldncu_h);
1422 if (ret != NWAM_SUCCESS) {
1423 nwamerr(ret, "Copy error");
1424 goto done;
1428 if (current_scope == NWAM_SCOPE_GBL) {
1429 (void) strlcpy(obj1_name, newname, sizeof (obj1_name));
1430 obj1_type = cmd->cmd_res1_type;
1431 if (obj1_type == RT1_ENM)
1432 current_scope = NWAM_SCOPE_ENM;
1433 else if (obj1_type == RT1_LOC)
1434 current_scope = NWAM_SCOPE_LOC;
1435 else if (obj1_type == RT1_WLAN)
1436 current_scope = NWAM_SCOPE_WLAN;
1437 else if (obj1_type == RT1_NCP)
1438 current_scope = NWAM_SCOPE_NCP;
1439 } else {
1440 (void) strlcpy(obj2_name, newname, sizeof (obj2_name));
1441 current_scope = NWAM_SCOPE_NCU;
1442 obj2_type = cmd->cmd_res2_type;
1444 if (current_scope != NWAM_SCOPE_NCP)
1445 need_to_commit = B_TRUE;
1447 /* do a walk of the properties if in interactive mode */
1448 if (interactive_mode && current_scope != NWAM_SCOPE_NCP) {
1449 (void) printf(gettext("Created %s '%s'. "
1450 "Walking properties ...\n"),
1451 scope_to_str(current_scope), newname);
1452 if ((walkprop_cmd = alloc_cmd()) == NULL)
1453 goto done;
1454 walkprop_func(walkprop_cmd);
1455 free(walkprop_cmd);
1458 read_error:
1459 if (ret != NWAM_SUCCESS)
1460 nwamerr(ret, "Copy error reading '%s'", oldname);
1462 done:
1463 free(oldname);
1464 free(newname);
1467 /* Processing of return value for destroy_*_callback() */
1468 static int
1469 destroy_ret(nwam_object_type_t object_type, nwam_error_t ret, void *handle)
1471 if (ret == NWAM_ENTITY_NOT_DESTROYABLE) {
1472 /* log a message to stderr, but don't consider it an error */
1473 char *name;
1474 if (object_name_from_handle(object_type, handle, &name)
1475 == NWAM_SUCCESS) {
1476 (void) fprintf(stderr,
1477 gettext("%s '%s' cannot be removed\n"),
1478 nwam_object_type_to_string(object_type), name);
1479 free(name);
1481 return (0);
1484 if (ret == NWAM_SUCCESS || ret == NWAM_ENTITY_IN_USE)
1485 return (0);
1487 return (1);
1491 * NWAM_FLAG_DO_NOT_FREE is passed to nwam_*_destory() so that it does not
1492 * free the handle. The calling nwam_walk_*() function frees this handle
1493 * as it is the function that created the handle.
1495 * Objects that are not destroyable or are active cannot be destroyed.
1496 * Don't return error in these situations so the walk can continue.
1498 /* ARGSUSED */
1499 static int
1500 destroy_ncp_callback(nwam_ncp_handle_t ncp, void *arg)
1502 /* The file is deleted, so NCUs are also removed */
1503 nwam_error_t ret = nwam_ncp_destroy(ncp, NWAM_FLAG_DO_NOT_FREE);
1504 return (destroy_ret(NWAM_OBJECT_TYPE_NCP, ret, ncp));
1507 /* ARGSUSED */
1508 static int
1509 destroy_loc_callback(nwam_loc_handle_t loc, void *arg)
1511 nwam_error_t ret = nwam_loc_destroy(loc, NWAM_FLAG_DO_NOT_FREE);
1512 return (destroy_ret(NWAM_OBJECT_TYPE_LOC, ret, loc));
1515 /* ARGSUSED */
1516 static int
1517 destroy_enm_callback(nwam_enm_handle_t enm, void *arg)
1519 nwam_error_t ret = nwam_enm_destroy(enm, NWAM_FLAG_DO_NOT_FREE);
1520 return (destroy_ret(NWAM_OBJECT_TYPE_ENM, ret, enm));
1523 /* ARGSUSED */
1524 static int
1525 destroy_wlan_callback(nwam_known_wlan_handle_t wlan, void *arg)
1527 nwam_error_t ret = nwam_known_wlan_destroy(wlan, NWAM_FLAG_DO_NOT_FREE);
1528 return (destroy_ret(NWAM_OBJECT_TYPE_KNOWN_WLAN, ret, wlan));
1532 * Remove all existing configuration that are not read-only.
1533 * walk through all ncps, locs, enms, wlans and destroy each one.
1535 static nwam_error_t
1536 destroy_all(void)
1538 nwam_error_t ret;
1540 assert(remove_all_configurations);
1542 ret = nwam_walk_ncps(destroy_ncp_callback, NULL, 0, NULL);
1543 if (ret != NWAM_SUCCESS)
1544 goto done;
1546 ret = nwam_walk_enms(destroy_enm_callback, NULL,
1547 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
1548 if (ret != NWAM_SUCCESS)
1549 goto done;
1551 ret = nwam_walk_locs(destroy_loc_callback, NULL,
1552 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
1553 if (ret != NWAM_SUCCESS)
1554 goto done;
1556 ret = nwam_walk_known_wlans(destroy_wlan_callback, NULL, 0, NULL);
1557 if (ret != NWAM_SUCCESS)
1558 goto done;
1560 if (interactive_mode)
1561 (void) printf(gettext("All user-defined entities destroyed\n"));
1562 remove_all_configurations = B_FALSE;
1564 done:
1565 if (ret != NWAM_SUCCESS) {
1566 nwamerr(ret, "Destroy error: "
1567 "could not destroy all configurations");
1569 return (ret);
1573 * Destroys an instance in persistent repository, and is permanent.
1574 * If interactive mode, it is allowed at global scope only
1575 * option -a destroys everything.
1577 void
1578 destroy_func(cmd_t *cmd)
1580 nwam_error_t ret;
1581 char *name, *realname = NULL;
1583 if (current_scope == NWAM_SCOPE_NCP &&
1584 (cmd->cmd_res1_type == RT1_ENM || cmd->cmd_res1_type == RT1_LOC ||
1585 cmd->cmd_res1_type == RT1_WLAN)) {
1586 nerr("Destroy error: only NCUs can be destroyed in NCP scope");
1587 return;
1590 assert(cmd->cmd_argc > 0);
1592 /* res1_type is -1 if -a flag is used */
1593 if (cmd->cmd_res1_type == -1) {
1594 int c;
1596 if (current_scope != NWAM_SCOPE_GBL) {
1597 nerr("Cannot destroy all configurations in a "
1598 "non-global scope");
1599 return;
1602 optind = 0;
1603 while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "a")) != EOF) {
1604 switch (c) {
1605 case 'a':
1606 remove_all_configurations = B_TRUE;
1607 break;
1608 default:
1609 command_usage(CMD_DESTROY);
1610 return;
1613 if (remove_all_configurations) {
1614 (void) destroy_all();
1615 return;
1619 /* argv[0] is name */
1620 name = trim_quotes(cmd->cmd_argv[0]);
1621 if (cmd->cmd_res2_type == RT2_NCU) {
1622 nwam_ncu_type_t ncu_type;
1623 nwam_ncu_class_t ncu_class;
1625 /* ncp must already be read */
1626 if (ncp_h == NULL) {
1627 nerr("Destroy ncu error: NCP has not been read");
1628 return;
1630 ncu_class = (nwam_ncu_class_t)cmd->cmd_ncu_class_type;
1631 ncu_type = nwam_ncu_class_to_type(ncu_class);
1632 ret = nwam_ncu_read(ncp_h, name, ncu_type, 0, &ncu_h);
1633 if (ret != NWAM_SUCCESS)
1634 goto done;
1635 (void) object_name_from_handle(NWAM_OBJECT_TYPE_NCU, ncu_h,
1636 &realname);
1637 ret = nwam_ncu_destroy(ncu_h, 0);
1638 ncu_h = NULL;
1639 } else if (cmd->cmd_res1_type == RT1_ENM) {
1640 if ((ret = nwam_enm_read(name, 0, &enm_h)) != NWAM_SUCCESS)
1641 goto done;
1642 (void) object_name_from_handle(NWAM_OBJECT_TYPE_ENM, enm_h,
1643 &realname);
1644 ret = nwam_enm_destroy(enm_h, 0);
1645 enm_h = NULL;
1646 } else if (cmd->cmd_res1_type == RT1_LOC) {
1647 if ((ret = nwam_loc_read(name, 0, &loc_h)) != NWAM_SUCCESS)
1648 goto done;
1649 (void) object_name_from_handle(NWAM_OBJECT_TYPE_LOC, loc_h,
1650 &realname);
1651 ret = nwam_loc_destroy(loc_h, 0);
1652 loc_h = NULL;
1653 } else if (cmd->cmd_res1_type == RT1_WLAN) {
1654 if ((ret = nwam_known_wlan_read(name, 0, &wlan_h))
1655 != NWAM_SUCCESS)
1656 goto done;
1657 (void) object_name_from_handle(NWAM_OBJECT_TYPE_KNOWN_WLAN,
1658 wlan_h, &realname);
1659 ret = nwam_known_wlan_destroy(wlan_h, 0);
1660 wlan_h = NULL;
1661 } else if (cmd->cmd_res1_type == RT1_NCP) {
1662 if ((ret = nwam_ncp_read(name, 0, &ncp_h)) != NWAM_SUCCESS)
1663 goto done;
1664 (void) object_name_from_handle(NWAM_OBJECT_TYPE_NCP, ncp_h,
1665 &realname);
1666 ret = nwam_ncp_destroy(ncp_h, 0);
1667 ncp_h = NULL;
1668 } else {
1669 nerr("Destroy error: unknown object-type");
1672 done:
1673 if (ret == NWAM_ENTITY_IN_USE) {
1674 nerr("Destroy error: active entity cannot be destroyed");
1675 } else if (ret != NWAM_SUCCESS) {
1676 nwamerr(ret, "Destroy error");
1677 } else if (interactive_mode) {
1678 (void) printf(gettext("Destroyed %s '%s'\n"),
1679 (cmd->cmd_res2_type == RT2_NCU ?
1680 rt2_to_str(cmd->cmd_res2_type) :
1681 rt1_to_str(cmd->cmd_res1_type)),
1682 realname != NULL ? realname : name);
1684 free(name);
1685 free(realname);
1689 * End operation on current scope and go up one scope.
1690 * Changes are saved.
1692 /* ARGSUSED */
1693 void
1694 end_func(cmd_t *cmd)
1696 /* if need_to_commit is set, commit changes */
1697 if (need_to_commit)
1698 do_commit();
1701 * Call do_cancel() to go up one scope. If commit fails,
1702 * need_to_commit is not reset and users are asked if they want to end.
1704 if (!need_to_commit ||
1705 (need_to_commit && (ask_yesno(B_FALSE,
1706 "Configuration not saved; really end")) == 1)) {
1707 /* set time_to_exit if in global scope */
1708 if (current_scope == NWAM_SCOPE_GBL)
1709 time_to_exit = B_TRUE;
1710 /* call do_cancel() to go up one scope */
1711 do_cancel();
1716 * Exit immediately. Configuration changes are saved by calling end_func().
1718 /* ARGSUSED */
1719 void
1720 exit_func(cmd_t *cmd)
1722 cmd_t *end_cmd;
1724 if (need_to_commit) {
1725 if ((end_cmd = alloc_cmd()) == NULL) {
1726 nerr("Exit error");
1727 return;
1729 end_func(end_cmd);
1730 free_cmd(end_cmd);
1734 * If need_to_commit is still set, then the commit failed.
1735 * Otherwise, exit.
1737 if (!need_to_commit)
1738 time_to_exit = B_TRUE;
1741 void
1742 help_func(cmd_t *cmd)
1744 int i;
1746 if (cmd->cmd_argc == 0) {
1747 (void) printf(gettext("commands:\n"));
1748 for (i = CMD_MIN; i <= CMD_MAX; i++)
1749 (void) printf("\t%s\n", helptab[i].cmd_usage);
1750 return;
1753 for (i = CMD_MIN; i <= CMD_MAX; i++) {
1754 if (strcmp(cmd->cmd_argv[0], cmd_to_str(i)) == 0) {
1755 long_usage(i);
1756 return;
1759 (void) fprintf(stderr, gettext("Unknown command: '%s'\n"),
1760 cmd->cmd_argv[0]);
1761 help_wrap();
1765 * Revert configuration of an instance to latest previous version.
1766 * Free the handle and read again.
1768 /* ARGSUSED */
1769 void
1770 revert_func(cmd_t *cmd)
1772 nwam_error_t ret;
1773 char *name = NULL;
1774 nwam_ncu_type_t ncu_type;
1775 nwam_object_type_t object_type = active_object_type();
1777 switch (object_type) {
1778 case NWAM_OBJECT_TYPE_NCU:
1779 /* retrieve name and type to use later */
1780 if ((ret = nwam_ncu_get_ncu_type(ncu_h, &ncu_type))
1781 != NWAM_SUCCESS) {
1782 nwamerr(ret, "Revert error: Get ncu type error");
1783 return;
1785 if ((ret = nwam_ncu_get_name(ncu_h, &name)) != NWAM_SUCCESS)
1786 goto name_error;
1787 nwam_ncu_free(ncu_h);
1788 ncu_h = NULL;
1789 ret = nwam_ncu_read(ncp_h, name, ncu_type, 0, &ncu_h);
1790 break;
1791 case NWAM_OBJECT_TYPE_ENM:
1792 if ((ret = nwam_enm_get_name(enm_h, &name)) != NWAM_SUCCESS)
1793 goto name_error;
1794 nwam_enm_free(enm_h);
1795 enm_h = NULL;
1796 ret = nwam_enm_read(name, 0, &enm_h);
1797 break;
1798 case NWAM_OBJECT_TYPE_LOC:
1799 if ((ret = nwam_loc_get_name(loc_h, &name)) != NWAM_SUCCESS)
1800 goto name_error;
1801 nwam_loc_free(loc_h);
1802 loc_h = NULL;
1803 ret = nwam_loc_read(name, 0, &loc_h);
1804 break;
1805 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
1806 if ((ret = nwam_known_wlan_get_name(wlan_h, &name))
1807 != NWAM_SUCCESS)
1808 goto name_error;
1809 nwam_known_wlan_free(wlan_h);
1810 wlan_h = NULL;
1811 ret = nwam_known_wlan_read(name, 0, &wlan_h);
1812 break;
1815 /* Exit this scope because handle already freed (call do_cancel()) */
1816 need_to_commit = B_FALSE;
1818 if (ret != NWAM_SUCCESS) {
1819 if (ret == NWAM_ENTITY_NOT_FOUND) {
1820 nerr("%s '%s' does not exist to revert to, removing it",
1821 nwam_object_type_to_string(object_type), name);
1822 } else {
1823 nwamerr(ret, "Revert error");
1825 do_cancel();
1827 free(name);
1828 return;
1830 name_error:
1831 if (ret != NWAM_SUCCESS)
1832 nwamerr(ret, "Revert error: get name error");
1836 * Load a resource from persistent repository and enter the scope
1837 * of that resource.
1839 void
1840 select_func(cmd_t *cmd)
1842 nwam_error_t ret;
1843 char *name, *realname = NULL;
1845 assert(cmd->cmd_argc > 0);
1846 if (current_scope == NWAM_SCOPE_NCP && cmd->cmd_res2_type != RT2_NCU) {
1847 nerr("cannot select '%s' at this scope",
1848 rt1_to_str(cmd->cmd_res1_type));
1849 return;
1852 /* argv[0] is name */
1853 name = trim_quotes(cmd->cmd_argv[0]);
1854 switch (cmd->cmd_res1_type) {
1855 case RT1_LOC:
1856 ret = nwam_loc_read(name, 0, &loc_h);
1857 if (ret == NWAM_SUCCESS) {
1858 current_scope = NWAM_SCOPE_LOC;
1859 (void) object_name_from_handle(NWAM_OBJECT_TYPE_LOC,
1860 loc_h, &realname);
1862 break;
1863 case RT1_ENM:
1864 ret = nwam_enm_read(name, 0, &enm_h);
1865 if (ret == NWAM_SUCCESS) {
1866 current_scope = NWAM_SCOPE_ENM;
1867 (void) object_name_from_handle(NWAM_OBJECT_TYPE_ENM,
1868 enm_h, &realname);
1870 break;
1871 case RT1_WLAN:
1872 ret = nwam_known_wlan_read(name, 0, &wlan_h);
1873 if (ret == NWAM_SUCCESS) {
1874 current_scope = NWAM_SCOPE_WLAN;
1875 (void) object_name_from_handle
1876 (NWAM_OBJECT_TYPE_KNOWN_WLAN, wlan_h, &realname);
1878 break;
1879 case RT1_NCP:
1880 if (cmd->cmd_res2_type == RT2_NCU) {
1881 nwam_ncu_type_t ncu_type;
1882 nwam_ncu_class_t ncu_class;
1884 /* ncp must already be read */
1885 if (ncp_h == NULL) {
1886 nerr("Select error: NCP has not been read");
1887 free(name);
1888 return;
1890 ncu_class = (nwam_ncu_class_t)cmd->cmd_ncu_class_type;
1891 ncu_type = nwam_ncu_class_to_type(ncu_class);
1892 ret = nwam_ncu_read(ncp_h, name, ncu_type, 0, &ncu_h);
1893 if (ret == NWAM_SUCCESS) {
1894 current_scope = NWAM_SCOPE_NCU;
1895 (void) object_name_from_handle
1896 (NWAM_OBJECT_TYPE_NCU, ncu_h, &realname);
1898 } else {
1899 ret = nwam_ncp_read(name, 0, &ncp_h);
1900 if (ret == NWAM_SUCCESS) {
1901 current_scope = NWAM_SCOPE_NCP;
1902 (void) object_name_from_handle
1903 (NWAM_OBJECT_TYPE_NCP, ncp_h, &realname);
1906 break;
1907 default:
1908 nerr("Select error: unknown object-type");
1909 free(name);
1910 return;
1913 if (ret != NWAM_SUCCESS) {
1914 nwamerr(ret, "Select error");
1915 } else {
1916 /* set the obj*_name or obj*_type depending on current scope */
1917 if (current_scope == NWAM_SCOPE_NCU) {
1918 obj2_type = RT2_NCU;
1919 (void) strlcpy(obj2_name,
1920 realname != NULL ? realname : name,
1921 sizeof (obj2_name));
1922 } else {
1923 (void) strlcpy(obj1_name,
1924 realname != NULL ? realname : name,
1925 sizeof (obj1_name));
1926 obj1_type = cmd->cmd_res1_type;
1929 free(name);
1930 free(realname);
1933 /* Given an int for prop, returns it as string */
1934 static const char *
1935 pt_to_prop_name(nwam_object_type_t object_type, int pt_type)
1937 int i;
1938 prop_table_entry_t *prop_table = get_prop_table(object_type);
1940 for (i = 0; prop_table[i].pte_name != NULL; i++) {
1941 if (pt_type == prop_table[i].pte_type)
1942 return (prop_table[i].pte_name);
1944 return (NULL);
1947 /* Given a prop as a string, returns it as an int */
1948 static int
1949 prop_to_pt(nwam_object_type_t object_type, const char *prop)
1951 int i;
1952 prop_table_entry_t *prop_table = get_prop_table(object_type);
1954 for (i = 0; prop_table[i].pte_name != NULL; i++) {
1955 if (strcmp(prop, prop_table[i].pte_name) == 0)
1956 return (prop_table[i].pte_type);
1958 return (-1);
1961 /* Given a prop as an int, returns its type (nwam_value_type_t) */
1962 static nwam_value_type_t
1963 prop_value_type(nwam_object_type_t object_type, const char *prop)
1965 nwam_error_t ret;
1966 nwam_value_type_t value_type;
1968 switch (object_type) {
1969 case NWAM_OBJECT_TYPE_NCU:
1970 ret = nwam_ncu_get_prop_type(prop, &value_type);
1971 break;
1972 case NWAM_OBJECT_TYPE_LOC:
1973 ret = nwam_loc_get_prop_type(prop, &value_type);
1974 break;
1975 case NWAM_OBJECT_TYPE_ENM:
1976 ret = nwam_enm_get_prop_type(prop, &value_type);
1977 break;
1978 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
1979 ret = nwam_known_wlan_get_prop_type(prop, &value_type);
1980 break;
1983 if (ret != NWAM_SUCCESS)
1984 value_type = NWAM_VALUE_TYPE_UNKNOWN;
1986 return (value_type);
1990 * Converts input_str to an array nwam_value.
1991 * If is_list_prop, break input_str into array of strings first.
1993 static nwam_value_t
1994 str_to_nwam_value(nwam_object_type_t object_type, char *input_str, int pt_type,
1995 boolean_t is_list_prop)
1997 int i, n = 0, ret;
1998 nwam_value_t data;
1999 char **val;
2000 int max_str_num;
2002 nwam_value_type_t value_type;
2003 int64_t *int_vals;
2004 uint64_t *uint_vals;
2005 boolean_t *boolean_vals;
2008 * Worst case is that each char separated by DELIMITER, so the
2009 * max number of sub strings is half of string length + 1.
2011 max_str_num = strlen(input_str) / 2 + 1;
2013 val = calloc(max_str_num, sizeof (char *));
2014 if (val == NULL) {
2015 nerr("Out of memory");
2016 return (NULL);
2019 if (is_list_prop) {
2020 char *tmp, *next;
2022 * Break down input_str and save as array of sub strings.
2023 * Set num as the number of the sub strings.
2024 * Use nwam_tokenize_by_unescaped_delim() rather than strtok()
2025 * because DELIMITER may be escaped
2027 tmp = (char *)input_str;
2028 while ((tmp = nwam_tokenize_by_unescaped_delim(tmp,
2029 NWAM_VALUE_DELIMITER_CHAR, &next)) != NULL) {
2030 val[n++] = trim_quotes(tmp);
2031 tmp = next;
2033 } else {
2034 val[n++] = trim_quotes(input_str);
2037 /* initialize int_vals or booleans_vals depending on pt_type */
2038 value_type = prop_value_type(object_type,
2039 pt_to_prop_name(object_type, pt_type));
2040 if (value_type == NWAM_VALUE_TYPE_INT64) {
2041 int_vals = calloc(n, sizeof (int64_t));
2042 if (int_vals == NULL) {
2043 nerr("Out of memory");
2044 array_free((void **)val, max_str_num);
2045 return (NULL);
2047 } else if (value_type == NWAM_VALUE_TYPE_UINT64) {
2048 uint_vals = calloc(n, sizeof (uint64_t));
2049 if (uint_vals == NULL) {
2050 nerr("Out of memory");
2051 array_free((void **)val, max_str_num);
2052 return (NULL);
2054 } else if (value_type == NWAM_VALUE_TYPE_BOOLEAN) {
2055 boolean_vals = calloc(n, sizeof (boolean_t));
2056 if (boolean_vals == NULL) {
2057 nerr("Out of memory");
2058 array_free((void **)val, max_str_num);
2059 return (NULL);
2062 /* set the appropriate array */
2063 for (i = 0; i < n; i++) {
2064 switch (value_type) {
2065 case NWAM_VALUE_TYPE_STRING:
2066 /* nothing to do - val already has the char** array */
2067 break;
2068 case NWAM_VALUE_TYPE_INT64:
2070 int_vals[i] = (int64_t)atoi(val[i]);
2071 break;
2073 case NWAM_VALUE_TYPE_UINT64:
2075 uint64_t str_as_enum;
2076 char *endptr;
2078 ret = nwam_value_string_get_uint64(
2079 pt_to_prop_name(object_type, pt_type),
2080 val[i], &str_as_enum);
2082 * Returns _SUCCESS if value for enum is valid.
2083 * Returns _INVALID_ARG if property is not an enum.
2085 if (ret == NWAM_SUCCESS) {
2086 uint_vals[i] = str_as_enum;
2087 } else if (ret == NWAM_INVALID_ARG) {
2088 uint_vals[i] = strtoul(val[i], &endptr, 10);
2089 /* verify conversion is valid */
2090 if (endptr == val[i]) {
2091 free(uint_vals);
2092 array_free((void **)val, max_str_num);
2093 return (NULL);
2095 } else {
2096 free(uint_vals);
2097 array_free((void **)val, max_str_num);
2098 return (NULL);
2100 break;
2102 case NWAM_VALUE_TYPE_BOOLEAN:
2103 boolean_vals[i] = str_to_boolean(val[i]);
2104 break;
2105 default:
2106 array_free((void **)val, max_str_num);
2107 return (NULL);
2111 /* create nwam_value_t */
2112 if (value_type == NWAM_VALUE_TYPE_STRING) {
2113 ret = nwam_value_create_string_array(val, n, &data);
2114 } else if (value_type == NWAM_VALUE_TYPE_INT64) {
2115 ret = nwam_value_create_int64_array(int_vals, n, &data);
2116 free(int_vals);
2117 } else if (value_type == NWAM_VALUE_TYPE_UINT64) {
2118 ret = nwam_value_create_uint64_array(uint_vals, n, &data);
2119 free(uint_vals);
2120 } else if (value_type == NWAM_VALUE_TYPE_BOOLEAN) {
2121 ret = nwam_value_create_boolean_array(boolean_vals, n, &data);
2122 free(boolean_vals);
2124 array_free((void **)val, max_str_num);
2126 if (ret != NWAM_SUCCESS) {
2127 nwamerr(ret, "Failed creating nwam_value");
2128 return (NULL);
2131 return (data);
2135 * Displaying/Skipping of properties
2136 * ---------------------------------
2138 * This table shows if a specific property should be shown if some
2139 * other property has a specific value. This table is used by
2140 * show_prop_test(), which is called by set_func() and walkprop_func().
2142 * An entry in the table looks like:
2143 * { property1, property2, { val1, val2, -1 } }
2144 * This is read as:
2145 * "show property1 only if property2 has value val1 or val2"
2147 * NB: If a property does not appear in this table, then that implies
2148 * that the property is always shown.
2150 * A property can have more than one rule. In such a case, the property is
2151 * displayed only any of the rules is satisfied. This checking, however,
2152 * is recursive. If a rule says that a property can be displayed, then the
2153 * property that's checked should also satisfy its rules. In the above
2154 * example, if property1 is to be displayed, then property2 should also
2155 * satisfy its rules and be displayable. This recursion is necessary as
2156 * properties that are not displayed (because rules are not satisfied) are
2157 * not deleted.
2160 /* The most number of values in pde_checkvals below */
2161 #define NWAM_CHECKVALS_MAX 5
2163 typedef struct prop_display_entry {
2164 const char *pde_name; /* property to show */
2165 const char *pde_checkname; /* property to check */
2166 int64_t pde_checkvals[NWAM_CHECKVALS_MAX]; /* show prop for these */
2167 } prop_display_entry_t;
2169 /* Rules for showing properties: commented for clarity */
2172 * Rules for NCUs
2173 * NB: There is no need to have an entry if a property is for IP only.
2174 * This is taken care of in libnwam_ncp.c
2176 static prop_display_entry_t ncu_prop_display_entry_table[] = {
2177 /* show priority-{group,mode} if activation == prioritized */
2178 { NWAM_NCU_PROP_PRIORITY_GROUP, NWAM_NCU_PROP_ACTIVATION_MODE,
2179 { NWAM_ACTIVATION_MODE_PRIORITIZED, -1 } },
2180 { NWAM_NCU_PROP_PRIORITY_MODE, NWAM_NCU_PROP_ACTIVATION_MODE,
2181 { NWAM_ACTIVATION_MODE_PRIORITIZED, -1 } },
2182 /* show ipv4-addrsrc if ip-version == ipv4 */
2183 { NWAM_NCU_PROP_IPV4_ADDRSRC, NWAM_NCU_PROP_IP_VERSION,
2184 { IPV4_VERSION, -1 } },
2185 /* show ipv4-addr if ipv4-addrsrc == static */
2186 { NWAM_NCU_PROP_IPV4_ADDR, NWAM_NCU_PROP_IPV4_ADDRSRC,
2187 { NWAM_ADDRSRC_STATIC, -1 } },
2188 /* show ipv4-default-route if ip-version == ipv4 */
2189 { NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE, NWAM_NCU_PROP_IP_VERSION,
2190 { IPV4_VERSION, -1 } },
2191 /* show ipv6-addrsrc if ip-version == ipv6 */
2192 { NWAM_NCU_PROP_IPV6_ADDRSRC, NWAM_NCU_PROP_IP_VERSION,
2193 { IPV6_VERSION, -1 } },
2194 /* show ipv6-addr if ipv6-addrsrc == static */
2195 { NWAM_NCU_PROP_IPV6_ADDR, NWAM_NCU_PROP_IPV6_ADDRSRC,
2196 { NWAM_ADDRSRC_STATIC, -1 } },
2197 /* show ipv6-default-route if ip-version == ipv6 */
2198 { NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE, NWAM_NCU_PROP_IP_VERSION,
2199 { IPV6_VERSION, -1 } },
2200 { NULL, NULL, { -1 } }
2203 /* Rules for ENMs */
2204 static prop_display_entry_t enm_prop_display_entry_table[] = {
2205 /* show conditions if activation-mode == conditional-{all,any} */
2206 { NWAM_ENM_PROP_CONDITIONS, NWAM_ENM_PROP_ACTIVATION_MODE,
2207 { NWAM_ACTIVATION_MODE_CONDITIONAL_ALL,
2208 NWAM_ACTIVATION_MODE_CONDITIONAL_ANY, -1 } },
2209 { NULL, NULL, { -1 } }
2212 /* Rules for LOCations */
2213 static prop_display_entry_t loc_prop_display_entry_table[] = {
2214 /* show conditions if activation-mode == conditional-{all,any} */
2215 { NWAM_LOC_PROP_CONDITIONS, NWAM_LOC_PROP_ACTIVATION_MODE,
2216 { NWAM_ACTIVATION_MODE_CONDITIONAL_ALL,
2217 NWAM_ACTIVATION_MODE_CONDITIONAL_ANY, -1 } },
2218 /* show dns-nameservice-configsrc if nameservices == dns */
2219 { NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC, NWAM_LOC_PROP_NAMESERVICES,
2220 { NWAM_NAMESERVICES_DNS, -1 } },
2221 /* show other DNS options if dns-nameservices-configsrc == manual */
2222 { NWAM_LOC_PROP_DNS_NAMESERVICE_DOMAIN,
2223 NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
2224 { NWAM_CONFIGSRC_MANUAL, -1 } },
2225 { NWAM_LOC_PROP_DNS_NAMESERVICE_SERVERS,
2226 NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
2227 { NWAM_CONFIGSRC_MANUAL, -1 } },
2228 { NWAM_LOC_PROP_DNS_NAMESERVICE_SEARCH,
2229 NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
2230 { NWAM_CONFIGSRC_MANUAL, -1 } },
2231 /* show nis-nameservice-configsrc if nameservices == nis */
2232 { NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC, NWAM_LOC_PROP_NAMESERVICES,
2233 { NWAM_NAMESERVICES_NIS, -1 } },
2234 /* show nis-nameservice-servers if nis-nameservice-configsrc = manual */
2235 { NWAM_LOC_PROP_NIS_NAMESERVICE_SERVERS,
2236 NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC,
2237 { NWAM_CONFIGSRC_MANUAL, -1 } },
2238 /* show ldap-nameservice-configsrc if nameservices == ldap */
2239 { NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC, NWAM_LOC_PROP_NAMESERVICES,
2240 { NWAM_NAMESERVICES_LDAP, -1 } },
2241 /* show ldap-nameservice-servers if ldap-nameservice-configsrc=manual */
2242 { NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS,
2243 NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
2244 { NWAM_CONFIGSRC_MANUAL, -1 } },
2245 /* show default-domain if {nis,ldap}-nameservice-configsrc == manual */
2246 { NWAM_LOC_PROP_DEFAULT_DOMAIN, NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC,
2247 { NWAM_CONFIGSRC_MANUAL, -1 } },
2248 { NWAM_LOC_PROP_DEFAULT_DOMAIN,
2249 NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
2250 { NWAM_CONFIGSRC_MANUAL, -1 } },
2251 { NULL, NULL, { -1 } }
2254 /* Rules for Known WLANs */
2255 static prop_display_entry_t wlan_prop_display_entry_table[] = {
2256 /* no rules for WLANs */
2257 { NULL, NULL, { -1 } }
2260 /* Returns the appropriate rules table for the given object type */
2261 static prop_display_entry_t *
2262 get_prop_display_table(nwam_object_type_t object_type)
2264 switch (object_type) {
2265 case NWAM_OBJECT_TYPE_NCU:
2266 return (ncu_prop_display_entry_table);
2267 case NWAM_OBJECT_TYPE_LOC:
2268 return (loc_prop_display_entry_table);
2269 case NWAM_OBJECT_TYPE_ENM:
2270 return (enm_prop_display_entry_table);
2271 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2272 return (wlan_prop_display_entry_table);
2274 return (NULL);
2278 * Tests whether prop must be shown during a walk depending on the
2279 * value of a different property.
2281 * This function is also used by set_func() to determine whether the
2282 * property being set should be allowed or not. If the property
2283 * would not be displayed in a walk, then it should not be set.
2285 * The checked_props and num_checked arguments are used to avoid circular
2286 * dependencies between properties. When this function recursively calls
2287 * itself, it adds the property that it just checked to the checked_props
2288 * list.
2290 static boolean_t
2291 show_prop_test(nwam_object_type_t object_type, const char *prop,
2292 prop_display_entry_t *display_list, char **checked_props, int num_checked)
2294 nwam_error_t ret;
2295 nwam_value_t prop_val;
2296 nwam_value_type_t prop_type;
2297 int i, j, k;
2298 boolean_t prop_found = B_FALSE, show_prop = B_FALSE;
2301 * Check if this property has already been checked previously in
2302 * the recursion. If so, return B_FALSE so that the initial prop
2303 * is not displayed.
2305 for (i = 0; i < num_checked; i++) {
2306 if (strcmp(prop, checked_props[i]) == 0) {
2307 free(checked_props);
2308 return (B_FALSE);
2312 for (i = 0; display_list[i].pde_name != NULL; i++) {
2313 if (strcmp(prop, display_list[i].pde_name) != 0)
2314 continue;
2315 prop_found = B_TRUE;
2317 /* get the value(s) of the (other) property to check */
2318 switch (object_type) {
2319 case NWAM_OBJECT_TYPE_NCU:
2320 ret = nwam_ncu_get_prop_value(ncu_h,
2321 display_list[i].pde_checkname, &prop_val);
2322 break;
2323 case NWAM_OBJECT_TYPE_LOC:
2324 ret = nwam_loc_get_prop_value(loc_h,
2325 display_list[i].pde_checkname, &prop_val);
2326 break;
2327 case NWAM_OBJECT_TYPE_ENM:
2328 ret = nwam_enm_get_prop_value(enm_h,
2329 display_list[i].pde_checkname, &prop_val);
2330 break;
2331 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2332 return (B_TRUE);
2334 if (ret != NWAM_SUCCESS)
2335 continue;
2337 /* prop_val may contain a uint64 array or a boolean */
2338 if (nwam_value_get_type(prop_val, &prop_type) != NWAM_SUCCESS)
2339 continue;
2341 if (prop_type == NWAM_VALUE_TYPE_UINT64) {
2342 uint64_t *prop_uvals;
2343 int64_t *check_uvals;
2344 uint_t numvals;
2346 if (nwam_value_get_uint64_array(prop_val, &prop_uvals,
2347 &numvals) != NWAM_SUCCESS) {
2348 nwam_value_free(prop_val);
2349 continue;
2352 /* for each value in uvals, check each value in table */
2353 for (j = 0; j < numvals; j++) {
2354 check_uvals = display_list[i].pde_checkvals;
2355 for (k = 0; check_uvals[k] != -1; k++) {
2356 /* show if uvals[j] matches */
2357 if (prop_uvals[j] ==
2358 (uint64_t)check_uvals[k]) {
2359 show_prop = B_TRUE;
2360 goto next_rule;
2364 } else if (prop_type == NWAM_VALUE_TYPE_BOOLEAN) {
2365 boolean_t bval;
2367 if (nwam_value_get_boolean(prop_val, &bval) !=
2368 NWAM_SUCCESS) {
2369 nwam_value_free(prop_val);
2370 continue;
2373 for (k = 0;
2374 display_list[i].pde_checkvals[k] != -1;
2375 k++) {
2376 /* show if bval matches */
2377 if (bval == (boolean_t)
2378 display_list[i].pde_checkvals[k]) {
2379 show_prop = B_TRUE;
2380 goto next_rule;
2385 next_rule:
2386 nwam_value_free(prop_val);
2388 * If show_prop is set, then a rule is satisfied; no need to
2389 * check other rules for this prop. However, recursively
2390 * check if the checked prop (pde_checkname) satisfies its
2391 * rules. Also, update the check_props array with this prop.
2393 if (show_prop) {
2394 char **newprops = realloc(checked_props,
2395 ++num_checked * sizeof (char *));
2396 if (newprops == NULL) {
2397 free(checked_props);
2398 return (B_FALSE);
2400 checked_props = newprops;
2401 checked_props[num_checked - 1] = (char *)prop;
2403 return (show_prop_test(object_type,
2404 display_list[i].pde_checkname, display_list,
2405 checked_props, num_checked));
2410 * If we are here and prop_found is set, it means that no rules were
2411 * satisfied by prop; return B_FALSE. If prop_found is not set, then
2412 * prop did not have a rule so it must be displayed; return B_TRUE.
2414 free(checked_props);
2415 if (prop_found)
2416 return (B_FALSE);
2417 else
2418 return (B_TRUE);
2422 * Returns true if the given property is read-only and cannot be modified.
2424 static boolean_t
2425 is_prop_read_only(nwam_object_type_t object_type, const char *prop)
2427 boolean_t ro;
2429 switch (object_type) {
2430 case NWAM_OBJECT_TYPE_NCU:
2431 if (nwam_ncu_prop_read_only(prop, &ro) == NWAM_SUCCESS && ro)
2432 return (B_TRUE);
2433 break;
2434 case NWAM_OBJECT_TYPE_ENM:
2435 if (nwam_enm_prop_read_only(prop, &ro) == NWAM_SUCCESS && ro)
2436 return (B_TRUE);
2437 break;
2438 case NWAM_OBJECT_TYPE_LOC:
2439 if (nwam_loc_prop_read_only(prop, &ro) == NWAM_SUCCESS && ro)
2440 return (B_TRUE);
2441 break;
2442 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2443 /* no read-only properties for WLANs */
2444 return (B_FALSE);
2446 return (B_FALSE);
2449 /* Returns true if the property is multi-valued */
2450 static boolean_t
2451 is_prop_multivalued(nwam_object_type_t object_type, const char *prop)
2453 nwam_error_t ret;
2454 boolean_t multi;
2456 switch (object_type) {
2457 case NWAM_OBJECT_TYPE_NCU:
2458 ret = nwam_ncu_prop_multivalued(prop, &multi);
2459 break;
2460 case NWAM_OBJECT_TYPE_LOC:
2461 ret = nwam_loc_prop_multivalued(prop, &multi);
2462 break;
2463 case NWAM_OBJECT_TYPE_ENM:
2464 ret = nwam_enm_prop_multivalued(prop, &multi);
2465 break;
2466 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2467 ret = nwam_known_wlan_prop_multivalued(prop, &multi);
2468 break;
2471 if (ret != NWAM_SUCCESS)
2472 multi = B_FALSE;
2473 return (multi);
2477 * Prints out error message specific to property that could not be set.
2478 * Property description is used to help guide user in entering correct value.
2480 static void
2481 invalid_set_prop_msg(const char *prop, nwam_error_t err)
2483 const char *description;
2485 if (err == NWAM_SUCCESS)
2486 return;
2488 if (err != NWAM_ENTITY_INVALID_VALUE) {
2489 nwamerr(err, "Set error");
2490 return;
2493 switch (active_object_type()) {
2494 case NWAM_OBJECT_TYPE_NCU:
2495 (void) nwam_ncu_get_prop_description(prop, &description);
2496 break;
2497 case NWAM_OBJECT_TYPE_LOC:
2498 (void) nwam_loc_get_prop_description(prop, &description);
2499 break;
2500 case NWAM_OBJECT_TYPE_ENM:
2501 (void) nwam_enm_get_prop_description(prop, &description);
2502 break;
2503 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2504 (void) nwam_known_wlan_get_prop_description(prop,
2505 &description);
2506 break;
2508 nerr("Set error: invalid value\n'%s' %s", prop, description);
2512 * Sets the property value.
2513 * Read-only properties and objects cannot be set.
2514 * "read-only" is a special in that it can be set on a read-only object.
2515 * The object has to be committed before other properties can be set.
2516 * Also uses show_prop_test() to test if the property being set would
2517 * be skipped during a walk (as determined by the value of some other
2518 * property). If so, then it cannot be set.
2520 void
2521 set_func(cmd_t *cmd)
2523 int pt_type = cmd->cmd_prop_type;
2524 nwam_error_t ret = NWAM_SUCCESS;
2525 nwam_value_t prop_value;
2526 const char *prop;
2527 boolean_t is_listprop = B_FALSE;
2528 nwam_object_type_t object_type;
2529 prop_display_entry_t *prop_table;
2530 char **checked = NULL;
2532 assert(cmd->cmd_argc > 0);
2534 object_type = active_object_type();
2535 prop_table = get_prop_display_table(object_type);
2537 /* argv[0] is property value */
2538 if ((prop = pt_to_prop_name(object_type, pt_type)) == NULL) {
2539 nerr("Set error: invalid %s property: '%s'",
2540 scope_to_str(current_scope), pt_to_str(pt_type));
2541 return;
2544 /* check if property can be set */
2545 if (is_prop_read_only(object_type, prop)) {
2546 nerr("Set error: property '%s' is read-only", prop);
2547 return;
2549 if (!show_prop_test(object_type, prop, prop_table, checked, 0)) {
2550 if (interactive_mode) {
2551 (void) printf(gettext("setting property '%s' "
2552 "has no effect\n"), prop);
2556 is_listprop = is_prop_multivalued(object_type, prop);
2557 prop_value = str_to_nwam_value(object_type, cmd->cmd_argv[0], pt_type,
2558 is_listprop);
2559 if (prop_value == NULL) {
2560 invalid_set_prop_msg(prop, NWAM_ENTITY_INVALID_VALUE);
2561 return;
2564 /* set the property value */
2565 switch (object_type) {
2566 case NWAM_OBJECT_TYPE_NCU:
2567 ret = nwam_ncu_set_prop_value(ncu_h, prop, prop_value);
2568 break;
2569 case NWAM_OBJECT_TYPE_LOC:
2570 ret = nwam_loc_set_prop_value(loc_h, prop, prop_value);
2571 break;
2572 case NWAM_OBJECT_TYPE_ENM:
2573 ret = nwam_enm_set_prop_value(enm_h, prop, prop_value);
2574 break;
2575 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2576 ret = nwam_known_wlan_set_prop_value(wlan_h, prop, prop_value);
2577 break;
2579 nwam_value_free(prop_value);
2581 /* delete other properties if needed */
2582 if (ret == NWAM_SUCCESS)
2583 need_to_commit = B_TRUE;
2584 else
2585 invalid_set_prop_msg(prop, ret);
2588 static int
2589 list_callback(nwam_object_type_t object_type, void *handle,
2590 boolean_t *list_msgp, const char *msg)
2592 nwam_error_t ret;
2593 char *name;
2594 nwam_ncu_class_t class;
2596 if (*list_msgp) {
2597 (void) printf("%s:\n", msg);
2598 *list_msgp = B_FALSE;
2601 ret = object_name_from_handle(object_type, handle, &name);
2602 if (ret != NWAM_SUCCESS) {
2603 nwamerr(ret, "List error: failed to get name");
2604 return (1);
2607 /* If NCU, get its class and print */
2608 if (object_type == NWAM_OBJECT_TYPE_NCU) {
2609 if ((ret = nwam_ncu_get_ncu_class(handle, &class))
2610 != NWAM_SUCCESS) {
2611 nwamerr(ret, "List error: failed to get ncu class");
2612 free(name);
2613 return (1);
2614 } else {
2615 (void) printf("\t%s",
2616 propval_to_str(NWAM_NCU_PROP_CLASS, class));
2619 (void) printf("\t%s\n", name);
2621 free(name);
2622 return (0);
2625 /* Print out name, type and status */
2626 static int
2627 list_loc_callback(nwam_loc_handle_t loc, void *arg)
2629 return (list_callback(NWAM_OBJECT_TYPE_LOC, loc, arg, "Locations"));
2632 static int
2633 list_enm_callback(nwam_enm_handle_t enm, void *arg)
2635 return (list_callback(NWAM_OBJECT_TYPE_ENM, enm, arg, "ENMs"));
2638 static int
2639 list_wlan_callback(nwam_known_wlan_handle_t wlan, void *arg)
2641 return (list_callback(NWAM_OBJECT_TYPE_KNOWN_WLAN, wlan, arg, "WLANs"));
2644 static int
2645 list_ncp_callback(nwam_ncp_handle_t ncp, void *arg)
2647 return (list_callback(NWAM_OBJECT_TYPE_NCP, ncp, arg, "NCPs"));
2650 static int
2651 list_ncu_callback(nwam_ncu_handle_t ncu, void *arg)
2653 return (list_callback(NWAM_OBJECT_TYPE_NCU, ncu, arg, "NCUs"));
2656 /* functions to convert a value to a string */
2657 /* ARGSUSED */
2658 static const char *
2659 str2str(void *s, const char *prop, char *str)
2661 (void) snprintf(str, NWAM_MAX_VALUE_LEN, "%s", s);
2662 return (str);
2665 /* ARGSUSED */
2666 static const char *
2667 str2qstr(void *s, const char *prop, char *qstr)
2669 /* quoted strings */
2670 (void) snprintf(qstr, NWAM_MAX_VALUE_LEN, "\"%s\"", s);
2671 return (qstr);
2674 /* ARGSUSED */
2675 static const char *
2676 int2str(void *in, const char *prop, char *instr)
2678 (void) snprintf(instr, NWAM_MAX_VALUE_LEN, "%lld", *((int64_t *)in));
2679 return (instr);
2682 static const char *
2683 uint2str(void *uin, const char *prop, char *uintstr)
2685 /* returns NWAM_SUCCESS if prop is enum with string in uintstr */
2686 if (nwam_uint64_get_value_string(prop, *((uint64_t *)uin),
2687 (const char **)&uintstr) != NWAM_SUCCESS) {
2688 (void) snprintf(uintstr, NWAM_MAX_VALUE_LEN, "%lld",
2689 *((uint64_t *)uin));
2691 return (uintstr);
2694 /* ARGSUSED */
2695 static const char *
2696 bool2str(void *bool, const char *prop, char *boolstr)
2698 (void) snprintf(boolstr, NWAM_MAX_VALUE_LEN, "%s",
2699 *((boolean_t *)bool) ? "true" : "false");
2700 return (boolstr);
2704 * Print the value (enums are converted to string), use DELIMITER for
2705 * array. If strings are to be "quoted", pass B_TRUE for quoted_strings.
2707 static void
2708 output_prop_val(const char *prop_name, nwam_value_t value, FILE *wf,
2709 boolean_t quoted_strings)
2711 nwam_value_type_t value_type;
2712 uint_t num;
2714 /* arrays for values retrieved according to the type of value */
2715 char **svals;
2716 uint64_t *uvals;
2717 int64_t *ivals;
2718 boolean_t *bvals;
2720 /* pointer to function to generate string representation of value */
2721 const char *(*tostr)(void *, const char *, char *);
2722 char str[NWAM_MAX_VALUE_LEN]; /* to store the string */
2723 int i;
2725 if (nwam_value_get_type(value, &value_type) != NWAM_SUCCESS) {
2726 nerr("Get value type error");
2727 return;
2730 if (value_type == NWAM_VALUE_TYPE_STRING) {
2731 if (nwam_value_get_string_array(value, &svals, &num) !=
2732 NWAM_SUCCESS) {
2733 nerr("Get string array error");
2734 return;
2736 tostr = quoted_strings ? str2qstr : str2str;
2737 } else if (value_type == NWAM_VALUE_TYPE_INT64) {
2738 if (nwam_value_get_int64_array(value, &ivals, &num) !=
2739 NWAM_SUCCESS) {
2740 nerr("Get int64 array error");
2741 return;
2743 tostr = int2str;
2744 } else if (value_type == NWAM_VALUE_TYPE_UINT64) {
2745 if (nwam_value_get_uint64_array(value, &uvals, &num) !=
2746 NWAM_SUCCESS) {
2747 nerr("Get uint64 array error");
2748 return;
2750 tostr = uint2str;
2751 } else if (value_type == NWAM_VALUE_TYPE_BOOLEAN) {
2752 if (nwam_value_get_boolean_array(value, &bvals, &num) !=
2753 NWAM_SUCCESS) {
2754 nerr("Get boolean array error");
2755 return;
2757 tostr = bool2str;
2760 /* now, loop and print each value */
2761 for (i = 0; i < num; i++) {
2762 void *val;
2764 /* get the pointer to the ith value to pass to func() */
2765 if (value_type == NWAM_VALUE_TYPE_STRING)
2766 val = svals[i];
2767 else if (value_type == NWAM_VALUE_TYPE_UINT64)
2768 val = &(uvals[i]);
2769 else if (value_type == NWAM_VALUE_TYPE_INT64)
2770 val = &(ivals[i]);
2771 else if (value_type == NWAM_VALUE_TYPE_BOOLEAN)
2772 val = &(bvals[i]);
2774 (void) fprintf(wf, "%s%s", tostr(val, prop_name, str),
2775 i != num-1 ? NWAM_VALUE_DELIMITER_STR : "");
2779 /* Prints the property names aligned (for list/get) or "prop=" (for export) */
2780 static int
2781 output_propname_common(const char *prop, nwam_value_t values, void *arg,
2782 int width)
2784 FILE *of = (arg == NULL) ? stdout : arg;
2786 /* arg is NULL for list/get, not NULL for export */
2787 if (arg == NULL)
2788 (void) fprintf(of, "\t%-*s\t", width, prop);
2789 else
2790 (void) fprintf(of, "%s=", prop);
2792 if (values != NULL)
2793 output_prop_val(prop, values, of, B_TRUE);
2795 (void) fprintf(of, "\n");
2796 return (0);
2799 static int
2800 output_propname(const char *prop, nwam_value_t values, void *arg)
2802 return (output_propname_common(prop, values, arg, 16));
2805 /* For locations because of longer property names */
2806 static int
2807 output_loc_propname(const char *prop, nwam_value_t values, void *arg)
2809 return (output_propname_common(prop, values, arg, 25));
2813 * all_props specifies whether properties that have not been set should be
2814 * printed or not. ncp and ncu_type are used only when the object_type is
2815 * NCU.
2817 static nwam_error_t
2818 listprop(nwam_object_type_t object_type, void *handle, const char *name,
2819 boolean_t all_props, nwam_ncp_handle_t ncp, nwam_ncu_type_t ncu_type)
2821 nwam_error_t ret;
2822 char *lname = NULL, *realname = NULL;
2823 boolean_t lhandle = B_FALSE;
2824 const char **props = NULL;
2825 uint_t prop_num;
2826 int i;
2827 nwam_value_t vals;
2830 * handle is NULL if called from a scope higher than the object's
2831 * scope, but name must be given; so get the handle.
2833 if (handle == NULL) {
2834 lname = trim_quotes(name); /* name may have quotes */
2835 switch (object_type) {
2836 case NWAM_OBJECT_TYPE_NCP:
2837 if ((ret = nwam_ncp_read(lname, 0,
2838 (nwam_ncp_handle_t *)&handle)) != NWAM_SUCCESS)
2839 goto readfail;
2840 break;
2841 case NWAM_OBJECT_TYPE_NCU:
2842 ret = nwam_ncu_read(ncp, lname, ncu_type, 0,
2843 (nwam_ncu_handle_t *)&handle);
2844 if (ret == NWAM_ENTITY_MULTIPLE_VALUES) {
2846 * Multiple NCUs with the given name exists.
2847 * Call listprop() for each NCU type.
2849 if ((ret = listprop(object_type, NULL, lname,
2850 all_props, ncp, NWAM_NCU_TYPE_LINK))
2851 != NWAM_SUCCESS)
2852 goto done;
2853 ret = listprop(object_type, NULL, lname,
2854 all_props, ncp, NWAM_NCU_TYPE_INTERFACE);
2855 goto done;
2856 } else if (ret != NWAM_SUCCESS) {
2857 goto readfail;
2859 break;
2860 case NWAM_OBJECT_TYPE_LOC:
2861 if ((ret = nwam_loc_read(lname, 0,
2862 (nwam_loc_handle_t *)&handle)) != NWAM_SUCCESS)
2863 goto readfail;
2864 break;
2865 case NWAM_OBJECT_TYPE_ENM:
2866 if ((ret = nwam_enm_read(lname, 0,
2867 (nwam_enm_handle_t *)&handle)) != NWAM_SUCCESS)
2868 goto readfail;
2869 break;
2870 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2871 if ((ret = nwam_known_wlan_read(lname, 0,
2872 (nwam_known_wlan_handle_t *)&handle))
2873 != NWAM_SUCCESS)
2874 goto readfail;
2875 break;
2877 lhandle = B_TRUE;
2880 if ((ret = object_name_from_handle(object_type, handle, &realname))
2881 != NWAM_SUCCESS)
2882 goto done;
2884 /* get the property list */
2885 switch (object_type) {
2886 case NWAM_OBJECT_TYPE_NCP:
2888 /* walk NCUs */
2889 boolean_t list_msg = B_TRUE;
2890 ret = nwam_ncp_walk_ncus(handle, list_ncu_callback, &list_msg,
2891 NWAM_FLAG_NCU_TYPE_CLASS_ALL, NULL);
2892 goto done;
2894 case NWAM_OBJECT_TYPE_NCU:
2896 nwam_ncu_type_t ncu_type;
2897 nwam_ncu_class_t ncu_class;
2899 if ((ret = nwam_ncu_get_ncu_type(handle, &ncu_type))
2900 != NWAM_SUCCESS)
2901 goto done;
2902 if ((ret = nwam_ncu_get_ncu_class(handle, &ncu_class))
2903 != NWAM_SUCCESS)
2904 goto done;
2906 ret = nwam_ncu_get_default_proplist(ncu_type, ncu_class, &props,
2907 &prop_num);
2908 break;
2910 case NWAM_OBJECT_TYPE_LOC:
2911 ret = nwam_loc_get_default_proplist(&props, &prop_num);
2912 break;
2913 case NWAM_OBJECT_TYPE_ENM:
2914 ret = nwam_enm_get_default_proplist(&props, &prop_num);
2915 break;
2916 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2917 ret = nwam_known_wlan_get_default_proplist(&props, &prop_num);
2918 break;
2920 if (ret != NWAM_SUCCESS)
2921 goto done;
2923 /* print object type and name */
2924 (void) printf("%s:%s\n", nwam_object_type_to_string(object_type),
2925 realname);
2927 /* Loop through the properties and print */
2928 for (i = 0; i < prop_num; i++) {
2929 /* get the existing value for this property */
2930 switch (object_type) {
2931 case NWAM_OBJECT_TYPE_NCU:
2932 ret = nwam_ncu_get_prop_value(handle, props[i], &vals);
2933 break;
2934 case NWAM_OBJECT_TYPE_LOC:
2935 ret = nwam_loc_get_prop_value(handle, props[i], &vals);
2936 break;
2937 case NWAM_OBJECT_TYPE_ENM:
2938 ret = nwam_enm_get_prop_value(handle, props[i], &vals);
2939 break;
2940 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2941 ret = nwam_known_wlan_get_prop_value(handle, props[i],
2942 &vals);
2943 break;
2945 if (ret != NWAM_SUCCESS) {
2946 /* _ENTITY_NOT_FOUND is ok if listing for all props */
2947 if (!all_props)
2948 continue;
2949 else if (ret != NWAM_ENTITY_NOT_FOUND)
2950 continue;
2953 /* print property and value */
2954 if (object_type == NWAM_OBJECT_TYPE_LOC)
2955 output_loc_propname(props[i], vals, NULL);
2956 else
2957 output_propname(props[i], vals, NULL);
2958 nwam_value_free(vals);
2961 done:
2962 free(lname);
2963 free(realname);
2964 if (props != NULL)
2965 free(props);
2966 if (lhandle) {
2967 switch (object_type) {
2968 case NWAM_OBJECT_TYPE_NCP:
2969 nwam_ncp_free(handle);
2970 break;
2971 case NWAM_OBJECT_TYPE_NCU:
2972 nwam_ncu_free(handle);
2973 break;
2974 case NWAM_OBJECT_TYPE_LOC:
2975 nwam_loc_free(handle);
2976 break;
2977 case NWAM_OBJECT_TYPE_ENM:
2978 nwam_enm_free(handle);
2979 break;
2980 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
2981 nwam_known_wlan_free(handle);
2982 break;
2985 /* don't treat _ENTITY_NOT_FOUND as an error */
2986 if (ret == NWAM_ENTITY_NOT_FOUND)
2987 ret = NWAM_SUCCESS;
2988 return (ret);
2990 readfail:
2991 /* When nwam_*_read() fails */
2992 free(lname);
2993 return (ret);
2997 * List profiles or property and its values.
2998 * If the -a option is specified, all properties are listed.
3000 void
3001 list_func(cmd_t *cmd)
3003 nwam_error_t ret = NWAM_SUCCESS;
3004 boolean_t list_msg = B_TRUE;
3006 boolean_t list_loc = B_FALSE, list_enm = B_FALSE;
3007 boolean_t list_ncp = B_FALSE, list_ncu = B_FALSE;
3008 boolean_t list_wlan = B_FALSE;
3010 /* whether all properties should be listed, given by the -a option */
3011 boolean_t all_props = B_FALSE;
3014 * list_props says whether the properties should be listed.
3015 * Note that, here NCUs are treated as properties of NCPs.
3017 boolean_t list_props = B_FALSE;
3019 /* determine which properties to list, also validity tests */
3020 if (current_scope == NWAM_SCOPE_GBL) {
3021 /* res1_type is -1 if only "list -a" is used */
3022 if (cmd->cmd_res1_type == -1) {
3023 nerr("'list' requires an object to be specified with "
3024 "the -a option in the global scope");
3025 return;
3027 if (cmd->cmd_res1_type == RT1_LOC) {
3028 list_props = B_TRUE;
3029 list_loc = B_TRUE;
3030 } else if (cmd->cmd_res1_type == RT1_ENM) {
3031 list_props = B_TRUE;
3032 list_enm = B_TRUE;
3033 } else if (cmd->cmd_res1_type == RT1_WLAN) {
3034 list_props = B_TRUE;
3035 list_wlan = B_TRUE;
3036 } else if (cmd->cmd_res1_type == RT1_NCP) {
3037 list_ncp = B_TRUE;
3038 list_props = B_TRUE;
3039 } else {
3040 list_loc = B_TRUE;
3041 list_enm = B_TRUE;
3042 list_wlan = B_TRUE;
3043 list_ncp = B_TRUE;
3046 if ((current_scope == NWAM_SCOPE_LOC ||
3047 current_scope == NWAM_SCOPE_ENM ||
3048 current_scope == NWAM_SCOPE_WLAN ||
3049 current_scope == NWAM_SCOPE_NCU) &&
3050 (cmd->cmd_argc >= 1 && cmd->cmd_res1_type != -1)) {
3051 nerr("Additional options are not allowed with the -a option "
3052 "at this scope");
3053 return;
3055 if (current_scope == NWAM_SCOPE_LOC) {
3056 list_loc = B_TRUE;
3057 list_props = B_TRUE;
3059 if (current_scope == NWAM_SCOPE_ENM) {
3060 list_enm = B_TRUE;
3061 list_props = B_TRUE;
3063 if (current_scope == NWAM_SCOPE_WLAN) {
3064 list_wlan = B_TRUE;
3065 list_props = B_TRUE;
3067 if (current_scope == NWAM_SCOPE_NCP) {
3068 if (cmd->cmd_res1_type == RT1_ENM ||
3069 cmd->cmd_res1_type == RT1_LOC ||
3070 cmd->cmd_res1_type == RT1_WLAN) {
3071 nerr("only ncu can be listed at this scope");
3072 return;
3074 if (cmd->cmd_res2_type == RT2_NCU) {
3075 list_ncu = B_TRUE;
3076 list_props = B_TRUE;
3077 } else {
3078 list_ncp = B_TRUE;
3079 list_props = B_TRUE;
3082 if (current_scope == NWAM_SCOPE_NCU) {
3083 list_ncu = B_TRUE;
3084 list_props = B_TRUE;
3087 /* Check if the -a option is specified to list all properties */
3088 if (cmd->cmd_res1_type == -1 || cmd->cmd_argc == 2) {
3089 int c, argc = 1;
3090 char **argv;
3091 optind = 0;
3093 /* if res1_type is -1, option is in argv[0], else in argv[1] */
3094 if (cmd->cmd_res1_type == -1)
3095 argv = cmd->cmd_argv;
3096 else
3097 argv = &(cmd->cmd_argv[1]);
3098 while ((c = getopt(argc, argv, "a")) != EOF) {
3099 switch (c) {
3100 case 'a':
3101 all_props = B_TRUE;
3102 break;
3103 default:
3104 command_usage(CMD_LIST);
3105 return;
3108 if (cmd->cmd_res1_type == -1)
3109 cmd->cmd_argv[0] = NULL;
3113 * Now, print objects and/or according to the flags set.
3114 * name, if requested, is in argv[0].
3116 if (list_ncp) {
3117 list_msg = B_TRUE;
3118 if (list_props) {
3119 ret = listprop(NWAM_OBJECT_TYPE_NCP, ncp_h,
3120 cmd->cmd_argv[0], all_props, NULL, -1);
3121 } else {
3122 ret = nwam_walk_ncps(list_ncp_callback, &list_msg, 0,
3123 NULL);
3125 if (ret != NWAM_SUCCESS)
3126 goto done;
3129 if (list_ncu) {
3130 list_msg = B_TRUE;
3131 if (ncp_h == NULL) {
3132 nerr("NCP has not been read");
3133 return;
3135 if (list_props) {
3136 nwam_ncu_class_t ncu_class;
3137 nwam_ncu_type_t ncu_type;
3139 /* determine the NCU type first */
3140 if (ncu_h == NULL) {
3141 ncu_class = (nwam_ncu_class_t)
3142 cmd->cmd_ncu_class_type;
3143 ncu_type = nwam_ncu_class_to_type(ncu_class);
3144 } else {
3145 if ((ret = nwam_ncu_get_ncu_type(ncu_h,
3146 &ncu_type)) != NWAM_SUCCESS)
3147 goto done;
3149 ret = listprop(NWAM_OBJECT_TYPE_NCU, ncu_h,
3150 cmd->cmd_argv[0], all_props, ncp_h, ncu_type);
3151 if (ret != NWAM_SUCCESS)
3152 goto done;
3156 if (list_loc) {
3157 list_msg = B_TRUE;
3158 if (list_props) {
3159 ret = listprop(NWAM_OBJECT_TYPE_LOC, loc_h,
3160 cmd->cmd_argv[0], all_props, NULL, -1);
3161 } else {
3162 ret = nwam_walk_locs(list_loc_callback, &list_msg,
3163 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
3165 if (ret != NWAM_SUCCESS)
3166 goto done;
3169 if (list_enm) {
3170 list_msg = B_TRUE;
3171 if (list_props) {
3172 ret = listprop(NWAM_OBJECT_TYPE_ENM, enm_h,
3173 cmd->cmd_argv[0], all_props, NULL, -1);
3174 } else {
3175 ret = nwam_walk_enms(list_enm_callback, &list_msg,
3176 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
3178 if (ret != NWAM_SUCCESS)
3179 goto done;
3182 if (list_wlan) {
3183 list_msg = B_TRUE;
3184 if (list_props) {
3185 ret = listprop(NWAM_OBJECT_TYPE_KNOWN_WLAN, wlan_h,
3186 cmd->cmd_argv[0], all_props, NULL, -1);
3187 } else {
3188 ret = nwam_walk_known_wlans(list_wlan_callback,
3189 &list_msg, NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER,
3190 NULL);
3192 if (ret != NWAM_SUCCESS)
3193 goto done;
3196 done:
3197 if (ret != NWAM_SUCCESS)
3198 nwamerr(ret, "List error");
3201 static int
3202 write_export_command(nwam_object_type_t object_type, const char *prop,
3203 nwam_value_t values, FILE *of)
3205 /* exclude read-only properties */
3206 if (is_prop_read_only(object_type, prop))
3207 return (0);
3209 (void) fprintf(of, "set ");
3210 output_propname(prop, values, of);
3211 return (0);
3214 static int
3215 export_ncu_callback(nwam_ncu_handle_t ncu, void *arg)
3217 char *name;
3218 const char **props;
3219 nwam_ncu_type_t type;
3220 nwam_ncu_class_t class;
3221 nwam_value_t vals;
3222 nwam_error_t ret;
3223 uint_t num;
3224 int i;
3225 FILE *of = arg;
3227 assert(of != NULL);
3229 /* get the NCU's type and class */
3230 if ((ret = nwam_ncu_get_ncu_type(ncu, &type)) != NWAM_SUCCESS)
3231 return (ret);
3232 if ((ret = nwam_ncu_get_ncu_class(ncu, &class)) != NWAM_SUCCESS)
3233 return (ret);
3235 if ((ret = nwam_ncu_get_name(ncu, &name)) != NWAM_SUCCESS)
3236 return (ret);
3238 (void) fprintf(of, "create ncu %s \"%s\"\n",
3239 propval_to_str(NWAM_NCU_PROP_CLASS, class), name);
3240 free(name);
3242 * Because of dependencies between properties, they have to be
3243 * exported in the same order as when they are walked.
3245 if ((ret = nwam_ncu_get_default_proplist(type, class, &props, &num))
3246 != NWAM_SUCCESS)
3247 return (ret);
3248 for (i = 0; i < num; i++) {
3249 ret = nwam_ncu_get_prop_value(ncu, props[i], &vals);
3250 if (ret == NWAM_SUCCESS) {
3251 write_export_command(NWAM_OBJECT_TYPE_NCU, props[i],
3252 vals, of);
3253 nwam_value_free(vals);
3256 (void) fprintf(of, "end\n");
3258 free(props);
3259 return (0);
3262 static int
3263 export_ncp_callback(nwam_ncp_handle_t ncp, void *arg)
3265 char *name;
3266 nwam_error_t ret;
3267 FILE *of = arg;
3269 assert(of != NULL);
3271 if ((ret = nwam_ncp_get_name(ncp, &name)) != NWAM_SUCCESS)
3272 return (ret);
3274 /* Do not export "automatic" NCP */
3275 if (NWAM_NCP_AUTOMATIC(name)) {
3276 free(name);
3277 return (0);
3280 (void) fprintf(of, "create ncp \"%s\"\n", name);
3281 free(name);
3283 /* now walk NCUs for this ncp */
3284 ret = nwam_ncp_walk_ncus(ncp, export_ncu_callback, of,
3285 NWAM_FLAG_NCU_TYPE_CLASS_ALL, NULL);
3286 if (ret != NWAM_SUCCESS) {
3287 nwamerr(ret, "Export ncp error: failed to walk ncus");
3288 return (ret);
3290 (void) fprintf(of, "end\n");
3291 return (0);
3294 static int
3295 export_enm_callback(nwam_enm_handle_t enm, void *arg)
3297 char *name;
3298 const char **props;
3299 nwam_value_t vals;
3300 nwam_error_t ret;
3301 uint_t num;
3302 int i;
3303 FILE *of = arg;
3305 assert(of != NULL);
3307 if ((ret = nwam_enm_get_name(enm, &name)) != NWAM_SUCCESS)
3308 return (ret);
3310 (void) fprintf(of, "create enm \"%s\"\n", name);
3311 free(name);
3313 * Because of dependencies between properties, they have to be
3314 * exported in the same order as when they are walked.
3316 if ((ret = nwam_enm_get_default_proplist(&props, &num)) != NWAM_SUCCESS)
3317 return (ret);
3318 for (i = 0; i < num; i++) {
3319 ret = nwam_enm_get_prop_value(enm, props[i], &vals);
3320 if (ret == NWAM_SUCCESS) {
3321 write_export_command(NWAM_OBJECT_TYPE_ENM, props[i],
3322 vals, of);
3323 nwam_value_free(vals);
3326 (void) fprintf(of, "end\n");
3328 free(props);
3329 return (0);
3332 static int
3333 export_loc_callback(nwam_loc_handle_t loc, void *arg)
3335 char *name;
3336 const char **props;
3337 nwam_value_t vals;
3338 nwam_error_t ret;
3339 uint_t num;
3340 int i;
3341 FILE *of = arg;
3343 assert(of != NULL);
3345 if ((ret = nwam_loc_get_name(loc, &name)) != NWAM_SUCCESS)
3346 return (ret);
3348 /* Do not export Automatic, NoNet or Legacy locations */
3349 if (NWAM_LOC_NAME_PRE_DEFINED(name)) {
3350 free(name);
3351 return (0);
3354 (void) fprintf(of, "create loc \"%s\"\n", name);
3355 free(name);
3357 * Because of dependencies between properties, they have to be
3358 * exported in the same order as when they are walked.
3360 if ((ret = nwam_loc_get_default_proplist(&props, &num)) != NWAM_SUCCESS)
3361 return (ret);
3362 for (i = 0; i < num; i++) {
3363 ret = nwam_loc_get_prop_value(loc, props[i], &vals);
3364 if (ret == NWAM_SUCCESS) {
3365 write_export_command(NWAM_OBJECT_TYPE_LOC, props[i],
3366 vals, of);
3367 nwam_value_free(vals);
3370 (void) fprintf(of, "end\n");
3372 free(props);
3373 return (0);
3376 static int
3377 export_wlan_callback(nwam_known_wlan_handle_t wlan, void *arg)
3379 char *name;
3380 const char **props;
3381 nwam_value_t vals;
3382 nwam_error_t ret;
3383 uint_t num;
3384 int i;
3385 FILE *of = arg;
3387 assert(of != NULL);
3389 if ((ret = nwam_known_wlan_get_name(wlan, &name)) != NWAM_SUCCESS)
3390 return (ret);
3392 (void) fprintf(of, "create wlan \"%s\"\n", name);
3393 free(name);
3395 * Because of dependencies between properties, they have to be
3396 * exported in the same order as when they are walked.
3398 if ((ret = nwam_known_wlan_get_default_proplist(&props, &num))
3399 != NWAM_SUCCESS)
3400 return (ret);
3401 for (i = 0; i < num; i++) {
3402 ret = nwam_known_wlan_get_prop_value(wlan, props[i], &vals);
3403 if (ret == NWAM_SUCCESS) {
3404 write_export_command(NWAM_OBJECT_TYPE_KNOWN_WLAN,
3405 props[i], vals, of);
3406 nwam_value_free(vals);
3409 (void) fprintf(of, "end\n");
3411 free(props);
3412 return (0);
3416 * Writes configuration to screen or file (with -f option).
3417 * Writes a "destroy -a" if option -d is given.
3419 void
3420 export_func(cmd_t *cmd)
3422 int c;
3423 boolean_t need_to_close = B_FALSE, write_to_file = B_FALSE;
3424 boolean_t add_destroy = B_FALSE, lhandle = B_FALSE;
3425 char filepath[MAXPATHLEN];
3426 nwam_error_t ret = NWAM_SUCCESS;
3427 FILE *of = NULL; /* either filename or stdout */
3429 /* what to export */
3430 boolean_t export_ncp = B_FALSE, export_ncu = B_FALSE;
3431 boolean_t export_loc = B_FALSE, export_enm = B_FALSE;
3432 boolean_t export_wlan = B_FALSE;
3433 char *name = NULL;
3435 /* check for -d and -f flags */
3436 filepath[0] = '\0';
3437 optind = 0;
3438 while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "df:")) != EOF) {
3439 switch (c) {
3440 case 'f':
3441 write_to_file = B_TRUE;
3442 break;
3443 case 'd':
3444 add_destroy = B_TRUE;
3445 break;
3446 default:
3447 command_usage(CMD_EXPORT);
3448 return;
3452 /* determine where to export */
3453 if (!write_to_file) {
3454 of = stdout;
3455 } else {
3457 * If -d was specified with -f, then argv[2] is filename,
3458 * otherwise, argv[1] is filename.
3460 (void) strlcpy(filepath,
3461 (add_destroy ? cmd->cmd_argv[2] : cmd->cmd_argv[1]),
3462 sizeof (filepath));
3463 if ((of = fopen(filepath, "w")) == NULL) {
3464 nerr(gettext("opening file '%s': %s"), filepath,
3465 strerror(errno));
3466 goto done;
3468 setbuf(of, NULL);
3469 need_to_close = B_TRUE;
3472 if (add_destroy) {
3473 /* only possible in global scope */
3474 if (current_scope == NWAM_SCOPE_GBL) {
3475 (void) fprintf(of, "destroy -a\n");
3476 } else {
3477 nerr("Option -d is not allowed in non-global scope");
3478 goto done;
3482 /* In the following scopes, only the -f argument is valid */
3483 if (((current_scope == NWAM_SCOPE_LOC ||
3484 current_scope == NWAM_SCOPE_ENM ||
3485 current_scope == NWAM_SCOPE_WLAN ||
3486 current_scope == NWAM_SCOPE_NCU) &&
3487 cmd->cmd_argc != 0 && !write_to_file)) {
3488 nerr("'export' does not take arguments at this scope");
3489 goto done;
3491 if (current_scope == NWAM_SCOPE_NCP) {
3492 if (cmd->cmd_res1_type == RT1_ENM ||
3493 cmd->cmd_res1_type == RT1_LOC ||
3494 cmd->cmd_res1_type == RT1_WLAN) {
3495 nerr("only ncu can be exported at this scope");
3496 goto done;
3501 * Determine what objects to export depending on scope and command
3502 * arguments. If -f is specified, then the object name is argv[2].
3503 * Otherwise, argv[0] is name, unless exporting all in global
3504 * scope in which case name is set back to NULL.
3506 switch (current_scope) {
3507 case NWAM_SCOPE_GBL:
3508 name = (write_to_file ? trim_quotes(cmd->cmd_argv[2]) :
3509 trim_quotes(cmd->cmd_argv[0]));
3510 switch (cmd->cmd_res1_type) {
3511 case RT1_LOC:
3512 export_loc = B_TRUE;
3513 break;
3514 case RT1_ENM:
3515 export_enm = B_TRUE;
3516 break;
3517 case RT1_WLAN:
3518 export_wlan = B_TRUE;
3519 break;
3520 case RT1_NCP:
3521 export_ncp = B_TRUE;
3522 if (cmd->cmd_res2_type == RT2_NCU) {
3523 nerr("cannot export ncu at from global scope");
3524 goto done;
3526 break;
3527 default:
3528 /* export everything */
3529 export_loc = B_TRUE;
3530 export_enm = B_TRUE;
3531 export_wlan = B_TRUE;
3532 export_ncp = B_TRUE; /* NCP will export the NCUs */
3533 free(name);
3534 name = NULL; /* exporting all, undo name */
3535 break;
3537 break;
3538 case NWAM_SCOPE_LOC:
3539 export_loc = B_TRUE;
3540 ret = nwam_loc_get_name(loc_h, &name);
3541 if (ret != NWAM_SUCCESS)
3542 goto fail;
3543 break;
3544 case NWAM_SCOPE_ENM:
3545 export_enm = B_TRUE;
3546 ret = nwam_enm_get_name(enm_h, &name);
3547 if (ret != NWAM_SUCCESS)
3548 goto fail;
3549 break;
3550 case NWAM_SCOPE_WLAN:
3551 export_wlan = B_TRUE;
3552 ret = nwam_known_wlan_get_name(wlan_h, &name);
3553 if (ret != NWAM_SUCCESS)
3554 goto fail;
3555 break;
3556 case NWAM_SCOPE_NCP:
3557 if (cmd->cmd_res2_type == RT2_NCU) {
3558 export_ncu = B_TRUE;
3559 name = (write_to_file ? trim_quotes(cmd->cmd_argv[2]) :
3560 trim_quotes(cmd->cmd_argv[0]));
3561 } else {
3562 export_ncp = B_TRUE;
3563 ret = nwam_ncp_get_name(ncp_h, &name);
3564 if (ret != NWAM_SUCCESS)
3565 goto fail;
3567 break;
3568 case NWAM_SCOPE_NCU:
3569 export_ncu = B_TRUE;
3570 ret = nwam_ncu_get_name(ncu_h, &name);
3571 if (ret != NWAM_SUCCESS)
3572 goto fail;
3573 break;
3574 default:
3575 nerr("Invalid scope");
3576 goto done;
3579 /* Now, export objects according to the flags set */
3580 if (export_ncp) {
3581 lhandle = B_FALSE;
3582 if (name == NULL) {
3583 /* export all NCPs */
3584 ret = nwam_walk_ncps(export_ncp_callback, of, 0, NULL);
3585 } else if (NWAM_NCP_AUTOMATIC(name)) {
3586 nerr("'%s' ncp cannot be exported", name);
3587 goto fail;
3588 } else {
3589 if (ncp_h == NULL) {
3590 ret = nwam_ncp_read(name, 0, &ncp_h);
3591 if (ret != NWAM_SUCCESS)
3592 goto fail;
3593 lhandle = B_TRUE;
3595 /* will export NCUs also */
3596 ret = export_ncp_callback(ncp_h, of);
3597 if (lhandle) {
3598 nwam_ncp_free(ncp_h);
3599 ncp_h = NULL;
3602 if (ret != NWAM_SUCCESS)
3603 goto fail;
3606 if (export_ncu) {
3607 if (name == NULL) {
3608 /* export all NCUs */
3609 ret = nwam_ncp_walk_ncus(ncp_h, export_ncu_callback, of,
3610 NWAM_FLAG_NCU_TYPE_CLASS_ALL, NULL);
3611 } else {
3612 if (ncu_h == NULL) {
3613 /* no NCU handle -> called from NCP scope */
3614 nwam_ncu_type_t ncu_type;
3615 nwam_ncu_class_t ncu_class;
3617 ncu_class = (nwam_ncu_class_t)
3618 cmd->cmd_ncu_class_type;
3619 ncu_type = nwam_ncu_class_to_type(ncu_class);
3620 ret = nwam_ncu_read(ncp_h, name,
3621 ncu_type, 0, &ncu_h);
3622 if (ret == NWAM_SUCCESS) {
3623 /* one NCU with given name */
3624 ret = export_ncu_callback(ncu_h, of);
3625 nwam_ncu_free(ncu_h);
3626 ncu_h = NULL;
3627 } else if (ret == NWAM_ENTITY_MULTIPLE_VALUES) {
3628 /* multiple NCUs with given name */
3629 ret = nwam_ncu_read(ncp_h, name,
3630 NWAM_NCU_TYPE_LINK, 0, &ncu_h);
3631 if (ret != NWAM_SUCCESS)
3632 goto fail;
3633 ret = export_ncu_callback(ncu_h, of);
3634 nwam_ncu_free(ncu_h);
3635 ncu_h = NULL;
3637 ret = nwam_ncu_read(ncp_h, name,
3638 NWAM_NCU_TYPE_INTERFACE, 0, &ncu_h);
3639 if (ret != NWAM_SUCCESS)
3640 goto fail;
3641 ret = export_ncu_callback(ncu_h, of);
3642 nwam_ncu_free(ncu_h);
3643 ncu_h = NULL;
3644 } else {
3645 goto fail;
3647 } else {
3648 /* NCU handle exists */
3649 ret = export_ncu_callback(ncu_h, of);
3652 if (ret != NWAM_SUCCESS)
3653 goto fail;
3656 if (export_loc) {
3657 lhandle = B_FALSE;
3658 if (name == NULL) {
3659 /* export all locations */
3660 ret = nwam_walk_locs(export_loc_callback, of,
3661 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
3662 } else if (NWAM_LOC_NAME_PRE_DEFINED(name)) {
3663 nerr("'%s' loc cannot be exported", name);
3664 goto fail;
3665 } else {
3666 if (loc_h == NULL) {
3667 ret = nwam_loc_read(name, 0, &loc_h);
3668 if (ret != NWAM_SUCCESS)
3669 goto fail;
3670 lhandle = B_TRUE;
3672 ret = export_loc_callback(loc_h, of);
3673 if (lhandle) {
3674 nwam_loc_free(loc_h);
3675 loc_h = NULL;
3678 if (ret != NWAM_SUCCESS)
3679 goto fail;
3682 if (export_enm) {
3683 lhandle = B_FALSE;
3684 if (name == NULL) {
3685 /* export all ENMs */
3686 ret = nwam_walk_enms(export_enm_callback, of,
3687 NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
3688 } else {
3689 if (enm_h == NULL) {
3690 ret = nwam_enm_read(name, 0, &enm_h);
3691 if (ret != NWAM_SUCCESS)
3692 goto fail;
3693 lhandle = B_TRUE;
3695 ret = export_enm_callback(enm_h, of);
3696 if (lhandle) {
3697 nwam_enm_free(enm_h);
3698 enm_h = NULL;
3701 if (ret != NWAM_SUCCESS)
3702 goto fail;
3705 if (export_wlan) {
3706 lhandle = B_FALSE;
3707 if (name == NULL) {
3708 /* export all WLANs */
3709 ret = nwam_walk_known_wlans(export_wlan_callback, of,
3710 NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER, NULL);
3711 } else {
3712 if (wlan_h == NULL) {
3713 ret = nwam_known_wlan_read(name, 0,
3714 &wlan_h);
3715 if (ret != NWAM_SUCCESS)
3716 goto fail;
3717 lhandle = B_TRUE;
3719 ret = export_wlan_callback(wlan_h, of);
3720 if (lhandle) {
3721 nwam_known_wlan_free(wlan_h);
3722 wlan_h = NULL;
3725 if (ret != NWAM_SUCCESS)
3726 goto fail;
3729 fail:
3730 free(name);
3731 if (ret != NWAM_SUCCESS)
3732 nwamerr(ret, "Export error");
3734 done:
3735 if (need_to_close)
3736 (void) fclose(of);
3740 * Get property value. If the -V option is specified, only the value is
3741 * printed without the property name.
3743 void
3744 get_func(cmd_t *cmd)
3746 nwam_error_t ret = NWAM_SUCCESS;
3747 nwam_value_t prop_value;
3748 const char *prop;
3749 boolean_t value_only = B_FALSE;
3750 nwam_object_type_t object_type = active_object_type();
3752 /* check if option is -V to print value only */
3753 if (cmd->cmd_argc == 1) {
3754 int c;
3756 optind = 0;
3757 while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "V")) != EOF) {
3758 switch (c) {
3759 case 'V':
3760 value_only = B_TRUE;
3761 break;
3762 default:
3763 command_usage(CMD_GET);
3764 return;
3769 /* property to get is in cmd->cmd_prop_type */
3770 if ((prop = pt_to_prop_name(object_type, cmd->cmd_prop_type)) == NULL) {
3771 nerr("Get error: invalid %s property: '%s'",
3772 scope_to_str(current_scope), pt_to_str(cmd->cmd_prop_type));
3773 return;
3776 switch (object_type) {
3777 case NWAM_OBJECT_TYPE_NCU:
3778 ret = nwam_ncu_get_prop_value(ncu_h, prop, &prop_value);
3779 break;
3780 case NWAM_OBJECT_TYPE_LOC:
3781 ret = nwam_loc_get_prop_value(loc_h, prop, &prop_value);
3782 break;
3783 case NWAM_OBJECT_TYPE_ENM:
3784 ret = nwam_enm_get_prop_value(enm_h, prop, &prop_value);
3785 break;
3786 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
3787 ret = nwam_known_wlan_get_prop_value(wlan_h, prop, &prop_value);
3788 break;
3791 if (ret != NWAM_SUCCESS) {
3792 if (ret == NWAM_ENTITY_NOT_FOUND)
3793 nerr("Get error: property '%s' has not been set", prop);
3794 else
3795 nwamerr(ret, "Get error");
3796 return;
3799 if (value_only) {
3800 output_prop_val(prop, prop_value, stdout, B_FALSE);
3801 (void) printf("\n");
3802 } else {
3803 output_propname(prop, prop_value, NULL);
3805 nwam_value_free(prop_value);
3809 * Clears value of a property.
3810 * Read-only properties cannot be cleared.
3811 * If clearing a property invalidates the object, then that property
3812 * cannot be cleared.
3814 void
3815 clear_func(cmd_t *cmd)
3817 nwam_error_t ret;
3818 const char *prop;
3819 nwam_object_type_t object_type = active_object_type();
3821 /* property to clear is in cmd->cmd_prop_type */
3822 if ((prop = pt_to_prop_name(object_type, cmd->cmd_prop_type)) == NULL) {
3823 nerr("Clear error: invalid %s property: '%s'",
3824 scope_to_str(current_scope), pt_to_str(cmd->cmd_prop_type));
3825 return;
3827 if (is_prop_read_only(object_type, prop)) {
3828 nerr("Clear error: property '%s' is read-only", prop);
3829 return;
3832 switch (object_type) {
3833 case NWAM_OBJECT_TYPE_NCU:
3834 ret = nwam_ncu_delete_prop(ncu_h, prop);
3835 break;
3836 case NWAM_OBJECT_TYPE_LOC:
3837 ret = nwam_loc_delete_prop(loc_h, prop);
3838 break;
3839 case NWAM_OBJECT_TYPE_ENM:
3840 ret = nwam_enm_delete_prop(enm_h, prop);
3841 break;
3842 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
3843 ret = nwam_known_wlan_delete_prop(wlan_h, prop);
3844 break;
3847 if (ret != NWAM_SUCCESS) {
3848 if (ret == NWAM_INVALID_ARG || ret == NWAM_ENTITY_NOT_FOUND) {
3849 nerr("Clear error: property '%s' has not been set",
3850 prop);
3851 } else {
3852 nwamerr(ret, "Clear error");
3854 return;
3857 need_to_commit = B_TRUE;
3861 * Prints all the choices available for an enum property [c1|c2|c3].
3862 * Prints [true|false] for a boolean property.
3864 static void
3865 print_all_prop_choices(nwam_object_type_t object_type, const char *prop)
3867 uint64_t i = 0;
3868 const char *str;
3869 boolean_t choices = B_FALSE;
3870 nwam_value_type_t value_type;
3871 nwam_error_t ret;
3873 /* Special case: print object-specific options for activation-mode */
3874 if (strcmp(prop, NWAM_NCU_PROP_ACTIVATION_MODE) == 0) {
3875 /* "manual" for all objects */
3876 (void) printf(" [%s|",
3877 propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
3878 NWAM_ACTIVATION_MODE_MANUAL));
3879 if (object_type == NWAM_OBJECT_TYPE_NCU) {
3880 (void) printf("%s]",
3881 propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
3882 NWAM_ACTIVATION_MODE_PRIORITIZED));
3883 } else {
3884 (void) printf("%s|%s]",
3885 propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
3886 NWAM_ACTIVATION_MODE_CONDITIONAL_ANY),
3887 propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
3888 NWAM_ACTIVATION_MODE_CONDITIONAL_ALL));
3890 return;
3893 /* Special case: only "manual" configsrc is allowed for LDAP */
3894 if (strcmp(prop, NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC) == 0) {
3895 (void) printf(" [%s]",
3896 propval_to_str(NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
3897 NWAM_CONFIGSRC_MANUAL));
3898 return;
3901 value_type = prop_value_type(object_type, prop);
3902 switch (value_type) {
3903 case NWAM_VALUE_TYPE_UINT64:
3904 /* uint64 may be an enum, will print nothing if not an enum */
3905 while ((ret = nwam_uint64_get_value_string(prop, i++, &str))
3906 == NWAM_SUCCESS || ret == NWAM_ENTITY_INVALID_VALUE) {
3907 /* No string representation for i, continue. */
3908 if (ret == NWAM_ENTITY_INVALID_VALUE)
3909 continue;
3911 if (!choices)
3912 (void) printf("%s", " [");
3913 (void) printf("%s%s", choices ? "|" : "", str);
3914 choices = B_TRUE;
3916 if (choices)
3917 (void) putchar(']');
3918 break;
3919 case NWAM_VALUE_TYPE_BOOLEAN:
3920 (void) printf(" [%s|%s]", "true", "false");
3921 break;
3922 case NWAM_VALUE_TYPE_STRING:
3923 break;
3928 * Walk through object properties.
3929 * For newly-created object, the property name with no value is displayed, and
3930 * the user can input a value for each property.
3931 * For existing object, the current value is displayed and user input overwrites
3932 * the existing one. If no input is given, the existing value remains.
3933 * Read-only properties are not displayed.
3934 * Read-only objects cannot be walked.
3935 * If the -a option is specified, no properties are skipped.
3937 void
3938 walkprop_func(cmd_t *cmd)
3940 nwam_error_t ret = NWAM_SUCCESS;
3941 nwam_value_t vals = NULL; /* freed in _wait_input() */
3942 int i;
3943 uint_t prop_num;
3944 const char **props;
3945 boolean_t read_only = B_FALSE, all_props = B_FALSE;
3947 nwam_object_type_t object_type;
3948 prop_display_entry_t *prop_table;
3950 if (!interactive_mode) {
3951 nerr("'walkprop' is only allowed in interactive mode");
3952 return;
3955 /* check if option -a is specified to show all properties */
3956 if (cmd->cmd_argc == 1) {
3957 int c;
3958 optind = 0;
3959 while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "a")) != EOF) {
3960 switch (c) {
3961 case 'a':
3962 all_props = B_TRUE;
3963 break;
3964 default:
3965 command_usage(CMD_WALKPROP);
3966 return;
3971 /* read-only objects cannot be walked */
3972 if (obj1_type == RT1_NCP) {
3973 /* must be in NCU scope, NCP scope doesn't get here */
3974 (void) nwam_ncu_get_read_only(ncu_h, &read_only);
3976 if (read_only) {
3977 nerr("'walkprop' cannot be used in read-only objects");
3978 return;
3981 /* get the current object type and the prop_display_table */
3982 object_type = active_object_type();
3983 prop_table = get_prop_display_table(object_type);
3985 /* get the property list depending on the object type */
3986 switch (object_type) {
3987 case NWAM_OBJECT_TYPE_NCU:
3989 nwam_ncu_type_t ncu_type;
3990 nwam_ncu_class_t ncu_class;
3992 if ((ret = nwam_ncu_get_ncu_type(ncu_h, &ncu_type))
3993 != NWAM_SUCCESS)
3994 break;
3995 if ((ret = nwam_ncu_get_ncu_class(ncu_h, &ncu_class))
3996 != NWAM_SUCCESS)
3997 break;
3999 ret = nwam_ncu_get_default_proplist(ncu_type, ncu_class, &props,
4000 &prop_num);
4001 break;
4003 case NWAM_OBJECT_TYPE_LOC:
4004 ret = nwam_loc_get_default_proplist(&props, &prop_num);
4005 break;
4006 case NWAM_OBJECT_TYPE_ENM:
4007 ret = nwam_enm_get_default_proplist(&props, &prop_num);
4008 break;
4009 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
4010 ret = nwam_known_wlan_get_default_proplist(&props, &prop_num);
4011 break;
4013 if (ret != NWAM_SUCCESS) {
4014 nwamerr(ret, "Walkprop error: could not get property list");
4015 return;
4018 /* Loop through the properties */
4019 if (all_props)
4020 (void) printf(gettext("Walking all properties ...\n"));
4021 for (i = 0; i < prop_num; i++) {
4022 char line[NWAM_MAX_VALUE_LEN];
4023 char **checked = NULL;
4025 /* check if this property should be displayed */
4026 if (is_prop_read_only(object_type, props[i]))
4027 continue;
4028 if (!all_props &&
4029 !show_prop_test(object_type, props[i], prop_table,
4030 checked, 0))
4031 continue;
4033 /* get the existing value for this property */
4034 switch (object_type) {
4035 case NWAM_OBJECT_TYPE_NCU:
4036 ret = nwam_ncu_get_prop_value(ncu_h, props[i], &vals);
4037 break;
4038 case NWAM_OBJECT_TYPE_LOC:
4039 ret = nwam_loc_get_prop_value(loc_h, props[i], &vals);
4040 break;
4041 case NWAM_OBJECT_TYPE_ENM:
4042 ret = nwam_enm_get_prop_value(enm_h, props[i], &vals);
4043 break;
4044 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
4045 ret = nwam_known_wlan_get_prop_value(wlan_h, props[i],
4046 &vals);
4047 break;
4049 /* returns NWAM_ENTITY_NOT_FOUND if no existing value */
4050 if (ret != NWAM_SUCCESS && ret != NWAM_ENTITY_NOT_FOUND)
4051 continue;
4053 /* print property */
4054 (void) printf("%s", props[i]);
4055 /* print the existing value(s) if they exist */
4056 if (ret == NWAM_SUCCESS) {
4057 (void) printf(" (");
4058 output_prop_val(props[i], vals, stdout, B_TRUE);
4059 (void) putchar(')');
4060 nwam_value_free(vals);
4062 /* print choices, won't print anything if there aren't any */
4063 print_all_prop_choices(object_type, props[i]);
4064 (void) printf("> ");
4066 /* wait for user input */
4067 if (fgets(line, sizeof (line), stdin) == NULL)
4068 continue;
4070 /* if user input new value, existing value is overrode */
4071 if (line[0] != '\n') {
4072 boolean_t is_listprop;
4073 int pt_type = prop_to_pt(object_type, props[i]);
4075 is_listprop = is_prop_multivalued(object_type,
4076 props[i]);
4077 vals = str_to_nwam_value(object_type, line, pt_type,
4078 is_listprop);
4079 if (vals == NULL) {
4080 ret = NWAM_ENTITY_INVALID_VALUE;
4081 goto repeat;
4084 /* set the new value for the property */
4085 switch (object_type) {
4086 case NWAM_OBJECT_TYPE_NCU:
4087 ret = nwam_ncu_set_prop_value(ncu_h, props[i],
4088 vals);
4089 break;
4090 case NWAM_OBJECT_TYPE_LOC:
4091 ret = nwam_loc_set_prop_value(loc_h, props[i],
4092 vals);
4093 break;
4094 case NWAM_OBJECT_TYPE_ENM:
4095 ret = nwam_enm_set_prop_value(enm_h, props[i],
4096 vals);
4097 break;
4098 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
4099 ret = nwam_known_wlan_set_prop_value(wlan_h,
4100 props[i], vals);
4101 break;
4103 nwam_value_free(vals);
4105 if (ret != NWAM_SUCCESS)
4106 goto repeat;
4108 need_to_commit = B_TRUE;
4109 continue;
4111 repeat:
4112 invalid_set_prop_msg(props[i], ret);
4113 i--; /* decrement i to repeat */
4117 free(props);
4121 * Verify whether all properties of a resource are valid.
4123 /* ARGSUSED */
4124 void
4125 verify_func(cmd_t *cmd)
4127 nwam_error_t ret;
4128 const char *errprop;
4130 switch (active_object_type()) {
4131 case NWAM_OBJECT_TYPE_NCU:
4132 ret = nwam_ncu_validate(ncu_h, &errprop);
4133 break;
4134 case NWAM_OBJECT_TYPE_LOC:
4135 ret = nwam_loc_validate(loc_h, &errprop);
4136 break;
4137 case NWAM_OBJECT_TYPE_ENM:
4138 ret = nwam_enm_validate(enm_h, &errprop);
4139 break;
4140 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
4141 ret = nwam_known_wlan_validate(wlan_h, &errprop);
4142 break;
4144 if (ret != NWAM_SUCCESS)
4145 nwamerr(ret, "Verify error on property '%s'", errprop);
4146 else if (interactive_mode)
4147 (void) printf(gettext("All properties verified\n"));
4151 * command-line mode (# nwamcfg list or # nwamcfg "select loc test; list")
4153 static int
4154 one_command_at_a_time(int argc, char *argv[])
4156 char *command;
4157 size_t len = 2; /* terminal \n\0 */
4158 int i, err;
4160 for (i = 0; i < argc; i++)
4161 len += strlen(argv[i]) + 1;
4162 if ((command = malloc(len)) == NULL) {
4163 nerr("Out of memory");
4164 return (NWAM_ERR);
4166 (void) strlcpy(command, argv[0], len);
4167 for (i = 1; i < argc; i++) {
4168 (void) strlcat(command, " ", len);
4169 (void) strlcat(command, argv[i], len);
4171 (void) strlcat(command, "\n", len);
4172 err = string_to_yyin(command);
4173 free(command);
4174 if (err != NWAM_OK)
4175 return (err);
4176 while (!feof(yyin)) {
4177 yyparse();
4180 * If any command on a list of commands give an error,
4181 * don't continue with the remaining commands.
4183 if (saw_error || time_to_exit)
4184 return (cleanup());
4187 /* if there are changes to commit, commit it */
4188 if (need_to_commit) {
4189 do_commit();
4190 /* if need_to_commit is not set, then there was a error */
4191 if (need_to_commit)
4192 return (NWAM_ERR);
4195 if (!interactive_mode)
4196 return (cleanup());
4197 else {
4198 yyin = stdin;
4199 return (read_input());
4204 * cmd_file is slightly more complicated, as it has to open the command file
4205 * and set yyin appropriately. Once that is done, though, it just calls
4206 * read_input(), and only once, since prompting is not possible.
4208 static int
4209 cmd_file(char *file)
4211 FILE *infile;
4212 int err;
4213 struct stat statbuf;
4214 boolean_t using_real_file = (strcmp(file, "-") != 0);
4216 if (using_real_file) {
4218 * nerr() prints a line number in cmd_file_mode, which we do
4219 * not want here, so temporarily unset it.
4221 cmd_file_mode = B_FALSE;
4222 if ((infile = fopen(file, "r")) == NULL) {
4223 nerr(gettext("could not open file '%s': %s"),
4224 file, strerror(errno));
4225 return (1);
4227 if ((err = fstat(fileno(infile), &statbuf)) != 0) {
4228 nerr(gettext("could not stat file '%s': %s"),
4229 file, strerror(errno));
4230 err = 1;
4231 goto done;
4233 if (!S_ISREG(statbuf.st_mode)) {
4234 nerr(gettext("'%s' is not a regular file."), file);
4235 err = 1;
4236 goto done;
4240 * If -d was passed on the command-line, we need to
4241 * start by removing any existing configuration.
4242 * Alternatively, the file may begin with 'destroy -a';
4243 * but in that case, the line will go through the lexer
4244 * and be processed as it's encountered in the file.
4246 if (remove_all_configurations && destroy_all() != NWAM_SUCCESS)
4247 goto done;
4249 /* set up for lexer */
4250 yyin = infile;
4251 cmd_file_mode = B_TRUE;
4252 ok_to_prompt = B_FALSE;
4253 } else {
4255 * "-f -" is essentially the same as interactive mode,
4256 * so treat it that way.
4258 interactive_mode = B_TRUE;
4260 /* NWAM_REPEAT is for interactive mode; treat it like NWAM_ERR here. */
4261 if ((err = read_input()) == NWAM_REPEAT)
4262 err = NWAM_ERR;
4263 if (err == NWAM_OK)
4264 (void) printf(gettext("Configuration read.\n"));
4266 done:
4267 if (using_real_file)
4268 (void) fclose(infile);
4269 return (err);
4273 main(int argc, char *argv[])
4275 int err;
4276 char c;
4278 /* This must be before anything goes to stdout. */
4279 setbuf(stdout, NULL);
4281 if ((execname = strrchr(argv[0], '/')) == NULL)
4282 execname = argv[0];
4283 else
4284 execname++;
4286 (void) setlocale(LC_ALL, "");
4287 (void) textdomain(TEXT_DOMAIN);
4289 while ((c = getopt(argc, argv, "?hf:d")) != EOF) {
4290 switch (c) {
4291 case 'f':
4292 cmd_file_name = optarg;
4293 cmd_file_mode = B_TRUE;
4294 break;
4295 case '?':
4296 case 'h':
4297 cmd_line_usage();
4298 return (NWAM_OK);
4299 case 'd':
4300 remove_all_configurations = B_TRUE;
4301 break;
4302 default:
4303 cmd_line_usage();
4304 return (NWAM_ERR);
4307 /* -d can only be used with -f */
4308 if (remove_all_configurations && !cmd_file_mode) {
4309 nerr("Option -d can only be used with -f");
4310 return (NWAM_ERR);
4314 * This may get set back to FALSE again in cmd_file() if cmd_file_name
4315 * is a "real" file as opposed to "-" (i.e. meaning use stdin).
4317 if (isatty(STDIN_FILENO))
4318 ok_to_prompt = B_TRUE;
4319 if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL)
4320 exit(NWAM_ERR);
4321 if (gl_customize_completion(gl, NULL, cmd_cpl_fn) != 0)
4322 exit(NWAM_ERR);
4323 (void) sigset(SIGINT, SIG_IGN);
4325 if (optind == argc) {
4326 /* interactive or command-file mode */
4327 if (!cmd_file_mode)
4328 err = do_interactive();
4329 else
4330 err = cmd_file(cmd_file_name);
4331 } else {
4332 /* command-line mode */
4333 err = one_command_at_a_time(argc - optind, &(argv[optind]));
4335 (void) del_GetLine(gl);
4337 return (err);