dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / cfgadm_plugins / sbd / common / ap_msg.c
blob8eaed437e50877344c46168fc9809a6d45c123a2
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <ctype.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <macros.h>
33 #include <errno.h>
34 #include <locale.h>
35 #include <libdevinfo.h>
36 #include <librcm.h>
37 #define CFGA_PLUGIN_LIB
38 #include <config_admin.h>
39 #include "ap.h"
41 #ifdef SBD_DEBUG
43 static FILE *debug_fp;
45 int
46 debugging(void)
48 char *ep;
49 static int inited;
51 if (inited)
52 return (debug_fp != NULL);
53 inited = 1;
55 if ((ep = getenv("SBD_DEBUG")) == NULL)
56 return (0);
58 if (*ep == '\0')
59 debug_fp = stderr;
60 else {
61 if ((debug_fp = fopen(ep, "a")) == NULL)
62 return (0);
64 (void) fprintf(debug_fp, "\nDebug started, pid=%d\n", (int)getpid());
65 return (1);
68 /*PRINTFLIKE1*/
69 void
70 dbg(char *fmt, ...)
72 va_list ap;
74 if (!debugging())
75 return;
77 va_start(ap, fmt);
78 (void) vfprintf(debug_fp, fmt, ap);
79 va_end(ap);
81 #endif
83 static char *
84 ap_err_fmts[] = {
85 "command invalid: %s",
86 "%s %s: %s%s%s", /* command failed */
87 "%s %s", /* command nacked */
88 "command not supported: %s %s",
89 "command aborted: %s %s",
90 "option invalid: %s",
91 "option requires value: %s",
92 "option requires no value: %s",
93 "option value invalid: %s %s",
94 "attachment point invalid: %s",
95 "component invalid: %s",
96 "sequence invalid: %s (%s %s) %s",
97 "change signal disposition failed",
98 "cannot get RCM handle",
99 "RCM %s failed for %s",
100 "\n%-30s %-10s %s",
101 "cannot open %s%s%s",
102 "cannot find symbol %s in %s",
103 "cannot stat %s: %s",
104 "not enough memory",
105 "%s plugin: %s",
106 "unknown error",
107 NULL
110 #define ap_err_fmt(i) ap_err_fmts[min((uint_t)(i), ERR_NONE)]
112 static char *
113 ap_msg_fmts[] = {
114 "%s %s\n",
115 "%s %s skipped\n",
116 "System may be temporarily suspended, proceed",
117 "%s %s aborted\n",
118 "%s %s done\n",
119 "%s %s failed\n",
120 "RCM library not found, feature will be disabled\n",
121 "Unknown message\n",
122 NULL
125 #define ap_msg_fmt(i) ap_msg_fmts[min((uint_t)(i), MSG_NONE)]
127 #define STR_BD "board"
128 #define STR_SEP ": "
129 #define STR_NULL "NULL"
130 #define STR_CMD_UNKNOWN "unknown command"
131 #define STR_ERR_UNKNOWN "unknown error"
132 #define STR_MSG_UNKNOWN "unknown message\n"
133 #define STR_TGT_UNKNOWN "unknown target"
135 #define get_cmd(c, ap, v) \
137 (v) = va_arg((ap), int); \
138 if (((c) = ap_cmd_name((v))) == NULL) \
139 (c) = STR_CMD_UNKNOWN; \
141 #define get_tgt(t, ap) {\
142 (t) = va_arg((ap), char *); \
143 if (!str_valid((t))) \
144 (t) = STR_TGT_UNKNOWN; \
146 #define check_tgt(tgt, t) {\
147 if (str_valid((tgt))) \
148 (t) = (tgt); \
149 else \
150 (t) = STR_TGT_UNKNOWN; \
152 #define get_str(v, ap, d) \
154 (v) = va_arg((ap), char *); \
155 if ((v) == NULL) \
156 (v) = (d); \
159 static char *
160 ap_stnames[] = {
161 "unknown state",
162 "empty",
163 "disconnected",
164 "connected",
165 "unconfigured",
166 "configured"
170 * ap_err() accepts a variable number of message IDs and constructs
171 * a corresponding error string. ap_err() calls dgettext() to
172 * internationalize the proper portions of a message. If a system
173 * error was encountered (errno set), ap_err() looks for the error
174 * string corresponding to the returned error code if one is available.
175 * If not, the standard libc error string is fetched.
177 void
178 ap_err(apd_t *a, ...)
180 int v;
181 int err;
182 int len;
183 char *p;
184 char *sep;
185 char *rsep;
186 const char *fmt;
187 char *cmd;
188 char *value;
189 char *target;
190 char *serr;
191 char *syserr;
192 char *rstate;
193 char *ostate;
194 char *srsrc;
195 char *sysrsrc;
196 char *option;
197 char *path;
198 char *sym;
199 char *msg;
200 const char *error;
201 char **errstring;
202 char *rinfostr = NULL;
203 va_list ap;
205 DBG("ap_err(%p)\n", (void *)a);
208 * If there is no descriptor or string pointer or if
209 * there is an outstanding error, just return.
211 if (a == NULL || (errstring = a->errstring) == NULL ||
212 *errstring != NULL)
213 return;
215 va_start(ap, a);
217 err = va_arg(ap, int);
219 if ((fmt = ap_err_fmt(err)) == NULL)
220 fmt = STR_ERR_UNKNOWN;
221 fmt = dgettext(TEXT_DOMAIN, fmt);
222 len = strlen(fmt);
224 sep = "";
225 serr = NULL;
226 srsrc = NULL;
227 error = NULL;
230 * Get the proper arguments for the error.
232 switch (err) {
233 case ERR_CMD_ABORT:
234 case ERR_CMD_FAIL:
235 case ERR_CMD_NACK:
236 get_cmd(cmd, ap, v);
237 check_tgt(a->target, target);
238 len += strlen(cmd) + strlen(target);
239 DBG("<%s><%s>", cmd, target);
240 break;
241 case ERR_CMD_NOTSUPP:
242 get_cmd(cmd, ap, v);
243 if (a->tgt == AP_BOARD)
244 target = STR_BD;
245 else
246 check_tgt(a->cname, target);
247 len += strlen(cmd) + strlen(target);
248 DBG("<%s><%s>", cmd, target);
249 break;
250 case ERR_AP_INVAL:
251 check_tgt((char *)a->apid, target);
252 len += strlen(target);
253 DBG("<%s>", target);
254 break;
255 case ERR_CMD_INVAL:
256 case ERR_CM_INVAL:
257 case ERR_OPT_INVAL:
258 case ERR_OPT_NOVAL:
259 case ERR_OPT_VAL:
260 case ERR_OPT_BADVAL:
261 get_str(option, ap, STR_NULL);
262 len += strlen(option);
263 DBG("<%s>", option);
264 if (err != ERR_OPT_BADVAL)
265 break;
266 get_str(value, ap, STR_NULL);
267 len += strlen(value);
268 DBG("<%s>", value);
269 break;
270 case ERR_TRANS_INVAL: {
271 cfga_stat_t rs, os;
273 get_cmd(cmd, ap, v);
274 check_tgt(a->target, target);
275 len += strlen(cmd) + strlen(target);
276 ap_state(a, &rs, &os);
277 rstate = ap_stnames[rs];
278 ostate = ap_stnames[os];
279 len += strlen(rstate) + strlen(ostate);
280 DBG("<%s><%s><%s><%s>", cmd, target, rstate, ostate);
281 break;
283 case ERR_RCM_CMD: {
285 get_cmd(cmd, ap, v);
286 check_tgt(a->target, target);
287 len += strlen(cmd) + strlen(target);
288 DBG("<%s><%s>", cmd, target);
290 if ((ap_rcm_info(a, &rinfostr) == 0) && (rinfostr != NULL)) {
291 len += strlen(rinfostr);
294 break;
296 case ERR_LIB_OPEN:
297 get_str(path, ap, STR_NULL);
298 get_str(error, ap, "");
299 if (str_valid(error))
300 sep = STR_SEP;
301 DBG("<%s><%s>", path, error);
302 break;
303 case ERR_LIB_SYM:
304 get_str(path, ap, STR_NULL);
305 get_str(sym, ap, STR_NULL);
306 DBG("<%s><%s>", path, sym);
307 break;
308 case ERR_STAT:
309 get_str(path, ap, STR_NULL);
310 break;
311 case ERR_PLUGIN:
312 get_str(msg, ap, STR_NULL);
313 break;
314 default:
315 DBG("<NOARGS>");
316 break;
319 va_end(ap);
322 * In case of a system error, get the reason for
323 * the failure as well as the resource if availbale.
324 * If we already got some error info (e.g. from RCM)
325 * don't bother looking.
327 if (!str_valid(error) && errno) {
328 sep = STR_SEP;
329 sysrsrc = NULL;
330 if ((syserr = ap_sys_err(a, &sysrsrc)) == NULL)
331 syserr = STR_ERR_UNKNOWN;
332 else
333 serr = syserr;
335 syserr = dgettext(TEXT_DOMAIN, syserr);
337 if (sysrsrc == NULL)
338 sysrsrc = "";
339 else
340 srsrc = sysrsrc;
342 len += strlen(syserr) + strlen(sysrsrc);
344 if (str_valid(sysrsrc)) {
345 rsep = STR_SEP;
346 len += strlen(rsep);
347 } else
348 rsep = "";
350 DBG("<%s><%s><%s>", syserr, rsep, sysrsrc);
352 } else
353 syserr = rsep = sysrsrc = "";
355 DBG("\n");
357 if ((p = (char *)calloc(len, 1)) != NULL)
358 *errstring = p;
361 * Print the string with appropriate arguments.
363 switch (err) {
364 case ERR_CMD_FAIL:
365 (void) snprintf(p, len, fmt, cmd, target,
366 syserr, rsep, sysrsrc);
367 break;
368 case ERR_CMD_ABORT:
369 case ERR_CMD_NACK:
370 case ERR_CMD_NOTSUPP:
371 (void) snprintf(p, len, fmt, cmd, target);
372 break;
373 case ERR_AP_INVAL:
374 (void) snprintf(p, len, fmt, target);
375 break;
376 case ERR_CMD_INVAL:
377 case ERR_CM_INVAL:
378 case ERR_OPT_INVAL:
379 case ERR_OPT_NOVAL:
380 case ERR_OPT_VAL:
381 (void) snprintf(p, len, fmt, option);
382 break;
383 case ERR_OPT_BADVAL:
384 (void) snprintf(p, len, fmt, option, value);
385 break;
386 case ERR_TRANS_INVAL:
387 (void) snprintf(p, len, fmt, cmd, rstate, ostate, target);
388 break;
389 case ERR_SIG_CHANGE:
390 case ERR_RCM_HANDLE:
391 (void) snprintf(p, len, fmt);
392 break;
393 case ERR_RCM_CMD:
395 * If the rinfostr has a string, then the librcm has returned
396 * us a text field of its reasons why the command failed.
398 * If the rinfostr is not returning data, we will use
399 * the standard ap_err_fmts[] for the rcm error.
401 if (rinfostr != NULL)
402 (void) snprintf(p, len, "%s", rinfostr);
403 else
404 (void) snprintf(p, len, fmt, cmd, target);
405 break;
406 case ERR_LIB_OPEN:
407 (void) snprintf(p, len, fmt, path, sep, error);
408 break;
409 case ERR_LIB_SYM:
410 (void) snprintf(p, len, fmt, sym, path);
411 break;
412 case ERR_STAT:
413 (void) snprintf(p, len, fmt, path, syserr);
414 break;
415 case ERR_NOMEM:
416 (void) snprintf(p, len, fmt);
417 break;
418 case ERR_PLUGIN:
419 (void) snprintf(p, len, fmt, a->class, msg);
420 break;
421 default:
422 break;
425 free(serr);
426 free(srsrc);
430 * ap_msg() accepts a variable number of message IDs and constructs
431 * a corresponding message string which is printed via the message print
432 * routine argument. ap_msg() internationalizes the appropriate portion
433 * of the message.
435 void
436 ap_msg(apd_t *a, ...)
438 int v;
439 int len;
440 char *p;
441 const char *fmt;
442 char *cmd;
443 char *target;
444 struct cfga_msg *msgp;
445 va_list ap;
447 DBG("ap_msg(%p)\n", (void *)a);
449 if (a == NULL || ap_getopt(a, OPT_VERBOSE) == 0)
450 return;
452 msgp = a->msgp;
454 if (msgp == NULL || msgp->message_routine == NULL)
455 return;
457 va_start(ap, a);
459 v = va_arg(ap, int);
461 if ((fmt = ap_msg_fmt(v)) == NULL)
462 fmt = STR_MSG_UNKNOWN;
463 fmt = dgettext(TEXT_DOMAIN, fmt);
464 len = strlen(fmt) + 128; /* slop */
466 DBG("<%d>", v);
468 switch (v) {
469 case MSG_ISSUE:
470 case MSG_SKIP:
471 case MSG_ABORT:
472 case MSG_FAIL:
473 case MSG_DONE:
474 get_cmd(cmd, ap, v);
475 get_tgt(target, ap);
476 DBG("<%s><%s>\n", cmd, target);
477 len += strlen(cmd) + strlen(target);
478 break;
479 default:
480 break;
483 va_end(ap);
485 if ((p = (char *)calloc(len, 1)) == NULL)
486 return;
488 (void) snprintf(p, len, fmt, cmd, target);
490 (*msgp->message_routine)(msgp->appdata_ptr, p);
491 free(p);
495 ap_confirm(apd_t *a)
497 int rc;
498 char *msg;
499 struct cfga_confirm *confp;
501 if (a == NULL)
502 return (0);
504 confp = a->confp;
506 if (confp == NULL || confp->confirm == NULL)
507 return (0);
509 msg = dgettext(TEXT_DOMAIN, ap_msg_fmt(MSG_SUSPEND));
511 rc = (*confp->confirm)(confp->appdata_ptr, msg);
513 return (rc);