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";
11457c478bd9Sstevel@tonic-gate 	char name[PICL_PROPNAMELEN_MAX];
11467c478bd9Sstevel@tonic-gate 	int32_t i, j, offset;
11477c478bd9Sstevel@tonic-gate 	int32_t dependents;
11487c478bd9Sstevel@tonic-gate 	int32_t err;
11497c478bd9Sstevel@tonic-gate 	char class[PICL_CLASSNAMELEN_MAX];
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate 	for (i = 0; i < count; ++i) {
11527c478bd9Sstevel@tonic-gate 		/* antecedent */
11537c478bd9Sstevel@tonic-gate 		aobjp = (picl_psvc_t *)bsearch(assoc_tbl[i].antecedent,
1154f79b6382SJustin Frank 		    psvc_hdl.objects, psvc_hdl.obj_count,
1155f79b6382SJustin Frank 		    sizeof (picl_psvc_t),
1156f79b6382SJustin Frank 		    (int (*)(const void *, const void *))
1157f79b6382SJustin Frank 		    name_compare_bsearch);
11587c478bd9Sstevel@tonic-gate 		if (aobjp == NULL) {
11597c478bd9Sstevel@tonic-gate 			init_err(ID_NOT_FOUND_MSG,
1160f79b6382SJustin Frank 			    funcname, assoc_tbl[i].antecedent);
11617c478bd9Sstevel@tonic-gate 			return;
11627c478bd9Sstevel@tonic-gate 		}
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate 		/* skip if table already created */
11657c478bd9Sstevel@tonic-gate 		if (ptree_get_propval_by_name(aobjp->node, assoc_name,
1166f79b6382SJustin Frank 		    &tbl_hdl, sizeof (tbl_hdl)) == 0) {
11677c478bd9Sstevel@tonic-gate 			continue;
11687c478bd9Sstevel@tonic-gate 		}
11697c478bd9Sstevel@tonic-gate 
11707c478bd9Sstevel@tonic-gate 		/* create a new table */
11717c478bd9Sstevel@tonic-gate 		err = ptree_create_table(&tbl_hdl);
11727c478bd9Sstevel@tonic-gate 		if (err != 0) {
11737c478bd9Sstevel@tonic-gate 			init_err(PTREE_CREATE_TABLE_FAILED_MSG,
1174f79b6382SJustin Frank 			    funcname, picl_strerror(err));
11757c478bd9Sstevel@tonic-gate 			return;
11767c478bd9Sstevel@tonic-gate 		}
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 		err = node_property(aobjp->node, NULL, NULL,
1179f79b6382SJustin Frank 		    PICL_PTYPE_TABLE, sizeof (tbl_hdl), PICL_READ,
1180f79b6382SJustin Frank 		    assoc_name, &tbl_hdl);
11817c478bd9Sstevel@tonic-gate 		if (err != 0) {
11827c478bd9Sstevel@tonic-gate 			init_err(CREATE_PROP_FAILED_MSG, funcname,
1183f79b6382SJustin Frank 			    picl_strerror(err));
11847c478bd9Sstevel@tonic-gate 			return;
11857c478bd9Sstevel@tonic-gate 		}
11867c478bd9Sstevel@tonic-gate 
11877c478bd9Sstevel@tonic-gate 		/* determine number of elements in the table */
11887c478bd9Sstevel@tonic-gate 		dependents = 0;
11897c478bd9Sstevel@tonic-gate 		for (j = i; j < count; ++j) {
11907c478bd9Sstevel@tonic-gate 			if (strcmp(aobjp->name, assoc_tbl[j].antecedent) == 0)
11917c478bd9Sstevel@tonic-gate 				++dependents;
11927c478bd9Sstevel@tonic-gate 		}
11937c478bd9Sstevel@tonic-gate 
11947c478bd9Sstevel@tonic-gate 		dep_list = (picl_nodehdl_t *)malloc(sizeof (picl_nodehdl_t) *
11957c478bd9Sstevel@tonic-gate 		    dependents);
11967c478bd9Sstevel@tonic-gate 		if (dep_list == NULL) {
11977c478bd9Sstevel@tonic-gate 			init_err(MALLOC_FAILED_MSG, funcname, strerror(errno));
11987c478bd9Sstevel@tonic-gate 			return;
11997c478bd9Sstevel@tonic-gate 		}
12007c478bd9Sstevel@tonic-gate 		/* build row of reference properties */
12017c478bd9Sstevel@tonic-gate 		offset = 0;
12027c478bd9Sstevel@tonic-gate 		for (j = i; j < count; ++j) {
12037c478bd9Sstevel@tonic-gate 			if (strcmp(aobjp->name, assoc_tbl[j].antecedent) != 0)
12047c478bd9Sstevel@tonic-gate 				continue;
12057c478bd9Sstevel@tonic-gate 
12067c478bd9Sstevel@tonic-gate 			dobjp = (picl_psvc_t *)bsearch(assoc_tbl[j].dependent,
1207f79b6382SJustin Frank 			    psvc_hdl.objects,
1208f79b6382SJustin Frank 			    psvc_hdl.obj_count, sizeof (picl_psvc_t),
1209f79b6382SJustin Frank 			    (int (*)(const void *, const void *))
1210f79b6382SJustin Frank 			    name_compare_bsearch);
12117c478bd9Sstevel@tonic-gate 			if (dobjp == NULL) {
12127c478bd9Sstevel@tonic-gate 				init_err(ID_NOT_FOUND_MSG,
1213f79b6382SJustin Frank 				    funcname, assoc_tbl[j].dependent);
12147c478bd9Sstevel@tonic-gate 				return;
12157c478bd9Sstevel@tonic-gate 			}
12167c478bd9Sstevel@tonic-gate 
12177c478bd9Sstevel@tonic-gate 			/*
12187c478bd9Sstevel@tonic-gate 			 * Reference property name must be
12197c478bd9Sstevel@tonic-gate 			 * _classname_propertyname
12207c478bd9Sstevel@tonic-gate 			 */
12217c478bd9Sstevel@tonic-gate 			err = ptree_get_propval_by_name(dobjp->node,
1222f79b6382SJustin Frank 			    "_class", class, sizeof (class));
12237c478bd9Sstevel@tonic-gate 			if (err != 0) {
12247c478bd9Sstevel@tonic-gate 				init_err(CLASS_NOT_FOUND_MSG, funcname,
1225f79b6382SJustin Frank 				    assoc_tbl[j].dependent);
12267c478bd9Sstevel@tonic-gate 				return;
12277c478bd9Sstevel@tonic-gate 			}
1228f79b6382SJustin Frank 			(void) snprintf(name, sizeof (name), "_%s_subclass",
1229f79b6382SJustin Frank 			    class);
12307c478bd9Sstevel@tonic-gate 
12317c478bd9Sstevel@tonic-gate 			propinfo.version = PSVC_PLUGIN_VERSION;
12327c478bd9Sstevel@tonic-gate 			propinfo.read = NULL;
12337c478bd9Sstevel@tonic-gate 			propinfo.write = NULL;
12347c478bd9Sstevel@tonic-gate 			propinfo.piclinfo.type = PICL_PTYPE_REFERENCE;
12357c478bd9Sstevel@tonic-gate 			propinfo.piclinfo.accessmode = PICL_READ;
12367c478bd9Sstevel@tonic-gate 			propinfo.piclinfo.size = sizeof (picl_nodehdl_t);
1237f79b6382SJustin Frank 			(void) strcpy(propinfo.piclinfo.name, name);
12387c478bd9Sstevel@tonic-gate 
12397c478bd9Sstevel@tonic-gate 			err = ptree_create_prop(&propinfo, &dobjp->node,
1240f79b6382SJustin Frank 			    dep_list + offset);
12417c478bd9Sstevel@tonic-gate 			if (err != 0) {
12427c478bd9Sstevel@tonic-gate 				init_err(PTREE_CREATE_PROP_FAILED_MSG,
1243f79b6382SJustin Frank 				    name, picl_strerror(err));
12447c478bd9Sstevel@tonic-gate 				return;
12457c478bd9Sstevel@tonic-gate 			}
12467c478bd9Sstevel@tonic-gate 
12477c478bd9Sstevel@tonic-gate 			++offset;
12487c478bd9Sstevel@tonic-gate 		}
12497c478bd9Sstevel@tonic-gate 
12507c478bd9Sstevel@tonic-gate 		/* add row to table */
12517c478bd9Sstevel@tonic-gate 		err = ptree_add_row_to_table(tbl_hdl, dependents, dep_list);
12527c478bd9Sstevel@tonic-gate 		if (err != 0) {
12537c478bd9Sstevel@tonic-gate 			init_err(PTREE_ADD_ROW_FAILED_MSG, funcname,
1254f79b6382SJustin Frank 			    picl_strerror(err));
12557c478bd9Sstevel@tonic-gate 			return;
12567c478bd9Sstevel@tonic-gate 		}
12577c478bd9Sstevel@tonic-gate 
12587c478bd9Sstevel@tonic-gate 	}
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate }
12627c478bd9Sstevel@tonic-gate 
12637c478bd9Sstevel@tonic-gate /* Load projected properties */
12647c478bd9Sstevel@tonic-gate static void
load_projected_properties(FILE * fp)12657c478bd9Sstevel@tonic-gate load_projected_properties(FILE *fp)
12667c478bd9Sstevel@tonic-gate {
12677c478bd9Sstevel@tonic-gate 	int32_t found;
12687c478bd9Sstevel@tonic-gate 	ptree_propinfo_t propinfo;
12697c478bd9Sstevel@tonic-gate 	ptree_propinfo_t dstinfo;
12707c478bd9Sstevel@tonic-gate 	picl_prophdl_t src_prophdl, dst_prophdl;
12717c478bd9Sstevel@tonic-gate 	picl_nodehdl_t src_node, dst_node;
12727c478bd9Sstevel@tonic-gate 	int err, i;
12737c478bd9Sstevel@tonic-gate 	picl_psvc_t *srcobjp, *dstobjp;
12747c478bd9Sstevel@tonic-gate 	char src[32], dst[256];
12757c478bd9Sstevel@tonic-gate 	char src_prop[32], dst_prop[32];
12767c478bd9Sstevel@tonic-gate 	char buf[BUFSZ];
12777c478bd9Sstevel@tonic-gate 	char *funcname = "load_projected_properties";
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate 	if (find_file_section(fp, "PROJECTED_PROPERTIES") != 0)
12807c478bd9Sstevel@tonic-gate 		return;
12817c478bd9Sstevel@tonic-gate 
12827c478bd9Sstevel@tonic-gate 	if (count_records(fp, "PROJECTED_PROPERTIES_END", &proj_prop_count) !=
1283f79b6382SJustin Frank 	    0) {
12847c478bd9Sstevel@tonic-gate 		init_err(INVALID_FILE_FORMAT_MSG, funcname, 0);
12857c478bd9Sstevel@tonic-gate 		return;
12867c478bd9Sstevel@tonic-gate 	}
12877c478bd9Sstevel@tonic-gate 
12887c478bd9Sstevel@tonic-gate 	prop_list = (struct proj_prop *)malloc(sizeof (struct proj_prop)
1289f79b6382SJustin Frank 	    * proj_prop_count);
12907c478bd9Sstevel@tonic-gate 	if (prop_list == NULL) {
12917c478bd9Sstevel@tonic-gate 		init_err(MALLOC_FAILED_MSG, funcname, strerror(errno));
12927c478bd9Sstevel@tonic-gate 		return;
12937c478bd9Sstevel@tonic-gate 	}
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 	for (i = 0; i < proj_prop_count; ++i) {
1296f79b6382SJustin Frank 		buf[0] = '\0';
1297f79b6382SJustin Frank 		(void) fgets(buf, BUFSZ, fp);
1298f79b6382SJustin Frank 		found = sscanf(buf, "%31s %31s %255s %31s", src, src_prop, dst,
1299f79b6382SJustin Frank 		    dst_prop);
13007c478bd9Sstevel@tonic-gate 		if (found != 4) {
13017c478bd9Sstevel@tonic-gate 			init_err(INVALID_FILE_FORMAT_MSG, funcname, 0);
13027c478bd9Sstevel@tonic-gate 			return;
13037c478bd9Sstevel@tonic-gate 		}
13047c478bd9Sstevel@tonic-gate 
13057c478bd9Sstevel@tonic-gate 		/* find src node */
13067c478bd9Sstevel@tonic-gate 		if (src[0] == '/') {
13077c478bd9Sstevel@tonic-gate 			/* picl node name, outside psvc subtree */
13087c478bd9Sstevel@tonic-gate 			err = ptree_get_node_by_path(src, &src_node);
13097c478bd9Sstevel@tonic-gate 			if (err != 0) {
13107c478bd9Sstevel@tonic-gate 				init_err(NODE_NOT_FOUND_MSG, funcname, src);
13117c478bd9Sstevel@tonic-gate 				return;
13127c478bd9Sstevel@tonic-gate 			}
13137c478bd9Sstevel@tonic-gate 		} else {
13147c478bd9Sstevel@tonic-gate 			srcobjp = (picl_psvc_t *)bsearch(src, psvc_hdl.objects,
1315f79b6382SJustin Frank 			    psvc_hdl.obj_count, sizeof (picl_psvc_t),
1316f79b6382SJustin Frank 			    (int (*)(const void *, const void *))
1317f79b6382SJustin Frank 			    name_compare_bsearch);
13187c478bd9Sstevel@tonic-gate 			if (srcobjp == NULL) {
13197c478bd9Sstevel@tonic-gate 				init_err(ID_NOT_FOUND_MSG, funcname, src);
13207c478bd9Sstevel@tonic-gate 				return;
13217c478bd9Sstevel@tonic-gate 			}
13227c478bd9Sstevel@tonic-gate 			src_node = srcobjp->node;
13237c478bd9Sstevel@tonic-gate 		}
13247c478bd9Sstevel@tonic-gate 
13257c478bd9Sstevel@tonic-gate 		/* find dest node */
13267c478bd9Sstevel@tonic-gate 		if (dst[0] == '/') {
13277c478bd9Sstevel@tonic-gate 			/* picl node name, outside psvc subtree */
13287c478bd9Sstevel@tonic-gate 			err = ptree_get_node_by_path(dst, &dst_node);
13297c478bd9Sstevel@tonic-gate 			if (err != 0) {
13307c478bd9Sstevel@tonic-gate 				init_err(NODE_NOT_FOUND_MSG, funcname, dst);
13317c478bd9Sstevel@tonic-gate 				return;
13327c478bd9Sstevel@tonic-gate 			}
13337c478bd9Sstevel@tonic-gate 			prop_list[i].dst_node = dst_node;
13347c478bd9Sstevel@tonic-gate 		} else {
13357c478bd9Sstevel@tonic-gate 			dstobjp = (picl_psvc_t *)bsearch(dst, psvc_hdl.objects,
1336f79b6382SJustin Frank 			    psvc_hdl.obj_count, sizeof (picl_psvc_t),
1337f79b6382SJustin Frank 			    (int (*)(const void *, const void *))
1338f79b6382SJustin Frank 			    name_compare_bsearch);
13397c478bd9Sstevel@tonic-gate 			if (dstobjp == NULL) {
13407c478bd9Sstevel@tonic-gate 				init_err(ID_NOT_FOUND_MSG, funcname, dst);
13417c478bd9Sstevel@tonic-gate 				return;
13427c478bd9Sstevel@tonic-gate 			}
13437c478bd9Sstevel@tonic-gate 			dst_node = dstobjp->node;
13447c478bd9Sstevel@tonic-gate 			prop_list[i].dst_node = dst_node;
13457c478bd9Sstevel@tonic-gate 		}
13467c478bd9Sstevel@tonic-gate 
13477c478bd9Sstevel@tonic-gate 		/* determine destination property size */
13487c478bd9Sstevel@tonic-gate 		err = ptree_get_first_prop(dst_node, &dst_prophdl);
13497c478bd9Sstevel@tonic-gate 		while (err == 0) {
13507c478bd9Sstevel@tonic-gate 			err = ptree_get_propinfo(dst_prophdl, &dstinfo);
13517c478bd9Sstevel@tonic-gate 			if (err != 0)
13527c478bd9Sstevel@tonic-gate 				break;
13537c478bd9Sstevel@tonic-gate 			if (strcmp(dst_prop, dstinfo.piclinfo.name) == 0)
13547c478bd9Sstevel@tonic-gate 				break;
13557c478bd9Sstevel@tonic-gate 			err = ptree_get_next_prop(dst_prophdl, &dst_prophdl);
13567c478bd9Sstevel@tonic-gate 		}
13577c478bd9Sstevel@tonic-gate 		if (err != 0) {
13587c478bd9Sstevel@tonic-gate 			init_err(SIZE_NOT_FOUND_MSG, funcname, dst_prop);
13597c478bd9Sstevel@tonic-gate 			return;
13607c478bd9Sstevel@tonic-gate 		}
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate 		propinfo.version = PSVC_PLUGIN_VERSION;
13637c478bd9Sstevel@tonic-gate 		propinfo.read = projected_read;
13647c478bd9Sstevel@tonic-gate 		propinfo.write = projected_write;
13657c478bd9Sstevel@tonic-gate 		propinfo.piclinfo.type = dstinfo.piclinfo.type;
13667c478bd9Sstevel@tonic-gate 		propinfo.piclinfo.accessmode =
1367f79b6382SJustin Frank 		    PICL_READ | PICL_WRITE | PICL_VOLATILE;
13687c478bd9Sstevel@tonic-gate 		propinfo.piclinfo.size = dstinfo.piclinfo.size;
1369f79b6382SJustin Frank 		(void) strcpy(propinfo.piclinfo.name, src_prop);
13707c478bd9Sstevel@tonic-gate 
13717c478bd9Sstevel@tonic-gate 		err = ptree_create_prop(&propinfo, 0, &src_prophdl);
13727c478bd9Sstevel@tonic-gate 		if (err != 0) {
13737c478bd9Sstevel@tonic-gate 			init_err(PTREE_CREATE_PROP_FAILED_MSG, funcname,
1374f79b6382SJustin Frank 			    picl_strerror(err));
13757c478bd9Sstevel@tonic-gate 			return;
13767c478bd9Sstevel@tonic-gate 		}
13777c478bd9Sstevel@tonic-gate 
13787c478bd9Sstevel@tonic-gate 		err = ptree_add_prop(src_node, src_prophdl);
13797c478bd9Sstevel@tonic-gate 		if (err != 0) {
13807c478bd9Sstevel@tonic-gate 			init_err(PTREE_ADD_PROP_FAILED_MSG, funcname,
1381f79b6382SJustin Frank 			    picl_strerror(err));
13827c478bd9Sstevel@tonic-gate 			return;
13837c478bd9Sstevel@tonic-gate 		}
13847c478bd9Sstevel@tonic-gate 
13857c478bd9Sstevel@tonic-gate 		prop_list[i].handle = src_prophdl;
1386f79b6382SJustin Frank 		(void) strcpy(prop_list[i].name, dst_prop);
13877c478bd9Sstevel@tonic-gate 
13887c478bd9Sstevel@tonic-gate 	}
13897c478bd9Sstevel@tonic-gate }
13907c478bd9Sstevel@tonic-gate 
13917c478bd9Sstevel@tonic-gate /* Load the association table */
load_associations(FILE * fp)13927c478bd9Sstevel@tonic-gate static void load_associations(FILE *fp)
13937c478bd9Sstevel@tonic-gate {
13947c478bd9Sstevel@tonic-gate 	char *funcname = "load_associations";
13957c478bd9Sstevel@tonic-gate 	uint32_t count;
13967c478bd9Sstevel@tonic-gate 	int found;
13977c478bd9Sstevel@tonic-gate 	int j;
13987c478bd9Sstevel@tonic-gate 	char assoc_name[32];
13997c478bd9Sstevel@tonic-gate 	struct assoc_pair *assoc_tbl;
14007c478bd9Sstevel@tonic-gate 	char name1[32];
14017c478bd9Sstevel@tonic-gate 	char buf[BUFSZ];
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 	/*
14047c478bd9Sstevel@tonic-gate 	 * ignore count in the file, correct count is highest
14057c478bd9Sstevel@tonic-gate 	 * association id + 1, now figured when loading ASSOC_STR
14067c478bd9Sstevel@tonic-gate 	 * section.
14077c478bd9Sstevel@tonic-gate 	 */
14087c478bd9Sstevel@tonic-gate 	if (find_file_section(fp, "ASSOCIATIONS") != 0)
14097c478bd9Sstevel@tonic-gate 		return;
14107c478bd9Sstevel@tonic-gate 
1411f79b6382SJustin Frank 	buf[0] = '\0';
1412f79b6382SJustin Frank 	(void) fgets(buf, BUFSZ, fp);
14137c478bd9Sstevel@tonic-gate 	while (strncmp("ASSOCIATIONS_END", buf, 16) != 0) {
1414f79b6382SJustin Frank 		found = sscanf(buf, "%31s %31s", name1, assoc_name);
14157c478bd9Sstevel@tonic-gate 		if (found != 2) {
14167c478bd9Sstevel@tonic-gate 			init_err(INVALID_FILE_FORMAT_MSG, funcname, 0);
14177c478bd9Sstevel@tonic-gate 			return;
14187c478bd9Sstevel@tonic-gate 		}
14197c478bd9Sstevel@tonic-gate 
14207c478bd9Sstevel@tonic-gate 		if (count_records(fp, "ASSOCIATION_END", &count) != 0) {
14217c478bd9Sstevel@tonic-gate 			init_err(INVALID_FILE_FORMAT_MSG, funcname, 0);
14227c478bd9Sstevel@tonic-gate 			return;
14237c478bd9Sstevel@tonic-gate 		}
14247c478bd9Sstevel@tonic-gate 
14257c478bd9Sstevel@tonic-gate 		assoc_tbl = (struct assoc_pair *)malloc(
1426f79b6382SJustin Frank 		    sizeof (struct assoc_pair) * count);
14277c478bd9Sstevel@tonic-gate 		if (assoc_tbl == NULL) {
14287c478bd9Sstevel@tonic-gate 			init_err(MALLOC_FAILED_MSG, funcname, strerror(errno));
14297c478bd9Sstevel@tonic-gate 			return;
14307c478bd9Sstevel@tonic-gate 		}
14317c478bd9Sstevel@tonic-gate 
14327c478bd9Sstevel@tonic-gate 		for (j = 0; j < count; ++j) {
1433f79b6382SJustin Frank 			buf[0] = '\0';
1434f79b6382SJustin Frank 			(void) fgets(buf, BUFSZ, fp);
1435f79b6382SJustin Frank 			found = sscanf(buf, "%31s %31s",
1436f79b6382SJustin Frank 			    assoc_tbl[j].antecedent, assoc_tbl[j].dependent);
14377c478bd9Sstevel@tonic-gate 			if (found != 2) {
14387c478bd9Sstevel@tonic-gate 				init_err(INVALID_FILE_FORMAT_MSG, funcname,
1439f79b6382SJustin Frank 				    0);
14407c478bd9Sstevel@tonic-gate 				return;
14417c478bd9Sstevel@tonic-gate 			}
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate 		}
1444f79b6382SJustin Frank 		buf[0] = '\0';
1445f79b6382SJustin Frank 		(void) fgets(buf, BUFSZ, fp);
14467c478bd9Sstevel@tonic-gate 		if (strncmp(buf, "ASSOCIATION_END", 15) != 0) {
14477c478bd9Sstevel@tonic-gate 			init_err(INVALID_FILE_FORMAT_MSG, funcname, 0);
14487c478bd9Sstevel@tonic-gate 			return;
14497c478bd9Sstevel@tonic-gate 		}
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 		/* Create separate list of dependents for each antecedent */
14527c478bd9Sstevel@tonic-gate 		if (strcmp(assoc_name, "PSVC_TABLE") != 0) {
14537c478bd9Sstevel@tonic-gate 			create_reference_properties(assoc_tbl, count,
1454f79b6382SJustin Frank 			    assoc_name);
14557c478bd9Sstevel@tonic-gate 		}
14567c478bd9Sstevel@tonic-gate 
14577c478bd9Sstevel@tonic-gate 		free(assoc_tbl);
1458f79b6382SJustin Frank 		buf[0] = '\0';
1459f79b6382SJustin Frank 		(void) fgets(buf, BUFSZ, fp);
14607c478bd9Sstevel@tonic-gate 	}
14617c478bd9Sstevel@tonic-gate 
14627c478bd9Sstevel@tonic-gate }
14637c478bd9Sstevel@tonic-gate 
14647c478bd9Sstevel@tonic-gate /* Enviornmental Lock Object's Read and Write routine */
1465f79b6382SJustin Frank /* ARGSUSED */
14667c478bd9Sstevel@tonic-gate static int
env_lock_read(ptree_rarg_t * rarg,void * buf)14677c478bd9Sstevel@tonic-gate env_lock_read(ptree_rarg_t *rarg, void *buf)
14687c478bd9Sstevel@tonic-gate {
1469f79b6382SJustin Frank 	(void) strlcpy((char *)buf, env_lock_state, LOCK_STRING_MAX);
14707c478bd9Sstevel@tonic-gate 	return (PSVC_SUCCESS);
14717c478bd9Sstevel@tonic-gate }
14727c478bd9Sstevel@tonic-gate 
1473f79b6382SJustin Frank /* ARGSUSED */
14747c478bd9Sstevel@tonic-gate static int
env_lock_write(ptree_warg_t * warg,const void * buf)14757c478bd9Sstevel@tonic-gate env_lock_write(ptree_warg_t *warg, const void *buf)
14767c478bd9Sstevel@tonic-gate {
14777c478bd9Sstevel@tonic-gate 	int32_t status = PSVC_SUCCESS;
14787c478bd9Sstevel@tonic-gate 	char *var = (char *)buf;
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate 	/*
14817c478bd9Sstevel@tonic-gate 	 * Check to make sure that the value is either Disabled or Enabled
14827c478bd9Sstevel@tonic-gate 	 * as these are the only 2 states that this object can be set to.
14837c478bd9Sstevel@tonic-gate 	 */
14847c478bd9Sstevel@tonic-gate 	if ((strcmp(var, PSVC_LOCK_DISABLED) != 0) &&
14857c478bd9Sstevel@tonic-gate 	    (strcmp(var, PSVC_LOCK_ENABLED) != 0)) {
14867c478bd9Sstevel@tonic-gate 		errno = EINVAL;
14877c478bd9Sstevel@tonic-gate 		return (PSVC_FAILURE);
14887c478bd9Sstevel@tonic-gate 	}
14897c478bd9Sstevel@tonic-gate 
1490f79b6382SJustin Frank 	(void) pthread_mutex_lock(&env_lock_mutex);
14917c478bd9Sstevel@tonic-gate 
14927c478bd9Sstevel@tonic-gate 	/*
14937c478bd9Sstevel@tonic-gate 	 * If the state is already Enabled we can set the state to Disabled
14947c478bd9Sstevel@tonic-gate 	 * to stop the policies.
14957c478bd9Sstevel@tonic-gate 	 */
14967c478bd9Sstevel@tonic-gate 	if (strcmp(env_lock_state, PSVC_LOCK_ENABLED) == 0) {
1497f79b6382SJustin Frank 		(void) pthread_mutex_unlock(&env_lock_mutex);
14987c478bd9Sstevel@tonic-gate 		status = timed_lock_wait(PSVC_LOCK_DISABLED);
14997c478bd9Sstevel@tonic-gate 		if (status == -1) {
15007c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, SEM_WAIT_FAILED_MSG);
15017c478bd9Sstevel@tonic-gate 		}
15027c478bd9Sstevel@tonic-gate 		return (status);
15037c478bd9Sstevel@tonic-gate 	}
15047c478bd9Sstevel@tonic-gate 
15057c478bd9Sstevel@tonic-gate 	/*
15067c478bd9Sstevel@tonic-gate 	 * If the state is Running we must go into timed_lock_wait to aquire
15077c478bd9Sstevel@tonic-gate 	 * the env_lock.
15087c478bd9Sstevel@tonic-gate 	 */
15097c478bd9Sstevel@tonic-gate 	if (strcmp(env_lock_state, PSVC_LOCK_RUNNING) == 0) {
1510f79b6382SJustin Frank 		(void) pthread_mutex_unlock(&env_lock_mutex);
15117c478bd9Sstevel@tonic-gate 		status = timed_lock_wait(PSVC_LOCK_DISABLED);
15127c478bd9Sstevel@tonic-gate 		if (status == -1) {
15137c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, SEM_WAIT_FAILED_MSG);
15147c478bd9Sstevel@tonic-gate 		}
15157c478bd9Sstevel@tonic-gate 		return (status);
15167c478bd9Sstevel@tonic-gate 	}
15177c478bd9Sstevel@tonic-gate 
15187c478bd9Sstevel@tonic-gate 	/*
15197c478bd9Sstevel@tonic-gate 	 * If the state is already Disabled we need to first check to see if
15207c478bd9Sstevel@tonic-gate 	 * we are resetting it to Disabled or changing it to Enabled. If we
15217c478bd9Sstevel@tonic-gate 	 * are resetting it to Disabled then we need to stop the timer and
15227c478bd9Sstevel@tonic-gate 	 * restart it. If we are changing it to Enabled we just set it to
15237c478bd9Sstevel@tonic-gate 	 * enabled.
15247c478bd9Sstevel@tonic-gate 	 */
15257c478bd9Sstevel@tonic-gate 	if (strcmp(env_lock_state, PSVC_LOCK_DISABLED) == 0) {
15267c478bd9Sstevel@tonic-gate 		if (strcmp(var, PSVC_LOCK_DISABLED) == 0) {
1527f79b6382SJustin Frank 			(void) pthread_mutex_lock(&timer_mutex);
15287c478bd9Sstevel@tonic-gate 			if (timer_state == ACTIVE) {
15297c478bd9Sstevel@tonic-gate 				timer_state = NOT_READY;
15307c478bd9Sstevel@tonic-gate 				/* stop timer */
1531f79b6382SJustin Frank 				(void) pthread_cond_signal(&timer_cond);
1532f79b6382SJustin Frank 				(void) pthread_mutex_unlock(&timer_mutex);
15337c478bd9Sstevel@tonic-gate 				/* wait for timer to reset */
15347c478bd9Sstevel@tonic-gate 				while (timer_state != READY)
1535f79b6382SJustin Frank 					(void) sched_yield();
1536f79b6382SJustin Frank 				(void) pthread_mutex_lock(&timer_mutex);
15377c478bd9Sstevel@tonic-gate 				timer_state = HAVE_REQUEST;
15387c478bd9Sstevel@tonic-gate 				/* restart timer */
1539f79b6382SJustin Frank 				(void) pthread_cond_signal(&timer_cond);
15407c478bd9Sstevel@tonic-gate 			}
1541f79b6382SJustin Frank 			(void) pthread_mutex_unlock(&timer_mutex);
15427c478bd9Sstevel@tonic-gate 		} else {
1543f79b6382SJustin Frank 			(void) strlcpy(env_lock_state, var, LOCK_STRING_MAX);
15447c478bd9Sstevel@tonic-gate 		}
15457c478bd9Sstevel@tonic-gate 	}
1546f79b6382SJustin Frank 	(void) pthread_mutex_unlock(&env_lock_mutex);
15477c478bd9Sstevel@tonic-gate 	return (PSVC_SUCCESS);
15487c478bd9Sstevel@tonic-gate }
15497c478bd9Sstevel@tonic-gate 
15507c478bd9Sstevel@tonic-gate static int
init_env_lock_node(picl_nodehdl_t root_node)15517c478bd9Sstevel@tonic-gate init_env_lock_node(picl_nodehdl_t root_node)
15527c478bd9Sstevel@tonic-gate {
15537c478bd9Sstevel@tonic-gate 	int err;
15547c478bd9Sstevel@tonic-gate 	ptree_propinfo_t propinfo;
15557c478bd9Sstevel@tonic-gate 	char *funcname = "init_env_lock_node";
15567c478bd9Sstevel@tonic-gate 
15577c478bd9Sstevel@tonic-gate 	/* Here we are creating a Enviornmental Lock Node */
15587c478bd9Sstevel@tonic-gate 	err = ptree_create_node("/plugins/environmental", "picl", &lock_node);
15597c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
15607c478bd9Sstevel@tonic-gate 		init_err(PTREE_CREATE_NODE_FAILED_MSG, funcname,
15617c478bd9Sstevel@tonic-gate 		    picl_strerror(err));
15627c478bd9Sstevel@tonic-gate 		return (err);
15637c478bd9Sstevel@tonic-gate 	}
15647c478bd9Sstevel@tonic-gate 
15657c478bd9Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION_1,
15667c478bd9Sstevel@tonic-gate 	    PICL_PTYPE_CHARSTRING, PICL_READ | PICL_WRITE | PICL_VOLATILE,
1567f79b6382SJustin Frank 	    32, "State", env_lock_read, env_lock_write);
15687c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
15697c478bd9Sstevel@tonic-gate 		init_err(NODE_PROP_FAILED_MSG, funcname, picl_strerror(err));
15707c478bd9Sstevel@tonic-gate 		return (err);
15717c478bd9Sstevel@tonic-gate 	}
15727c478bd9Sstevel@tonic-gate 
15737c478bd9Sstevel@tonic-gate 	err = ptree_create_and_add_prop(lock_node, &propinfo,
15747c478bd9Sstevel@tonic-gate 	    NULL, NULL);
15757c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
15767c478bd9Sstevel@tonic-gate 		init_err(PTREE_ADD_PROP_FAILED_MSG, funcname,
15777c478bd9Sstevel@tonic-gate 		    picl_strerror(err));
15787c478bd9Sstevel@tonic-gate 		return (err);
15797c478bd9Sstevel@tonic-gate 	}
15807c478bd9Sstevel@tonic-gate 
15817c478bd9Sstevel@tonic-gate 	err = ptree_add_node(root_node, lock_node);
15827c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
15837c478bd9Sstevel@tonic-gate 		init_err(PTREE_ADD_NODE_FAILED_MSG, funcname,
15847c478bd9Sstevel@tonic-gate 		    picl_strerror(err));
15857c478bd9Sstevel@tonic-gate 		return (err);
15867c478bd9Sstevel@tonic-gate 	}
15877c478bd9Sstevel@tonic-gate 
15887c478bd9Sstevel@tonic-gate 	return (PSVC_SUCCESS);
15897c478bd9Sstevel@tonic-gate }
15907c478bd9Sstevel@tonic-gate 
15917c478bd9Sstevel@tonic-gate void
psvc_plugin_init(void)15927c478bd9Sstevel@tonic-gate psvc_plugin_init(void)
15937c478bd9Sstevel@tonic-gate {
15947c478bd9Sstevel@tonic-gate 	struct classinfo *cp;
15957c478bd9Sstevel@tonic-gate 	picl_nodehdl_t root_node;
15967c478bd9Sstevel@tonic-gate 	picl_nodehdl_t parent_node;
15977c478bd9Sstevel@tonic-gate 	char *funcname = "psvc_plugin_init";
15987c478bd9Sstevel@tonic-gate 	char platform[32];
15997c478bd9Sstevel@tonic-gate 	char filename[256];
16007c478bd9Sstevel@tonic-gate 	char buf[BUFSZ];
16017c478bd9Sstevel@tonic-gate 	int32_t i, j;
16027c478bd9Sstevel@tonic-gate 	int err, found;
16037c478bd9Sstevel@tonic-gate 
16047c478bd9Sstevel@tonic-gate 	psvc_paths = NULL;
16057c478bd9Sstevel@tonic-gate 	psvc_hdl.obj_count = 0;
16067c478bd9Sstevel@tonic-gate 	psvc_hdl.objects = NULL;
16077c478bd9Sstevel@tonic-gate 	psvc_hdl.fp = NULL;
16087c478bd9Sstevel@tonic-gate 	first_interval = NULL;
16097c478bd9Sstevel@tonic-gate 
16107c478bd9Sstevel@tonic-gate 	/*
16117c478bd9Sstevel@tonic-gate 	 * So the volatile read/write routines can retrieve data from
16127c478bd9Sstevel@tonic-gate 	 * psvc or picl
16137c478bd9Sstevel@tonic-gate 	 */
16147c478bd9Sstevel@tonic-gate 	err = psvc_init(&hdlp);
16157c478bd9Sstevel@tonic-gate 	if (err != 0) {
16167c478bd9Sstevel@tonic-gate 		init_err(PSVC_INIT_ERR_MSG, funcname, strerror(errno));
16177c478bd9Sstevel@tonic-gate 	}
16187c478bd9Sstevel@tonic-gate 
16197c478bd9Sstevel@tonic-gate 	if (sysinfo(SI_PLATFORM, platform, sizeof (platform)) == -1) {
16207c478bd9Sstevel@tonic-gate 		init_err(SYSINFO_FAILED_MSG, funcname, 0);
16217c478bd9Sstevel@tonic-gate 		return;
16227c478bd9Sstevel@tonic-gate 	}
16237c478bd9Sstevel@tonic-gate 
1624f79b6382SJustin Frank 	(void) snprintf(filename, sizeof (filename),
1625f79b6382SJustin Frank 	    "/usr/platform/%s/lib/psvcobj.conf", platform);
16267c478bd9Sstevel@tonic-gate 	if ((psvc_hdl.fp = fopen(filename, "r")) == NULL) {
16277c478bd9Sstevel@tonic-gate 		init_err(FILE_OPEN_FAILED_MSG, funcname, filename);
16287c478bd9Sstevel@tonic-gate 		return;
16297c478bd9Sstevel@tonic-gate 	}
16307c478bd9Sstevel@tonic-gate 
16317c478bd9Sstevel@tonic-gate 	/* Create all PICL nodes */
16327c478bd9Sstevel@tonic-gate 	if (find_file_section(psvc_hdl.fp, "OBJECT_INFO") == -1) {
16337c478bd9Sstevel@tonic-gate 		init_err(INVALID_FILE_FORMAT1_MSG, funcname, filename);
16347c478bd9Sstevel@tonic-gate 		return;
16357c478bd9Sstevel@tonic-gate 	}
16367c478bd9Sstevel@tonic-gate 	if (count_records(psvc_hdl.fp, "OBJECT_INFO_END", &psvc_hdl.obj_count)
16377c478bd9Sstevel@tonic-gate 	    == -1) {
16387c478bd9Sstevel@tonic-gate 		init_err(INVALID_FILE_FORMAT1_MSG, funcname, filename);
16397c478bd9Sstevel@tonic-gate 		return;
16407c478bd9Sstevel@tonic-gate 	}
16417c478bd9Sstevel@tonic-gate 	if ((psvc_hdl.objects = (picl_psvc_t *)malloc(sizeof (picl_psvc_t) *
1642f79b6382SJustin Frank 	    psvc_hdl.obj_count)) == NULL) {
16437c478bd9Sstevel@tonic-gate 		init_err(MALLOC_FAILED_MSG, funcname, strerror(errno));
16447c478bd9Sstevel@tonic-gate 		return;
16457c478bd9Sstevel@tonic-gate 	}
1646f79b6382SJustin Frank 	(void) memset(psvc_hdl.objects, 0,
1647f79b6382SJustin Frank 	    sizeof (picl_psvc_t) * psvc_hdl.obj_count);
16487c478bd9Sstevel@tonic-gate 
16497c478bd9Sstevel@tonic-gate 	err = ptree_get_root(&root_node);
16507c478bd9Sstevel@tonic-gate 	if (err != 0) {
16517c478bd9Sstevel@tonic-gate 		init_err(PTREE_GET_ROOT_FAILED_MSG, funcname,
1652f79b6382SJustin Frank 		    picl_strerror(err));
16537c478bd9Sstevel@tonic-gate 		return;
16547c478bd9Sstevel@tonic-gate 	}
16557c478bd9Sstevel@tonic-gate 
16567c478bd9Sstevel@tonic-gate 	/* Following array is  accessed directly by the psvc policies. */
16577c478bd9Sstevel@tonic-gate 	psvc_paths = (psvc_name_t *)malloc(sizeof (psvc_name_t) *
1658f79b6382SJustin Frank 	    psvc_hdl.obj_count);
16597c478bd9Sstevel@tonic-gate 	psvc_picl_nodes = psvc_hdl.obj_count;
16607c478bd9Sstevel@tonic-gate 	if (psvc_paths == NULL) {
16617c478bd9Sstevel@tonic-gate 		init_err(MALLOC_FAILED_MSG, funcname, strerror(errno));
16627c478bd9Sstevel@tonic-gate 		return;
16637c478bd9Sstevel@tonic-gate 	}
16647c478bd9Sstevel@tonic-gate 	for (i = 0; i < psvc_hdl.obj_count; ++i) {
16657c478bd9Sstevel@tonic-gate 		char *start;
16667c478bd9Sstevel@tonic-gate 		int32_t class;
16677c478bd9Sstevel@tonic-gate 		int32_t subclass;
16687c478bd9Sstevel@tonic-gate 		int32_t	cp_count;
16697c478bd9Sstevel@tonic-gate 		picl_psvc_t *objp = &psvc_hdl.objects[i];
1670f79b6382SJustin Frank 		buf[0] = '\0';
1671f79b6382SJustin Frank 		(void) fgets(buf, BUFSZ, psvc_hdl.fp);
16727c478bd9Sstevel@tonic-gate 		if (strncmp(buf, "OBJECT_INFO_END", 15) == 0)
16737c478bd9Sstevel@tonic-gate 			break;
16747c478bd9Sstevel@tonic-gate 
16757c478bd9Sstevel@tonic-gate 		start = strrchr(buf, '/');
16767c478bd9Sstevel@tonic-gate 		if (start == NULL) {
16777c478bd9Sstevel@tonic-gate 			init_err(INVALID_FILE_FORMAT1_MSG, funcname,
1678f79b6382SJustin Frank 			    filename);
16797c478bd9Sstevel@tonic-gate 			return;
16807c478bd9Sstevel@tonic-gate 		}
1681f79b6382SJustin Frank 		found = sscanf(start + 1, "%31s",  objp->name);
16827c478bd9Sstevel@tonic-gate 		if (found != 1) {
16837c478bd9Sstevel@tonic-gate 			init_err(INVALID_FILE_FORMAT1_MSG, funcname,
1684f79b6382SJustin Frank 			    filename);
16857c478bd9Sstevel@tonic-gate 			return;
16867c478bd9Sstevel@tonic-gate 		}
16877c478bd9Sstevel@tonic-gate 
16887c478bd9Sstevel@tonic-gate 		/* get class */
16897c478bd9Sstevel@tonic-gate 		err = psvc_get_attr(hdlp, objp->name, PSVC_CLASS_ATTR, &class);
16907c478bd9Sstevel@tonic-gate 		if (err != PSVC_SUCCESS) {
16917c478bd9Sstevel@tonic-gate 			init_err(CLASS_NOT_FOUND_MSG, funcname, objp->name);
16927c478bd9Sstevel@tonic-gate 			return;
16937c478bd9Sstevel@tonic-gate 		}
16947c478bd9Sstevel@tonic-gate 		if (class > NUM_CLASSES) {
16957c478bd9Sstevel@tonic-gate 			init_err(UNKNOWN_CLASS_MSG, funcname, 0);
16967c478bd9Sstevel@tonic-gate 			return;
16977c478bd9Sstevel@tonic-gate 		}
16987c478bd9Sstevel@tonic-gate 
16997c478bd9Sstevel@tonic-gate 		err = psvc_get_attr(hdlp, objp->name, PSVC_SUBCLASS_ATTR,
1700f79b6382SJustin Frank 		    &subclass);
17017c478bd9Sstevel@tonic-gate 		if (err != PSVC_SUCCESS) {
17027c478bd9Sstevel@tonic-gate 			init_err(SUBCLASS_NOT_FOUND_MSG, funcname, objp->name);
17037c478bd9Sstevel@tonic-gate 			return;
17047c478bd9Sstevel@tonic-gate 		}
17057c478bd9Sstevel@tonic-gate 
17067c478bd9Sstevel@tonic-gate 		err = ptree_create_node(objp->name, class_name[class],
1707f79b6382SJustin Frank 		    &objp->node);
17087c478bd9Sstevel@tonic-gate 		if (err != 0) {
17097c478bd9Sstevel@tonic-gate 			init_err(PTREE_CREATE_NODE_FAILED_MSG, funcname,
1710f79b6382SJustin Frank 			    picl_strerror(err));
17117c478bd9Sstevel@tonic-gate 			return;
17127c478bd9Sstevel@tonic-gate 		}
17137c478bd9Sstevel@tonic-gate 		if (strcmp(objp->name, PSVC_CHASSIS) == 0)
17147c478bd9Sstevel@tonic-gate 			system_node = objp->node;
17157c478bd9Sstevel@tonic-gate 
17167c478bd9Sstevel@tonic-gate 		for (j = 0; j < COMMON_COUNT; ++j) {
17177c478bd9Sstevel@tonic-gate 
17187c478bd9Sstevel@tonic-gate 			err = node_property(objp->node,
17197c478bd9Sstevel@tonic-gate 			    common[j].access & PICL_READ ?
17207c478bd9Sstevel@tonic-gate 			    psvc_read_volatile : 0,
17217c478bd9Sstevel@tonic-gate 			    common[j].access & PICL_WRITE ?
17227c478bd9Sstevel@tonic-gate 			    psvc_write_volatile : 0,
17237c478bd9Sstevel@tonic-gate 			    common[j].type, common[j].size,
17247c478bd9Sstevel@tonic-gate 			    common[j].access, common[j].name, 0);
17257c478bd9Sstevel@tonic-gate 			if (err != PSVC_SUCCESS) {
17267c478bd9Sstevel@tonic-gate 				init_err(NODE_PROP_FAILED_MSG, funcname,
1727f79b6382SJustin Frank 				    picl_strerror(err));
17287c478bd9Sstevel@tonic-gate 				return;
17297c478bd9Sstevel@tonic-gate 			}
17307c478bd9Sstevel@tonic-gate 		}
17317c478bd9Sstevel@tonic-gate 		cp = &class_properties[class];
17327c478bd9Sstevel@tonic-gate 		/* Locator LED Support */
17337c478bd9Sstevel@tonic-gate 		if (class == 2 && subclass == 2) {
17347c478bd9Sstevel@tonic-gate 			cp_count = 3;
17357c478bd9Sstevel@tonic-gate 		} else {
17367c478bd9Sstevel@tonic-gate 			cp_count = cp->count;
17377c478bd9Sstevel@tonic-gate 		}
17387c478bd9Sstevel@tonic-gate 
17397c478bd9Sstevel@tonic-gate 		for (j = 0; j < cp_count; ++j) {
17407c478bd9Sstevel@tonic-gate 			err = node_property(objp->node, psvc_read_volatile,
1741f79b6382SJustin Frank 			    psvc_write_volatile, cp->props[j].type,
1742f79b6382SJustin Frank 			    cp->props[j].size,
1743f79b6382SJustin Frank 			    cp->props[j].access, cp->props[j].name, 0);
17447c478bd9Sstevel@tonic-gate 			if (err != PSVC_SUCCESS) {
17457c478bd9Sstevel@tonic-gate 				init_err(NODE_PROP_FAILED_MSG, funcname,
1746f79b6382SJustin Frank 				    picl_strerror(err));
17477c478bd9Sstevel@tonic-gate 				return;
17487c478bd9Sstevel@tonic-gate 			}
17497c478bd9Sstevel@tonic-gate 		}
17507c478bd9Sstevel@tonic-gate 
17517c478bd9Sstevel@tonic-gate 		/* Link the nodes into the PICL tree */
17527c478bd9Sstevel@tonic-gate 		*start = 0;
17537c478bd9Sstevel@tonic-gate 		if (start == buf) {	/* no parent */
17547c478bd9Sstevel@tonic-gate 			parent_node = root_node;
17557c478bd9Sstevel@tonic-gate 		} else {
17567c478bd9Sstevel@tonic-gate 			err = ptree_get_node_by_path(buf, &parent_node);
17577c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
17587c478bd9Sstevel@tonic-gate 				init_err(NODE_NOT_FOUND_MSG, funcname, buf);
17597c478bd9Sstevel@tonic-gate 				return;
17607c478bd9Sstevel@tonic-gate 			}
17617c478bd9Sstevel@tonic-gate 		}
17627c478bd9Sstevel@tonic-gate 
17637c478bd9Sstevel@tonic-gate 		err = ptree_add_node(parent_node, objp->node);
17647c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
17657c478bd9Sstevel@tonic-gate 			init_err(PTREE_ADD_NODE_FAILED_MSG, funcname,
1766f79b6382SJustin Frank 			    picl_strerror(err));
17677c478bd9Sstevel@tonic-gate 			return;
17687c478bd9Sstevel@tonic-gate 		}
1769f79b6382SJustin Frank 		(void) strcpy(psvc_paths[i].parent_path, buf);
1770f79b6382SJustin Frank 		(void) strcpy(psvc_paths[i].child_name, objp->name);
17717c478bd9Sstevel@tonic-gate 		psvc_paths[i].child_node = objp->node;
17727c478bd9Sstevel@tonic-gate 	}
17737c478bd9Sstevel@tonic-gate 
17747c478bd9Sstevel@tonic-gate 	qsort(psvc_hdl.objects, psvc_hdl.obj_count, sizeof (picl_psvc_t),
1775f79b6382SJustin Frank 	    (int (*)(const void *, const void *))name_compare_qsort);
17767c478bd9Sstevel@tonic-gate 
17777c478bd9Sstevel@tonic-gate 	load_associations(psvc_hdl.fp);
17787c478bd9Sstevel@tonic-gate 	load_projected_properties(psvc_hdl.fp);
17797c478bd9Sstevel@tonic-gate 
17807c478bd9Sstevel@tonic-gate 	if (init_env_lock_node(root_node) != PSVC_SUCCESS)
17817c478bd9Sstevel@tonic-gate 		return;
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 	init_daemon();
17847c478bd9Sstevel@tonic-gate }
17857c478bd9Sstevel@tonic-gate 
17867c478bd9Sstevel@tonic-gate void
psvc_plugin_fini(void)17877c478bd9Sstevel@tonic-gate psvc_plugin_fini(void)
17887c478bd9Sstevel@tonic-gate {
17897c478bd9Sstevel@tonic-gate 	int32_t i;
17907c478bd9Sstevel@tonic-gate 	EInterval_t *ip, *next;
17917c478bd9Sstevel@tonic-gate 
1792f79b6382SJustin Frank 	fini_daemon();
17937c478bd9Sstevel@tonic-gate 	for (ip = first_interval; ip != 0; ip = next) {
1794f79b6382SJustin Frank 		for (i = 0; i < ip->num_tasks; ++i) {
1795f79b6382SJustin Frank 			(void) dlclose(ip->task_list[i].hdl);
17967c478bd9Sstevel@tonic-gate 			free(ip->task_list[i].obj_list);
1797f79b6382SJustin Frank 		}
17987c478bd9Sstevel@tonic-gate 		free(ip->task_list);
17997c478bd9Sstevel@tonic-gate 		next = ip->next;
18007c478bd9Sstevel@tonic-gate 		free(ip);
18017c478bd9Sstevel@tonic-gate 	}
1802f79b6382SJustin Frank 	free(prop_list);
1803f79b6382SJustin Frank 	free(psvc_paths);
1804f79b6382SJustin Frank 	free(psvc_hdl.objects);
1805f79b6382SJustin Frank 	if (psvc_hdl.fp != NULL)
1806f79b6382SJustin Frank 		(void) fclose(psvc_hdl.fp);
18077c478bd9Sstevel@tonic-gate 	psvc_fini(hdlp);
18087c478bd9Sstevel@tonic-gate }
18097c478bd9Sstevel@tonic-gate 
18107c478bd9Sstevel@tonic-gate void
psvc_plugin_register(void)18117c478bd9Sstevel@tonic-gate psvc_plugin_register(void)
18127c478bd9Sstevel@tonic-gate {
18137c478bd9Sstevel@tonic-gate 	picld_plugin_register(&psvc_reg);
18147c478bd9Sstevel@tonic-gate }
1815