xref: /titanic_50/usr/src/cmd/hal/hald/util.c (revision 97191cec6312a1c3a1b70c5f4a543c415c59edf7)
118c2aff7Sartem /***************************************************************************
218c2aff7Sartem  * CVSID: $Id$
318c2aff7Sartem  *
418c2aff7Sartem  * util.c - Various utilities
518c2aff7Sartem  *
618c2aff7Sartem  * Copyright (C) 2004 David Zeuthen, <david@fubar.dk>
718c2aff7Sartem  *
818c2aff7Sartem  * Licensed under the Academic Free License version 2.1
918c2aff7Sartem  *
1018c2aff7Sartem  * This program is free software; you can redistribute it and/or modify
1118c2aff7Sartem  * it under the terms of the GNU General Public License as published by
1218c2aff7Sartem  * the Free Software Foundation; either version 2 of the License, or
1318c2aff7Sartem  * (at your option) any later version.
1418c2aff7Sartem  *
1518c2aff7Sartem  * This program is distributed in the hope that it will be useful,
1618c2aff7Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1718c2aff7Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1818c2aff7Sartem  * GNU General Public License for more details.
1918c2aff7Sartem  *
2018c2aff7Sartem  * You should have received a copy of the GNU General Public License
2118c2aff7Sartem  * along with this program; if not, write to the Free Software
2218c2aff7Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2318c2aff7Sartem  *
2418c2aff7Sartem  **************************************************************************/
2518c2aff7Sartem 
2618c2aff7Sartem #ifdef HAVE_CONFIG_H
2718c2aff7Sartem #  include <config.h>
2818c2aff7Sartem #endif
2918c2aff7Sartem 
3018c2aff7Sartem #include <stdio.h>
3118c2aff7Sartem #include <stdarg.h>
3218c2aff7Sartem #include <string.h>
3318c2aff7Sartem #include <errno.h>
3418c2aff7Sartem #include <time.h>
3518c2aff7Sartem #include <ctype.h>
3618c2aff7Sartem #include <stdint.h>
3718c2aff7Sartem #include <sys/stat.h>
3818c2aff7Sartem #include <unistd.h>
3918c2aff7Sartem #include <fcntl.h>
4018c2aff7Sartem #include <signal.h>
4118c2aff7Sartem #include <sys/wait.h>
4218c2aff7Sartem #include <sys/file.h>
4318c2aff7Sartem 
4418c2aff7Sartem #include <glib.h>
4518c2aff7Sartem #include <dbus/dbus.h>
4618c2aff7Sartem #include <dbus/dbus-glib.h>
4718c2aff7Sartem 
4818c2aff7Sartem #include "osspec.h"
4918c2aff7Sartem #include "logger.h"
5018c2aff7Sartem #include "hald.h"
5118c2aff7Sartem #include "hald_runner.h"
5218c2aff7Sartem #include "hald_dbus.h"
5318c2aff7Sartem #include "device_info.h"
5418c2aff7Sartem 
5518c2aff7Sartem #include "util.h"
5618c2aff7Sartem 
57*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China /** Determine whether the given character is valid as the first character
58*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China  *  in a name.
59*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China  */
60*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China #define VALID_INITIAL_NAME_CHARACTER(c)          \
61*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	(((c) >= 'A' && (c) <= 'Z') ||           \
62*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	((c) >= 'a' && (c) <= 'z') ||            \
63*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	((c) == '_'))
64*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 
65*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China /** Determine whether the given character is valid as a second or later
66*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China  *  character in a name.
67*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China  */
68*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China #define VALID_NAME_CHARACTER(c)                  \
69*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	(((c) >= '0' && (c) <= '9') ||           \
70*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	((c) >= 'A' && (c) <= 'Z') ||            \
71*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	((c) >= 'a' && (c) <= 'z') ||            \
72*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	((c) == '_'))
73*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 
7418c2aff7Sartem gboolean
hal_util_remove_trailing_slash(gchar * path)7518c2aff7Sartem hal_util_remove_trailing_slash (gchar *path)
7618c2aff7Sartem {
7718c2aff7Sartem 	gchar *c = NULL;
7818c2aff7Sartem 
7918c2aff7Sartem 	if (path == NULL) {
8018c2aff7Sartem 		return FALSE;
8118c2aff7Sartem 	}
8218c2aff7Sartem 
8318c2aff7Sartem 	c = strrchr (path, '/');
8418c2aff7Sartem 	if (c == NULL) {
8518c2aff7Sartem 		HAL_WARNING (("Invalid path %s", path));
8618c2aff7Sartem 		return 1;
8718c2aff7Sartem 	}
8818c2aff7Sartem 	if (*(c+1) == '\0')
8918c2aff7Sartem 		*c = '\0';
9018c2aff7Sartem 
9118c2aff7Sartem 	return TRUE;
9218c2aff7Sartem }
9318c2aff7Sartem 
9418c2aff7Sartem /** Given a path, /foo/bar/bat/foobar, return the last element, e.g.
9518c2aff7Sartem  *  foobar.
9618c2aff7Sartem  *
9718c2aff7Sartem  *  @param  path                Path
9818c2aff7Sartem  *  @return                     Pointer into given string
9918c2aff7Sartem  */
10018c2aff7Sartem const gchar *
hal_util_get_last_element(const gchar * s)10118c2aff7Sartem hal_util_get_last_element (const gchar *s)
10218c2aff7Sartem {
10318c2aff7Sartem 	int len;
10418c2aff7Sartem 	const gchar *p;
10518c2aff7Sartem 
10618c2aff7Sartem 	len = strlen (s);
10718c2aff7Sartem 	for (p = s + len - 1; p > s; --p) {
10818c2aff7Sartem 		if ((*p) == '/')
10918c2aff7Sartem 			return p + 1;
11018c2aff7Sartem 	}
11118c2aff7Sartem 
11218c2aff7Sartem 	return s;
11318c2aff7Sartem }
11418c2aff7Sartem 
11518c2aff7Sartem /** Given a path, this functions finds the path representing the
11618c2aff7Sartem  *  parent directory by truncation.
11718c2aff7Sartem  *
11818c2aff7Sartem  *  @param  path                Path
11918c2aff7Sartem  *  @return                     Path for parent or NULL. Must be freed by caller
12018c2aff7Sartem  */
12118c2aff7Sartem gchar *
hal_util_get_parent_path(const gchar * path)12218c2aff7Sartem hal_util_get_parent_path (const gchar *path)
12318c2aff7Sartem {
12418c2aff7Sartem 	guint i;
12518c2aff7Sartem 	guint len;
12618c2aff7Sartem 	gchar *parent_path;
12718c2aff7Sartem 
12818c2aff7Sartem 	/* Find parent device by truncating our own path */
12918c2aff7Sartem 	parent_path = g_strndup (path, HAL_PATH_MAX);
13018c2aff7Sartem 	len = strlen (parent_path);
13118c2aff7Sartem 	for (i = len - 1; parent_path[i] != '/'; --i) {
13218c2aff7Sartem 		parent_path[i] = '\0';
13318c2aff7Sartem 	}
13418c2aff7Sartem 	parent_path[i] = '\0';
13518c2aff7Sartem 
13618c2aff7Sartem 	return parent_path;
13718c2aff7Sartem }
13818c2aff7Sartem 
13918c2aff7Sartem gchar *
hal_util_get_normalized_path(const gchar * path1,const gchar * path2)14018c2aff7Sartem hal_util_get_normalized_path (const gchar *path1, const gchar *path2)
14118c2aff7Sartem {
14218c2aff7Sartem 	int len1;
14318c2aff7Sartem 	int len2;
14418c2aff7Sartem 	const gchar *p1;
14518c2aff7Sartem 	const gchar *p2;
14618c2aff7Sartem 	gchar buf[HAL_PATH_MAX];
14718c2aff7Sartem 
14818c2aff7Sartem 	len1 = strlen (path1);
14918c2aff7Sartem 	len2 = strlen (path2);
15018c2aff7Sartem 
15118c2aff7Sartem 	p1 = path1 + len1;
15218c2aff7Sartem 
15318c2aff7Sartem 	p2 = path2;
15418c2aff7Sartem 	while (p2 < path2 + len2 && strncmp (p2, "../", 3) == 0) {
15518c2aff7Sartem 		p2 += 3;
15618c2aff7Sartem 
15718c2aff7Sartem 		while (p1 >= path1 && *(--p1)!='/')
15818c2aff7Sartem 			;
15918c2aff7Sartem 	}
16018c2aff7Sartem 
16118c2aff7Sartem 	if ((p1-path1) < 0) {
16218c2aff7Sartem 		HAL_ERROR (("Could not normalize '%s' and '%s', return 'NULL'", path1, path2));
16318c2aff7Sartem 		return NULL;
16418c2aff7Sartem 	}
16518c2aff7Sartem 
16618c2aff7Sartem 	strncpy (buf, path1, (p1-path1));
16718c2aff7Sartem 	buf[p1-path1] = '\0';
16818c2aff7Sartem 
16918c2aff7Sartem 	return g_strdup_printf ("%s/%s", buf, p2);
17018c2aff7Sartem }
17118c2aff7Sartem 
17218c2aff7Sartem gboolean
hal_util_get_int_from_file(const gchar * directory,const gchar * file,gint * result,gint base)17318c2aff7Sartem hal_util_get_int_from_file (const gchar *directory, const gchar *file, gint *result, gint base)
17418c2aff7Sartem {
17518c2aff7Sartem 	FILE *f;
17618c2aff7Sartem 	char buf[64];
17718c2aff7Sartem 	gchar path[HAL_PATH_MAX];
17818c2aff7Sartem 	gboolean ret;
17918c2aff7Sartem 
18018c2aff7Sartem 	f = NULL;
18118c2aff7Sartem 	ret = FALSE;
18218c2aff7Sartem 
18318c2aff7Sartem 	g_snprintf (path, sizeof (path), "%s/%s", directory, file);
18418c2aff7Sartem 
18518c2aff7Sartem 	f = fopen (path, "rb");
18618c2aff7Sartem 	if (f == NULL) {
18718c2aff7Sartem 		HAL_ERROR (("Cannot open '%s'", path));
18818c2aff7Sartem 		goto out;
18918c2aff7Sartem 	}
19018c2aff7Sartem 
19118c2aff7Sartem 	if (fgets (buf, sizeof (buf), f) == NULL) {
19218c2aff7Sartem 		HAL_ERROR (("Cannot read from '%s'", path));
19318c2aff7Sartem 		goto out;
19418c2aff7Sartem 	}
19518c2aff7Sartem 
19618c2aff7Sartem 	/* TODO: handle error condition */
19718c2aff7Sartem 	*result = strtol (buf, NULL, base);
19818c2aff7Sartem 	ret = TRUE;
19918c2aff7Sartem 
20018c2aff7Sartem out:
20118c2aff7Sartem 	if (f != NULL)
20218c2aff7Sartem 		fclose (f);
20318c2aff7Sartem 
20418c2aff7Sartem 	return ret;
20518c2aff7Sartem }
20618c2aff7Sartem 
20718c2aff7Sartem gboolean
hal_util_set_int_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file,gint base)20818c2aff7Sartem hal_util_set_int_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base)
20918c2aff7Sartem {
21018c2aff7Sartem 	gint value;
21118c2aff7Sartem 	gboolean ret;
21218c2aff7Sartem 
21318c2aff7Sartem 	ret = FALSE;
21418c2aff7Sartem 
21518c2aff7Sartem 	if (hal_util_get_int_from_file (directory, file, &value, base))
21618c2aff7Sartem 		ret = hal_device_property_set_int (d, key, value);
21718c2aff7Sartem 
21818c2aff7Sartem 	return ret;
21918c2aff7Sartem }
22018c2aff7Sartem 
22118c2aff7Sartem 
22218c2aff7Sartem gboolean
hal_util_get_uint64_from_file(const gchar * directory,const gchar * file,guint64 * result,gint base)22318c2aff7Sartem hal_util_get_uint64_from_file (const gchar *directory, const gchar *file, guint64 *result, gint base)
22418c2aff7Sartem {
22518c2aff7Sartem 	FILE *f;
22618c2aff7Sartem 	char buf[64];
22718c2aff7Sartem 	gchar path[HAL_PATH_MAX];
22818c2aff7Sartem 	gboolean ret;
22918c2aff7Sartem 
23018c2aff7Sartem 	f = NULL;
23118c2aff7Sartem 	ret = FALSE;
23218c2aff7Sartem 
23318c2aff7Sartem 	g_snprintf (path, sizeof (path), "%s/%s", directory, file);
23418c2aff7Sartem 
23518c2aff7Sartem 	f = fopen (path, "rb");
23618c2aff7Sartem 	if (f == NULL) {
23718c2aff7Sartem 		HAL_ERROR (("Cannot open '%s'", path));
23818c2aff7Sartem 		goto out;
23918c2aff7Sartem 	}
24018c2aff7Sartem 
24118c2aff7Sartem 	if (fgets (buf, sizeof (buf), f) == NULL) {
24218c2aff7Sartem 		HAL_ERROR (("Cannot read from '%s'", path));
24318c2aff7Sartem 		goto out;
24418c2aff7Sartem 	}
24518c2aff7Sartem 
24618c2aff7Sartem 	/* TODO: handle error condition */
24718c2aff7Sartem 	*result = strtoll (buf, NULL, base);
24818c2aff7Sartem 
24918c2aff7Sartem 	ret = TRUE;
25018c2aff7Sartem 
25118c2aff7Sartem out:
25218c2aff7Sartem 	if (f != NULL)
25318c2aff7Sartem 		fclose (f);
25418c2aff7Sartem 
25518c2aff7Sartem 	return ret;
25618c2aff7Sartem }
25718c2aff7Sartem 
25818c2aff7Sartem gboolean
hal_util_set_uint64_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file,gint base)25918c2aff7Sartem hal_util_set_uint64_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base)
26018c2aff7Sartem {
26118c2aff7Sartem 	guint64 value;
26218c2aff7Sartem 	gboolean ret;
26318c2aff7Sartem 
26418c2aff7Sartem 	ret = FALSE;
26518c2aff7Sartem 
26618c2aff7Sartem 	if (hal_util_get_uint64_from_file (directory, file, &value, base))
26718c2aff7Sartem 		ret = hal_device_property_set_uint64 (d, key, value);
26818c2aff7Sartem 
26918c2aff7Sartem 	return ret;
27018c2aff7Sartem }
27118c2aff7Sartem 
27218c2aff7Sartem gboolean
hal_util_get_bcd2_from_file(const gchar * directory,const gchar * file,gint * result)27318c2aff7Sartem hal_util_get_bcd2_from_file (const gchar *directory, const gchar *file, gint *result)
27418c2aff7Sartem {
27518c2aff7Sartem 	FILE *f;
27618c2aff7Sartem 	char buf[64];
27718c2aff7Sartem 	gchar path[HAL_PATH_MAX];
27818c2aff7Sartem 	gboolean ret;
27918c2aff7Sartem 	gint digit;
28018c2aff7Sartem 	gint left, right;
28118c2aff7Sartem 	gboolean passed_white_space;
28218c2aff7Sartem 	gint num_prec;
28318c2aff7Sartem 	gsize len;
28418c2aff7Sartem 	gchar c;
28518c2aff7Sartem 	guint i;
28618c2aff7Sartem 
28718c2aff7Sartem 	f = NULL;
28818c2aff7Sartem 	ret = FALSE;
28918c2aff7Sartem 
29018c2aff7Sartem 	g_snprintf (path, sizeof (path), "%s/%s", directory, file);
29118c2aff7Sartem 
29218c2aff7Sartem 	f = fopen (path, "rb");
29318c2aff7Sartem 	if (f == NULL) {
29418c2aff7Sartem 		HAL_ERROR (("Cannot open '%s'", path));
29518c2aff7Sartem 		goto out;
29618c2aff7Sartem 	}
29718c2aff7Sartem 
29818c2aff7Sartem 	if (fgets (buf, sizeof (buf), f) == NULL) {
29918c2aff7Sartem 		HAL_ERROR (("Cannot read from '%s'", path));
30018c2aff7Sartem 		goto out;
30118c2aff7Sartem 	}
30218c2aff7Sartem 
30318c2aff7Sartem 	left = 0;
30418c2aff7Sartem 	len = strlen (buf);
30518c2aff7Sartem 	passed_white_space = FALSE;
30618c2aff7Sartem 	for (i = 0; i < len && buf[i] != '.'; i++) {
30718c2aff7Sartem 		if (g_ascii_isspace (buf[i])) {
30818c2aff7Sartem 			if (passed_white_space)
30918c2aff7Sartem 				break;
31018c2aff7Sartem 			else
31118c2aff7Sartem 				continue;
31218c2aff7Sartem 		}
31318c2aff7Sartem 		passed_white_space = TRUE;
31418c2aff7Sartem 		left *= 16;
31518c2aff7Sartem 		c = buf[i];
31618c2aff7Sartem 		digit = (int) (c - '0');
31718c2aff7Sartem 		left += digit;
31818c2aff7Sartem 	}
31918c2aff7Sartem 	i++;
32018c2aff7Sartem 	right = 0;
32118c2aff7Sartem 	num_prec = 0;
32218c2aff7Sartem 	for (; i < len; i++) {
32318c2aff7Sartem 		if (g_ascii_isspace (buf[i]))
32418c2aff7Sartem 			break;
32518c2aff7Sartem 		if (num_prec == 2)	        /* Only care about two digits
32618c2aff7Sartem 						 * of precision */
32718c2aff7Sartem 			break;
32818c2aff7Sartem 		right *= 16;
32918c2aff7Sartem 		c = buf[i];
33018c2aff7Sartem 		digit = (int) (c - '0');
33118c2aff7Sartem 		right += digit;
33218c2aff7Sartem 		num_prec++;
33318c2aff7Sartem 	}
33418c2aff7Sartem 
33518c2aff7Sartem 	for (; num_prec < 2; num_prec++)
33618c2aff7Sartem 		right *= 16;
33718c2aff7Sartem 
33818c2aff7Sartem 	*result = left * 256 + (right & 255);
33918c2aff7Sartem 	ret = TRUE;
34018c2aff7Sartem 
34118c2aff7Sartem out:
34218c2aff7Sartem 	if (f != NULL)
34318c2aff7Sartem 		fclose (f);
34418c2aff7Sartem 
34518c2aff7Sartem 	return ret;
34618c2aff7Sartem }
34718c2aff7Sartem 
34818c2aff7Sartem gboolean
hal_util_set_bcd2_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file)34918c2aff7Sartem hal_util_set_bcd2_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file)
35018c2aff7Sartem {
35118c2aff7Sartem 	gint value;
35218c2aff7Sartem 	gboolean ret;
35318c2aff7Sartem 
35418c2aff7Sartem 	ret = FALSE;
35518c2aff7Sartem 
35618c2aff7Sartem 	if (hal_util_get_bcd2_from_file (directory, file, &value))
35718c2aff7Sartem 		ret = hal_device_property_set_int (d, key, value);
35818c2aff7Sartem 
35918c2aff7Sartem 	return ret;
36018c2aff7Sartem }
36118c2aff7Sartem 
36218c2aff7Sartem gchar *
hal_util_get_string_from_file(const gchar * directory,const gchar * file)36318c2aff7Sartem hal_util_get_string_from_file (const gchar *directory, const gchar *file)
36418c2aff7Sartem {
36518c2aff7Sartem 	FILE *f;
36618c2aff7Sartem 	static gchar buf[256];
36718c2aff7Sartem 	gchar path[HAL_PATH_MAX];
36818c2aff7Sartem 	gchar *result;
36918c2aff7Sartem 	gsize len;
37018c2aff7Sartem 	gint i;
37118c2aff7Sartem 
37218c2aff7Sartem 	f = NULL;
37318c2aff7Sartem 	result = NULL;
37418c2aff7Sartem 
37518c2aff7Sartem 	g_snprintf (path, sizeof (path), "%s/%s", directory, file);
37618c2aff7Sartem 
37718c2aff7Sartem 	f = fopen (path, "rb");
37818c2aff7Sartem 	if (f == NULL) {
37918c2aff7Sartem 		HAL_ERROR (("Cannot open '%s'", path));
38018c2aff7Sartem 		goto out;
38118c2aff7Sartem 	}
38218c2aff7Sartem 
38318c2aff7Sartem 	buf[0] = '\0';
38418c2aff7Sartem 	if (fgets (buf, sizeof (buf), f) == NULL) {
38518c2aff7Sartem 		HAL_ERROR (("Cannot read from '%s'", path));
38618c2aff7Sartem 		goto out;
38718c2aff7Sartem 	}
38818c2aff7Sartem 
38918c2aff7Sartem 	len = strlen (buf);
39018c2aff7Sartem 	if (len>0)
39118c2aff7Sartem 		buf[len-1] = '\0';
39218c2aff7Sartem 
39318c2aff7Sartem 	/* Clear remaining whitespace */
39418c2aff7Sartem 	for (i = len - 2; i >= 0; --i) {
39518c2aff7Sartem 		if (!g_ascii_isspace (buf[i]))
39618c2aff7Sartem 			break;
39718c2aff7Sartem 		buf[i] = '\0';
39818c2aff7Sartem 	}
39918c2aff7Sartem 
40018c2aff7Sartem 	result = buf;
40118c2aff7Sartem 
40218c2aff7Sartem out:
40318c2aff7Sartem 	if (f != NULL)
40418c2aff7Sartem 		fclose (f);
40518c2aff7Sartem 
40618c2aff7Sartem 	return result;
40718c2aff7Sartem }
40818c2aff7Sartem 
40918c2aff7Sartem gboolean
hal_util_set_string_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file)41018c2aff7Sartem hal_util_set_string_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file)
41118c2aff7Sartem {
41218c2aff7Sartem 	gchar *buf;
41318c2aff7Sartem 	gboolean ret;
41418c2aff7Sartem 
41518c2aff7Sartem 	ret = FALSE;
41618c2aff7Sartem 
41718c2aff7Sartem 	if ((buf = hal_util_get_string_from_file (directory, file)) != NULL)
41818c2aff7Sartem 		ret = hal_device_property_set_string (d, key, buf);
41918c2aff7Sartem 
42018c2aff7Sartem 	return ret;
42118c2aff7Sartem }
42218c2aff7Sartem 
42318c2aff7Sartem void
hal_util_compute_udi(HalDeviceStore * store,gchar * dst,gsize dstsize,const gchar * format,...)42418c2aff7Sartem hal_util_compute_udi (HalDeviceStore *store, gchar *dst, gsize dstsize, const gchar *format, ...)
42518c2aff7Sartem {
42618c2aff7Sartem 	guint i;
42718c2aff7Sartem 	va_list args;
42818c2aff7Sartem 	gchar buf[256];
42918c2aff7Sartem 
43018c2aff7Sartem 	va_start (args, format);
43118c2aff7Sartem 	g_vsnprintf (buf, sizeof (buf), format, args);
43218c2aff7Sartem 	va_end (args);
43318c2aff7Sartem 
43418c2aff7Sartem 	g_strcanon (buf,
43518c2aff7Sartem 		    "/_"
43618c2aff7Sartem 		    "abcdefghijklmnopqrstuvwxyz"
43718c2aff7Sartem 		    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
43818c2aff7Sartem 		    "1234567890", '_');
43918c2aff7Sartem 
44018c2aff7Sartem 	g_strlcpy (dst, buf, dstsize);
44118c2aff7Sartem 	if (hal_device_store_find (store, dst) == NULL)
44218c2aff7Sartem 		goto out;
44318c2aff7Sartem 
44418c2aff7Sartem 	for (i = 0; ; i++) {
44518c2aff7Sartem 		g_snprintf (dst, dstsize, "%s_%d", buf, i);
44618c2aff7Sartem 		if (hal_device_store_find (store, dst) == NULL)
44718c2aff7Sartem 			goto out;
44818c2aff7Sartem 	}
44918c2aff7Sartem 
45018c2aff7Sartem out:
45118c2aff7Sartem 	;
45218c2aff7Sartem }
45318c2aff7Sartem 
45418c2aff7Sartem 
45518c2aff7Sartem gboolean
hal_util_path_ascend(gchar * path)45618c2aff7Sartem hal_util_path_ascend (gchar *path)
45718c2aff7Sartem {
45818c2aff7Sartem 	gchar *p;
45918c2aff7Sartem 
46018c2aff7Sartem 	if (path == NULL)
46118c2aff7Sartem 		return FALSE;
46218c2aff7Sartem 
46318c2aff7Sartem 	p = strrchr (path, '/');
46418c2aff7Sartem 	if (p == NULL)
46518c2aff7Sartem 		return FALSE;
46618c2aff7Sartem 
46718c2aff7Sartem 	*p = '\0';
46818c2aff7Sartem 	return TRUE;
46918c2aff7Sartem }
47018c2aff7Sartem 
47118c2aff7Sartem static gboolean _grep_can_reuse = FALSE;
47218c2aff7Sartem 
47318c2aff7Sartem void
hal_util_grep_discard_existing_data(void)47418c2aff7Sartem hal_util_grep_discard_existing_data (void)
47518c2aff7Sartem {
47618c2aff7Sartem 	_grep_can_reuse = FALSE;
47718c2aff7Sartem }
47818c2aff7Sartem 
47918c2aff7Sartem /** Given a directory and filename, open the file and search for the
48018c2aff7Sartem  *  first line that starts with the given linestart string. Returns
48118c2aff7Sartem  *  the rest of the line as a string if found.
48218c2aff7Sartem  *
48318c2aff7Sartem  *  @param  directory           Directory, e.g. "/proc/acpi/battery/BAT0"
48418c2aff7Sartem  *  @param  file                File, e.g. "info"
48518c2aff7Sartem  *  @param  linestart           Start of line, e.g. "serial number"
48618c2aff7Sartem  *  @param  reuse               Whether we should reuse the file contents
48718c2aff7Sartem  *                              if the file is the same; can be cleared
48818c2aff7Sartem  *                              with hal_util_grep_discard_existing_data()
48918c2aff7Sartem  *  @return                     NULL if not found, otherwise the remainder
49018c2aff7Sartem  *                              of the line, e.g. ":           21805" if
49118c2aff7Sartem  *                              the file /proc/acpi/battery/BAT0 contains
49218c2aff7Sartem  *                              this line "serial number:           21805"
49318c2aff7Sartem  *                              The string is only valid until the next
49418c2aff7Sartem  *                              invocation of this function.
49518c2aff7Sartem  */
49618c2aff7Sartem gchar *
hal_util_grep_file(const gchar * directory,const gchar * file,const gchar * linestart,gboolean reuse)49718c2aff7Sartem hal_util_grep_file (const gchar *directory, const gchar *file, const gchar *linestart, gboolean reuse)
49818c2aff7Sartem {
49918c2aff7Sartem 	static gchar buf[2048];
50018c2aff7Sartem 	static unsigned int bufsize;
50118c2aff7Sartem 	static gchar filename[HAL_PATH_MAX];
50218c2aff7Sartem 	static gchar oldfilename[HAL_PATH_MAX];
50318c2aff7Sartem 	gchar *result;
50418c2aff7Sartem 	gsize linestart_len;
50518c2aff7Sartem 	gchar *p;
50618c2aff7Sartem 
50718c2aff7Sartem 	result = NULL;
50818c2aff7Sartem 
50918c2aff7Sartem 	/* TODO: use reuse and _grep_can_reuse parameters to avoid loading
51018c2aff7Sartem 	 *       the file again and again
51118c2aff7Sartem 	 */
51218c2aff7Sartem 
51318c2aff7Sartem 	if (file != NULL && strlen (file) > 0)
51418c2aff7Sartem 		snprintf (filename, sizeof (filename), "%s/%s", directory, file);
51518c2aff7Sartem 	else
51618c2aff7Sartem 		strncpy (filename, directory, sizeof (filename));
51718c2aff7Sartem 
51818c2aff7Sartem 	if (_grep_can_reuse && reuse && strcmp (oldfilename, filename) == 0) {
51918c2aff7Sartem 		/* just reuse old file; e.g. bufsize, buf */
52018c2aff7Sartem 		/*HAL_INFO (("hal_util_grep_file: reusing buf for %s", filename));*/
52118c2aff7Sartem 	} else {
52218c2aff7Sartem 		FILE *f;
52318c2aff7Sartem 
52418c2aff7Sartem 		f = fopen (filename, "r");
52518c2aff7Sartem 		if (f == NULL)
52618c2aff7Sartem 			goto out;
52718c2aff7Sartem 		bufsize = fread (buf, sizeof (char), sizeof (buf) - 1, f);
52818c2aff7Sartem 		buf[bufsize] = '\0';
52918c2aff7Sartem 		fclose (f);
53018c2aff7Sartem 
53118c2aff7Sartem 		/*HAL_INFO (("hal_util_grep_file: read %s of %d bytes", filename, bufsize));*/
53218c2aff7Sartem 	}
53318c2aff7Sartem 
53418c2aff7Sartem 	/* book keeping */
53518c2aff7Sartem 	_grep_can_reuse = TRUE;
53618c2aff7Sartem 	strncpy (oldfilename, filename, sizeof(oldfilename));
53718c2aff7Sartem 
53818c2aff7Sartem 	linestart_len = strlen (linestart);
53918c2aff7Sartem 
54018c2aff7Sartem 	/* analyze buf */
54118c2aff7Sartem 	p = buf;
54218c2aff7Sartem 	do {
54318c2aff7Sartem 		unsigned int linelen;
54418c2aff7Sartem 		static char line[256];
54518c2aff7Sartem 
54618c2aff7Sartem 		for (linelen = 0; p[linelen] != '\n' && p[linelen] != '\0'; linelen++)
54718c2aff7Sartem 			;
54818c2aff7Sartem 
54918c2aff7Sartem 		if (linelen < sizeof (line)) {
55018c2aff7Sartem 
55118c2aff7Sartem 			strncpy (line, p, linelen);
55218c2aff7Sartem 			line[linelen] = '\0';
55318c2aff7Sartem 
55418c2aff7Sartem 			if (strncmp (line, linestart, linestart_len) == 0) {
55518c2aff7Sartem 				result = line + linestart_len;
55618c2aff7Sartem 				goto out;
55718c2aff7Sartem 			}
55818c2aff7Sartem 		}
55918c2aff7Sartem 
56018c2aff7Sartem 		p += linelen + 1;
56118c2aff7Sartem 
56218c2aff7Sartem 	} while (p < buf + bufsize);
56318c2aff7Sartem 
56418c2aff7Sartem out:
56518c2aff7Sartem 	return result;
56618c2aff7Sartem }
56718c2aff7Sartem 
56818c2aff7Sartem gchar *
hal_util_grep_string_elem_from_file(const gchar * directory,const gchar * file,const gchar * linestart,guint elem,gboolean reuse)56918c2aff7Sartem hal_util_grep_string_elem_from_file (const gchar *directory, const gchar *file,
57018c2aff7Sartem 				     const gchar *linestart, guint elem, gboolean reuse)
57118c2aff7Sartem {
57218c2aff7Sartem 	gchar *line;
57318c2aff7Sartem 	gchar *res;
57418c2aff7Sartem 	static gchar buf[256];
57518c2aff7Sartem 	gchar **tokens;
57618c2aff7Sartem 	guint i, j;
57718c2aff7Sartem 
57818c2aff7Sartem 	res = NULL;
57918c2aff7Sartem 	tokens = NULL;
58018c2aff7Sartem 
58118c2aff7Sartem 	if (((line = hal_util_grep_file (directory, file, linestart, reuse)) == NULL) || (strlen (line) == 0))
58218c2aff7Sartem 		goto out;
58318c2aff7Sartem 
58418c2aff7Sartem 	tokens = g_strsplit_set (line, " \t:", 0);
58518c2aff7Sartem 	for (i = 0, j = 0; tokens[i] != NULL; i++) {
58618c2aff7Sartem 		if (strlen (tokens[i]) == 0)
58718c2aff7Sartem 			continue;
58818c2aff7Sartem 		if (j == elem) {
58918c2aff7Sartem 			strncpy (buf, tokens[i], sizeof (buf));
59018c2aff7Sartem 			res = buf;
59118c2aff7Sartem 			goto out;
59218c2aff7Sartem 		}
59318c2aff7Sartem 		j++;
59418c2aff7Sartem 	}
59518c2aff7Sartem 
59618c2aff7Sartem out:
59718c2aff7Sartem 	if (tokens != NULL)
59818c2aff7Sartem 		g_strfreev (tokens);
59918c2aff7Sartem 
60018c2aff7Sartem 	return res;
60118c2aff7Sartem }
60218c2aff7Sartem 
60318c2aff7Sartem gint
hal_util_grep_int_elem_from_file(const gchar * directory,const gchar * file,const gchar * linestart,guint elem,guint base,gboolean reuse)60418c2aff7Sartem hal_util_grep_int_elem_from_file (const gchar *directory, const gchar *file,
60518c2aff7Sartem 				  const gchar *linestart, guint elem, guint base, gboolean reuse)
60618c2aff7Sartem {
60718c2aff7Sartem 	gchar *endptr;
60818c2aff7Sartem 	gchar *strvalue;
60918c2aff7Sartem 	int value;
61018c2aff7Sartem 
61118c2aff7Sartem 	value = G_MAXINT;
61218c2aff7Sartem 
61318c2aff7Sartem 	strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse);
61418c2aff7Sartem 	if (strvalue == NULL)
61518c2aff7Sartem 		goto out;
61618c2aff7Sartem 
61718c2aff7Sartem 	value = strtol (strvalue, &endptr, base);
61818c2aff7Sartem 	if (endptr == strvalue) {
61918c2aff7Sartem 		value = G_MAXINT;
62018c2aff7Sartem 		goto out;
62118c2aff7Sartem 	}
62218c2aff7Sartem 
62318c2aff7Sartem out:
62418c2aff7Sartem 	return value;
62518c2aff7Sartem }
62618c2aff7Sartem 
62718c2aff7Sartem /** Get a string value from a formatted text file and assign it to
62818c2aff7Sartem  *  a property on a device object.
62918c2aff7Sartem  *
63018c2aff7Sartem  *  Example: Given that the file /proc/acpi/battery/BAT0/info contains
63118c2aff7Sartem  *  the line
63218c2aff7Sartem  *
63318c2aff7Sartem  *    "design voltage:          10800 mV"
63418c2aff7Sartem  *
63518c2aff7Sartem  *  then hal_util_set_string_elem_from_file (d, "battery.foo",
63618c2aff7Sartem  *  "/proc/acpi/battery/BAT0", "info", "design voltage", 1) will assign
63718c2aff7Sartem  *  the string "mV" to the property "battery.foo" on d.
63818c2aff7Sartem  *
63918c2aff7Sartem  *  @param  d                   Device object
64018c2aff7Sartem  *  @param  key                 Property name
64118c2aff7Sartem  *  @param  directory           Directory, e.g. "/proc/acpi/battery/BAT0"
64218c2aff7Sartem  *  @param  file                File, e.g. "info"
64318c2aff7Sartem  *  @param  linestart           Start of line, e.g. "design voltage"
64418c2aff7Sartem  *  @param  elem                Element number after linestart to extract
64518c2aff7Sartem  *                              excluding whitespace and ':' characters.
64618c2aff7Sartem  *  @return                     TRUE, if, and only if, the value could be
64718c2aff7Sartem  *                              extracted and the property was set
64818c2aff7Sartem  */
64918c2aff7Sartem gboolean
hal_util_set_string_elem_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file,const gchar * linestart,guint elem,gboolean reuse)65018c2aff7Sartem hal_util_set_string_elem_from_file (HalDevice *d, const gchar *key,
65118c2aff7Sartem 				    const gchar *directory, const gchar *file,
65218c2aff7Sartem 				    const gchar *linestart, guint elem, gboolean reuse)
65318c2aff7Sartem {
65418c2aff7Sartem 	gboolean res;
65518c2aff7Sartem 	gchar *value;
65618c2aff7Sartem 
65718c2aff7Sartem 	res = FALSE;
65818c2aff7Sartem 
65918c2aff7Sartem 	if ((value = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse)) == NULL)
66018c2aff7Sartem 		goto out;
66118c2aff7Sartem 
66218c2aff7Sartem 	res = hal_device_property_set_string (d, key, value);
66318c2aff7Sartem out:
66418c2aff7Sartem 	return res;
66518c2aff7Sartem }
66618c2aff7Sartem 
66718c2aff7Sartem /** Get an integer value from a formatted text file and assign it to
66818c2aff7Sartem  *  a property on a device object.
66918c2aff7Sartem  *
67018c2aff7Sartem  *  Example: Given that the file /proc/acpi/battery/BAT0/info contains
67118c2aff7Sartem  *  the line
67218c2aff7Sartem  *
67318c2aff7Sartem  *    "design voltage:          10800 mV"
67418c2aff7Sartem  *
67518c2aff7Sartem  *  then hal_util_set_int_elem_from_file (d, "battery.foo",
67618c2aff7Sartem  *  "/proc/acpi/battery/BAT0", "info", "design voltage", 0) will assign
67718c2aff7Sartem  *  the integer 10800 to the property "battery.foo" on d.
67818c2aff7Sartem  *
67918c2aff7Sartem  *  @param  d                   Device object
68018c2aff7Sartem  *  @param  key                 Property name
68118c2aff7Sartem  *  @param  directory           Directory, e.g. "/proc/acpi/battery/BAT0"
68218c2aff7Sartem  *  @param  file                File, e.g. "info"
68318c2aff7Sartem  *  @param  linestart           Start of line, e.g. "design voltage"
68418c2aff7Sartem  *  @param  elem                Element number after linestart to extract
68518c2aff7Sartem  *                              excluding whitespace and ':' characters.
68618c2aff7Sartem  *  @return                     TRUE, if, and only if, the value could be
68718c2aff7Sartem  *                              extracted and the property was set
68818c2aff7Sartem  */
68918c2aff7Sartem gboolean
hal_util_set_int_elem_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file,const gchar * linestart,guint elem,guint base,gboolean reuse)69018c2aff7Sartem hal_util_set_int_elem_from_file (HalDevice *d, const gchar *key,
69118c2aff7Sartem 				 const gchar *directory, const gchar *file,
69218c2aff7Sartem 				 const gchar *linestart, guint elem, guint base, gboolean reuse)
69318c2aff7Sartem {
69418c2aff7Sartem 	gchar *endptr;
69518c2aff7Sartem 	gboolean res;
69618c2aff7Sartem 	gchar *strvalue;
69718c2aff7Sartem 	int value;
69818c2aff7Sartem 
69918c2aff7Sartem 	res = FALSE;
70018c2aff7Sartem 
70118c2aff7Sartem 	strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse);
70218c2aff7Sartem 	if (strvalue == NULL)
70318c2aff7Sartem 		goto out;
70418c2aff7Sartem 
70518c2aff7Sartem 	value = strtol (strvalue, &endptr, base);
70618c2aff7Sartem 	if (endptr == strvalue)
70718c2aff7Sartem 		goto out;
70818c2aff7Sartem 
70918c2aff7Sartem 	res = hal_device_property_set_int (d, key, value);
71018c2aff7Sartem 
71118c2aff7Sartem out:
71218c2aff7Sartem 	return res;
71318c2aff7Sartem 
71418c2aff7Sartem }
71518c2aff7Sartem 
71618c2aff7Sartem /** Get a value from a formatted text file, test it against a given
71718c2aff7Sartem  *  value, and set a boolean property on a device object with the
71818c2aff7Sartem  *  test result.
71918c2aff7Sartem  *
72018c2aff7Sartem  *  Example: Given that the file /proc/acpi/battery/BAT0/info contains
72118c2aff7Sartem  *  the line
72218c2aff7Sartem  *
72318c2aff7Sartem  *    "present:                 yes"
72418c2aff7Sartem  *
72518c2aff7Sartem  *  then hal_util_set_bool_elem_from_file (d, "battery.baz",
72618c2aff7Sartem  *  "/proc/acpi/battery/BAT0", "info", "present", 0, "yes") will assign
72718c2aff7Sartem  *  the boolean TRUE to the property "battery.baz" on d.
72818c2aff7Sartem  *
72918c2aff7Sartem  *  If, instead, the line was
73018c2aff7Sartem  *
73118c2aff7Sartem  *    "present:                 no"
73218c2aff7Sartem  *
73318c2aff7Sartem  *  the value assigned will be FALSE.
73418c2aff7Sartem  *
73518c2aff7Sartem  *  @param  d                   Device object
73618c2aff7Sartem  *  @param  key                 Property name
73718c2aff7Sartem  *  @param  directory           Directory, e.g. "/proc/acpi/battery/BAT0"
73818c2aff7Sartem  *  @param  file                File, e.g. "info"
73918c2aff7Sartem  *  @param  linestart           Start of line, e.g. "design voltage"
74018c2aff7Sartem  *  @param  elem                Element number after linestart to extract
74118c2aff7Sartem  *                              excluding whitespace and ':' characters.
74218c2aff7Sartem  *  @param  expected            Value to test against
74318c2aff7Sartem  *  @return                     TRUE, if, and only if, the value could be
74418c2aff7Sartem  *                              extracted and the property was set
74518c2aff7Sartem  */
74618c2aff7Sartem gboolean
hal_util_set_bool_elem_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file,const gchar * linestart,guint elem,const gchar * expected,gboolean reuse)74718c2aff7Sartem hal_util_set_bool_elem_from_file (HalDevice *d, const gchar *key,
74818c2aff7Sartem 				  const gchar *directory, const gchar *file,
74918c2aff7Sartem 				  const gchar *linestart, guint elem, const gchar *expected, gboolean reuse)
75018c2aff7Sartem {
75118c2aff7Sartem 	gchar *line;
75218c2aff7Sartem 	gboolean res;
75318c2aff7Sartem 	gchar **tokens;
75418c2aff7Sartem 	guint i, j;
75518c2aff7Sartem 
75618c2aff7Sartem 	res = FALSE;
75718c2aff7Sartem 	tokens = NULL;
75818c2aff7Sartem 
75918c2aff7Sartem 	if (((line = hal_util_grep_file (directory, file, linestart, reuse)) == NULL) || (strlen (line) == 0))
76018c2aff7Sartem 		goto out;
76118c2aff7Sartem 
76218c2aff7Sartem 	tokens = g_strsplit_set (line, " \t:", 0);
76318c2aff7Sartem 
76418c2aff7Sartem 	for (i = 0, j = 0; tokens[i] != NULL; i++) {
76518c2aff7Sartem 		if (strlen (tokens[i]) == 0)
76618c2aff7Sartem 			continue;
76718c2aff7Sartem 		if (j == elem) {
76818c2aff7Sartem 			hal_device_property_set_bool (d, key, strcmp (tokens[i], expected) == 0);
76918c2aff7Sartem 			res = TRUE;
77018c2aff7Sartem 			goto out;
77118c2aff7Sartem 		}
77218c2aff7Sartem 		j++;
77318c2aff7Sartem 	}
77418c2aff7Sartem 
77518c2aff7Sartem 
77618c2aff7Sartem out:
77718c2aff7Sartem 	if (tokens != NULL)
77818c2aff7Sartem 		g_strfreev (tokens);
77918c2aff7Sartem 
78018c2aff7Sartem 	return res;
78118c2aff7Sartem }
78218c2aff7Sartem 
78318c2aff7Sartem gchar **
hal_util_dup_strv_from_g_slist(GSList * strlist)78418c2aff7Sartem hal_util_dup_strv_from_g_slist (GSList *strlist)
78518c2aff7Sartem {
78618c2aff7Sartem 	guint j;
78718c2aff7Sartem 	guint len;
78818c2aff7Sartem 	gchar **strv;
78918c2aff7Sartem 	GSList *i;
79018c2aff7Sartem 
79118c2aff7Sartem 	len = g_slist_length (strlist);
79218c2aff7Sartem 	strv = g_new (char *, len + 1);
79318c2aff7Sartem 
79418c2aff7Sartem 	for (i = strlist, j = 0; i != NULL; i = g_slist_next (i), j++) {
79518c2aff7Sartem 		strv[j] = g_strdup ((const gchar *) i->data);
79618c2aff7Sartem 	}
79718c2aff7Sartem 	strv[j] = NULL;
79818c2aff7Sartem 
79918c2aff7Sartem 	return strv;
80018c2aff7Sartem }
80118c2aff7Sartem 
80218c2aff7Sartem /* -------------------------------------------------------------------------------------------------------------- */
80318c2aff7Sartem 
80418c2aff7Sartem typedef struct {
80518c2aff7Sartem 	HalDevice *d;
80618c2aff7Sartem 	gchar **programs;
80718c2aff7Sartem 	gchar **extra_env;
80818c2aff7Sartem 	guint next_program;
80918c2aff7Sartem 
81018c2aff7Sartem 	HalCalloutsDone callback;
81118c2aff7Sartem 	gpointer userdata1;
81218c2aff7Sartem 	gpointer userdata2;
81318c2aff7Sartem 
81418c2aff7Sartem } Callout;
81518c2aff7Sartem 
81618c2aff7Sartem static void callout_do_next (Callout *c);
81718c2aff7Sartem 
81818c2aff7Sartem static void
callout_terminated(HalDevice * d,guint32 exit_type,gint return_code,gchar ** error,gpointer data1,gpointer data2)81918c2aff7Sartem callout_terminated (HalDevice *d, guint32 exit_type,
82018c2aff7Sartem                    gint return_code, gchar **error,
82118c2aff7Sartem                    gpointer data1, gpointer data2)
82218c2aff7Sartem {
82318c2aff7Sartem 	Callout *c;
82418c2aff7Sartem 
82518c2aff7Sartem 	c = (Callout *) data1;
82618c2aff7Sartem 	callout_do_next (c);
82718c2aff7Sartem }
82818c2aff7Sartem 
82918c2aff7Sartem static void
callout_do_next(Callout * c)83018c2aff7Sartem callout_do_next (Callout *c)
83118c2aff7Sartem {
83218c2aff7Sartem 
83318c2aff7Sartem 	/* Check if we're done */
83418c2aff7Sartem 	if (c->programs[c->next_program] == NULL) {
83518c2aff7Sartem 		HalDevice *d;
83618c2aff7Sartem 		gpointer userdata1;
83718c2aff7Sartem 		gpointer userdata2;
83818c2aff7Sartem 		HalCalloutsDone callback;
83918c2aff7Sartem 
84018c2aff7Sartem 		d = c->d;
84118c2aff7Sartem 		userdata1 = c->userdata1;
84218c2aff7Sartem 		userdata2 = c->userdata2;
84318c2aff7Sartem 		callback = c->callback;
84418c2aff7Sartem 
84518c2aff7Sartem 		g_strfreev (c->programs);
84618c2aff7Sartem 		g_strfreev (c->extra_env);
84718c2aff7Sartem 		g_free (c);
84818c2aff7Sartem 
84918c2aff7Sartem 		callback (d, userdata1, userdata2);
85018c2aff7Sartem 
85118c2aff7Sartem 	} else {
85218c2aff7Sartem     hald_runner_run(c->d, c->programs[c->next_program], c->extra_env,
85318c2aff7Sartem                     HAL_HELPER_TIMEOUT, callout_terminated,
85418c2aff7Sartem                     (gpointer)c, NULL);
85518c2aff7Sartem 		c->next_program++;
85618c2aff7Sartem 	}
85718c2aff7Sartem }
85818c2aff7Sartem 
85918c2aff7Sartem static void
hal_callout_device(HalDevice * d,HalCalloutsDone callback,gpointer userdata1,gpointer userdata2,GSList * programs,gchar ** extra_env)86018c2aff7Sartem hal_callout_device (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2,
86118c2aff7Sartem 		    GSList *programs, gchar **extra_env)
86218c2aff7Sartem {
86318c2aff7Sartem 	Callout *c;
86418c2aff7Sartem 
86518c2aff7Sartem 	c = g_new0 (Callout, 1);
86618c2aff7Sartem 	c->d = d;
86718c2aff7Sartem 	c->callback = callback;
86818c2aff7Sartem 	c->userdata1 = userdata1;
86918c2aff7Sartem 	c->userdata2 = userdata2;
87018c2aff7Sartem 	c->programs = hal_util_dup_strv_from_g_slist (programs);
87118c2aff7Sartem 	c->extra_env = g_strdupv (extra_env);
87218c2aff7Sartem 	c->next_program = 0;
87318c2aff7Sartem 
87418c2aff7Sartem 	callout_do_next (c);
87518c2aff7Sartem }
87618c2aff7Sartem 
87718c2aff7Sartem void
hal_util_callout_device_add(HalDevice * d,HalCalloutsDone callback,gpointer userdata1,gpointer userdata2)87818c2aff7Sartem hal_util_callout_device_add (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2)
87918c2aff7Sartem {
88018c2aff7Sartem 	GSList *programs;
88118c2aff7Sartem 	gchar *extra_env[2] = {"HALD_ACTION=add", NULL};
88218c2aff7Sartem 
88318c2aff7Sartem 	if ((programs = hal_device_property_get_strlist (d, "info.callouts.add")) == NULL) {
88418c2aff7Sartem 		callback (d, userdata1, userdata2);
88518c2aff7Sartem 		goto out;
88618c2aff7Sartem 	}
88718c2aff7Sartem 
88818c2aff7Sartem 	HAL_INFO (("Add callouts for udi=%s", d->udi));
88918c2aff7Sartem 
89018c2aff7Sartem 	hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env);
89118c2aff7Sartem out:
89218c2aff7Sartem 	;
89318c2aff7Sartem }
89418c2aff7Sartem 
89518c2aff7Sartem void
hal_util_callout_device_remove(HalDevice * d,HalCalloutsDone callback,gpointer userdata1,gpointer userdata2)89618c2aff7Sartem hal_util_callout_device_remove (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2)
89718c2aff7Sartem {
89818c2aff7Sartem 	GSList *programs;
89918c2aff7Sartem 	gchar *extra_env[2] = {"HALD_ACTION=remove", NULL};
90018c2aff7Sartem 
90118c2aff7Sartem 	if ((programs = hal_device_property_get_strlist (d, "info.callouts.remove")) == NULL) {
90218c2aff7Sartem 		callback (d, userdata1, userdata2);
90318c2aff7Sartem 		goto out;
90418c2aff7Sartem 	}
90518c2aff7Sartem 
90618c2aff7Sartem 	HAL_INFO (("Remove callouts for udi=%s", d->udi));
90718c2aff7Sartem 
90818c2aff7Sartem 	hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env);
90918c2aff7Sartem out:
91018c2aff7Sartem 	;
91118c2aff7Sartem }
91218c2aff7Sartem 
91318c2aff7Sartem void
hal_util_callout_device_preprobe(HalDevice * d,HalCalloutsDone callback,gpointer userdata1,gpointer userdata2)91418c2aff7Sartem hal_util_callout_device_preprobe (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2)
91518c2aff7Sartem {
91618c2aff7Sartem 	GSList *programs;
91718c2aff7Sartem 	gchar *extra_env[2] = {"HALD_ACTION=preprobe", NULL};
91818c2aff7Sartem 
91918c2aff7Sartem 	if ((programs = hal_device_property_get_strlist (d, "info.callouts.preprobe")) == NULL) {
92018c2aff7Sartem 		callback (d, userdata1, userdata2);
92118c2aff7Sartem 		goto out;
92218c2aff7Sartem 	}
92318c2aff7Sartem 
92418c2aff7Sartem 	HAL_INFO (("Preprobe callouts for udi=%s", d->udi));
92518c2aff7Sartem 
92618c2aff7Sartem 	hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env);
92718c2aff7Sartem out:
92818c2aff7Sartem 	;
92918c2aff7Sartem }
93018c2aff7Sartem 
93118c2aff7Sartem gchar *
hal_util_strdup_valid_utf8(const char * str)93218c2aff7Sartem hal_util_strdup_valid_utf8 (const char *str)
93318c2aff7Sartem {
93418c2aff7Sartem 	char *endchar;
93518c2aff7Sartem 	char *newstr;
93618c2aff7Sartem 	unsigned int count = 0;
93718c2aff7Sartem 
93818c2aff7Sartem 	if (str == NULL)
93918c2aff7Sartem 		return NULL;
94018c2aff7Sartem 
94118c2aff7Sartem 	newstr = g_strdup (str);
94218c2aff7Sartem 
94318c2aff7Sartem 	while (!g_utf8_validate (newstr, -1, (const char **) &endchar)) {
94418c2aff7Sartem 		*endchar = '?';
94518c2aff7Sartem 		count++;
94618c2aff7Sartem 	}
94718c2aff7Sartem 
94818c2aff7Sartem 	if (strlen(newstr) == count)
94918c2aff7Sartem 		return NULL;
95018c2aff7Sartem 	else
95118c2aff7Sartem 		return newstr;
95218c2aff7Sartem }
95318c2aff7Sartem 
95418c2aff7Sartem void
hal_util_hexdump(const void * mem,unsigned int size)95518c2aff7Sartem hal_util_hexdump (const void *mem, unsigned int size)
95618c2aff7Sartem {
95718c2aff7Sartem 	unsigned int i;
95818c2aff7Sartem 	unsigned int j;
95918c2aff7Sartem 	unsigned int n;
96018c2aff7Sartem 	const char *buf = (const char *) mem;
96118c2aff7Sartem 
96218c2aff7Sartem 	n = 0;
96318c2aff7Sartem 	printf ("Dumping %d=0x%x bytes\n", size, size);
96418c2aff7Sartem 	while (n < size) {
96518c2aff7Sartem 
96618c2aff7Sartem 		printf ("0x%04x: ", n);
96718c2aff7Sartem 
96818c2aff7Sartem 		j = n;
96918c2aff7Sartem 		for (i = 0; i < 16; i++) {
97018c2aff7Sartem 			if (j >= size)
97118c2aff7Sartem 				break;
97218c2aff7Sartem 			printf ("%02x ", buf[j]);
97318c2aff7Sartem 			j++;
97418c2aff7Sartem 		}
97518c2aff7Sartem 
97618c2aff7Sartem 		for ( ; i < 16; i++) {
97718c2aff7Sartem 			printf ("   ");
97818c2aff7Sartem 		}
97918c2aff7Sartem 
98018c2aff7Sartem 		printf ("   ");
98118c2aff7Sartem 
98218c2aff7Sartem 		j = n;
98318c2aff7Sartem 		for (i = 0; i < 16; i++) {
98418c2aff7Sartem 			if (j >= size)
98518c2aff7Sartem 				break;
98618c2aff7Sartem 			printf ("%c", isprint(buf[j]) ? buf[j] : '.');
98718c2aff7Sartem 			j++;
98818c2aff7Sartem 		}
98918c2aff7Sartem 
99018c2aff7Sartem 		printf ("\n");
99118c2aff7Sartem 
99218c2aff7Sartem 		n += 16;
99318c2aff7Sartem 	}
99418c2aff7Sartem }
99518c2aff7Sartem 
99618c2aff7Sartem gboolean
hal_util_is_mounted_by_hald(const char * mount_point)99718c2aff7Sartem hal_util_is_mounted_by_hald (const char *mount_point)
99818c2aff7Sartem {
99918c2aff7Sartem 	int i;
100018c2aff7Sartem 	FILE *hal_mtab;
100118c2aff7Sartem 	int hal_mtab_len;
100218c2aff7Sartem 	int num_read;
100318c2aff7Sartem 	char *hal_mtab_buf;
100418c2aff7Sartem 	char **lines;
100518c2aff7Sartem 	gboolean found;
100618c2aff7Sartem 
100718c2aff7Sartem 	hal_mtab = NULL;
100818c2aff7Sartem 	hal_mtab_buf = NULL;
100918c2aff7Sartem 	found = FALSE;
101018c2aff7Sartem 
101118c2aff7Sartem 	/*HAL_DEBUG (("examining /media/.hal-mtab for %s", mount_point));*/
101218c2aff7Sartem 
101318c2aff7Sartem 	hal_mtab = fopen ("/media/.hal-mtab", "r");
101418c2aff7Sartem 	if (hal_mtab == NULL) {
101518c2aff7Sartem 		HAL_ERROR (("Cannot open /media/.hal-mtab"));
101618c2aff7Sartem 		goto out;
101718c2aff7Sartem 	}
101818c2aff7Sartem 	if (fseek (hal_mtab, 0L, SEEK_END) != 0) {
101918c2aff7Sartem 		HAL_ERROR (("Cannot seek to end of /media/.hal-mtab"));
102018c2aff7Sartem 		goto out;
102118c2aff7Sartem 	}
102218c2aff7Sartem 	hal_mtab_len = ftell (hal_mtab);
102318c2aff7Sartem 	if (hal_mtab_len < 0) {
102418c2aff7Sartem 		HAL_ERROR (("Cannot determine size of /media/.hal-mtab"));
102518c2aff7Sartem 		goto out;
102618c2aff7Sartem 	}
102718c2aff7Sartem 	rewind (hal_mtab);
102818c2aff7Sartem 
102918c2aff7Sartem 	hal_mtab_buf = g_new0 (char, hal_mtab_len + 1);
103018c2aff7Sartem 	num_read = fread (hal_mtab_buf, 1, hal_mtab_len, hal_mtab);
103118c2aff7Sartem 	if (num_read != hal_mtab_len) {
103218c2aff7Sartem 		HAL_ERROR (("Cannot read from /media/.hal-mtab"));
103318c2aff7Sartem 		goto out;
103418c2aff7Sartem 	}
103518c2aff7Sartem 	fclose (hal_mtab);
103618c2aff7Sartem 	hal_mtab = NULL;
103718c2aff7Sartem 
103818c2aff7Sartem 	/*HAL_DEBUG (("hal_mtab = '%s'\n", hal_mtab_buf));*/
103918c2aff7Sartem 
104018c2aff7Sartem 	lines = g_strsplit (hal_mtab_buf, "\n", 0);
104118c2aff7Sartem 	g_free (hal_mtab_buf);
104218c2aff7Sartem 	hal_mtab_buf = NULL;
104318c2aff7Sartem 
104418c2aff7Sartem 	/* find the entry we're going to unmount */
104518c2aff7Sartem 	for (i = 0; lines[i] != NULL && !found; i++) {
104618c2aff7Sartem 		char **line_elements;
104718c2aff7Sartem 
104818c2aff7Sartem 		/*HAL_DEBUG ((" line = '%s'", lines[i]));*/
104918c2aff7Sartem 
105018c2aff7Sartem 		if ((lines[i])[0] == '#')
105118c2aff7Sartem 			continue;
105218c2aff7Sartem 
105318c2aff7Sartem 		line_elements = g_strsplit (lines[i], "\t", 6);
105418c2aff7Sartem 		if (g_strv_length (line_elements) == 6) {
105518c2aff7Sartem /*
105618c2aff7Sartem 			HAL_DEBUG (("  devfile     = '%s'", line_elements[0]));
105718c2aff7Sartem 			HAL_DEBUG (("  uid         = '%s'", line_elements[1]));
105818c2aff7Sartem 			HAL_DEBUG (("  session id  = '%s'", line_elements[2]));
105918c2aff7Sartem 			HAL_DEBUG (("  fs          = '%s'", line_elements[3]));
106018c2aff7Sartem 			HAL_DEBUG (("  options     = '%s'", line_elements[4]));
106118c2aff7Sartem 			HAL_DEBUG (("  mount_point = '%s'", line_elements[5]));
106218c2aff7Sartem 			HAL_DEBUG (("  (comparing against '%s')", mount_point));
106318c2aff7Sartem */
106418c2aff7Sartem 
106518c2aff7Sartem 			if (strcmp (line_elements[5], mount_point) == 0) {
106618c2aff7Sartem 				found = TRUE;
106718c2aff7Sartem 				/*HAL_INFO (("device at '%s' is indeed mounted by HAL's Mount()", mount_point));*/
106818c2aff7Sartem 			}
106918c2aff7Sartem 
107018c2aff7Sartem 		}
107118c2aff7Sartem 
107218c2aff7Sartem 		g_strfreev (line_elements);
107318c2aff7Sartem 	}
107418c2aff7Sartem 
107518c2aff7Sartem 	g_strfreev (lines);
107618c2aff7Sartem 
107718c2aff7Sartem out:
107818c2aff7Sartem 	if (hal_mtab != NULL)
107918c2aff7Sartem 		fclose (hal_mtab);
108018c2aff7Sartem 	if (hal_mtab_buf != NULL)
108118c2aff7Sartem 		g_free (hal_mtab_buf);
108218c2aff7Sartem 
108318c2aff7Sartem 	return found;
108418c2aff7Sartem }
108518c2aff7Sartem 
108618c2aff7Sartem void
hal_util_branch_claim(HalDeviceStore * store,HalDevice * root,dbus_bool_t claimed,const char * service,int uid)108718c2aff7Sartem hal_util_branch_claim (HalDeviceStore *store, HalDevice *root, dbus_bool_t claimed,
108818c2aff7Sartem     const char *service, int uid)
108918c2aff7Sartem {
109018c2aff7Sartem 	GSList *children;
109118c2aff7Sartem 	GSList *i;
109218c2aff7Sartem 	HalDevice *d;
109318c2aff7Sartem 
109418c2aff7Sartem 	if (claimed) {
109518c2aff7Sartem 		hal_device_property_set_bool (root, "info.claimed", claimed);
109618c2aff7Sartem 		hal_device_property_set_string (root, "info.claimed.service", service);
109718c2aff7Sartem 		hal_device_property_set_int (root, "info.claimed.uid", uid);
109818c2aff7Sartem 	} else {
109918c2aff7Sartem 		hal_device_property_remove (root, "info.claimed");
110018c2aff7Sartem 		hal_device_property_remove (root, "info.claimed.service");
110118c2aff7Sartem 		hal_device_property_remove (root, "info.claimed.uid");
110218c2aff7Sartem 	}
110318c2aff7Sartem 
110418c2aff7Sartem 
110518c2aff7Sartem 	children = hal_device_store_match_multiple_key_value_string (store,
110618c2aff7Sartem 	    "info.parent", root->udi);
110718c2aff7Sartem 
110818c2aff7Sartem 	for (i = children; i != NULL; i = g_slist_next (i)) {
110918c2aff7Sartem 		d = HAL_DEVICE (i->data);
111018c2aff7Sartem 		hal_util_branch_claim (store, d, claimed, service, uid);
111118c2aff7Sartem 	}
111218c2aff7Sartem 
111318c2aff7Sartem 	g_slist_free (children);
111418c2aff7Sartem }
1115*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 
1116*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China /** Given an interface name, check if it is valid.
1117*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China  *  @param  name	A given interface name
1118*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China  *  @return		TRUE if name is valid, otherwise FALSE
1119*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China  */
1120*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China gboolean
is_valid_interface_name(const char * name)1121*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China is_valid_interface_name(const char *name) {
1122*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 
1123*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	const char *end;
1124*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	const char *last_dot;
1125*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 
1126*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	last_dot = NULL;
1127*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 
1128*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	if (strlen(name) == 0)
1129*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 		return FALSE;
1130*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 
1131*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	end = name + strlen(name);
1132*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 
1133*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	if (*name == '.')    /* disallow starting with a . */
1134*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 		return FALSE;
1135*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	else if (!VALID_INITIAL_NAME_CHARACTER (*name))
1136*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 		return FALSE;
1137*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	else
1138*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 		name++;
1139*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 
1140*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	while (name != end) {
1141*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 		if (*name == '.') {
1142*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 			if ((name + 1) == end)
1143*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 				return FALSE;
1144*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 			else if (!VALID_INITIAL_NAME_CHARACTER (*(name + 1)))
1145*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 				return FALSE;
1146*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 			last_dot = name;
1147*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 			name++;    /* we just validated the next char, so skip two */
1148*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 		} else if (!VALID_NAME_CHARACTER (*name))
1149*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 			return FALSE;
1150*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 		name++;
1151*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	}
1152*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	if (last_dot == NULL)
1153*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 		return FALSE;
1154*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 
1155*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 	return TRUE;
1156*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China }
1157