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>
51 #include <config_admin.h>
54 #define S_FREE(x) (((x) != NULL) ? (free(x), (x) = NULL) : (void *)0)
55 #define GET_DYN(a) (strstr((a), CFGA_DYN_SEP))
57 * forward declarations
59 static char *basename(char *);
60 static void cfgadm_error(int, char *);
61 static int confirm_interactive(void *, const char *);
62 static int confirm_no(void *, const char *);
63 static int confirm_yes(void *, const char *);
64 static void usage(void);
65 static void usage_field(void);
66 static int extract_list_suboptions(char *, char **, char **, char **,
67 int *, char **, char **, char **);
68 static int message_output(void *appdata_ptr
, const char *message
);
69 static void *config_calloc_check(size_t, size_t);
70 static cfga_ap_types_t
find_arg_type(const char *);
71 static int yesno(char *, 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
= NULL
;
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;
687 appdata_ptr
= appdata_ptr
;
690 * First time through initialisation. In the original
691 * version of this command this function is only called once,
692 * but this function is generalized for the future.
695 (void) strncpy(yeschr
, nl_langinfo(YESSTR
), YESNO_STR_MAX
+ 1);
696 (void) strncpy(nochr
, nl_langinfo(NOSTR
), YESNO_STR_MAX
+ 1);
701 (void) fprintf(stderr
, "%s (%s/%s)? ", message
, yeschr
, nochr
);
702 isyes
= yesno(yeschr
, nochr
);
703 } while (isyes
== -1);
708 * If any text is input it must sub-string match either yes or no.
709 * Failure of this match is indicated by return of -1.
710 * If an empty line is input, this is taken as no.
718 char ans
[YESNO_STR_MAX
+ 1];
724 b
= getc(stdin
); /* more explicit that rm.c version */
725 if (b
== '\n' || b
== '\0' || b
== EOF
) {
726 if (i
< YESNO_STR_MAX
) /* bug fix to rm.c version */
730 if (i
< YESNO_STR_MAX
)
734 if (i
>= YESNO_STR_MAX
) {
736 ans
[YESNO_STR_MAX
] = 0;
738 /* changes to rm.c version follow */
741 if (strncmp(nop
, ans
, i
) == 0)
743 if (strncmp(yesp
, ans
, i
) == 0)
767 * Find base name of filename.
775 if ((sp
= strrchr(cp
, '/')) != NULL
)
786 (void) fprintf(stderr
, "%s", message
);
792 * extract_list_suboptions - process list option string
795 extract_list_suboptions(
809 while (*arg
!= '\0') {
810 static char need_value
[] =
811 "%s: sub-option \"%s\" requires a value\n";
812 static char no_value
[] =
813 "%s: sub-option \"%s\" does not take a value\n";
814 static char unk_subopt
[] =
815 "%s: sub-option \"%s\" unknown\n";
818 subopt
= getsubopt(&arg
, list_options
, &value
);
839 (void) fprintf(stderr
, gettext(need_value
),
840 cmdname
, list_options
[subopt
]);
845 case LIST_NOHEADINGS
:
847 (void) fprintf(stderr
, gettext(no_value
),
848 cmdname
, list_options
[subopt
]);
854 (void) fprintf(stderr
, gettext(unk_subopt
),
864 setup_prefilter(post_filter_t
*post_filtp
, char **prefilt_optpp
)
867 const char *clopt
= PREFILT_CLASS_STR
;
871 *prefilt_optpp
= NULL
;
873 /* Get the index for the "class" field */
874 for (idx
= 0; idx
< N_FIELDS
; idx
++) {
875 if (strcmp(all_fields
[idx
].name
, PREFILT_CLASS_STR
) == 0)
880 * Currently pre-filter available only for class fld w/ EXACT match
882 if (idx
>= N_FIELDS
||
883 post_filtp
->match_type_p
[idx
] != CFGA_MATCH_EXACT
) {
887 len
= strlen(clopt
) + strlen(post_filtp
->ldata
.ap_class
) + 1;
888 if ((*prefilt_optpp
= config_calloc_check(1, len
)) == NULL
) {
889 return (CFGA_LIB_ERROR
);
892 (void) strcpy(*prefilt_optpp
, clopt
);
893 (void) strcat(*prefilt_optpp
, post_filtp
->ldata
.ap_class
);
896 * Since it is being pre-filtered, this attribute does not need
899 post_filtp
->match_type_p
[idx
] = CFGA_MATCH_NOFILTER
;
900 if (all_fields
[idx
].set_filter
!= NULL
) {
901 (void) all_fields
[idx
].set_filter(&post_filtp
->ldata
, "");
911 post_filter_t
*post_filtp
,
912 match_type_t match_type
)
915 cfga_err_t ret
= CFGA_ERROR
;
917 for (fld
= 0; fld
< N_FIELDS
; fld
++) {
918 if (strcmp(attr
, all_fields
[fld
].name
) == 0)
922 /* Valid field or is the select option supported for this field */
923 if (fld
>= N_FIELDS
|| all_fields
[fld
].set_filter
== NULL
) {
924 return (CFGA_ATTR_INVAL
);
927 if ((ret
= all_fields
[fld
].set_filter(&post_filtp
->ldata
, val
))
929 post_filtp
->match_type_p
[fld
] = match_type
;
936 static char inval_optarg
[] =
937 "%s: invalid value \"%s\" for %s suboption.\n";
940 * Parses the "select" string and fills in the post_filter structure
945 post_filter_t
*post_filtp
,
946 match_type_t match_type
)
948 parse_state_t state
= CFGA_PSTATE_INIT
;
949 char *cp
= NULL
, *optstr
= NULL
, *attr
= NULL
, *val
= NULL
;
950 int bal
= 0; /* Tracks balancing */
955 if (selectp
== NULL
|| post_filtp
== NULL
) {
959 optstr
= config_calloc_check(1, strlen(selectp
) + 1);
960 if (optstr
== NULL
) {
961 return (CFGA_LIB_ERROR
);
964 (void) strcpy(optstr
, selectp
);
967 ret
= CFGA_ATTR_INVAL
;
970 state
= CFGA_PSTATE_INIT
;
972 for (; *cp
!= '\0'; cp
++) {
974 case CFGA_PSTATE_INIT
:
975 if (*cp
!= LEFT_PAREN
)
980 state
= CFGA_PSTATE_ATTR_DONE
;
982 case CFGA_PSTATE_ATTR_DONE
:
992 state
= CFGA_PSTATE_VAL_DONE
;
997 case CFGA_PSTATE_VAL_DONE
:
999 state
= CFGA_PSTATE_ERR
;
1004 if (set_attrval(attr
, val
, post_filtp
,
1005 match_type
) != CFGA_OK
) {
1006 state
= CFGA_PSTATE_ERR
;
1009 state
= CFGA_PSTATE_INIT
;
1013 state
= CFGA_PSTATE_ERR
;
1015 case CFGA_PSTATE_ERR
:
1022 if (state
== CFGA_PSTATE_VAL_DONE
) {
1023 ret
= set_attrval(attr
, val
, post_filtp
, match_type
);
1025 ret
= CFGA_ATTR_INVAL
;
1028 if (ret
!= CFGA_OK
) {
1029 (void) fprintf(stderr
, gettext(inval_optarg
), cmdname
,
1030 selectp
, list_options
[LIST_SELECT
]);
1041 const char *selectp
,
1043 post_filter_t
*post_filtp
,
1044 char **prefilt_optpp
)
1046 cfga_err_t ret
= CFGA_ERROR
;
1047 match_type_t match_type
= CFGA_MATCH_NOFILTER
;
1050 static char match_needs_select
[] =
1051 "%s: %s suboption can only be used with %s suboption.\n";
1054 *prefilt_optpp
= NULL
;
1057 * Initial: no filtering.
1058 * CFGA_MATCH_NOFILTER is NOT a valid user input
1060 for (i
= 0; i
< N_FIELDS
; i
++) {
1061 post_filtp
->match_type_p
[i
] = CFGA_MATCH_NOFILTER
;
1064 /* Determine type of match */
1065 if (matchp
== NULL
&& selectp
== NULL
) {
1068 } else if (matchp
== NULL
&& selectp
!= NULL
) {
1069 match_type
= CFGA_DEFAULT_MATCH
;
1070 } else if (matchp
!= NULL
&& selectp
== NULL
) {
1071 /* If only match specified, select criteria also needed */
1072 (void) fprintf(stderr
, gettext(match_needs_select
),
1073 cmdname
, list_options
[LIST_MATCH
],
1074 list_options
[LIST_SELECT
]);
1075 return (CFGA_ERROR
);
1077 for (i
= 0; i
< N_MATCH_TYPES
; i
++) {
1078 if (strcmp(matchp
, match_type_array
[i
].str
) == 0) {
1079 match_type
= match_type_array
[i
].type
;
1083 if (i
>= N_MATCH_TYPES
) {
1084 (void) fprintf(stderr
, gettext(inval_optarg
), cmdname
,
1085 matchp
, list_options
[LIST_MATCH
]);
1086 return (CFGA_ERROR
);
1090 if ((ret
= parse_select_opt(selectp
, post_filtp
, match_type
))
1095 /* Handle pre-filtering. */
1096 if ((ret
= setup_prefilter(post_filtp
, prefilt_optpp
)) != CFGA_OK
) {
1098 for (i
= 0; i
< N_FIELDS
; i
++) {
1099 post_filtp
->match_type_p
[i
] = CFGA_MATCH_NOFILTER
;
1109 * compare_ap_id - compare two ap_id's
1111 * For partial matches, argument order is significant. The filtering criterion
1112 * should be the first argument.
1117 cfga_list_data_t
*p1
,
1118 cfga_list_data_t
*p2
,
1119 match_type_t match_type
)
1122 switch (match_type
) {
1123 case CFGA_MATCH_NOFILTER
:
1124 return (0); /* No filtering. all pass */
1125 case CFGA_MATCH_PARTIAL
:
1126 return (strncmp(p1
->ap_log_id
, p2
->ap_log_id
,
1127 strlen(p1
->ap_log_id
)));
1128 case CFGA_MATCH_EXACT
:
1129 return (strcmp(p1
->ap_log_id
, p2
->ap_log_id
));
1130 case CFGA_MATCH_ORDER
:
1132 return (config_ap_id_cmp(p1
->ap_log_id
, p2
->ap_log_id
));
1137 * print_log_id - print logical ap_id
1141 cfga_list_data_t
*p
,
1145 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_log_id
),
1150 * set_log_flt - Setup filter for logical ap_id
1154 cfga_list_data_t
*p
,
1157 if (strlen(val
) > sizeof (p
->ap_log_id
) - 1)
1158 return (CFGA_ATTR_INVAL
);
1160 (void) strcpy(p
->ap_log_id
, val
);
1166 * set_type_flt - Setup filter for type field
1171 cfga_list_data_t
*p
,
1174 if (strlen(val
) > sizeof (p
->ap_type
) - 1)
1175 return (CFGA_ATTR_INVAL
);
1177 (void) strcpy(p
->ap_type
, val
);
1183 * set_class_flt - Setup filter for class field
1187 cfga_list_data_t
*p
,
1190 if (strlen(val
) > sizeof (p
->ap_class
) - 1)
1191 return (CFGA_ATTR_INVAL
);
1193 (void) strcpy(p
->ap_class
, val
);
1200 * compare_r_state - compare receptacle state of two ap_id's
1204 cfga_list_data_t
*p1
,
1205 cfga_list_data_t
*p2
,
1206 match_type_t match_type
)
1208 switch (match_type
) {
1209 case CFGA_MATCH_NOFILTER
: /* no filtering. pass all */
1211 case CFGA_MATCH_ORDER
:
1213 return (p1
->ap_r_state
- p2
->ap_r_state
);
1218 * compare_o_state - compare occupant state of two ap_id's
1222 cfga_list_data_t
*p1
,
1223 cfga_list_data_t
*p2
,
1224 match_type_t match_type
)
1226 switch (match_type
) {
1227 case CFGA_MATCH_NOFILTER
: /* no filtering. all pass */
1229 case CFGA_MATCH_ORDER
:
1231 return (p1
->ap_o_state
- p2
->ap_o_state
);
1236 * compare_busy - compare busy field of two ap_id's
1240 cfga_list_data_t
*p1
,
1241 cfga_list_data_t
*p2
,
1242 match_type_t match_type
)
1245 switch (match_type
) {
1246 case CFGA_MATCH_NOFILTER
: /* no filtering. all pass */
1248 case CFGA_MATCH_ORDER
:
1250 return (p1
->ap_busy
- p2
->ap_busy
);
1255 * print_r_state - print receptacle state
1259 cfga_list_data_t
*p
,
1265 switch (p
->ap_r_state
) {
1266 case CFGA_STAT_EMPTY
:
1269 case CFGA_STAT_CONNECTED
:
1272 case CFGA_STAT_DISCONNECTED
:
1273 cp
= "disconnected";
1279 (void) sprintf(lp
, "%-*s", width
, cp
);
1283 * print_o_state - print occupant state
1287 cfga_list_data_t
*p
,
1293 switch (p
->ap_o_state
) {
1294 case CFGA_STAT_UNCONFIGURED
:
1295 cp
= "unconfigured";
1297 case CFGA_STAT_CONFIGURED
:
1304 (void) sprintf(lp
, "%-*s", width
, cp
);
1308 * compare_cond - compare condition field of two ap_id's
1312 cfga_list_data_t
*p1
,
1313 cfga_list_data_t
*p2
,
1314 match_type_t match_type
)
1317 switch (match_type
) {
1318 case CFGA_MATCH_NOFILTER
:
1320 case CFGA_MATCH_ORDER
:
1322 return (p1
->ap_cond
- p2
->ap_cond
);
1327 * print_cond - print attachment point condition
1331 cfga_list_data_t
*p
,
1337 switch (p
->ap_cond
) {
1338 case CFGA_COND_UNKNOWN
:
1341 case CFGA_COND_UNUSABLE
:
1344 case CFGA_COND_FAILING
:
1347 case CFGA_COND_FAILED
:
1357 (void) sprintf(lp
, "%-*s", width
, cp
);
1361 * compare_time - compare time field of two ap_id's
1365 cfga_list_data_t
*p1
,
1366 cfga_list_data_t
*p2
,
1367 match_type_t match_type
)
1369 switch (match_type
) {
1370 case CFGA_MATCH_NOFILTER
:
1372 case CFGA_MATCH_ORDER
:
1374 return (p1
->ap_status_time
- p2
->ap_status_time
);
1380 * print_time - print time from cfga_list_data.
1381 * Time print based on ls(1).
1385 cfga_list_data_t
*p
,
1389 static time_t year
, now
;
1391 char time_buf
[50]; /* array to hold day and time */
1394 now
= time((long *)NULL
);
1395 year
= now
- 6L*30L*24L*60L*60L; /* 6 months ago */
1398 stime
= p
->ap_status_time
;
1399 if (stime
== (time_t)-1) {
1400 (void) sprintf(lp
, "%-*s", width
, gettext("unavailable"));
1404 if ((stime
< year
) || (stime
> now
)) {
1405 (void) strftime(time_buf
, sizeof (time_buf
),
1406 dcgettext(NULL
, FORMAT1
, LC_TIME
), localtime(&stime
));
1408 (void) strftime(time_buf
, sizeof (time_buf
),
1409 dcgettext(NULL
, FORMAT2
, LC_TIME
), localtime(&stime
));
1411 (void) sprintf(lp
, "%-*s", width
, time_buf
);
1415 * print_time_p - print time from cfga_list_data.
1419 cfga_list_data_t
*p
,
1424 char tstr
[TIME_P_WIDTH
+1];
1426 tp
= localtime(&p
->ap_status_time
);
1427 (void) sprintf(tstr
, "%04d%02d%02d%02d%02d%02d", tp
->tm_year
+ 1900,
1428 tp
->tm_mon
+ 1, tp
->tm_mday
, tp
->tm_hour
, tp
->tm_min
, tp
->tm_sec
);
1429 (void) sprintf(lp
, "%-*s", width
, tstr
);
1433 * compare_info - compare info from two cfga_list_data structs
1437 cfga_list_data_t
*p1
,
1438 cfga_list_data_t
*p2
,
1439 match_type_t match_type
)
1441 switch (match_type
) {
1442 case CFGA_MATCH_NOFILTER
:
1444 case CFGA_MATCH_ORDER
:
1446 return (strncmp(p1
->ap_info
, p2
->ap_info
,
1447 sizeof (p2
->ap_info
)));
1452 * print_info - print info from cfga_list_data struct
1456 cfga_list_data_t
*p
,
1460 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_info
), p
->ap_info
);
1464 * compare_type - compare type from two cfga_list_data structs
1466 * For partial matches, argument order is significant. The filtering criterion
1467 * should be the first argument.
1471 cfga_list_data_t
*p1
,
1472 cfga_list_data_t
*p2
,
1473 match_type_t match_type
)
1475 switch (match_type
) {
1476 case CFGA_MATCH_NOFILTER
:
1478 case CFGA_MATCH_PARTIAL
:
1479 return (strncmp(p1
->ap_type
, p2
->ap_type
, strlen(p1
->ap_type
)));
1480 case CFGA_MATCH_EXACT
:
1481 case CFGA_MATCH_ORDER
:
1483 return (strncmp(p1
->ap_type
, p2
->ap_type
,
1484 sizeof (p2
->ap_type
)));
1489 * print_type - print type from cfga_list_data struct
1493 cfga_list_data_t
*p
,
1497 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_type
), p
->ap_type
);
1502 * compare_class - compare class from two cfga_list_data structs
1504 * For partial matches, argument order is significant. The filtering criterion
1505 * should be the first argument.
1509 cfga_list_data_t
*p1
,
1510 cfga_list_data_t
*p2
,
1511 match_type_t match_type
)
1514 switch (match_type
) {
1515 case CFGA_MATCH_NOFILTER
:
1517 case CFGA_MATCH_PARTIAL
:
1518 return (strncmp(p1
->ap_class
, p2
->ap_class
,
1519 strlen(p1
->ap_class
)));
1520 case CFGA_MATCH_EXACT
:
1521 case CFGA_MATCH_ORDER
:
1523 return (strncmp(p1
->ap_class
, p2
->ap_class
,
1524 sizeof (p2
->ap_class
)));
1529 * print_class - print class from cfga_list_data struct
1533 cfga_list_data_t
*p
,
1537 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_class
), p
->ap_class
);
1540 * print_busy - print busy from cfga_list_data struct
1545 cfga_list_data_t
*p
,
1550 (void) sprintf(lp
, "%-*.*s", width
, width
, "y");
1552 (void) sprintf(lp
, "%-*.*s", width
, width
, "n");
1556 * print_phys_id - print physical ap_id
1560 cfga_list_data_t
*p
,
1564 (void) sprintf(lp
, "%-*.*s", width
, sizeof (p
->ap_phys_id
),
1570 * find_field - find the named field
1572 static struct field_info
*
1573 find_field(char *fname
)
1575 struct field_info
*fldp
;
1577 for (fldp
= all_fields
; fldp
< &all_fields
[N_FIELDS
]; fldp
++)
1578 if (strcmp(fname
, fldp
->name
) == 0)
1584 * usage_field - print field usage
1589 struct field_info
*fldp
= NULL
;
1591 static char field_list
[] = "%s: print or sort fields must be one of:";
1593 (void) fprintf(stderr
, gettext(field_list
), cmdname
);
1596 for (fldp
= all_fields
; fldp
< &all_fields
[N_FIELDS
]; fldp
++) {
1597 (void) fprintf(stderr
, "%s %s", sep
, fldp
->name
);
1600 (void) fprintf(stderr
, "\n");
1604 * compare_null - null comparison routine
1609 cfga_list_data_t
*p1
,
1610 cfga_list_data_t
*p2
,
1611 match_type_t match_type
)
1617 * print_null - print out a field of spaces
1622 cfga_list_data_t
*p
,
1626 (void) sprintf(lp
, "%-*s", width
, "");
1630 * do_config_list - directs the output of the listing functions
1636 cfga_list_data_t
*statlist
,
1643 post_filter_t
*post_filtp
,
1646 int nprcols
= 0, ncols2
= 0;
1647 struct print_col
*prnt_list
= NULL
;
1648 int napids_to_list
= 0;
1651 cfga_list_data_t
**sel_boards
= NULL
;
1656 ap_arg_t
*arg_array
= NULL
;
1657 ap_out_t
*out_array
= NULL
;
1663 nsort_list
= count_fields(sortp
, FDELIM
);
1664 if (nsort_list
!= 0) {
1665 sort_list
= config_calloc_check(nsort_list
,
1666 sizeof (*sort_list
));
1667 if (sort_list
== NULL
) {
1668 ret
= CFGA_LIB_ERROR
;
1671 f_err
|= process_sort_fields(nsort_list
, sort_list
, sortp
);
1675 nprcols
= count_fields(colsp
, FDELIM
);
1676 if ((ncols2
= count_fields(cols2p
, FDELIM
)) > nprcols
)
1679 prnt_list
= config_calloc_check(nprcols
, sizeof (*prnt_list
));
1680 if (prnt_list
== NULL
) {
1681 ret
= CFGA_LIB_ERROR
;
1684 f_err
|= process_fields(nprcols
, prnt_list
, 0, colsp
);
1686 f_err
|= process_fields(nprcols
, prnt_list
, 1, cols2p
);
1696 /* Create an array of all user args (if any) */
1702 for (i
= 0; i
< l_argc
; i
++) {
1703 napids_to_list
+= count_fields(l_argv
[i
], ARG_DELIM
);
1706 arg_array
= config_calloc_check(napids_to_list
,
1707 sizeof (*arg_array
));
1708 if (arg_array
== NULL
) {
1709 ret
= CFGA_LIB_ERROR
;
1713 for (i
= 0, j
= 0; i
< l_argc
; i
++) {
1716 n
= count_fields(l_argv
[i
], ARG_DELIM
);
1719 } else if (n
== 1) {
1720 arg_array
[j
].arg
= l_argv
[i
];
1721 arg_array
[j
].resp
= 0;
1728 arg_array
[j
].arg
= cp
;
1729 arg_array
[j
].resp
= 0;
1731 ncp
= strchr(cp
, ARG_DELIM
);
1739 assert(j
== napids_to_list
);
1747 out_array
= config_calloc_check(nlist
, sizeof (*out_array
));
1748 if (out_array
== NULL
) {
1749 ret
= CFGA_LIB_ERROR
;
1754 /* create a list of output stat data */
1755 for (i
= 0; i
< nlist
; i
++) {
1756 out_array
[i
].ldatap
= &statlist
[i
];
1757 out_array
[i
].req
= 0;
1761 * Mark all user input which got atleast 1 stat data in response
1763 for (i
= 0; i
< napids_to_list
; i
++) {
1764 arg_got_resp(&arg_array
[i
], out_array
, nlist
, dyn_exp
);
1768 * Process output data
1771 for (i
= 0; i
< nlist
; i
++) {
1773 * Mark all the stats which were actually requested by user
1775 out_was_req(&out_array
[i
], arg_array
, napids_to_list
, 0);
1776 if (out_array
[i
].req
== 0 && dyn_exp
) {
1778 * Try again without the dynamic component for the
1779 * if dynamic expansion was requested.
1781 out_was_req(&out_array
[i
], arg_array
,
1786 * post filter data which was actually requested
1788 if (out_array
[i
].req
== 1) {
1789 do_post_filter(&out_array
[i
], post_filtp
, &nsel
);
1793 sel_boards
= config_calloc_check(nsel
, sizeof (*sel_boards
));
1794 if (sel_boards
== NULL
) {
1795 ret
= CFGA_LIB_ERROR
;
1799 for (i
= 0, j
= 0; i
< nlist
; i
++) {
1800 if (out_array
[i
].req
== 1) {
1801 sel_boards
[j
] = out_array
[i
].ldatap
;
1809 * Print headings even if no list entries - Bug or feature ?
1811 if (!noheadings
&& prnt_list
!= NULL
) {
1812 if ((ret
= print_fields(nprcols
, prnt_list
, 1, 0,
1813 delimp
, NULL
, fp
)) != CFGA_OK
) {
1817 if ((ret
= print_fields(nprcols
, prnt_list
, 1,
1818 1, delimp
, NULL
, fp
)) != CFGA_OK
) {
1825 if (sort_list
!= NULL
&& nsel
> 1) {
1826 qsort(sel_boards
, nsel
, sizeof (sel_boards
[0]),
1830 if (prnt_list
!= NULL
) {
1831 for (i
= 0; i
< nsel
; i
++) {
1832 if ((ret
= print_fields(nprcols
,
1833 prnt_list
, 0, 0, delimp
, sel_boards
[i
], fp
))
1837 if ((ret
= print_fields(
1838 nprcols
, prnt_list
, 0, 1, delimp
,
1839 sel_boards
[i
], fp
)) != CFGA_OK
)
1846 * Go thru the argument list and notify user about args
1847 * which did not have a match
1849 report_no_response(arg_array
, napids_to_list
);
1865 * Mark all user inputs which got a response
1868 arg_got_resp(ap_arg_t
*inp
, ap_out_t
*out_array
, int nouts
, int dyn_exp
)
1871 cfga_ap_types_t type
;
1878 type
= find_arg_type(inp
->arg
);
1881 * Go through list of output stats and check if argument
1882 * produced that output
1884 for (i
= 0; i
< nouts
; i
++) {
1885 if (type
== PHYSICAL_AP_ID
) {
1886 if (config_ap_id_cmp(out_array
[i
].ldatap
->ap_phys_id
,
1890 } else if (type
== LOGICAL_AP_ID
) {
1891 if (config_ap_id_cmp(out_array
[i
].ldatap
->ap_log_id
,
1895 } else if (type
== AP_TYPE
) {
1897 * An AP_TYPE argument cannot generate dynamic
1898 * attachment point stats unless dynamic expansion was
1899 * requested by user.
1901 if (!dyn_exp
&& get_dyn(out_array
[i
].ldatap
->ap_log_id
)
1906 if (strncmp(out_array
[i
].ldatap
->ap_log_id
, inp
->arg
,
1907 strlen(inp
->arg
)) == 0) {
1920 /* Mark all stat data which were requested by user */
1922 out_was_req(ap_out_t
*outp
, ap_arg_t
*in_array
, int nargs
, int no_dyn
)
1925 cfga_ap_types_t type
= UNKNOWN_AP
;
1926 char physid
[MAXPATHLEN
], logid
[MAXPATHLEN
];
1929 /* If no user args, all output is acceptable */
1936 (void) snprintf(physid
, sizeof (physid
), "%s",
1937 outp
->ldatap
->ap_phys_id
);
1938 (void) snprintf(logid
, sizeof (logid
), "%s", outp
->ldatap
->ap_log_id
);
1941 * Do comparison with or without dynamic component as requested by
1945 /* Remove the dynamic component */
1950 for (i
= 0; i
< nargs
; i
++) {
1951 type
= find_arg_type(in_array
[i
].arg
);
1952 if (type
== PHYSICAL_AP_ID
) {
1954 if (config_ap_id_cmp(in_array
[i
].arg
, physid
) == 0) {
1957 } else if (type
== LOGICAL_AP_ID
) {
1959 if (config_ap_id_cmp(in_array
[i
].arg
, logid
) == 0) {
1962 } else if (type
== AP_TYPE
) {
1964 * Aptypes cannot generate dynamic attachment
1965 * points unless dynamic expansion is specified.
1966 * in which case this routine would be called a
1967 * 2nd time with the no_dyn flag set and there
1968 * would be no dynamic ap_ids.
1970 if (get_dyn(logid
) != NULL
) {
1974 if (strncmp(in_array
[i
].arg
, logid
,
1975 strlen(in_array
[i
].arg
)) == 0) {
1984 /* Ok, this output was requested */
1991 do_post_filter(ap_out_t
*outp
, post_filter_t
*post_filtp
, int *nselp
)
1995 if (outp
->req
!= 1) {
2000 * For fields without filtering (CFGA_MATCH_NOFILTER),
2001 * compare always returns 0 (success)
2003 for (i
= 0; i
< N_FIELDS
; i
++) {
2005 * Note: Order is important for partial match (via strncmp).
2006 * The first argument for compare must be the filter.
2008 if (all_fields
[i
].compare(&post_filtp
->ldata
, outp
->ldatap
,
2009 post_filtp
->match_type_p
[i
])) {
2010 outp
->req
= 0; /* Blocked by filter */
2016 * Passed through filter
2022 report_no_response(ap_arg_t
*arg_array
, int nargs
)
2032 * nop if no user arguments
2034 for (i
= 0; i
< nargs
; i
++) {
2035 if (arg_array
[i
].resp
== 0) {
2036 (void) fprintf(stderr
,
2037 gettext("%s: No matching library found\n"),
2044 * ldata_compare - compare two attachment point list data structures.
2053 cfga_list_data_t
*b1
, *b2
;
2056 b1
= *(cfga_list_data_t
**)vb1
;
2057 b2
= *(cfga_list_data_t
**)vb2
;
2059 for (i
= 0; i
< nsort_list
; i
++) {
2060 res
= (*(sort_list
[i
].fld
->compare
))(b1
, b2
, CFGA_MATCH_ORDER
);
2062 if (sort_list
[i
].reverse
)
2072 * count_fields - Count the number of fields, using supplied delimiter.
2075 count_fields(char *fspec
, char delim
)
2080 if (fspec
== 0 || *fspec
== '\0')
2083 for (cp
= fspec
; *cp
!= '\0'; cp
++)
2091 * This function is not a re-implementation of strtok().
2092 * There can be null fields - strtok() eats spans of delimiters.
2095 get_field(char **fspp
)
2097 char *cp
= NULL
, *fld
;
2101 if (fld
!= NULL
&& *fld
== '\0')
2105 cp
= strchr(*fspp
, FDELIM
);
2124 struct print_col
*list
,
2128 struct print_col
*pp
= NULL
;
2129 struct field_info
*fldp
= NULL
;
2136 for (pp
= list
; pp
< &list
[ncol
]; pp
++) {
2137 fldn
= get_field(&fmtx
);
2140 struct field_info
*tfldp
;
2142 tfldp
= find_field(fldn
);
2143 if (tfldp
!= NULL
) {
2146 (void) fprintf(stderr
, gettext(unk_field
),
2153 if (fldp
->width
> pp
->width
)
2154 pp
->width
= fldp
->width
;
2157 pp
->width
= fldp
->width
;
2164 * process_sort_fields -
2167 process_sort_fields(
2169 struct sort_el
*list
,
2174 struct field_info
*fldp
= NULL
;
2181 for (i
= 0; i
< nsort
; i
++) {
2182 fldn
= get_field(&fmtx
);
2186 struct field_info
*tfldp
= NULL
;
2192 tfldp
= find_field(fldn
);
2193 if (tfldp
!= NULL
) {
2196 (void) fprintf(stderr
, gettext(unk_field
),
2201 list
[i
].reverse
= rev
;
2213 struct print_col
*list
,
2217 cfga_list_data_t
*bdp
,
2221 struct print_col
*pp
= NULL
;
2222 struct field_info
*fldp
= NULL
;
2223 static char *outline
, *end
;
2226 if (outline
== NULL
) {
2227 int out_len
, delim_len
;
2229 delim_len
= strlen(delim
);
2231 for (pp
= list
; pp
< &list
[ncol
]; pp
++) {
2232 out_len
+= pp
->width
;
2233 out_len
+= delim_len
;
2235 out_len
-= delim_len
;
2236 outline
= config_calloc_check(out_len
+ 1, 1);
2237 if (outline
== NULL
) {
2238 return (CFGA_LIB_ERROR
);
2240 end
= &outline
[out_len
+ 1];
2245 for (pp
= list
; pp
< &list
[ncol
]; pp
++) {
2246 fldp
= line2
? pp
->line2
: pp
->line1
;
2247 (void) snprintf(lp
, end
- lp
, "%s", del
);
2250 (void) snprintf(lp
, end
- lp
, "%-*s",
2251 fldp
->width
, fldp
->heading
);
2253 (*fldp
->printfn
)(bdp
, fldp
->width
, lp
);
2260 * Trim trailing spaces
2262 while (--lp
>= outline
&& *lp
== ' ')
2264 (void) fprintf(fp
, "%s\n", outline
);
2269 * config_calloc_check - perform allocation, check result and
2270 * set error indicator
2273 config_calloc_check(
2278 static char alloc_fail
[] =
2279 "%s: memory allocation failed (%d*%d bytes)\n";
2282 p
= calloc(nelem
, elsize
);
2284 (void) fprintf(stderr
, gettext(alloc_fail
), cmdname
,
2291 * find_arg_type - determine if an argument is an ap_id or an ap_type.
2293 static cfga_ap_types_t
2294 find_arg_type(const char *ap_id
)
2297 cfga_ap_types_t type
;
2298 char *mkr
= NULL
, *cp
;
2299 int size_ap
= 0, size_mkr
= 0, digit
= 0, i
= 0;
2300 char path
[MAXPATHLEN
];
2301 char apbuf
[MAXPATHLEN
];
2308 if (ap_id
== NULL
|| *ap_id
== '\0') {
2309 return (UNKNOWN_AP
);
2313 * Mask the dynamic component if any
2315 if ((cp
= GET_DYN(ap_id
)) != NULL
) {
2318 len
= strlen(ap_id
);
2321 if (len
>= sizeof (apbuf
)) {
2322 return (UNKNOWN_AP
);
2325 (void) strncpy(apbuf
, ap_id
, len
);
2329 * If it starts with a slash and is stat-able
2332 if (*apbuf
== '/' && stat(apbuf
, &sbuf
) == 0) {
2333 return (PHYSICAL_AP_ID
);
2337 * Is this a symlink in CFGA_DEV_DIR ?
2339 (void) snprintf(path
, sizeof (path
), "%s/%s", CFGA_DEV_DIR
, apbuf
);
2341 if (lstat(path
, &sbuf
) == 0 && S_ISLNK(sbuf
.st_mode
) &&
2342 stat(path
, &sbuf
) == 0) {
2343 return (LOGICAL_AP_ID
);
2347 * Check for ":" which is always present in an ap_id but not maybe
2348 * present or absent in an ap_type.
2349 * We need to check that the characters right before the : are digits
2350 * since an ap_id is of the form <name><instance>:<specific ap name>
2352 if ((mkr
= strchr(apbuf
, ':')) == NULL
) {
2355 size_ap
= strlen(apbuf
);
2356 size_mkr
= strlen(mkr
);
2360 for (i
= size_ap
- size_mkr
- 1; i
> 0; i
--) {
2361 if ((int)isdigit(mkr
[i
])) {
2369 type
= LOGICAL_AP_ID
;
2378 get_dyn(const char *ap_id
)
2380 if (ap_id
== NULL
) {
2384 return (strstr(ap_id
, CFGA_DYN_SEP
));
2388 * removes the dynamic component
2391 remove_dyn(char *ap_id
)
2395 if (ap_id
== NULL
) {
2399 cp
= strstr(ap_id
, CFGA_DYN_SEP
);
2412 * sometimes NULL strings may be passed in (see DEF_COLS2). This
2421 (void) fprintf(stderr
,
2422 "%s \"%s\"\n", gettext("Cannot copy string"), str
);