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 5bc9ec910Snakanon * Common Development and Distribution License (the "License"). 6bc9ec910Snakanon * 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 /* 22bc9ec910Snakanon * 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 /* 297c478bd9Sstevel@tonic-gate * sysevent_conf_mod - syseventd daemon sysevent.conf module 307c478bd9Sstevel@tonic-gate * 317c478bd9Sstevel@tonic-gate * This module provides a configuration file registration 327c478bd9Sstevel@tonic-gate * mechanism whereby event producers can define an event 337c478bd9Sstevel@tonic-gate * specification to be matched against events, with an 347c478bd9Sstevel@tonic-gate * associated command line to be invoked for each matching event. 357c478bd9Sstevel@tonic-gate * It includes a simple macro capability for flexibility in 367c478bd9Sstevel@tonic-gate * generating arbitrary command line formats from event-associated 377c478bd9Sstevel@tonic-gate * data, and a user specification so that commands can be invoked 387c478bd9Sstevel@tonic-gate * with reduced privileges to eliminate a security risk. 397c478bd9Sstevel@tonic-gate * 407c478bd9Sstevel@tonic-gate * sysevent.conf files contain event specifications and associated 417c478bd9Sstevel@tonic-gate * command path and optional arguments. System events received 427c478bd9Sstevel@tonic-gate * from the kernel by the sysevent daemon, syseventd, are 437c478bd9Sstevel@tonic-gate * compared against the event specifications in the sysevent.conf 447c478bd9Sstevel@tonic-gate * files. The command as specified by pathname and arguments 457c478bd9Sstevel@tonic-gate * is invoked for each matching event. 467c478bd9Sstevel@tonic-gate * 477c478bd9Sstevel@tonic-gate * All sysevent.conf files reside in /etc/sysevent/config. 487c478bd9Sstevel@tonic-gate * 497c478bd9Sstevel@tonic-gate */ 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #include <stdio.h> 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #include <unistd.h> 557c478bd9Sstevel@tonic-gate #include <stdarg.h> 567c478bd9Sstevel@tonic-gate #include <stdlib.h> 577c478bd9Sstevel@tonic-gate #include <string.h> 587c478bd9Sstevel@tonic-gate #include <strings.h> 597c478bd9Sstevel@tonic-gate #include <limits.h> 607c478bd9Sstevel@tonic-gate #include <thread.h> 617c478bd9Sstevel@tonic-gate #include <synch.h> 627c478bd9Sstevel@tonic-gate #include <errno.h> 637c478bd9Sstevel@tonic-gate #include <fcntl.h> 647c478bd9Sstevel@tonic-gate #include <ctype.h> 657c478bd9Sstevel@tonic-gate #include <pwd.h> 667c478bd9Sstevel@tonic-gate #include <syslog.h> 677c478bd9Sstevel@tonic-gate #include <sys/types.h> 687c478bd9Sstevel@tonic-gate #include <sys/stat.h> 697c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 707c478bd9Sstevel@tonic-gate #include <sys/sysevent.h> 717c478bd9Sstevel@tonic-gate #include <libsysevent.h> 727c478bd9Sstevel@tonic-gate #include <libnvpair.h> 737c478bd9Sstevel@tonic-gate #include <dirent.h> 747c478bd9Sstevel@tonic-gate #include <locale.h> 757c478bd9Sstevel@tonic-gate #include <signal.h> 767c478bd9Sstevel@tonic-gate #include <wait.h> 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate #include "syseventd.h" 797c478bd9Sstevel@tonic-gate #include "syseventconfd_door.h" 807c478bd9Sstevel@tonic-gate #include "sysevent_conf_mod.h" 817c478bd9Sstevel@tonic-gate #include "message_conf_mod.h" 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate static char *whoami = "sysevent_conf_mod"; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate /* 877c478bd9Sstevel@tonic-gate * Event sequencing, time stamp and retry count 887c478bd9Sstevel@tonic-gate */ 897c478bd9Sstevel@tonic-gate static int ev_nretries; /* retry count per event */ 907c478bd9Sstevel@tonic-gate static uint64_t ev_seq; /* current event sequencing number */ 917c478bd9Sstevel@tonic-gate static hrtime_t ev_ts; /* current event timestamp */ 927c478bd9Sstevel@tonic-gate static int first_event; /* first event since init */ 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate /* 957c478bd9Sstevel@tonic-gate * State of the sysevent conf table, derived from 967c478bd9Sstevel@tonic-gate * the /etc/sysevent/config files 977c478bd9Sstevel@tonic-gate */ 987c478bd9Sstevel@tonic-gate static conftab_t *conftab = NULL; 997c478bd9Sstevel@tonic-gate static syseventtab_t *syseventtab = NULL; 1007c478bd9Sstevel@tonic-gate static syseventtab_t *syseventtab_tail = NULL; 1017c478bd9Sstevel@tonic-gate static sysevent_handle_t *confd_handle = NULL; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * The cmd queue is a queue of commands ready to be sent 1057c478bd9Sstevel@tonic-gate * to syseventconfd. Each command consists of the path 1067c478bd9Sstevel@tonic-gate * and arguments to be fork/exec'ed. The daemon is unable 1077c478bd9Sstevel@tonic-gate * to handle events during an active fork/exec and returns 1087c478bd9Sstevel@tonic-gate * EAGAIN as a result. It is grossly inefficient to bounce 1097c478bd9Sstevel@tonic-gate * these events back to syseventd, so we queue them here for delivery. 1107c478bd9Sstevel@tonic-gate */ 1117c478bd9Sstevel@tonic-gate static cmdqueue_t *cmdq = NULL; 1127c478bd9Sstevel@tonic-gate static cmdqueue_t *cmdq_tail = NULL; 1137c478bd9Sstevel@tonic-gate static mutex_t cmdq_lock; 1147c478bd9Sstevel@tonic-gate static cond_t cmdq_cv; 1157c478bd9Sstevel@tonic-gate static int cmdq_cnt; 1167c478bd9Sstevel@tonic-gate static thread_t cmdq_thr_id; 1177c478bd9Sstevel@tonic-gate static cond_t cmdq_thr_cv; 1187c478bd9Sstevel@tonic-gate static int want_fini; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* 1217c478bd9Sstevel@tonic-gate * State of the door channel to syseventconfd 1227c478bd9Sstevel@tonic-gate */ 1237c478bd9Sstevel@tonic-gate static int confd_state = CONFD_STATE_NOT_RUNNING; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* 1267c478bd9Sstevel@tonic-gate * Number of times to retry event after restarting syeventconfd 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate static int confd_retries; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate /* 1317c478bd9Sstevel@tonic-gate * Number of times to retry a failed transport 1327c478bd9Sstevel@tonic-gate */ 1337c478bd9Sstevel@tonic-gate static int transport_retries; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * Normal sleep time when syseventconfd returns EAGAIN 1377c478bd9Sstevel@tonic-gate * is one second but to avoid thrashing, sleep for 1387c478bd9Sstevel@tonic-gate * something larger when syseventconfd not responding. 1397c478bd9Sstevel@tonic-gate * This should never happen of course but it seems better 1407c478bd9Sstevel@tonic-gate * to attempt to handle possible errors gracefully. 1417c478bd9Sstevel@tonic-gate */ 1427c478bd9Sstevel@tonic-gate static int confd_err_msg_emitted; 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate static int sysevent_conf_dummy_event(sysevent_t *, int); 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate /* 1487c478bd9Sstevel@tonic-gate * External references 1497c478bd9Sstevel@tonic-gate */ 1507c478bd9Sstevel@tonic-gate extern int debug_level; 1517c478bd9Sstevel@tonic-gate extern char *root_dir; 1527c478bd9Sstevel@tonic-gate extern void syseventd_print(int level, char *format, ...); 1537c478bd9Sstevel@tonic-gate extern void syseventd_err_print(char *format, ...); 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate static struct slm_mod_ops sysevent_conf_mod_ops = { 1587c478bd9Sstevel@tonic-gate SE_MAJOR_VERSION, /* syseventd module major version */ 1597c478bd9Sstevel@tonic-gate SE_MINOR_VERSION, /* syseventd module minor version */ 1607c478bd9Sstevel@tonic-gate SE_MAX_RETRY_LIMIT, /* max retry if EAGAIN */ 1617c478bd9Sstevel@tonic-gate &sysevent_conf_event /* event handler */ 1627c478bd9Sstevel@tonic-gate }; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate static struct slm_mod_ops sysevent_conf_dummy_mod_ops = { 1657c478bd9Sstevel@tonic-gate SE_MAJOR_VERSION, /* syseventd module major version */ 1667c478bd9Sstevel@tonic-gate SE_MINOR_VERSION, /* syseventd module minor version */ 1677c478bd9Sstevel@tonic-gate 0, /* no retries, always succeeds */ 1687c478bd9Sstevel@tonic-gate &sysevent_conf_dummy_event /* dummy event handler */ 1697c478bd9Sstevel@tonic-gate }; 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate /* 1747c478bd9Sstevel@tonic-gate * skip_spaces() - skip to next non-space character 1757c478bd9Sstevel@tonic-gate */ 1767c478bd9Sstevel@tonic-gate static char * 1777c478bd9Sstevel@tonic-gate skip_spaces(char **cpp) 1787c478bd9Sstevel@tonic-gate { 1797c478bd9Sstevel@tonic-gate char *cp = *cpp; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate while (*cp == ' ' || *cp == '\t') 1827c478bd9Sstevel@tonic-gate cp++; 1837c478bd9Sstevel@tonic-gate if (*cp == 0) { 1847c478bd9Sstevel@tonic-gate *cpp = 0; 1857c478bd9Sstevel@tonic-gate return (NULL); 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate return (cp); 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * Get next white-space separated field. 1937c478bd9Sstevel@tonic-gate * next_field() will not check any characters on next line. 1947c478bd9Sstevel@tonic-gate * Each entry is composed of a single line. 1957c478bd9Sstevel@tonic-gate */ 1967c478bd9Sstevel@tonic-gate static char * 1977c478bd9Sstevel@tonic-gate next_field(char **cpp) 1987c478bd9Sstevel@tonic-gate { 1997c478bd9Sstevel@tonic-gate char *cp = *cpp; 2007c478bd9Sstevel@tonic-gate char *start; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate while (*cp == ' ' || *cp == '\t') 2037c478bd9Sstevel@tonic-gate cp++; 2047c478bd9Sstevel@tonic-gate if (*cp == 0) { 2057c478bd9Sstevel@tonic-gate *cpp = 0; 2067c478bd9Sstevel@tonic-gate return (NULL); 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate start = cp; 2097c478bd9Sstevel@tonic-gate while (*cp && *cp != ' ' && *cp != '\t') 2107c478bd9Sstevel@tonic-gate cp++; 2117c478bd9Sstevel@tonic-gate if (*cp != 0) 2127c478bd9Sstevel@tonic-gate *cp++ = 0; 2137c478bd9Sstevel@tonic-gate *cpp = cp; 2147c478bd9Sstevel@tonic-gate return (start); 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate /* 2207c478bd9Sstevel@tonic-gate * The following functions are simple wrappers/equivalents 2217c478bd9Sstevel@tonic-gate * for malloc, realloc, free, strdup and a special free 2227c478bd9Sstevel@tonic-gate * for strdup. 2237c478bd9Sstevel@tonic-gate * 2247c478bd9Sstevel@tonic-gate * These functions ensure that any failed mallocs are 2257c478bd9Sstevel@tonic-gate * reported via syslog() so if a command is not evoked 2267c478bd9Sstevel@tonic-gate * in response to an event, the reason should be logged. 2277c478bd9Sstevel@tonic-gate * These functions also provide a convenient place for 2287c478bd9Sstevel@tonic-gate * hooks for checking for memory leaks. 2297c478bd9Sstevel@tonic-gate */ 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate static void * 2327c478bd9Sstevel@tonic-gate sc_malloc(size_t n) 2337c478bd9Sstevel@tonic-gate { 2347c478bd9Sstevel@tonic-gate void *p; 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate p = malloc(n); 2377c478bd9Sstevel@tonic-gate if (p == NULL) { 2387c478bd9Sstevel@tonic-gate syslog(LOG_ERR, OUT_OF_MEMORY_ERR); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate return (p); 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2447c478bd9Sstevel@tonic-gate static void * 2457c478bd9Sstevel@tonic-gate sc_realloc(void *p, size_t current, size_t n) 2467c478bd9Sstevel@tonic-gate { 2477c478bd9Sstevel@tonic-gate p = realloc(p, n); 2487c478bd9Sstevel@tonic-gate if (p == NULL) { 2497c478bd9Sstevel@tonic-gate syslog(LOG_ERR, OUT_OF_MEMORY_ERR); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate return (p); 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2567c478bd9Sstevel@tonic-gate static void 2577c478bd9Sstevel@tonic-gate sc_free(void *p, size_t n) 2587c478bd9Sstevel@tonic-gate { 2597c478bd9Sstevel@tonic-gate free(p); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate static char * 2647c478bd9Sstevel@tonic-gate sc_strdup(char *cp) 2657c478bd9Sstevel@tonic-gate { 2667c478bd9Sstevel@tonic-gate char *new; 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate new = malloc((unsigned)(strlen(cp) + 1)); 2697c478bd9Sstevel@tonic-gate if (new == NULL) { 2707c478bd9Sstevel@tonic-gate syslog(LOG_ERR, OUT_OF_MEMORY_ERR); 2717c478bd9Sstevel@tonic-gate return (NULL); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate (void) strcpy(new, cp); 2747c478bd9Sstevel@tonic-gate return (new); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate static void 2797c478bd9Sstevel@tonic-gate sc_strfree(char *s) 2807c478bd9Sstevel@tonic-gate { 2817c478bd9Sstevel@tonic-gate if (s) 2827c478bd9Sstevel@tonic-gate free(s); 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* 2877c478bd9Sstevel@tonic-gate * The following functions provide some simple dynamic string 2887c478bd9Sstevel@tonic-gate * capability. This module has no hard-coded maximum string 2897c478bd9Sstevel@tonic-gate * lengths and should be able to parse and generate arbitrarily 2907c478bd9Sstevel@tonic-gate * long strings, macro expansion and command lines. 2917c478bd9Sstevel@tonic-gate * 2927c478bd9Sstevel@tonic-gate * Each string must be explicitly allocated and freed. 2937c478bd9Sstevel@tonic-gate */ 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate /* 2967c478bd9Sstevel@tonic-gate * Allocate a dynamic string, with a hint to indicate how 2977c478bd9Sstevel@tonic-gate * much memory to dynamically add to the string as it grows 2987c478bd9Sstevel@tonic-gate * beyond its existing bounds, so as to avoid excessive 2997c478bd9Sstevel@tonic-gate * reallocs as a string grows. 3007c478bd9Sstevel@tonic-gate */ 3017c478bd9Sstevel@tonic-gate static str_t * 3027c478bd9Sstevel@tonic-gate initstr(int hint) 3037c478bd9Sstevel@tonic-gate { 3047c478bd9Sstevel@tonic-gate str_t *str; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate if ((str = sc_malloc(sizeof (str_t))) == NULL) 3077c478bd9Sstevel@tonic-gate return (NULL); 3087c478bd9Sstevel@tonic-gate str->s_str = NULL; 3097c478bd9Sstevel@tonic-gate str->s_len = 0; 3107c478bd9Sstevel@tonic-gate str->s_alloc = 0; 3117c478bd9Sstevel@tonic-gate str->s_hint = hint; 3127c478bd9Sstevel@tonic-gate return (str); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* 3177c478bd9Sstevel@tonic-gate * Free a dynamically-allocated string 3187c478bd9Sstevel@tonic-gate */ 3197c478bd9Sstevel@tonic-gate static void 3207c478bd9Sstevel@tonic-gate freestr(str_t *str) 3217c478bd9Sstevel@tonic-gate { 3227c478bd9Sstevel@tonic-gate if (str->s_str) { 3237c478bd9Sstevel@tonic-gate sc_free(str->s_str, str->s_alloc); 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate sc_free(str, sizeof (str_t)); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate /* 3307c478bd9Sstevel@tonic-gate * Reset a dynamically-allocated string, allows reuse 3317c478bd9Sstevel@tonic-gate * rather than freeing the old and allocating a new one. 3327c478bd9Sstevel@tonic-gate */ 3337c478bd9Sstevel@tonic-gate static void 3347c478bd9Sstevel@tonic-gate resetstr(str_t *str) 3357c478bd9Sstevel@tonic-gate { 3367c478bd9Sstevel@tonic-gate str->s_len = 0; 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate /* 3417c478bd9Sstevel@tonic-gate * Copy a (simple) string onto a dynamically-allocated string 3427c478bd9Sstevel@tonic-gate */ 3437c478bd9Sstevel@tonic-gate static int 3447c478bd9Sstevel@tonic-gate strcopys(str_t *str, char *s) 3457c478bd9Sstevel@tonic-gate { 3467c478bd9Sstevel@tonic-gate char *new_str; 3477c478bd9Sstevel@tonic-gate int len = strlen(s) + 1; 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate if (str->s_alloc < len) { 3507c478bd9Sstevel@tonic-gate new_str = (str->s_str == NULL) ? 3517c478bd9Sstevel@tonic-gate sc_malloc(len+str->s_hint) : 3527c478bd9Sstevel@tonic-gate sc_realloc(str->s_str, str->s_alloc, len+str->s_hint); 3537c478bd9Sstevel@tonic-gate if (new_str == NULL) { 3547c478bd9Sstevel@tonic-gate return (1); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate str->s_str = new_str; 3577c478bd9Sstevel@tonic-gate str->s_alloc = len + str->s_hint; 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate (void) strcpy(str->s_str, s); 3607c478bd9Sstevel@tonic-gate str->s_len = len - 1; 3617c478bd9Sstevel@tonic-gate return (0); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate /* 3667c478bd9Sstevel@tonic-gate * Concatenate a (simple) string onto a dynamically-allocated string 3677c478bd9Sstevel@tonic-gate */ 3687c478bd9Sstevel@tonic-gate static int 3697c478bd9Sstevel@tonic-gate strcats(str_t *str, char *s) 3707c478bd9Sstevel@tonic-gate { 3717c478bd9Sstevel@tonic-gate char *new_str; 3727c478bd9Sstevel@tonic-gate int len = str->s_len + strlen(s) + 1; 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate if (str->s_alloc < len) { 3757c478bd9Sstevel@tonic-gate new_str = (str->s_str == NULL) ? sc_malloc(len+str->s_hint) : 3767c478bd9Sstevel@tonic-gate sc_realloc(str->s_str, str->s_alloc, len+str->s_hint); 3777c478bd9Sstevel@tonic-gate if (new_str == NULL) { 3787c478bd9Sstevel@tonic-gate return (1); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate str->s_str = new_str; 3817c478bd9Sstevel@tonic-gate str->s_alloc = len + str->s_hint; 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate (void) strcpy(str->s_str + str->s_len, s); 3847c478bd9Sstevel@tonic-gate str->s_len = len - 1; 3857c478bd9Sstevel@tonic-gate return (0); 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate /* 3907c478bd9Sstevel@tonic-gate * Concatenate a character onto a dynamically-allocated string 3917c478bd9Sstevel@tonic-gate */ 3927c478bd9Sstevel@tonic-gate static int 3937c478bd9Sstevel@tonic-gate strcatc(str_t *str, int c) 3947c478bd9Sstevel@tonic-gate { 3957c478bd9Sstevel@tonic-gate char *new_str; 3967c478bd9Sstevel@tonic-gate int len = str->s_len + 2; 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate if (str->s_alloc < len) { 3997c478bd9Sstevel@tonic-gate new_str = (str->s_str == NULL) ? sc_malloc(len+str->s_hint) : 4007c478bd9Sstevel@tonic-gate sc_realloc(str->s_str, str->s_alloc, len+str->s_hint); 4017c478bd9Sstevel@tonic-gate if (new_str == NULL) { 4027c478bd9Sstevel@tonic-gate return (1); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate str->s_str = new_str; 4057c478bd9Sstevel@tonic-gate str->s_alloc = len + str->s_hint; 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate *(str->s_str + str->s_len) = (char)c; 4087c478bd9Sstevel@tonic-gate *(str->s_str + str->s_len + 1) = 0; 4097c478bd9Sstevel@tonic-gate str->s_len++; 4107c478bd9Sstevel@tonic-gate return (0); 4117c478bd9Sstevel@tonic-gate } 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate /* 4147c478bd9Sstevel@tonic-gate * fgets() equivalent using a dynamically-allocated string 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate static char * 4177c478bd9Sstevel@tonic-gate fstrgets(str_t *line, FILE *fp) 4187c478bd9Sstevel@tonic-gate { 4197c478bd9Sstevel@tonic-gate int c; 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate resetstr(line); 4227c478bd9Sstevel@tonic-gate while ((c = fgetc(fp)) != EOF) { 4237c478bd9Sstevel@tonic-gate if (strcatc(line, c)) 4247c478bd9Sstevel@tonic-gate return (NULL); 4257c478bd9Sstevel@tonic-gate if (c == '\n') 4267c478bd9Sstevel@tonic-gate break; 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate if (line->s_len == 0) 4297c478bd9Sstevel@tonic-gate return (NULL); 4307c478bd9Sstevel@tonic-gate return (line->s_str); 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate /* 4347c478bd9Sstevel@tonic-gate * Truncate a dynamically-allocated string at index position 'pos' 4357c478bd9Sstevel@tonic-gate */ 4367c478bd9Sstevel@tonic-gate static void 4377c478bd9Sstevel@tonic-gate strtrunc(str_t *str, int pos) 4387c478bd9Sstevel@tonic-gate { 4397c478bd9Sstevel@tonic-gate if (str->s_len > pos) { 4407c478bd9Sstevel@tonic-gate str->s_len = pos; 4417c478bd9Sstevel@tonic-gate *(str->s_str + pos) = 0; 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate /* 4487c478bd9Sstevel@tonic-gate * Parse a sysevent.conf file, adding each entry spec to the event table. 4497c478bd9Sstevel@tonic-gate * 4507c478bd9Sstevel@tonic-gate * The format of an entry in a sysevent.conf file is: 4517c478bd9Sstevel@tonic-gate * 4527c478bd9Sstevel@tonic-gate * class subclass vendor publisher user reserved1 reserved path arguments 4537c478bd9Sstevel@tonic-gate * 4547c478bd9Sstevel@tonic-gate * Fields are separated by either SPACE or TAB characters. A 4557c478bd9Sstevel@tonic-gate * '#' (number sign) at the beginning of a line indicates a 4567c478bd9Sstevel@tonic-gate * comment. Comment lines and blank lines are ignored. 4577c478bd9Sstevel@tonic-gate * 4587c478bd9Sstevel@tonic-gate * class 4597c478bd9Sstevel@tonic-gate * The class of the event. 4607c478bd9Sstevel@tonic-gate * 4617c478bd9Sstevel@tonic-gate * subclass 4627c478bd9Sstevel@tonic-gate * The subclass of the event. 4637c478bd9Sstevel@tonic-gate * 4647c478bd9Sstevel@tonic-gate * vendor 4657c478bd9Sstevel@tonic-gate * The name of the vendor defining the event, usually the 4667c478bd9Sstevel@tonic-gate * stock symbol. Events generated by system components 4677c478bd9Sstevel@tonic-gate * provided by Sun Microsystems, Inc. always define vendor 4687c478bd9Sstevel@tonic-gate * as 'SUNW'. 4697c478bd9Sstevel@tonic-gate * 4707c478bd9Sstevel@tonic-gate * publisher 4717c478bd9Sstevel@tonic-gate * The name of the application, driver or system module 4727c478bd9Sstevel@tonic-gate * producing the event. 4737c478bd9Sstevel@tonic-gate * 4747c478bd9Sstevel@tonic-gate * user 4757c478bd9Sstevel@tonic-gate * The name of the user under which the command should be 4767c478bd9Sstevel@tonic-gate * run. This allows commands to run with access privileges 4777c478bd9Sstevel@tonic-gate * other than those for root. The user field should be '-' 4787c478bd9Sstevel@tonic-gate * for commands to be run as root. 4797c478bd9Sstevel@tonic-gate * 4807c478bd9Sstevel@tonic-gate * reserved1 4817c478bd9Sstevel@tonic-gate * Must be '-'. 4827c478bd9Sstevel@tonic-gate * 4837c478bd9Sstevel@tonic-gate * reserved2 4847c478bd9Sstevel@tonic-gate * Must be '-'. 4857c478bd9Sstevel@tonic-gate * 4867c478bd9Sstevel@tonic-gate * path 4877c478bd9Sstevel@tonic-gate * Pathname of the command to be invoked for matching events. 4887c478bd9Sstevel@tonic-gate * 4897c478bd9Sstevel@tonic-gate * arguments 4907c478bd9Sstevel@tonic-gate * Optional argument with possible macro substitution to permit 4917c478bd9Sstevel@tonic-gate * arbitrary command line construction with event-specific data. 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate static void 4947c478bd9Sstevel@tonic-gate parse_conf_file(char *conf_file) 4957c478bd9Sstevel@tonic-gate { 4967c478bd9Sstevel@tonic-gate char conf_path[PATH_MAX]; 4977c478bd9Sstevel@tonic-gate FILE *fp; 4987c478bd9Sstevel@tonic-gate char *lp; 4997c478bd9Sstevel@tonic-gate str_t *line; 5007c478bd9Sstevel@tonic-gate int lineno = 0; 5017c478bd9Sstevel@tonic-gate char *vendor, *publisher; 5027c478bd9Sstevel@tonic-gate char *class, *subclass; 5037c478bd9Sstevel@tonic-gate char *user; 5047c478bd9Sstevel@tonic-gate char *reserved1, *reserved2; 5057c478bd9Sstevel@tonic-gate char *path, *args; 5067c478bd9Sstevel@tonic-gate syseventtab_t *sep; 5077c478bd9Sstevel@tonic-gate struct passwd pwd; 5087c478bd9Sstevel@tonic-gate struct passwd *pwdp; 5097c478bd9Sstevel@tonic-gate char pwdbuf[1024]; 5107c478bd9Sstevel@tonic-gate int do_setuid; 5117c478bd9Sstevel@tonic-gate pid_t saved_uid; 5127c478bd9Sstevel@tonic-gate gid_t saved_gid; 5137c478bd9Sstevel@tonic-gate int i, err; 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate (void) snprintf(conf_path, PATH_MAX, "%s/%s", 5167c478bd9Sstevel@tonic-gate SYSEVENT_CONFIG_DIR, conf_file); 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate syseventd_print(DBG_CONF_FILE, "%s: reading %s\n", whoami, conf_path); 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate if ((fp = fopen(conf_path, "r")) == NULL) { 5217c478bd9Sstevel@tonic-gate syslog(LOG_ERR, CANNOT_OPEN_ERR, conf_file, strerror(errno)); 5227c478bd9Sstevel@tonic-gate return; 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate if ((line = initstr(128)) == NULL) 5267c478bd9Sstevel@tonic-gate return; 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate while ((lp = fstrgets(line, fp)) != NULL) { 5297c478bd9Sstevel@tonic-gate lineno++; 5307c478bd9Sstevel@tonic-gate if (*lp == '\n' || *lp == '#') 5317c478bd9Sstevel@tonic-gate continue; 5327c478bd9Sstevel@tonic-gate *(lp + strlen(lp)-1) = 0; 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate syseventd_print(DBG_CONF_FILE, "[%d]: %s\n", 5357c478bd9Sstevel@tonic-gate lineno, lp); 5367c478bd9Sstevel@tonic-gate 537*3e11238aSjg if ((class = next_field(&lp)) == NULL) 538*3e11238aSjg goto mal_formed; 539*3e11238aSjg if ((subclass = next_field(&lp)) == NULL) 540*3e11238aSjg goto mal_formed; 541*3e11238aSjg if ((vendor = next_field(&lp)) == NULL) 542*3e11238aSjg goto mal_formed; 543*3e11238aSjg if ((publisher = next_field(&lp)) == NULL) 544*3e11238aSjg goto mal_formed; 545*3e11238aSjg if ((user = next_field(&lp)) == NULL) 546*3e11238aSjg goto mal_formed; 547*3e11238aSjg if ((reserved1 = next_field(&lp)) == NULL) 548*3e11238aSjg goto mal_formed; 549*3e11238aSjg if ((reserved2 = next_field(&lp)) == NULL) 550*3e11238aSjg goto mal_formed; 551*3e11238aSjg if ((path = next_field(&lp)) == NULL) 552*3e11238aSjg goto mal_formed; 553*3e11238aSjg args = skip_spaces(&lp); 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate /* 5567c478bd9Sstevel@tonic-gate * validate user 5577c478bd9Sstevel@tonic-gate */ 5587c478bd9Sstevel@tonic-gate do_setuid = 0; 5597c478bd9Sstevel@tonic-gate if ((strcmp(user, "-") != 0) && (strcmp(user, "root") != 0)) { 5607c478bd9Sstevel@tonic-gate i = getpwnam_r(user, &pwd, pwdbuf, 5617c478bd9Sstevel@tonic-gate sizeof (pwdbuf), &pwdp); 5627c478bd9Sstevel@tonic-gate if (i != 0 || pwdp == NULL) { 5637c478bd9Sstevel@tonic-gate syslog(LOG_ERR, NO_USER_ERR, 5647c478bd9Sstevel@tonic-gate conf_file, lineno, user); 5657c478bd9Sstevel@tonic-gate continue; 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate do_setuid = 1; 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate /* 5717c478bd9Sstevel@tonic-gate * validate reserved fields 5727c478bd9Sstevel@tonic-gate */ 5737c478bd9Sstevel@tonic-gate if (strcmp(reserved1, "-") != 0) { 5747c478bd9Sstevel@tonic-gate syslog(LOG_ERR, RESERVED_FIELD_ERR, 5757c478bd9Sstevel@tonic-gate conf_file, lineno, reserved1); 5767c478bd9Sstevel@tonic-gate continue; 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate if (strcmp(reserved2, "-") != 0) { 5797c478bd9Sstevel@tonic-gate syslog(LOG_ERR, RESERVED_FIELD_ERR, 5807c478bd9Sstevel@tonic-gate conf_file, lineno, reserved2); 5817c478bd9Sstevel@tonic-gate continue; 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate /* 5857c478bd9Sstevel@tonic-gate * ensure path is executable by user 5867c478bd9Sstevel@tonic-gate */ 5877c478bd9Sstevel@tonic-gate err = 0; 5887c478bd9Sstevel@tonic-gate if (do_setuid) { 5897c478bd9Sstevel@tonic-gate saved_uid = getuid(); 5907c478bd9Sstevel@tonic-gate saved_gid = getgid(); 5917c478bd9Sstevel@tonic-gate if (setregid(pwdp->pw_gid, -1) == -1) { 5927c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SETREGID_ERR, 5937c478bd9Sstevel@tonic-gate whoami, pwdp->pw_gid, strerror(errno)); 5947c478bd9Sstevel@tonic-gate err = -1; 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate if (setreuid(pwdp->pw_uid, -1) == -1) { 5977c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SETREUID_ERR, 5987c478bd9Sstevel@tonic-gate whoami, pwdp->pw_uid, strerror(errno)); 5997c478bd9Sstevel@tonic-gate err = -1; 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate if ((i = access(path, X_OK)) == -1) { 6037c478bd9Sstevel@tonic-gate syslog(LOG_ERR, CANNOT_EXECUTE_ERR, 6047c478bd9Sstevel@tonic-gate conf_file, lineno, path, strerror(errno)); 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate if (do_setuid) { 6077c478bd9Sstevel@tonic-gate if (setreuid(saved_uid, -1) == -1) { 6087c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SETREUID_ERR, 6097c478bd9Sstevel@tonic-gate whoami, saved_uid, strerror(errno)); 6107c478bd9Sstevel@tonic-gate err = -1; 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate if (setregid(saved_gid, -1) == -1) { 6137c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SETREGID_ERR, 6147c478bd9Sstevel@tonic-gate whoami, saved_gid, strerror(errno)); 6157c478bd9Sstevel@tonic-gate err = -1; 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate if (i == -1 || err == -1) 6197c478bd9Sstevel@tonic-gate continue; 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate /* 6227c478bd9Sstevel@tonic-gate * all sanity tests successful - perform allocations 6237c478bd9Sstevel@tonic-gate * to add entry to table 6247c478bd9Sstevel@tonic-gate */ 6257c478bd9Sstevel@tonic-gate if ((sep = sc_malloc(sizeof (syseventtab_t))) == NULL) 6267c478bd9Sstevel@tonic-gate break; 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate sep->se_conf_file = conf_file; 6297c478bd9Sstevel@tonic-gate sep->se_lineno = lineno; 6307c478bd9Sstevel@tonic-gate sep->se_vendor = sc_strdup(vendor); 6317c478bd9Sstevel@tonic-gate sep->se_publisher = sc_strdup(publisher); 6327c478bd9Sstevel@tonic-gate sep->se_class = sc_strdup(class); 6337c478bd9Sstevel@tonic-gate sep->se_subclass = sc_strdup(subclass); 6347c478bd9Sstevel@tonic-gate sep->se_user = sc_strdup(user); 6357c478bd9Sstevel@tonic-gate if (do_setuid) { 6367c478bd9Sstevel@tonic-gate sep->se_uid = pwdp->pw_uid; 6377c478bd9Sstevel@tonic-gate sep->se_gid = pwdp->pw_gid; 6387c478bd9Sstevel@tonic-gate } else { 6397c478bd9Sstevel@tonic-gate sep->se_uid = 0; 6407c478bd9Sstevel@tonic-gate sep->se_gid = 0; 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate sep->se_reserved1 = sc_strdup(reserved1); 6437c478bd9Sstevel@tonic-gate sep->se_reserved2 = sc_strdup(reserved2); 6447c478bd9Sstevel@tonic-gate sep->se_path = sc_strdup(path); 6457c478bd9Sstevel@tonic-gate sep->se_args = (args == NULL) ? NULL : sc_strdup(args); 6467c478bd9Sstevel@tonic-gate sep->se_next = NULL; 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate if (sep->se_vendor == NULL || sep->se_publisher == NULL || 6497c478bd9Sstevel@tonic-gate sep->se_class == NULL || sep->se_subclass == NULL || 6507c478bd9Sstevel@tonic-gate sep->se_user == NULL || sep->se_reserved1 == NULL || 6517c478bd9Sstevel@tonic-gate sep->se_reserved2 == NULL || sep->se_path == NULL || 6527c478bd9Sstevel@tonic-gate (args && sep->se_args == NULL)) { 6537c478bd9Sstevel@tonic-gate sc_strfree(sep->se_vendor); 6547c478bd9Sstevel@tonic-gate sc_strfree(sep->se_publisher); 6557c478bd9Sstevel@tonic-gate sc_strfree(sep->se_class); 6567c478bd9Sstevel@tonic-gate sc_strfree(sep->se_subclass); 6577c478bd9Sstevel@tonic-gate sc_strfree(sep->se_user); 6587c478bd9Sstevel@tonic-gate sc_strfree(sep->se_reserved1); 6597c478bd9Sstevel@tonic-gate sc_strfree(sep->se_reserved2); 6607c478bd9Sstevel@tonic-gate sc_strfree(sep->se_path); 6617c478bd9Sstevel@tonic-gate sc_strfree(sep->se_args); 6627c478bd9Sstevel@tonic-gate sc_free(sep, sizeof (syseventtab_t)); 6637c478bd9Sstevel@tonic-gate break; 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate /* 6677c478bd9Sstevel@tonic-gate * link new entry into the table 6687c478bd9Sstevel@tonic-gate */ 6697c478bd9Sstevel@tonic-gate if (syseventtab == NULL) { 6707c478bd9Sstevel@tonic-gate syseventtab = sep; 6717c478bd9Sstevel@tonic-gate syseventtab_tail = sep; 6727c478bd9Sstevel@tonic-gate } else { 6737c478bd9Sstevel@tonic-gate syseventtab_tail->se_next = sep; 6747c478bd9Sstevel@tonic-gate syseventtab_tail = sep; 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate if (debug_level >= DBG_DETAILED) { 6787c478bd9Sstevel@tonic-gate syseventtab_t *sp; 6797c478bd9Sstevel@tonic-gate for (sp = syseventtab; sp; sp = sp->se_next) { 6807c478bd9Sstevel@tonic-gate syseventd_print(DBG_DETAILED, 6817c478bd9Sstevel@tonic-gate " vendor=%s\n", sp->se_vendor); 6827c478bd9Sstevel@tonic-gate syseventd_print(DBG_DETAILED, 6837c478bd9Sstevel@tonic-gate " publisher=%s\n", sp->se_publisher); 6847c478bd9Sstevel@tonic-gate syseventd_print(DBG_DETAILED, 6857c478bd9Sstevel@tonic-gate " class=%s\n", sp->se_class); 6867c478bd9Sstevel@tonic-gate syseventd_print(DBG_DETAILED, 6877c478bd9Sstevel@tonic-gate " subclass=%s\n", sp->se_subclass); 6887c478bd9Sstevel@tonic-gate syseventd_print(DBG_DETAILED, 6897c478bd9Sstevel@tonic-gate " user=%s uid=%d gid=%d\n", 6907c478bd9Sstevel@tonic-gate sp->se_user, sp->se_uid, sp->se_gid); 6917c478bd9Sstevel@tonic-gate syseventd_print(DBG_DETAILED, 6927c478bd9Sstevel@tonic-gate " reserved1=%s\n", sp->se_reserved1); 6937c478bd9Sstevel@tonic-gate syseventd_print(DBG_DETAILED, 6947c478bd9Sstevel@tonic-gate " reserved2=%s\n", sp->se_reserved2); 6957c478bd9Sstevel@tonic-gate syseventd_print(DBG_DETAILED, 6967c478bd9Sstevel@tonic-gate " path=%s\n", sp->se_path); 6977c478bd9Sstevel@tonic-gate if (sp->se_args != NULL) { 6987c478bd9Sstevel@tonic-gate syseventd_print(DBG_DETAILED, 6997c478bd9Sstevel@tonic-gate " args=%s\n", sp->se_args); 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate continue; 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate mal_formed: 7077c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SYNTAX_ERR, conf_file, lineno); 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate freestr(line); 7117c478bd9Sstevel@tonic-gate (void) fclose(fp); 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate /* 7167c478bd9Sstevel@tonic-gate * Build the events specification table, a summation of all 7177c478bd9Sstevel@tonic-gate * event specification found in the installed sysevent.conf 7187c478bd9Sstevel@tonic-gate * configuration files. 7197c478bd9Sstevel@tonic-gate * 7207c478bd9Sstevel@tonic-gate * All sysevent.conf files reside in the /etc/sysevent/config 7217c478bd9Sstevel@tonic-gate * and may contain zero or more event/command specifications. 7227c478bd9Sstevel@tonic-gate * A sysevent.conf file should be named as follows: 7237c478bd9Sstevel@tonic-gate * 7247c478bd9Sstevel@tonic-gate * <vendor>,[<publisher>,][<class>,]sysevent.conf 7257c478bd9Sstevel@tonic-gate * 7267c478bd9Sstevel@tonic-gate * Event/command specifications delivered by the base Solaris 7277c478bd9Sstevel@tonic-gate * system are provided in /etc/sysevent/config/SUNW,sysevent.conf. 7287c478bd9Sstevel@tonic-gate * Event/command specifications delivered by optional 7297c478bd9Sstevel@tonic-gate * Sun-supplied packages may install additional sysevent.conf 7307c478bd9Sstevel@tonic-gate * files in /etc/sysevent/config using vendor SUNW, and additional 7317c478bd9Sstevel@tonic-gate * publisher and/or event class naming to distinguish the 7327c478bd9Sstevel@tonic-gate * events required for those products. Products provided 7337c478bd9Sstevel@tonic-gate * by third-party hardware or software companies may 7347c478bd9Sstevel@tonic-gate * distinguish their sysevent.conf files by vendor, and 7357c478bd9Sstevel@tonic-gate * by publisher and/or event class within vendor. 7367c478bd9Sstevel@tonic-gate * 7377c478bd9Sstevel@tonic-gate * Files residing in /etc/sysevent/config with a '.' (period) 7387c478bd9Sstevel@tonic-gate * as the first character of the name and files with a suffix 7397c478bd9Sstevel@tonic-gate * of other than "sysevent.conf" are ignored. 7407c478bd9Sstevel@tonic-gate */ 7417c478bd9Sstevel@tonic-gate static void 7427c478bd9Sstevel@tonic-gate build_event_table() 7437c478bd9Sstevel@tonic-gate { 7447c478bd9Sstevel@tonic-gate conftab_t *cfp = NULL; 7457c478bd9Sstevel@tonic-gate DIR *dir; 7467c478bd9Sstevel@tonic-gate struct dirent *result; 7477c478bd9Sstevel@tonic-gate conftab_t *new_cfp; 7487c478bd9Sstevel@tonic-gate char *str; 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate if ((dir = opendir(SYSEVENT_CONFIG_DIR)) == NULL) { 7517c478bd9Sstevel@tonic-gate syslog(LOG_ERR, CANNOT_OPEN_ERR, 7527c478bd9Sstevel@tonic-gate SYSEVENT_CONFIG_DIR, strerror(errno)); 7537c478bd9Sstevel@tonic-gate return; 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate 7564bc0a2efScasper while ((result = readdir(dir)) != NULL) { 7577c478bd9Sstevel@tonic-gate if (result->d_name[0] == '.') 7587c478bd9Sstevel@tonic-gate continue; 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate /* 7617c478bd9Sstevel@tonic-gate * file must have extension "sysevent.conf" 7627c478bd9Sstevel@tonic-gate */ 7637c478bd9Sstevel@tonic-gate if ((str = strrchr(result->d_name, ',')) != NULL) { 7647c478bd9Sstevel@tonic-gate str++; 7657c478bd9Sstevel@tonic-gate } else { 7667c478bd9Sstevel@tonic-gate str = result->d_name; 7677c478bd9Sstevel@tonic-gate } 7687c478bd9Sstevel@tonic-gate if (strcmp(str, "sysevent.conf") != 0) { 7697c478bd9Sstevel@tonic-gate syseventd_print(DBG_CONF_FILE, 7707c478bd9Sstevel@tonic-gate "%s: ignoring %s\n", whoami, str); 7717c478bd9Sstevel@tonic-gate continue; 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate /* 7757c478bd9Sstevel@tonic-gate * Add to file table and parse this conf file 7767c478bd9Sstevel@tonic-gate */ 7777c478bd9Sstevel@tonic-gate if ((str = sc_strdup(result->d_name)) == NULL) 7787c478bd9Sstevel@tonic-gate goto err; 7797c478bd9Sstevel@tonic-gate if ((new_cfp = sc_malloc(sizeof (conftab_t))) == NULL) { 7807c478bd9Sstevel@tonic-gate sc_strfree(str); 7817c478bd9Sstevel@tonic-gate goto err; 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate if (conftab == NULL) { 7847c478bd9Sstevel@tonic-gate conftab = new_cfp; 7857c478bd9Sstevel@tonic-gate } else { 7867c478bd9Sstevel@tonic-gate for (cfp = conftab; cfp->cf_next; cfp = cfp->cf_next) 7877c478bd9Sstevel@tonic-gate ; 7887c478bd9Sstevel@tonic-gate cfp->cf_next = new_cfp; 7897c478bd9Sstevel@tonic-gate } 7907c478bd9Sstevel@tonic-gate cfp = new_cfp; 7917c478bd9Sstevel@tonic-gate cfp->cf_conf_file = str; 7927c478bd9Sstevel@tonic-gate cfp->cf_next = NULL; 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate parse_conf_file(cfp->cf_conf_file); 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate err: 7987c478bd9Sstevel@tonic-gate if (closedir(dir) == -1) { 7997c478bd9Sstevel@tonic-gate if (errno == EAGAIN) 8007c478bd9Sstevel@tonic-gate goto err; 8017c478bd9Sstevel@tonic-gate syslog(LOG_ERR, CLOSEDIR_ERR, 8027c478bd9Sstevel@tonic-gate SYSEVENT_CONFIG_DIR, strerror(errno)); 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate } 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate static int 8087c478bd9Sstevel@tonic-gate enter_lock(char *lock_file) 8097c478bd9Sstevel@tonic-gate { 8107c478bd9Sstevel@tonic-gate struct flock lock; 8117c478bd9Sstevel@tonic-gate int lock_fd; 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate (void) snprintf(lock_file, PATH_MAX, "%s/%s", 8147c478bd9Sstevel@tonic-gate SYSEVENT_CONFIG_DIR, LOCK_FILENAME); 8157c478bd9Sstevel@tonic-gate lock_fd = open(lock_file, O_CREAT|O_RDWR, 0644); 8167c478bd9Sstevel@tonic-gate if (lock_fd < 0) { 8177c478bd9Sstevel@tonic-gate syslog(LOG_ERR, MSG_LOCK_CREATE_ERR, 8187c478bd9Sstevel@tonic-gate whoami, lock_file, strerror(errno)); 8197c478bd9Sstevel@tonic-gate return (-1); 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate lock.l_type = F_WRLCK; 8237c478bd9Sstevel@tonic-gate lock.l_whence = SEEK_SET; 8247c478bd9Sstevel@tonic-gate lock.l_start = 0; 8257c478bd9Sstevel@tonic-gate lock.l_len = 0; 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate retry: 8287c478bd9Sstevel@tonic-gate if (fcntl(lock_fd, F_SETLKW, &lock) == -1) { 8297c478bd9Sstevel@tonic-gate if (errno == EAGAIN || errno == EINTR) 8307c478bd9Sstevel@tonic-gate goto retry; 8317c478bd9Sstevel@tonic-gate (void) close(lock_fd); 8327c478bd9Sstevel@tonic-gate syslog(LOG_ERR, MSG_LOCK_SET_ERR, 8337c478bd9Sstevel@tonic-gate whoami, lock_file, strerror(errno)); 8347c478bd9Sstevel@tonic-gate return (-1); 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate return (lock_fd); 8387c478bd9Sstevel@tonic-gate } 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate static void 8427c478bd9Sstevel@tonic-gate exit_lock(int lock_fd, char *lock_file) 8437c478bd9Sstevel@tonic-gate { 8447c478bd9Sstevel@tonic-gate struct flock lock; 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate lock.l_type = F_UNLCK; 8477c478bd9Sstevel@tonic-gate lock.l_whence = SEEK_SET; 8487c478bd9Sstevel@tonic-gate lock.l_start = 0; 8497c478bd9Sstevel@tonic-gate lock.l_len = 0; 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate if (fcntl(lock_fd, F_SETLK, &lock) == -1) { 8527c478bd9Sstevel@tonic-gate syslog(LOG_ERR, MSG_LOCK_CLR_ERR, 8537c478bd9Sstevel@tonic-gate whoami, lock_file, strerror(errno)); 8547c478bd9Sstevel@tonic-gate } 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate if (close(lock_fd) == -1) { 8577c478bd9Sstevel@tonic-gate syslog(LOG_ERR, MSG_LOCK_CLOSE_ERR, 8587c478bd9Sstevel@tonic-gate whoami, lock_file, strerror(errno)); 8597c478bd9Sstevel@tonic-gate } 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate /* 8647c478bd9Sstevel@tonic-gate * Free the events specification table, constructed by 8657c478bd9Sstevel@tonic-gate * parsing all the sysevent.conf files found. 8667c478bd9Sstevel@tonic-gate * 8677c478bd9Sstevel@tonic-gate * The free of this table is in response to a HUP 8687c478bd9Sstevel@tonic-gate * given to the syseventd daemon, permitting the 8697c478bd9Sstevel@tonic-gate * table to be rebuilt after adding a new sysevent.conf 8707c478bd9Sstevel@tonic-gate * file or changing an existing one without shutting 8717c478bd9Sstevel@tonic-gate * down the daemon. 8727c478bd9Sstevel@tonic-gate */ 8737c478bd9Sstevel@tonic-gate static void 8747c478bd9Sstevel@tonic-gate free_event_table() 8757c478bd9Sstevel@tonic-gate { 8767c478bd9Sstevel@tonic-gate syseventtab_t *sep; 8777c478bd9Sstevel@tonic-gate syseventtab_t *sep_next; 8787c478bd9Sstevel@tonic-gate conftab_t *cfp; 8797c478bd9Sstevel@tonic-gate conftab_t *cfp_next; 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate sep = syseventtab; 8827c478bd9Sstevel@tonic-gate while (sep) { 8837c478bd9Sstevel@tonic-gate sc_strfree(sep->se_vendor); 8847c478bd9Sstevel@tonic-gate sc_strfree(sep->se_publisher); 8857c478bd9Sstevel@tonic-gate sc_strfree(sep->se_class); 8867c478bd9Sstevel@tonic-gate sc_strfree(sep->se_subclass); 8877c478bd9Sstevel@tonic-gate sc_strfree(sep->se_user); 8887c478bd9Sstevel@tonic-gate sc_strfree(sep->se_reserved1); 8897c478bd9Sstevel@tonic-gate sc_strfree(sep->se_reserved2); 8907c478bd9Sstevel@tonic-gate sc_strfree(sep->se_path); 8917c478bd9Sstevel@tonic-gate if (sep->se_args) 8927c478bd9Sstevel@tonic-gate sc_strfree(sep->se_args); 8937c478bd9Sstevel@tonic-gate sep_next = sep->se_next; 8947c478bd9Sstevel@tonic-gate sc_free(sep, sizeof (syseventtab_t)); 8957c478bd9Sstevel@tonic-gate sep = sep_next; 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate syseventtab = NULL; 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate cfp = conftab; 9007c478bd9Sstevel@tonic-gate while (cfp) { 9017c478bd9Sstevel@tonic-gate sc_strfree(cfp->cf_conf_file); 9027c478bd9Sstevel@tonic-gate cfp_next = cfp->cf_next; 9037c478bd9Sstevel@tonic-gate sc_free(cfp, sizeof (conftab_t)); 9047c478bd9Sstevel@tonic-gate cfp = cfp_next; 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate conftab = NULL; 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate static char ident_chars[] = "_"; 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate /* 9147c478bd9Sstevel@tonic-gate * Return a dynamically-allocated string containing the 9157c478bd9Sstevel@tonic-gate * the next identifier in the string being parsed, pointed 9167c478bd9Sstevel@tonic-gate * at by 'id'. 'end' returns a pointer to the character 9177c478bd9Sstevel@tonic-gate * after the identifier. 9187c478bd9Sstevel@tonic-gate * 9197c478bd9Sstevel@tonic-gate * Identifiers are all alphanumeric ascii characters and 9207c478bd9Sstevel@tonic-gate * those contained in ident_chars. 9217c478bd9Sstevel@tonic-gate * 9227c478bd9Sstevel@tonic-gate * The returned string must be explicitly freed via 9237c478bd9Sstevel@tonic-gate * freestr(). 9247c478bd9Sstevel@tonic-gate */ 9257c478bd9Sstevel@tonic-gate static str_t * 9267c478bd9Sstevel@tonic-gate snip_identifier(char *id, char **end) 9277c478bd9Sstevel@tonic-gate { 9287c478bd9Sstevel@tonic-gate str_t *token; 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate if ((token = initstr(32)) == NULL) 9317c478bd9Sstevel@tonic-gate return (NULL); 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate while (*id != 0) { 9347c478bd9Sstevel@tonic-gate if (isascii(*id) && 9357c478bd9Sstevel@tonic-gate (isalnum(*id) || strchr(ident_chars, *id) != NULL)) { 9367c478bd9Sstevel@tonic-gate if (strcatc(token, *id++)) { 9377c478bd9Sstevel@tonic-gate freestr(token); 9387c478bd9Sstevel@tonic-gate return (NULL); 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate } else { 9417c478bd9Sstevel@tonic-gate *end = id; 9427c478bd9Sstevel@tonic-gate return (token); 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate } 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate *end = id; 9477c478bd9Sstevel@tonic-gate return (token); 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate /* 9527c478bd9Sstevel@tonic-gate * Identical to snip_identifier(), but the identifier 9537c478bd9Sstevel@tonic-gate * is delimited by the characters { and }. 9547c478bd9Sstevel@tonic-gate */ 9557c478bd9Sstevel@tonic-gate static str_t * 9567c478bd9Sstevel@tonic-gate snip_delimited_identifier(char *id, char **end) 9577c478bd9Sstevel@tonic-gate { 9587c478bd9Sstevel@tonic-gate str_t *token; 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate if ((token = initstr(32)) == NULL) 9617c478bd9Sstevel@tonic-gate return (NULL); 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate while (*id != 0) { 9647c478bd9Sstevel@tonic-gate if (*id == '}') { 9657c478bd9Sstevel@tonic-gate *end = id+1; 9667c478bd9Sstevel@tonic-gate return (token); 9677c478bd9Sstevel@tonic-gate } 9687c478bd9Sstevel@tonic-gate if (strcatc(token, *id++)) { 9697c478bd9Sstevel@tonic-gate freestr(token); 9707c478bd9Sstevel@tonic-gate return (NULL); 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate if (*id == 0) { 9757c478bd9Sstevel@tonic-gate freestr(token); 9767c478bd9Sstevel@tonic-gate return (NULL); 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate *end = id; 9807c478bd9Sstevel@tonic-gate return (token); 9817c478bd9Sstevel@tonic-gate } 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate /* 9857c478bd9Sstevel@tonic-gate * Return a string with the name of the attribute type 9867c478bd9Sstevel@tonic-gate */ 9877c478bd9Sstevel@tonic-gate static char *nv_attr_type_strings[] = { 9887c478bd9Sstevel@tonic-gate "unknown", 9897c478bd9Sstevel@tonic-gate "boolean", 9907c478bd9Sstevel@tonic-gate "byte", 9917c478bd9Sstevel@tonic-gate "int16", 9927c478bd9Sstevel@tonic-gate "uint16", 9937c478bd9Sstevel@tonic-gate "int32", 9947c478bd9Sstevel@tonic-gate "uint32", 9957c478bd9Sstevel@tonic-gate "int64", 9967c478bd9Sstevel@tonic-gate "uint64", 9977c478bd9Sstevel@tonic-gate "string", 9987c478bd9Sstevel@tonic-gate "byte-array", 9997c478bd9Sstevel@tonic-gate "int16-array", 10007c478bd9Sstevel@tonic-gate "uint16-array", 10017c478bd9Sstevel@tonic-gate "int32-array", 10027c478bd9Sstevel@tonic-gate "uint32-array", 10037c478bd9Sstevel@tonic-gate "int64-array", 10047c478bd9Sstevel@tonic-gate "uint64-array", 10057c478bd9Sstevel@tonic-gate "string-array", 10067c478bd9Sstevel@tonic-gate "hrtime" 10077c478bd9Sstevel@tonic-gate }; 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate static char * 10107c478bd9Sstevel@tonic-gate se_attr_type_to_str(int se_attr_type) 10117c478bd9Sstevel@tonic-gate { 10127c478bd9Sstevel@tonic-gate if (se_attr_type >= 0 && 10137c478bd9Sstevel@tonic-gate se_attr_type < sizeof (nv_attr_type_strings) / sizeof (char *)) { 10147c478bd9Sstevel@tonic-gate return (nv_attr_type_strings[se_attr_type]); 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate return (nv_attr_type_strings[DATA_TYPE_UNKNOWN]); 10177c478bd9Sstevel@tonic-gate } 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate /* 10217c478bd9Sstevel@tonic-gate * Find and return the data matching the macro name 'token' 10227c478bd9Sstevel@tonic-gate * 10237c478bd9Sstevel@tonic-gate * Predefined macros are simply substituted with the 10247c478bd9Sstevel@tonic-gate * data from the event header: 10257c478bd9Sstevel@tonic-gate * 10267c478bd9Sstevel@tonic-gate * $vendor - the vendor string defining the event. 10277c478bd9Sstevel@tonic-gate * 10287c478bd9Sstevel@tonic-gate * $publisher - the publisher string defining the event. 10297c478bd9Sstevel@tonic-gate * 10307c478bd9Sstevel@tonic-gate * $class - the class string defining the event. 10317c478bd9Sstevel@tonic-gate * 10327c478bd9Sstevel@tonic-gate * $subclass - the subclass string defining the event. 10337c478bd9Sstevel@tonic-gate * 10347c478bd9Sstevel@tonic-gate * $sequence - the sequence number of the event. 10357c478bd9Sstevel@tonic-gate * 10367c478bd9Sstevel@tonic-gate * $timestamp - the timestamp of the event. 10377c478bd9Sstevel@tonic-gate * 10387c478bd9Sstevel@tonic-gate * Attributes with signed data types (DATA_TYPE_INT16, 10397c478bd9Sstevel@tonic-gate * DATA_TYPE_INT32 and DATA_TYPE_INT64) are expanded 10407c478bd9Sstevel@tonic-gate * as decimal digits. 10417c478bd9Sstevel@tonic-gate * 10427c478bd9Sstevel@tonic-gate * Attributes with unsigned data types (DATA_TYPE_BYTE, 10437c478bd9Sstevel@tonic-gate * DATA_TYPE_UINT16, DATA_TYPE_UINT32, DATA_TYPE_UINT64 and 10447c478bd9Sstevel@tonic-gate * DATA_TYPE_HTTIME) are expanded as hexadecimal digits 10457c478bd9Sstevel@tonic-gate * with a "0x" prefix. 10467c478bd9Sstevel@tonic-gate * 10477c478bd9Sstevel@tonic-gate * Attributes with string data type (DATA_TYPE_STRING) 10487c478bd9Sstevel@tonic-gate * are expanded with the string data. The data is 10497c478bd9Sstevel@tonic-gate * not quoted. If if it desired that the quoted strings 10507c478bd9Sstevel@tonic-gate * be generated on the command line, put quotes around 10517c478bd9Sstevel@tonic-gate * the macro call in the arguments. 10527c478bd9Sstevel@tonic-gate * 10537c478bd9Sstevel@tonic-gate * Array types are expanded with each element expanded 10547c478bd9Sstevel@tonic-gate * as defined for that scalar type, with a space separating 10557c478bd9Sstevel@tonic-gate * each element substitution. 10567c478bd9Sstevel@tonic-gate */ 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate static str_t * 10597c478bd9Sstevel@tonic-gate find_macro_definition(sysevent_t *ev, nvlist_t *nvlist, syseventtab_t *sep, 10607c478bd9Sstevel@tonic-gate char *token, sysevent_hdr_info_t *hdr) 10617c478bd9Sstevel@tonic-gate { 10627c478bd9Sstevel@tonic-gate nvpair_t *nvp; 10637c478bd9Sstevel@tonic-gate int nmatches; 10647c478bd9Sstevel@tonic-gate char num[64]; 10657c478bd9Sstevel@tonic-gate str_t *replacement; 10667c478bd9Sstevel@tonic-gate int i; 10677c478bd9Sstevel@tonic-gate uint_t nelems; 10687c478bd9Sstevel@tonic-gate union { 10697c478bd9Sstevel@tonic-gate uchar_t x_byte; 10707c478bd9Sstevel@tonic-gate int16_t x_int16; 10717c478bd9Sstevel@tonic-gate uint16_t x_uint16; 10727c478bd9Sstevel@tonic-gate int32_t x_int32; 10737c478bd9Sstevel@tonic-gate uint32_t x_uint32; 10747c478bd9Sstevel@tonic-gate int64_t x_int64; 10757c478bd9Sstevel@tonic-gate uint64_t x_uint64; 10767c478bd9Sstevel@tonic-gate hrtime_t x_time; 10777c478bd9Sstevel@tonic-gate char *x_string; 10787c478bd9Sstevel@tonic-gate uchar_t *x_byte_array; 10797c478bd9Sstevel@tonic-gate int16_t *x_int16_array; 10807c478bd9Sstevel@tonic-gate int32_t *x_int32_array; 10817c478bd9Sstevel@tonic-gate int64_t *x_int64_array; 10827c478bd9Sstevel@tonic-gate uint16_t *x_uint16_array; 10837c478bd9Sstevel@tonic-gate uint32_t *x_uint32_array; 10847c478bd9Sstevel@tonic-gate uint64_t *x_uint64_array; 10857c478bd9Sstevel@tonic-gate char **x_string_array; 10867c478bd9Sstevel@tonic-gate } x; 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate if ((replacement = initstr(128)) == NULL) { 10907c478bd9Sstevel@tonic-gate return (NULL); 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate if (strcmp(token, "vendor") == 0) { 10947c478bd9Sstevel@tonic-gate if (strcopys(replacement, hdr->vendor)) { 10957c478bd9Sstevel@tonic-gate freestr(replacement); 10967c478bd9Sstevel@tonic-gate return (NULL); 10977c478bd9Sstevel@tonic-gate } 10987c478bd9Sstevel@tonic-gate return (replacement); 10997c478bd9Sstevel@tonic-gate } 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate if (strcmp(token, "publisher") == 0) { 11027c478bd9Sstevel@tonic-gate if (strcopys(replacement, hdr->publisher)) { 11037c478bd9Sstevel@tonic-gate freestr(replacement); 11047c478bd9Sstevel@tonic-gate return (NULL); 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate return (replacement); 11077c478bd9Sstevel@tonic-gate } 11087c478bd9Sstevel@tonic-gate 11097c478bd9Sstevel@tonic-gate if (strcmp(token, "class") == 0) { 11107c478bd9Sstevel@tonic-gate if (strcopys(replacement, hdr->class)) { 11117c478bd9Sstevel@tonic-gate freestr(replacement); 11127c478bd9Sstevel@tonic-gate return (NULL); 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate return (replacement); 11157c478bd9Sstevel@tonic-gate } 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate if (strcmp(token, "subclass") == 0) { 11187c478bd9Sstevel@tonic-gate if (strcopys(replacement, hdr->subclass)) { 11197c478bd9Sstevel@tonic-gate freestr(replacement); 11207c478bd9Sstevel@tonic-gate return (NULL); 11217c478bd9Sstevel@tonic-gate } 11227c478bd9Sstevel@tonic-gate return (replacement); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate if ((strcmp(token, "sequence") == 0) || 11267c478bd9Sstevel@tonic-gate (strcmp(token, "timestamp") == 0)) { 11277c478bd9Sstevel@tonic-gate if (strcmp(token, "sequence") == 0) { 11287c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), 11297c478bd9Sstevel@tonic-gate "0x%llx", sysevent_get_seq(ev)); 11307c478bd9Sstevel@tonic-gate } else { 11317c478bd9Sstevel@tonic-gate hrtime_t ts; 11327c478bd9Sstevel@tonic-gate sysevent_get_time(ev, &ts); 11337c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), "0x%llx", ts); 11347c478bd9Sstevel@tonic-gate } 11357c478bd9Sstevel@tonic-gate if (strcopys(replacement, num)) { 11367c478bd9Sstevel@tonic-gate freestr(replacement); 11377c478bd9Sstevel@tonic-gate return (NULL); 11387c478bd9Sstevel@tonic-gate } 11397c478bd9Sstevel@tonic-gate return (replacement); 11407c478bd9Sstevel@tonic-gate } 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate nmatches = 0; 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate if (nvlist) { 11457c478bd9Sstevel@tonic-gate nvpair_t *nvp_match; 11467c478bd9Sstevel@tonic-gate nvp = NULL; 11477c478bd9Sstevel@tonic-gate while ((nvp = nvlist_next_nvpair(nvlist, nvp)) != NULL) { 11487c478bd9Sstevel@tonic-gate if (debug_level >= DBG_DETAILED) { 11497c478bd9Sstevel@tonic-gate syseventd_print(DBG_DETAILED, 11507c478bd9Sstevel@tonic-gate " attribute: %s %s\n", nvpair_name(nvp), 11517c478bd9Sstevel@tonic-gate se_attr_type_to_str(nvpair_type(nvp))); 11527c478bd9Sstevel@tonic-gate } 11537c478bd9Sstevel@tonic-gate if (strcmp(token, nvpair_name(nvp)) == 0) { 11547c478bd9Sstevel@tonic-gate nmatches++; 11557c478bd9Sstevel@tonic-gate nvp_match = nvp; 11567c478bd9Sstevel@tonic-gate } 11577c478bd9Sstevel@tonic-gate } 11587c478bd9Sstevel@tonic-gate nvp = nvp_match; 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate if (nmatches == 0) { 11627c478bd9Sstevel@tonic-gate syslog(LOG_ERR, MACRO_UNDEF_ERR, 11637c478bd9Sstevel@tonic-gate sep->se_conf_file, sep->se_lineno, token); 11647c478bd9Sstevel@tonic-gate freestr(replacement); 11657c478bd9Sstevel@tonic-gate return (NULL); 11667c478bd9Sstevel@tonic-gate } else if (nmatches > 1) { 11677c478bd9Sstevel@tonic-gate syslog(LOG_ERR, MACRO_MULT_DEF_ERR, 11687c478bd9Sstevel@tonic-gate sep->se_conf_file, sep->se_lineno, token); 11697c478bd9Sstevel@tonic-gate freestr(replacement); 11707c478bd9Sstevel@tonic-gate return (NULL); 11717c478bd9Sstevel@tonic-gate } 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate switch (nvpair_type(nvp)) { 11747c478bd9Sstevel@tonic-gate case DATA_TYPE_BYTE: 11757c478bd9Sstevel@tonic-gate (void) nvpair_value_byte(nvp, &x.x_byte); 11767c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), "0x%x", x.x_byte); 11777c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 11787c478bd9Sstevel@tonic-gate freestr(replacement); 11797c478bd9Sstevel@tonic-gate return (NULL); 11807c478bd9Sstevel@tonic-gate } 11817c478bd9Sstevel@tonic-gate break; 11827c478bd9Sstevel@tonic-gate case DATA_TYPE_INT16: 11837c478bd9Sstevel@tonic-gate (void) nvpair_value_int16(nvp, &x.x_int16); 11847c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), "%d", x.x_int16); 11857c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 11867c478bd9Sstevel@tonic-gate freestr(replacement); 11877c478bd9Sstevel@tonic-gate return (NULL); 11887c478bd9Sstevel@tonic-gate } 11897c478bd9Sstevel@tonic-gate break; 11907c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT16: 11917c478bd9Sstevel@tonic-gate (void) nvpair_value_uint16(nvp, &x.x_uint16); 11927c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), "0x%x", x.x_uint16); 11937c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 11947c478bd9Sstevel@tonic-gate freestr(replacement); 11957c478bd9Sstevel@tonic-gate return (NULL); 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate break; 11987c478bd9Sstevel@tonic-gate case DATA_TYPE_INT32: 11997c478bd9Sstevel@tonic-gate (void) nvpair_value_int32(nvp, &x.x_int32); 12007c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), "%d", x.x_int32); 12017c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 12027c478bd9Sstevel@tonic-gate freestr(replacement); 12037c478bd9Sstevel@tonic-gate return (NULL); 12047c478bd9Sstevel@tonic-gate } 12057c478bd9Sstevel@tonic-gate break; 12067c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT32: 12077c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32(nvp, &x.x_uint32); 12087c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), "0x%x", x.x_uint32); 12097c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 12107c478bd9Sstevel@tonic-gate freestr(replacement); 12117c478bd9Sstevel@tonic-gate return (NULL); 12127c478bd9Sstevel@tonic-gate } 12137c478bd9Sstevel@tonic-gate break; 12147c478bd9Sstevel@tonic-gate case DATA_TYPE_INT64: 12157c478bd9Sstevel@tonic-gate (void) nvpair_value_int64(nvp, &x.x_int64); 12167c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), "%lld", x.x_int64); 12177c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 12187c478bd9Sstevel@tonic-gate freestr(replacement); 12197c478bd9Sstevel@tonic-gate return (NULL); 12207c478bd9Sstevel@tonic-gate } 12217c478bd9Sstevel@tonic-gate break; 12227c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT64: 12237c478bd9Sstevel@tonic-gate (void) nvpair_value_uint64(nvp, &x.x_uint64); 12247c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), "0x%llx", x.x_uint64); 12257c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 12267c478bd9Sstevel@tonic-gate freestr(replacement); 12277c478bd9Sstevel@tonic-gate return (NULL); 12287c478bd9Sstevel@tonic-gate } 12297c478bd9Sstevel@tonic-gate break; 12307c478bd9Sstevel@tonic-gate case DATA_TYPE_STRING: 12317c478bd9Sstevel@tonic-gate (void) nvpair_value_string(nvp, &x.x_string); 12327c478bd9Sstevel@tonic-gate if (strcats(replacement, x.x_string)) { 12337c478bd9Sstevel@tonic-gate freestr(replacement); 12347c478bd9Sstevel@tonic-gate return (NULL); 12357c478bd9Sstevel@tonic-gate } 12367c478bd9Sstevel@tonic-gate break; 12377c478bd9Sstevel@tonic-gate case DATA_TYPE_BYTE_ARRAY: { 12387c478bd9Sstevel@tonic-gate uchar_t *p; 12397c478bd9Sstevel@tonic-gate (void) nvpair_value_byte_array(nvp, 12407c478bd9Sstevel@tonic-gate &x.x_byte_array, &nelems); 12417c478bd9Sstevel@tonic-gate p = x.x_byte_array; 12427c478bd9Sstevel@tonic-gate for (i = 0; i < nelems; i++) { 12437c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), 12447c478bd9Sstevel@tonic-gate "0x%x ", *p++ & 0xff); 12457c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 12467c478bd9Sstevel@tonic-gate freestr(replacement); 12477c478bd9Sstevel@tonic-gate return (NULL); 12487c478bd9Sstevel@tonic-gate } 12497c478bd9Sstevel@tonic-gate } 12507c478bd9Sstevel@tonic-gate } 12517c478bd9Sstevel@tonic-gate break; 12527c478bd9Sstevel@tonic-gate case DATA_TYPE_INT16_ARRAY: { 12537c478bd9Sstevel@tonic-gate int16_t *p; 12547c478bd9Sstevel@tonic-gate (void) nvpair_value_int16_array(nvp, 12557c478bd9Sstevel@tonic-gate &x.x_int16_array, &nelems); 12567c478bd9Sstevel@tonic-gate p = x.x_int16_array; 12577c478bd9Sstevel@tonic-gate for (i = 0; i < nelems; i++) { 12587c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), "%d ", *p++); 12597c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 12607c478bd9Sstevel@tonic-gate freestr(replacement); 12617c478bd9Sstevel@tonic-gate return (NULL); 12627c478bd9Sstevel@tonic-gate } 12637c478bd9Sstevel@tonic-gate } 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate break; 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT16_ARRAY: { 12687c478bd9Sstevel@tonic-gate uint16_t *p; 12697c478bd9Sstevel@tonic-gate (void) nvpair_value_uint16_array(nvp, 12707c478bd9Sstevel@tonic-gate &x.x_uint16_array, &nelems); 12717c478bd9Sstevel@tonic-gate p = x.x_uint16_array; 12727c478bd9Sstevel@tonic-gate for (i = 0; i < nelems; i++) { 12737c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), 12747c478bd9Sstevel@tonic-gate "0x%x ", *p++); 12757c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 12767c478bd9Sstevel@tonic-gate freestr(replacement); 12777c478bd9Sstevel@tonic-gate return (NULL); 12787c478bd9Sstevel@tonic-gate } 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate } 12817c478bd9Sstevel@tonic-gate break; 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate case DATA_TYPE_INT32_ARRAY: { 12847c478bd9Sstevel@tonic-gate int32_t *p; 12857c478bd9Sstevel@tonic-gate (void) nvpair_value_int32_array(nvp, 12867c478bd9Sstevel@tonic-gate &x.x_int32_array, &nelems); 12877c478bd9Sstevel@tonic-gate p = x.x_int32_array; 12887c478bd9Sstevel@tonic-gate for (i = 0; i < nelems; i++) { 12897c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), "%d ", *p++); 12907c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 12917c478bd9Sstevel@tonic-gate freestr(replacement); 12927c478bd9Sstevel@tonic-gate return (NULL); 12937c478bd9Sstevel@tonic-gate } 12947c478bd9Sstevel@tonic-gate } 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate break; 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT32_ARRAY: { 12997c478bd9Sstevel@tonic-gate uint32_t *p; 13007c478bd9Sstevel@tonic-gate (void) nvpair_value_uint32_array(nvp, 13017c478bd9Sstevel@tonic-gate &x.x_uint32_array, &nelems); 13027c478bd9Sstevel@tonic-gate p = x.x_uint32_array; 13037c478bd9Sstevel@tonic-gate for (i = 0; i < nelems; i++) { 13047c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), 13057c478bd9Sstevel@tonic-gate "0x%x ", *p++); 13067c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 13077c478bd9Sstevel@tonic-gate freestr(replacement); 13087c478bd9Sstevel@tonic-gate return (NULL); 13097c478bd9Sstevel@tonic-gate } 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate } 13127c478bd9Sstevel@tonic-gate break; 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate case DATA_TYPE_INT64_ARRAY: { 13157c478bd9Sstevel@tonic-gate int64_t *p; 13167c478bd9Sstevel@tonic-gate (void) nvpair_value_int64_array(nvp, 13177c478bd9Sstevel@tonic-gate &x.x_int64_array, &nelems); 13187c478bd9Sstevel@tonic-gate p = x.x_int64_array; 13197c478bd9Sstevel@tonic-gate for (i = 0; i < nelems; i++) { 13207c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), 13217c478bd9Sstevel@tonic-gate "%lld ", *p++); 13227c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 13237c478bd9Sstevel@tonic-gate freestr(replacement); 13247c478bd9Sstevel@tonic-gate return (NULL); 13257c478bd9Sstevel@tonic-gate } 13267c478bd9Sstevel@tonic-gate } 13277c478bd9Sstevel@tonic-gate } 13287c478bd9Sstevel@tonic-gate break; 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT64_ARRAY: { 13317c478bd9Sstevel@tonic-gate uint64_t *p; 13327c478bd9Sstevel@tonic-gate (void) nvpair_value_uint64_array(nvp, 13337c478bd9Sstevel@tonic-gate &x.x_uint64_array, &nelems); 13347c478bd9Sstevel@tonic-gate p = x.x_uint64_array; 13357c478bd9Sstevel@tonic-gate for (i = 0; i < nelems; i++) { 13367c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), 13377c478bd9Sstevel@tonic-gate "0x%llx ", *p++); 13387c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 13397c478bd9Sstevel@tonic-gate freestr(replacement); 13407c478bd9Sstevel@tonic-gate return (NULL); 13417c478bd9Sstevel@tonic-gate } 13427c478bd9Sstevel@tonic-gate } 13437c478bd9Sstevel@tonic-gate } 13447c478bd9Sstevel@tonic-gate break; 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate case DATA_TYPE_STRING_ARRAY: { 13477c478bd9Sstevel@tonic-gate char **p; 13487c478bd9Sstevel@tonic-gate (void) nvpair_value_string_array(nvp, 13497c478bd9Sstevel@tonic-gate &x.x_string_array, &nelems); 13507c478bd9Sstevel@tonic-gate p = x.x_string_array; 13517c478bd9Sstevel@tonic-gate for (i = 0; i < nelems; i++) { 13527c478bd9Sstevel@tonic-gate if (strcats(replacement, *p++) || 13537c478bd9Sstevel@tonic-gate strcats(replacement, " ")) { 13547c478bd9Sstevel@tonic-gate freestr(replacement); 13557c478bd9Sstevel@tonic-gate return (NULL); 13567c478bd9Sstevel@tonic-gate } 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate } 13597c478bd9Sstevel@tonic-gate break; 13607c478bd9Sstevel@tonic-gate 13617c478bd9Sstevel@tonic-gate case DATA_TYPE_HRTIME: 13627c478bd9Sstevel@tonic-gate (void) nvpair_value_hrtime(nvp, &x.x_time); 13637c478bd9Sstevel@tonic-gate (void) snprintf(num, sizeof (num), "0x%llx", x.x_time); 13647c478bd9Sstevel@tonic-gate if (strcats(replacement, num)) { 13657c478bd9Sstevel@tonic-gate freestr(replacement); 13667c478bd9Sstevel@tonic-gate return (NULL); 13677c478bd9Sstevel@tonic-gate } 13687c478bd9Sstevel@tonic-gate break; 13697c478bd9Sstevel@tonic-gate default: 13707c478bd9Sstevel@tonic-gate syslog(LOG_ERR, ATTR_UNSUPPORTED_ERR, 13717c478bd9Sstevel@tonic-gate sep->se_conf_file, sep->se_lineno, 13727c478bd9Sstevel@tonic-gate nvpair_type(nvp), token); 13737c478bd9Sstevel@tonic-gate freestr(replacement); 13747c478bd9Sstevel@tonic-gate return (NULL); 13757c478bd9Sstevel@tonic-gate } 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate return (replacement); 13787c478bd9Sstevel@tonic-gate } 13797c478bd9Sstevel@tonic-gate 13807c478bd9Sstevel@tonic-gate /* 13817c478bd9Sstevel@tonic-gate * Expand macros in the command template provided in an event 13827c478bd9Sstevel@tonic-gate * specification with the data from the event or event attributes. 13837c478bd9Sstevel@tonic-gate * 13847c478bd9Sstevel@tonic-gate * Macros are introduced by the '$' character, with the macro 13857c478bd9Sstevel@tonic-gate * name being the following token separated by a SPACE or 13867c478bd9Sstevel@tonic-gate * TAB character. If the macro name is embedded in text, 13877c478bd9Sstevel@tonic-gate * it may be delineated by '${' and "}'. A backslash before 13887c478bd9Sstevel@tonic-gate * the '$' causes macro expansion not to occur. 13897c478bd9Sstevel@tonic-gate * 13907c478bd9Sstevel@tonic-gate * The following predefined macros are defined for each event: 13917c478bd9Sstevel@tonic-gate * 13927c478bd9Sstevel@tonic-gate * $vendor - the vendor string defining the event. 13937c478bd9Sstevel@tonic-gate * 13947c478bd9Sstevel@tonic-gate * $publisher - the publisher string defining the event. 13957c478bd9Sstevel@tonic-gate * 13967c478bd9Sstevel@tonic-gate * $class - the class string defining the event. 13977c478bd9Sstevel@tonic-gate * 13987c478bd9Sstevel@tonic-gate * $subclass - the subclass string defining the event. 13997c478bd9Sstevel@tonic-gate * 14007c478bd9Sstevel@tonic-gate * $sequence - the sequence number of the event. 14017c478bd9Sstevel@tonic-gate * 14027c478bd9Sstevel@tonic-gate * $timestamp - the timestamp of the event. 14037c478bd9Sstevel@tonic-gate * 14047c478bd9Sstevel@tonic-gate * 14057c478bd9Sstevel@tonic-gate * Macro names other than those predefined are compared against 14067c478bd9Sstevel@tonic-gate * the attribute list provided with the event. An attribute 14077c478bd9Sstevel@tonic-gate * with name matching the macro name causes the value of 14087c478bd9Sstevel@tonic-gate * of the attribute to be substituted as ASCII text on the 14097c478bd9Sstevel@tonic-gate * generated command line. 14107c478bd9Sstevel@tonic-gate * 14117c478bd9Sstevel@tonic-gate * Use of a macro for which no attribute with that name 14127c478bd9Sstevel@tonic-gate * is defined, or for which multiple attributes with that 14137c478bd9Sstevel@tonic-gate * name are provided, cause an error and the command is 14147c478bd9Sstevel@tonic-gate * not invoked. 14157c478bd9Sstevel@tonic-gate */ 14167c478bd9Sstevel@tonic-gate static int 14177c478bd9Sstevel@tonic-gate expand_macros(sysevent_t *ev, nvlist_t *nvlist, syseventtab_t *sep, 14187c478bd9Sstevel@tonic-gate str_t *line, sysevent_hdr_info_t *hdr) 14197c478bd9Sstevel@tonic-gate { 14207c478bd9Sstevel@tonic-gate char *p; 14217c478bd9Sstevel@tonic-gate int state; 14227c478bd9Sstevel@tonic-gate char *end; 14237c478bd9Sstevel@tonic-gate str_t *token; 14247c478bd9Sstevel@tonic-gate str_t *remainder; 14257c478bd9Sstevel@tonic-gate str_t *replacement; 14267c478bd9Sstevel@tonic-gate int count; 14277c478bd9Sstevel@tonic-gate int dollar_position; 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate syseventd_print(DBG_MACRO, " expanding macros: '%s'\n", line->s_str); 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate reset: 14327c478bd9Sstevel@tonic-gate state = 0; 14337c478bd9Sstevel@tonic-gate count = 0; 14347c478bd9Sstevel@tonic-gate for (p = line->s_str; *p != 0; p++, count++) { 14357c478bd9Sstevel@tonic-gate switch (state) { 14367c478bd9Sstevel@tonic-gate case 0: /* initial state */ 14377c478bd9Sstevel@tonic-gate if (*p == '\\') { 14387c478bd9Sstevel@tonic-gate state = 1; 14397c478bd9Sstevel@tonic-gate } else if (*p == '$') { 14407c478bd9Sstevel@tonic-gate dollar_position = count; 14417c478bd9Sstevel@tonic-gate state = 2; 14427c478bd9Sstevel@tonic-gate } 14437c478bd9Sstevel@tonic-gate break; 14447c478bd9Sstevel@tonic-gate case 1: /* skip characters */ 14457c478bd9Sstevel@tonic-gate state = 0; /* after backslash */ 14467c478bd9Sstevel@tonic-gate break; 14477c478bd9Sstevel@tonic-gate case 2: /* character after $ */ 14487c478bd9Sstevel@tonic-gate if (*p == '{') { 14497c478bd9Sstevel@tonic-gate token = snip_delimited_identifier(p+1, &end); 14507c478bd9Sstevel@tonic-gate } else { 14517c478bd9Sstevel@tonic-gate token = snip_identifier(p, &end); 14527c478bd9Sstevel@tonic-gate } 14537c478bd9Sstevel@tonic-gate if (token == NULL) 14547c478bd9Sstevel@tonic-gate goto failed; 14557c478bd9Sstevel@tonic-gate 14567c478bd9Sstevel@tonic-gate if ((remainder = initstr(128)) == NULL) { 14577c478bd9Sstevel@tonic-gate freestr(token); 14587c478bd9Sstevel@tonic-gate return (1); 14597c478bd9Sstevel@tonic-gate } 14607c478bd9Sstevel@tonic-gate if (strcopys(remainder, end)) { 14617c478bd9Sstevel@tonic-gate freestr(token); 14627c478bd9Sstevel@tonic-gate freestr(remainder); 14637c478bd9Sstevel@tonic-gate return (1); 14647c478bd9Sstevel@tonic-gate } 14657c478bd9Sstevel@tonic-gate replacement = find_macro_definition(ev, nvlist, 14667c478bd9Sstevel@tonic-gate sep, token->s_str, hdr); 14677c478bd9Sstevel@tonic-gate if (replacement == NULL) { 14687c478bd9Sstevel@tonic-gate freestr(token); 14697c478bd9Sstevel@tonic-gate freestr(remainder); 14707c478bd9Sstevel@tonic-gate return (1); 14717c478bd9Sstevel@tonic-gate } 14727c478bd9Sstevel@tonic-gate syseventd_print(DBG_MACRO, 14737c478bd9Sstevel@tonic-gate " '%s' expands to '%s'\n", 14747c478bd9Sstevel@tonic-gate token->s_str, replacement->s_str); 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate strtrunc(line, dollar_position); 14777c478bd9Sstevel@tonic-gate if (strcats(line, replacement->s_str)) { 14787c478bd9Sstevel@tonic-gate freestr(token); 14797c478bd9Sstevel@tonic-gate freestr(replacement); 14807c478bd9Sstevel@tonic-gate freestr(remainder); 14817c478bd9Sstevel@tonic-gate return (1); 14827c478bd9Sstevel@tonic-gate } 14837c478bd9Sstevel@tonic-gate if (strcats(line, remainder->s_str)) { 14847c478bd9Sstevel@tonic-gate freestr(token); 14857c478bd9Sstevel@tonic-gate freestr(replacement); 14867c478bd9Sstevel@tonic-gate freestr(remainder); 14877c478bd9Sstevel@tonic-gate return (1); 14887c478bd9Sstevel@tonic-gate } 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate syseventd_print(DBG_MACRO, 14917c478bd9Sstevel@tonic-gate " with macro expanded: '%s'\n", line->s_str); 14927c478bd9Sstevel@tonic-gate 14937c478bd9Sstevel@tonic-gate freestr(token); 14947c478bd9Sstevel@tonic-gate freestr(replacement); 14957c478bd9Sstevel@tonic-gate freestr(remainder); 14967c478bd9Sstevel@tonic-gate goto reset; 14977c478bd9Sstevel@tonic-gate } 14987c478bd9Sstevel@tonic-gate } 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate failed: 15017c478bd9Sstevel@tonic-gate if (state != 0) { 15027c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SYNTAX_ERR, sep->se_conf_file, sep->se_lineno); 15037c478bd9Sstevel@tonic-gate return (1); 15047c478bd9Sstevel@tonic-gate } 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate return (0); 15077c478bd9Sstevel@tonic-gate } 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate static void 15117c478bd9Sstevel@tonic-gate start_syseventconfd() 15127c478bd9Sstevel@tonic-gate { 15137c478bd9Sstevel@tonic-gate int err; 15147c478bd9Sstevel@tonic-gate 15157c478bd9Sstevel@tonic-gate err = system1("/usr/lib/sysevent/syseventconfd", 15167c478bd9Sstevel@tonic-gate "/usr/lib/sysevent/syseventconfd"); 15177c478bd9Sstevel@tonic-gate 15187c478bd9Sstevel@tonic-gate if (err != 0 && confd_err_msg_emitted == 0) { 15197c478bd9Sstevel@tonic-gate if (confd_state == CONFD_STATE_NOT_RUNNING) { 15207c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SYSEVENTCONFD_START_ERR, 15217c478bd9Sstevel@tonic-gate strerror(errno)); 15227c478bd9Sstevel@tonic-gate } else { 15237c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SYSEVENTCONFD_RESTART_ERR, 15247c478bd9Sstevel@tonic-gate strerror(errno)); 15257c478bd9Sstevel@tonic-gate } 15267c478bd9Sstevel@tonic-gate } 15277c478bd9Sstevel@tonic-gate } 15287c478bd9Sstevel@tonic-gate 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate static int 15317c478bd9Sstevel@tonic-gate system1(const char *s_path, const char *s) 15327c478bd9Sstevel@tonic-gate { 15337c478bd9Sstevel@tonic-gate struct sigaction cbuf, ibuf, qbuf, ignore, dfl; 15347c478bd9Sstevel@tonic-gate sigset_t mask; 15357c478bd9Sstevel@tonic-gate sigset_t savemask; 15367c478bd9Sstevel@tonic-gate struct stat st; 15377c478bd9Sstevel@tonic-gate pid_t pid; 15387c478bd9Sstevel@tonic-gate int status, w; 15397c478bd9Sstevel@tonic-gate 15407c478bd9Sstevel@tonic-gate /* Check the requested command */ 15417c478bd9Sstevel@tonic-gate if (s == NULL) { 15427c478bd9Sstevel@tonic-gate errno = EINVAL; 15437c478bd9Sstevel@tonic-gate return (-1); 15447c478bd9Sstevel@tonic-gate } 15457c478bd9Sstevel@tonic-gate 15467c478bd9Sstevel@tonic-gate /* Check the ability to execute devfsadmd from this process */ 15477c478bd9Sstevel@tonic-gate if (stat(s_path, &st) < 0) { 15487c478bd9Sstevel@tonic-gate return (-1); 15497c478bd9Sstevel@tonic-gate } 15507c478bd9Sstevel@tonic-gate if (((geteuid() == st.st_uid) && ((st.st_mode & S_IXUSR) == 0)) || 15517c478bd9Sstevel@tonic-gate ((getegid() == st.st_gid) && ((st.st_mode & S_IXGRP) == 0)) || 15527c478bd9Sstevel@tonic-gate ((st.st_mode & S_IXOTH) == 0)) { 15537c478bd9Sstevel@tonic-gate errno = EPERM; 15547c478bd9Sstevel@tonic-gate return (-1); 15557c478bd9Sstevel@tonic-gate } 15567c478bd9Sstevel@tonic-gate 15577c478bd9Sstevel@tonic-gate /* 15587c478bd9Sstevel@tonic-gate * Block SIGCHLD and set up a default handler for the duration of the 15597c478bd9Sstevel@tonic-gate * system1 call. 15607c478bd9Sstevel@tonic-gate */ 15617c478bd9Sstevel@tonic-gate (void) sigemptyset(&mask); 15627c478bd9Sstevel@tonic-gate (void) sigaddset(&mask, SIGCHLD); 15637c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &mask, &savemask); 15647c478bd9Sstevel@tonic-gate (void) memset(&dfl, 0, sizeof (dfl)); 15657c478bd9Sstevel@tonic-gate dfl.sa_handler = SIG_DFL; 15667c478bd9Sstevel@tonic-gate (void) sigaction(SIGCHLD, &dfl, &cbuf); 15677c478bd9Sstevel@tonic-gate 15687c478bd9Sstevel@tonic-gate /* Fork off the child process (using fork1(), because it's MT-safe) */ 15697c478bd9Sstevel@tonic-gate switch (pid = fork1()) { 15707c478bd9Sstevel@tonic-gate case -1: 15717c478bd9Sstevel@tonic-gate /* Error */ 15727c478bd9Sstevel@tonic-gate (void) sigaction(SIGCHLD, &cbuf, NULL); 15737c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &savemask, NULL); 15747c478bd9Sstevel@tonic-gate return (-1); 15757c478bd9Sstevel@tonic-gate case 0: 15767c478bd9Sstevel@tonic-gate /* Set-up an initial signal mask for the child */ 15777c478bd9Sstevel@tonic-gate (void) sigemptyset(&mask); 15787c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &mask, NULL); 1579bc9ec910Snakanon closefrom(3); 15807c478bd9Sstevel@tonic-gate (void) execl(s_path, s, (char *)0); 15817c478bd9Sstevel@tonic-gate _exit(-1); 15827c478bd9Sstevel@tonic-gate break; 15837c478bd9Sstevel@tonic-gate default: 15847c478bd9Sstevel@tonic-gate /* Parent */ 15857c478bd9Sstevel@tonic-gate break; 15867c478bd9Sstevel@tonic-gate } 15877c478bd9Sstevel@tonic-gate 15887c478bd9Sstevel@tonic-gate (void) memset(&ignore, 0, sizeof (ignore)); 15897c478bd9Sstevel@tonic-gate ignore.sa_handler = SIG_IGN; 15907c478bd9Sstevel@tonic-gate (void) sigaction(SIGINT, &ignore, &ibuf); 15917c478bd9Sstevel@tonic-gate (void) sigaction(SIGQUIT, &ignore, &qbuf); 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate do { 15947c478bd9Sstevel@tonic-gate w = waitpid(pid, &status, 0); 15957c478bd9Sstevel@tonic-gate } while (w == -1 && errno == EINTR); 15967c478bd9Sstevel@tonic-gate 15977c478bd9Sstevel@tonic-gate (void) sigaction(SIGINT, &ibuf, NULL); 15987c478bd9Sstevel@tonic-gate (void) sigaction(SIGQUIT, &qbuf, NULL); 15997c478bd9Sstevel@tonic-gate 16007c478bd9Sstevel@tonic-gate (void) sigaction(SIGCHLD, &cbuf, NULL); 16017c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &savemask, NULL); 16027c478bd9Sstevel@tonic-gate 16037c478bd9Sstevel@tonic-gate return ((w == -1)? w: status); 16047c478bd9Sstevel@tonic-gate } 16057c478bd9Sstevel@tonic-gate 16067c478bd9Sstevel@tonic-gate /* 16077c478bd9Sstevel@tonic-gate * Free all commands on the cmd queue 16087c478bd9Sstevel@tonic-gate */ 16097c478bd9Sstevel@tonic-gate static void 16107c478bd9Sstevel@tonic-gate abort_cmd_queue() 16117c478bd9Sstevel@tonic-gate { 16127c478bd9Sstevel@tonic-gate cmdqueue_t *cmd; 16137c478bd9Sstevel@tonic-gate cmdqueue_t *next; 16147c478bd9Sstevel@tonic-gate int nevents = 0; 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate while ((cmd = cmdq) != NULL) { 16177c478bd9Sstevel@tonic-gate next = cmd->next; 16187c478bd9Sstevel@tonic-gate cmdq_cnt--; 16197c478bd9Sstevel@tonic-gate sysevent_free(cmd->event); 16207c478bd9Sstevel@tonic-gate sc_free(cmd, sizeof (cmdqueue_t)); 16217c478bd9Sstevel@tonic-gate cmdq = next; 16227c478bd9Sstevel@tonic-gate nevents++; 16237c478bd9Sstevel@tonic-gate } 16247c478bd9Sstevel@tonic-gate cmdq_tail = NULL; 16257c478bd9Sstevel@tonic-gate 16267c478bd9Sstevel@tonic-gate /* 16277c478bd9Sstevel@tonic-gate * Generate error msgs if events were discarded or 16287c478bd9Sstevel@tonic-gate * we are entering the disabled state. 16297c478bd9Sstevel@tonic-gate */ 16307c478bd9Sstevel@tonic-gate if (nevents > 0) { 16317c478bd9Sstevel@tonic-gate syslog(LOG_ERR, N_EVENTS_DISCARDED_ERR, nevents); 16327c478bd9Sstevel@tonic-gate } 16337c478bd9Sstevel@tonic-gate if (want_fini == 0) { 16347c478bd9Sstevel@tonic-gate confd_state = CONFD_STATE_DISABLED; 16357c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SERVICE_DISABLED_MSG); 16367c478bd9Sstevel@tonic-gate } 16377c478bd9Sstevel@tonic-gate } 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate /* 16407c478bd9Sstevel@tonic-gate * For a matching event specification, build the command to be 16417c478bd9Sstevel@tonic-gate * invoked in response to the event. Building the command involves 16427c478bd9Sstevel@tonic-gate * expanding macros supplied in the event specification command 16437c478bd9Sstevel@tonic-gate * with values from the actual event. These macros can be 16447c478bd9Sstevel@tonic-gate * the class/subclass/vendor/publisher strings, or arbitrary 16457c478bd9Sstevel@tonic-gate * attribute data attached to the event. 16467c478bd9Sstevel@tonic-gate * 16477c478bd9Sstevel@tonic-gate * This module does not invoke (fork/exec) the command itself, 16487c478bd9Sstevel@tonic-gate * since this module is running in the context of the syseventd 16497c478bd9Sstevel@tonic-gate * daemon, and fork/exec's done here interfere with the door 16507c478bd9Sstevel@tonic-gate * upcall delivering events from the kernel to the daemon. 16517c478bd9Sstevel@tonic-gate * Instead, we build a separate event and nvlist with the 16527c478bd9Sstevel@tonic-gate * attributes of the command to be invoked, and pass that on 16537c478bd9Sstevel@tonic-gate * to the syseventconfd daemon, which is basically a fork/exec 16547c478bd9Sstevel@tonic-gate * server on our behalf. 16557c478bd9Sstevel@tonic-gate * 16567c478bd9Sstevel@tonic-gate * Errors queuing the event are returned to syseventd with 16577c478bd9Sstevel@tonic-gate * EAGAIN, allowing syseventd to manage a limited number of 16587c478bd9Sstevel@tonic-gate * retries after a short delay. 16597c478bd9Sstevel@tonic-gate */ 16607c478bd9Sstevel@tonic-gate static int 16617c478bd9Sstevel@tonic-gate queue_event(sysevent_t *ev, syseventtab_t *sep, sysevent_hdr_info_t *hdr) 16627c478bd9Sstevel@tonic-gate { 16637c478bd9Sstevel@tonic-gate str_t *line; 16647c478bd9Sstevel@tonic-gate nvlist_t *nvlist; 16657c478bd9Sstevel@tonic-gate char *argv0; 16667c478bd9Sstevel@tonic-gate sysevent_t *cmd_event; 16677c478bd9Sstevel@tonic-gate nvlist_t *cmd_nvlist; 16687c478bd9Sstevel@tonic-gate cmdqueue_t *new_cmd; 16697c478bd9Sstevel@tonic-gate 16707c478bd9Sstevel@tonic-gate if ((line = initstr(128)) == NULL) 16717c478bd9Sstevel@tonic-gate return (1); 16727c478bd9Sstevel@tonic-gate 16737c478bd9Sstevel@tonic-gate if ((argv0 = strrchr(sep->se_path, '/')) == NULL) { 16747c478bd9Sstevel@tonic-gate argv0 = sep->se_path; 16757c478bd9Sstevel@tonic-gate } else { 16767c478bd9Sstevel@tonic-gate argv0++; 16777c478bd9Sstevel@tonic-gate } 16787c478bd9Sstevel@tonic-gate if (strcopys(line, argv0)) { 16797c478bd9Sstevel@tonic-gate freestr(line); 16807c478bd9Sstevel@tonic-gate return (1); 16817c478bd9Sstevel@tonic-gate } 16827c478bd9Sstevel@tonic-gate 16837c478bd9Sstevel@tonic-gate if (sep->se_args) { 16847c478bd9Sstevel@tonic-gate if (strcats(line, " ")) { 16857c478bd9Sstevel@tonic-gate freestr(line); 16867c478bd9Sstevel@tonic-gate return (1); 16877c478bd9Sstevel@tonic-gate } 16887c478bd9Sstevel@tonic-gate if (strcats(line, sep->se_args)) { 16897c478bd9Sstevel@tonic-gate freestr(line); 16907c478bd9Sstevel@tonic-gate return (1); 16917c478bd9Sstevel@tonic-gate } 16927c478bd9Sstevel@tonic-gate 16937c478bd9Sstevel@tonic-gate if (sysevent_get_attr_list(ev, &nvlist) != 0) { 16947c478bd9Sstevel@tonic-gate syslog(LOG_ERR, GET_ATTR_LIST_ERR, 16957c478bd9Sstevel@tonic-gate sep->se_conf_file, sep->se_lineno, 16967c478bd9Sstevel@tonic-gate strerror(errno)); 16977c478bd9Sstevel@tonic-gate freestr(line); 16987c478bd9Sstevel@tonic-gate return (1); 16997c478bd9Sstevel@tonic-gate } 17007c478bd9Sstevel@tonic-gate if (expand_macros(ev, nvlist, sep, line, hdr)) { 17017c478bd9Sstevel@tonic-gate freestr(line); 17027c478bd9Sstevel@tonic-gate if (nvlist) 17037c478bd9Sstevel@tonic-gate nvlist_free(nvlist); 17047c478bd9Sstevel@tonic-gate return (1); 17057c478bd9Sstevel@tonic-gate } 17067c478bd9Sstevel@tonic-gate if (nvlist) 17077c478bd9Sstevel@tonic-gate nvlist_free(nvlist); 17087c478bd9Sstevel@tonic-gate } 17097c478bd9Sstevel@tonic-gate 17107c478bd9Sstevel@tonic-gate if (debug_level >= DBG_EXEC) { 17117c478bd9Sstevel@tonic-gate syseventd_print(DBG_EXEC, "%s, line %d: path = %s\n", 17127c478bd9Sstevel@tonic-gate sep->se_conf_file, sep->se_lineno, sep->se_path); 17137c478bd9Sstevel@tonic-gate syseventd_print(DBG_EXEC, " cmd = %s\n", line->s_str); 17147c478bd9Sstevel@tonic-gate } 17157c478bd9Sstevel@tonic-gate 17167c478bd9Sstevel@tonic-gate cmd_nvlist = NULL; 17177c478bd9Sstevel@tonic-gate if ((errno = nvlist_alloc(&cmd_nvlist, NV_UNIQUE_NAME, 0)) != 0) { 17187c478bd9Sstevel@tonic-gate freestr(line); 17197c478bd9Sstevel@tonic-gate syslog(LOG_ERR, NVLIST_ALLOC_ERR, 17207c478bd9Sstevel@tonic-gate sep->se_conf_file, sep->se_lineno, 17217c478bd9Sstevel@tonic-gate strerror(errno)); 17227c478bd9Sstevel@tonic-gate return (1); 17237c478bd9Sstevel@tonic-gate } 17247c478bd9Sstevel@tonic-gate 17257c478bd9Sstevel@tonic-gate if ((errno = nvlist_add_string(cmd_nvlist, "path", sep->se_path)) != 0) 17267c478bd9Sstevel@tonic-gate goto err; 17277c478bd9Sstevel@tonic-gate if ((errno = nvlist_add_string(cmd_nvlist, "cmd", line->s_str)) != 0) 17287c478bd9Sstevel@tonic-gate goto err; 17297c478bd9Sstevel@tonic-gate if ((errno = nvlist_add_string(cmd_nvlist, "file", 17307c478bd9Sstevel@tonic-gate sep->se_conf_file)) != 0) 17317c478bd9Sstevel@tonic-gate goto err; 17327c478bd9Sstevel@tonic-gate if ((errno = nvlist_add_int32(cmd_nvlist, "line", sep->se_lineno)) != 0) 17337c478bd9Sstevel@tonic-gate goto err; 17347c478bd9Sstevel@tonic-gate if ((errno = nvlist_add_string(cmd_nvlist, "user", sep->se_user)) != 0) 17357c478bd9Sstevel@tonic-gate goto err; 17367c478bd9Sstevel@tonic-gate 17377c478bd9Sstevel@tonic-gate if (sep->se_uid != (uid_t)0) { 17387c478bd9Sstevel@tonic-gate if ((errno = nvlist_add_int32(cmd_nvlist, "uid", 17397c478bd9Sstevel@tonic-gate sep->se_uid)) != 0) 17407c478bd9Sstevel@tonic-gate goto err; 17417c478bd9Sstevel@tonic-gate if ((errno = nvlist_add_int32(cmd_nvlist, "gid", 17427c478bd9Sstevel@tonic-gate sep->se_gid)) != 0) 17437c478bd9Sstevel@tonic-gate goto err; 17447c478bd9Sstevel@tonic-gate } 17457c478bd9Sstevel@tonic-gate 17467c478bd9Sstevel@tonic-gate cmd_event = sysevent_alloc_event(hdr->class, hdr->subclass, hdr->vendor, 17477c478bd9Sstevel@tonic-gate hdr->publisher, cmd_nvlist); 17487c478bd9Sstevel@tonic-gate if (cmd_event == NULL) { 17497c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SYSEVENT_ALLOC_ERR, 17507c478bd9Sstevel@tonic-gate sep->se_conf_file, sep->se_lineno, 17517c478bd9Sstevel@tonic-gate strerror(errno)); 17527c478bd9Sstevel@tonic-gate nvlist_free(cmd_nvlist); 17537c478bd9Sstevel@tonic-gate freestr(line); 17547c478bd9Sstevel@tonic-gate return (1); 17557c478bd9Sstevel@tonic-gate } 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate nvlist_free(cmd_nvlist); 17587c478bd9Sstevel@tonic-gate freestr(line); 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate /* 17617c478bd9Sstevel@tonic-gate * Place cmd_event on queue to be transported to syseventconfd 17627c478bd9Sstevel@tonic-gate */ 17637c478bd9Sstevel@tonic-gate if ((new_cmd = sc_malloc(sizeof (cmdqueue_t))) == NULL) { 17647c478bd9Sstevel@tonic-gate sysevent_free(cmd_event); 17657c478bd9Sstevel@tonic-gate return (1); 17667c478bd9Sstevel@tonic-gate } 17677c478bd9Sstevel@tonic-gate new_cmd->event = cmd_event; 17687c478bd9Sstevel@tonic-gate new_cmd->next = NULL; 17697c478bd9Sstevel@tonic-gate (void) mutex_lock(&cmdq_lock); 17707c478bd9Sstevel@tonic-gate if (cmdq == NULL) { 17717c478bd9Sstevel@tonic-gate cmdq = new_cmd; 17727c478bd9Sstevel@tonic-gate } else { 17737c478bd9Sstevel@tonic-gate cmdq_tail->next = new_cmd; 17747c478bd9Sstevel@tonic-gate } 17757c478bd9Sstevel@tonic-gate cmdq_cnt++; 17767c478bd9Sstevel@tonic-gate cmdq_tail = new_cmd; 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate /* 17797c478bd9Sstevel@tonic-gate * signal queue flush thread 17807c478bd9Sstevel@tonic-gate */ 17817c478bd9Sstevel@tonic-gate (void) cond_signal(&cmdq_cv); 17827c478bd9Sstevel@tonic-gate 17837c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cmdq_lock); 17847c478bd9Sstevel@tonic-gate 17857c478bd9Sstevel@tonic-gate return (0); 17867c478bd9Sstevel@tonic-gate 17877c478bd9Sstevel@tonic-gate err: 17887c478bd9Sstevel@tonic-gate syslog(LOG_ERR, NVLIST_BUILD_ERR, 17897c478bd9Sstevel@tonic-gate sep->se_conf_file, sep->se_lineno, strerror(errno)); 17907c478bd9Sstevel@tonic-gate nvlist_free(cmd_nvlist); 17917c478bd9Sstevel@tonic-gate freestr(line); 17927c478bd9Sstevel@tonic-gate return (1); 17937c478bd9Sstevel@tonic-gate } 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate 17967c478bd9Sstevel@tonic-gate static int 17977c478bd9Sstevel@tonic-gate transport_event(sysevent_t *event) 17987c478bd9Sstevel@tonic-gate { 17997c478bd9Sstevel@tonic-gate int rval; 18007c478bd9Sstevel@tonic-gate 18017c478bd9Sstevel@tonic-gate rval = sysevent_send_event(confd_handle, event); 18027c478bd9Sstevel@tonic-gate if (rval != 0) { 18037c478bd9Sstevel@tonic-gate switch (errno) { 18047c478bd9Sstevel@tonic-gate case EAGAIN: 18057c478bd9Sstevel@tonic-gate case EINTR: 18067c478bd9Sstevel@tonic-gate /* 18077c478bd9Sstevel@tonic-gate * syseventconfd daemon may be forking, stop 18087c478bd9Sstevel@tonic-gate * attempting to empty the queue momentarily. 18097c478bd9Sstevel@tonic-gate */ 18107c478bd9Sstevel@tonic-gate rval = errno; 18117c478bd9Sstevel@tonic-gate break; 18127c478bd9Sstevel@tonic-gate case ENOENT: 18137c478bd9Sstevel@tonic-gate case EBADF: 18147c478bd9Sstevel@tonic-gate /* 18157c478bd9Sstevel@tonic-gate * start/restart the syseventconfd daemon, 18167c478bd9Sstevel@tonic-gate * allowing for some delay when starting 18177c478bd9Sstevel@tonic-gate * up before it begins to reply. 18187c478bd9Sstevel@tonic-gate */ 18197c478bd9Sstevel@tonic-gate if (confd_state == CONFD_STATE_NOT_RUNNING || 18207c478bd9Sstevel@tonic-gate confd_state == CONFD_STATE_OK) { 18217c478bd9Sstevel@tonic-gate confd_state = CONFD_STATE_STARTED; 18227c478bd9Sstevel@tonic-gate start_syseventconfd(); 18237c478bd9Sstevel@tonic-gate confd_retries = 0; 18247c478bd9Sstevel@tonic-gate rval = EAGAIN; 18257c478bd9Sstevel@tonic-gate } else if (confd_state == CONFD_STATE_STARTED && 18267c478bd9Sstevel@tonic-gate confd_retries < 16) { 18277c478bd9Sstevel@tonic-gate if (++confd_retries == 16) { 18287c478bd9Sstevel@tonic-gate confd_state = CONFD_STATE_ERR; 18297c478bd9Sstevel@tonic-gate if (confd_err_msg_emitted == 0) { 18307c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 18317c478bd9Sstevel@tonic-gate SYSEVENTCONFD_ERR); 18327c478bd9Sstevel@tonic-gate confd_err_msg_emitted = 1; 18337c478bd9Sstevel@tonic-gate } 18347c478bd9Sstevel@tonic-gate } 18357c478bd9Sstevel@tonic-gate rval = EAGAIN; 18367c478bd9Sstevel@tonic-gate } else { 18377c478bd9Sstevel@tonic-gate rval = errno; 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate break; 18407c478bd9Sstevel@tonic-gate default: 18417c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SYSEVENTCONFD_TRAN_ERR, 18427c478bd9Sstevel@tonic-gate strerror(errno)); 18437c478bd9Sstevel@tonic-gate rval = errno; 18447c478bd9Sstevel@tonic-gate break; 18457c478bd9Sstevel@tonic-gate } 18467c478bd9Sstevel@tonic-gate } else if (confd_state != CONFD_STATE_OK) { 18477c478bd9Sstevel@tonic-gate if (confd_state == CONFD_STATE_ERR) { 18487c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SYSEVENTCONFD_OK); 18497c478bd9Sstevel@tonic-gate confd_err_msg_emitted = 0; 18507c478bd9Sstevel@tonic-gate } 18517c478bd9Sstevel@tonic-gate confd_state = CONFD_STATE_OK; 18527c478bd9Sstevel@tonic-gate confd_retries = 0; 18537c478bd9Sstevel@tonic-gate confd_err_msg_emitted = 0; 18547c478bd9Sstevel@tonic-gate } 18557c478bd9Sstevel@tonic-gate return (rval); 18567c478bd9Sstevel@tonic-gate } 18577c478bd9Sstevel@tonic-gate 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate /* 18607c478bd9Sstevel@tonic-gate * Send events on queue to syseventconfd daemon. We queue events 18617c478bd9Sstevel@tonic-gate * here since the daemon is unable to handle events during an 18627c478bd9Sstevel@tonic-gate * active fork/exec, returning EAGAIN as a result. It is grossly 18637c478bd9Sstevel@tonic-gate * inefficient to bounce these events back to syseventd, so 18647c478bd9Sstevel@tonic-gate * we queue them here for delivery. 18657c478bd9Sstevel@tonic-gate * 18667c478bd9Sstevel@tonic-gate * EAGAIN/EINTR don't indicate errors with the transport to 18677c478bd9Sstevel@tonic-gate * syseventconfd itself, just the daemon is busy or some 18687c478bd9Sstevel@tonic-gate * other transient difficulty. We retry EBADF and other errors 18697c478bd9Sstevel@tonic-gate * for some time, then eventually give up - something's broken. 18707c478bd9Sstevel@tonic-gate * 18717c478bd9Sstevel@tonic-gate * Error handling strategy: 18727c478bd9Sstevel@tonic-gate * If we're trying to shut down and the syseventconfd daemon isn't 18737c478bd9Sstevel@tonic-gate * responding, abort the queue so we don't cause the fini to hang 18747c478bd9Sstevel@tonic-gate * forever. Otherwise, EAGAIN/EINTR are retried forever, as 18757c478bd9Sstevel@tonic-gate * we presume the daemon is active but either busy or some transient 18767c478bd9Sstevel@tonic-gate * state is preventing the transport. We make considerable effort 18777c478bd9Sstevel@tonic-gate * to retry EBADF since the daemon may take some time to come up when 18787c478bd9Sstevel@tonic-gate * restarted so don't want to give up too easily. Once we enter 18797c478bd9Sstevel@tonic-gate * the DISABLED state, we stop handling events altogther to 18807c478bd9Sstevel@tonic-gate * avoid thrashing the system if the syseventconfd binary is 18817c478bd9Sstevel@tonic-gate * corrupted or missing. This state can be cleared by issuing 18827c478bd9Sstevel@tonic-gate * a HUP signal to the syseventd daemon. For errors other than 18837c478bd9Sstevel@tonic-gate * EAGAIN/EINTR/EBADF, we just drop the event and if we get 18847c478bd9Sstevel@tonic-gate * a certain number of these in a row, we enter the DISABLED 18857c478bd9Sstevel@tonic-gate * state. 18867c478bd9Sstevel@tonic-gate */ 18877c478bd9Sstevel@tonic-gate 18887c478bd9Sstevel@tonic-gate static void 18897c478bd9Sstevel@tonic-gate transport_queued_events() 18907c478bd9Sstevel@tonic-gate { 18917c478bd9Sstevel@tonic-gate int rval; 18927c478bd9Sstevel@tonic-gate cmdqueue_t *cmd; 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate (void) mutex_lock(&cmdq_lock); 18957c478bd9Sstevel@tonic-gate while (cmdq != NULL) { 18967c478bd9Sstevel@tonic-gate cmd = cmdq; 18977c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cmdq_lock); 18987c478bd9Sstevel@tonic-gate rval = transport_event(cmd->event); 18997c478bd9Sstevel@tonic-gate (void) mutex_lock(&cmdq_lock); 19007c478bd9Sstevel@tonic-gate if (rval != 0) { 19017c478bd9Sstevel@tonic-gate switch (rval) { 19027c478bd9Sstevel@tonic-gate case EAGAIN: 19037c478bd9Sstevel@tonic-gate case EINTR: 19047c478bd9Sstevel@tonic-gate /* 19057c478bd9Sstevel@tonic-gate * Limit retries in the case of fini 19067c478bd9Sstevel@tonic-gate */ 19077c478bd9Sstevel@tonic-gate if (want_fini) { 19087c478bd9Sstevel@tonic-gate if (++transport_retries == 16) { 19097c478bd9Sstevel@tonic-gate abort_cmd_queue(); 19107c478bd9Sstevel@tonic-gate } 19117c478bd9Sstevel@tonic-gate } 19127c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cmdq_lock); 19137c478bd9Sstevel@tonic-gate return; 19147c478bd9Sstevel@tonic-gate case EBADF: 19157c478bd9Sstevel@tonic-gate /* 19167c478bd9Sstevel@tonic-gate * retry up to 16 times 19177c478bd9Sstevel@tonic-gate */ 19187c478bd9Sstevel@tonic-gate if (want_fini || ++transport_retries == 16) { 19197c478bd9Sstevel@tonic-gate abort_cmd_queue(); 19207c478bd9Sstevel@tonic-gate } 19217c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cmdq_lock); 19227c478bd9Sstevel@tonic-gate return; 19237c478bd9Sstevel@tonic-gate default: 19247c478bd9Sstevel@tonic-gate /* 19257c478bd9Sstevel@tonic-gate * After 16 sequential errors, give up 19267c478bd9Sstevel@tonic-gate */ 19277c478bd9Sstevel@tonic-gate if (++transport_retries == 16) { 19287c478bd9Sstevel@tonic-gate abort_cmd_queue(); 19297c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cmdq_lock); 19307c478bd9Sstevel@tonic-gate return; 19317c478bd9Sstevel@tonic-gate } 19327c478bd9Sstevel@tonic-gate /* 19337c478bd9Sstevel@tonic-gate * We don't retry these errors, we 19347c478bd9Sstevel@tonic-gate * fall through to remove this event 19357c478bd9Sstevel@tonic-gate * from the queue. 19367c478bd9Sstevel@tonic-gate */ 19377c478bd9Sstevel@tonic-gate break; 19387c478bd9Sstevel@tonic-gate } 19397c478bd9Sstevel@tonic-gate } else { 19407c478bd9Sstevel@tonic-gate transport_retries = 0; 19417c478bd9Sstevel@tonic-gate } 19427c478bd9Sstevel@tonic-gate 19437c478bd9Sstevel@tonic-gate /* 19447c478bd9Sstevel@tonic-gate * Take completed event off queue 19457c478bd9Sstevel@tonic-gate */ 19467c478bd9Sstevel@tonic-gate cmdq_cnt--; 19477c478bd9Sstevel@tonic-gate cmdq = cmdq->next; 19487c478bd9Sstevel@tonic-gate if (cmdq == NULL) { 19497c478bd9Sstevel@tonic-gate cmdq_tail = NULL; 19507c478bd9Sstevel@tonic-gate } 19517c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cmdq_lock); 19527c478bd9Sstevel@tonic-gate sysevent_free(cmd->event); 19537c478bd9Sstevel@tonic-gate sc_free(cmd, sizeof (cmdqueue_t)); 19547c478bd9Sstevel@tonic-gate (void) mutex_lock(&cmdq_lock); 19557c478bd9Sstevel@tonic-gate } 19567c478bd9Sstevel@tonic-gate 19577c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cmdq_lock); 19587c478bd9Sstevel@tonic-gate } 19597c478bd9Sstevel@tonic-gate 19607c478bd9Sstevel@tonic-gate 19617c478bd9Sstevel@tonic-gate static void 19627c478bd9Sstevel@tonic-gate queue_flush_thr() 19637c478bd9Sstevel@tonic-gate { 19647c478bd9Sstevel@tonic-gate int n; 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate (void) mutex_lock(&cmdq_lock); 19677c478bd9Sstevel@tonic-gate for (;;) { 19687c478bd9Sstevel@tonic-gate while (cmdq_cnt == 0 && want_fini == 0) { 19697c478bd9Sstevel@tonic-gate (void) cond_wait(&cmdq_cv, &cmdq_lock); 19707c478bd9Sstevel@tonic-gate } 19717c478bd9Sstevel@tonic-gate if (cmdq_cnt == 0 && want_fini) { 19727c478bd9Sstevel@tonic-gate (void) cond_signal(&cmdq_thr_cv); 19737c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cmdq_lock); 19747c478bd9Sstevel@tonic-gate thr_exit(NULL); 19757c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 19767c478bd9Sstevel@tonic-gate } 19777c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cmdq_lock); 19787c478bd9Sstevel@tonic-gate transport_queued_events(); 19797c478bd9Sstevel@tonic-gate (void) mutex_lock(&cmdq_lock); 19807c478bd9Sstevel@tonic-gate if (cmdq_cnt != 0) { 19817c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cmdq_lock); 19827c478bd9Sstevel@tonic-gate if (want_fini == 0 && confd_err_msg_emitted) { 19837c478bd9Sstevel@tonic-gate for (n = 0; n < 60; n++) { 19847c478bd9Sstevel@tonic-gate (void) sleep(1); 19857c478bd9Sstevel@tonic-gate if (want_fini) 19867c478bd9Sstevel@tonic-gate break; 19877c478bd9Sstevel@tonic-gate } 19887c478bd9Sstevel@tonic-gate } else { 19897c478bd9Sstevel@tonic-gate (void) sleep(1); 19907c478bd9Sstevel@tonic-gate } 19917c478bd9Sstevel@tonic-gate (void) mutex_lock(&cmdq_lock); 19927c478bd9Sstevel@tonic-gate } 19937c478bd9Sstevel@tonic-gate } 19947c478bd9Sstevel@tonic-gate } 19957c478bd9Sstevel@tonic-gate 19967c478bd9Sstevel@tonic-gate 19977c478bd9Sstevel@tonic-gate /* 19987c478bd9Sstevel@tonic-gate * syseventd daemon module event handler 19997c478bd9Sstevel@tonic-gate * 20007c478bd9Sstevel@tonic-gate * The syseventd daemon calls this handler with each event 20017c478bd9Sstevel@tonic-gate * for this module to handle the event as appropriate. 20027c478bd9Sstevel@tonic-gate * The task of this module is to compare the event's 20037c478bd9Sstevel@tonic-gate * class/subclass/publisher/vendor against the list of 20047c478bd9Sstevel@tonic-gate * event specifications provided in the installed 20057c478bd9Sstevel@tonic-gate * sysevent.conf files. Build and execute the 20067c478bd9Sstevel@tonic-gate * defined command for that event specification 20077c478bd9Sstevel@tonic-gate * for each match. 20087c478bd9Sstevel@tonic-gate * 20097c478bd9Sstevel@tonic-gate * Events are matched against the class, subclass, vendor 20107c478bd9Sstevel@tonic-gate * and publisher specifications. Any field not to be matched 20117c478bd9Sstevel@tonic-gate * against an event should be set to '-'. A specification 20127c478bd9Sstevel@tonic-gate * of '- - - -' generates a match against every event. 20137c478bd9Sstevel@tonic-gate */ 20147c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 20157c478bd9Sstevel@tonic-gate static int 20167c478bd9Sstevel@tonic-gate sysevent_conf_event(sysevent_t *ev, int flag) 20177c478bd9Sstevel@tonic-gate { 20187c478bd9Sstevel@tonic-gate int ret = 0; 20197c478bd9Sstevel@tonic-gate char *vendor; 20207c478bd9Sstevel@tonic-gate char *publisher; 20217c478bd9Sstevel@tonic-gate char *class; 20227c478bd9Sstevel@tonic-gate char *subclass; 20237c478bd9Sstevel@tonic-gate syseventtab_t *sep; 20247c478bd9Sstevel@tonic-gate sysevent_hdr_info_t hdr; 20257c478bd9Sstevel@tonic-gate uint64_t seq; 20267c478bd9Sstevel@tonic-gate hrtime_t ts; 20277c478bd9Sstevel@tonic-gate 20287c478bd9Sstevel@tonic-gate /* 20297c478bd9Sstevel@tonic-gate * If we've been completely unable to communicate with 20307c478bd9Sstevel@tonic-gate * syseventconfd, there's not much we can do. 20317c478bd9Sstevel@tonic-gate */ 20327c478bd9Sstevel@tonic-gate if (confd_state == CONFD_STATE_DISABLED) { 20337c478bd9Sstevel@tonic-gate return (0); 20347c478bd9Sstevel@tonic-gate } 20357c478bd9Sstevel@tonic-gate 20367c478bd9Sstevel@tonic-gate /* 20377c478bd9Sstevel@tonic-gate * sysevent_get_seq(ev) < ev_seq): 20387c478bd9Sstevel@tonic-gate * an event we have played before, ignore it 20397c478bd9Sstevel@tonic-gate * sysevent_get_seq(ev) == ev_seq): 20407c478bd9Sstevel@tonic-gate * ev_nretries > 0, an event being retried 20417c478bd9Sstevel@tonic-gate * sysevent_get_seq(ev) > ev_seq): 20427c478bd9Sstevel@tonic-gate * a new event 20437c478bd9Sstevel@tonic-gate */ 20447c478bd9Sstevel@tonic-gate if (debug_level >= DBG_EVENTS) { 20457c478bd9Sstevel@tonic-gate if (sysevent_get_seq(ev) == ev_seq && ev_nretries > 0) { 20467c478bd9Sstevel@tonic-gate syseventd_print(DBG_EVENTS, 20477c478bd9Sstevel@tonic-gate "sequence: %lld/%lld, retry %d\n", 20487c478bd9Sstevel@tonic-gate sysevent_get_seq(ev), ev_seq, ev_nretries); 20497c478bd9Sstevel@tonic-gate } else if (sysevent_get_seq(ev) > ev_seq) { 20507c478bd9Sstevel@tonic-gate syseventd_print(DBG_EVENTS, 20517c478bd9Sstevel@tonic-gate "sequence: %lld/%lld\n", 20527c478bd9Sstevel@tonic-gate sysevent_get_seq(ev), ev_seq); 20537c478bd9Sstevel@tonic-gate } 20547c478bd9Sstevel@tonic-gate } 20557c478bd9Sstevel@tonic-gate 20567c478bd9Sstevel@tonic-gate seq = sysevent_get_seq(ev); 20577c478bd9Sstevel@tonic-gate sysevent_get_time(ev, &ts); 20587c478bd9Sstevel@tonic-gate 20597c478bd9Sstevel@tonic-gate if (seq > ev_seq || ts > ev_ts) { 20607c478bd9Sstevel@tonic-gate ev_nretries = 0; 20617c478bd9Sstevel@tonic-gate } else if (first_event == 0 && 20627c478bd9Sstevel@tonic-gate (((seq < ev_seq) || (seq == 0 && ts > ev_ts)) || 20637c478bd9Sstevel@tonic-gate (seq == ev_seq && ev_nretries == 0))) { 20647c478bd9Sstevel@tonic-gate syseventd_print(DBG_TEST, 20657c478bd9Sstevel@tonic-gate "out-of-order sequence: received %lld/0x%llx, " 20667c478bd9Sstevel@tonic-gate "expected %lld/0x%llx\n", seq, ts, ev_seq+1, ev_ts); 20677c478bd9Sstevel@tonic-gate return (ret); 20687c478bd9Sstevel@tonic-gate } 20697c478bd9Sstevel@tonic-gate 20707c478bd9Sstevel@tonic-gate ev_ts = ts; 20717c478bd9Sstevel@tonic-gate ev_seq = seq; 20727c478bd9Sstevel@tonic-gate first_event = 0; 20737c478bd9Sstevel@tonic-gate 20747c478bd9Sstevel@tonic-gate /* 20757c478bd9Sstevel@tonic-gate * sysevent_get_vendor_name() and sysevent_get_pub_name() 20767c478bd9Sstevel@tonic-gate * allocate strings which must be freed. 20777c478bd9Sstevel@tonic-gate */ 20787c478bd9Sstevel@tonic-gate vendor = sysevent_get_vendor_name(ev); 20797c478bd9Sstevel@tonic-gate publisher = sysevent_get_pub_name(ev); 20807c478bd9Sstevel@tonic-gate class = sysevent_get_class_name(ev); 20817c478bd9Sstevel@tonic-gate subclass = sysevent_get_subclass_name(ev); 20827c478bd9Sstevel@tonic-gate 20837c478bd9Sstevel@tonic-gate if (vendor == NULL || publisher == NULL) { 20847c478bd9Sstevel@tonic-gate syseventd_print(DBG_EVENTS, "Short on memory with vendor " 20857c478bd9Sstevel@tonic-gate "and/or publisher string generation\n"); 20867c478bd9Sstevel@tonic-gate /* Temporary short on memory */ 20877c478bd9Sstevel@tonic-gate ev_nretries++; 20887c478bd9Sstevel@tonic-gate free(publisher); 20897c478bd9Sstevel@tonic-gate free(vendor); 20907c478bd9Sstevel@tonic-gate return (EAGAIN); 20917c478bd9Sstevel@tonic-gate } 20927c478bd9Sstevel@tonic-gate 20937c478bd9Sstevel@tonic-gate syseventd_print(DBG_EVENTS, 20947c478bd9Sstevel@tonic-gate "%s event %lld: vendor='%s' publisher='%s' class='%s' " 20957c478bd9Sstevel@tonic-gate "subclass='%s'\n", whoami, sysevent_get_seq(ev), vendor, 20967c478bd9Sstevel@tonic-gate publisher, class, subclass); 20977c478bd9Sstevel@tonic-gate 20987c478bd9Sstevel@tonic-gate for (sep = syseventtab; sep; sep = sep->se_next) { 20997c478bd9Sstevel@tonic-gate if (strcmp(sep->se_vendor, "-") != 0) { 21007c478bd9Sstevel@tonic-gate if (strcmp(sep->se_vendor, vendor) != 0) 21017c478bd9Sstevel@tonic-gate continue; 21027c478bd9Sstevel@tonic-gate } 21037c478bd9Sstevel@tonic-gate if (strcmp(sep->se_publisher, "-") != 0) { 21047c478bd9Sstevel@tonic-gate if (strcmp(sep->se_publisher, publisher) != 0) 21057c478bd9Sstevel@tonic-gate continue; 21067c478bd9Sstevel@tonic-gate } 21077c478bd9Sstevel@tonic-gate if (strcmp(sep->se_class, "-") != 0) { 21087c478bd9Sstevel@tonic-gate if (strcmp(sep->se_class, class) != 0) 21097c478bd9Sstevel@tonic-gate continue; 21107c478bd9Sstevel@tonic-gate } 21117c478bd9Sstevel@tonic-gate if (strcmp(sep->se_subclass, "-") != 0) { 21127c478bd9Sstevel@tonic-gate if (strcmp(sep->se_subclass, subclass) != 0) 21137c478bd9Sstevel@tonic-gate continue; 21147c478bd9Sstevel@tonic-gate } 21157c478bd9Sstevel@tonic-gate syseventd_print(DBG_MATCHES, " event match: %s, line %d\n", 21167c478bd9Sstevel@tonic-gate sep->se_conf_file, sep->se_lineno); 21177c478bd9Sstevel@tonic-gate hdr.class = class; 21187c478bd9Sstevel@tonic-gate hdr.subclass = subclass; 21197c478bd9Sstevel@tonic-gate hdr.vendor = vendor; 21207c478bd9Sstevel@tonic-gate hdr.publisher = publisher; 21217c478bd9Sstevel@tonic-gate if ((ret = queue_event(ev, sep, &hdr)) != 0) 21227c478bd9Sstevel@tonic-gate break; 21237c478bd9Sstevel@tonic-gate } 21247c478bd9Sstevel@tonic-gate 21257c478bd9Sstevel@tonic-gate if (ret == 0) { 21267c478bd9Sstevel@tonic-gate ev_nretries = 0; 21277c478bd9Sstevel@tonic-gate } else { 21287c478bd9Sstevel@tonic-gate /* 21297c478bd9Sstevel@tonic-gate * Ask syseventd to retry any failed event. If we have 21307c478bd9Sstevel@tonic-gate * reached the limit on retries, emit a msg that we're 21317c478bd9Sstevel@tonic-gate * not going to be able to service it. 21327c478bd9Sstevel@tonic-gate */ 21337c478bd9Sstevel@tonic-gate if (ev_nretries == SE_MAX_RETRY_LIMIT) { 21347c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SYSEVENT_SEND_ERR, 21357c478bd9Sstevel@tonic-gate sep->se_conf_file, sep->se_lineno, errno); 21367c478bd9Sstevel@tonic-gate } else { 21377c478bd9Sstevel@tonic-gate syseventd_print(DBG_TEST, "%s event %lld: " 21387c478bd9Sstevel@tonic-gate "'%s' '%s' '%s' '%s - errno %d, retry %d\n", 21397c478bd9Sstevel@tonic-gate whoami, sysevent_get_seq(ev), vendor, 21407c478bd9Sstevel@tonic-gate publisher, class, subclass, errno, ev_nretries); 21417c478bd9Sstevel@tonic-gate } 21427c478bd9Sstevel@tonic-gate ret = EAGAIN; 21437c478bd9Sstevel@tonic-gate ev_nretries++; 21447c478bd9Sstevel@tonic-gate } 21457c478bd9Sstevel@tonic-gate 21467c478bd9Sstevel@tonic-gate free(publisher); 21477c478bd9Sstevel@tonic-gate free(vendor); 21487c478bd9Sstevel@tonic-gate 21497c478bd9Sstevel@tonic-gate return (ret); 21507c478bd9Sstevel@tonic-gate } 21517c478bd9Sstevel@tonic-gate 21527c478bd9Sstevel@tonic-gate /* 21537c478bd9Sstevel@tonic-gate * syseventd daemon module initialization 21547c478bd9Sstevel@tonic-gate */ 21557c478bd9Sstevel@tonic-gate struct slm_mod_ops * 21567c478bd9Sstevel@tonic-gate slm_init() 21577c478bd9Sstevel@tonic-gate { 21587c478bd9Sstevel@tonic-gate char lock_file[PATH_MAX+1]; 21597c478bd9Sstevel@tonic-gate int lock_fd; 21607c478bd9Sstevel@tonic-gate int err; 21617c478bd9Sstevel@tonic-gate 21627c478bd9Sstevel@tonic-gate /* 21637c478bd9Sstevel@tonic-gate * This functionality is not supported in the mini-root 21647c478bd9Sstevel@tonic-gate * environment, ie install. If root_dir is set, implying 21657c478bd9Sstevel@tonic-gate * install, we quietly fail. Return dummy ops rather 21667c478bd9Sstevel@tonic-gate * than NULL to avoid error msgs out of syseventd. 21677c478bd9Sstevel@tonic-gate */ 21687c478bd9Sstevel@tonic-gate if (strcmp(root_dir, "") != 0) { 21697c478bd9Sstevel@tonic-gate return (&sysevent_conf_dummy_mod_ops); 21707c478bd9Sstevel@tonic-gate } 21717c478bd9Sstevel@tonic-gate 21727c478bd9Sstevel@tonic-gate ev_nretries = 0; 21737c478bd9Sstevel@tonic-gate first_event = 1; 21747c478bd9Sstevel@tonic-gate 21757c478bd9Sstevel@tonic-gate /* 21767c478bd9Sstevel@tonic-gate * Initialize the channel to syseventconfd 21777c478bd9Sstevel@tonic-gate */ 21787c478bd9Sstevel@tonic-gate confd_handle = sysevent_open_channel_alt(SYSEVENTCONFD_SERVICE_DOOR); 21797c478bd9Sstevel@tonic-gate if (confd_handle == NULL) { 21807c478bd9Sstevel@tonic-gate syslog(LOG_ERR, CHANNEL_OPEN_ERR); 21817c478bd9Sstevel@tonic-gate return (NULL); 21827c478bd9Sstevel@tonic-gate } 21837c478bd9Sstevel@tonic-gate 21847c478bd9Sstevel@tonic-gate if (sysevent_bind_publisher(confd_handle) != 0) { 21857c478bd9Sstevel@tonic-gate if (errno == EBUSY) { 21867c478bd9Sstevel@tonic-gate sysevent_cleanup_publishers(confd_handle); 21877c478bd9Sstevel@tonic-gate if (sysevent_bind_publisher(confd_handle) != 0) { 21887c478bd9Sstevel@tonic-gate sysevent_close_channel(confd_handle); 21897c478bd9Sstevel@tonic-gate return (NULL); 21907c478bd9Sstevel@tonic-gate } 21917c478bd9Sstevel@tonic-gate } 21927c478bd9Sstevel@tonic-gate } 21937c478bd9Sstevel@tonic-gate 21947c478bd9Sstevel@tonic-gate sysevent_cleanup_subscribers(confd_handle); 21957c478bd9Sstevel@tonic-gate 21967c478bd9Sstevel@tonic-gate cmdq = NULL; 21977c478bd9Sstevel@tonic-gate cmdq_tail = NULL; 21987c478bd9Sstevel@tonic-gate cmdq_cnt = 0; 21997c478bd9Sstevel@tonic-gate want_fini = 0; 22007c478bd9Sstevel@tonic-gate confd_err_msg_emitted = 0; 22017c478bd9Sstevel@tonic-gate if (confd_state != CONFD_STATE_OK) { 22027c478bd9Sstevel@tonic-gate confd_state = CONFD_STATE_NOT_RUNNING; 22037c478bd9Sstevel@tonic-gate } 22047c478bd9Sstevel@tonic-gate 22057c478bd9Sstevel@tonic-gate confd_retries = 0; 22067c478bd9Sstevel@tonic-gate transport_retries = 0; 22077c478bd9Sstevel@tonic-gate 22087c478bd9Sstevel@tonic-gate (void) mutex_init(&cmdq_lock, USYNC_THREAD, NULL); 22097c478bd9Sstevel@tonic-gate (void) cond_init(&cmdq_cv, USYNC_THREAD, NULL); 22107c478bd9Sstevel@tonic-gate (void) cond_init(&cmdq_thr_cv, USYNC_THREAD, NULL); 22117c478bd9Sstevel@tonic-gate 22127c478bd9Sstevel@tonic-gate /* 22137c478bd9Sstevel@tonic-gate * Create thread to flush cmd queue 22147c478bd9Sstevel@tonic-gate */ 22157c478bd9Sstevel@tonic-gate if ((err = thr_create(NULL, NULL, (void *(*)(void*))queue_flush_thr, 22167c478bd9Sstevel@tonic-gate (void *)NULL, 0, &cmdq_thr_id)) != 0) { 22177c478bd9Sstevel@tonic-gate syslog(LOG_ERR, THR_CREATE_ERR, strerror(err)); 22187c478bd9Sstevel@tonic-gate sysevent_close_channel(confd_handle); 22197c478bd9Sstevel@tonic-gate confd_handle = NULL; 22207c478bd9Sstevel@tonic-gate (void) mutex_destroy(&cmdq_lock); 22217c478bd9Sstevel@tonic-gate (void) cond_destroy(&cmdq_cv); 22227c478bd9Sstevel@tonic-gate (void) cond_destroy(&cmdq_thr_cv); 22237c478bd9Sstevel@tonic-gate return (NULL); 22247c478bd9Sstevel@tonic-gate } 22257c478bd9Sstevel@tonic-gate 22267c478bd9Sstevel@tonic-gate if ((lock_fd = enter_lock(lock_file)) == -1) { 22277c478bd9Sstevel@tonic-gate (void) thr_join(cmdq_thr_id, NULL, NULL); 22287c478bd9Sstevel@tonic-gate sysevent_close_channel(confd_handle); 22297c478bd9Sstevel@tonic-gate confd_handle = NULL; 22307c478bd9Sstevel@tonic-gate (void) mutex_destroy(&cmdq_lock); 22317c478bd9Sstevel@tonic-gate (void) cond_destroy(&cmdq_cv); 22327c478bd9Sstevel@tonic-gate (void) cond_destroy(&cmdq_thr_cv); 22337c478bd9Sstevel@tonic-gate return (NULL); 22347c478bd9Sstevel@tonic-gate } 22357c478bd9Sstevel@tonic-gate 22367c478bd9Sstevel@tonic-gate build_event_table(); 22377c478bd9Sstevel@tonic-gate exit_lock(lock_fd, lock_file); 22387c478bd9Sstevel@tonic-gate return (&sysevent_conf_mod_ops); 22397c478bd9Sstevel@tonic-gate } 22407c478bd9Sstevel@tonic-gate 22417c478bd9Sstevel@tonic-gate /* 22427c478bd9Sstevel@tonic-gate * syseventd daemon module tear-down 22437c478bd9Sstevel@tonic-gate */ 22447c478bd9Sstevel@tonic-gate void 22457c478bd9Sstevel@tonic-gate slm_fini() 22467c478bd9Sstevel@tonic-gate { 22477c478bd9Sstevel@tonic-gate int err; 22487c478bd9Sstevel@tonic-gate 22497c478bd9Sstevel@tonic-gate /* 22507c478bd9Sstevel@tonic-gate * Nothing to clean up if we're in the install environment 22517c478bd9Sstevel@tonic-gate */ 22527c478bd9Sstevel@tonic-gate if (strcmp(root_dir, "") != 0) { 22537c478bd9Sstevel@tonic-gate return; 22547c478bd9Sstevel@tonic-gate } 22557c478bd9Sstevel@tonic-gate 22567c478bd9Sstevel@tonic-gate /* 22577c478bd9Sstevel@tonic-gate * Wait for the queue to drain 22587c478bd9Sstevel@tonic-gate */ 22597c478bd9Sstevel@tonic-gate (void) mutex_lock(&cmdq_lock); 22607c478bd9Sstevel@tonic-gate want_fini = 1; 22617c478bd9Sstevel@tonic-gate (void) cond_signal(&cmdq_cv); 22627c478bd9Sstevel@tonic-gate (void) cond_wait(&cmdq_thr_cv, &cmdq_lock); 22637c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cmdq_lock); 22647c478bd9Sstevel@tonic-gate 22657c478bd9Sstevel@tonic-gate /* 22667c478bd9Sstevel@tonic-gate * Shut down the the queue flush thread 22677c478bd9Sstevel@tonic-gate */ 22687c478bd9Sstevel@tonic-gate if ((err = thr_join(cmdq_thr_id, NULL, NULL)) != 0) { 22697c478bd9Sstevel@tonic-gate syslog(LOG_ERR, THR_JOIN_ERR, strerror(err)); 22707c478bd9Sstevel@tonic-gate } 22717c478bd9Sstevel@tonic-gate 22727c478bd9Sstevel@tonic-gate sysevent_close_channel(confd_handle); 22737c478bd9Sstevel@tonic-gate confd_handle = NULL; 22747c478bd9Sstevel@tonic-gate (void) mutex_destroy(&cmdq_lock); 22757c478bd9Sstevel@tonic-gate (void) cond_destroy(&cmdq_cv); 22767c478bd9Sstevel@tonic-gate (void) cond_destroy(&cmdq_thr_cv); 22777c478bd9Sstevel@tonic-gate free_event_table(); 22787c478bd9Sstevel@tonic-gate } 22797c478bd9Sstevel@tonic-gate 22807c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 22817c478bd9Sstevel@tonic-gate static int 22827c478bd9Sstevel@tonic-gate sysevent_conf_dummy_event(sysevent_t *ev, int flag) 22837c478bd9Sstevel@tonic-gate { 22847c478bd9Sstevel@tonic-gate return (0); 22857c478bd9Sstevel@tonic-gate } 2286