Home | History | Annotate | Line # | Download | only in envstat
config.c revision 1.5.2.2
      1  1.5.2.2  matt /* 	$NetBSD: config.c,v 1.5.2.2 2007/11/06 23:36:23 matt Exp $	*/
      2  1.5.2.2  matt 
      3  1.5.2.2  matt /*-
      4  1.5.2.2  matt  * Copyright (c) 2007 Juan Romero Pardines.
      5  1.5.2.2  matt  * All rights reserved.
      6  1.5.2.2  matt  *
      7  1.5.2.2  matt  * Redistribution and use in source and binary forms, with or without
      8  1.5.2.2  matt  * modification, are permitted provided that the following conditions
      9  1.5.2.2  matt  * are met:
     10  1.5.2.2  matt  * 1. Redistributions of source code must retain the above copyright
     11  1.5.2.2  matt  *    notice, this list of conditions and the following disclaimer.
     12  1.5.2.2  matt  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.5.2.2  matt  *    notice, this list of conditions and the following disclaimer in the
     14  1.5.2.2  matt  *    documentation and/or other materials provided with the distribution.
     15  1.5.2.2  matt  *
     16  1.5.2.2  matt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  1.5.2.2  matt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  1.5.2.2  matt  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  1.5.2.2  matt  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  1.5.2.2  matt  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  1.5.2.2  matt  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  1.5.2.2  matt  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  1.5.2.2  matt  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  1.5.2.2  matt  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  1.5.2.2  matt  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  1.5.2.2  matt  */
     27  1.5.2.2  matt 
     28  1.5.2.2  matt #include <sys/cdefs.h>
     29  1.5.2.2  matt #ifndef lint
     30  1.5.2.2  matt __RCSID("$NetBSD: config.c,v 1.5.2.2 2007/11/06 23:36:23 matt Exp $");
     31  1.5.2.2  matt #endif /* not lint */
     32  1.5.2.2  matt 
     33  1.5.2.2  matt #include <stdio.h>
     34  1.5.2.2  matt #include <string.h>
     35  1.5.2.2  matt #include <stdlib.h>
     36  1.5.2.2  matt #include <err.h>
     37  1.5.2.2  matt #include <errno.h>
     38  1.5.2.2  matt #include <sys/queue.h>
     39  1.5.2.2  matt #include <prop/proplib.h>
     40  1.5.2.2  matt 
     41  1.5.2.2  matt #include "envstat.h"
     42  1.5.2.2  matt 
     43  1.5.2.2  matt /*
     44  1.5.2.2  matt  * Singly linked list for dictionaries that store properties
     45  1.5.2.2  matt  * in a sensor.
     46  1.5.2.2  matt  */
     47  1.5.2.2  matt static SLIST_HEAD(, sensor_block) sensor_block_list =
     48  1.5.2.2  matt     SLIST_HEAD_INITIALIZER(&sensor_block_list);
     49  1.5.2.2  matt 
     50  1.5.2.2  matt /*
     51  1.5.2.2  matt  * Singly linked list for devices that store a proplib array
     52  1.5.2.2  matt  * device with a device name.
     53  1.5.2.2  matt  */
     54  1.5.2.2  matt static SLIST_HEAD(, device_block) device_block_list =
     55  1.5.2.2  matt     SLIST_HEAD_INITIALIZER(&device_block_list);
     56  1.5.2.2  matt 
     57  1.5.2.2  matt enum {
     58  1.5.2.2  matt 	VALUE_ERR,
     59  1.5.2.2  matt 	PROP_ERR,
     60  1.5.2.2  matt 	SENSOR_ERR,
     61  1.5.2.2  matt 	DEV_ERR
     62  1.5.2.2  matt };
     63  1.5.2.2  matt 
     64  1.5.2.2  matt static prop_dictionary_t cfdict, sensordict;
     65  1.5.2.2  matt static void config_errmsg(int, const char *, const char *);
     66  1.5.2.2  matt 
     67  1.5.2.2  matt static void
     68  1.5.2.2  matt config_errmsg(int lvl, const char *key, const char *key2)
     69  1.5.2.2  matt {
     70  1.5.2.2  matt 	(void)printf("error: ");
     71  1.5.2.2  matt 
     72  1.5.2.2  matt 	switch (lvl) {
     73  1.5.2.2  matt 	case VALUE_ERR:
     74  1.5.2.2  matt 		(void)printf("invalid value for '%s' in `%s'\n",
     75  1.5.2.2  matt 		    key, key2);
     76  1.5.2.2  matt 		break;
     77  1.5.2.2  matt 	case PROP_ERR:
     78  1.5.2.2  matt 		(void)printf("the '%s' property is not allowed "
     79  1.5.2.2  matt 		    "in `%s'\n", key, key2);
     80  1.5.2.2  matt 		break;
     81  1.5.2.2  matt 	case SENSOR_ERR:
     82  1.5.2.2  matt 		(void)printf("'%s' is not a valid sensor in the "
     83  1.5.2.2  matt 		   "`%s' device\n", key, key2);
     84  1.5.2.2  matt 		break;
     85  1.5.2.2  matt 	case DEV_ERR:
     86  1.5.2.2  matt 		(void)printf("device `%s' doesn't exist\n", key);
     87  1.5.2.2  matt 		break;
     88  1.5.2.2  matt 	}
     89  1.5.2.2  matt 
     90  1.5.2.2  matt 	(void)printf("please fix the configuration file!\n");
     91  1.5.2.2  matt 	exit(EXIT_FAILURE);
     92  1.5.2.2  matt }
     93  1.5.2.2  matt 
     94  1.5.2.2  matt /*
     95  1.5.2.2  matt  * Adds a property into the global dictionary 'cfdict'.
     96  1.5.2.2  matt  */
     97  1.5.2.2  matt void
     98  1.5.2.2  matt config_dict_add_prop(const char *key, char *value)
     99  1.5.2.2  matt {
    100  1.5.2.2  matt 	if (!key || !value)
    101  1.5.2.2  matt 		return;
    102  1.5.2.2  matt 
    103  1.5.2.2  matt 	if (!sensordict) {
    104  1.5.2.2  matt 		sensordict = prop_dictionary_create();
    105  1.5.2.2  matt 		if (!sensordict)
    106  1.5.2.2  matt 			err(EXIT_FAILURE, "cfdict");
    107  1.5.2.2  matt 	}
    108  1.5.2.2  matt 
    109  1.5.2.2  matt 	if (!prop_dictionary_set_cstring(sensordict, key, value))
    110  1.5.2.2  matt 		err(EXIT_FAILURE, "prop_dict_set_cstring");
    111  1.5.2.2  matt }
    112  1.5.2.2  matt 
    113  1.5.2.2  matt /*
    114  1.5.2.2  matt  * Adds the last property into the dictionary and puts it into
    115  1.5.2.2  matt  * the singly linked list for future use.
    116  1.5.2.2  matt  */
    117  1.5.2.2  matt void
    118  1.5.2.2  matt config_dict_mark(const char *key)
    119  1.5.2.2  matt {
    120  1.5.2.2  matt 	struct sensor_block *sb;
    121  1.5.2.2  matt 
    122  1.5.2.2  matt 	if (!key)
    123  1.5.2.2  matt 		err(EXIT_FAILURE, "!key");
    124  1.5.2.2  matt 
    125  1.5.2.2  matt 	sb = calloc(1, sizeof(*sb));
    126  1.5.2.2  matt 	if (!sb)
    127  1.5.2.2  matt 		err(EXIT_FAILURE, "!sb");
    128  1.5.2.2  matt 
    129  1.5.2.2  matt 	sb->dict = prop_dictionary_create();
    130  1.5.2.2  matt 	if (!sb->dict)
    131  1.5.2.2  matt 		err(EXIT_FAILURE, "!sb->dict");
    132  1.5.2.2  matt 
    133  1.5.2.2  matt 	sb->dict = prop_dictionary_copy(sensordict);
    134  1.5.2.2  matt 	SLIST_INSERT_HEAD(&sensor_block_list, sb, sb_head);
    135  1.5.2.2  matt 	config_dict_destroy(sensordict);
    136  1.5.2.2  matt }
    137  1.5.2.2  matt 
    138  1.5.2.2  matt /*
    139  1.5.2.2  matt  * Only used for debugging purposses.
    140  1.5.2.2  matt  */
    141  1.5.2.2  matt void
    142  1.5.2.2  matt config_dict_dump(prop_dictionary_t d)
    143  1.5.2.2  matt {
    144  1.5.2.2  matt 	char *buf;
    145  1.5.2.2  matt 
    146  1.5.2.2  matt 	buf = prop_dictionary_externalize(d);
    147  1.5.2.2  matt 	(void)printf("%s", buf);
    148  1.5.2.2  matt 	free(buf);
    149  1.5.2.2  matt }
    150  1.5.2.2  matt 
    151  1.5.2.2  matt /*
    152  1.5.2.2  matt  * Returns the global dictionary.
    153  1.5.2.2  matt  */
    154  1.5.2.2  matt prop_dictionary_t
    155  1.5.2.2  matt config_dict_parsed(void)
    156  1.5.2.2  matt {
    157  1.5.2.2  matt 	return cfdict;
    158  1.5.2.2  matt }
    159  1.5.2.2  matt 
    160  1.5.2.2  matt /*
    161  1.5.2.2  matt  * Destroys all objects from a dictionary.
    162  1.5.2.2  matt  */
    163  1.5.2.2  matt void
    164  1.5.2.2  matt config_dict_destroy(prop_dictionary_t d)
    165  1.5.2.2  matt {
    166  1.5.2.2  matt 	prop_object_iterator_t iter;
    167  1.5.2.2  matt 	prop_object_t obj;
    168  1.5.2.2  matt 
    169  1.5.2.2  matt 	iter = prop_dictionary_iterator(d);
    170  1.5.2.2  matt 	if (!iter)
    171  1.5.2.2  matt 		err(EXIT_FAILURE, "!iter");
    172  1.5.2.2  matt 
    173  1.5.2.2  matt 	 while ((obj = prop_object_iterator_next(iter)) != NULL) {
    174  1.5.2.2  matt 		 prop_dictionary_remove(d,
    175  1.5.2.2  matt 		     prop_dictionary_keysym_cstring_nocopy(obj));
    176  1.5.2.2  matt 		 prop_object_iterator_reset(iter);
    177  1.5.2.2  matt 	 }
    178  1.5.2.2  matt 
    179  1.5.2.2  matt 	 prop_object_iterator_release(iter);
    180  1.5.2.2  matt }
    181  1.5.2.2  matt 
    182  1.5.2.2  matt /*
    183  1.5.2.2  matt  * Parses all properties on the device and adds the device
    184  1.5.2.2  matt  * into the singly linked list for devices and the global dictionary.
    185  1.5.2.2  matt  */
    186  1.5.2.2  matt void
    187  1.5.2.2  matt config_devblock_add(const char *key, prop_dictionary_t kdict)
    188  1.5.2.2  matt {
    189  1.5.2.2  matt 	struct device_block *db;
    190  1.5.2.2  matt 	struct sensor_block *sb;
    191  1.5.2.2  matt 	prop_array_t array;
    192  1.5.2.2  matt 	prop_object_iterator_t iter;
    193  1.5.2.2  matt 	prop_dictionary_t sdict;
    194  1.5.2.2  matt 	prop_object_t obj;
    195  1.5.2.2  matt 	prop_string_t lindex;
    196  1.5.2.2  matt 	const char *sensor;
    197  1.5.2.2  matt 	bool sensor_found = false;
    198  1.5.2.2  matt 
    199  1.5.2.2  matt 	if (!key)
    200  1.5.2.2  matt 		err(EXIT_FAILURE, "devblock !key");
    201  1.5.2.2  matt 
    202  1.5.2.2  matt 	array = prop_dictionary_get(kdict, key);
    203  1.5.2.2  matt 	if (!array)
    204  1.5.2.2  matt 		config_errmsg(DEV_ERR, key, NULL);
    205  1.5.2.2  matt 
    206  1.5.2.2  matt 	SLIST_FOREACH(sb, &sensor_block_list, sb_head) {
    207  1.5.2.2  matt 		/* get the index object value from configuration */
    208  1.5.2.2  matt 		lindex = prop_dictionary_get(sb->dict, "index");
    209  1.5.2.2  matt 		sensor = prop_string_cstring_nocopy(lindex);
    210  1.5.2.2  matt 
    211  1.5.2.2  matt 		iter = prop_array_iterator(array);
    212  1.5.2.2  matt 		if (!iter)
    213  1.5.2.2  matt 			err(EXIT_FAILURE, "prop_array_iterator devblock");
    214  1.5.2.2  matt 
    215  1.5.2.2  matt 		/*
    216  1.5.2.2  matt 		 * Get the correct sensor's dictionary from kernel's
    217  1.5.2.2  matt 		 * dictionary.
    218  1.5.2.2  matt 		 */
    219  1.5.2.2  matt 		while ((sdict = prop_object_iterator_next(iter)) != NULL) {
    220  1.5.2.2  matt 			obj = prop_dictionary_get(sdict, "index");
    221  1.5.2.2  matt 			if (prop_string_equals(lindex, obj)) {
    222  1.5.2.2  matt 				sensor_found = true;
    223  1.5.2.2  matt 				break;
    224  1.5.2.2  matt 			}
    225  1.5.2.2  matt 		}
    226  1.5.2.2  matt 
    227  1.5.2.2  matt 		if (!sensor_found) {
    228  1.5.2.2  matt 			prop_object_iterator_release(iter);
    229  1.5.2.2  matt 			config_errmsg(SENSOR_ERR, sensor, key);
    230  1.5.2.2  matt 		}
    231  1.5.2.2  matt 
    232  1.5.2.2  matt 		config_devblock_check_sensorprops(sdict, sb->dict, sensor);
    233  1.5.2.2  matt 		prop_object_iterator_release(iter);
    234  1.5.2.2  matt 	}
    235  1.5.2.2  matt 
    236  1.5.2.2  matt 	db = calloc(1, sizeof(*db));
    237  1.5.2.2  matt 	if (!db)
    238  1.5.2.2  matt 		err(EXIT_FAILURE, "calloc db");
    239  1.5.2.2  matt 
    240  1.5.2.2  matt 	db->array = prop_array_create();
    241  1.5.2.2  matt 	if (!db->array)
    242  1.5.2.2  matt 		err(EXIT_FAILURE, "prop_array_create devblock");
    243  1.5.2.2  matt 
    244  1.5.2.2  matt 	/*
    245  1.5.2.2  matt 	 * Add all dictionaries into the array.
    246  1.5.2.2  matt 	 */
    247  1.5.2.2  matt 	SLIST_FOREACH(sb, &sensor_block_list, sb_head)
    248  1.5.2.2  matt 		if (!prop_array_add(db->array, sb->dict))
    249  1.5.2.2  matt 			err(EXIT_FAILURE, "prop_array_add");
    250  1.5.2.2  matt 
    251  1.5.2.2  matt 	/*
    252  1.5.2.2  matt 	 * Add this device block into our list.
    253  1.5.2.2  matt 	 */
    254  1.5.2.2  matt 	db->dev_key = strdup(key);
    255  1.5.2.2  matt 	SLIST_INSERT_HEAD(&device_block_list, db, db_head);
    256  1.5.2.2  matt 
    257  1.5.2.2  matt 	/*
    258  1.5.2.2  matt 	 * Remove all items in the list, but just decrement
    259  1.5.2.2  matt 	 * the refcnt in the dictionaries... they are in use.
    260  1.5.2.2  matt 	 */
    261  1.5.2.2  matt 	while (!SLIST_EMPTY(&sensor_block_list)) {
    262  1.5.2.2  matt 		sb = SLIST_FIRST(&sensor_block_list);
    263  1.5.2.2  matt 		SLIST_REMOVE_HEAD(&sensor_block_list, sb_head);
    264  1.5.2.2  matt 		prop_object_release(sb->dict);
    265  1.5.2.2  matt 		free(sb);
    266  1.5.2.2  matt 	}
    267  1.5.2.2  matt 
    268  1.5.2.2  matt 	/*
    269  1.5.2.2  matt 	 * Now the properties on the array has been parsed,
    270  1.5.2.2  matt 	 * add it into the global dict.
    271  1.5.2.2  matt 	 */
    272  1.5.2.2  matt 	if (!cfdict) {
    273  1.5.2.2  matt 		cfdict = prop_dictionary_create();
    274  1.5.2.2  matt 		if (!cfdict)
    275  1.5.2.2  matt 			err(EXIT_FAILURE, "prop_dictionary_create cfdict");
    276  1.5.2.2  matt 	}
    277  1.5.2.2  matt 
    278  1.5.2.2  matt 	if (!prop_dictionary_set(cfdict, key, db->array))
    279  1.5.2.2  matt 		err(EXIT_FAILURE, "prop_dictionary_set db->array");
    280  1.5.2.2  matt 
    281  1.5.2.2  matt }
    282  1.5.2.2  matt 
    283  1.5.2.2  matt /*
    284  1.5.2.2  matt  * Returns the dictionary that has 'sensor_key' in the 'dvname'
    285  1.5.2.2  matt  * array.
    286  1.5.2.2  matt  */
    287  1.5.2.2  matt prop_dictionary_t
    288  1.5.2.2  matt config_devblock_getdict(const char *dvname, const char *sensor_key)
    289  1.5.2.2  matt {
    290  1.5.2.2  matt 	struct device_block *db;
    291  1.5.2.2  matt 	prop_object_iterator_t iter;
    292  1.5.2.2  matt 	prop_object_t obj, obj2;
    293  1.5.2.2  matt 
    294  1.5.2.2  matt 	if (!dvname || !sensor_key)
    295  1.5.2.2  matt 		return NULL;
    296  1.5.2.2  matt 
    297  1.5.2.2  matt 	SLIST_FOREACH(db, &device_block_list, db_head)
    298  1.5.2.2  matt 		if (strcmp(db->dev_key, dvname) == 0)
    299  1.5.2.2  matt 			break;
    300  1.5.2.2  matt 
    301  1.5.2.2  matt 	if (!db)
    302  1.5.2.2  matt 		return NULL;
    303  1.5.2.2  matt 
    304  1.5.2.2  matt 	iter = prop_array_iterator(db->array);
    305  1.5.2.2  matt 	if (!iter)
    306  1.5.2.2  matt 		return NULL;
    307  1.5.2.2  matt 
    308  1.5.2.2  matt 	while ((obj = prop_object_iterator_next(iter)) != NULL) {
    309  1.5.2.2  matt 		obj2 = prop_dictionary_get(obj, "index");
    310  1.5.2.2  matt 		if (prop_string_equals_cstring(obj2, sensor_key))
    311  1.5.2.2  matt 			break;
    312  1.5.2.2  matt 	}
    313  1.5.2.2  matt 
    314  1.5.2.2  matt 	prop_object_iterator_release(iter);
    315  1.5.2.2  matt 	return obj;
    316  1.5.2.2  matt }
    317  1.5.2.2  matt 
    318  1.5.2.2  matt /*
    319  1.5.2.2  matt  * Checks that all properties specified in the configuration file
    320  1.5.2.2  matt  * are valid and updates the objects with proper values.
    321  1.5.2.2  matt  */
    322  1.5.2.2  matt void
    323  1.5.2.2  matt config_devblock_check_sensorprops(prop_dictionary_t ksdict,
    324  1.5.2.2  matt 				  prop_dictionary_t csdict,
    325  1.5.2.2  matt 				  const char *sensor)
    326  1.5.2.2  matt {
    327  1.5.2.2  matt 	prop_object_t obj, obj2, obj3;
    328  1.5.2.2  matt 	char *strval, *endptr;
    329  1.5.2.2  matt 	double val;
    330  1.5.2.2  matt 
    331  1.5.2.2  matt 	/*
    332  1.5.2.2  matt 	 * rfact property set?
    333  1.5.2.2  matt 	 */
    334  1.5.2.2  matt 	obj = prop_dictionary_get(csdict, "rfact");
    335  1.5.2.2  matt 	if (obj) {
    336  1.5.2.2  matt 		obj2 = prop_dictionary_get(ksdict, "allow-rfact");
    337  1.5.2.2  matt 		if (prop_bool_true(obj2)) {
    338  1.5.2.2  matt 			strval = prop_string_cstring(obj);
    339  1.5.2.2  matt 			val = strtod(strval, &endptr);
    340  1.5.2.2  matt 			if (*endptr != '\0')
    341  1.5.2.2  matt 				config_errmsg(VALUE_ERR, "rfact", sensor);
    342  1.5.2.2  matt 
    343  1.5.2.2  matt 			if (!prop_dictionary_set_uint32(csdict, "rfact", val))
    344  1.5.2.2  matt 				err(EXIT_FAILURE, "dict_set rfact");
    345  1.5.2.2  matt 		} else
    346  1.5.2.2  matt 			config_errmsg(PROP_ERR, "rfact", sensor);
    347  1.5.2.2  matt 	}
    348  1.5.2.2  matt 
    349  1.5.2.2  matt 	/*
    350  1.5.2.2  matt 	 * critical-capacity property set?
    351  1.5.2.2  matt 	 */
    352  1.5.2.2  matt 	obj = prop_dictionary_get(csdict, "critical-capacity");
    353  1.5.2.2  matt 	if (obj) {
    354  1.5.2.2  matt 		obj2 = prop_dictionary_get(ksdict, "want-percentage");
    355  1.5.2.2  matt 		obj3 = prop_dictionary_get(ksdict, "monitoring-supported");
    356  1.5.2.2  matt 		if (prop_bool_true(obj2) && prop_bool_true(obj3)) {
    357  1.5.2.2  matt 			strval = prop_string_cstring(obj);
    358  1.5.2.2  matt 			val = strtod(strval, &endptr);
    359  1.5.2.2  matt 			if ((*endptr != '\0') || (val < 0 || val > 100))
    360  1.5.2.2  matt 				config_errmsg(VALUE_ERR,
    361  1.5.2.2  matt 					      "critical-capacity",
    362  1.5.2.2  matt 					      sensor);
    363  1.5.2.2  matt 			/*
    364  1.5.2.2  matt 			 * Convert the value to a valid percentage.
    365  1.5.2.2  matt 			 */
    366  1.5.2.2  matt 			obj = prop_dictionary_get(ksdict, "max-value");
    367  1.5.2.2  matt 			val = (val / 100) * prop_number_integer_value(obj);
    368  1.5.2.2  matt 
    369  1.5.2.2  matt 			if (!prop_dictionary_set_uint32(csdict,
    370  1.5.2.2  matt 						       "critical-capacity",
    371  1.5.2.2  matt 						       val))
    372  1.5.2.2  matt 				err(EXIT_FAILURE, "dict_set critcap");
    373  1.5.2.2  matt 		} else
    374  1.5.2.2  matt 			config_errmsg(PROP_ERR,
    375  1.5.2.2  matt 				      "critical-capacity", sensor);
    376  1.5.2.2  matt 	}
    377  1.5.2.2  matt 
    378  1.5.2.2  matt 	/*
    379  1.5.2.2  matt 	 * critical-max property set?
    380  1.5.2.2  matt 	 */
    381  1.5.2.2  matt 	obj = prop_dictionary_get(csdict, "critical-max");
    382  1.5.2.2  matt 	if (obj) {
    383  1.5.2.2  matt 		obj2 = prop_dictionary_get(ksdict, "monitoring-supported");
    384  1.5.2.2  matt 		if (!prop_bool_true(obj2))
    385  1.5.2.2  matt 			config_errmsg(PROP_ERR, "critical-max", sensor);
    386  1.5.2.2  matt 
    387  1.5.2.2  matt 		strval = prop_string_cstring(obj);
    388  1.5.2.2  matt 		obj = convert_val_to_pnumber(ksdict, "critical-max",
    389  1.5.2.2  matt 					     sensor, strval);
    390  1.5.2.2  matt 		if (!prop_dictionary_set(csdict, "critical-max", obj))
    391  1.5.2.2  matt 			err(EXIT_FAILURE, "prop_dict_set cmax");
    392  1.5.2.2  matt 	}
    393  1.5.2.2  matt 
    394  1.5.2.2  matt 	/*
    395  1.5.2.2  matt 	 * critical-min property set?
    396  1.5.2.2  matt 	 */
    397  1.5.2.2  matt 	obj = prop_dictionary_get(csdict, "critical-min");
    398  1.5.2.2  matt 	if (obj) {
    399  1.5.2.2  matt 		obj2 = prop_dictionary_get(ksdict, "monitoring-supported");
    400  1.5.2.2  matt 		if (!prop_bool_true(obj2))
    401  1.5.2.2  matt 			config_errmsg(PROP_ERR, "critical-min", sensor);
    402  1.5.2.2  matt 
    403  1.5.2.2  matt 		strval = prop_string_cstring(obj);
    404  1.5.2.2  matt 		obj = convert_val_to_pnumber(ksdict, "critical-min",
    405  1.5.2.2  matt 					     sensor, strval);
    406  1.5.2.2  matt 		if (!prop_dictionary_set(csdict, "critical-min", obj))
    407  1.5.2.2  matt 			err(EXIT_FAILURE, "prop_dict_set cmin");
    408  1.5.2.2  matt 	}
    409  1.5.2.2  matt }
    410  1.5.2.2  matt 
    411  1.5.2.2  matt /*
    412  1.5.2.2  matt  * Conversions for critical-max and critical-min properties.
    413  1.5.2.2  matt  */
    414  1.5.2.2  matt prop_number_t
    415  1.5.2.2  matt convert_val_to_pnumber(prop_dictionary_t kdict, const char *prop,
    416  1.5.2.2  matt 		       const char *sensor, char *value)
    417  1.5.2.2  matt {
    418  1.5.2.2  matt 	prop_object_t obj;
    419  1.5.2.2  matt 	prop_number_t num;
    420  1.5.2.2  matt 	double val, max, min;
    421  1.5.2.2  matt 	char *strval, *tmp, *endptr;
    422  1.5.2.2  matt 	bool celsius;
    423  1.5.2.2  matt 	size_t len;
    424  1.5.2.2  matt 
    425  1.5.2.2  matt 	val = max = min = 0;
    426  1.5.2.2  matt 
    427  1.5.2.2  matt 	/*
    428  1.5.2.2  matt 	 * critical-max and critical-min are not allowed in
    429  1.5.2.2  matt 	 * battery sensors.
    430  1.5.2.2  matt 	 */
    431  1.5.2.2  matt 	obj = prop_dictionary_get(kdict, "want-percentage");
    432  1.5.2.2  matt 	if (prop_bool_true(obj))
    433  1.5.2.2  matt 		config_errmsg(PROP_ERR, prop, sensor);
    434  1.5.2.2  matt 
    435  1.5.2.2  matt 	/*
    436  1.5.2.2  matt 	 * Make the conversion for sensor's type.
    437  1.5.2.2  matt 	 */
    438  1.5.2.2  matt 	obj = prop_dictionary_get(kdict, "type");
    439  1.5.2.2  matt 	if (prop_string_equals_cstring(obj, "Temperature")) {
    440  1.5.2.2  matt 		tmp = strchr(value, 'C');
    441  1.5.2.2  matt 		if (tmp)
    442  1.5.2.2  matt 			celsius = true;
    443  1.5.2.2  matt 		else {
    444  1.5.2.2  matt 			tmp = strchr(value, 'F');
    445  1.5.2.2  matt 			if (!tmp)
    446  1.5.2.2  matt 				config_errmsg(VALUE_ERR, prop, sensor);
    447  1.5.2.2  matt 
    448  1.5.2.2  matt 			celsius = false;
    449  1.5.2.2  matt 		}
    450  1.5.2.2  matt 
    451  1.5.2.2  matt 		len = strlen(value);
    452  1.5.2.2  matt 		strval = calloc(len, sizeof(*value));
    453  1.5.2.2  matt 		if (!strval)
    454  1.5.2.2  matt 			err(EXIT_FAILURE, "calloc");
    455  1.5.2.2  matt 
    456  1.5.2.2  matt 		(void)strlcpy(strval, value, len);
    457  1.5.2.2  matt 		val = strtod(strval, &endptr);
    458  1.5.2.2  matt 		if (*endptr != '\0')
    459  1.5.2.2  matt 			config_errmsg(VALUE_ERR, prop, sensor);
    460  1.5.2.2  matt 
    461  1.5.2.2  matt 		/* convert to fahrenheit */
    462  1.5.2.2  matt 		if (!celsius)
    463  1.5.2.2  matt 			val = (val - 32.0) * (5.0 / 9.0);
    464  1.5.2.2  matt 
    465  1.5.2.2  matt 		/* convert to microKelvin */
    466  1.5.2.2  matt 		val = val * 1000000 + 273150000;
    467  1.5.2.2  matt 		num = prop_number_create_unsigned_integer(val);
    468  1.5.2.2  matt 
    469  1.5.2.2  matt 	} else if (prop_string_equals_cstring(obj, "Fan")) {
    470  1.5.2.2  matt 		/* no conversion */
    471  1.5.2.2  matt 		val = strtod(value, &endptr);
    472  1.5.2.2  matt 		if (*endptr != '\0')
    473  1.5.2.2  matt 			config_errmsg(VALUE_ERR, prop, sensor);
    474  1.5.2.2  matt 
    475  1.5.2.2  matt 		num = prop_number_create_unsigned_integer(val);
    476  1.5.2.2  matt 
    477  1.5.2.2  matt 	} else {
    478  1.5.2.2  matt 		obj = prop_dictionary_get(kdict, "max-value");
    479  1.5.2.2  matt 		if (obj)
    480  1.5.2.2  matt 			max = prop_number_integer_value(obj);
    481  1.5.2.2  matt 
    482  1.5.2.2  matt 		obj = prop_dictionary_get(kdict, "min-value");
    483  1.5.2.2  matt 		if (obj)
    484  1.5.2.2  matt 			min = prop_number_integer_value(obj);
    485  1.5.2.2  matt 
    486  1.5.2.2  matt 		val = strtod(value, &endptr);
    487  1.5.2.2  matt 		if (*endptr != '\0')
    488  1.5.2.2  matt 			config_errmsg(VALUE_ERR, prop, sensor);
    489  1.5.2.2  matt 
    490  1.5.2.2  matt 		/* convert to m[V,W,Ohms] again */
    491  1.5.2.2  matt 		val *= 1000000.0;
    492  1.5.2.2  matt 
    493  1.5.2.2  matt 		/*
    494  1.5.2.2  matt 		 * trying to set a value higher than the max
    495  1.5.2.2  matt 		 * assigned?
    496  1.5.2.2  matt 		 */
    497  1.5.2.2  matt 		if (max && val > max)
    498  1.5.2.2  matt 			config_errmsg(VALUE_ERR, prop, sensor);
    499  1.5.2.2  matt 
    500  1.5.2.2  matt 		/*
    501  1.5.2.2  matt 		 * trying to set a value lower than the min
    502  1.5.2.2  matt 		 * assigned?
    503  1.5.2.2  matt 		 */
    504  1.5.2.2  matt 		if (min && val < min)
    505  1.5.2.2  matt 			config_errmsg(VALUE_ERR, prop, sensor);
    506  1.5.2.2  matt 
    507  1.5.2.2  matt 		num = prop_number_create_integer(val);
    508  1.5.2.2  matt 	}
    509  1.5.2.2  matt 
    510  1.5.2.2  matt 	return num;
    511  1.5.2.2  matt }
    512