17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*af6a7a2cSkd * Common Development and Distribution License (the "License"). 6*af6a7a2cSkd * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*af6a7a2cSkd * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <ctype.h> 297c478bd9Sstevel@tonic-gate #include <stdio.h> 307c478bd9Sstevel@tonic-gate #include <stdlib.h> 317c478bd9Sstevel@tonic-gate #include <stdarg.h> 327c478bd9Sstevel@tonic-gate #include <string.h> 337c478bd9Sstevel@tonic-gate #include <unistd.h> 347c478bd9Sstevel@tonic-gate #include <macros.h> 357c478bd9Sstevel@tonic-gate #include <errno.h> 367c478bd9Sstevel@tonic-gate #include <locale.h> 377c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 387c478bd9Sstevel@tonic-gate #include <librcm.h> 397c478bd9Sstevel@tonic-gate #define CFGA_PLUGIN_LIB 407c478bd9Sstevel@tonic-gate #include <config_admin.h> 417c478bd9Sstevel@tonic-gate #include "ap.h" 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #ifdef SBD_DEBUG 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate static FILE *debug_fp; 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate int 487c478bd9Sstevel@tonic-gate debugging(void) 497c478bd9Sstevel@tonic-gate { 507c478bd9Sstevel@tonic-gate char *ep; 517c478bd9Sstevel@tonic-gate static int inited; 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate if (inited) 547c478bd9Sstevel@tonic-gate return (debug_fp != NULL); 557c478bd9Sstevel@tonic-gate inited = 1; 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate if ((ep = getenv("SBD_DEBUG")) == NULL) 587c478bd9Sstevel@tonic-gate return (0); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate if (*ep == '\0') 617c478bd9Sstevel@tonic-gate debug_fp = stderr; 627c478bd9Sstevel@tonic-gate else { 637c478bd9Sstevel@tonic-gate if ((debug_fp = fopen(ep, "a")) == NULL) 647c478bd9Sstevel@tonic-gate return (0); 657c478bd9Sstevel@tonic-gate } 667c478bd9Sstevel@tonic-gate (void) fprintf(debug_fp, 677c478bd9Sstevel@tonic-gate "\nDebug started, pid=%d\n", (int)getpid()); 687c478bd9Sstevel@tonic-gate return (1); 697c478bd9Sstevel@tonic-gate } 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 727c478bd9Sstevel@tonic-gate void 737c478bd9Sstevel@tonic-gate dbg(char *fmt, ...) 747c478bd9Sstevel@tonic-gate { 757c478bd9Sstevel@tonic-gate va_list ap; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate if (!debugging()) 787c478bd9Sstevel@tonic-gate return; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate va_start(ap, fmt); 817c478bd9Sstevel@tonic-gate (void) vfprintf(debug_fp, fmt, ap); 827c478bd9Sstevel@tonic-gate va_end(ap); 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate #endif 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate static char * 877c478bd9Sstevel@tonic-gate ap_err_fmts[] = { 887c478bd9Sstevel@tonic-gate "command invalid: %s", 897c478bd9Sstevel@tonic-gate "%s %s: %s%s%s", /* command failed */ 907c478bd9Sstevel@tonic-gate "%s %s", /* command nacked */ 917c478bd9Sstevel@tonic-gate "command not supported: %s %s", 927c478bd9Sstevel@tonic-gate "command aborted: %s %s", 937c478bd9Sstevel@tonic-gate "option invalid: %s", 947c478bd9Sstevel@tonic-gate "option requires value: %s", 957c478bd9Sstevel@tonic-gate "option requires no value: %s", 967c478bd9Sstevel@tonic-gate "option value invalid: %s %s", 977c478bd9Sstevel@tonic-gate "attachment point invalid: %s", 987c478bd9Sstevel@tonic-gate "component invalid: %s", 997c478bd9Sstevel@tonic-gate "sequence invalid: %s (%s %s) %s", 1007c478bd9Sstevel@tonic-gate "change signal disposition failed", 1017c478bd9Sstevel@tonic-gate "cannot get RCM handle", 1027c478bd9Sstevel@tonic-gate "RCM %s failed for %s", 1037c478bd9Sstevel@tonic-gate "\n%-30s %-10s %s", 1047c478bd9Sstevel@tonic-gate "cannot open %s%s%s", 1057c478bd9Sstevel@tonic-gate "cannot find symbol %s in %s", 1067c478bd9Sstevel@tonic-gate "cannot stat %s: %s", 1077c478bd9Sstevel@tonic-gate "not enough memory", 1087c478bd9Sstevel@tonic-gate "%s plugin: %s", 1097c478bd9Sstevel@tonic-gate "unknown error", 1107c478bd9Sstevel@tonic-gate NULL 1117c478bd9Sstevel@tonic-gate }; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate #define ap_err_fmt(i) ap_err_fmts[min((i), ERR_NONE)] 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate static char * 1167c478bd9Sstevel@tonic-gate ap_msg_fmts[] = { 1177c478bd9Sstevel@tonic-gate "%s %s\n", 1187c478bd9Sstevel@tonic-gate "%s %s skipped\n", 1197c478bd9Sstevel@tonic-gate "System may be temporarily suspended, proceed", 1207c478bd9Sstevel@tonic-gate "%s %s aborted\n", 1217c478bd9Sstevel@tonic-gate "%s %s done\n", 1227c478bd9Sstevel@tonic-gate "%s %s failed\n", 1237c478bd9Sstevel@tonic-gate "RCM library not found, feature will be disabled\n", 1247c478bd9Sstevel@tonic-gate "Unknown message\n", 1257c478bd9Sstevel@tonic-gate NULL 1267c478bd9Sstevel@tonic-gate }; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate #define ap_msg_fmt(i) ap_msg_fmts[min((i), MSG_NONE)] 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate #define STR_BD "board" 1317c478bd9Sstevel@tonic-gate #define STR_SEP ": " 1327c478bd9Sstevel@tonic-gate #define STR_NULL "NULL" 1337c478bd9Sstevel@tonic-gate #define STR_CMD_UNKNOWN "unknown command" 1347c478bd9Sstevel@tonic-gate #define STR_ERR_UNKNOWN "unknown error" 1357c478bd9Sstevel@tonic-gate #define STR_MSG_UNKNOWN "unknown message\n" 1367c478bd9Sstevel@tonic-gate #define STR_TGT_UNKNOWN "unknown target" 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate #define get_cmd(c, ap, v) \ 1397c478bd9Sstevel@tonic-gate { \ 1407c478bd9Sstevel@tonic-gate (v) = va_arg((ap), int); \ 1417c478bd9Sstevel@tonic-gate if (((c) = ap_cmd_name((v))) == NULL) \ 1427c478bd9Sstevel@tonic-gate (c) = STR_CMD_UNKNOWN; \ 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate #define get_tgt(t, ap) {\ 1457c478bd9Sstevel@tonic-gate (t) = va_arg((ap), char *); \ 1467c478bd9Sstevel@tonic-gate if (!str_valid((t))) \ 1477c478bd9Sstevel@tonic-gate (t) = STR_TGT_UNKNOWN; \ 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate #define check_tgt(tgt, t) {\ 1507c478bd9Sstevel@tonic-gate if (str_valid((tgt))) \ 1517c478bd9Sstevel@tonic-gate (t) = (tgt); \ 1527c478bd9Sstevel@tonic-gate else \ 1537c478bd9Sstevel@tonic-gate (t) = STR_TGT_UNKNOWN; \ 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate #define get_str(v, ap, d) \ 1567c478bd9Sstevel@tonic-gate { \ 1577c478bd9Sstevel@tonic-gate (v) = va_arg((ap), char *); \ 1587c478bd9Sstevel@tonic-gate if ((v) == NULL) \ 1597c478bd9Sstevel@tonic-gate (v) = (d); \ 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate static char * 1637c478bd9Sstevel@tonic-gate ap_stnames[] = { 1647c478bd9Sstevel@tonic-gate "unknown state", 1657c478bd9Sstevel@tonic-gate "empty", 1667c478bd9Sstevel@tonic-gate "disconnected", 1677c478bd9Sstevel@tonic-gate "connected", 1687c478bd9Sstevel@tonic-gate "unconfigured", 1697c478bd9Sstevel@tonic-gate "configured" 1707c478bd9Sstevel@tonic-gate }; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* 1737c478bd9Sstevel@tonic-gate * ap_err() accepts a variable number of message IDs and constructs 1747c478bd9Sstevel@tonic-gate * a corresponding error string. ap_err() calls dgettext() to 1757c478bd9Sstevel@tonic-gate * internationalize the proper portions of a message. If a system 1767c478bd9Sstevel@tonic-gate * error was encountered (errno set), ap_err() looks for the error 1777c478bd9Sstevel@tonic-gate * string corresponding to the returned error code if one is available. 1787c478bd9Sstevel@tonic-gate * If not, the standard libc error string is fetched. 1797c478bd9Sstevel@tonic-gate */ 1807c478bd9Sstevel@tonic-gate void 1817c478bd9Sstevel@tonic-gate ap_err(apd_t *a, ...) 1827c478bd9Sstevel@tonic-gate { 1837c478bd9Sstevel@tonic-gate int v; 1847c478bd9Sstevel@tonic-gate int err; 1857c478bd9Sstevel@tonic-gate int len; 1867c478bd9Sstevel@tonic-gate char *p; 1877c478bd9Sstevel@tonic-gate char *sep; 1887c478bd9Sstevel@tonic-gate char *rsep; 1897c478bd9Sstevel@tonic-gate const char *fmt; 1907c478bd9Sstevel@tonic-gate char *cmd; 1917c478bd9Sstevel@tonic-gate char *value; 1927c478bd9Sstevel@tonic-gate char *target; 1937c478bd9Sstevel@tonic-gate char *serr; 1947c478bd9Sstevel@tonic-gate char *syserr; 1957c478bd9Sstevel@tonic-gate char *rstate; 1967c478bd9Sstevel@tonic-gate char *ostate; 1977c478bd9Sstevel@tonic-gate char *srsrc; 1987c478bd9Sstevel@tonic-gate char *sysrsrc; 1997c478bd9Sstevel@tonic-gate char *option; 2007c478bd9Sstevel@tonic-gate char *path; 2017c478bd9Sstevel@tonic-gate char *sym; 2027c478bd9Sstevel@tonic-gate char *msg; 2037c478bd9Sstevel@tonic-gate const char *error; 2047c478bd9Sstevel@tonic-gate char **errstring; 2057c478bd9Sstevel@tonic-gate char *rinfostr = NULL; 2067c478bd9Sstevel@tonic-gate va_list ap; 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate DBG("ap_err(%p)\n", (void *)a); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate /* 2117c478bd9Sstevel@tonic-gate * If there is no descriptor or string pointer or if 2127c478bd9Sstevel@tonic-gate * there is an outstanding error, just return. 2137c478bd9Sstevel@tonic-gate */ 2147c478bd9Sstevel@tonic-gate if (a == NULL || (errstring = a->errstring) == NULL || 2157c478bd9Sstevel@tonic-gate *errstring != NULL) 2167c478bd9Sstevel@tonic-gate return; 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate va_start(ap, a); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate err = va_arg(ap, int); 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate if ((fmt = ap_err_fmt(err)) == NULL) 2237c478bd9Sstevel@tonic-gate fmt = STR_ERR_UNKNOWN; 2247c478bd9Sstevel@tonic-gate fmt = dgettext(TEXT_DOMAIN, fmt); 2257c478bd9Sstevel@tonic-gate len = strlen(fmt); 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate sep = ""; 2287c478bd9Sstevel@tonic-gate serr = NULL; 2297c478bd9Sstevel@tonic-gate srsrc = NULL; 2307c478bd9Sstevel@tonic-gate error = NULL; 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate /* 2337c478bd9Sstevel@tonic-gate * Get the proper arguments for the error. 2347c478bd9Sstevel@tonic-gate */ 2357c478bd9Sstevel@tonic-gate switch (err) { 2367c478bd9Sstevel@tonic-gate case ERR_CMD_ABORT: 2377c478bd9Sstevel@tonic-gate case ERR_CMD_FAIL: 2387c478bd9Sstevel@tonic-gate case ERR_CMD_NACK: 2397c478bd9Sstevel@tonic-gate get_cmd(cmd, ap, v); 2407c478bd9Sstevel@tonic-gate check_tgt(a->target, target); 2417c478bd9Sstevel@tonic-gate len += strlen(cmd) + strlen(target); 2427c478bd9Sstevel@tonic-gate DBG("<%s><%s>", cmd, target); 2437c478bd9Sstevel@tonic-gate break; 2447c478bd9Sstevel@tonic-gate case ERR_CMD_NOTSUPP: 2457c478bd9Sstevel@tonic-gate get_cmd(cmd, ap, v); 2467c478bd9Sstevel@tonic-gate if (a->tgt == AP_BOARD) 2477c478bd9Sstevel@tonic-gate target = STR_BD; 2487c478bd9Sstevel@tonic-gate else 2497c478bd9Sstevel@tonic-gate check_tgt(a->cname, target); 2507c478bd9Sstevel@tonic-gate len += strlen(cmd) + strlen(target); 2517c478bd9Sstevel@tonic-gate DBG("<%s><%s>", cmd, target); 2527c478bd9Sstevel@tonic-gate break; 2537c478bd9Sstevel@tonic-gate case ERR_AP_INVAL: 2547c478bd9Sstevel@tonic-gate check_tgt((char *)a->apid, target); 2557c478bd9Sstevel@tonic-gate len += strlen(target); 2567c478bd9Sstevel@tonic-gate DBG("<%s>", target); 2577c478bd9Sstevel@tonic-gate break; 2587c478bd9Sstevel@tonic-gate case ERR_CMD_INVAL: 2597c478bd9Sstevel@tonic-gate case ERR_CM_INVAL: 2607c478bd9Sstevel@tonic-gate case ERR_OPT_INVAL: 2617c478bd9Sstevel@tonic-gate case ERR_OPT_NOVAL: 2627c478bd9Sstevel@tonic-gate case ERR_OPT_VAL: 2637c478bd9Sstevel@tonic-gate case ERR_OPT_BADVAL: 2647c478bd9Sstevel@tonic-gate get_str(option, ap, STR_NULL); 2657c478bd9Sstevel@tonic-gate len += strlen(option); 2667c478bd9Sstevel@tonic-gate DBG("<%s>", option); 2677c478bd9Sstevel@tonic-gate if (err != ERR_OPT_BADVAL) 2687c478bd9Sstevel@tonic-gate break; 2697c478bd9Sstevel@tonic-gate get_str(value, ap, STR_NULL); 2707c478bd9Sstevel@tonic-gate len += strlen(value); 2717c478bd9Sstevel@tonic-gate DBG("<%s>", value); 2727c478bd9Sstevel@tonic-gate break; 2737c478bd9Sstevel@tonic-gate case ERR_TRANS_INVAL: { 2747c478bd9Sstevel@tonic-gate cfga_stat_t rs, os; 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate get_cmd(cmd, ap, v); 2777c478bd9Sstevel@tonic-gate check_tgt(a->target, target); 2787c478bd9Sstevel@tonic-gate len += strlen(cmd) + strlen(target); 2797c478bd9Sstevel@tonic-gate ap_state(a, &rs, &os); 2807c478bd9Sstevel@tonic-gate rstate = ap_stnames[rs]; 2817c478bd9Sstevel@tonic-gate ostate = ap_stnames[os]; 2827c478bd9Sstevel@tonic-gate len += strlen(rstate) + strlen(ostate); 2837c478bd9Sstevel@tonic-gate DBG("<%s><%s><%s><%s>", cmd, target, rstate, ostate); 2847c478bd9Sstevel@tonic-gate break; 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate case ERR_RCM_CMD: { 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate get_cmd(cmd, ap, v); 2897c478bd9Sstevel@tonic-gate check_tgt(a->target, target); 2907c478bd9Sstevel@tonic-gate len += strlen(cmd) + strlen(target); 2917c478bd9Sstevel@tonic-gate DBG("<%s><%s>", cmd, target); 2927c478bd9Sstevel@tonic-gate 293*af6a7a2cSkd if ((ap_rcm_info(a, &rinfostr) == 0) && (rinfostr != NULL)) { 2947c478bd9Sstevel@tonic-gate len += strlen(rinfostr); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate break; 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate case ERR_LIB_OPEN: 3007c478bd9Sstevel@tonic-gate get_str(path, ap, STR_NULL); 3017c478bd9Sstevel@tonic-gate get_str(error, ap, ""); 3027c478bd9Sstevel@tonic-gate if (str_valid(error)) 3037c478bd9Sstevel@tonic-gate sep = STR_SEP; 3047c478bd9Sstevel@tonic-gate DBG("<%s><%s>", path, error); 3057c478bd9Sstevel@tonic-gate break; 3067c478bd9Sstevel@tonic-gate case ERR_LIB_SYM: 3077c478bd9Sstevel@tonic-gate get_str(path, ap, STR_NULL); 3087c478bd9Sstevel@tonic-gate get_str(sym, ap, STR_NULL); 3097c478bd9Sstevel@tonic-gate DBG("<%s><%s>", path, sym); 3107c478bd9Sstevel@tonic-gate break; 3117c478bd9Sstevel@tonic-gate case ERR_STAT: 3127c478bd9Sstevel@tonic-gate get_str(path, ap, STR_NULL); 3137c478bd9Sstevel@tonic-gate break; 3147c478bd9Sstevel@tonic-gate case ERR_PLUGIN: 3157c478bd9Sstevel@tonic-gate get_str(msg, ap, STR_NULL); 3167c478bd9Sstevel@tonic-gate break; 3177c478bd9Sstevel@tonic-gate default: 3187c478bd9Sstevel@tonic-gate DBG("<NOARGS>"); 3197c478bd9Sstevel@tonic-gate break; 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate va_end(ap); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate /* 3257c478bd9Sstevel@tonic-gate * In case of a system error, get the reason for 3267c478bd9Sstevel@tonic-gate * the failure as well as the resource if availbale. 3277c478bd9Sstevel@tonic-gate * If we already got some error info (e.g. from RCM) 3287c478bd9Sstevel@tonic-gate * don't bother looking. 3297c478bd9Sstevel@tonic-gate */ 3307c478bd9Sstevel@tonic-gate if (!str_valid(error) && errno) { 3317c478bd9Sstevel@tonic-gate sep = STR_SEP; 3327c478bd9Sstevel@tonic-gate sysrsrc = NULL; 3337c478bd9Sstevel@tonic-gate if ((syserr = ap_sys_err(a, &sysrsrc)) == NULL) 3347c478bd9Sstevel@tonic-gate syserr = STR_ERR_UNKNOWN; 3357c478bd9Sstevel@tonic-gate else 3367c478bd9Sstevel@tonic-gate serr = syserr; 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate syserr = dgettext(TEXT_DOMAIN, syserr); 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate if (sysrsrc == NULL) 3417c478bd9Sstevel@tonic-gate sysrsrc = ""; 3427c478bd9Sstevel@tonic-gate else 3437c478bd9Sstevel@tonic-gate srsrc = sysrsrc; 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate len += strlen(syserr) + strlen(sysrsrc); 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate if (str_valid(sysrsrc)) { 3487c478bd9Sstevel@tonic-gate rsep = STR_SEP; 3497c478bd9Sstevel@tonic-gate len += strlen(rsep); 3507c478bd9Sstevel@tonic-gate } else 3517c478bd9Sstevel@tonic-gate rsep = ""; 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate DBG("<%s><%s><%s>", syserr, rsep, sysrsrc); 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate } else 3567c478bd9Sstevel@tonic-gate syserr = rsep = sysrsrc = ""; 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate DBG("\n"); 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if ((p = (char *)calloc(len, 1)) != NULL) 3617c478bd9Sstevel@tonic-gate *errstring = p; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate * Print the string with appropriate arguments. 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate switch (err) { 3677c478bd9Sstevel@tonic-gate case ERR_CMD_FAIL: 3687c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt, cmd, target, 3697c478bd9Sstevel@tonic-gate syserr, rsep, sysrsrc); 3707c478bd9Sstevel@tonic-gate break; 3717c478bd9Sstevel@tonic-gate case ERR_CMD_ABORT: 3727c478bd9Sstevel@tonic-gate case ERR_CMD_NACK: 3737c478bd9Sstevel@tonic-gate case ERR_CMD_NOTSUPP: 3747c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt, cmd, target); 3757c478bd9Sstevel@tonic-gate break; 3767c478bd9Sstevel@tonic-gate case ERR_AP_INVAL: 3777c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt, target); 3787c478bd9Sstevel@tonic-gate break; 3797c478bd9Sstevel@tonic-gate case ERR_CMD_INVAL: 3807c478bd9Sstevel@tonic-gate case ERR_CM_INVAL: 3817c478bd9Sstevel@tonic-gate case ERR_OPT_INVAL: 3827c478bd9Sstevel@tonic-gate case ERR_OPT_NOVAL: 3837c478bd9Sstevel@tonic-gate case ERR_OPT_VAL: 3847c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt, option); 3857c478bd9Sstevel@tonic-gate break; 3867c478bd9Sstevel@tonic-gate case ERR_OPT_BADVAL: 3877c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt, option, value); 3887c478bd9Sstevel@tonic-gate break; 3897c478bd9Sstevel@tonic-gate case ERR_TRANS_INVAL: 3907c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt, cmd, rstate, ostate, target); 3917c478bd9Sstevel@tonic-gate break; 3927c478bd9Sstevel@tonic-gate case ERR_SIG_CHANGE: 3937c478bd9Sstevel@tonic-gate case ERR_RCM_HANDLE: 3947c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt); 3957c478bd9Sstevel@tonic-gate break; 3967c478bd9Sstevel@tonic-gate case ERR_RCM_CMD: 3977c478bd9Sstevel@tonic-gate /* 3987c478bd9Sstevel@tonic-gate * If the rinfostr has a string, then the librcm has returned 3997c478bd9Sstevel@tonic-gate * us a text field of its reasons why the command failed. 4007c478bd9Sstevel@tonic-gate * 4017c478bd9Sstevel@tonic-gate * If the rinfostr is not returning data, we will use 4027c478bd9Sstevel@tonic-gate * the standard ap_err_fmts[] for the rcm error. 4037c478bd9Sstevel@tonic-gate */ 4047c478bd9Sstevel@tonic-gate if (rinfostr != NULL) 4057c478bd9Sstevel@tonic-gate (void) snprintf(p, len, "%s", rinfostr); 4067c478bd9Sstevel@tonic-gate else 4077c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt, cmd, target); 4087c478bd9Sstevel@tonic-gate break; 4097c478bd9Sstevel@tonic-gate case ERR_LIB_OPEN: 4107c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt, path, sep, error); 4117c478bd9Sstevel@tonic-gate break; 4127c478bd9Sstevel@tonic-gate case ERR_LIB_SYM: 4137c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt, sym, path); 4147c478bd9Sstevel@tonic-gate break; 4157c478bd9Sstevel@tonic-gate case ERR_STAT: 4167c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt, path, syserr); 4177c478bd9Sstevel@tonic-gate break; 4187c478bd9Sstevel@tonic-gate case ERR_NOMEM: 4197c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt); 4207c478bd9Sstevel@tonic-gate break; 4217c478bd9Sstevel@tonic-gate case ERR_PLUGIN: 4227c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt, a->class, msg); 4237c478bd9Sstevel@tonic-gate break; 4247c478bd9Sstevel@tonic-gate default: 4257c478bd9Sstevel@tonic-gate break; 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate if (serr) 4297c478bd9Sstevel@tonic-gate free(serr); 4307c478bd9Sstevel@tonic-gate if (srsrc) 4317c478bd9Sstevel@tonic-gate free(srsrc); 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate /* 4357c478bd9Sstevel@tonic-gate * ap_msg() accepts a variable number of message IDs and constructs 4367c478bd9Sstevel@tonic-gate * a corresponding message string which is printed via the message print 4377c478bd9Sstevel@tonic-gate * routine argument. ap_msg() internationalizes the appropriate portion 4387c478bd9Sstevel@tonic-gate * of the message. 4397c478bd9Sstevel@tonic-gate */ 4407c478bd9Sstevel@tonic-gate void 4417c478bd9Sstevel@tonic-gate ap_msg(apd_t *a, ...) 4427c478bd9Sstevel@tonic-gate { 4437c478bd9Sstevel@tonic-gate int v; 4447c478bd9Sstevel@tonic-gate int len; 4457c478bd9Sstevel@tonic-gate char *p; 4467c478bd9Sstevel@tonic-gate const char *fmt; 4477c478bd9Sstevel@tonic-gate char *cmd; 4487c478bd9Sstevel@tonic-gate char *target; 4497c478bd9Sstevel@tonic-gate struct cfga_msg *msgp; 4507c478bd9Sstevel@tonic-gate va_list ap; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate DBG("ap_msg(%p)\n", (void *)a); 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate if (a == NULL || ap_getopt(a, OPT_VERBOSE) == 0) 4557c478bd9Sstevel@tonic-gate return; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate msgp = a->msgp; 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate if (msgp == NULL || msgp->message_routine == NULL) 4607c478bd9Sstevel@tonic-gate return; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate va_start(ap, a); 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate v = va_arg(ap, int); 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if ((fmt = ap_msg_fmt(v)) == NULL) 4677c478bd9Sstevel@tonic-gate fmt = STR_MSG_UNKNOWN; 4687c478bd9Sstevel@tonic-gate fmt = dgettext(TEXT_DOMAIN, fmt); 4697c478bd9Sstevel@tonic-gate len = strlen(fmt) + 128; /* slop */ 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate DBG("<%d>", v); 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate switch (v) { 4747c478bd9Sstevel@tonic-gate case MSG_ISSUE: 4757c478bd9Sstevel@tonic-gate case MSG_SKIP: 4767c478bd9Sstevel@tonic-gate case MSG_ABORT: 4777c478bd9Sstevel@tonic-gate case MSG_FAIL: 4787c478bd9Sstevel@tonic-gate case MSG_DONE: 4797c478bd9Sstevel@tonic-gate get_cmd(cmd, ap, v); 4807c478bd9Sstevel@tonic-gate get_tgt(target, ap); 4817c478bd9Sstevel@tonic-gate DBG("<%s><%s>\n", cmd, target); 4827c478bd9Sstevel@tonic-gate len += strlen(cmd) + strlen(target); 4837c478bd9Sstevel@tonic-gate break; 4847c478bd9Sstevel@tonic-gate default: 4857c478bd9Sstevel@tonic-gate break; 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate va_end(ap); 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate if ((p = (char *)calloc(len, 1)) == NULL) 4917c478bd9Sstevel@tonic-gate return; 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate (void) snprintf(p, len, fmt, cmd, target); 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate (*msgp->message_routine)(msgp->appdata_ptr, p); 4967c478bd9Sstevel@tonic-gate free(p); 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate int 5007c478bd9Sstevel@tonic-gate ap_confirm(apd_t *a) 5017c478bd9Sstevel@tonic-gate { 5027c478bd9Sstevel@tonic-gate int rc; 5037c478bd9Sstevel@tonic-gate char *msg; 5047c478bd9Sstevel@tonic-gate struct cfga_confirm *confp; 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate if (a == NULL) 5077c478bd9Sstevel@tonic-gate return (0); 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate confp = a->confp; 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate if (confp == NULL || confp->confirm == NULL) 5127c478bd9Sstevel@tonic-gate return (0); 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate msg = dgettext(TEXT_DOMAIN, ap_msg_fmt(MSG_SUSPEND)); 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate rc = (*confp->confirm)(confp->appdata_ptr, msg); 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate return (rc); 5197c478bd9Sstevel@tonic-gate } 520