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
5f79b6382SJustin Frank  * Common Development and Distribution License (the "License").
6f79b6382SJustin Frank  * 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 /*
22f79b6382SJustin Frank  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * PICL plug-in to create environment tree nodes.
287c478bd9Sstevel@tonic-gate  * This plugin should only be installed in the platform directories
297c478bd9Sstevel@tonic-gate  * of supported systems, such as /usr/platform/picl/plugins/SUNW,<>.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <picl.h>
337c478bd9Sstevel@tonic-gate #include <picltree.h>
347c478bd9Sstevel@tonic-gate #include <stdio.h>
357c478bd9Sstevel@tonic-gate #include <time.h>
367c478bd9Sstevel@tonic-gate #include <dlfcn.h>
377c478bd9Sstevel@tonic-gate #include <fcntl.h>
387c478bd9Sstevel@tonic-gate #include <unistd.h>
397c478bd9Sstevel@tonic-gate #include <stdlib.h>
407c478bd9Sstevel@tonic-gate #include <limits.h>
417c478bd9Sstevel@tonic-gate #include  <ctype.h>
427c478bd9Sstevel@tonic-gate #include <pthread.h>
437c478bd9Sstevel@tonic-gate #include <libintl.h>
447c478bd9Sstevel@tonic-gate #include <errno.h>
457c478bd9Sstevel@tonic-gate #include <semaphore.h>
467c478bd9Sstevel@tonic-gate #include <sched.h>
477c478bd9Sstevel@tonic-gate #include <syslog.h>
487c478bd9Sstevel@tonic-gate #include <string.h>
497c478bd9Sstevel@tonic-gate #include <signal.h>
507c478bd9Sstevel@tonic-gate #include <sys/types.h>
517c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
527c478bd9Sstevel@tonic-gate #include <psvc_objects.h>
537c478bd9Sstevel@tonic-gate #include <psvc_objects_class.h>
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate #define	BUFSZ	512
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate typedef struct {
587c478bd9Sstevel@tonic-gate 	char	name[32];
597c478bd9Sstevel@tonic-gate } EName_t;
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate typedef struct {
62f79b6382SJustin Frank 	void *hdl;
637c478bd9Sstevel@tonic-gate 	int32_t (*funcp)(void *, char *);
647c478bd9Sstevel@tonic-gate 	int32_t	num_objects;
657c478bd9Sstevel@tonic-gate 	EName_t *obj_list;
667c478bd9Sstevel@tonic-gate 	char    routine[64];
677c478bd9Sstevel@tonic-gate } ETask_t;
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate typedef struct interval_info {
70f79b6382SJustin Frank 	volatile int32_t   interval;
717c478bd9Sstevel@tonic-gate 	int32_t	  num_tasks;
727c478bd9Sstevel@tonic-gate 	ETask_t   *task_list;
737c478bd9Sstevel@tonic-gate 	pthread_t thread;
74f79b6382SJustin Frank 	int32_t   has_thread;
757c478bd9Sstevel@tonic-gate 	struct interval_info *next;
767c478bd9Sstevel@tonic-gate } EInterval_t;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate static EInterval_t *first_interval;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate static psvc_opaque_t hdlp;
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate sem_t timer_sem;
83f79b6382SJustin Frank pthread_mutex_t timer_mutex;
84f79b6382SJustin Frank pthread_cond_t timer_cond;
857c478bd9Sstevel@tonic-gate pthread_t timer_thread_id;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate extern int ptree_get_node_by_path(const char *, picl_nodehdl_t *);
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate /* Timer states */
907c478bd9Sstevel@tonic-gate #define	NOT_READY	0
917c478bd9Sstevel@tonic-gate #define	READY		1
927c478bd9Sstevel@tonic-gate #define	HAVE_REQUEST	2
937c478bd9Sstevel@tonic-gate #define	ACTIVE		3
94f79b6382SJustin Frank #define	TIMER_SHUTDOWN	4
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate int timer_state = NOT_READY;
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate int app_timeout;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate /* Lock State Loop State Definitions */
1017c478bd9Sstevel@tonic-gate #define	STATE_CHANGED		1
1027c478bd9Sstevel@tonic-gate #define	STATE_NOT_CHANGED	0
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate #ifdef DEBUG
1057c478bd9Sstevel@tonic-gate static int32_t debug_flag = 1;
1067c478bd9Sstevel@tonic-gate #else
1077c478bd9Sstevel@tonic-gate static int32_t debug_flag = 0;
1087c478bd9Sstevel@tonic-gate #endif
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate static char library[PATH_MAX];
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate #define	PSVC_PLUGIN_VERSION	PICLD_PLUGIN_VERSION_1
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate #pragma init(psvc_plugin_register)	/* place in .init section */
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate typedef struct  {
1177c478bd9Sstevel@tonic-gate 	char	parent_path[256];
1187c478bd9Sstevel@tonic-gate 	char    child_name[32];
1197c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	child_node;
1207c478bd9Sstevel@tonic-gate } psvc_name_t;
1217c478bd9Sstevel@tonic-gate psvc_name_t *psvc_paths;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate #define	MUTEX_LOCK_FAILED_MSG	gettext("platsvcd: pthread_mutex_lock %s\n")
1247c478bd9Sstevel@tonic-gate #define	CV_WAIT_FAILED_MSG	gettext("platsvcd: pthread_cond_wait %s\n")
1257c478bd9Sstevel@tonic-gate #define	CV_TWAIT_FAILED_MSG gettext("platsvcd: pthread_cond_timed_wait %s\n")
1267c478bd9Sstevel@tonic-gate #define	SEM_WAIT_FAILED_MSG	gettext("platsvcd: sem_wait failed %s\n")
1277c478bd9Sstevel@tonic-gate #define	PSVC_APP_DEATH_MSG	gettext("PSVC application death detected\n")
1287c478bd9Sstevel@tonic-gate #define	POLICY_FAILED_MSG	gettext("ERROR running %s on %s (%d)")
1297c478bd9Sstevel@tonic-gate #define	ID_NOT_FOUND_MSG	gettext("%s: Can't determine id of %s\n")
1307c478bd9Sstevel@tonic-gate #define	CLASS_NOT_FOUND_MSG	gettext("%s: Can't determine class of %s\n")
1317c478bd9Sstevel@tonic-gate #define	SUBCLASS_NOT_FOUND_MSG	gettext("%s: Can't determine subclass of %s\n")
1327c478bd9Sstevel@tonic-gate #define	NODE_NOT_FOUND_MSG	gettext("%s: Can't determine node of %s\n")
1337c478bd9Sstevel@tonic-gate #define	SIZE_NOT_FOUND_MSG	gettext("%s: Couldn't determine size of %s\n")
1347c478bd9Sstevel@tonic-gate #define	PTREE_CREATE_TABLE_FAILED_MSG		\
1357c478bd9Sstevel@tonic-gate 	gettext("%s: ptree_create_table failed, %s\n")
1367c478bd9Sstevel@tonic-gate #define	PTREE_CREATE_PROP_FAILED_MSG		\
1377c478bd9Sstevel@tonic-gate 	gettext("%s: ptree_create_prop failed, %s\n")
1387c478bd9Sstevel@tonic-gate #define	PTREE_CREATE_NODE_FAILED_MSG		\
1397c478bd9Sstevel@tonic-gate 	gettext("%s: ptree_create_node failed, %s\n")
1407c478bd9Sstevel@tonic-gate #define	PTREE_ADD_ROW_FAILED_MSG gettext("%s: ptree_add_row_to_table: %s\n")
1417c478bd9Sstevel@tonic-gate #define	PTREE_ADD_NODE_FAILED_MSG gettext("%s: ptree_add_node: %s\n")
1427c478bd9Sstevel@tonic-gate #define	PTREE_ADD_PROP_FAILED_MSG gettext("%s: ptree_add_prop: %s\n")
1437c478bd9Sstevel@tonic-gate #define	PTREE_GET_ROOT_FAILED_MSG gettext("%s: ptree_get_root: %s\n")
1447c478bd9Sstevel@tonic-gate #define	CREATE_PROP_FAILED_MSG	gettext("%s: Error creating property %s\n")
1457c478bd9Sstevel@tonic-gate #define	INVALID_FILE_FORMAT_MSG		gettext("%s: Invalid file format\n")
1467c478bd9Sstevel@tonic-gate #define	INVALID_FILE_FORMAT1_MSG	gettext("%s: Invalid file format %s\n")
1477c478bd9Sstevel@tonic-gate #define	PSVC_INIT_ERR_MSG	gettext("%s: Error in psvc_init(): %s\n")
1487c478bd9Sstevel@tonic-gate #define	SYSINFO_FAILED_MSG	gettext("%s: Can't determine platform type\n")
1497c478bd9Sstevel@tonic-gate #define	FILE_OPEN_FAILED_MSG	gettext("%s: Can't open file %s\n")
1507c478bd9Sstevel@tonic-gate #define	MALLOC_FAILED_MSG	gettext("%s: malloc failed, %s\n")
1517c478bd9Sstevel@tonic-gate #define	UNKNOWN_CLASS_MSG	gettext("%s: Unknown class\n")
1527c478bd9Sstevel@tonic-gate #define	NODE_PROP_FAILED_MSG	gettext("%s: node_property: %s\n")
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate #define	LOCK_STRING_MAX 32
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate picl_nodehdl_t system_node;
1577c478bd9Sstevel@tonic-gate static picl_nodehdl_t lock_node;
1587c478bd9Sstevel@tonic-gate static char env_lock_state[LOCK_STRING_MAX] = PSVC_LOCK_ENABLED;
159f79b6382SJustin Frank static pthread_mutex_t env_lock_mutex;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate static char *class_name[] = {
1627c478bd9Sstevel@tonic-gate "temperature-sensor",
1637c478bd9Sstevel@tonic-gate "fan",
1647c478bd9Sstevel@tonic-gate "led",
1657c478bd9Sstevel@tonic-gate "picl",
1667c478bd9Sstevel@tonic-gate "digital-sensor",
1677c478bd9Sstevel@tonic-gate "digital-control",
1687c478bd9Sstevel@tonic-gate "gpio",
1697c478bd9Sstevel@tonic-gate "fan-tachometer",
1707c478bd9Sstevel@tonic-gate "switch",
1717c478bd9Sstevel@tonic-gate "keyswitch",
1727c478bd9Sstevel@tonic-gate "gpio",
1737c478bd9Sstevel@tonic-gate "i2c"
1747c478bd9Sstevel@tonic-gate };
1757c478bd9Sstevel@tonic-gate #define	NUM_CLASSES (sizeof (class_name) / sizeof (char *))
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate struct proj_prop {	/* projected property */
1787c478bd9Sstevel@tonic-gate 	picl_prophdl_t	handle;
1797c478bd9Sstevel@tonic-gate 	picl_nodehdl_t  dst_node;
1807c478bd9Sstevel@tonic-gate 	char		name[32];
1817c478bd9Sstevel@tonic-gate };
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate struct propinfo {
1847c478bd9Sstevel@tonic-gate 	char		*name;
1857c478bd9Sstevel@tonic-gate 	uint32_t	type;
1867c478bd9Sstevel@tonic-gate 	uint32_t	size;
1877c478bd9Sstevel@tonic-gate 	uint32_t	access;
1887c478bd9Sstevel@tonic-gate };
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate struct propinfo common[] = {
1917c478bd9Sstevel@tonic-gate 	{"State", PICL_PTYPE_CHARSTRING, 32,
1927c478bd9Sstevel@tonic-gate 	PICL_READ | PICL_WRITE | PICL_VOLATILE},
1937c478bd9Sstevel@tonic-gate 	{"FaultInformation", PICL_PTYPE_CHARSTRING, 32,
1947c478bd9Sstevel@tonic-gate 	PICL_READ | PICL_VOLATILE}
1957c478bd9Sstevel@tonic-gate };
1967c478bd9Sstevel@tonic-gate #define	COMMON_COUNT (sizeof (common) / sizeof (struct propinfo))
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate struct propinfo led_properties[] = {
1997c478bd9Sstevel@tonic-gate 	{"Color", PICL_PTYPE_CHARSTRING, 32, PICL_READ | PICL_VOLATILE},
2007c478bd9Sstevel@tonic-gate 	{"IsLocator", PICL_PTYPE_CHARSTRING, 32, PICL_READ | PICL_VOLATILE},
2017c478bd9Sstevel@tonic-gate 	{"LocatorName", PICL_PTYPE_CHARSTRING, 32, PICL_READ | PICL_VOLATILE}
2027c478bd9Sstevel@tonic-gate };
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate  * We define the amount of LED properties to 1 because not all LED's have
2057c478bd9Sstevel@tonic-gate  * the two remainding properties.  This number is augmented in psvc_plugin_init
2067c478bd9Sstevel@tonic-gate  * when it sees an LED of subclass 2.
2077c478bd9Sstevel@tonic-gate  */
2087c478bd9Sstevel@tonic-gate #define	LED_COUNT 1
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate struct propinfo temperature_sensor_properties[] = {
2117c478bd9Sstevel@tonic-gate 	{"Temperature", PICL_PTYPE_INT, 4, PICL_READ | PICL_VOLATILE},
2127c478bd9Sstevel@tonic-gate 	{"LowWarningThreshold", PICL_PTYPE_INT, 4, PICL_READ | PICL_VOLATILE},
2137c478bd9Sstevel@tonic-gate 	{"LowShutdownThreshold", PICL_PTYPE_INT, 4, PICL_READ | PICL_VOLATILE},
2147c478bd9Sstevel@tonic-gate 	{"HighWarningThreshold", PICL_PTYPE_INT, 4, PICL_READ | PICL_VOLATILE},
2157c478bd9Sstevel@tonic-gate 	{"HighShutdownThreshold", PICL_PTYPE_INT, 4, PICL_READ | PICL_VOLATILE}
2167c478bd9Sstevel@tonic-gate };
2177c478bd9Sstevel@tonic-gate #define	TEMP_SENSOR_COUNT \
2187c478bd9Sstevel@tonic-gate 	(sizeof (temperature_sensor_properties) / sizeof (struct propinfo))
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate struct propinfo digi_sensor_properties[] = {
2217c478bd9Sstevel@tonic-gate 	{"AtoDSensorValue", PICL_PTYPE_INT, 4, PICL_READ | PICL_VOLATILE},
2227c478bd9Sstevel@tonic-gate 	{"LowWarningThreshold", PICL_PTYPE_INT, 4, PICL_READ | PICL_VOLATILE},
2237c478bd9Sstevel@tonic-gate 	{"LowShutdownThreshold", PICL_PTYPE_INT, 4, PICL_READ | PICL_VOLATILE},
2247c478bd9Sstevel@tonic-gate 	{"HighWarningThreshold", PICL_PTYPE_INT, 4, PICL_READ | PICL_VOLATILE},
2257c478bd9Sstevel@tonic-gate 	{"HighShutdownThreshold", PICL_PTYPE_INT, 4, PICL_READ | PICL_VOLATILE}
2267c478bd9Sstevel@tonic-gate };
2277c478bd9Sstevel@tonic-gate #define	DIGI_SENSOR_COUNT \
2287c478bd9Sstevel@tonic-gate 	(sizeof (digi_sensor_properties) / sizeof (struct propinfo))
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate struct propinfo boolgpio_properties[] = {
2317c478bd9Sstevel@tonic-gate 	{"Gpio-value", PICL_PTYPE_UNSIGNED_INT, sizeof (boolean_t),
2327c478bd9Sstevel@tonic-gate 	PICL_READ | PICL_WRITE | PICL_VOLATILE},
2337c478bd9Sstevel@tonic-gate 	{"#Bits", PICL_PTYPE_UNSIGNED_INT, 4, PICL_READ |PICL_VOLATILE}
2347c478bd9Sstevel@tonic-gate };
2357c478bd9Sstevel@tonic-gate #define	BOOLGPIO_COUNT (sizeof (boolgpio_properties) / sizeof (struct propinfo))
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate struct propinfo gpio8_properties[] = {
2387c478bd9Sstevel@tonic-gate 	{"Gpio-value", PICL_PTYPE_UNSIGNED_INT, 1,
2397c478bd9Sstevel@tonic-gate 	PICL_READ | PICL_WRITE | PICL_VOLATILE},
2407c478bd9Sstevel@tonic-gate 	{"#Bits", PICL_PTYPE_UNSIGNED_INT, 4, PICL_READ |PICL_VOLATILE}
2417c478bd9Sstevel@tonic-gate };
2427c478bd9Sstevel@tonic-gate #define	GPIO8_COUNT (sizeof (gpio8_properties) / sizeof (struct propinfo))
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate struct propinfo digictrl_properties[] = {
2457c478bd9Sstevel@tonic-gate 	{"DtoAControlValue", PICL_PTYPE_INT, 4,
2467c478bd9Sstevel@tonic-gate 	PICL_READ | PICL_WRITE | PICL_VOLATILE},
2477c478bd9Sstevel@tonic-gate };
2487c478bd9Sstevel@tonic-gate #define	DIGICTRL_COUNT (sizeof (digictrl_properties) / sizeof (struct propinfo))
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate struct classinfo {
2517c478bd9Sstevel@tonic-gate 	struct propinfo	*props;
2527c478bd9Sstevel@tonic-gate 	int32_t		count;
2537c478bd9Sstevel@tonic-gate } class_properties[] =
2547c478bd9Sstevel@tonic-gate {
2557c478bd9Sstevel@tonic-gate 	{temperature_sensor_properties, TEMP_SENSOR_COUNT}, /* temp sensor */
2567c478bd9Sstevel@tonic-gate 	{0, 0},				/* fan, only has projected properties */
2577c478bd9Sstevel@tonic-gate 	{led_properties, LED_COUNT},
2587c478bd9Sstevel@tonic-gate 	{0, 0},						  /* system class */
2597c478bd9Sstevel@tonic-gate 	{digi_sensor_properties, DIGI_SENSOR_COUNT}, /* digital sensor */
2607c478bd9Sstevel@tonic-gate 	{digictrl_properties, DIGICTRL_COUNT},
2617c478bd9Sstevel@tonic-gate 	{boolgpio_properties, BOOLGPIO_COUNT},
2627c478bd9Sstevel@tonic-gate 	{digi_sensor_properties, DIGI_SENSOR_COUNT}, /* fan tach */
2637c478bd9Sstevel@tonic-gate 	{0, 0},
2647c478bd9Sstevel@tonic-gate 	{0, 0},
2657c478bd9Sstevel@tonic-gate 	{gpio8_properties, GPIO8_COUNT},
2667c478bd9Sstevel@tonic-gate 	{0, 0},
2677c478bd9Sstevel@tonic-gate };
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate struct prop_trans {
2707c478bd9Sstevel@tonic-gate 	char *picl_class;
2717c478bd9Sstevel@tonic-gate 	char *picl_prop;
2727c478bd9Sstevel@tonic-gate 	int32_t psvc_prop;
2737c478bd9Sstevel@tonic-gate } picl_prop_trans[] =
2747c478bd9Sstevel@tonic-gate {
2757c478bd9Sstevel@tonic-gate 	{"digital-sensor", "AtoDSensorValue", PSVC_SENSOR_VALUE_ATTR},
2767c478bd9Sstevel@tonic-gate 	{"digital-sensor", "LowWarningThreshold", PSVC_LO_WARN_ATTR},
2777c478bd9Sstevel@tonic-gate 	{"digital-sensor", "LowShutdownThreshold", PSVC_LO_SHUT_ATTR},
2787c478bd9Sstevel@tonic-gate 	{"digital-sensor", "HighWarningThreshold", PSVC_HI_WARN_ATTR},
2797c478bd9Sstevel@tonic-gate 	{"digital-sensor", "HighShutdownThreshold", PSVC_HI_SHUT_ATTR},
2807c478bd9Sstevel@tonic-gate 	{"digital-control", "DtoAControlValue", PSVC_CONTROL_VALUE_ATTR},
2817c478bd9Sstevel@tonic-gate 	{"fan-tachometer", "AtoDSensorValue", PSVC_SENSOR_VALUE_ATTR},
2827c478bd9Sstevel@tonic-gate 	{"fan-tachometer", "LowWarningThreshold", PSVC_LO_WARN_ATTR},
2837c478bd9Sstevel@tonic-gate 	{"fan-tachometer", "LowShutdownThreshold", PSVC_LO_SHUT_ATTR},
2847c478bd9Sstevel@tonic-gate 	{"fan-tachometer", "HighWarningThreshold", PSVC_HI_WARN_ATTR},
2857c478bd9Sstevel@tonic-gate 	{"fan-tachometer", "HighShutdownThreshold", PSVC_HI_SHUT_ATTR},
2867c478bd9Sstevel@tonic-gate 	{"temperature-sensor", "Temperature", PSVC_SENSOR_VALUE_ATTR},
2877c478bd9Sstevel@tonic-gate 	{"temperature-sensor", "LowWarningThreshold", PSVC_LO_WARN_ATTR},
2887c478bd9Sstevel@tonic-gate 	{"temperature-sensor", "LowShutdownThreshold", PSVC_LO_SHUT_ATTR},
2897c478bd9Sstevel@tonic-gate 	{"temperature-sensor", "HighWarningThreshold", PSVC_HI_WARN_ATTR},
2907c478bd9Sstevel@tonic-gate 	{"temperature-sensor", "HighShutdownThreshold", PSVC_HI_SHUT_ATTR},
2917c478bd9Sstevel@tonic-gate 	{"led", "State", PSVC_LED_STATE_ATTR},
2927c478bd9Sstevel@tonic-gate 	{"led", "Color", PSVC_LED_COLOR_ATTR},
2937c478bd9Sstevel@tonic-gate 	{"switch", "State", PSVC_SWITCH_STATE_ATTR},
2947c478bd9Sstevel@tonic-gate 	{"keyswitch", "State", PSVC_SWITCH_STATE_ATTR},
2957c478bd9Sstevel@tonic-gate 	{"i2c", "State", PSVC_PROBE_RESULT_ATTR}
2967c478bd9Sstevel@tonic-gate };
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate #define	PICL_PROP_TRANS_COUNT \
2997c478bd9Sstevel@tonic-gate 	(sizeof (picl_prop_trans) / sizeof (struct prop_trans))
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate typedef struct {
3037c478bd9Sstevel@tonic-gate 	char		name[32];
3047c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	node;
3057c478bd9Sstevel@tonic-gate } picl_psvc_t;
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate struct assoc_pair {
3087c478bd9Sstevel@tonic-gate 	char	antecedent[32];
3097c478bd9Sstevel@tonic-gate 	char	dependent[32];
3107c478bd9Sstevel@tonic-gate };
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate struct handle {
3137c478bd9Sstevel@tonic-gate 	uint32_t    obj_count;
3147c478bd9Sstevel@tonic-gate 	picl_psvc_t *objects;
3157c478bd9Sstevel@tonic-gate 	FILE	*fp;
3167c478bd9Sstevel@tonic-gate } psvc_hdl;
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate struct proj_prop *prop_list;
3197c478bd9Sstevel@tonic-gate uint32_t proj_prop_count;
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate int psvc_picl_nodes;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate void psvc_plugin_init(void);
3247c478bd9Sstevel@tonic-gate void psvc_plugin_fini(void);
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate picld_plugin_reg_t psvc_reg = {
3277c478bd9Sstevel@tonic-gate 	PSVC_PLUGIN_VERSION,
3287c478bd9Sstevel@tonic-gate 	PICLD_PLUGIN_CRITICAL,
3297c478bd9Sstevel@tonic-gate 	"PSVC",
3307c478bd9Sstevel@tonic-gate 	psvc_plugin_init,
3317c478bd9Sstevel@tonic-gate 	psvc_plugin_fini
3327c478bd9Sstevel@tonic-gate };
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate /*
3357c478bd9Sstevel@tonic-gate  * psvcplugin_add_children was written so that devices which are hotplugable
3367c478bd9Sstevel@tonic-gate  * will be able to add in all thier children and children's children. The
3377c478bd9Sstevel@tonic-gate  * routine takes in the path of a parent and then searches the psvc_paths
3387c478bd9Sstevel@tonic-gate  * array to find all of it's children.  It in turns adds the child and then
3397c478bd9Sstevel@tonic-gate  * recursively check to see if it had children and add them too.
3407c478bd9Sstevel@tonic-gate  */
3417c478bd9Sstevel@tonic-gate void
psvcplugin_add_children(char * parent_path)3427c478bd9Sstevel@tonic-gate psvcplugin_add_children(char *parent_path)
3437c478bd9Sstevel@tonic-gate {
3447c478bd9Sstevel@tonic-gate 	int i;
3457c478bd9Sstevel@tonic-gate 	picl_nodehdl_t parent_node;
3467c478bd9Sstevel@tonic-gate 	char next_path[256];
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	for (i = 0; i < psvc_picl_nodes; ++i) {
3497c478bd9Sstevel@tonic-gate 		if (strcmp(parent_path, psvc_paths[i].parent_path) == 0) {
3507c478bd9Sstevel@tonic-gate 			ptree_get_node_by_path(parent_path, &parent_node);
3517c478bd9Sstevel@tonic-gate 			ptree_add_node(parent_node, psvc_paths[i].child_node);
352f79b6382SJustin Frank 			(void) snprintf(next_path, sizeof (next_path), "%s/%s",
3537c478bd9Sstevel@tonic-gate 			    parent_path, psvc_paths[i].child_name);
3547c478bd9Sstevel@tonic-gate 			psvcplugin_add_children(next_path);
3557c478bd9Sstevel@tonic-gate 		}
3567c478bd9Sstevel@tonic-gate 	}
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate void
psvcplugin_lookup(char * name,char * parent,picl_nodehdl_t * node)3607c478bd9Sstevel@tonic-gate psvcplugin_lookup(char *name, char *parent, picl_nodehdl_t *node)
3617c478bd9Sstevel@tonic-gate {
3627c478bd9Sstevel@tonic-gate 	int i;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	for (i = 0; i < psvc_picl_nodes; ++i) {
3657c478bd9Sstevel@tonic-gate 		if (strcmp(name, psvc_paths[i].child_name) == 0) {
366f79b6382SJustin Frank 			(void) strcpy(parent, psvc_paths[i].parent_path);
3677c478bd9Sstevel@tonic-gate 			*node = psvc_paths[i].child_node;
3687c478bd9Sstevel@tonic-gate 		}
3697c478bd9Sstevel@tonic-gate 	}
3707c478bd9Sstevel@tonic-gate }
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate void
timer_thread(void)373f79b6382SJustin Frank timer_thread(void)
3747c478bd9Sstevel@tonic-gate {
3757c478bd9Sstevel@tonic-gate 	struct timespec timeout;
3767c478bd9Sstevel@tonic-gate 	int status;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	status = pthread_mutex_lock(&timer_mutex);
3807c478bd9Sstevel@tonic-gate 	if (status != 0) {
3817c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, MUTEX_LOCK_FAILED_MSG, strerror(status));
3827c478bd9Sstevel@tonic-gate 	}
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	for (;;) {
3857c478bd9Sstevel@tonic-gate 		/* wait for thread to tell us to start timer */
3867c478bd9Sstevel@tonic-gate 		timer_state = READY;
3877c478bd9Sstevel@tonic-gate 		do {
3887c478bd9Sstevel@tonic-gate 			status = pthread_cond_wait(&timer_cond, &timer_mutex);
3897c478bd9Sstevel@tonic-gate 		} while (timer_state == READY && status == 0);
3907c478bd9Sstevel@tonic-gate 
391f79b6382SJustin Frank 		if (timer_state == TIMER_SHUTDOWN) {
392f79b6382SJustin Frank 			pthread_exit(NULL);
393f79b6382SJustin Frank 			/* not reached */
394f79b6382SJustin Frank 		}
395f79b6382SJustin Frank 
3967c478bd9Sstevel@tonic-gate 		if (status != 0) {
3977c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, CV_WAIT_FAILED_MSG, strerror(status));
3987c478bd9Sstevel@tonic-gate 		}
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 		/*
4017c478bd9Sstevel@tonic-gate 		 * Will get signalled after semaphore acquired,
4027c478bd9Sstevel@tonic-gate 		 * or when timeout occurs.
4037c478bd9Sstevel@tonic-gate 		 */
404f79b6382SJustin Frank 		(void) clock_gettime(CLOCK_REALTIME, &timeout);
4057c478bd9Sstevel@tonic-gate 		timeout.tv_sec += app_timeout;
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 		if (timer_state == HAVE_REQUEST) {
4087c478bd9Sstevel@tonic-gate 			timer_state = ACTIVE;
4097c478bd9Sstevel@tonic-gate 			do {
4107c478bd9Sstevel@tonic-gate 				status = pthread_cond_timedwait(&timer_cond,
411f79b6382SJustin Frank 				    &timer_mutex, &timeout);
4127c478bd9Sstevel@tonic-gate 			} while (timer_state == ACTIVE && status == 0);
4137c478bd9Sstevel@tonic-gate 		}
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 		if (status != 0) {
4167c478bd9Sstevel@tonic-gate 			if (status == ETIMEDOUT) {
4177c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, PSVC_APP_DEATH_MSG);
418f79b6382SJustin Frank 				(void) pthread_mutex_lock(&env_lock_mutex);
419f79b6382SJustin Frank 				(void) strlcpy(env_lock_state,
420f79b6382SJustin Frank 				    PSVC_LOCK_ENABLED, LOCK_STRING_MAX);
421f79b6382SJustin Frank 				(void) pthread_mutex_unlock(&env_lock_mutex);
4227c478bd9Sstevel@tonic-gate 			} else {
4237c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, CV_TWAIT_FAILED_MSG,
424f79b6382SJustin Frank 				    strerror(status));
4257c478bd9Sstevel@tonic-gate 			}
4267c478bd9Sstevel@tonic-gate 		}
4277c478bd9Sstevel@tonic-gate 	}
4287c478bd9Sstevel@tonic-gate }
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate static int
lock_state_loop(char * set_lock_state)4317c478bd9Sstevel@tonic-gate lock_state_loop(char *set_lock_state)
4327c478bd9Sstevel@tonic-gate {
433f79b6382SJustin Frank 	(void) pthread_mutex_lock(&env_lock_mutex);
4347c478bd9Sstevel@tonic-gate 	if (strcmp(env_lock_state, PSVC_LOCK_ENABLED) == 0) {
435f79b6382SJustin Frank 		(void) strlcpy(env_lock_state, set_lock_state, LOCK_STRING_MAX);
436f79b6382SJustin Frank 		(void) pthread_mutex_unlock(&env_lock_mutex);
4377c478bd9Sstevel@tonic-gate 		return (STATE_NOT_CHANGED);
4387c478bd9Sstevel@tonic-gate 	}
439f79b6382SJustin Frank 	(void) pthread_mutex_unlock(&env_lock_mutex);
4407c478bd9Sstevel@tonic-gate 	return (STATE_CHANGED);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate 
timed_lock_wait(char * set_lock_state)4437c478bd9Sstevel@tonic-gate static int timed_lock_wait(char *set_lock_state)
4447c478bd9Sstevel@tonic-gate {
4457c478bd9Sstevel@tonic-gate 	int32_t status;
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	/* Only want one timer active at a time */
4487c478bd9Sstevel@tonic-gate 	do {
4497c478bd9Sstevel@tonic-gate 		status = sem_wait(&timer_sem);
4507c478bd9Sstevel@tonic-gate 	} while (status == -1 && errno == EINTR);
4517c478bd9Sstevel@tonic-gate 	if (status == -1)
4527c478bd9Sstevel@tonic-gate 		return (status);
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	while (timer_state != READY)
455f79b6382SJustin Frank 		(void) sched_yield();
456f79b6382SJustin Frank 	(void) pthread_mutex_lock(&timer_mutex);
4577c478bd9Sstevel@tonic-gate 	timer_state = HAVE_REQUEST;
458f79b6382SJustin Frank 	(void) pthread_cond_signal(&timer_cond);	/* start timer */
459f79b6382SJustin Frank 	(void) pthread_mutex_unlock(&timer_mutex);
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	/*
4627c478bd9Sstevel@tonic-gate 	 * We now spin checking the state env_lock_state for it to change to
4637c478bd9Sstevel@tonic-gate 	 * enabled.
4647c478bd9Sstevel@tonic-gate 	 */
4657c478bd9Sstevel@tonic-gate 	while (lock_state_loop(set_lock_state))
466f79b6382SJustin Frank 		(void) sleep(1);
4677c478bd9Sstevel@tonic-gate 
468f79b6382SJustin Frank 	(void) pthread_mutex_lock(&timer_mutex);
4697c478bd9Sstevel@tonic-gate 	if (timer_state == ACTIVE) {
4707c478bd9Sstevel@tonic-gate 		timer_state = NOT_READY;
471f79b6382SJustin Frank 		(void) pthread_cond_signal(&timer_cond);	/* stop timer */
4727c478bd9Sstevel@tonic-gate 	}
4737c478bd9Sstevel@tonic-gate 	if (timer_state == HAVE_REQUEST) {		/* cancel request */
4747c478bd9Sstevel@tonic-gate 		timer_state = NOT_READY;
4757c478bd9Sstevel@tonic-gate 	}
476f79b6382SJustin Frank 	(void) pthread_mutex_unlock(&timer_mutex);
477f79b6382SJustin Frank 	(void) sem_post(&timer_sem);
4787c478bd9Sstevel@tonic-gate 	return (0);
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate 
lock_and_run(ETask_t * tp,int32_t obj_num)4817c478bd9Sstevel@tonic-gate static void lock_and_run(ETask_t *tp, int32_t obj_num)
4827c478bd9Sstevel@tonic-gate {
4837c478bd9Sstevel@tonic-gate 	int32_t status;
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	/* Grab mutex to stop the env_lock from being changed. */
486f79b6382SJustin Frank 	(void) pthread_mutex_lock(&env_lock_mutex);
4877c478bd9Sstevel@tonic-gate 	/*
4887c478bd9Sstevel@tonic-gate 	 * Check to see if the lock is anything but Enabled. If so, we then
4897c478bd9Sstevel@tonic-gate 	 * goto our timer routine to wait for it to become enabled.
4907c478bd9Sstevel@tonic-gate 	 * If not then set it to RUNNING and run policy.
4917c478bd9Sstevel@tonic-gate 	 */
4927c478bd9Sstevel@tonic-gate 	if (strcmp(env_lock_state, PSVC_LOCK_ENABLED) != 0) {
4937c478bd9Sstevel@tonic-gate 		/* drop mutex and goto timer */
494f79b6382SJustin Frank 		(void) pthread_mutex_unlock(&env_lock_mutex);
4957c478bd9Sstevel@tonic-gate 		status = timed_lock_wait(PSVC_LOCK_RUNNING);
4967c478bd9Sstevel@tonic-gate 		if (status == -1) {
4977c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, SEM_WAIT_FAILED_MSG);
4987c478bd9Sstevel@tonic-gate 		}
4997c478bd9Sstevel@tonic-gate 	} else {
500f79b6382SJustin Frank 		(void) strlcpy(env_lock_state, PSVC_LOCK_RUNNING,
501f79b6382SJustin Frank 		    LOCK_STRING_MAX);
502f79b6382SJustin Frank 		(void) pthread_mutex_unlock(&env_lock_mutex);
5037c478bd9Sstevel@tonic-gate 	}
5047c478bd9Sstevel@tonic-gate 	status = (*tp->funcp)(hdlp, (tp->obj_list + obj_num)->name);
5057c478bd9Sstevel@tonic-gate 	if (status == PSVC_FAILURE && errno != ENODEV) {
5067c478bd9Sstevel@tonic-gate 		char dev_name[32];
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 		psvc_get_attr(hdlp, (tp->obj_list + obj_num)->name,
5097c478bd9Sstevel@tonic-gate 		    PSVC_LABEL_ATTR, dev_name);
5107c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, POLICY_FAILED_MSG, tp->routine, dev_name,
5117c478bd9Sstevel@tonic-gate 		    (tp->obj_list + obj_num)->name);
512f79b6382SJustin Frank 		syslog(LOG_ERR, "%s", strerror(errno));
5137c478bd9Sstevel@tonic-gate 	}
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	/* The policy is done so set the lock back to ENABLED. */
516f79b6382SJustin Frank 	(void) pthread_mutex_lock(&env_lock_mutex);
517f79b6382SJustin Frank 	(void) strlcpy(env_lock_state, PSVC_LOCK_ENABLED, LOCK_STRING_MAX);
518f79b6382SJustin Frank 	(void) pthread_mutex_unlock(&env_lock_mutex);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
521*afe82bdcSToomas Soome static void *
run_policies(void * ptr)522*afe82bdcSToomas Soome run_policies(void *ptr)
5237c478bd9Sstevel@tonic-gate {
524*afe82bdcSToomas Soome 	EInterval_t *ip = ptr;
5257c478bd9Sstevel@tonic-gate 	ETask_t *tp;
5267c478bd9Sstevel@tonic-gate 	int32_t i, j;
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	do {
5297c478bd9Sstevel@tonic-gate 		if (ip->interval) {
5307c478bd9Sstevel@tonic-gate 			int remaining = ip->interval;
5317c478bd9Sstevel@tonic-gate 			do {
532f79b6382SJustin Frank 				/* check to see if we've been told to exit */
533f79b6382SJustin Frank 				if (ip->has_thread && (ip->interval == 0))
534f79b6382SJustin Frank 					break;
5357c478bd9Sstevel@tonic-gate 				remaining = sleep(remaining);
5367c478bd9Sstevel@tonic-gate 			} while (remaining > 0);
5377c478bd9Sstevel@tonic-gate 		}
5387c478bd9Sstevel@tonic-gate 		for (i = 0; i < ip->num_tasks; ++i) {
5397c478bd9Sstevel@tonic-gate 			tp = &ip->task_list[i];
5407c478bd9Sstevel@tonic-gate 			for (j = 0; j < tp->num_objects; ++j) {
541f79b6382SJustin Frank 				/* check to see if we've been told to exit */
542f79b6382SJustin Frank 				if (ip->has_thread && (ip->interval == 0))
543f79b6382SJustin Frank 					break;
5447c478bd9Sstevel@tonic-gate 				lock_and_run(tp, j);
5457c478bd9Sstevel@tonic-gate 			}
546f79b6382SJustin Frank 			if (ip->has_thread && (ip->interval == 0))
547f79b6382SJustin Frank 				break;
5487c478bd9Sstevel@tonic-gate 		}
5497c478bd9Sstevel@tonic-gate 	} while (ip->interval);
550*afe82bdcSToomas Soome 
551*afe82bdcSToomas Soome 	return (NULL);
5527c478bd9Sstevel@tonic-gate }
5537c478bd9Sstevel@tonic-gate 
thread_setup(EInterval_t * ip)5547c478bd9Sstevel@tonic-gate static void thread_setup(EInterval_t *ip)
5557c478bd9Sstevel@tonic-gate {
5567c478bd9Sstevel@tonic-gate 	int32_t status;
5577c478bd9Sstevel@tonic-gate 
558*afe82bdcSToomas Soome 	status = pthread_create(&ip->thread, NULL, run_policies, ip);
5597c478bd9Sstevel@tonic-gate 	if (status != 0) {
5607c478bd9Sstevel@tonic-gate 		if (debug_flag)
561f79b6382SJustin Frank 			syslog(LOG_ERR, "%s", strerror(errno));
5627c478bd9Sstevel@tonic-gate 		exit(-1);
5637c478bd9Sstevel@tonic-gate 	}
564f79b6382SJustin Frank 	ip->has_thread = 1;
5657c478bd9Sstevel@tonic-gate }
5667c478bd9Sstevel@tonic-gate 
load_policy(const char * library,ETask_t * tp)567f79b6382SJustin Frank static int32_t load_policy(const char *library, ETask_t *tp)
5687c478bd9Sstevel@tonic-gate {
569f79b6382SJustin Frank 	tp->hdl = dlopen(library, RTLD_NOW | RTLD_GLOBAL);
570f79b6382SJustin Frank 	if (tp->hdl == NULL) {
5717c478bd9Sstevel@tonic-gate 		if (debug_flag) {
5727c478bd9Sstevel@tonic-gate 			char *errstr = dlerror();
573f79b6382SJustin Frank 			syslog(LOG_ERR, "%s", errstr);
5747c478bd9Sstevel@tonic-gate 		}
5757c478bd9Sstevel@tonic-gate 		exit(1);
5767c478bd9Sstevel@tonic-gate 	}
577f79b6382SJustin Frank 	tp->funcp = (int32_t (*)(void *, char *))dlsym(tp->hdl, tp->routine);
578f79b6382SJustin Frank 	if (tp->funcp == NULL) {
5797c478bd9Sstevel@tonic-gate 		if (debug_flag) {
5807c478bd9Sstevel@tonic-gate 			char *errstr = dlerror();
581f79b6382SJustin Frank 			syslog(LOG_ERR, "%s", errstr);
5827c478bd9Sstevel@tonic-gate 		}
5837c478bd9Sstevel@tonic-gate 		exit(1);
5847c478bd9Sstevel@tonic-gate 	}
5857c478bd9Sstevel@tonic-gate 	return (0);
5867c478bd9Sstevel@tonic-gate }
5877c478bd9Sstevel@tonic-gate 
get_timeout(FILE * fp,int * timeout)5887c478bd9Sstevel@tonic-gate static int32_t get_timeout(FILE *fp, int *timeout)
5897c478bd9Sstevel@tonic-gate {
5907c478bd9Sstevel@tonic-gate 	char buf[BUFSZ];
5917c478bd9Sstevel@tonic-gate 	char name[32];
5927c478bd9Sstevel@tonic-gate 	char *cp;
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	/* skip blank lines */
5957c478bd9Sstevel@tonic-gate 	do {
5967c478bd9Sstevel@tonic-gate 		cp = fgets(buf, BUFSZ, fp);
5977c478bd9Sstevel@tonic-gate 		if (cp == NULL)
5987c478bd9Sstevel@tonic-gate 			return (1);
5997c478bd9Sstevel@tonic-gate 		while (isspace(*cp))
6007c478bd9Sstevel@tonic-gate 			++cp;
601f79b6382SJustin Frank 		(void) sscanf(buf, "%31s %d", name, timeout);
6027c478bd9Sstevel@tonic-gate 	} while (*cp == 0 || *cp == '\n' || strcmp(name, "TIMEOUT") != 0);
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	if (strcmp(name, "TIMEOUT") != 0) {
6057c478bd9Sstevel@tonic-gate 		errno = EINVAL;
6067c478bd9Sstevel@tonic-gate 		return (-1);
6077c478bd9Sstevel@tonic-gate 	}
6087c478bd9Sstevel@tonic-gate 	return (0);
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate 
load_interval(FILE * fp,EInterval_t ** ipp)6127c478bd9Sstevel@tonic-gate static int32_t load_interval(FILE *fp, EInterval_t **ipp)
6137c478bd9Sstevel@tonic-gate {
6147c478bd9Sstevel@tonic-gate 	char buf[BUFSZ];
6157c478bd9Sstevel@tonic-gate 	int32_t found;
6167c478bd9Sstevel@tonic-gate 	EInterval_t *ip;
6177c478bd9Sstevel@tonic-gate 	ETask_t *tp;
6187c478bd9Sstevel@tonic-gate 	int32_t tasks;
6197c478bd9Sstevel@tonic-gate 	int32_t status, i, j;
6207c478bd9Sstevel@tonic-gate 	int32_t interval;
6217c478bd9Sstevel@tonic-gate 	char name[32];
6227c478bd9Sstevel@tonic-gate 	char *cp;
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	/* skip blank lines */
6257c478bd9Sstevel@tonic-gate 	do {
6267c478bd9Sstevel@tonic-gate 		cp = fgets(buf, BUFSZ, fp);
6277c478bd9Sstevel@tonic-gate 		if (cp == NULL)
6287c478bd9Sstevel@tonic-gate 			return (1);
6297c478bd9Sstevel@tonic-gate 		while (isspace(*cp))
6307c478bd9Sstevel@tonic-gate 			++cp;
6317c478bd9Sstevel@tonic-gate 	} while (*cp == 0 || *cp == '\n');
632f79b6382SJustin Frank 	found = sscanf(buf, "%31s %d %d", name, &interval, &tasks);
6337c478bd9Sstevel@tonic-gate 	if (found != 3) {
6347c478bd9Sstevel@tonic-gate 		errno = EINVAL;
6357c478bd9Sstevel@tonic-gate 		return (-1);
6367c478bd9Sstevel@tonic-gate 	}
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 	if (strcmp(name, "INTERVAL") != 0) {
6397c478bd9Sstevel@tonic-gate 		errno = EINVAL;
6407c478bd9Sstevel@tonic-gate 		return (-1);
6417c478bd9Sstevel@tonic-gate 	}
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 	ip = (EInterval_t *)malloc(sizeof (EInterval_t));
6447c478bd9Sstevel@tonic-gate 	if (ip == NULL)
6457c478bd9Sstevel@tonic-gate 		return (-1);
6467c478bd9Sstevel@tonic-gate 	ip->num_tasks = tasks;
6477c478bd9Sstevel@tonic-gate 	ip->interval = interval;
6487c478bd9Sstevel@tonic-gate 	ip->next = NULL;
649f79b6382SJustin Frank 	ip->has_thread = 0;
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	/* allocate and load table */
6527c478bd9Sstevel@tonic-gate 	ip->task_list = (ETask_t *)malloc(ip->num_tasks * sizeof (ETask_t));
6537c478bd9Sstevel@tonic-gate 	if (ip->task_list == NULL)
6547c478bd9Sstevel@tonic-gate 		return (-1);
6557c478bd9Sstevel@tonic-gate 	for (i = 0; i < ip->num_tasks; ++i) {
6567c478bd9Sstevel@tonic-gate 		tp = &ip->task_list[i];
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 		(void) fgets(buf, BUFSZ, fp);
659f79b6382SJustin Frank 		found = sscanf(buf, "%31s %1023s %63s",
660f79b6382SJustin Frank 		    name, library, tp->routine);
6617c478bd9Sstevel@tonic-gate 		if (found != 3) {
6627c478bd9Sstevel@tonic-gate 			errno = EINVAL;
6637c478bd9Sstevel@tonic-gate 			return (-1);
6647c478bd9Sstevel@tonic-gate 		}
6657c478bd9Sstevel@tonic-gate 
666f79b6382SJustin Frank 		status = load_policy(library, tp);
6677c478bd9Sstevel@tonic-gate 		if (status == -1)
6687c478bd9Sstevel@tonic-gate 			return (-1);
6697c478bd9Sstevel@tonic-gate 		found = fscanf(fp, "%d", &tp->num_objects);
6707c478bd9Sstevel@tonic-gate 		if (found != 1) {
6717c478bd9Sstevel@tonic-gate 			if (debug_flag)
6727c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, "No list of objects for task");
6737c478bd9Sstevel@tonic-gate 			errno = EINVAL;
6747c478bd9Sstevel@tonic-gate 			return (-1);
6757c478bd9Sstevel@tonic-gate 		}
6767c478bd9Sstevel@tonic-gate 		tp->obj_list =
677f79b6382SJustin Frank 		    (EName_t *)malloc(tp->num_objects * sizeof (EName_t));
6787c478bd9Sstevel@tonic-gate 		if (tp->obj_list == NULL)
6797c478bd9Sstevel@tonic-gate 			return (-1);
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 		for (j = 0; j < tp->num_objects; ++j) {
682f79b6382SJustin Frank 			found = fscanf(fp, "%31s", (char *)(tp->obj_list + j));
6837c478bd9Sstevel@tonic-gate 			if (found != 1) {
6847c478bd9Sstevel@tonic-gate 				if (debug_flag)
6857c478bd9Sstevel@tonic-gate 					syslog(LOG_ERR,
6867c478bd9Sstevel@tonic-gate 					"Wrong number of objects for task");
6877c478bd9Sstevel@tonic-gate 				errno = EINVAL;
6887c478bd9Sstevel@tonic-gate 				return (-1);
6897c478bd9Sstevel@tonic-gate 			}
6907c478bd9Sstevel@tonic-gate 		}
6917c478bd9Sstevel@tonic-gate 		(void) fgets(buf, BUFSZ, fp);  /* reads newline on data line */
6927c478bd9Sstevel@tonic-gate 		(void) fgets(buf, BUFSZ, fp);
6937c478bd9Sstevel@tonic-gate 		if (strncmp(buf, "TASK_END", 8) != 0) {
6947c478bd9Sstevel@tonic-gate 			if (debug_flag)
6957c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, "Expected TASK_END, task %s",
696f79b6382SJustin Frank 				    tp->routine);
6977c478bd9Sstevel@tonic-gate 			errno = EINVAL;
6987c478bd9Sstevel@tonic-gate 			return (-1);
6997c478bd9Sstevel@tonic-gate 		}
7007c478bd9Sstevel@tonic-gate 	}
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	(void) fgets(buf, BUFSZ, fp);
7037c478bd9Sstevel@tonic-gate 	if (strncmp(buf, "INTERVAL_END", 12) != 0) {
7047c478bd9Sstevel@tonic-gate 		if (debug_flag)
7057c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "Expected INTERVAL_END");
7067c478bd9Sstevel@tonic-gate 		errno = EINVAL;
7077c478bd9Sstevel@tonic-gate 		return (-1);
7087c478bd9Sstevel@tonic-gate 	}
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	*ipp = ip;
7117c478bd9Sstevel@tonic-gate 	return (0);
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate 
714f79b6382SJustin Frank void
fini_daemon(void)715f79b6382SJustin Frank fini_daemon(void)
716f79b6382SJustin Frank {
717f79b6382SJustin Frank 	EInterval_t *ip;
718f79b6382SJustin Frank 
719f79b6382SJustin Frank 	/* shut down the threads running the policies */
720f79b6382SJustin Frank 	for (ip = first_interval; ip != NULL; ip = ip->next) {
721f79b6382SJustin Frank 		if (ip->has_thread) {
722f79b6382SJustin Frank 			/*
723f79b6382SJustin Frank 			 * there is a thread for this interval; tell it to stop
724f79b6382SJustin Frank 			 * by clearing the interval
725f79b6382SJustin Frank 			 */
726f79b6382SJustin Frank 			ip->interval = 0;
727f79b6382SJustin Frank 		}
728f79b6382SJustin Frank 	}
729f79b6382SJustin Frank 	for (ip = first_interval; ip != NULL; ip = ip->next) {
730f79b6382SJustin Frank 		if (ip->has_thread) {
731f79b6382SJustin Frank 			(void) pthread_join(ip->thread, NULL);
732f79b6382SJustin Frank 		}
733f79b6382SJustin Frank 	}
734f79b6382SJustin Frank 	/* shut down the timer thread */
735f79b6382SJustin Frank 	while (timer_state != READY)
736f79b6382SJustin Frank 		(void) sched_yield();
737f79b6382SJustin Frank 	(void) pthread_mutex_lock(&timer_mutex);
738f79b6382SJustin Frank 	timer_state = TIMER_SHUTDOWN;
739f79b6382SJustin Frank 	(void) pthread_cond_signal(&timer_cond);
740f79b6382SJustin Frank 	(void) pthread_mutex_unlock(&timer_mutex);
741f79b6382SJustin Frank 	(void) pthread_join(timer_thread_id, NULL);
742f79b6382SJustin Frank 	(void) pthread_mutex_destroy(&env_lock_mutex);
743f79b6382SJustin Frank 	(void) pthread_mutex_destroy(&timer_mutex);
744f79b6382SJustin Frank 	(void) pthread_cond_destroy(&timer_cond);
745f79b6382SJustin Frank 	(void) sem_destroy(&timer_sem);
746f79b6382SJustin Frank }
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate void
init_daemon(void)7497c478bd9Sstevel@tonic-gate init_daemon(void)
7507c478bd9Sstevel@tonic-gate {
7517c478bd9Sstevel@tonic-gate 	int32_t intervals = 0;
7527c478bd9Sstevel@tonic-gate 	int32_t threads = 0;
7537c478bd9Sstevel@tonic-gate 	int32_t status;
7547c478bd9Sstevel@tonic-gate 	FILE *fp;
7557c478bd9Sstevel@tonic-gate 	char filename[PATH_MAX];
7567c478bd9Sstevel@tonic-gate 	char platform[64];
7577c478bd9Sstevel@tonic-gate 	EInterval_t *ip, *prev;
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 	if (sysinfo(SI_PLATFORM, platform, sizeof (platform)) == -1) {
7607c478bd9Sstevel@tonic-gate 		if (debug_flag)
761f79b6382SJustin Frank 			syslog(LOG_ERR, "%s", strerror(errno));
7627c478bd9Sstevel@tonic-gate 		return;
7637c478bd9Sstevel@tonic-gate 	}
7647c478bd9Sstevel@tonic-gate 
765f79b6382SJustin Frank 	(void) snprintf(filename, sizeof (filename),
766f79b6382SJustin Frank 	    "/usr/platform/%s/lib/platsvcd.conf", platform);
7677c478bd9Sstevel@tonic-gate 	if ((fp = fopen(filename, "r")) == NULL) {
7687c478bd9Sstevel@tonic-gate 		if (debug_flag)
769f79b6382SJustin Frank 			syslog(LOG_ERR, "%s", strerror(errno));
7707c478bd9Sstevel@tonic-gate 		return;
7717c478bd9Sstevel@tonic-gate 	}
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate 	status = get_timeout(fp, &app_timeout);
7747c478bd9Sstevel@tonic-gate 	if (status != 0) {
7757c478bd9Sstevel@tonic-gate 		if (debug_flag)
776f79b6382SJustin Frank 			syslog(LOG_ERR, "%s", strerror(errno));
7777c478bd9Sstevel@tonic-gate 		return;
7787c478bd9Sstevel@tonic-gate 	}
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate 	status = sem_init(&timer_sem, 0, 1);
7817c478bd9Sstevel@tonic-gate 	if (status == -1) {
7827c478bd9Sstevel@tonic-gate 		if (debug_flag)
783f79b6382SJustin Frank 			syslog(LOG_ERR, "%s", strerror(errno));
7847c478bd9Sstevel@tonic-gate 		return;
7857c478bd9Sstevel@tonic-gate 	}
7867c478bd9Sstevel@tonic-gate 
787f79b6382SJustin Frank 	(void) strlcpy(env_lock_state, PSVC_LOCK_ENABLED, LOCK_STRING_MAX);
788f79b6382SJustin Frank 	(void) pthread_mutex_init(&env_lock_mutex, NULL);
789f79b6382SJustin Frank 	(void) pthread_mutex_init(&timer_mutex, NULL);
790f79b6382SJustin Frank 	(void) pthread_cond_init(&timer_cond, NULL);
791f79b6382SJustin Frank 
792f79b6382SJustin Frank 	timer_state = NOT_READY;
7937c478bd9Sstevel@tonic-gate 	status = pthread_create(&timer_thread_id, NULL,
794f79b6382SJustin Frank 	    (void *(*)())timer_thread, 0);
7957c478bd9Sstevel@tonic-gate 	if (status != 0) {
7967c478bd9Sstevel@tonic-gate 		if (debug_flag)
797f79b6382SJustin Frank 			syslog(LOG_ERR, "%s", strerror(errno));
7987c478bd9Sstevel@tonic-gate 		return;
7997c478bd9Sstevel@tonic-gate 	}
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 	/* get timer thread running */
8027c478bd9Sstevel@tonic-gate 	while (timer_state != READY)
803f79b6382SJustin Frank 		(void) sched_yield();
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate 	for (;;) {
8067c478bd9Sstevel@tonic-gate 		status = load_interval(fp, &ip);
8077c478bd9Sstevel@tonic-gate 		if (status != 0)
8087c478bd9Sstevel@tonic-gate 			break;
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate #ifdef	lint
8117c478bd9Sstevel@tonic-gate 		prev = NULL;
8127c478bd9Sstevel@tonic-gate #endif
8137c478bd9Sstevel@tonic-gate 		if (first_interval == 0)
8147c478bd9Sstevel@tonic-gate 			first_interval = ip;
8157c478bd9Sstevel@tonic-gate 		else
8167c478bd9Sstevel@tonic-gate 			prev->next = ip;
8177c478bd9Sstevel@tonic-gate 		prev = ip;
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 		++intervals;
8207c478bd9Sstevel@tonic-gate 		if (ip->interval == 0) {
8217c478bd9Sstevel@tonic-gate 			run_policies(ip);
8227c478bd9Sstevel@tonic-gate 		} else {
8237c478bd9Sstevel@tonic-gate 			thread_setup(ip);
8247c478bd9Sstevel@tonic-gate 			++threads;
8257c478bd9Sstevel@tonic-gate 		}
8267c478bd9Sstevel@tonic-gate 	}
8277c478bd9Sstevel@tonic-gate 	if (intervals == 0) {
8287c478bd9Sstevel@tonic-gate 		if (debug_flag)
8297c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "ERROR: No policies started");
8307c478bd9Sstevel@tonic-gate 		return;
8317c478bd9Sstevel@tonic-gate 	}
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate 	if (status == -1) {
8347c478bd9Sstevel@tonic-gate 		if (debug_flag)
835f79b6382SJustin Frank 			syslog(LOG_ERR, "%s", strerror(errno));
8367c478bd9Sstevel@tonic-gate 		return;
8377c478bd9Sstevel@tonic-gate 	}
8387c478bd9Sstevel@tonic-gate }
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate 
count_records(FILE * fp,char * end,uint32_t * countp)8417c478bd9Sstevel@tonic-gate static int32_t count_records(FILE *fp, char *end, uint32_t *countp)
8427c478bd9Sstevel@tonic-gate {
8437c478bd9Sstevel@tonic-gate 	long first_record;
8447c478bd9Sstevel@tonic-gate 	char *ret;
8457c478bd9Sstevel@tonic-gate 	char buf[BUFSZ];
8467c478bd9Sstevel@tonic-gate 	uint32_t count = 0;
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 	first_record = ftell(fp);
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 	while ((ret = fgets(buf, BUFSZ, fp)) != NULL) {
8517c478bd9Sstevel@tonic-gate 		if (strncmp(end, buf, strlen(end)) == 0)
8527c478bd9Sstevel@tonic-gate 			break;
8537c478bd9Sstevel@tonic-gate 		++count;
8547c478bd9Sstevel@tonic-gate 	}
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate 	if (ret == NULL) {
8577c478bd9Sstevel@tonic-gate 		errno = EINVAL;
8587c478bd9Sstevel@tonic-gate 		return (-1);
8597c478bd9Sstevel@tonic-gate 	}
8607c478bd9Sstevel@tonic-gate 
861f79b6382SJustin Frank 	(void) fseek(fp, first_record, SEEK_SET);
8627c478bd9Sstevel@tonic-gate 	*countp = count;
8637c478bd9Sstevel@tonic-gate 	return (0);
8647c478bd9Sstevel@tonic-gate }
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate /*
8677c478bd9Sstevel@tonic-gate  * Find start of a section within the config file,
8687c478bd9Sstevel@tonic-gate  * Returns number of records in the section.
8697c478bd9Sstevel@tonic-gate  * FILE *fd is set to first data record within section.
8707c478bd9Sstevel@tonic-gate  */
8717c478bd9Sstevel@tonic-gate static int32_t
find_file_section(FILE * fd,char * start)8727c478bd9Sstevel@tonic-gate find_file_section(FILE *fd, char *start)
8737c478bd9Sstevel@tonic-gate {
8747c478bd9Sstevel@tonic-gate 	char *ret;
8757c478bd9Sstevel@tonic-gate 	char buf[BUFSZ];
8767c478bd9Sstevel@tonic-gate 	char name[32];
8777c478bd9Sstevel@tonic-gate 	int found;
8787c478bd9Sstevel@tonic-gate 
879f79b6382SJustin Frank 	(void) fseek(fd, 0, SEEK_SET);
8807c478bd9Sstevel@tonic-gate 	while ((ret = fgets(buf, BUFSZ, fd)) != NULL) {
8817c478bd9Sstevel@tonic-gate 		if (strncmp(start, buf, strlen(start)) == 0)
8827c478bd9Sstevel@tonic-gate 			break;
8837c478bd9Sstevel@tonic-gate 	}
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate 	if (ret == NULL) {
8867c478bd9Sstevel@tonic-gate 		errno = EINVAL;
8877c478bd9Sstevel@tonic-gate 		return (-1);
8887c478bd9Sstevel@tonic-gate 	}
8897c478bd9Sstevel@tonic-gate 
890f79b6382SJustin Frank 	found = sscanf(buf, "%31s", name);
8917c478bd9Sstevel@tonic-gate 	if (found != 1) {
8927c478bd9Sstevel@tonic-gate 		errno = EINVAL;
8937c478bd9Sstevel@tonic-gate 		return (-1);
8947c478bd9Sstevel@tonic-gate 	} else {
8957c478bd9Sstevel@tonic-gate 		return (0);
8967c478bd9Sstevel@tonic-gate 	}
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate }
8997c478bd9Sstevel@tonic-gate 
name_compare_qsort(picl_psvc_t * s1,picl_psvc_t * s2)9007c478bd9Sstevel@tonic-gate static int32_t name_compare_qsort(picl_psvc_t *s1, picl_psvc_t *s2)
9017c478bd9Sstevel@tonic-gate {
9027c478bd9Sstevel@tonic-gate 	return (strcmp(s1->name, s2->name));
9037c478bd9Sstevel@tonic-gate }
9047c478bd9Sstevel@tonic-gate 
name_compare_bsearch(char * s1,picl_psvc_t * s2)9057c478bd9Sstevel@tonic-gate static int32_t name_compare_bsearch(char *s1, picl_psvc_t *s2)
9067c478bd9Sstevel@tonic-gate {
9077c478bd9Sstevel@tonic-gate 	return (strcmp(s1, s2->name));
9087c478bd9Sstevel@tonic-gate }
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate /*
9117c478bd9Sstevel@tonic-gate  * Create a property and add it to the specified node.
9127c478bd9Sstevel@tonic-gate  * PICL will take a segmentation violation if a volatile property
9137c478bd9Sstevel@tonic-gate  * has a non-zero size.
9147c478bd9Sstevel@tonic-gate  */
node_property(picl_nodehdl_t node,int (* read)(ptree_rarg_t *,void *),int (* write)(ptree_warg_t *,const void *),picl_prop_type_t type,unsigned int size,unsigned int accessmode,char * name,void * value)9157c478bd9Sstevel@tonic-gate static int32_t node_property(picl_nodehdl_t node,
9167c478bd9Sstevel@tonic-gate 	int (*read)(ptree_rarg_t *, void *),
9177c478bd9Sstevel@tonic-gate 	int (*write)(ptree_warg_t *, const void *), picl_prop_type_t type,
9187c478bd9Sstevel@tonic-gate 	unsigned int size, unsigned int accessmode, char *name, void *value)
9197c478bd9Sstevel@tonic-gate {
9207c478bd9Sstevel@tonic-gate 	ptree_propinfo_t propinfo;
9217c478bd9Sstevel@tonic-gate 	picl_prophdl_t prophdl;
9227c478bd9Sstevel@tonic-gate 	int err;
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 	propinfo.version = PSVC_PLUGIN_VERSION;
9257c478bd9Sstevel@tonic-gate 	if (accessmode & PICL_VOLATILE) {
9267c478bd9Sstevel@tonic-gate 		propinfo.read = read;
9277c478bd9Sstevel@tonic-gate 		propinfo.write = write;
9287c478bd9Sstevel@tonic-gate 	} else {
9297c478bd9Sstevel@tonic-gate 		propinfo.read = NULL;
9307c478bd9Sstevel@tonic-gate 		propinfo.write = NULL;
9317c478bd9Sstevel@tonic-gate 	}
9327c478bd9Sstevel@tonic-gate 	propinfo.piclinfo.type = type;
9337c478bd9Sstevel@tonic-gate 	propinfo.piclinfo.accessmode = accessmode;
9347c478bd9Sstevel@tonic-gate 	propinfo.piclinfo.size = size;
935f79b6382SJustin Frank 	(void) strcpy(propinfo.piclinfo.name, name);
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 	err = ptree_create_prop(&propinfo, value, &prophdl);
9387c478bd9Sstevel@tonic-gate 	if (err != 0) {
9397c478bd9Sstevel@tonic-gate 		return (err);
9407c478bd9Sstevel@tonic-gate 	}
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate 	err = ptree_add_prop(node, prophdl);
9437c478bd9Sstevel@tonic-gate 	if (err != 0)
9447c478bd9Sstevel@tonic-gate 		return (err);
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 	return (0);
9477c478bd9Sstevel@tonic-gate }
9487c478bd9Sstevel@tonic-gate 
init_err(const char * fmt,char * arg1,char * arg2)949f79b6382SJustin Frank static void init_err(const char *fmt, char *arg1, char *arg2)
9507c478bd9Sstevel@tonic-gate {
9517c478bd9Sstevel@tonic-gate 	char msg[256];
9527c478bd9Sstevel@tonic-gate 
953f79b6382SJustin Frank 	(void) snprintf(msg, sizeof (msg), fmt, arg1, arg2);
954f79b6382SJustin Frank 	syslog(LOG_ERR, "%s", msg);
9557c478bd9Sstevel@tonic-gate }
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate static int
projected_lookup(picl_prophdl_t proph,struct proj_prop ** dstp)9587c478bd9Sstevel@tonic-gate projected_lookup(picl_prophdl_t proph, struct proj_prop **dstp)
9597c478bd9Sstevel@tonic-gate {
9607c478bd9Sstevel@tonic-gate 	int i;
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate 	for (i = 0; i < proj_prop_count; ++i) {
9637c478bd9Sstevel@tonic-gate 		if (prop_list[i].handle == proph) {
9647c478bd9Sstevel@tonic-gate 			*dstp = &prop_list[i];
9657c478bd9Sstevel@tonic-gate 			return (PICL_SUCCESS);
9667c478bd9Sstevel@tonic-gate 		}
9677c478bd9Sstevel@tonic-gate 	}
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate 	return (PICL_INVALIDHANDLE);
9707c478bd9Sstevel@tonic-gate }
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate int
projected_read(ptree_rarg_t * rarg,void * buf)9737c478bd9Sstevel@tonic-gate projected_read(ptree_rarg_t *rarg, void *buf)
9747c478bd9Sstevel@tonic-gate {
9757c478bd9Sstevel@tonic-gate 	ptree_propinfo_t propinfo;
9767c478bd9Sstevel@tonic-gate 	struct proj_prop *dstinfo;
9777c478bd9Sstevel@tonic-gate 	int err;
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate 	err = projected_lookup(rarg->proph, &dstinfo);
9807c478bd9Sstevel@tonic-gate 	if (err != 0) {
9817c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
9827c478bd9Sstevel@tonic-gate 	}
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 	err = ptree_get_propinfo(rarg->proph, &propinfo);
9867c478bd9Sstevel@tonic-gate 	if (err != 0)
9877c478bd9Sstevel@tonic-gate 		return (err);
9887c478bd9Sstevel@tonic-gate 	err = ptree_get_propval_by_name(dstinfo->dst_node,
989f79b6382SJustin Frank 	    dstinfo->name, buf, propinfo.piclinfo.size);
9907c478bd9Sstevel@tonic-gate 	if (err != 0)
9917c478bd9Sstevel@tonic-gate 		return (err);
9927c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
9937c478bd9Sstevel@tonic-gate }
9947c478bd9Sstevel@tonic-gate 
9957c478bd9Sstevel@tonic-gate int
projected_write(ptree_warg_t * warg,const void * buf)9967c478bd9Sstevel@tonic-gate projected_write(ptree_warg_t *warg, const void *buf)
9977c478bd9Sstevel@tonic-gate {
9987c478bd9Sstevel@tonic-gate 	ptree_propinfo_t propinfo;
9997c478bd9Sstevel@tonic-gate 	struct proj_prop *dstinfo;
10007c478bd9Sstevel@tonic-gate 	int err;
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 	err = projected_lookup(warg->proph, &dstinfo);
10037c478bd9Sstevel@tonic-gate 	if (err != 0) {
10047c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
10057c478bd9Sstevel@tonic-gate 	}
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 	err = ptree_get_propinfo(warg->proph, &propinfo);
10087c478bd9Sstevel@tonic-gate 	if (err != 0)
10097c478bd9Sstevel@tonic-gate 		return (err);
10107c478bd9Sstevel@tonic-gate 	err = ptree_update_propval_by_name(dstinfo->dst_node,
1011f79b6382SJustin Frank 	    dstinfo->name, buf, propinfo.piclinfo.size);
10127c478bd9Sstevel@tonic-gate 	if (err != 0)
10137c478bd9Sstevel@tonic-gate 		return (err);
10147c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
10157c478bd9Sstevel@tonic-gate }
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate int
psvc_read_volatile(ptree_rarg_t * rarg,void * buf)10187c478bd9Sstevel@tonic-gate psvc_read_volatile(ptree_rarg_t *rarg, void *buf)
10197c478bd9Sstevel@tonic-gate {
10207c478bd9Sstevel@tonic-gate 	ptree_propinfo_t propinfo;
10217c478bd9Sstevel@tonic-gate 	char name[32], class[32];
10227c478bd9Sstevel@tonic-gate 	int err, i;
10237c478bd9Sstevel@tonic-gate 	int32_t attr_num = -1;
10247c478bd9Sstevel@tonic-gate 	int32_t use_attr_num = 0;
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate 	err = ptree_get_propval_by_name(rarg->nodeh, "name", name,
1027f79b6382SJustin Frank 	    sizeof (name));
10287c478bd9Sstevel@tonic-gate 	if (err != 0) {
10297c478bd9Sstevel@tonic-gate 		return (err);
10307c478bd9Sstevel@tonic-gate 	}
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 	err = ptree_get_propval_by_name(rarg->nodeh, "_class", class,
1033f79b6382SJustin Frank 	    sizeof (class));
10347c478bd9Sstevel@tonic-gate 	if (err != 0) {
10357c478bd9Sstevel@tonic-gate 		return (err);
10367c478bd9Sstevel@tonic-gate 	}
10377c478bd9Sstevel@tonic-gate 
10387c478bd9Sstevel@tonic-gate 	err = ptree_get_propinfo(rarg->proph, &propinfo);
10397c478bd9Sstevel@tonic-gate 	if (err != 0) {
10407c478bd9Sstevel@tonic-gate 		return (err);
10417c478bd9Sstevel@tonic-gate 	}
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate 	for (i = 0; i < PICL_PROP_TRANS_COUNT; i++) {
10447c478bd9Sstevel@tonic-gate 		if ((strcmp(class, picl_prop_trans[i].picl_class) == 0) &&
10457c478bd9Sstevel@tonic-gate 		    (strcmp(propinfo.piclinfo.name,
1046f79b6382SJustin Frank 		    picl_prop_trans[i].picl_prop) == 0)) {
10477c478bd9Sstevel@tonic-gate 			attr_num = i;
10487c478bd9Sstevel@tonic-gate 			break;
10497c478bd9Sstevel@tonic-gate 		}
10507c478bd9Sstevel@tonic-gate 	}
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 	if (attr_num == -1)
10537c478bd9Sstevel@tonic-gate 		for (i = 0; i < ATTR_STR_TAB_SIZE; i++) {
10547c478bd9Sstevel@tonic-gate 			if (strcmp(propinfo.piclinfo.name,
1055f79b6382SJustin Frank 			    attr_str_tab[i]) == 0) {
10567c478bd9Sstevel@tonic-gate 				attr_num = i;
10577c478bd9Sstevel@tonic-gate 				use_attr_num = 1;
10587c478bd9Sstevel@tonic-gate 				break;
10597c478bd9Sstevel@tonic-gate 			}
10607c478bd9Sstevel@tonic-gate 		}
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate 	if (use_attr_num)
10637c478bd9Sstevel@tonic-gate 		err = psvc_get_attr(hdlp, name, attr_num, buf);
10647c478bd9Sstevel@tonic-gate 	else
10657c478bd9Sstevel@tonic-gate 		err = psvc_get_attr(hdlp, name,
10667c478bd9Sstevel@tonic-gate 		    picl_prop_trans[attr_num].psvc_prop,
10677c478bd9Sstevel@tonic-gate 		    buf);
10687c478bd9Sstevel@tonic-gate 
10697c478bd9Sstevel@tonic-gate 	if (err != 0) {
10707c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
10717c478bd9Sstevel@tonic-gate 	}
10727c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
10737c478bd9Sstevel@tonic-gate }
10747c478bd9Sstevel@tonic-gate 
10757c478bd9Sstevel@tonic-gate int
psvc_write_volatile(ptree_warg_t * warg,const void * buf)10767c478bd9Sstevel@tonic-gate psvc_write_volatile(ptree_warg_t *warg, const void *buf)
10777c478bd9Sstevel@tonic-gate {
10787c478bd9Sstevel@tonic-gate 	ptree_propinfo_t propinfo;
10797c478bd9Sstevel@tonic-gate 	char name[32], class[32];
10807c478bd9Sstevel@tonic-gate 	int err, i;
10817c478bd9Sstevel@tonic-gate 	int32_t attr_num = -1;
10827c478bd9Sstevel@tonic-gate 	int32_t use_attr_num = 0;
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 	if (warg->cred.dc_euid != 0)
10857c478bd9Sstevel@tonic-gate 		return (PICL_PERMDENIED);
10867c478bd9Sstevel@tonic-gate 
10877c478bd9Sstevel@tonic-gate 	err = ptree_get_propval_by_name(warg->nodeh, "name", name,
1088f79b6382SJustin Frank 	    sizeof (name));
10897c478bd9Sstevel@tonic-gate 	if (err != 0) {
10907c478bd9Sstevel@tonic-gate 		return (err);
10917c478bd9Sstevel@tonic-gate 	}
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 	err = ptree_get_propval_by_name(warg->nodeh, "_class", class,
1094f79b6382SJustin Frank 	    sizeof (class));
10957c478bd9Sstevel@tonic-gate 	if (err != 0) {
10967c478bd9Sstevel@tonic-gate 		return (err);
10977c478bd9Sstevel@tonic-gate 	}
10987c478bd9Sstevel@tonic-gate 
10997c478bd9Sstevel@tonic-gate 	err = ptree_get_propinfo(warg->proph, &propinfo);
11007c478bd9Sstevel@tonic-gate 	if (err != 0) {
11017c478bd9Sstevel@tonic-gate 		return (err);
11027c478bd9Sstevel@tonic-gate 	}
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 	for (i = 0; i < PICL_PROP_TRANS_COUNT; i++) {
11057c478bd9Sstevel@tonic-gate 		if ((strcmp(class, picl_prop_trans[i].picl_class) == 0) &&
11067c478bd9Sstevel@tonic-gate 		    (strcmp(propinfo.piclinfo.name,
1107f79b6382SJustin Frank 		    picl_prop_trans[i].picl_prop) == 0)) {
11087c478bd9Sstevel@tonic-gate 			attr_num = i;
11097c478bd9Sstevel@tonic-gate 			break;
11107c478bd9Sstevel@tonic-gate 		}
11117c478bd9Sstevel@tonic-gate 	}
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate 	if (attr_num == -1)
11147c478bd9Sstevel@tonic-gate 		for (i = 0; i < ATTR_STR_TAB_SIZE; i++) {
11157c478bd9Sstevel@tonic-gate 			if (strcmp(propinfo.piclinfo.name,
1116f79b6382SJustin Frank 			    attr_str_tab[i]) == 0) {
11177c478bd9Sstevel@tonic-gate 			attr_num = i;
11187c478bd9Sstevel@tonic-gate 			use_attr_num = 1;
11197c478bd9Sstevel@tonic-gate 			break;
11207c478bd9Sstevel@tonic-gate 			}
11217c478bd9Sstevel@tonic-gate 		}
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 	if (use_attr_num)
11247c478bd9Sstevel@tonic-gate 		err = psvc_set_attr(hdlp, name, attr_num, (void *)buf);
11257c478bd9Sstevel@tonic-gate 	else
11267c478bd9Sstevel@tonic-gate 		err = psvc_set_attr(hdlp, name,
11277c478bd9Sstevel@tonic-gate 		    picl_prop_trans[attr_num].psvc_prop,
11287c478bd9Sstevel@tonic-gate 		    (void *)buf);
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate 	if (err != 0) {
11317c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
11327c478bd9Sstevel@tonic-gate 	}
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
11357c478bd9Sstevel@tonic-gate }
11367c478bd9Sstevel@tonic-gate 
create_reference_properties(struct assoc_pair * assoc_tbl,int32_t count,char * assoc_name)11377c478bd9Sstevel@tonic-gate void create_reference_properties(struct assoc_pair *assoc_tbl, int32_t count,
11387c478bd9Sstevel@tonic-gate 	char *assoc_name)
11397c478bd9Sstevel@tonic-gate {
11407c478bd9Sstevel@tonic-gate 	picl_psvc_t *aobjp, *dobjp;
11417c478bd9Sstevel@tonic-gate 	picl_prophdl_t tbl_hdl;
11427c478bd9Sstevel@tonic-gate 	picl_nodehdl_t *dep_list;
11437c478bd9Sstevel@tonic-gate 	ptree_propinfo_t propinfo;
11447c478bd9Sstevel@tonic-gate 	char *funcname = "create_reference_properties"