4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * This is the main program file for the configuration administration
29 * command as set out in manual page cfgadm(1M). It uses the configuration
30 * administration library interface, libcfgadm, as set out in manual
31 * page config_admin(3X).
41 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <sys/sunddi.h>
45 #include <sys/openpromio.h>
46 #include <sys/ddi_impldefs.h>
47 #include <sys/systeminfo.h>
50 #include <getresponse.h>
52 #include <config_admin.h>
55 #define S_FREE(x) (((x) != NULL) ? (free(x), (x) = NULL) : (void *)0)
56 #define GET_DYN(a) (strstr((a), CFGA_DYN_SEP))
58 * forward declarations
60 static char *basename(char *);
61 static void cfgadm_error(int, char *);
62 static int confirm_interactive(void *, const char *);
63 static int confirm_no(void *, const char *);
64 static int confirm_yes(void *, const char *);
65 static void usage(void);
66 static void usage_field(void);
67 static int extract_list_suboptions(char *, char **, char **, char **,
68 int *, char **, char **, char **);
69 static int message_output(void *appdata_ptr
, const char *message
);
70 static void *config_calloc_check(size_t, size_t);
71 static cfga_ap_types_t
find_arg_type(const char *);
74 static int compare_ap_id(cfga_list_data_t
*, cfga_list_data_t
*, match_type_t
);
75 static int compare_r_state(cfga_list_data_t
*, cfga_list_data_t
*,
77 static int compare_o_state(cfga_list_data_t
*, cfga_list_data_t
*,
79 static int compare_cond(cfga_list_data_t
*, cfga_list_data_t
*, match_type_t
);
80 static int compare_time(cfga_list_data_t
*, cfga_list_data_t
*, match_type_t
);
81 static int compare_info(cfga_list_data_t
*, cfga_list_data_t
*, match_type_t
);
82 static int compare_type(cfga_list_data_t
*, cfga_list_data_t
*, match_type_t
);
83 static int compare_busy(cfga_list_data_t
*, cfga_list_data_t
*, match_type_t
);
84 static int compare_class(cfga_list_data_t
*, cfga_list_data_t
*, match_type_t
);
85 static int compare_null(cfga_list_data_t
*, cfga_list_data_t
*, match_type_t
);
86 static void print_log_id(cfga_list_data_t
*, int, char *);
87 static void print_r_state(cfga_list_data_t
*, int, char *);
88 static void print_o_state(cfga_list_data_t
*, int, char *);
89 static void print_cond(cfga_list_data_t
*, int, char *);
90 static void print_time(cfga_list_data_t
*, int, char *);
91 static void print_time_p(cfga_list_data_t
*, int, char *);
92 static void print_info(cfga_list_data_t
*, int, char *);
93 static void print_type(cfga_list_data_t
*, int, char *);
94 static void print_busy(cfga_list_data_t
*, int, char *);
95 static void print_phys_id(cfga_list_data_t
*, int, char *);
96 static void print_class(cfga_list_data_t
*, int, char *);
97 static void print_null(cfga_list_data_t
*, int, char *);
98 static int count_fields(char *, char);
99 static int process_sort_fields(int, struct sort_el
*, char *);
100 static int process_fields(int, struct print_col
*, int, char *);
101 static cfga_err_t
print_fields(int, struct print_col
*, int, int, char *,
102 cfga_list_data_t
*, FILE *);
103 static int ldata_compare(const void *, const void *);
105 static void arg_got_resp(ap_arg_t
*inp
, ap_out_t
*out_array
, int nouts
,
107 static void out_was_req(ap_out_t
*outp
, ap_arg_t
*in_array
, int nargs
,
109 static void report_no_response(ap_arg_t
*arg_array
, int napids_to_list
);
111 static cfga_err_t
set_log_flt(cfga_list_data_t
*p
, const char *val
);
112 static cfga_err_t
set_type_flt(cfga_list_data_t
*p
, const char *val
);
113 static cfga_err_t
set_class_flt(cfga_list_data_t
*p
, const char *val
);
115 static char *get_dyn(const char *ap_id
);
116 static void remove_dyn(char *ap_id
);
117 static char *s_strdup(char *str
);
122 /* command name for messages */
123 static char *cmdname
;
126 * control for comparing, printing and filtering cfga_list_data
127 * NOTE:Field names (i.e. member 0 of field_info struct) may not contain '('.
128 * The post filtering code depends on it.
129 * NOTE:A NULL value for the set_filter member indicates that filtering based
130 * on that field is currently not supported.
132 static struct field_info all_fields
[] = {
133 {"ap_id", "Ap_Id", SZ_EL(ap_log_id
), compare_ap_id
, print_log_id
, set_log_flt
},
134 {"r_state", "Receptacle", STATE_WIDTH
, compare_r_state
, print_r_state
, NULL
},
135 {"o_state", "Occupant", STATE_WIDTH
, compare_o_state
, print_o_state
, NULL
},
136 {"condition", "Condition", COND_WIDTH
, compare_cond
, print_cond
, NULL
},
137 {"status_time", "When", TIME_WIDTH
, compare_time
, print_time
, NULL
},
138 {"status_time_p", "When", TIME_P_WIDTH
, compare_time
, print_time_p
, NULL
},
139 {"info", "Information", SZ_EL(ap_info
), compare_info
, print_info
, NULL
},
140 {"type", "Type", SZ_EL(ap_type
), compare_type
, print_type
, set_type_flt
},
141 {"busy", "Busy", 8, compare_busy
, print_busy
, NULL
},
142 {"physid", "Phys_Id", SZ_EL(ap_phys_id
), compare_ap_id
, print_phys_id
, NULL
},
143 {"class", "Class", SZ_EL(ap_class
), compare_class
, print_class
, set_class_flt
}
146 #define PREFILT_CLASS_STR "class="
149 cfga_list_data_t ldata
; /* Selection criteria */
150 match_type_t match_type_p
[N_FIELDS
]; /* Type of match */
153 static struct field_info null_field
=
154 {"null", "", 0, compare_null
, print_null
, NULL
};
156 static struct sort_el
*sort_list
; /* Used in ldata_compare() */
157 static int nsort_list
;
158 static char unk_field
[] = "%s: field \"%s\" unknown\n";
160 static char aptype_no_dyn
[] = "%s: Invalid ap_id: %s\n";
162 /* strings that make up the usage message */
163 static char *usage_tab
[] = {
164 " %s [-f] [-y|-n] [-v] [-o hardware_opts ] -c function ap_id [ap_id...]\n",
165 " %s [-f] [-y|-n] [-v] [-o hardware_opts ] -x function ap_id [ap_id...]\n",
166 " %s [-v] [-s listing_options ] [-o hardware_opts ] [-a]\n"
167 "\t[-l [ap_id|ap_type...]]\n",
168 " %s [-v] [-o hardware_opts ] -t ap_id [ap_id...]\n",
169 " %s [-v] [-o hardware_opts ] -h [ap_id|ap_type...]\n",
172 /* Type of matches currently supported by the select sub-option */
173 static match_cvt_t match_type_array
[] = {
174 {"partial", CFGA_MATCH_PARTIAL
},
175 {"exact", CFGA_MATCH_EXACT
}
178 #define N_MATCH_TYPES (sizeof (match_type_array)/sizeof (match_type_array[0]))
180 static cfga_err_t
setup_filter(const char *selectp
, const char *matchp
,
181 post_filter_t
*post_filtp
, char **prefilt_optpp
);
182 static cfga_err_t
parse_select_opt(const char *selectp
,
183 post_filter_t
*post_filtp
, match_type_t match_type
);
184 static int do_config_list(int, char *[], cfga_list_data_t
*, int, char *,
185 char *, char *, int, char *, post_filter_t
*, int);
186 static void do_post_filter(ap_out_t
*outp
, post_filter_t
*post_filtp
, int *jp
);
190 * main - the main routine of cfgadm, processes the command line
191 * and dispatches functions off to libraries.
203 char *const *ap_args
= NULL
;
204 cfga_cmd_t sc_opt
= CFGA_CMD_NONE
;
205 struct cfga_confirm confirm
;
206 struct cfga_msg message
;
207 int ret
= CFGA_ERROR
;
210 cfga_op_t action
= CFGA_OP_NONE
;
211 char *plat_opts
= NULL
;
212 char *act_arg
= NULL
;
213 enum confirm confarg
= CONFIRM_DEFAULT
;
214 char *list_opts
= NULL
;
215 cfga_flags_t flags
= 0;
221 cmdname
= basename(argv
[0]);
224 (void) setlocale(LC_ALL
, "");
225 #if !defined(TEXT_DOMAIN)
226 #define TEXT_DOMAIN "SYS_TEST"
228 (void) textdomain(TEXT_DOMAIN
);
230 while ((c
= getopt(argc
, argv
, OPTIONS
)) != EOF
) {
231 static char dup_action
[] =
232 "%s: more than one action specified (-c,-l,-t,-x)\n";
233 static char dup_option
[] =
234 "%s: more than one -%c option specified\n";
239 (void) fprintf(stderr
, gettext(dup_option
),
245 if (action
!= CFGA_OP_NONE
) {
247 (void) fprintf(stderr
, gettext(dup_action
),
250 action
= CFGA_OP_CHANGE_STATE
;
254 * Reject -c suboption if they are unrecognized
255 * or more than one or have a associated value.
257 if ((sc_opt
= getsubopt(&subopts
, state_opts
,
258 &subvalue
)) == -1 || *subopts
!= '\0' ||
265 if ((flags
& CFGA_FLAG_FORCE
) != 0) {
267 (void) fprintf(stderr
, gettext(dup_option
),
270 flags
|= CFGA_FLAG_FORCE
;
273 if (action
!= CFGA_OP_NONE
) {
275 (void) fprintf(stderr
, gettext(dup_action
),
278 action
= CFGA_OP_HELP
;
281 if (action
!= CFGA_OP_NONE
) {
283 (void) fprintf(stderr
, gettext(dup_action
),
286 action
= CFGA_OP_LIST
;
289 if (confarg
!= CONFIRM_DEFAULT
) {
291 (void) fprintf(stderr
, gettext(dup_option
),
294 confarg
= CONFIRM_NO
;
297 if (plat_opts
!= NULL
) {
299 (void) fprintf(stderr
, gettext(dup_option
),
305 if (list_opts
!= NULL
) {
307 (void) fprintf(stderr
, gettext(dup_option
),
313 if (action
!= CFGA_OP_NONE
) {
315 (void) fprintf(stderr
, gettext(dup_action
),
318 action
= CFGA_OP_TEST
;
321 if (action
!= CFGA_OP_NONE
) {
323 (void) fprintf(stderr
, gettext(dup_action
),
326 action
= CFGA_OP_PRIVATE
;
330 if ((flags
& CFGA_FLAG_VERBOSE
) != 0) {
332 (void) fprintf(stderr
, gettext(dup_option
),
335 flags
|= CFGA_FLAG_VERBOSE
;
338 if (confarg
!= CONFIRM_DEFAULT
) {
340 (void) fprintf(stderr
, gettext(dup_option
),
343 confarg
= CONFIRM_YES
;
345 case '?': /* getopts issues message is this case */
346 default: /* catch programming errors */
352 /* default action is list */
353 if (action
== CFGA_OP_NONE
)
354 action
= CFGA_OP_LIST
;
356 /* -s and -a option only for list */
357 if (action
!= CFGA_OP_LIST
&& (list_opts
!= NULL
|| dyn_exp
)) {
367 if (getzoneid() != GLOBAL_ZONEID
) {
368 cfgadm_error(CFGA_NOTSUPP
,
369 gettext("cfgadm can only be run from the global zone"));
373 ap_args
= &argv
[optind
];
376 * If neither -n of -y was specified, interactive confirmation
377 * is used. Check if the program has terminal I/O and
380 (void) memset(&confirm
, 0, sizeof (confirm
));
381 if (action
== CFGA_OP_CHANGE_STATE
|| action
== CFGA_OP_PRIVATE
) {
382 if (confarg
== CONFIRM_DEFAULT
&&
383 !(isatty(fileno(stdin
)) && isatty(fileno(stderr
))))
384 confarg
= CONFIRM_NO
;
386 case CONFIRM_DEFAULT
:
387 confirm
.confirm
= confirm_interactive
;
390 confirm
.confirm
= confirm_no
;
393 confirm
.confirm
= confirm_yes
;
395 default: /* paranoia */
402 * set up message output routine
404 message
.message_routine
= message_output
;
407 case CFGA_OP_CHANGE_STATE
:
408 /* Sanity check - requires an argument */
409 if ((argc
- optind
) <= 0) {
413 /* Sanity check - args cannot be ap_types */
414 for (i
= 0; i
< (argc
- optind
); i
++) {
415 if (find_arg_type(ap_args
[i
]) == AP_TYPE
) {
421 ret
= config_change_state(sc_opt
, argc
- optind
, ap_args
,
422 plat_opts
, &confirm
, &message
, &estrp
, flags
);
424 cfgadm_error(ret
, estrp
);
426 case CFGA_OP_PRIVATE
:
427 /* Sanity check - requires an argument */
428 if ((argc
- optind
) <= 0) {
432 /* Sanity check - args cannot be ap_types */
433 for (i
= 0; i
< (argc
- optind
); i
++) {
434 if (find_arg_type(ap_args
[i
]) == AP_TYPE
) {
441 ret
= config_private_func(act_arg
, argc
- optind
, ap_args
,
442 plat_opts
, &confirm
, &message
, &estrp
, flags
);
445 cfgadm_error(ret
, estrp
);
448 /* Sanity check - requires an argument */
449 if ((argc
- optind
) <= 0) {
454 if ((flags
& ~CFGA_FLAG_VERBOSE
) != 0) {
460 /* Sanity check - args cannot be ap_types */
461 for (i
= 0; i
< (argc
- optind
); i
++) {
462 if (find_arg_type(ap_args
[i
]) == AP_TYPE
) {
468 ret
= config_test(argc
- optind
, ap_args
, plat_opts
, &message
,
471 cfgadm_error(ret
, estrp
);
475 if ((flags
& ~CFGA_FLAG_VERBOSE
) != 0) {
481 /* always do usage? */
483 ret
= config_help(argc
- optind
, ap_args
, &message
, plat_opts
,
486 cfgadm_error(ret
, estrp
);
491 * Note that we leak the strdup strings below (we never free
492 * them). This is ok in this context since cfgadm is
493 * a short lived process that will exit shortly freeing
496 cfga_list_data_t
*list_array
= NULL
;
498 char *sort_fields
= s_strdup(DEF_SORT_FIELDS
);
499 char *cols
= s_strdup(DEF_COLS
);
500 char *cols2
= s_strdup(DEF_COLS2
);
502 char *delim
= s_strdup(DEF_DELIM
);
503 int exitcode
= EXIT_OK
;
506 char *selectp
= NULL
, *matchp
= NULL
, *prefilt_optp
= NULL
;
507 post_filter_t
*post_filtp
= NULL
;
509 if ((flags
& ~CFGA_FLAG_VERBOSE
) != 0) {
515 if (flags
& CFGA_FLAG_VERBOSE
) {
516 cols
= s_strdup(DEF_COLS_VERBOSE
);
517 cols2
= s_strdup(DEF_COLS2_VERBOSE
);
520 if (list_opts
!= NULL
&& !extract_list_suboptions(list_opts
,
521 &sort_fields
, &cols
, &cols2
, &noheadings
, &delim
,
522 &selectp
, &matchp
)) {
529 * Scan any args and see if there are any ap_types.
530 * If there are we get all attachment point stats and
531 * then filter what gets printed.
535 for (i
= 0; i
< (argc
- optind
); i
++) {
536 if (find_arg_type(ap_args
[i
]) == AP_TYPE
) {
538 /* ap_types cannot have dynamic components */
539 if (get_dyn(ap_args
[i
]) != NULL
) {
540 (void) fprintf(stderr
,
541 gettext(aptype_no_dyn
),
542 cmdname
, ap_args
[i
]);
551 post_filtp
= config_calloc_check(1, sizeof (*post_filtp
));
552 if (post_filtp
== NULL
) {
556 if (setup_filter(selectp
, matchp
, post_filtp
, &prefilt_optp
)
567 * Check for args. No args means find all libs
568 * and call the cfga_list_ext routine with no ap_ids specified.
569 * With args, if any one of the args are ap_types we
570 * again find all attachment points as in the
571 * no-args case above and then select which attachment points
572 * are actually displayed.
574 if (((argc
- optind
) == 0) || (type
== 1)) {
576 * No args, or atleast 1 ap_type arg
578 ret
= config_list_ext(0, NULL
, &list_array
,
579 &nlist
, plat_opts
, prefilt_optp
, &estrp
,
580 dyn_exp
? CFGA_FLAG_LIST_ALL
: 0);
583 * If the args are all ap_ids (no ap_types) we call the
584 * cfga_list_ext routine with those specific ap_ids.
586 ret
= config_list_ext(argc
- optind
, ap_args
,
587 &list_array
, &nlist
, plat_opts
, prefilt_optp
,
588 &estrp
, dyn_exp
? CFGA_FLAG_LIST_ALL
: 0);
591 S_FREE(prefilt_optp
);
593 if (ret
== CFGA_OK
) {
596 (argc
- optind
), &argv
[optind
], list_array
, nlist
,
597 sort_fields
, cols
, cols2
, noheadings
, delim
,
598 post_filtp
, dyn_exp
) != CFGA_OK
) {
599 exitcode
= EXIT_ARGERROR
;
607 if (estrp
!= NULL
&& *estrp
!= '\0')
608 cfgadm_error(CFGA_NOTSUPP
, estrp
);
609 if (exitcode
!= EXIT_OK
) {
616 cfgadm_error(ret
, estrp
);
620 default: /* paranoia */
625 if (ret
== CFGA_NOTSUPP
) {
626 return (EXIT_NOTSUPP
);
627 } else if (ret
!= CFGA_OK
) {
628 return (EXIT_OPFAILED
);
636 * usage - outputs the usage help message.
643 (void) fprintf(stderr
, "%s\n", gettext("Usage:"));
644 for (i
= 0; i
< sizeof (usage_tab
)/sizeof (usage_tab
[0]); i
++) {
645 (void) fprintf(stderr
, gettext(usage_tab
[i
]), cmdname
);
650 * Emit an error message.
651 * As a side-effect the hardware specific error message is deallocated
652 * as described in config_admin(3X).
655 cfgadm_error(int errnum
, char *estrp
)
659 ep
= config_strerror(errnum
);
661 ep
= gettext("configuration administration unknown error");
662 if (estrp
!= NULL
&& *estrp
!= '\0') {
663 (void) fprintf(stderr
, "%s: %s: %s\n", cmdname
, ep
, estrp
);
665 (void) fprintf(stderr
, "%s: %s\n", cmdname
, ep
);
669 if (errnum
== CFGA_INVAL
)
674 * confirm_interactive - prompt user for confirmation
681 static char yeschr
[YESNO_STR_MAX
+ 2];
682 static char nochr
[YESNO_STR_MAX
+ 2];
683 static int inited
= 0;
686 * First time through initialisation. In the original
687 * version of this command this function is only called once,
688 * but this function is generalized for the future.
691 (void) strncpy(yeschr
, nl_langinfo(YESSTR
), YESNO_STR_MAX
+ 1);
692 (void) strncpy(nochr
, nl_langinfo(NOSTR
), YESNO_STR_MAX
+ 1);
697 (void) fprintf(stderr
, "%s? ", message
);
720 * Find base name of filename.
728 if ((sp
= strrchr(cp
, '/')) != NULL
)
739 (void) fprintf(stderr
, "%s", message
);
745 * extract_list_suboptions - process list option string
748 extract_list_suboptions(
762 while (*arg
!= '\0') {
763 static char need_value
[] =
764 "%s: sub-option \"%s\" requires a value\n";
765 static char no_value
[] =
766 "%s: sub-option \"%s\" does not take a value\n";
767 static char unk_subopt
[] =
768 "%s: sub-option \"%s\" unknown\n";
771 subopt
= getsubopt(&arg
, list_options
, &value
);
792 (void) fprintf(stderr
, gettext(need_value
),
793 cmdname
, list_options
[subopt
]);
798 case LIST_NOHEADINGS
:
800 (void) fprintf(stderr
, gettext(no_value
),
801 cmdname
, list_options
[subopt
]);
807 (void) fprintf(stderr
, gettext(unk_subopt
),
817 setup_prefilter(post_filter_t
*post_filtp
, char **prefilt_optpp
)
820 const char *clopt
= PREFILT_CLASS_STR
;
824 *prefilt_optpp
= NULL
;
826 /* Get the index for the "class" field */
827 for (idx
= 0; idx
< N_FIELDS
; idx
++) {
828 if (strcmp(all_fields
[idx
].name
, PREFILT_CLASS_STR
) == 0)
833 * Currently pre-filter available only for class fld w/ EXACT match
835 if (idx
>= N_FIELDS
||
836 post_filtp
->match_type_p
[idx
] != CFGA_MATCH_EXACT
) {
840 len
= strlen(clopt
) + strlen(post_filtp
->ldata
.ap_class
) + 1;
841 if ((*prefilt_optpp
= config_calloc_check(1, len
)) == NULL
) {
842 return (CFGA_LIB_ERROR
);
845 (void) strcpy(*prefilt_optpp
, clopt
);
846 (void) strcat(*prefilt_optpp
, post_filtp
->ldata
.ap_class
);
849 * Since it is being pre-filtered, this attribute does not need
852 post_filtp
->match_type_p
[idx
] = CFGA_MATCH_NOFILTER
;
853 if (all_fields
[idx
].set_filter
!= NULL
) {
854 (void) all_fields
[idx
].set_filter(&post_filtp
->ldata
, "");
864 post_filter_t
*post_filtp
,
865 match_type_t match_type
)
868 cfga_err_t ret
= CFGA_ERROR
;
870 for (fld
= 0; fld
< N_FIELDS
; fld
++) {
871 if (strcmp(attr
, all_fields
[fld
].name
) == 0)
875 /* Valid field or is the select option supported for this field */
876 if (fld
>= N_FIELDS
|| all_fields
[fld
].set_filter
== NULL
) {
877 return (CFGA_ATTR_INVAL
);
880 if ((ret
= all_fields
[fld
].set_filter(&post_filtp
->ldata
, val
))
882 post_filtp
->match_type_p
[fld
] = match_type
;
889 static char inval_optarg
[] =
890 "%s: invalid value \"%s\" for %s suboption.\n";
893 * Parses the "select" string and fills in the post_filter structure
898 post_filter_t
*post_filtp
,
899 match_type_t match_type
)
901 parse_state_t state
= CFGA_PSTATE_INIT
;
902 char *cp
= NULL
, *optstr
= NULL
, *attr
= NULL
, *val
= NULL
;
903 int bal
= 0; /* Tracks balancing */
908 if (selectp
== NULL
|| post_filtp
== NULL
) {
912 optstr
= config_calloc_check(1, strlen(selectp
) + 1);
913 if (optstr
== NULL
) {
914 return (CFGA_LIB_ERROR
);
917 (void) strcpy(optstr
, selectp
);
920 ret
= CFGA_ATTR_INVAL
;
923 state
= CFGA_PSTATE_INIT
;
925 for (; *cp
!= '\0'; cp
++) {
927 case CFGA_PSTATE_INIT
:
928 if (*cp
!= LEFT_PAREN
)
933 state
= CFGA_PSTATE_ATTR_DONE
;
935 case CFGA_PSTATE_ATTR_DONE
:
945 state
= CFGA_PSTATE_VAL_DONE
;
950 case CFGA_PSTATE_VAL_DONE
:
952 state
= CFGA_PSTATE_ERR
;
957 if (set_attrval(attr
, val
, post_filtp
,
958 match_type
) != CFGA_OK
) {
959 state
= CFGA_PSTATE_ERR
;
962 state
= CFGA_PSTATE_INIT
;
966 state
= CFGA_PSTATE_ERR
;
968 case CFGA_PSTATE_ERR
:
975 if (state
== CFGA_PSTATE_VAL_DONE
) {
976 ret
= set_attrval(attr
, val
, post_filtp
, match_type
);
978 ret
= CFGA_ATTR_INVAL
;
981 if (ret
!= CFGA_OK
) {
982 (void) fprintf(stderr
, gettext(inval_optarg
), cmdname
,
983 selectp
, list_options
[LIST_SELECT
]);
996 post_filter_t
*post_filtp
,
997 char **prefilt_optpp
)
999 cfga_err_t ret
= CFGA_ERROR
;
1000 match_type_t match_type
= CFGA_MATCH_NOFILTER
;
1003 static char match_needs_select
[] =
1004 "%s: %s suboption can only be used with %s suboption.\n";
1007 *prefilt_optpp
= NULL
;
1010 * Initial: no filtering.
1011 * CFGA_MATCH_NOFILTER is NOT a valid user input
1013 for (i
= 0; i
< N_FIELDS
; i
++) {
1014 post_filtp
->match_type_p
[i
] = CFGA_MATCH_NOFILTER
;
1017 /* Determine type of match */
1018 if (matchp
== NULL
&& selectp
== NULL
) {
1021 } else if (matchp
== NULL
&& selectp
!= NULL
) {
1022 match_type
= CFGA_DEFAULT_MATCH
;
1023 } else if (matchp
!= NULL
&& selectp
== NULL
) {
1024 /* If only match specified, select criteria also needed */
1025 (void) fprintf(stderr
, gettext(match_needs_select
),
1026 cmdname
, list_options
[LIST_MATCH
],
1027 list_options
[LIST_SELECT
]);
1028 return (CFGA_ERROR
);
1030 for (i
= 0; i
< N_MATCH_TYPES
; i
++) {
1031 if (strcmp(matchp
, match_type_array
[i
].str
) == 0) {
1032 match_type
= match_type_array
[i
].type
;
1036 if (i
>= N_MATCH_TYPES
) {
1037 (void) fprintf(stderr
, gettext(inval_optarg
), cmdname
,
1038 matchp
, list_options
[LIST_MATCH
]);
1039 return (CFGA_ERROR
);
1043 if ((ret
= parse_select_opt(selectp
, post_filtp
, match_type
))
1048 /* Handle pre-filtering. */
1049 if ((ret
= setup_prefilter(post_filtp
, prefilt_optpp
)) != CFGA_OK
) {
1051 for (i
= 0; i
< N_FIELDS
; i
++) {
1052 post_filtp
->match_type_p
[i
] = CFGA_MATCH_NOFILTER
;
1062 * compare_ap_id - compare two ap_id's
1064 * For partial matches, argument order is significant. The filtering criterion
1065 * should be the first argument.
1070 cfga_list_data_t
*p1
,
1071 cfga_list_data_t
*p2
,
1072 match_type_t match_type
)
1075 switch (match_type
) {
1076 case CFGA_MATCH_NOFILTER
:
1077 return (0); /* No filtering. all pass */
1078 case CFGA_MATCH_PARTIAL
:
1079 return (strncmp(p1
->ap_log_id
, p2
->ap_log_id
,
1080 strlen(p1
->ap_log_id
)));
1081 case CFGA_MATCH_EXACT
:
1082 return (strcmp(p1
->ap_log_id
, p2
->ap_log_id
));
1083 case CFGA_MATCH_ORDER
:
1085 return (config_ap_id_cmp(p1
->ap_log_id
, p2
->ap_log_id
));
1090 * print_log_id - print logical ap_id
1094 cfga_list_data_t
*p
,
1098 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_log_id
),
1103 * set_log_flt - Setup filter for logical ap_id
1107 cfga_list_data_t
*p
,
1110 if (strlen(val
) > sizeof (p
->ap_log_id
) - 1)
1111 return (CFGA_ATTR_INVAL
);
1113 (void) strcpy(p
->ap_log_id
, val
);
1119 * set_type_flt - Setup filter for type field
1124 cfga_list_data_t
*p
,
1127 if (strlen(val
) > sizeof (p
->ap_type
) - 1)
1128 return (CFGA_ATTR_INVAL
);
1130 (void) strcpy(p
->ap_type
, val
);
1136 * set_class_flt - Setup filter for class field
1140 cfga_list_data_t
*p
,
1143 if (strlen(val
) > sizeof (p
->ap_class
) - 1)
1144 return (CFGA_ATTR_INVAL
);
1146 (void) strcpy(p
->ap_class
, val
);
1153 * compare_r_state - compare receptacle state of two ap_id's
1157 cfga_list_data_t
*p1
,
1158 cfga_list_data_t
*p2
,
1159 match_type_t match_type
)
1161 switch (match_type
) {
1162 case CFGA_MATCH_NOFILTER
: /* no filtering. pass all */
1164 case CFGA_MATCH_ORDER
:
1166 return (p1
->ap_r_state
- p2
->ap_r_state
);
1171 * compare_o_state - compare occupant state of two ap_id's
1175 cfga_list_data_t
*p1
,
1176 cfga_list_data_t
*p2
,
1177 match_type_t match_type
)
1179 switch (match_type
) {
1180 case CFGA_MATCH_NOFILTER
: /* no filtering. all pass */
1182 case CFGA_MATCH_ORDER
:
1184 return (p1
->ap_o_state
- p2
->ap_o_state
);
1189 * compare_busy - compare busy field of two ap_id's
1193 cfga_list_data_t
*p1
,
1194 cfga_list_data_t
*p2
,
1195 match_type_t match_type
)
1198 switch (match_type
) {
1199 case CFGA_MATCH_NOFILTER
: /* no filtering. all pass */
1201 case CFGA_MATCH_ORDER
:
1203 return (p1
->ap_busy
- p2
->ap_busy
);
1208 * print_r_state - print receptacle state
1212 cfga_list_data_t
*p
,
1218 switch (p
->ap_r_state
) {
1219 case CFGA_STAT_EMPTY
:
1222 case CFGA_STAT_CONNECTED
:
1225 case CFGA_STAT_DISCONNECTED
:
1226 cp
= "disconnected";
1232 (void) sprintf(lp
, "%-*s", width
, cp
);
1236 * print_o_state - print occupant state
1240 cfga_list_data_t
*p
,
1246 switch (p
->ap_o_state
) {
1247 case CFGA_STAT_UNCONFIGURED
:
1248 cp
= "unconfigured";
1250 case CFGA_STAT_CONFIGURED
:
1257 (void) sprintf(lp
, "%-*s", width
, cp
);
1261 * compare_cond - compare condition field of two ap_id's
1265 cfga_list_data_t
*p1
,
1266 cfga_list_data_t
*p2
,
1267 match_type_t match_type
)
1270 switch (match_type
) {
1271 case CFGA_MATCH_NOFILTER
:
1273 case CFGA_MATCH_ORDER
:
1275 return (p1
->ap_cond
- p2
->ap_cond
);
1280 * print_cond - print attachment point condition
1284 cfga_list_data_t
*p
,
1290 switch (p
->ap_cond
) {
1291 case CFGA_COND_UNKNOWN
:
1294 case CFGA_COND_UNUSABLE
:
1297 case CFGA_COND_FAILING
:
1300 case CFGA_COND_FAILED
:
1310 (void) sprintf(lp
, "%-*s", width
, cp
);
1314 * compare_time - compare time field of two ap_id's
1318 cfga_list_data_t
*p1
,
1319 cfga_list_data_t
*p2
,
1320 match_type_t match_type
)
1322 switch (match_type
) {
1323 case CFGA_MATCH_NOFILTER
:
1325 case CFGA_MATCH_ORDER
:
1327 return (p1
->ap_status_time
- p2
->ap_status_time
);
1333 * print_time - print time from cfga_list_data.
1334 * Time print based on ls(1).
1338 cfga_list_data_t
*p
,
1342 static time_t year
, now
;
1344 char time_buf
[50]; /* array to hold day and time */
1347 now
= time((long *)NULL
);
1348 year
= now
- 6L*30L*24L*60L*60L; /* 6 months ago */
1351 stime
= p
->ap_status_time
;
1352 if (stime
== (time_t)-1) {
1353 (void) sprintf(lp
, "%-*s", width
, gettext("unavailable"));
1357 if ((stime
< year
) || (stime
> now
)) {
1358 (void) strftime(time_buf
, sizeof (time_buf
),
1359 dcgettext(NULL
, FORMAT1
, LC_TIME
), localtime(&stime
));
1361 (void) strftime(time_buf
, sizeof (time_buf
),
1362 dcgettext(NULL
, FORMAT2
, LC_TIME
), localtime(&stime
));
1364 (void) sprintf(lp
, "%-*s", width
, time_buf
);
1368 * print_time_p - print time from cfga_list_data.
1372 cfga_list_data_t
*p
,
1377 char tstr
[TIME_P_WIDTH
+1];
1379 tp
= localtime(&p
->ap_status_time
);
1380 (void) sprintf(tstr
, "%04d%02d%02d%02d%02d%02d", tp
->tm_year
+ 1900,
1381 tp
->tm_mon
+ 1, tp
->tm_mday
, tp
->tm_hour
, tp
->tm_min
, tp
->tm_sec
);
1382 (void) sprintf(lp
, "%-*s", width
, tstr
);
1386 * compare_info - compare info from two cfga_list_data structs
1390 cfga_list_data_t
*p1
,
1391 cfga_list_data_t
*p2
,
1392 match_type_t match_type
)
1394 switch (match_type
) {
1395 case CFGA_MATCH_NOFILTER
:
1397 case CFGA_MATCH_ORDER
:
1399 return (strncmp(p1
->ap_info
, p2
->ap_info
,
1400 sizeof (p2
->ap_info
)));
1405 * print_info - print info from cfga_list_data struct
1409 cfga_list_data_t
*p
,
1413 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_info
), p
->ap_info
);
1417 * compare_type - compare type from two cfga_list_data structs
1419 * For partial matches, argument order is significant. The filtering criterion
1420 * should be the first argument.
1424 cfga_list_data_t
*p1
,
1425 cfga_list_data_t
*p2
,
1426 match_type_t match_type
)
1428 switch (match_type
) {
1429 case CFGA_MATCH_NOFILTER
:
1431 case CFGA_MATCH_PARTIAL
:
1432 return (strncmp(p1
->ap_type
, p2
->ap_type
, strlen(p1
->ap_type
)));
1433 case CFGA_MATCH_EXACT
:
1434 case CFGA_MATCH_ORDER
:
1436 return (strncmp(p1
->ap_type
, p2
->ap_type
,
1437 sizeof (p2
->ap_type
)));
1442 * print_type - print type from cfga_list_data struct
1446 cfga_list_data_t
*p
,
1450 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_type
), p
->ap_type
);
1455 * compare_class - compare class from two cfga_list_data structs
1457 * For partial matches, argument order is significant. The filtering criterion
1458 * should be the first argument.
1462 cfga_list_data_t
*p1
,
1463 cfga_list_data_t
*p2
,
1464 match_type_t match_type
)
1467 switch (match_type
) {
1468 case CFGA_MATCH_NOFILTER
:
1470 case CFGA_MATCH_PARTIAL
:
1471 return (strncmp(p1
->ap_class
, p2
->ap_class
,
1472 strlen(p1
->ap_class
)));
1473 case CFGA_MATCH_EXACT
:
1474 case CFGA_MATCH_ORDER
:
1476 return (strncmp(p1
->ap_class
, p2
->ap_class
,
1477 sizeof (p2
->ap_class
)));
1482 * print_class - print class from cfga_list_data struct
1486 cfga_list_data_t
*p
,
1490 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_class
), p
->ap_class
);
1493 * print_busy - print busy from cfga_list_data struct
1498 cfga_list_data_t
*p
,
1503 (void) sprintf(lp
, "%-*.*s", width
, width
, "y");
1505 (void) sprintf(lp
, "%-*.*s", width
, width
, "n");
1509 * print_phys_id - print physical ap_id
1513 cfga_list_data_t
*p
,
1517 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_phys_id
),
1523 * find_field - find the named field
1525 static struct field_info
*
1526 find_field(char *fname
)
1528 struct field_info
*fldp
;
1530 for (fldp
= all_fields
; fldp
< &all_fields
[N_FIELDS
]; fldp
++)
1531 if (strcmp(fname
, fldp
->name
) == 0)
1537 * usage_field - print field usage
1542 struct field_info
*fldp
= NULL
;
1544 static char field_list
[] = "%s: print or sort fields must be one of:";
1546 (void) fprintf(stderr
, gettext(field_list
), cmdname
);
1549 for (fldp
= all_fields
; fldp
< &all_fields
[N_FIELDS
]; fldp
++) {
1550 (void) fprintf(stderr
, "%s %s", sep
, fldp
->name
);
1553 (void) fprintf(stderr
, "\n");
1557 * compare_null - null comparison routine
1562 cfga_list_data_t
*p1
,
1563 cfga_list_data_t
*p2
,
1564 match_type_t match_type
)
1570 * print_null - print out a field of spaces
1575 cfga_list_data_t
*p
,
1579 (void) sprintf(lp
, "%-*s", width
, "");
1583 * do_config_list - directs the output of the listing functions
1589 cfga_list_data_t
*statlist
,
1596 post_filter_t
*post_filtp
,
1599 int nprcols
= 0, ncols2
= 0;
1600 struct print_col
*prnt_list
= NULL
;
1601 int napids_to_list
= 0;
1604 cfga_list_data_t
**sel_boards
= NULL
;
1609 ap_arg_t
*arg_array
= NULL
;
1610 ap_out_t
*out_array
= NULL
;
1616 nsort_list
= count_fields(sortp
, FDELIM
);
1617 if (nsort_list
!= 0) {
1618 sort_list
= config_calloc_check(nsort_list
,
1619 sizeof (*sort_list
));
1620 if (sort_list
== NULL
) {
1621 ret
= CFGA_LIB_ERROR
;
1624 f_err
|= process_sort_fields(nsort_list
, sort_list
, sortp
);
1628 nprcols
= count_fields(colsp
, FDELIM
);
1629 if ((ncols2
= count_fields(cols2p
, FDELIM
)) > nprcols
)
1632 prnt_list
= config_calloc_check(nprcols
, sizeof (*prnt_list
));
1633 if (prnt_list
== NULL
) {
1634 ret
= CFGA_LIB_ERROR
;
1637 f_err
|= process_fields(nprcols
, prnt_list
, 0, colsp
);
1639 f_err
|= process_fields(nprcols
, prnt_list
, 1, cols2p
);
1649 /* Create an array of all user args (if any) */
1655 for (i
= 0; i
< l_argc
; i
++) {
1656 napids_to_list
+= count_fields(l_argv
[i
], ARG_DELIM
);
1659 arg_array
= config_calloc_check(napids_to_list
,
1660 sizeof (*arg_array
));
1661 if (arg_array
== NULL
) {
1662 ret
= CFGA_LIB_ERROR
;
1666 for (i
= 0, j
= 0; i
< l_argc
; i
++) {
1669 n
= count_fields(l_argv
[i
], ARG_DELIM
);
1672 } else if (n
== 1) {
1673 arg_array
[j
].arg
= l_argv
[i
];
1674 arg_array
[j
].resp
= 0;
1681 arg_array
[j
].arg
= cp
;
1682 arg_array
[j
].resp
= 0;
1684 ncp
= strchr(cp
, ARG_DELIM
);
1692 assert(j
== napids_to_list
);
1700 out_array
= config_calloc_check(nlist
, sizeof (*out_array
));
1701 if (out_array
== NULL
) {
1702 ret
= CFGA_LIB_ERROR
;
1707 /* create a list of output stat data */
1708 for (i
= 0; i
< nlist
; i
++) {
1709 out_array
[i
].ldatap
= &statlist
[i
];
1710 out_array
[i
].req
= 0;
1714 * Mark all user input which got atleast 1 stat data in response
1716 for (i
= 0; i
< napids_to_list
; i
++) {
1717 arg_got_resp(&arg_array
[i
], out_array
, nlist
, dyn_exp
);
1721 * Process output data
1724 for (i
= 0; i
< nlist
; i
++) {
1726 * Mark all the stats which were actually requested by user
1728 out_was_req(&out_array
[i
], arg_array
, napids_to_list
, 0);
1729 if (out_array
[i
].req
== 0 && dyn_exp
) {
1731 * Try again without the dynamic component for the
1732 * if dynamic expansion was requested.
1734 out_was_req(&out_array
[i
], arg_array
,
1739 * post filter data which was actually requested
1741 if (out_array
[i
].req
== 1) {
1742 do_post_filter(&out_array
[i
], post_filtp
, &nsel
);
1746 sel_boards
= config_calloc_check(nsel
, sizeof (*sel_boards
));
1747 if (sel_boards
== NULL
) {
1748 ret
= CFGA_LIB_ERROR
;
1752 for (i
= 0, j
= 0; i
< nlist
; i
++) {
1753 if (out_array
[i
].req
== 1) {
1754 sel_boards
[j
] = out_array
[i
].ldatap
;
1762 * Print headings even if no list entries - Bug or feature ?
1764 if (!noheadings
&& prnt_list
!= NULL
) {
1765 if ((ret
= print_fields(nprcols
, prnt_list
, 1, 0,
1766 delimp
, NULL
, fp
)) != CFGA_OK
) {
1770 if ((ret
= print_fields(nprcols
, prnt_list
, 1,
1771 1, delimp
, NULL
, fp
)) != CFGA_OK
) {
1778 if (sort_list
!= NULL
&& nsel
> 1) {
1779 qsort(sel_boards
, nsel
, sizeof (sel_boards
[0]),
1783 if (prnt_list
!= NULL
) {
1784 for (i
= 0; i
< nsel
; i
++) {
1785 if ((ret
= print_fields(nprcols
,
1786 prnt_list
, 0, 0, delimp
, sel_boards
[i
], fp
))
1790 if ((ret
= print_fields(
1791 nprcols
, prnt_list
, 0, 1, delimp
,
1792 sel_boards
[i
], fp
)) != CFGA_OK
)
1799 * Go thru the argument list and notify user about args
1800 * which did not have a match
1802 report_no_response(arg_array
, napids_to_list
);
1818 * Mark all user inputs which got a response
1821 arg_got_resp(ap_arg_t
*inp
, ap_out_t
*out_array
, int nouts
, int dyn_exp
)
1824 cfga_ap_types_t type
;
1831 type
= find_arg_type(inp
->arg
);
1834 * Go through list of output stats and check if argument
1835 * produced that output
1837 for (i
= 0; i
< nouts
; i
++) {
1838 if (type
== PHYSICAL_AP_ID
) {
1839 if (config_ap_id_cmp(out_array
[i
].ldatap
->ap_phys_id
,
1843 } else if (type
== LOGICAL_AP_ID
) {
1844 if (config_ap_id_cmp(out_array
[i
].ldatap
->ap_log_id
,
1848 } else if (type
== AP_TYPE
) {
1850 * An AP_TYPE argument cannot generate dynamic
1851 * attachment point stats unless dynamic expansion was
1852 * requested by user.
1854 if (!dyn_exp
&& get_dyn(out_array
[i
].ldatap
->ap_log_id
)
1859 if (strncmp(out_array
[i
].ldatap
->ap_log_id
, inp
->arg
,
1860 strlen(inp
->arg
)) == 0) {
1873 /* Mark all stat data which were requested by user */
1875 out_was_req(ap_out_t
*outp
, ap_arg_t
*in_array
, int nargs
, int no_dyn
)
1878 cfga_ap_types_t type
= UNKNOWN_AP
;
1879 char physid
[MAXPATHLEN
], logid
[MAXPATHLEN
];
1882 /* If no user args, all output is acceptable */
1889 (void) snprintf(physid
, sizeof (physid
), "%s",
1890 outp
->ldatap
->ap_phys_id
);
1891 (void) snprintf(logid
, sizeof (logid
), "%s", outp
->ldatap
->ap_log_id
);
1894 * Do comparison with or without dynamic component as requested by
1898 /* Remove the dynamic component */
1903 for (i
= 0; i
< nargs
; i
++) {
1904 type
= find_arg_type(in_array
[i
].arg
);
1905 if (type
== PHYSICAL_AP_ID
) {
1907 if (config_ap_id_cmp(in_array
[i
].arg
, physid
) == 0) {
1910 } else if (type
== LOGICAL_AP_ID
) {
1912 if (config_ap_id_cmp(in_array
[i
].arg
, logid
) == 0) {
1915 } else if (type
== AP_TYPE
) {
1917 * Aptypes cannot generate dynamic attachment
1918 * points unless dynamic expansion is specified.
1919 * in which case this routine would be called a
1920 * 2nd time with the no_dyn flag set and there
1921 * would be no dynamic ap_ids.
1923 if (get_dyn(logid
) != NULL
) {
1927 if (strncmp(in_array
[i
].arg
, logid
,
1928 strlen(in_array
[i
].arg
)) == 0) {
1937 /* Ok, this output was requested */
1944 do_post_filter(ap_out_t
*outp
, post_filter_t
*post_filtp
, int *nselp
)
1948 if (outp
->req
!= 1) {
1953 * For fields without filtering (CFGA_MATCH_NOFILTER),
1954 * compare always returns 0 (success)
1956 for (i
= 0; i
< N_FIELDS
; i
++) {
1958 * Note: Order is important for partial match (via strncmp).
1959 * The first argument for compare must be the filter.
1961 if (all_fields
[i
].compare(&post_filtp
->ldata
, outp
->ldatap
,
1962 post_filtp
->match_type_p
[i
])) {
1963 outp
->req
= 0; /* Blocked by filter */
1969 * Passed through filter
1975 report_no_response(ap_arg_t
*arg_array
, int nargs
)
1985 * nop if no user arguments
1987 for (i
= 0; i
< nargs
; i
++) {
1988 if (arg_array
[i
].resp
== 0) {
1989 (void) fprintf(stderr
,
1990 gettext("%s: No matching library found\n"),
1997 * ldata_compare - compare two attachment point list data structures.
2006 cfga_list_data_t
*b1
, *b2
;
2009 b1
= *(cfga_list_data_t
**)vb1
;
2010 b2
= *(cfga_list_data_t
**)vb2
;
2012 for (i
= 0; i
< nsort_list
; i
++) {
2013 res
= (*(sort_list
[i
].fld
->compare
))(b1
, b2
, CFGA_MATCH_ORDER
);
2015 if (sort_list
[i
].reverse
)
2025 * count_fields - Count the number of fields, using supplied delimiter.
2028 count_fields(char *fspec
, char delim
)
2033 if (fspec
== 0 || *fspec
== '\0')
2036 for (cp
= fspec
; *cp
!= '\0'; cp
++)
2044 * This function is not a re-implementation of strtok().
2045 * There can be null fields - strtok() eats spans of delimiters.
2048 get_field(char **fspp
)
2050 char *cp
= NULL
, *fld
;
2054 if (fld
!= NULL
&& *fld
== '\0')
2058 cp
= strchr(*fspp
, FDELIM
);
2077 struct print_col
*list
,
2081 struct print_col
*pp
= NULL
;
2082 struct field_info
*fldp
= NULL
;
2089 for (pp
= list
; pp
< &list
[ncol
]; pp
++) {
2090 fldn
= get_field(&fmtx
);
2093 struct field_info
*tfldp
;
2095 tfldp
= find_field(fldn
);
2096 if (tfldp
!= NULL
) {
2099 (void) fprintf(stderr
, gettext(unk_field
),
2106 if (fldp
->width
> pp
->width
)
2107 pp
->width
= fldp
->width
;
2110 pp
->width
= fldp
->width
;
2117 * process_sort_fields -
2120 process_sort_fields(
2122 struct sort_el
*list
,
2127 struct field_info
*fldp
= NULL
;
2134 for (i
= 0; i
< nsort
; i
++) {
2135 fldn
= get_field(&fmtx
);
2139 struct field_info
*tfldp
= NULL
;
2145 tfldp
= find_field(fldn
);
2146 if (tfldp
!= NULL
) {
2149 (void) fprintf(stderr
, gettext(unk_field
),
2154 list
[i
].reverse
= rev
;
2166 struct print_col
*list
,
2170 cfga_list_data_t
*bdp
,
2174 struct print_col
*pp
= NULL
;
2175 struct field_info
*fldp
= NULL
;
2176 static char *outline
, *end
;
2179 if (outline
== NULL
) {
2180 int out_len
, delim_len
;
2182 delim_len
= strlen(delim
);
2184 for (pp
= list
; pp
< &list
[ncol
]; pp
++) {
2185 out_len
+= pp
->width
;
2186 out_len
+= delim_len
;
2188 out_len
-= delim_len
;
2189 outline
= config_calloc_check(out_len
+ 1, 1);
2190 if (outline
== NULL
) {
2191 return (CFGA_LIB_ERROR
);
2193 end
= &outline
[out_len
+ 1];
2198 for (pp
= list
; pp
< &list
[ncol
]; pp
++) {
2199 fldp
= line2
? pp
->line2
: pp
->line1
;
2200 (void) snprintf(lp
, end
- lp
, "%s", del
);
2203 (void) snprintf(lp
, end
- lp
, "%-*s",
2204 fldp
->width
, fldp
->heading
);
2206 (*fldp
->printfn
)(bdp
, fldp
->width
, lp
);
2213 * Trim trailing spaces
2215 while (--lp
>= outline
&& *lp
== ' ')
2217 (void) fprintf(fp
, "%s\n", outline
);
2222 * config_calloc_check - perform allocation, check result and
2223 * set error indicator
2226 config_calloc_check(
2231 static char alloc_fail
[] =
2232 "%s: memory allocation failed (%d*%d bytes)\n";
2235 p
= calloc(nelem
, elsize
);
2237 (void) fprintf(stderr
, gettext(alloc_fail
), cmdname
,
2244 * find_arg_type - determine if an argument is an ap_id or an ap_type.
2246 static cfga_ap_types_t
2247 find_arg_type(const char *ap_id
)
2250 cfga_ap_types_t type
;
2251 char *mkr
= NULL
, *cp
;
2252 int size_ap
= 0, size_mkr
= 0, digit
= 0, i
= 0;
2253 char path
[MAXPATHLEN
];
2254 char apbuf
[MAXPATHLEN
];
2261 if (ap_id
== NULL
|| *ap_id
== '\0') {
2262 return (UNKNOWN_AP
);
2266 * Mask the dynamic component if any
2268 if ((cp
= GET_DYN(ap_id
)) != NULL
) {
2271 len
= strlen(ap_id
);
2274 if (len
>= sizeof (apbuf
)) {
2275 return (UNKNOWN_AP
);
2278 (void) strncpy(apbuf
, ap_id
, len
);
2282 * If it starts with a slash and is stat-able
2285 if (*apbuf
== '/' && stat(apbuf
, &sbuf
) == 0) {
2286 return (PHYSICAL_AP_ID
);
2290 * Is this a symlink in CFGA_DEV_DIR ?
2292 (void) snprintf(path
, sizeof (path
), "%s/%s", CFGA_DEV_DIR
, apbuf
);
2294 if (lstat(path
, &sbuf
) == 0 && S_ISLNK(sbuf
.st_mode
) &&
2295 stat(path
, &sbuf
) == 0) {
2296 return (LOGICAL_AP_ID
);
2300 * Check for ":" which is always present in an ap_id but not maybe
2301 * present or absent in an ap_type.
2302 * We need to check that the characters right before the : are digits
2303 * since an ap_id is of the form <name><instance>:<specific ap name>
2305 if ((mkr
= strchr(apbuf
, ':')) == NULL
) {
2308 size_ap
= strlen(apbuf
);
2309 size_mkr
= strlen(mkr
);
2313 for (i
= size_ap
- size_mkr
- 1; i
> 0; i
--) {
2314 if ((int)isdigit(mkr
[i
])) {
2322 type
= LOGICAL_AP_ID
;
2331 get_dyn(const char *ap_id
)
2333 if (ap_id
== NULL
) {
2337 return (strstr(ap_id
, CFGA_DYN_SEP
));
2341 * removes the dynamic component
2344 remove_dyn(char *ap_id
)
2348 if (ap_id
== NULL
) {
2352 cp
= strstr(ap_id
, CFGA_DYN_SEP
);
2365 * sometimes NULL strings may be passed in (see DEF_COLS2). This
2374 (void) fprintf(stderr
,
2375 "%s \"%s\"\n", gettext("Cannot copy string"), str
);