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) (free(x), (x) = NULL)
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 int inited
= 0;
684 * First time through initialisation. In the original
685 * version of this command this function is only called once,
686 * but this function is generalized for the future.
693 (void) fprintf(stderr
, "%s? ", message
);
716 * Find base name of filename.
724 if ((sp
= strrchr(cp
, '/')) != NULL
)
735 (void) fprintf(stderr
, "%s", message
);
741 * extract_list_suboptions - process list option string
744 extract_list_suboptions(
758 while (*arg
!= '\0') {
759 static char need_value
[] =
760 "%s: sub-option \"%s\" requires a value\n";
761 static char no_value
[] =
762 "%s: sub-option \"%s\" does not take a value\n";
763 static char unk_subopt
[] =
764 "%s: sub-option \"%s\" unknown\n";
767 subopt
= getsubopt(&arg
, list_options
, &value
);
788 (void) fprintf(stderr
, gettext(need_value
),
789 cmdname
, list_options
[subopt
]);
794 case LIST_NOHEADINGS
:
796 (void) fprintf(stderr
, gettext(no_value
),
797 cmdname
, list_options
[subopt
]);
803 (void) fprintf(stderr
, gettext(unk_subopt
),
813 setup_prefilter(post_filter_t
*post_filtp
, char **prefilt_optpp
)
816 const char *clopt
= PREFILT_CLASS_STR
;
820 *prefilt_optpp
= NULL
;
822 /* Get the index for the "class" field */
823 for (idx
= 0; idx
< N_FIELDS
; idx
++) {
824 if (strcmp(all_fields
[idx
].name
, PREFILT_CLASS_STR
) == 0)
829 * Currently pre-filter available only for class fld w/ EXACT match
831 if (idx
>= N_FIELDS
||
832 post_filtp
->match_type_p
[idx
] != CFGA_MATCH_EXACT
) {
836 len
= strlen(clopt
) + strlen(post_filtp
->ldata
.ap_class
) + 1;
837 if ((*prefilt_optpp
= config_calloc_check(1, len
)) == NULL
) {
838 return (CFGA_LIB_ERROR
);
841 (void) strcpy(*prefilt_optpp
, clopt
);
842 (void) strcat(*prefilt_optpp
, post_filtp
->ldata
.ap_class
);
845 * Since it is being pre-filtered, this attribute does not need
848 post_filtp
->match_type_p
[idx
] = CFGA_MATCH_NOFILTER
;
849 if (all_fields
[idx
].set_filter
!= NULL
) {
850 (void) all_fields
[idx
].set_filter(&post_filtp
->ldata
, "");
860 post_filter_t
*post_filtp
,
861 match_type_t match_type
)
864 cfga_err_t ret
= CFGA_ERROR
;
866 for (fld
= 0; fld
< N_FIELDS
; fld
++) {
867 if (strcmp(attr
, all_fields
[fld
].name
) == 0)
871 /* Valid field or is the select option supported for this field */
872 if (fld
>= N_FIELDS
|| all_fields
[fld
].set_filter
== NULL
) {
873 return (CFGA_ATTR_INVAL
);
876 if ((ret
= all_fields
[fld
].set_filter(&post_filtp
->ldata
, val
))
878 post_filtp
->match_type_p
[fld
] = match_type
;
885 static char inval_optarg
[] =
886 "%s: invalid value \"%s\" for %s suboption.\n";
889 * Parses the "select" string and fills in the post_filter structure
894 post_filter_t
*post_filtp
,
895 match_type_t match_type
)
897 parse_state_t state
= CFGA_PSTATE_INIT
;
898 char *cp
= NULL
, *optstr
= NULL
, *attr
= NULL
, *val
= NULL
;
899 int bal
= 0; /* Tracks balancing */
904 if (selectp
== NULL
|| post_filtp
== NULL
) {
908 optstr
= config_calloc_check(1, strlen(selectp
) + 1);
909 if (optstr
== NULL
) {
910 return (CFGA_LIB_ERROR
);
913 (void) strcpy(optstr
, selectp
);
916 ret
= CFGA_ATTR_INVAL
;
919 state
= CFGA_PSTATE_INIT
;
921 for (; *cp
!= '\0'; cp
++) {
923 case CFGA_PSTATE_INIT
:
924 if (*cp
!= LEFT_PAREN
)
929 state
= CFGA_PSTATE_ATTR_DONE
;
931 case CFGA_PSTATE_ATTR_DONE
:
941 state
= CFGA_PSTATE_VAL_DONE
;
946 case CFGA_PSTATE_VAL_DONE
:
948 state
= CFGA_PSTATE_ERR
;
953 if (set_attrval(attr
, val
, post_filtp
,
954 match_type
) != CFGA_OK
) {
955 state
= CFGA_PSTATE_ERR
;
958 state
= CFGA_PSTATE_INIT
;
962 state
= CFGA_PSTATE_ERR
;
964 case CFGA_PSTATE_ERR
:
971 if (state
== CFGA_PSTATE_VAL_DONE
) {
972 ret
= set_attrval(attr
, val
, post_filtp
, match_type
);
974 ret
= CFGA_ATTR_INVAL
;
977 if (ret
!= CFGA_OK
) {
978 (void) fprintf(stderr
, gettext(inval_optarg
), cmdname
,
979 selectp
, list_options
[LIST_SELECT
]);
992 post_filter_t
*post_filtp
,
993 char **prefilt_optpp
)
995 cfga_err_t ret
= CFGA_ERROR
;
996 match_type_t match_type
= CFGA_MATCH_NOFILTER
;
999 static char match_needs_select
[] =
1000 "%s: %s suboption can only be used with %s suboption.\n";
1003 *prefilt_optpp
= NULL
;
1006 * Initial: no filtering.
1007 * CFGA_MATCH_NOFILTER is NOT a valid user input
1009 for (i
= 0; i
< N_FIELDS
; i
++) {
1010 post_filtp
->match_type_p
[i
] = CFGA_MATCH_NOFILTER
;
1013 /* Determine type of match */
1014 if (matchp
== NULL
&& selectp
== NULL
) {
1017 } else if (matchp
== NULL
&& selectp
!= NULL
) {
1018 match_type
= CFGA_DEFAULT_MATCH
;
1019 } else if (matchp
!= NULL
&& selectp
== NULL
) {
1020 /* If only match specified, select criteria also needed */
1021 (void) fprintf(stderr
, gettext(match_needs_select
),
1022 cmdname
, list_options
[LIST_MATCH
],
1023 list_options
[LIST_SELECT
]);
1024 return (CFGA_ERROR
);
1026 for (i
= 0; i
< N_MATCH_TYPES
; i
++) {
1027 if (strcmp(matchp
, match_type_array
[i
].str
) == 0) {
1028 match_type
= match_type_array
[i
].type
;
1032 if (i
>= N_MATCH_TYPES
) {
1033 (void) fprintf(stderr
, gettext(inval_optarg
), cmdname
,
1034 matchp
, list_options
[LIST_MATCH
]);
1035 return (CFGA_ERROR
);
1039 if ((ret
= parse_select_opt(selectp
, post_filtp
, match_type
))
1044 /* Handle pre-filtering. */
1045 if ((ret
= setup_prefilter(post_filtp
, prefilt_optpp
)) != CFGA_OK
) {
1047 for (i
= 0; i
< N_FIELDS
; i
++) {
1048 post_filtp
->match_type_p
[i
] = CFGA_MATCH_NOFILTER
;
1058 * compare_ap_id - compare two ap_id's
1060 * For partial matches, argument order is significant. The filtering criterion
1061 * should be the first argument.
1066 cfga_list_data_t
*p1
,
1067 cfga_list_data_t
*p2
,
1068 match_type_t match_type
)
1071 switch (match_type
) {
1072 case CFGA_MATCH_NOFILTER
:
1073 return (0); /* No filtering. all pass */
1074 case CFGA_MATCH_PARTIAL
:
1075 return (strncmp(p1
->ap_log_id
, p2
->ap_log_id
,
1076 strlen(p1
->ap_log_id
)));
1077 case CFGA_MATCH_EXACT
:
1078 return (strcmp(p1
->ap_log_id
, p2
->ap_log_id
));
1079 case CFGA_MATCH_ORDER
:
1081 return (config_ap_id_cmp(p1
->ap_log_id
, p2
->ap_log_id
));
1086 * print_log_id - print logical ap_id
1090 cfga_list_data_t
*p
,
1094 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_log_id
),
1099 * set_log_flt - Setup filter for logical ap_id
1103 cfga_list_data_t
*p
,
1106 if (strlen(val
) > sizeof (p
->ap_log_id
) - 1)
1107 return (CFGA_ATTR_INVAL
);
1109 (void) strcpy(p
->ap_log_id
, val
);
1115 * set_type_flt - Setup filter for type field
1120 cfga_list_data_t
*p
,
1123 if (strlen(val
) > sizeof (p
->ap_type
) - 1)
1124 return (CFGA_ATTR_INVAL
);
1126 (void) strcpy(p
->ap_type
, val
);
1132 * set_class_flt - Setup filter for class field
1136 cfga_list_data_t
*p
,
1139 if (strlen(val
) > sizeof (p
->ap_class
) - 1)
1140 return (CFGA_ATTR_INVAL
);
1142 (void) strcpy(p
->ap_class
, val
);
1149 * compare_r_state - compare receptacle state of two ap_id's
1153 cfga_list_data_t
*p1
,
1154 cfga_list_data_t
*p2
,
1155 match_type_t match_type
)
1157 switch (match_type
) {
1158 case CFGA_MATCH_NOFILTER
: /* no filtering. pass all */
1160 case CFGA_MATCH_ORDER
:
1162 return (p1
->ap_r_state
- p2
->ap_r_state
);
1167 * compare_o_state - compare occupant state of two ap_id's
1171 cfga_list_data_t
*p1
,
1172 cfga_list_data_t
*p2
,
1173 match_type_t match_type
)
1175 switch (match_type
) {
1176 case CFGA_MATCH_NOFILTER
: /* no filtering. all pass */
1178 case CFGA_MATCH_ORDER
:
1180 return (p1
->ap_o_state
- p2
->ap_o_state
);
1185 * compare_busy - compare busy field of two ap_id's
1189 cfga_list_data_t
*p1
,
1190 cfga_list_data_t
*p2
,
1191 match_type_t match_type
)
1194 switch (match_type
) {
1195 case CFGA_MATCH_NOFILTER
: /* no filtering. all pass */
1197 case CFGA_MATCH_ORDER
:
1199 return (p1
->ap_busy
- p2
->ap_busy
);
1204 * print_r_state - print receptacle state
1208 cfga_list_data_t
*p
,
1214 switch (p
->ap_r_state
) {
1215 case CFGA_STAT_EMPTY
:
1218 case CFGA_STAT_CONNECTED
:
1221 case CFGA_STAT_DISCONNECTED
:
1222 cp
= "disconnected";
1228 (void) sprintf(lp
, "%-*s", width
, cp
);
1232 * print_o_state - print occupant state
1236 cfga_list_data_t
*p
,
1242 switch (p
->ap_o_state
) {
1243 case CFGA_STAT_UNCONFIGURED
:
1244 cp
= "unconfigured";
1246 case CFGA_STAT_CONFIGURED
:
1253 (void) sprintf(lp
, "%-*s", width
, cp
);
1257 * compare_cond - compare condition field of two ap_id's
1261 cfga_list_data_t
*p1
,
1262 cfga_list_data_t
*p2
,
1263 match_type_t match_type
)
1266 switch (match_type
) {
1267 case CFGA_MATCH_NOFILTER
:
1269 case CFGA_MATCH_ORDER
:
1271 return (p1
->ap_cond
- p2
->ap_cond
);
1276 * print_cond - print attachment point condition
1280 cfga_list_data_t
*p
,
1286 switch (p
->ap_cond
) {
1287 case CFGA_COND_UNKNOWN
:
1290 case CFGA_COND_UNUSABLE
:
1293 case CFGA_COND_FAILING
:
1296 case CFGA_COND_FAILED
:
1306 (void) sprintf(lp
, "%-*s", width
, cp
);
1310 * compare_time - compare time field of two ap_id's
1314 cfga_list_data_t
*p1
,
1315 cfga_list_data_t
*p2
,
1316 match_type_t match_type
)
1318 switch (match_type
) {
1319 case CFGA_MATCH_NOFILTER
:
1321 case CFGA_MATCH_ORDER
:
1323 return (p1
->ap_status_time
- p2
->ap_status_time
);
1329 * print_time - print time from cfga_list_data.
1330 * Time print based on ls(1).
1334 cfga_list_data_t
*p
,
1338 static time_t year
, now
;
1340 char time_buf
[50]; /* array to hold day and time */
1344 year
= now
- 6L*30L*24L*60L*60L; /* 6 months ago */
1347 stime
= p
->ap_status_time
;
1348 if (stime
== (time_t)-1) {
1349 (void) sprintf(lp
, "%-*s", width
, gettext("unavailable"));
1353 if ((stime
< year
) || (stime
> now
)) {
1354 (void) strftime(time_buf
, sizeof (time_buf
),
1355 dcgettext(NULL
, FORMAT1
, LC_TIME
), localtime(&stime
));
1357 (void) strftime(time_buf
, sizeof (time_buf
),
1358 dcgettext(NULL
, FORMAT2
, LC_TIME
), localtime(&stime
));
1360 (void) sprintf(lp
, "%-*s", width
, time_buf
);
1364 * print_time_p - print time from cfga_list_data.
1368 cfga_list_data_t
*p
,
1373 char tstr
[TIME_P_WIDTH
+1];
1375 tp
= localtime(&p
->ap_status_time
);
1376 (void) sprintf(tstr
, "%04d%02d%02d%02d%02d%02d", tp
->tm_year
+ 1900,
1377 tp
->tm_mon
+ 1, tp
->tm_mday
, tp
->tm_hour
, tp
->tm_min
, tp
->tm_sec
);
1378 (void) sprintf(lp
, "%-*s", width
, tstr
);
1382 * compare_info - compare info from two cfga_list_data structs
1386 cfga_list_data_t
*p1
,
1387 cfga_list_data_t
*p2
,
1388 match_type_t match_type
)
1390 switch (match_type
) {
1391 case CFGA_MATCH_NOFILTER
:
1393 case CFGA_MATCH_ORDER
:
1395 return (strncmp(p1
->ap_info
, p2
->ap_info
,
1396 sizeof (p2
->ap_info
)));
1401 * print_info - print info from cfga_list_data struct
1405 cfga_list_data_t
*p
,
1409 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_info
), p
->ap_info
);
1413 * compare_type - compare type from two cfga_list_data structs
1415 * For partial matches, argument order is significant. The filtering criterion
1416 * should be the first argument.
1420 cfga_list_data_t
*p1
,
1421 cfga_list_data_t
*p2
,
1422 match_type_t match_type
)
1424 switch (match_type
) {
1425 case CFGA_MATCH_NOFILTER
:
1427 case CFGA_MATCH_PARTIAL
:
1428 return (strncmp(p1
->ap_type
, p2
->ap_type
, strlen(p1
->ap_type
)));
1429 case CFGA_MATCH_EXACT
:
1430 case CFGA_MATCH_ORDER
:
1432 return (strncmp(p1
->ap_type
, p2
->ap_type
,
1433 sizeof (p2
->ap_type
)));
1438 * print_type - print type from cfga_list_data struct
1442 cfga_list_data_t
*p
,
1446 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_type
), p
->ap_type
);
1451 * compare_class - compare class from two cfga_list_data structs
1453 * For partial matches, argument order is significant. The filtering criterion
1454 * should be the first argument.
1458 cfga_list_data_t
*p1
,
1459 cfga_list_data_t
*p2
,
1460 match_type_t match_type
)
1463 switch (match_type
) {
1464 case CFGA_MATCH_NOFILTER
:
1466 case CFGA_MATCH_PARTIAL
:
1467 return (strncmp(p1
->ap_class
, p2
->ap_class
,
1468 strlen(p1
->ap_class
)));
1469 case CFGA_MATCH_EXACT
:
1470 case CFGA_MATCH_ORDER
:
1472 return (strncmp(p1
->ap_class
, p2
->ap_class
,
1473 sizeof (p2
->ap_class
)));
1478 * print_class - print class from cfga_list_data struct
1482 cfga_list_data_t
*p
,
1486 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_class
), p
->ap_class
);
1489 * print_busy - print busy from cfga_list_data struct
1494 cfga_list_data_t
*p
,
1499 (void) sprintf(lp
, "%-*.*s", width
, width
, "y");
1501 (void) sprintf(lp
, "%-*.*s", width
, width
, "n");
1505 * print_phys_id - print physical ap_id
1509 cfga_list_data_t
*p
,
1513 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_phys_id
),
1519 * find_field - find the named field
1521 static struct field_info
*
1522 find_field(char *fname
)
1524 struct field_info
*fldp
;
1526 for (fldp
= all_fields
; fldp
< &all_fields
[N_FIELDS
]; fldp
++)
1527 if (strcmp(fname
, fldp
->name
) == 0)
1533 * usage_field - print field usage
1538 struct field_info
*fldp
= NULL
;
1540 static char field_list
[] = "%s: print or sort fields must be one of:";
1542 (void) fprintf(stderr
, gettext(field_list
), cmdname
);
1545 for (fldp
= all_fields
; fldp
< &all_fields
[N_FIELDS
]; fldp
++) {
1546 (void) fprintf(stderr
, "%s %s", sep
, fldp
->name
);
1549 (void) fprintf(stderr
, "\n");
1553 * compare_null - null comparison routine
1558 cfga_list_data_t
*p1
,
1559 cfga_list_data_t
*p2
,
1560 match_type_t match_type
)
1566 * print_null - print out a field of spaces
1571 cfga_list_data_t
*p
,
1575 (void) sprintf(lp
, "%-*s", width
, "");
1579 * do_config_list - directs the output of the listing functions
1585 cfga_list_data_t
*statlist
,
1592 post_filter_t
*post_filtp
,
1595 int nprcols
= 0, ncols2
= 0;
1596 struct print_col
*prnt_list
= NULL
;
1597 int napids_to_list
= 0;
1600 cfga_list_data_t
**sel_boards
= NULL
;
1605 ap_arg_t
*arg_array
= NULL
;
1606 ap_out_t
*out_array
= NULL
;
1612 nsort_list
= count_fields(sortp
, FDELIM
);
1613 if (nsort_list
!= 0) {
1614 sort_list
= config_calloc_check(nsort_list
,
1615 sizeof (*sort_list
));
1616 if (sort_list
== NULL
) {
1617 ret
= CFGA_LIB_ERROR
;
1620 f_err
|= process_sort_fields(nsort_list
, sort_list
, sortp
);
1624 nprcols
= count_fields(colsp
, FDELIM
);
1625 if ((ncols2
= count_fields(cols2p
, FDELIM
)) > nprcols
)
1628 prnt_list
= config_calloc_check(nprcols
, sizeof (*prnt_list
));
1629 if (prnt_list
== NULL
) {
1630 ret
= CFGA_LIB_ERROR
;
1633 f_err
|= process_fields(nprcols
, prnt_list
, 0, colsp
);
1635 f_err
|= process_fields(nprcols
, prnt_list
, 1, cols2p
);
1645 /* Create an array of all user args (if any) */
1651 for (i
= 0; i
< l_argc
; i
++) {
1652 napids_to_list
+= count_fields(l_argv
[i
], ARG_DELIM
);
1655 arg_array
= config_calloc_check(napids_to_list
,
1656 sizeof (*arg_array
));
1657 if (arg_array
== NULL
) {
1658 ret
= CFGA_LIB_ERROR
;
1662 for (i
= 0, j
= 0; i
< l_argc
; i
++) {
1665 n
= count_fields(l_argv
[i
], ARG_DELIM
);
1668 } else if (n
== 1) {
1669 arg_array
[j
].arg
= l_argv
[i
];
1670 arg_array
[j
].resp
= 0;
1677 arg_array
[j
].arg
= cp
;
1678 arg_array
[j
].resp
= 0;
1680 ncp
= strchr(cp
, ARG_DELIM
);
1688 assert(j
== napids_to_list
);
1696 out_array
= config_calloc_check(nlist
, sizeof (*out_array
));
1697 if (out_array
== NULL
) {
1698 ret
= CFGA_LIB_ERROR
;
1703 /* create a list of output stat data */
1704 for (i
= 0; i
< nlist
; i
++) {
1705 out_array
[i
].ldatap
= &statlist
[i
];
1706 out_array
[i
].req
= 0;
1710 * Mark all user input which got atleast 1 stat data in response
1712 for (i
= 0; i
< napids_to_list
; i
++) {
1713 arg_got_resp(&arg_array
[i
], out_array
, nlist
, dyn_exp
);
1717 * Process output data
1720 for (i
= 0; i
< nlist
; i
++) {
1722 * Mark all the stats which were actually requested by user
1724 out_was_req(&out_array
[i
], arg_array
, napids_to_list
, 0);
1725 if (out_array
[i
].req
== 0 && dyn_exp
) {
1727 * Try again without the dynamic component for the
1728 * if dynamic expansion was requested.
1730 out_was_req(&out_array
[i
], arg_array
,
1735 * post filter data which was actually requested
1737 if (out_array
[i
].req
== 1) {
1738 do_post_filter(&out_array
[i
], post_filtp
, &nsel
);
1742 sel_boards
= config_calloc_check(nsel
, sizeof (*sel_boards
));
1743 if (sel_boards
== NULL
) {
1744 ret
= CFGA_LIB_ERROR
;
1748 for (i
= 0, j
= 0; i
< nlist
; i
++) {
1749 if (out_array
[i
].req
== 1) {
1750 sel_boards
[j
] = out_array
[i
].ldatap
;
1758 * Print headings even if no list entries - Bug or feature ?
1760 if (!noheadings
&& prnt_list
!= NULL
) {
1761 if ((ret
= print_fields(nprcols
, prnt_list
, 1, 0,
1762 delimp
, NULL
, fp
)) != CFGA_OK
) {
1766 if ((ret
= print_fields(nprcols
, prnt_list
, 1,
1767 1, delimp
, NULL
, fp
)) != CFGA_OK
) {
1774 if (sort_list
!= NULL
&& nsel
> 1) {
1775 qsort(sel_boards
, nsel
, sizeof (sel_boards
[0]),
1779 if (prnt_list
!= NULL
) {
1780 for (i
= 0; i
< nsel
; i
++) {
1781 if ((ret
= print_fields(nprcols
,
1782 prnt_list
, 0, 0, delimp
, sel_boards
[i
], fp
))
1786 if ((ret
= print_fields(
1787 nprcols
, prnt_list
, 0, 1, delimp
,
1788 sel_boards
[i
], fp
)) != CFGA_OK
)
1795 * Go thru the argument list and notify user about args
1796 * which did not have a match
1798 report_no_response(arg_array
, napids_to_list
);
1814 * Mark all user inputs which got a response
1817 arg_got_resp(ap_arg_t
*inp
, ap_out_t
*out_array
, int nouts
, int dyn_exp
)
1820 cfga_ap_types_t type
;
1827 type
= find_arg_type(inp
->arg
);
1830 * Go through list of output stats and check if argument
1831 * produced that output
1833 for (i
= 0; i
< nouts
; i
++) {
1834 if (type
== PHYSICAL_AP_ID
) {
1835 if (config_ap_id_cmp(out_array
[i
].ldatap
->ap_phys_id
,
1839 } else if (type
== LOGICAL_AP_ID
) {
1840 if (config_ap_id_cmp(out_array
[i
].ldatap
->ap_log_id
,
1844 } else if (type
== AP_TYPE
) {
1846 * An AP_TYPE argument cannot generate dynamic
1847 * attachment point stats unless dynamic expansion was
1848 * requested by user.
1850 if (!dyn_exp
&& get_dyn(out_array
[i
].ldatap
->ap_log_id
)
1855 if (strncmp(out_array
[i
].ldatap
->ap_log_id
, inp
->arg
,
1856 strlen(inp
->arg
)) == 0) {
1869 /* Mark all stat data which were requested by user */
1871 out_was_req(ap_out_t
*outp
, ap_arg_t
*in_array
, int nargs
, int no_dyn
)
1874 cfga_ap_types_t type
= UNKNOWN_AP
;
1875 char physid
[MAXPATHLEN
], logid
[MAXPATHLEN
];
1878 /* If no user args, all output is acceptable */
1885 (void) snprintf(physid
, sizeof (physid
), "%s",
1886 outp
->ldatap
->ap_phys_id
);
1887 (void) snprintf(logid
, sizeof (logid
), "%s", outp
->ldatap
->ap_log_id
);
1890 * Do comparison with or without dynamic component as requested by
1894 /* Remove the dynamic component */
1899 for (i
= 0; i
< nargs
; i
++) {
1900 type
= find_arg_type(in_array
[i
].arg
);
1901 if (type
== PHYSICAL_AP_ID
) {
1903 if (config_ap_id_cmp(in_array
[i
].arg
, physid
) == 0) {
1906 } else if (type
== LOGICAL_AP_ID
) {
1908 if (config_ap_id_cmp(in_array
[i
].arg
, logid
) == 0) {
1911 } else if (type
== AP_TYPE
) {
1913 * Aptypes cannot generate dynamic attachment
1914 * points unless dynamic expansion is specified.
1915 * in which case this routine would be called a
1916 * 2nd time with the no_dyn flag set and there
1917 * would be no dynamic ap_ids.
1919 if (get_dyn(logid
) != NULL
) {
1923 if (strncmp(in_array
[i
].arg
, logid
,
1924 strlen(in_array
[i
].arg
)) == 0) {
1933 /* Ok, this output was requested */
1940 do_post_filter(ap_out_t
*outp
, post_filter_t
*post_filtp
, int *nselp
)
1944 if (outp
->req
!= 1) {
1949 * For fields without filtering (CFGA_MATCH_NOFILTER),
1950 * compare always returns 0 (success)
1952 for (i
= 0; i
< N_FIELDS
; i
++) {
1954 * Note: Order is important for partial match (via strncmp).
1955 * The first argument for compare must be the filter.
1957 if (all_fields
[i
].compare(&post_filtp
->ldata
, outp
->ldatap
,
1958 post_filtp
->match_type_p
[i
])) {
1959 outp
->req
= 0; /* Blocked by filter */
1965 * Passed through filter
1971 report_no_response(ap_arg_t
*arg_array
, int nargs
)
1981 * nop if no user arguments
1983 for (i
= 0; i
< nargs
; i
++) {
1984 if (arg_array
[i
].resp
== 0) {
1985 (void) fprintf(stderr
,
1986 gettext("%s: No matching library found\n"),
1993 * ldata_compare - compare two attachment point list data structures.
2002 cfga_list_data_t
*b1
, *b2
;
2005 b1
= *(cfga_list_data_t
**)vb1
;
2006 b2
= *(cfga_list_data_t
**)vb2
;
2008 for (i
= 0; i
< nsort_list
; i
++) {
2009 res
= (*(sort_list
[i
].fld
->compare
))(b1
, b2
, CFGA_MATCH_ORDER
);
2011 if (sort_list
[i
].reverse
)
2021 * count_fields - Count the number of fields, using supplied delimiter.
2024 count_fields(char *fspec
, char delim
)
2029 if (fspec
== 0 || *fspec
== '\0')
2032 for (cp
= fspec
; *cp
!= '\0'; cp
++)
2040 * This function is not a re-implementation of strtok().
2041 * There can be null fields - strtok() eats spans of delimiters.
2044 get_field(char **fspp
)
2046 char *cp
= NULL
, *fld
;
2050 if (fld
!= NULL
&& *fld
== '\0')
2054 cp
= strchr(*fspp
, FDELIM
);
2073 struct print_col
*list
,
2077 struct print_col
*pp
= NULL
;
2078 struct field_info
*fldp
= NULL
;
2085 for (pp
= list
; pp
< &list
[ncol
]; pp
++) {
2086 fldn
= get_field(&fmtx
);
2089 struct field_info
*tfldp
;
2091 tfldp
= find_field(fldn
);
2092 if (tfldp
!= NULL
) {
2095 (void) fprintf(stderr
, gettext(unk_field
),
2102 if (fldp
->width
> pp
->width
)
2103 pp
->width
= fldp
->width
;
2106 pp
->width
= fldp
->width
;
2113 * process_sort_fields -
2116 process_sort_fields(
2118 struct sort_el
*list
,
2123 struct field_info
*fldp
= NULL
;
2130 for (i
= 0; i
< nsort
; i
++) {
2131 fldn
= get_field(&fmtx
);
2135 struct field_info
*tfldp
= NULL
;
2141 tfldp
= find_field(fldn
);
2142 if (tfldp
!= NULL
) {
2145 (void) fprintf(stderr
, gettext(unk_field
),
2150 list
[i
].reverse
= rev
;
2162 struct print_col
*list
,
2166 cfga_list_data_t
*bdp
,
2170 struct print_col
*pp
= NULL
;
2171 struct field_info
*fldp
= NULL
;
2172 static char *outline
, *end
;
2175 if (outline
== NULL
) {
2176 int out_len
, delim_len
;
2178 delim_len
= strlen(delim
);
2180 for (pp
= list
; pp
< &list
[ncol
]; pp
++) {
2181 out_len
+= pp
->width
;
2182 out_len
+= delim_len
;
2184 out_len
-= delim_len
;
2185 outline
= config_calloc_check(out_len
+ 1, 1);
2186 if (outline
== NULL
) {
2187 return (CFGA_LIB_ERROR
);
2189 end
= &outline
[out_len
+ 1];
2194 for (pp
= list
; pp
< &list
[ncol
]; pp
++) {
2195 fldp
= line2
? pp
->line2
: pp
->line1
;
2196 (void) snprintf(lp
, end
- lp
, "%s", del
);
2199 (void) snprintf(lp
, end
- lp
, "%-*s",
2200 fldp
->width
, fldp
->heading
);
2202 (*fldp
->printfn
)(bdp
, fldp
->width
, lp
);
2209 * Trim trailing spaces
2211 while (--lp
>= outline
&& *lp
== ' ')
2213 (void) fprintf(fp
, "%s\n", outline
);
2218 * config_calloc_check - perform allocation, check result and
2219 * set error indicator
2222 config_calloc_check(
2227 static char alloc_fail
[] =
2228 "%s: memory allocation failed (%d*%d bytes)\n";
2231 p
= calloc(nelem
, elsize
);
2233 (void) fprintf(stderr
, gettext(alloc_fail
), cmdname
,
2240 * find_arg_type - determine if an argument is an ap_id or an ap_type.
2242 static cfga_ap_types_t
2243 find_arg_type(const char *ap_id
)
2246 cfga_ap_types_t type
;
2247 char *mkr
= NULL
, *cp
;
2248 int size_ap
= 0, size_mkr
= 0, digit
= 0, i
= 0;
2249 char path
[MAXPATHLEN
];
2250 char apbuf
[MAXPATHLEN
];
2257 if (ap_id
== NULL
|| *ap_id
== '\0') {
2258 return (UNKNOWN_AP
);
2262 * Mask the dynamic component if any
2264 if ((cp
= GET_DYN(ap_id
)) != NULL
) {
2267 len
= strlen(ap_id
);
2270 if (len
>= sizeof (apbuf
)) {
2271 return (UNKNOWN_AP
);
2274 (void) strncpy(apbuf
, ap_id
, len
);
2278 * If it starts with a slash and is stat-able
2281 if (*apbuf
== '/' && stat(apbuf
, &sbuf
) == 0) {
2282 return (PHYSICAL_AP_ID
);
2286 * Is this a symlink in CFGA_DEV_DIR ?
2288 (void) snprintf(path
, sizeof (path
), "%s/%s", CFGA_DEV_DIR
, apbuf
);
2290 if (lstat(path
, &sbuf
) == 0 && S_ISLNK(sbuf
.st_mode
) &&
2291 stat(path
, &sbuf
) == 0) {
2292 return (LOGICAL_AP_ID
);
2296 * Check for ":" which is always present in an ap_id but not maybe
2297 * present or absent in an ap_type.
2298 * We need to check that the characters right before the : are digits
2299 * since an ap_id is of the form <name><instance>:<specific ap name>
2301 if ((mkr
= strchr(apbuf
, ':')) == NULL
) {
2304 size_ap
= strlen(apbuf
);
2305 size_mkr
= strlen(mkr
);
2309 for (i
= size_ap
- size_mkr
- 1; i
> 0; i
--) {
2310 if ((int)isdigit(mkr
[i
])) {
2318 type
= LOGICAL_AP_ID
;
2327 get_dyn(const char *ap_id
)
2329 if (ap_id
== NULL
) {
2333 return (strstr(ap_id
, CFGA_DYN_SEP
));
2337 * removes the dynamic component
2340 remove_dyn(char *ap_id
)
2344 if (ap_id
== NULL
) {
2348 cp
= strstr(ap_id
, CFGA_DYN_SEP
);
2361 * sometimes NULL strings may be passed in (see DEF_COLS2). This
2370 (void) fprintf(stderr
,
2371 "%s \"%s\"\n", gettext("Cannot copy string"), str
);