Home | History | Annotate | Line # | Download | only in envstat
config.c revision 1.5.2.4
      1  1.5.2.4  matt /* 	config.c,v 1.5.2.3 2008/01/09 02:01:58 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.4  matt __RCSID("config.c,v 1.5.2.3 2008/01/09 02:01:58 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.3  matt static prop_dictionary_t cfdict, sensordict, refreshdict;
     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.3  matt 	(void)printf("envstat: ");
     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.3  matt 	(void)printf("envstat: 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.3  matt  * Adds a property into a temporary dictionary.
     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.4  matt 			err(EXIT_FAILURE, "sensordict");
    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.3  matt  * Marks sensor's dictionary to say that it's the last property
    115  1.5.2.3  matt  * and the dictionary should be added into the singly linked list.
    116  1.5.2.2  matt  */
    117  1.5.2.2  matt void
    118  1.5.2.3  matt config_dict_mark(void)
    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 	sb = calloc(1, sizeof(*sb));
    123  1.5.2.2  matt 	if (!sb)
    124  1.5.2.2  matt 		err(EXIT_FAILURE, "!sb");
    125  1.5.2.2  matt 
    126  1.5.2.2  matt 	sb->dict = prop_dictionary_create();
    127  1.5.2.2  matt 	if (!sb->dict)
    128  1.5.2.2  matt 		err(EXIT_FAILURE, "!sb->dict");
    129  1.5.2.2  matt 
    130  1.5.2.2  matt 	sb->dict = prop_dictionary_copy(sensordict);
    131  1.5.2.2  matt 	SLIST_INSERT_HEAD(&sensor_block_list, sb, sb_head);
    132  1.5.2.2  matt 	config_dict_destroy(sensordict);
    133  1.5.2.2  matt }
    134  1.5.2.2  matt 
    135  1.5.2.2  matt /*
    136  1.5.2.2  matt  * Only used for debugging purposses.
    137  1.5.2.2  matt  */
    138  1.5.2.2  matt void
    139  1.5.2.2  matt config_dict_dump(prop_dictionary_t d)
    140  1.5.2.2  matt {
    141  1.5.2.2  matt 	char *buf;
    142  1.5.2.2  matt 
    143  1.5.2.2  matt 	buf = prop_dictionary_externalize(d);
    144  1.5.2.2  matt 	(void)printf("%s", buf);
    145  1.5.2.2  matt 	free(buf);
    146  1.5.2.2  matt }
    147  1.5.2.2  matt 
    148  1.5.2.2  matt /*
    149  1.5.2.2  matt  * Returns the global dictionary.
    150  1.5.2.2  matt  */
    151  1.5.2.2  matt prop_dictionary_t
    152  1.5.2.2  matt config_dict_parsed(void)
    153  1.5.2.2  matt {
    154  1.5.2.2  matt 	return cfdict;
    155  1.5.2.2  matt }
    156  1.5.2.2  matt 
    157  1.5.2.2  matt /*
    158  1.5.2.3  matt  * To add device properties into the global array, for now only the
    159  1.5.2.3  matt  * 'refresh-timeout' property is accepted.
    160  1.5.2.3  matt  */
    161  1.5.2.3  matt void
    162  1.5.2.3  matt config_dict_adddev_prop(const char *key, const char *value, int line)
    163  1.5.2.3  matt {
    164  1.5.2.3  matt 	prop_dictionary_t d = NULL;
    165  1.5.2.3  matt 	uint64_t timo;
    166  1.5.2.3  matt 	size_t len;
    167  1.5.2.3  matt 	char *endptr, *tmp, *strval;
    168  1.5.2.3  matt 	bool minutes, hours;
    169  1.5.2.3  matt 
    170  1.5.2.3  matt 	minutes = hours = false;
    171  1.5.2.3  matt 
    172  1.5.2.3  matt 	/*
    173  1.5.2.3  matt 	 * Check what was specified: seconds, minutes or hours.
    174  1.5.2.3  matt 	 */
    175  1.5.2.3  matt 	if ((tmp = strchr(value, 's'))) {
    176  1.5.2.3  matt 		/*
    177  1.5.2.3  matt 		 * do nothing, by default the value will be sent as seconds.
    178  1.5.2.3  matt 		 */
    179  1.5.2.3  matt 	} else if ((tmp = strchr(value, 'm'))) {
    180  1.5.2.3  matt 		minutes = true;
    181  1.5.2.3  matt 	} else if ((tmp = strchr(value, 'h'))) {
    182  1.5.2.3  matt 		hours = true;
    183  1.5.2.3  matt 	} else
    184  1.5.2.3  matt 		goto bad;
    185  1.5.2.3  matt 
    186  1.5.2.3  matt 	len = strlen(value);
    187  1.5.2.3  matt 	strval = calloc(len, sizeof(*value));
    188  1.5.2.3  matt 	if (!strval)
    189  1.5.2.3  matt 		err(EXIT_FAILURE, "calloc");
    190  1.5.2.3  matt 
    191  1.5.2.3  matt 	(void)strlcpy(strval, value, len);
    192  1.5.2.3  matt 
    193  1.5.2.3  matt 	timo = strtoul(strval, &endptr, 10);
    194  1.5.2.3  matt 	if (*endptr != '\0') {
    195  1.5.2.3  matt 		free(strval);
    196  1.5.2.3  matt 		goto bad;
    197  1.5.2.3  matt 	}
    198  1.5.2.3  matt 
    199  1.5.2.3  matt 	free(strval);
    200  1.5.2.3  matt 
    201  1.5.2.4  matt 	refreshdict = prop_dictionary_create();
    202  1.5.2.4  matt 	if (!refreshdict)
    203  1.5.2.4  matt 		err(EXIT_FAILURE, "prop_dict_create refresh");
    204  1.5.2.3  matt 
    205  1.5.2.3  matt 	d = prop_dictionary_create();
    206  1.5.2.3  matt 	if (!d)
    207  1.5.2.3  matt 		err(EXIT_FAILURE, "prop_dict_create refresh 1");
    208  1.5.2.3  matt 
    209  1.5.2.3  matt 	if (minutes)
    210  1.5.2.3  matt 		timo *= 60;
    211  1.5.2.3  matt 	else if (hours) {
    212  1.5.2.3  matt 		/*
    213  1.5.2.3  matt 		 * Make sure the value is not too high...
    214  1.5.2.3  matt 		 */
    215  1.5.2.3  matt 		if (timo > 999)
    216  1.5.2.3  matt 			goto bad;
    217  1.5.2.3  matt 		timo *= 60 * 60;
    218  1.5.2.3  matt 	} else {
    219  1.5.2.3  matt 		/*
    220  1.5.2.3  matt 		 * 1 second is the lowest value allowed.
    221  1.5.2.3  matt 		 */
    222  1.5.2.3  matt 		if (timo < 1)
    223  1.5.2.3  matt 			goto bad;
    224  1.5.2.3  matt 	}
    225  1.5.2.3  matt 
    226  1.5.2.3  matt 	if (!prop_dictionary_set_uint64(d, key, timo))
    227  1.5.2.3  matt 		err(EXIT_FAILURE, "%s", key);
    228  1.5.2.3  matt 
    229  1.5.2.3  matt 	if (!prop_dictionary_set(refreshdict, "device-properties", d))
    230  1.5.2.3  matt 		err(EXIT_FAILURE, "device-properties %s", key);
    231  1.5.2.3  matt 
    232  1.5.2.3  matt 	prop_object_release(d);
    233  1.5.2.3  matt 	return;
    234  1.5.2.3  matt 
    235  1.5.2.3  matt bad:
    236  1.5.2.3  matt 	(void)printf("envstat: invalid value for the '%s' "
    237  1.5.2.3  matt 	    "property at line %d\n", key, line);
    238  1.5.2.3  matt 	(void)printf("envstat: please fix the configuration file!\n");
    239  1.5.2.3  matt 	if (d)
    240  1.5.2.3  matt 		prop_object_release(d);
    241  1.5.2.3  matt 
    242  1.5.2.3  matt 	exit(EXIT_FAILURE);
    243  1.5.2.3  matt }
    244  1.5.2.3  matt 
    245  1.5.2.3  matt /*
    246  1.5.2.2  matt  * Destroys all objects from a dictionary.
    247  1.5.2.2  matt  */
    248  1.5.2.2  matt void
    249  1.5.2.2  matt config_dict_destroy(prop_dictionary_t d)
    250  1.5.2.2  matt {
    251  1.5.2.2  matt 	prop_object_iterator_t iter;
    252  1.5.2.2  matt 	prop_object_t obj;
    253  1.5.2.2  matt 
    254  1.5.2.2  matt 	iter = prop_dictionary_iterator(d);
    255  1.5.2.2  matt 	if (!iter)
    256  1.5.2.2  matt 		err(EXIT_FAILURE, "!iter");
    257  1.5.2.2  matt 
    258  1.5.2.2  matt 	 while ((obj = prop_object_iterator_next(iter)) != NULL) {
    259  1.5.2.2  matt 		 prop_dictionary_remove(d,
    260  1.5.2.2  matt 		     prop_dictionary_keysym_cstring_nocopy(obj));
    261  1.5.2.2  matt 		 prop_object_iterator_reset(iter);
    262  1.5.2.2  matt 	 }
    263  1.5.2.2  matt 
    264  1.5.2.2  matt 	 prop_object_iterator_release(iter);
    265  1.5.2.2  matt }
    266  1.5.2.2  matt 
    267  1.5.2.2  matt /*
    268  1.5.2.2  matt  * Parses all properties on the device and adds the device
    269  1.5.2.2  matt  * into the singly linked list for devices and the global dictionary.
    270  1.5.2.2  matt  */
    271  1.5.2.2  matt void
    272  1.5.2.2  matt config_devblock_add(const char *key, prop_dictionary_t kdict)
    273  1.5.2.2  matt {
    274  1.5.2.2  matt 	struct device_block *db;
    275  1.5.2.2  matt 	struct sensor_block *sb;
    276  1.5.2.2  matt 	prop_array_t array;
    277  1.5.2.2  matt 	prop_object_iterator_t iter;
    278  1.5.2.2  matt 	prop_dictionary_t sdict;
    279  1.5.2.2  matt 	prop_object_t obj;
    280  1.5.2.2  matt 	prop_string_t lindex;
    281  1.5.2.2  matt 	const char *sensor;
    282  1.5.2.2  matt 	bool sensor_found = false;
    283  1.5.2.2  matt 
    284  1.5.2.2  matt 	if (!key)
    285  1.5.2.2  matt 		err(EXIT_FAILURE, "devblock !key");
    286  1.5.2.2  matt 
    287  1.5.2.2  matt 	array = prop_dictionary_get(kdict, key);
    288  1.5.2.2  matt 	if (!array)
    289  1.5.2.2  matt 		config_errmsg(DEV_ERR, key, NULL);
    290  1.5.2.2  matt 
    291  1.5.2.2  matt 	SLIST_FOREACH(sb, &sensor_block_list, sb_head) {
    292  1.5.2.2  matt 		/* get the index object value from configuration */
    293  1.5.2.2  matt 		lindex = prop_dictionary_get(sb->dict, "index");
    294  1.5.2.2  matt 		sensor = prop_string_cstring_nocopy(lindex);
    295  1.5.2.2  matt 
    296  1.5.2.2  matt 		iter = prop_array_iterator(array);
    297  1.5.2.2  matt 		if (!iter)
    298  1.5.2.2  matt 			err(EXIT_FAILURE, "prop_array_iterator devblock");
    299  1.5.2.2  matt 
    300  1.5.2.2  matt 		/*
    301  1.5.2.2  matt 		 * Get the correct sensor's dictionary from kernel's
    302  1.5.2.2  matt 		 * dictionary.
    303  1.5.2.2  matt 		 */
    304  1.5.2.2  matt 		while ((sdict = prop_object_iterator_next(iter)) != NULL) {
    305  1.5.2.2  matt 			obj = prop_dictionary_get(sdict, "index");
    306  1.5.2.2  matt 			if (prop_string_equals(lindex, obj)) {
    307  1.5.2.2  matt 				sensor_found = true;
    308  1.5.2.2  matt 				break;
    309  1.5.2.2  matt 			}
    310  1.5.2.2  matt 		}
    311  1.5.2.2  matt 
    312  1.5.2.2  matt 		if (!sensor_found) {
    313  1.5.2.2  matt 			prop_object_iterator_release(iter);
    314  1.5.2.2  matt 			config_errmsg(SENSOR_ERR, sensor, key);
    315  1.5.2.2  matt 		}
    316  1.5.2.2  matt 
    317  1.5.2.2  matt 		config_devblock_check_sensorprops(sdict, sb->dict, sensor);
    318  1.5.2.2  matt 		prop_object_iterator_release(iter);
    319  1.5.2.2  matt 	}
    320  1.5.2.2  matt 
    321  1.5.2.2  matt 	db = calloc(1, sizeof(*db));
    322  1.5.2.2  matt 	if (!db)
    323  1.5.2.2  matt 		err(EXIT_FAILURE, "calloc db");
    324  1.5.2.2  matt 
    325  1.5.2.2  matt 	db->array = prop_array_create();
    326  1.5.2.2  matt 	if (!db->array)
    327  1.5.2.2  matt 		err(EXIT_FAILURE, "prop_array_create devblock");
    328  1.5.2.2  matt 
    329  1.5.2.2  matt 	/*
    330  1.5.2.2  matt 	 * Add all dictionaries into the array.
    331  1.5.2.2  matt 	 */
    332  1.5.2.2  matt 	SLIST_FOREACH(sb, &sensor_block_list, sb_head)
    333  1.5.2.2  matt 		if (!prop_array_add(db->array, sb->dict))
    334  1.5.2.2  matt 			err(EXIT_FAILURE, "prop_array_add");
    335  1.5.2.2  matt 
    336  1.5.2.2  matt 	/*
    337  1.5.2.3  matt 	 * Add the device-properties dictionary into the array.
    338  1.5.2.3  matt 	 */
    339  1.5.2.3  matt 	if (refreshdict) {
    340  1.5.2.3  matt 		if (!prop_array_add(db->array, refreshdict))
    341  1.5.2.3  matt 			err(EXIT_FAILURE, "prop_array_add refreshdict");
    342  1.5.2.3  matt 		prop_object_release(refreshdict);
    343  1.5.2.3  matt 	}
    344  1.5.2.3  matt 
    345  1.5.2.3  matt 	/*
    346  1.5.2.2  matt 	 * Add this device block into our list.
    347  1.5.2.2  matt 	 */
    348  1.5.2.2  matt 	db->dev_key = strdup(key);
    349  1.5.2.2  matt 	SLIST_INSERT_HEAD(&device_block_list, db, db_head);
    350  1.5.2.2  matt 
    351  1.5.2.2  matt 	/*
    352  1.5.2.2  matt 	 * Remove all items in the list, but just decrement
    353  1.5.2.2  matt 	 * the refcnt in the dictionaries... they are in use.
    354  1.5.2.2  matt 	 */
    355  1.5.2.2  matt 	while (!SLIST_EMPTY(&sensor_block_list)) {
    356  1.5.2.2  matt 		sb = SLIST_FIRST(&sensor_block_list);
    357  1.5.2.2  matt 		SLIST_REMOVE_HEAD(&sensor_block_list, sb_head);
    358  1.5.2.2  matt 		prop_object_release(sb->dict);
    359  1.5.2.2  matt 		free(sb);
    360  1.5.2.2  matt 	}
    361  1.5.2.2  matt 
    362  1.5.2.2  matt 	/*
    363  1.5.2.2  matt 	 * Now the properties on the array has been parsed,
    364  1.5.2.2  matt 	 * add it into the global dict.
    365  1.5.2.2  matt 	 */
    366  1.5.2.2  matt 	if (!cfdict) {
    367  1.5.2.2  matt 		cfdict = prop_dictionary_create();
    368  1.5.2.2  matt 		if (!cfdict)
    369  1.5.2.2  matt 			err(EXIT_FAILURE, "prop_dictionary_create cfdict");
    370  1.5.2.2  matt 	}
    371  1.5.2.2  matt 
    372  1.5.2.2  matt 	if (!prop_dictionary_set(cfdict, key, db->array))
    373  1.5.2.2  matt 		err(EXIT_FAILURE, "prop_dictionary_set db->array");
    374  1.5.2.2  matt 
    375  1.5.2.4  matt 	/*
    376  1.5.2.4  matt 	 * refreshdict must be NULLed to avoid false positives in
    377  1.5.2.4  matt 	 * next matches.
    378  1.5.2.4  matt 	 */
    379  1.5.2.4  matt 	refreshdict = NULL;
    380  1.5.2.2  matt }
    381  1.5.2.2  matt 
    382  1.5.2.2  matt /*
    383  1.5.2.2  matt  * Returns the dictionary that has 'sensor_key' in the 'dvname'
    384  1.5.2.2  matt  * array.
    385  1.5.2.2  matt  */
    386  1.5.2.2  matt prop_dictionary_t
    387  1.5.2.2  matt config_devblock_getdict(const char *dvname, const char *sensor_key)
    388  1.5.2.2  matt {
    389  1.5.2.2  matt 	struct device_block *db;
    390  1.5.2.2  matt 	prop_object_iterator_t iter;
    391  1.5.2.2  matt 	prop_object_t obj, obj2;
    392  1.5.2.2  matt 
    393  1.5.2.2  matt 	if (!dvname || !sensor_key)
    394  1.5.2.2  matt 		return NULL;
    395  1.5.2.2  matt 
    396  1.5.2.2  matt 	SLIST_FOREACH(db, &device_block_list, db_head)
    397  1.5.2.2  matt 		if (strcmp(db->dev_key, dvname) == 0)
    398  1.5.2.2  matt 			break;
    399  1.5.2.2  matt 
    400  1.5.2.2  matt 	if (!db)
    401  1.5.2.2  matt 		return NULL;
    402  1.5.2.2  matt 
    403  1.5.2.2  matt 	iter = prop_array_iterator(db->array);
    404  1.5.2.2  matt 	if (!iter)
    405  1.5.2.2  matt 		return NULL;
    406  1.5.2.2  matt 
    407  1.5.2.2  matt 	while ((obj = prop_object_iterator_next(iter)) != NULL) {
    408  1.5.2.2  matt 		obj2 = prop_dictionary_get(obj, "index");
    409  1.5.2.2  matt 		if (prop_string_equals_cstring(obj2, sensor_key))
    410  1.5.2.2  matt 			break;
    411  1.5.2.2  matt 	}
    412  1.5.2.2  matt 
    413  1.5.2.2  matt 	prop_object_iterator_release(iter);
    414  1.5.2.2  matt 	return obj;
    415  1.5.2.2  matt }
    416  1.5.2.2  matt 
    417  1.5.2.2  matt /*
    418  1.5.2.2  matt  * Checks that all properties specified in the configuration file
    419  1.5.2.2  matt  * are valid and updates the objects with proper values.
    420  1.5.2.2  matt  */
    421  1.5.2.2  matt void
    422  1.5.2.2  matt config_devblock_check_sensorprops(prop_dictionary_t ksdict,
    423  1.5.2.2  matt 				  prop_dictionary_t csdict,
    424  1.5.2.2  matt 				  const char *sensor)
    425  1.5.2.2  matt {
    426  1.5.2.2  matt 	prop_object_t obj, obj2, obj3;
    427  1.5.2.2  matt 	char *strval, *endptr;
    428  1.5.2.2  matt 	double val;
    429  1.5.2.2  matt 
    430  1.5.2.2  matt 	/*
    431  1.5.2.2  matt 	 * rfact property set?
    432  1.5.2.2  matt 	 */
    433  1.5.2.2  matt 	obj = prop_dictionary_get(csdict, "rfact");
    434  1.5.2.2  matt 	if (obj) {
    435  1.5.2.2  matt 		obj2 = prop_dictionary_get(ksdict, "allow-rfact");
    436  1.5.2.2  matt 		if (prop_bool_true(obj2)) {
    437  1.5.2.2  matt 			strval = prop_string_cstring(obj);
    438  1.5.2.2  matt 			val = strtod(strval, &endptr);
    439  1.5.2.2  matt 			if (*endptr != '\0')
    440  1.5.2.2  matt 				config_errmsg(VALUE_ERR, "rfact", sensor);
    441  1.5.2.2  matt 
    442  1.5.2.2  matt 			if (!prop_dictionary_set_uint32(csdict, "rfact", val))
    443  1.5.2.2  matt 				err(EXIT_FAILURE, "dict_set rfact");
    444  1.5.2.2  matt 		} else
    445  1.5.2.2  matt 			config_errmsg(PROP_ERR, "rfact", sensor);
    446  1.5.2.2  matt 	}
    447  1.5.2.2  matt 
    448  1.5.2.2  matt 	/*
    449  1.5.2.2  matt 	 * critical-capacity property set?
    450  1.5.2.2  matt 	 */
    451  1.5.2.2  matt 	obj = prop_dictionary_get(csdict, "critical-capacity");
    452  1.5.2.2  matt 	if (obj) {
    453  1.5.2.2  matt 		obj2 = prop_dictionary_get(ksdict, "want-percentage");
    454  1.5.2.2  matt 		obj3 = prop_dictionary_get(ksdict, "monitoring-supported");
    455  1.5.2.2  matt 		if (prop_bool_true(obj2) && prop_bool_true(obj3)) {
    456  1.5.2.2  matt 			strval = prop_string_cstring(obj);
    457  1.5.2.2  matt 			val = strtod(strval, &endptr);
    458  1.5.2.2  matt 			if ((*endptr != '\0') || (val < 0 || val > 100))
    459  1.5.2.2  matt 				config_errmsg(VALUE_ERR,
    460  1.5.2.2  matt 					      "critical-capacity",
    461  1.5.2.2  matt 					      sensor);
    462  1.5.2.2  matt 			/*
    463  1.5.2.2  matt 			 * Convert the value to a valid percentage.
    464  1.5.2.2  matt 			 */
    465  1.5.2.2  matt 			obj = prop_dictionary_get(ksdict, "max-value");
    466  1.5.2.2  matt 			val = (val / 100) * prop_number_integer_value(obj);
    467  1.5.2.2  matt 
    468  1.5.2.2  matt 			if (!prop_dictionary_set_uint32(csdict,
    469  1.5.2.2  matt 						       "critical-capacity",
    470  1.5.2.2  matt 						       val))
    471  1.5.2.2  matt 				err(EXIT_FAILURE, "dict_set critcap");
    472  1.5.2.2  matt 		} else
    473  1.5.2.3  matt 			config_errmsg(PROP_ERR, "critical-capacity", sensor);
    474  1.5.2.2  matt 	}
    475  1.5.2.2  matt 
    476  1.5.2.2  matt 	/*
    477  1.5.2.2  matt 	 * critical-max property set?
    478  1.5.2.2  matt 	 */
    479  1.5.2.2  matt 	obj = prop_dictionary_get(csdict, "critical-max");
    480  1.5.2.2  matt 	if (obj) {
    481  1.5.2.2  matt 		obj2 = prop_dictionary_get(ksdict, "monitoring-supported");
    482  1.5.2.2  matt 		if (!prop_bool_true(obj2))
    483  1.5.2.2  matt 			config_errmsg(PROP_ERR, "critical-max", sensor);
    484  1.5.2.2  matt 
    485  1.5.2.2  matt 		strval = prop_string_cstring(obj);
    486  1.5.2.2  matt 		obj = convert_val_to_pnumber(ksdict, "critical-max",
    487  1.5.2.2  matt 					     sensor, strval);
    488  1.5.2.2  matt 		if (!prop_dictionary_set(csdict, "critical-max", obj))
    489  1.5.2.2  matt 			err(EXIT_FAILURE, "prop_dict_set cmax");
    490  1.5.2.2  matt 	}
    491  1.5.2.2  matt 
    492  1.5.2.2  matt 	/*
    493  1.5.2.2  matt 	 * critical-min property set?
    494  1.5.2.2  matt 	 */
    495  1.5.2.2  matt 	obj = prop_dictionary_get(csdict, "critical-min");
    496  1.5.2.2  matt 	if (obj) {
    497  1.5.2.2  matt 		obj2 = prop_dictionary_get(ksdict, "monitoring-supported");
    498  1.5.2.2  matt 		if (!prop_bool_true(obj2))
    499  1.5.2.2  matt 			config_errmsg(PROP_ERR, "critical-min", sensor);
    500  1.5.2.2  matt 
    501  1.5.2.2  matt 		strval = prop_string_cstring(obj);
    502  1.5.2.2  matt 		obj = convert_val_to_pnumber(ksdict, "critical-min",
    503  1.5.2.2  matt 					     sensor, strval);
    504  1.5.2.2  matt 		if (!prop_dictionary_set(csdict, "critical-min", obj))
    505  1.5.2.2  matt 			err(EXIT_FAILURE, "prop_dict_set cmin");
    506  1.5.2.2  matt 	}
    507  1.5.2.2  matt }
    508  1.5.2.2  matt 
    509  1.5.2.2  matt /*
    510  1.5.2.2  matt  * Conversions for critical-max and critical-min properties.
    511  1.5.2.2  matt  */
    512  1.5.2.2  matt prop_number_t
    513  1.5.2.2  matt convert_val_to_pnumber(prop_dictionary_t kdict, const char *prop,
    514  1.5.2.2  matt 		       const char *sensor, char *value)
    515  1.5.2.2  matt {
    516  1.5.2.2  matt 	prop_object_t obj;
    517  1.5.2.2  matt 	prop_number_t num;
    518  1.5.2.2  matt 	double val, max, min;
    519  1.5.2.2  matt 	char *strval, *tmp, *endptr;
    520  1.5.2.2  matt 	bool celsius;
    521  1.5.2.2  matt 	size_t len;
    522  1.5.2.2  matt 
    523  1.5.2.2  matt 	val = max = min = 0;
    524  1.5.2.2  matt 
    525  1.5.2.2  matt 	/*
    526  1.5.2.2  matt 	 * critical-max and critical-min are not allowed in
    527  1.5.2.2  matt 	 * battery sensors.
    528  1.5.2.2  matt 	 */
    529  1.5.2.2  matt 	obj = prop_dictionary_get(kdict, "want-percentage");
    530  1.5.2.2  matt 	if (prop_bool_true(obj))
    531  1.5.2.2  matt 		config_errmsg(PROP_ERR, prop, sensor);
    532  1.5.2.2  matt 
    533  1.5.2.2  matt 	/*
    534  1.5.2.2  matt 	 * Make the conversion for sensor's type.
    535  1.5.2.2  matt 	 */
    536  1.5.2.2  matt 	obj = prop_dictionary_get(kdict, "type");
    537  1.5.2.2  matt 	if (prop_string_equals_cstring(obj, "Temperature")) {
    538  1.5.2.2  matt 		tmp = strchr(value, 'C');
    539  1.5.2.2  matt 		if (tmp)
    540  1.5.2.2  matt 			celsius = true;
    541  1.5.2.2  matt 		else {
    542  1.5.2.2  matt 			tmp = strchr(value, 'F');
    543  1.5.2.2  matt 			if (!tmp)
    544  1.5.2.2  matt 				config_errmsg(VALUE_ERR, prop, sensor);
    545  1.5.2.2  matt 
    546  1.5.2.2  matt 			celsius = false;
    547  1.5.2.2  matt 		}
    548  1.5.2.2  matt 
    549  1.5.2.2  matt 		len = strlen(value);
    550  1.5.2.2  matt 		strval = calloc(len, sizeof(*value));
    551  1.5.2.2  matt 		if (!strval)
    552  1.5.2.2  matt 			err(EXIT_FAILURE, "calloc");
    553  1.5.2.2  matt 
    554  1.5.2.2  matt 		(void)strlcpy(strval, value, len);
    555  1.5.2.2  matt 		val = strtod(strval, &endptr);
    556  1.5.2.3  matt 		if (*endptr != '\0') {
    557  1.5.2.3  matt 			free(strval);
    558  1.5.2.2  matt 			config_errmsg(VALUE_ERR, prop, sensor);
    559  1.5.2.3  matt 		}
    560  1.5.2.2  matt 
    561  1.5.2.2  matt 		/* convert to fahrenheit */
    562  1.5.2.2  matt 		if (!celsius)
    563  1.5.2.2  matt 			val = (val - 32.0) * (5.0 / 9.0);
    564  1.5.2.2  matt 
    565  1.5.2.2  matt 		/* convert to microKelvin */
    566  1.5.2.2  matt 		val = val * 1000000 + 273150000;
    567  1.5.2.2  matt 		num = prop_number_create_unsigned_integer(val);
    568  1.5.2.3  matt 		free(strval);
    569  1.5.2.2  matt 
    570  1.5.2.2  matt 	} else if (prop_string_equals_cstring(obj, "Fan")) {
    571  1.5.2.2  matt 		/* no conversion */
    572  1.5.2.2  matt 		val = strtod(value, &endptr);
    573  1.5.2.2  matt 		if (*endptr != '\0')
    574  1.5.2.2  matt 			config_errmsg(VALUE_ERR, prop, sensor);
    575  1.5.2.2  matt 
    576  1.5.2.2  matt 		num = prop_number_create_unsigned_integer(val);
    577  1.5.2.2  matt 
    578  1.5.2.2  matt 	} else {
    579  1.5.2.2  matt 		obj = prop_dictionary_get(kdict, "max-value");
    580  1.5.2.2  matt 		if (obj)
    581  1.5.2.2  matt 			max = prop_number_integer_value(obj);
    582  1.5.2.2  matt 
    583  1.5.2.2  matt 		obj = prop_dictionary_get(kdict, "min-value");
    584  1.5.2.2  matt 		if (obj)
    585  1.5.2.2  matt 			min = prop_number_integer_value(obj);
    586  1.5.2.2  matt 
    587  1.5.2.2  matt 		val = strtod(value, &endptr);
    588  1.5.2.2  matt 		if (*endptr != '\0')
    589  1.5.2.2  matt 			config_errmsg(VALUE_ERR, prop, sensor);
    590  1.5.2.2  matt 
    591  1.5.2.2  matt 		/* convert to m[V,W,Ohms] again */
    592  1.5.2.2  matt 		val *= 1000000.0;
    593  1.5.2.2  matt 
    594  1.5.2.2  matt 		/*
    595  1.5.2.2  matt 		 * trying to set a value higher than the max
    596  1.5.2.2  matt 		 * assigned?
    597  1.5.2.2  matt 		 */
    598  1.5.2.2  matt 		if (max && val > max)
    599  1.5.2.2  matt 			config_errmsg(VALUE_ERR, prop, sensor);
    600  1.5.2.2  matt 
    601  1.5.2.2  matt 		/*
    602  1.5.2.2  matt 		 * trying to set a value lower than the min
    603  1.5.2.2  matt 		 * assigned?
    604  1.5.2.2  matt 		 */
    605  1.5.2.2  matt 		if (min && val < min)
    606  1.5.2.2  matt 			config_errmsg(VALUE_ERR, prop, sensor);
    607  1.5.2.2  matt 
    608  1.5.2.2  matt 		num = prop_number_create_integer(val);
    609  1.5.2.2  matt 	}
    610  1.5.2.2  matt 
    611  1.5.2.2  matt 	return num;
    612  1.5.2.2  matt }
    613