Print this page
patch tsoome-feedback
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/pcidr/pcidr.c
+++ new/usr/src/cmd/pcidr/pcidr.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
29 27 #include <stdio.h>
30 28 #include <stdlib.h>
31 29 #include <unistd.h>
32 30 #include <strings.h>
33 31 #include <string.h>
34 32 #include <errno.h>
35 33 #include <sys/param.h>
36 34 #include <sys/systeminfo.h>
37 35 #include <sys/sysevent/eventdefs.h>
38 36 #include <sys/sysevent/dr.h>
39 37 #include <syslog.h>
40 38 #include <libnvpair.h>
41 39 #include <stdarg.h>
42 40 #include <assert.h>
43 41 #include <sys/stat.h>
44 42 #include <dlfcn.h>
45 43 #include <signal.h>
46 44 #include <pcidr.h>
47 45
48 46 /*
49 47 * pcidr takes in arguments of the form specified in the help() routine
50 48 * including a set of name=value pairs, then looks up a plugin (shared object)
51 49 * based on <plugin_paths> and however find_plugin() operates. The entry
52 50 * point of the plugin is <PCIDR_PLUGIN_SYM> and has the type
53 51 * <pcidr_plugin_t>. Plugins must use the <PCIDR_PLUGIN_PROTO> macro to
54 52 * define their entry point.
55 53 *
56 54 * The name=value arguments are intended to be used as a mechanism to pass
57 55 * arbitrary sysevent attributes using the macro expansion capability provided
58 56 * by the syseventd SLM processing sysevent.conf files (i.e. specifying
59 57 * "$attribute" arguments for the handler in a .conf file entry). They are
60 58 * converted into an nvlist_t (see libnvpair(3LIB)) by converting the values
61 59 * of recognized names into appropriate types using pcidr_name2type() and
62 60 * leaving all others as string types. Because pcidr is used as a sysevent.conf
63 61 * handler, the format of the value string for non-string attributes in each
64 62 * name=value argument must match that used by the syseventd macro capability
65 63 *
66 64 * The plugin will be passed this (nvlist_t *) along with a (pcidr_opt_t *) arg
67 65 * for other options. While pcidr does some basic checking of arguments, it
68 66 * leaves any name=value check (after conversion) up to each plugin. Note
69 67 * that pcidr_check_attrs() is used by the default plugin and can be used by
70 68 * any plugin that support the same or a superset of its attributes. If the
71 69 * default plugin supports additional publishers, it should be updated in
72 70 * pcidr_check_attrs().
73 71 *
74 72 * See help() for an example of how pcidr can be specified in a sysevent.conf
75 73 * file.
76 74 */
77 75
78 76 /*
79 77 * plugin search paths (searched in order specified);
80 78 * macros begin MACRO_BEGTOK and end with MACRO_ENDTOK;
81 79 *
82 80 * be sure to update parse_path() and its support functions whenever macros
83 81 * are updated e.g. si_name2cmd(), as well as substring tokens (prefix or
84 82 * suffix) used to recognize different types of macros e.g. SI_MACRO
85 83 *
86 84 * NOTE: if plugin search algorithm is changed starting with find_plugin(),
87 85 * please update documentation here.
88 86 *
89 87 * macros:
90 88 * SI_PLATFORM = cmd of same name in sysinfo(2)
91 89 * SI_MACHINE = cmd of same name in sysinfo(2)
92 90 */
93 91 #define MACRO_BEGTOK "${"
94 92 #define MACRO_ENDTOK "}"
95 93 #define SI_MACRO "SI_"
96 94
97 95 static char *plugin_paths[] = {
98 96 "/usr/platform/${SI_PLATFORM}/lib/pci/" PCIDR_PLUGIN_NAME,
99 97 "/usr/platform/${SI_MACHINE}/lib/pci/" PCIDR_PLUGIN_NAME,
100 98 "/usr/lib/pci/" PCIDR_PLUGIN_NAME,
101 99 };
102 100 static int plugin_paths_len = sizeof (plugin_paths) / sizeof (plugin_paths[0]);
103 101
104 102
105 103 static nvlist_t *nvlistp = NULL; /* attribute list */
106 104
107 105 typedef struct {
108 106 char *name;
109 107 char *beg;
110 108 char *end;
111 109 } macro_list_t;
112 110 static macro_list_t *parse_macros(char *const, int *);
113 111 static void free_macros(macro_list_t *, int);
114 112 static char *parse_path(char *const);
115 113 static void help();
116 114 static void exiter();
117 115 static char *find_plugin(nvlist_t *);
118 116 static int do_plugin(char *, nvlist_t *, pcidr_opt_t *);
119 117 static int nvadd(nvlist_t *, char *, char *, data_type_t);
120 118 static nvlist_t *parse_argv_attr(int, char **, int *);
121 119 static int si_name2cmd(char *);
122 120
123 121
124 122 static void
125 123 help()
126 124 {
127 125 /* since the handler is not public, we don't expose its usage normally */
128 126 #ifdef DEBUG
129 127 (void) printf(
130 128 "%s [-h] [-s] [-v <level>] [-l <log_file>] <attributes>\n"
131 129 " -h help\n"
132 130 "\n"
133 131 " -s turn OFF messages to the syslog (use syslog by default)\n"
134 132 "\n"
135 133 " -v verbose mode; <level> range is %d..%d; default is %d\n"
136 134 "\n"
137 135 " -l also log messages to <log_file> (in addition to using\n"
138 136 " the syslog if that option is not disabled);\n"
139 137 " if <log_file> is '-', stdout is used\n"
140 138 "\n"
141 139 " <attributes>\n"
142 140 " whitespace seperated strings of <name>=<value> pairs\n"
143 141 "\n"
144 142 "Example 1 (command line):\n"
145 143 " %s -s -v%d -l- \\\n"
146 144 " class=EC_dr subclass=ESC_dr_req publisher=pcie_pci \\\n"
147 145 " dr_request_type=dr_request_outgoing_resource \\\n"
148 146 " dr_ap_id=/devices/foo/bar\n"
149 147 "\n"
150 148 "Example 2 (/etc/sysevent/config/SUNW,sysevent.conf entry):\n"
151 149 " EC_dr ESC_dr_req SUNW pcie_pci - - - %s -v%d -l/tmp/log \\\n"
152 150 " class=$class subclass=$subclass publisher=$publisher \\\n"
153 151 " dr_request_type=$dr_request_type\\\n"
154 152 " dr_ap_id=$dr_ap_id\n"
155 153 "\n",
156 154 prg, MIN_DLVL, MAX_DLVL, dlvl,
157 155 prg, MAX_DLVL, /* Example 1 */
158 156 prg, DWARN); /* Example 2 */
159 157 #endif
160 158 }
161 159
162 160
163 161 /*
164 162 * will convert <value> from a string to the type indicated by <type>
165 163 * and will add it with <name> to nvlist_t <listp>; function returns the same
166 164 * value as nvlist_add_*()
167 165 */
168 166 static int
169 167 nvadd(nvlist_t *listp, char *name, char *value, data_type_t type)
170 168 {
171 169 char *fn = "nvadd";
172 170 int rv = 0;
173 171
174 172 switch (type) {
175 173 case DATA_TYPE_STRING:
176 174 rv = nvlist_add_string(listp, name, value);
177 175 if (rv != 0) {
178 176 dprint(DDEBUG, "%s: nvlist_add_string() failed: "
179 177 "name = %s, value = %s, rv = %d\n",
180 178 fn, name, value, rv);
181 179 }
182 180 break;
183 181 /*
184 182 * Conversion must support whatever string format syseventd uses for
185 183 * its .conf macros; in addition, minimum types supported must match
186 184 * those for pcidr_name2type()
187 185 */
188 186 default:
189 187 dprint(DDEBUG, "%s: unsupported type: name = %s, value = %s, "
190 188 "type = 0x%x\n", fn, name, value, (int)type);
191 189 rv = EINVAL;
192 190 }
193 191
194 192 return (rv);
195 193 }
196 194
197 195
198 196 /*
199 197 * argc: length of argv
200 198 * argv: each string starting from index <argip> has the format "name=value"
201 199 * argip: starting index in <argv>; also used to return ending index
202 200 *
203 201 * return: allocated nvlist on success, exits otherwise
204 202 *
205 203 * recognized names will have predetermined types, while all others will have
206 204 * values of type string
207 205 */
208 206 static nvlist_t *
209 207 parse_argv_attr(int argc, char **argv, int *argip)
210 208 {
211 209 char *fn = "parse_argv_attr";
212 210 int rv, i;
213 211 nvlist_t *attrlistp = NULL;
214 212 char *eqp, *name, *value;
215 213 data_type_t type;
216 214
217 215 assert(*argip < argc);
218 216
219 217 rv = nvlist_alloc(&attrlistp, NV_UNIQUE_NAME_TYPE, 0);
220 218 if (rv != 0) {
221 219 dprint(DDEBUG, "%s: nvlist_alloc() failed: rv = %d\n", fn, rv);
222 220 goto ERR;
223 221 }
224 222
225 223 for (i = *argip; i < argc; i++) {
226 224 eqp = strchr(argv[i], '=');
227 225 if (eqp == NULL)
228 226 goto ERR_ARG;
229 227 *eqp = '\0';
230 228 name = argv[i];
231 229 value = eqp;
232 230 value++;
233 231 if (*name == '\0' || *value == '\0')
234 232 goto ERR_ARG;
235 233
236 234 if (pcidr_name2type(name, &type) != 0)
237 235 type = DATA_TYPE_STRING;
238 236
239 237 rv = nvadd(attrlistp, name, value, type);
240 238 if (rv != 0) {
241 239 dprint(DDEBUG, "%s: nvadd() failed: attribute \"%s\", "
242 240 "value = %s, type = %d, rv = %d\n",
243 241 fn, name, value, (int)type, rv);
244 242 goto ERR;
245 243 }
246 244 *eqp = '=';
247 245 }
↓ open down ↓ |
209 lines elided |
↑ open up ↑ |
248 246
249 247 *argip = i;
250 248 return (attrlistp);
251 249
252 250 /*NOTREACHED*/
253 251 ERR_ARG:
254 252 if (eqp != NULL)
255 253 *eqp = '=';
256 254 dprint(DDEBUG, "%s: bad attribute argv[%d]: \"%s\"\n", fn, i, argv[i]);
257 255 ERR:
258 - if (attrlistp != NULL)
259 - nvlist_free(attrlistp);
256 + nvlist_free(attrlistp);
260 257 return (NULL);
261 258 }
262 259
263 260
264 261 static struct {
265 262 int cmd;
266 263 char *name;
267 264 } si_cmd_nametab[] = {
268 265 SI_PLATFORM, "SI_PLATFORM",
269 266 SI_MACHINE, "SI_MACHINE",
270 267 };
271 268 static int si_cmd_nametab_len =
272 269 sizeof (si_cmd_nametab) / sizeof (si_cmd_nametab[0]);
273 270
274 271 static int
275 272 si_name2cmd(char *name)
276 273 {
277 274 int i;
278 275
279 276 for (i = 0; i < si_cmd_nametab_len; i++) {
280 277 if (strcmp(name, si_cmd_nametab[i].name) == 0)
281 278 return (si_cmd_nametab[i].cmd);
282 279 }
283 280 return (-1);
284 281 }
285 282
286 283
287 284 /*
288 285 * finds occurences of substrings surrounded (delimited) by MACRO_BEGTOK and
289 286 * MACRO_ENDTOK in <str>;
290 287 * returns an allocated array of macro_list_t whose length is
291 288 * returned through <lenp>; array entries will be in order of the occurrence;
292 289 * else returns NULL if none are found
293 290 *
294 291 * macro_list_t members:
295 292 * char *name = allocated string containing name without macro delimiters
296 293 * char *beg = location in <str> at _first char_ of MACRO_BEGTOK
297 294 * char *end = location in <str> at _last char_ of MACRO_ENDTOK
298 295 */
299 296 static macro_list_t *
300 297 parse_macros(char *const str, int *lenp)
301 298 {
302 299 char *beg, *end;
303 300 macro_list_t *lp;
304 301 size_t size;
305 302 int i, begtok_len, endtok_len;
306 303
307 304 begtok_len = strlen(MACRO_BEGTOK);
308 305 endtok_len = strlen(MACRO_ENDTOK);
309 306
310 307 /* count all occurrences */
311 308 for (beg = str, i = 0; beg != NULL; i++) {
312 309 beg = strstr(beg, MACRO_BEGTOK);
313 310 if (beg == NULL)
314 311 break;
315 312 end = strstr(beg + begtok_len, MACRO_ENDTOK);
316 313 if (end == NULL)
317 314 break;
318 315 beg = end + endtok_len;
319 316 }
320 317 if (i <= 0)
321 318 return (NULL);
322 319
323 320 *lenp = i;
324 321 lp = pcidr_malloc(sizeof (macro_list_t) * i);
325 322
326 323 for (beg = str, i = 0; i < *lenp; i++) {
327 324 beg = strstr(beg, MACRO_BEGTOK);
328 325 assert(beg != NULL);
329 326 end = strstr(beg + begtok_len, MACRO_ENDTOK);
330 327 assert(end != NULL);
331 328
332 329 size = (end - (beg + begtok_len)) + 1;
333 330 lp[i].name = pcidr_malloc(size * sizeof (char));
334 331 (void) strlcpy(lp[i].name, beg + begtok_len, size);
335 332
336 333 lp[i].beg = beg;
337 334 lp[i].end = (end + endtok_len) - 1;
338 335
339 336 beg = end + endtok_len;
340 337 }
341 338
342 339 return (lp);
343 340 }
344 341
345 342 static void
346 343 free_macros(macro_list_t *lp, int len)
347 344 {
348 345 int i;
349 346
350 347 for (i = 0; i < len; i++)
351 348 free(lp[i].name);
352 349 free(lp);
353 350 }
354 351
355 352
356 353 /*
357 354 * evaluates any macros in <opath> and returns allocated string on success;
358 355 * else NULL
359 356 */
360 357 static char *
361 358 parse_path(char *const opath)
362 359 {
363 360 char *fn = "parse_path";
364 361 char buf[MAXPATHLEN + 1];
365 362 int bufsize = sizeof (buf) / sizeof (buf[0]);
366 363 char sibuf[257];
367 364 int sibufsize = sizeof (sibuf) / sizeof (sibuf[0]);
368 365 macro_list_t *lp;
369 366 char *path, *pathp, *pathend;
370 367 int rv, i, lplen, si_cmd, pathlen, okmacro, si_macro_len;
371 368 size_t sz;
372 369
373 370 /*
374 371 * make a copy so we can modify it for easier parsing;
375 372 * lp members will refer to the copy
376 373 */
377 374 path = strdup(opath);
378 375 lp = parse_macros(path, &lplen);
379 376 if (lp == NULL)
380 377 return (path);
381 378
382 379 rv = 0;
383 380 si_macro_len = strlen(SI_MACRO);
384 381 pathlen = strlen(path);
385 382 pathend = &path[pathlen - 1];
386 383 pathp = path;
387 384 buf[0] = '\0';
388 385 for (i = 0; i < lplen; i++) {
389 386 lp[i].beg[0] = '\0';
390 387 sz = strlcat(buf, pathp, bufsize);
391 388 assert(sz < bufsize);
392 389
393 390 okmacro = 0;
394 391 if (strncmp(lp[i].name, SI_MACRO, si_macro_len) == 0) {
395 392 si_cmd = si_name2cmd(lp[i].name);
396 393 assert(si_cmd >= 0);
397 394
398 395 rv = sysinfo(si_cmd, sibuf, sibufsize);
399 396 if (rv < 0) {
400 397 dprint(DDEBUG, "%s: sysinfo cmd %d failed: "
401 398 "errno = %d\n", fn, si_cmd, errno);
402 399 goto OUT;
403 400 }
404 401
405 402 sz = strlcat(buf, sibuf, bufsize);
406 403 assert(sz < bufsize);
407 404 okmacro = 1;
408 405 }
409 406 /* check for unrecognized macros */
410 407 assert(okmacro);
411 408 pathp = lp[i].end + 1;
412 409 }
413 410
414 411 rv = 0;
415 412 if (pathp < pathend) {
416 413 sz = strlcat(buf, pathp, bufsize);
417 414 assert(sz < bufsize);
418 415 }
419 416 OUT:
420 417 free_macros(lp, lplen);
421 418 free(path);
422 419 if (rv == 0)
423 420 return (strdup(buf));
424 421 return (NULL);
425 422 }
426 423
427 424
428 425 /*
429 426 * returns allocated string containing plugin path which caller must free;
430 427 * else NULL; <attrlistp> is for future use if attributes can be used to
431 428 * determin plugin
432 429 */
433 430 /*ARGSUSED*/
434 431 static char *
435 432 find_plugin(nvlist_t *attrlistp)
436 433 {
437 434 char *fn = "find_plugin";
438 435 char *path = NULL;
439 436 int i, rv;
440 437 struct stat statbuf;
441 438
442 439 for (i = 0; i < plugin_paths_len; i++) {
443 440 path = parse_path(plugin_paths[i]);
444 441 if (path == NULL) {
445 442 dprint(DDEBUG, "%s: error parsing path %s\n", fn,
446 443 path);
447 444 return (NULL);
448 445 }
449 446
450 447 rv = stat(path, &statbuf);
451 448 if (rv < 0)
452 449 dprint(DDEBUG, "%s: stat on %s failed: "
453 450 "errno = %d\n", fn, path, errno);
454 451 else if ((statbuf.st_mode & S_IFMT) != S_IFREG)
455 452 dprint(DDEBUG, "%s: %s is not a regular "
456 453 "file\n", fn, path);
457 454 else
458 455 return (path);
459 456
460 457 free(path);
461 458 }
462 459 return (NULL);
463 460 }
464 461
465 462
466 463 /*
467 464 * load plugin specified by <path> and pass the proceeding arguments
468 465 * to the plugin interface; returns 0 on success (likewise for
469 466 * the plugin function)
470 467 */
471 468 static int
472 469 do_plugin(char *path, nvlist_t *attrlistp, pcidr_opt_t *optp)
473 470 {
474 471 char *fn = "do_plugin";
475 472 int rv;
476 473 void *dlh;
477 474 sigset_t set, oset;
478 475 pcidr_plugin_t fp;
479 476
480 477 dlh = dlopen(path, RTLD_LAZY | RTLD_GLOBAL);
481 478 if (dlh == NULL) {
482 479 dprint(DDEBUG, "%s: dlopen() failed: %s\n", fn, dlerror());
483 480 rv = EINVAL;
484 481 goto OUT;
485 482 }
486 483
487 484 if (sigfillset(&set) != 0) {
488 485 dprint(DDEBUG, "%s: sigfillset() failed: errno = %d\n", fn,
489 486 errno);
490 487 rv = errno;
491 488 goto OUT;
492 489 }
493 490 if (sigprocmask(SIG_BLOCK, &set, &oset) != 0) {
494 491 dprint(DDEBUG, "%s: blocking signals with sigprocmask() "
495 492 "failed: errno = %d\n", fn, errno);
496 493 rv = errno;
497 494 goto OUT;
498 495 }
499 496
500 497 fp = (pcidr_plugin_t)dlsym(dlh, PCIDR_PLUGIN_SYMSTR);
501 498 if (fp == NULL) {
502 499 dprint(DDEBUG, "%s: dlsym() failed: %s\n", fn, dlerror());
503 500 rv = EINVAL;
504 501 goto OUT;
505 502 }
506 503 rv = fp(attrlistp, optp);
507 504 if (rv != 0)
508 505 dprint(DDEBUG, "%s: %s() failed: rv = %d\n", fn,
509 506 PCIDR_PLUGIN_SYMSTR, rv);
510 507
511 508 if (sigprocmask(SIG_SETMASK, &oset, NULL) != 0) {
512 509 dprint(DDEBUG, "%s: unblocking signals with sigprocmask() "
513 510 "failed: errno = %d\n", fn, errno);
514 511 rv = errno;
515 512 goto OUT;
516 513 }
517 514 OUT:
518 515 if (dlh != NULL)
519 516 (void) dlclose(dlh);
520 517 return (rv);
521 518 }
522 519
523 520
524 521 static void
525 522 exiter()
526 523 {
527 524 extern FILE *dfp;
528 525
529 526 if (nvlistp != NULL)
530 527 nvlist_free(nvlistp);
531 528 if (dfp != NULL)
532 529 (void) fclose(dfp);
533 530 #ifdef DEBUG
534 531 closelog();
535 532 #endif
536 533 }
537 534
538 535
539 536 int
540 537 main(int argc, char **argv)
541 538 {
542 539 int rv, argi;
543 540 char *dfile = NULL, *plugin_path = NULL;
544 541 struct stat statbuf;
545 542 pcidr_opt_t plugin_opt;
546 543 char *optstr = NULL;
547 544
548 545 extern char *optarg;
549 546 extern int optind, optopt;
550 547 int c;
551 548
552 549 /*CONSTCOND*/
553 550 assert(MIN_DLVL == 0);
554 551 /*CONSTCOND*/
555 552 assert(MIN_DLVL == DNONE);
556 553 assert(MAX_DLVL == dpritab_len - 1);
557 554
558 555 (void) atexit(exiter);
559 556 prg = argv[0];
560 557 dfp = NULL;
561 558
562 559 #ifdef DEBUG
563 560 openlog(prg, LOG_PID | LOG_CONS, LOG_DAEMON);
564 561 dlvl = DWARN;
565 562 dsys = 1;
566 563 optstr = "hsv:l:";
567 564 #else
568 565 dlvl = DNONE;
569 566 dsys = 0;
570 567 optstr = "sv:l:";
571 568 #endif
572 569
573 570 while ((c = getopt(argc, argv, optstr)) != -1) {
574 571 switch (c) {
575 572 case 'h':
576 573 help();
577 574 exit(0);
578 575 break;
579 576 case 's':
580 577 dsys = 0;
581 578 break;
582 579 case 'v':
583 580 dlvl = atoi(optarg);
584 581 break;
585 582 case 'l':
586 583 dfile = optarg;
587 584 break;
588 585 default:
589 586 dprint(DWARN, "bad option: %c\n", optopt);
590 587 return (EINVAL);
591 588 }
592 589 }
593 590
594 591 /*
595 592 * [ -l ] do file option first so we can still get msgs if -s is used
596 593 */
597 594 if (dfile != NULL) {
598 595 if (strcmp(dfile, "-") == 0) {
599 596 /* ignore if stdout is not open/valid */
600 597 dfp = NULL;
601 598 if (stdout != NULL &&
602 599 fstat(fileno(stdout), &statbuf) == 0)
603 600 dfp = stdout;
604 601 } else {
605 602 dfp = fopen(dfile, "a");
606 603 if (dfp == NULL) {
607 604 dprint(DWARN, "cannot open %s: %s\n",
608 605 dfile, strerror(errno));
609 606 return (EINVAL);
610 607 }
611 608 }
612 609 }
613 610
614 611 /* [ -v ] */
615 612 if (dlvl < MIN_DLVL || dlvl > MAX_DLVL) {
616 613 dprint(DWARN, "bad arg for -v: %d\n", dlvl);
617 614 return (EINVAL);
618 615 }
619 616
620 617 argi = optind;
621 618 if (argi >= argc) {
622 619 dprint(DWARN, "missing attribute arguments\n");
623 620 return (EINVAL);
624 621 }
625 622
626 623 nvlistp = parse_argv_attr(argc, argv, &argi);
627 624 if (nvlistp == NULL) {
628 625 dprint(DWARN, "attribute parsing error\n");
629 626 return (EINVAL);
630 627 }
631 628
632 629 (void) memset(&plugin_opt, 0, sizeof (plugin_opt));
633 630 plugin_opt.logopt.dlvl = dlvl;
634 631 plugin_opt.logopt.prg = prg;
635 632 plugin_opt.logopt.dfp = dfp;
636 633 plugin_opt.logopt.dsys = dsys;
637 634
638 635 dprint(DINFO, "=== sysevent attributes ========================\n");
639 636 pcidr_print_attrlist(DINFO, nvlistp, NULL);
640 637 dprint(DINFO, "================================================\n");
641 638
642 639 plugin_path = find_plugin(nvlistp);
643 640 if (plugin_path == NULL) {
644 641 dprint(DWARN, "cannot find plugin\n");
645 642 return (EINVAL);
646 643 }
647 644 dprint(DINFO, "using plugin: %s\n\n", plugin_path);
648 645
649 646 rv = do_plugin(plugin_path, nvlistp, &plugin_opt);
650 647 if (rv != 0) {
651 648 dprint(DWARN, "plugin %s failed\n", plugin_path);
652 649 }
653 650 if (plugin_path != NULL)
654 651 free(plugin_path);
655 652 return (rv);
656 653 }
↓ open down ↓ |
387 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX