xref: /onnv-gate/usr/src/cmd/hal/tools/hal-device.c (revision 3502:2bf49c526f07)
1*2912Sartem /***************************************************************************
2*2912Sartem  * CVSID: $Id$
3*2912Sartem  *
4*2912Sartem  * hal-device.c : add devices HAL
5*2912Sartem  *
6*2912Sartem  * Copyright (C) 2005 SuSE Linux Gmbh
7*2912Sartem  *
8*2912Sartem  * Authors:
9*2912Sartem  *	Steffen Winterfeldt <snwint@suse.de>
10*2912Sartem  *
11*2912Sartem  * Licensed under the Academic Free License version 2.1
12*2912Sartem  *
13*2912Sartem  * This program is free software; you can redistribute it and/or modify
14*2912Sartem  * it under the terms of the GNU General Public License as published by
15*2912Sartem  * the Free Software Foundation; either version 2 of the License, or
16*2912Sartem  * (at your option) any later version.
17*2912Sartem  *
18*2912Sartem  * This program is distributed in the hope that it will be useful,
19*2912Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20*2912Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21*2912Sartem  * GNU General Public License for more details.
22*2912Sartem  *
23*2912Sartem  * You should have received a copy of the GNU General Public License
24*2912Sartem  * along with this program; if not, write to the Free Software
25*2912Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
26*2912Sartem  *
27*2912Sartem  */
28*2912Sartem 
29*2912Sartem #define _GNU_SOURCE
30*2912Sartem 
31*2912Sartem #ifdef HAVE_CONFIG_H
32*2912Sartem #  include <config.h>
33*2912Sartem #endif
34*2912Sartem 
35*2912Sartem #include <stdio.h>
36*2912Sartem #include <string.h>
37*2912Sartem #include <unistd.h>
38*2912Sartem #include <stdlib.h>
39*2912Sartem #include <ctype.h>
40*2912Sartem #include <inttypes.h>
41*2912Sartem #include <getopt.h>
42*2912Sartem 
43*2912Sartem #ifndef DBUS_API_SUBJECT_TO_CHANGE
44*2912Sartem #define DBUS_API_SUBJECT_TO_CHANGE 1
45*2912Sartem #endif
46*2912Sartem 
47*2912Sartem #include <dbus/dbus.h>
48*2912Sartem #include <libhal.h>
49*2912Sartem 
50*2912Sartem typedef struct {
51*2912Sartem 	char *udi;
52*2912Sartem 	char *real_udi;
53*2912Sartem } new_dev_t;
54*2912Sartem 
55*2912Sartem typedef struct lh_prop_s {
56*2912Sartem 	struct lh_prop_s *next;
57*2912Sartem 	LibHalPropertyType type;
58*2912Sartem 	char *key;
59*2912Sartem 	union {
60*2912Sartem 		char *str_value;
61*2912Sartem 		dbus_int32_t int_value;
62*2912Sartem 		dbus_uint64_t uint64_value;
63*2912Sartem 		double double_value;
64*2912Sartem 		dbus_bool_t bool_value;
65*2912Sartem 		char **strlist_value;
66*2912Sartem 	} v;
67*2912Sartem } lh_prop_t;
68*2912Sartem 
69*2912Sartem 
70*2912Sartem void help(void);
71*2912Sartem int dump_devices(LibHalContext *hal_ctx, char *arg);
72*2912Sartem int remove_udi(LibHalContext *hal_ctx, char *arg);
73*2912Sartem int add_udi(LibHalContext *hal_ctx, char *arg);
74*2912Sartem void process_property(LibHalContext *hal_ctx, char *buf, lh_prop_t **prop);
75*2912Sartem int add_properties(LibHalContext *hal_ctx, new_dev_t *nd, lh_prop_t *prop);
76*2912Sartem lh_prop_t *free_properties(lh_prop_t *prop);
77*2912Sartem static char *skip_space(char *s);
78*2912Sartem static char *skip_non_eq_or_space(char *s);
79*2912Sartem static char *skip_number(char *s);
80*2912Sartem static char *skip_nonquote(char *s);
81*2912Sartem 
82*2912Sartem 
83*2912Sartem new_dev_t new_dev;
84*2912Sartem 
85*2912Sartem struct {
86*2912Sartem 	unsigned remove:1;
87*2912Sartem 	unsigned add:1;
88*2912Sartem 	unsigned list:1;
89*2912Sartem 	char *udi;
90*2912Sartem } opt;
91*2912Sartem 
92*2912Sartem struct option options[] = {
93*2912Sartem 	{ "remove", 1, NULL, 'r' },
94*2912Sartem 	{ "add", 1, NULL, 'a' },
95*2912Sartem 	{ "help", 0, NULL, 'h' },
96*2912Sartem 	{ 0, 0, 0, 0 }
97*2912Sartem };
98*2912Sartem 
99*2912Sartem 
main(int argc,char ** argv)100*2912Sartem int main(int argc, char **argv)
101*2912Sartem {
102*2912Sartem 	DBusError error;
103*2912Sartem 	DBusConnection *conn;
104*2912Sartem 	LibHalContext *hal_ctx;
105*2912Sartem 	int i, err;
106*2912Sartem 
107*2912Sartem 	opterr = 0;
108*2912Sartem 	opt.list = 1;
109*2912Sartem 
110*2912Sartem 	while ((i = getopt_long(argc, argv, "a:hr:", options, NULL)) != -1) {
111*2912Sartem 		switch (i) {
112*2912Sartem 		case 'a':
113*2912Sartem 			opt.add = 1;
114*2912Sartem 			opt.list = 0;
115*2912Sartem 			opt.udi = optarg;
116*2912Sartem 			break;
117*2912Sartem 		case 'r':
118*2912Sartem 			opt.remove = 1;
119*2912Sartem 			opt.list = 0;
120*2912Sartem 			opt.udi = optarg;
121*2912Sartem 			break;
122*2912Sartem 		case 'h':
123*2912Sartem 			help();
124*2912Sartem 			return 0;
125*2912Sartem 		default:
126*2912Sartem 			help();
127*2912Sartem 			return 1;
128*2912Sartem 		}
129*2912Sartem 	}
130*2912Sartem 
131*2912Sartem 	dbus_error_init(&error);
132*2912Sartem 
133*2912Sartem 	if (!(conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
134*2912Sartem 		fprintf(stderr, "error: dbus_bus_get: %s: %s\n", error.name, error.message);
135*2912Sartem 		LIBHAL_FREE_DBUS_ERROR (&error);
136*2912Sartem 		return 2;
137*2912Sartem 	}
138*2912Sartem 
139*2912Sartem 	/* fprintf(stderr, "connected to: %s\n", dbus_bus_get_unique_name(conn)); */
140*2912Sartem 	if (!(hal_ctx = libhal_ctx_new())) return 3;
141*2912Sartem 	if (!libhal_ctx_set_dbus_connection(hal_ctx, conn)) return 4;
142*2912Sartem 	if (!libhal_ctx_init(hal_ctx, &error)) {
143*2912Sartem 		if (dbus_error_is_set(&error)) {
144*2912Sartem 			fprintf (stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message);
145*2912Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
146*2912Sartem 		}
147*2912Sartem 		fprintf (stderr, "Could not initialise connection to hald.\n"
148*2912Sartem 				 "Normally this means the HAL daemon (hald) is not running or not ready.\n");
149*2912Sartem 		return 5;
150*2912Sartem 	}
151*2912Sartem 
152*2912Sartem 	err = 0;
153*2912Sartem 	if (opt.list)
154*2912Sartem 		err = dump_devices(hal_ctx, argv[optind]);
155*2912Sartem 	else if (opt.remove)
156*2912Sartem 		err = remove_udi(hal_ctx, opt.udi);
157*2912Sartem 	else if (opt.add)
158*2912Sartem 		err = add_udi(hal_ctx, opt.udi);
159*2912Sartem 	else
160*2912Sartem 		err = 6;
161*2912Sartem 
162*2912Sartem 	libhal_ctx_shutdown(hal_ctx, &error);
163*2912Sartem 	libhal_ctx_free(hal_ctx);
164*2912Sartem 	dbus_connection_unref(conn);
165*2912Sartem 	dbus_error_free(&error);
166*2912Sartem 
167*2912Sartem 	return err;
168*2912Sartem }
169*2912Sartem 
170*2912Sartem 
help()171*2912Sartem void help()
172*2912Sartem {
173*2912Sartem 	fprintf(stderr,
174*2912Sartem 		"usage: hal-device [--help] [--add udi] [--remove udi] [udi]\n"
175*2912Sartem 		"Create, remove, or show HAL device. If no udi is given, shows all devices.\n"
176*2912Sartem 		"If udi doesn't start with a '/', '/org/freedesktop/Hal/devices/' is prepended.\n"
177*2912Sartem 		"  -a, --add udi\t\tAdd new device.\n"
178*2912Sartem 		"  \t\t\tReads property list in 'lshal' syntax from stdin.\n"
179*2912Sartem 		"  -r, --remove udi\tRemove device.\n"
180*2912Sartem 		"  -h, --help\t\tShow this text.\n"
181*2912Sartem 	);
182*2912Sartem }
183*2912Sartem 
184*2912Sartem 
185*2912Sartem /*
186*2912Sartem  * Dump all devices.
187*2912Sartem  */
dump_devices(LibHalContext * hal_ctx,char * arg)188*2912Sartem int dump_devices(LibHalContext *hal_ctx, char *arg)
189*2912Sartem {
190*2912Sartem 	int i;
191*2912Sartem 	int num_devices;
192*2912Sartem 	char **device_names;
193*2912Sartem 	DBusError error;
194*2912Sartem 	char *udi = NULL;
195*2912Sartem 
196*2912Sartem 	if (arg) {
197*2912Sartem 		if (*arg == '/') {
198*2912Sartem 			udi = arg;
199*2912Sartem 		} else {
200*2912Sartem #ifdef HAVE_ASPRINTF
201*2912Sartem 			asprintf(&udi, "/org/freedesktop/Hal/devices/%s", arg);
202*2912Sartem #else
203*2912Sartem 			udi = calloc(1, sizeof ("/org/freedesktop/Hal/devices/%s") + strlen(arg));
204*2912Sartem 			sprintf(udi, "/org/freedesktop/Hal/devices/%s", arg);
205*2912Sartem 
206*2912Sartem #endif
207*2912Sartem 		}
208*2912Sartem 	}
209*2912Sartem 
210*2912Sartem 	dbus_error_init(&error);
211*2912Sartem 
212*2912Sartem 	if (!udi) {
213*2912Sartem 		if (!(device_names = libhal_get_all_devices(hal_ctx, &num_devices, &error))) {
214*2912Sartem 			fprintf(stderr, "Empty HAL device list.\n");
215*2912Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
216*2912Sartem 			return 31;
217*2912Sartem 		}
218*2912Sartem 	} else {
219*2912Sartem 		device_names = calloc(2, sizeof *device_names);
220*2912Sartem 		device_names[0] = strdup(udi);
221*2912Sartem 		num_devices = 1;
222*2912Sartem 	}
223*2912Sartem 
224*2912Sartem 	for(i = 0; i < num_devices; i++) {
225*2912Sartem 		LibHalPropertySet *props;
226*2912Sartem 		LibHalPropertySetIterator it;
227*2912Sartem 		int type;
228*2912Sartem 
229*2912Sartem 		if (!(props = libhal_device_get_all_properties(hal_ctx, device_names[i], &error))) {
230*2912Sartem 			fprintf(stderr, "%s: %s\n", error.name, error.message);
231*2912Sartem 			dbus_error_init(&error);
232*2912Sartem 			continue;
233*2912Sartem 		}
234*2912Sartem 
235*2912Sartem 		if (!udi)
236*2912Sartem 			printf("%d: ", i);
237*2912Sartem 		printf("udi = '%s'\n", device_names[i]);
238*2912Sartem 
239*2912Sartem 		for(libhal_psi_init(&it, props); libhal_psi_has_more(&it); libhal_psi_next(&it)) {
240*2912Sartem 			type = libhal_psi_get_type(&it);
241*2912Sartem 			switch (type) {
242*2912Sartem 			case LIBHAL_PROPERTY_TYPE_STRING:
243*2912Sartem 				printf("  %s = '%s'  (string)\n",
244*2912Sartem 					libhal_psi_get_key(&it),
245*2912Sartem 					libhal_psi_get_string(&it)
246*2912Sartem 				);
247*2912Sartem 				break;
248*2912Sartem 			case LIBHAL_PROPERTY_TYPE_INT32:
249*2912Sartem 				printf("  %s = %d  (0x%x)  (int)\n",
250*2912Sartem 					libhal_psi_get_key(&it),
251*2912Sartem 					libhal_psi_get_int(&it),
252*2912Sartem 					libhal_psi_get_int(&it)
253*2912Sartem 				);
254*2912Sartem 				break;
255*2912Sartem 			case LIBHAL_PROPERTY_TYPE_UINT64:
256*2912Sartem 				printf("  %s = %lld  (0x%llx)  (uint64)\n",
257*2912Sartem 					libhal_psi_get_key(&it),
258*2912Sartem 					(long long) libhal_psi_get_uint64(&it),
259*2912Sartem 					(long long) libhal_psi_get_uint64(&it)
260*2912Sartem 				);
261*2912Sartem 				break;
262*2912Sartem 			case LIBHAL_PROPERTY_TYPE_DOUBLE:
263*2912Sartem 				printf("  %s = %g  (double)\n",
264*2912Sartem 					libhal_psi_get_key(&it),
265*2912Sartem 					libhal_psi_get_double(&it)
266*2912Sartem 				);
267*2912Sartem 				break;
268*2912Sartem 			case LIBHAL_PROPERTY_TYPE_BOOLEAN:
269*2912Sartem 				printf("  %s = %s  (bool)\n",
270*2912Sartem 					libhal_psi_get_key(&it),
271*2912Sartem 					libhal_psi_get_bool(&it) ? "true" : "false"
272*2912Sartem 				);
273*2912Sartem 				break;
274*2912Sartem 			case LIBHAL_PROPERTY_TYPE_STRLIST:
275*2912Sartem 				{
276*2912Sartem 					char **strlist;
277*2912Sartem 
278*2912Sartem 					printf ("  %s = { ", libhal_psi_get_key(&it));
279*2912Sartem 					strlist = libhal_psi_get_strlist(&it);
280*2912Sartem 					while (*strlist) {
281*2912Sartem 						printf("'%s'%s", *strlist, strlist[1] ? ", " : "");
282*2912Sartem 						strlist++;
283*2912Sartem 					}
284*2912Sartem 					printf(" } (string list)\n");
285*2912Sartem 				}
286*2912Sartem 				break;
287*2912Sartem 			default:
288*2912Sartem 				printf("Unknown type %d = 0x%02x\n", type, type);
289*2912Sartem 				break;
290*2912Sartem 			}
291*2912Sartem 		}
292*2912Sartem 
293*2912Sartem 		libhal_free_property_set(props);
294*2912Sartem 		printf("\n");
295*2912Sartem 	}
296*2912Sartem 
297*2912Sartem 	libhal_free_string_array(device_names);
298*2912Sartem 	dbus_error_free(&error);
299*2912Sartem 
300*2912Sartem 	return 0;
301*2912Sartem }
302*2912Sartem 
303*2912Sartem 
remove_udi(LibHalContext * hal_ctx,char * arg)304*2912Sartem int remove_udi(LibHalContext *hal_ctx, char *arg)
305*2912Sartem {
306*2912Sartem 	DBusError error;
307*2912Sartem 	char *udi;
308*2912Sartem 
309*2912Sartem 	if (!arg) return 11;
310*2912Sartem 
311*2912Sartem 	if (*arg == '/') {
312*2912Sartem 		udi = arg;
313*2912Sartem 	} else {
314*2912Sartem #ifdef HAVE_ASPRINTF
315*2912Sartem 		asprintf(&udi, "/org/freedesktop/Hal/devices/%s", arg);
316*2912Sartem #else
317*2912Sartem 		udi = calloc(1, sizeof ("/org/freedesktop/Hal/devices/%s") + strlen(arg));
318*2912Sartem 		sprintf(udi, "/org/freedesktop/Hal/devices/%s", arg);
319*2912Sartem #endif
320*2912Sartem 
321*2912Sartem 	}
322*2912Sartem 
323*2912Sartem 	dbus_error_init(&error);
324*2912Sartem 
325*2912Sartem 	if (opt.remove) {
326*2912Sartem 		if (!libhal_remove_device(hal_ctx, udi, &error)) {
327*2912Sartem 			fprintf(stderr, "%s: %s\n", error.name, error.message);
328*2912Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
329*2912Sartem 			return 12;
330*2912Sartem 		}
331*2912Sartem 
332*2912Sartem 		fprintf(stderr, "removed: %s\n", udi);
333*2912Sartem 		return 13;
334*2912Sartem 	}
335*2912Sartem 
336*2912Sartem 	return 0;
337*2912Sartem }
338*2912Sartem 
339*2912Sartem 
add_udi(LibHalContext * hal_ctx,char * arg)340*2912Sartem int add_udi(LibHalContext *hal_ctx, char *arg)
341*2912Sartem {
342*2912Sartem 	DBusError error;
343*2912Sartem 	dbus_bool_t dev_exists = FALSE;
344*2912Sartem 	char *udi = NULL, buf[1024];
345*2912Sartem 	lh_prop_t *prop;
346*2912Sartem 	int err;
347*2912Sartem 
348*2912Sartem 	if (!arg)
349*2912Sartem 		return 21;
350*2912Sartem 
351*2912Sartem 	if (*arg == '/') {
352*2912Sartem 		udi = arg;
353*2912Sartem 	} else {
354*2912Sartem #ifdef HAVE_ASPRINTF
355*2912Sartem 		asprintf(&udi, "/org/freedesktop/Hal/devices/%s", arg);
356*2912Sartem #else
357*2912Sartem 		udi = calloc(1, sizeof ("/org/freedesktop/Hal/devices/%s") + strlen(arg));
358*2912Sartem 		sprintf(udi, "/org/freedesktop/Hal/devices/%s", arg);
359*2912Sartem #endif
360*2912Sartem 	}
361*2912Sartem 
362*2912Sartem 	if (udi)
363*2912Sartem 		new_dev.udi = strdup(udi);
364*2912Sartem 
365*2912Sartem 	dbus_error_init(&error);
366*2912Sartem 
367*2912Sartem 	if (udi)
368*2912Sartem 		dev_exists = libhal_device_exists(hal_ctx, udi, &error);
369*2912Sartem 
370*2912Sartem 	if (dev_exists) {
371*2912Sartem 		new_dev.real_udi = strdup(new_dev.udi);
372*2912Sartem 	} else {
373*2912Sartem 		new_dev.real_udi = libhal_new_device(hal_ctx, &error);
374*2912Sartem 
375*2912Sartem 		if (!new_dev.real_udi) {
376*2912Sartem 			fprintf(stderr, "%s: %s\n", error.name, error.message);
377*2912Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
378*2912Sartem 			free(new_dev.real_udi);
379*2912Sartem 
380*2912Sartem 			return 22;
381*2912Sartem 		}
382*2912Sartem 
383*2912Sartem 		printf("tmp udi: %s\n", new_dev.real_udi);
384*2912Sartem 	}
385*2912Sartem 
386*2912Sartem 	prop = NULL;
387*2912Sartem 
388*2912Sartem 	while (fgets(buf, sizeof buf, stdin)) {
389*2912Sartem 		process_property(hal_ctx, buf, &prop);
390*2912Sartem 	}
391*2912Sartem 
392*2912Sartem 	err = add_properties(hal_ctx, &new_dev, prop);
393*2912Sartem 
394*2912Sartem 	prop = free_properties(prop);
395*2912Sartem 
396*2912Sartem 	if (!dev_exists) {
397*2912Sartem 		if (!libhal_device_commit_to_gdl(hal_ctx, new_dev.real_udi, new_dev.udi, &error)) {
398*2912Sartem 			fprintf(stderr, "%s: %s\n", error.name, error.message);
399*2912Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
400*2912Sartem 			free(new_dev.real_udi);
401*2912Sartem 
402*2912Sartem 			err = err ? err : 23;
403*2912Sartem 		}
404*2912Sartem 	}
405*2912Sartem 
406*2912Sartem 	printf("%s: %s\n", dev_exists ? "merged": "created", new_dev.udi);
407*2912Sartem 
408*2912Sartem 	return err;
409*2912Sartem }
410*2912Sartem 
411*2912Sartem 
skip_space(char * s)412*2912Sartem char *skip_space(char *s)
413*2912Sartem {
414*2912Sartem 	while (isspace(*s)) s++;
415*2912Sartem 
416*2912Sartem 	return s;
417*2912Sartem }
418*2912Sartem 
419*2912Sartem 
skip_non_eq_or_space(char * s)420*2912Sartem char *skip_non_eq_or_space(char *s)
421*2912Sartem {
422*2912Sartem 	while (*s && *s != '=' && !isspace(*s))
423*2912Sartem 		s++;
424*2912Sartem 
425*2912Sartem 	return s;
426*2912Sartem }
427*2912Sartem 
428*2912Sartem 
skip_number(char * s)429*2912Sartem char *skip_number(char *s)
430*2912Sartem {
431*2912Sartem 	while (*s == '-' || *s == '+' || *s == '.' || isdigit(*s))
432*2912Sartem 		s++;
433*2912Sartem 
434*2912Sartem 	return s;
435*2912Sartem }
436*2912Sartem 
437*2912Sartem 
skip_nonquote(char * s)438*2912Sartem char *skip_nonquote(char *s)
439*2912Sartem {
440*2912Sartem 	while (*s && *s != '\'')
441*2912Sartem 		s++;
442*2912Sartem 
443*2912Sartem 	return s;
444*2912Sartem }
445*2912Sartem 
446*2912Sartem 
process_property(LibHalContext * hal_ctx,char * buf,lh_prop_t ** prop)447*2912Sartem void process_property(LibHalContext *hal_ctx, char *buf, lh_prop_t **prop)
448*2912Sartem {
449*2912Sartem 	char *s, *s1;
450*2912Sartem 	char *key, *s_val = NULL;
451*2912Sartem 	lh_prop_t *p;
452*2912Sartem 	unsigned len;
453*2912Sartem 	int remove = 0;
454*2912Sartem 
455*2912Sartem 	s = skip_space(buf);
456*2912Sartem 
457*2912Sartem 	if (*s == '-') {
458*2912Sartem 		remove = 1;
459*2912Sartem 		s = skip_space(s + 1);
460*2912Sartem 	}
461*2912Sartem 
462*2912Sartem 	if ((s1 = skip_number(s), s1 != s) && *s1 == ':') s = skip_space(s1 + 1);
463*2912Sartem 
464*2912Sartem 	s = skip_non_eq_or_space(key = s);
465*2912Sartem 	*s++ = 0;
466*2912Sartem 	if (!*key)
467*2912Sartem 		return;
468*2912Sartem 
469*2912Sartem 	if (*key == '#')
470*2912Sartem 		return;
471*2912Sartem 
472*2912Sartem 	if (*s == '=')
473*2912Sartem 		s++;
474*2912Sartem 	s = skip_space(s);
475*2912Sartem 
476*2912Sartem 	if (!*s)
477*2912Sartem 		remove = 1;
478*2912Sartem 
479*2912Sartem 	p = calloc(1, sizeof *p);
480*2912Sartem 	p->type = LIBHAL_PROPERTY_TYPE_INVALID;
481*2912Sartem 	p->key = strdup(key);
482*2912Sartem 
483*2912Sartem 	if (remove) {
484*2912Sartem 		p->next = *prop;
485*2912Sartem 		*prop = p;
486*2912Sartem 		return;
487*2912Sartem 	}
488*2912Sartem 
489*2912Sartem 	if (*s == '\'') {
490*2912Sartem 		s_val = s + 1;
491*2912Sartem 		s = strrchr(s_val, '\'');
492*2912Sartem 		*(s ? s : s_val) = 0;
493*2912Sartem 		p->type = LIBHAL_PROPERTY_TYPE_STRING;
494*2912Sartem 		p->v.str_value = strdup(s_val);
495*2912Sartem 	} else if (*s == '{') {
496*2912Sartem 		s_val = s + 1;
497*2912Sartem 		s1 = strrchr(s_val, '}');
498*2912Sartem 		if (s1) *s1 = 0;
499*2912Sartem 		p->type = LIBHAL_PROPERTY_TYPE_STRLIST;
500*2912Sartem 		len = 0;
501*2912Sartem 		p->v.strlist_value = calloc(1, sizeof *p->v.strlist_value);
502*2912Sartem 		while (*s_val++ == '\'') {
503*2912Sartem 			s = skip_nonquote(s_val);
504*2912Sartem 			if (*s) *s++ = 0;
505*2912Sartem 			p->v.strlist_value = realloc(p->v.strlist_value, (len + 2) * sizeof *p->v.strlist_value);
506*2912Sartem 			p->v.strlist_value[len] = strdup(s_val);
507*2912Sartem 			p->v.strlist_value[++len] = NULL;
508*2912Sartem 			s_val = skip_nonquote(s);
509*2912Sartem 		}
510*2912Sartem 	} else if (!strncmp(s, "true", 4)) {
511*2912Sartem 		s += 4;
512*2912Sartem 		p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
513*2912Sartem 		p->v.bool_value = TRUE;
514*2912Sartem 	} else if (!strncmp(s, "false", 5)) {
515*2912Sartem 		s += 5;
516*2912Sartem 		p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
517*2912Sartem 		p->v.bool_value = FALSE;
518*2912Sartem 	} else if ((s1 = skip_number(s)) != s) {
519*2912Sartem 		if (strstr(s1, "(int)")) {
520*2912Sartem 			*s1++ = 0;
521*2912Sartem 			p->type = LIBHAL_PROPERTY_TYPE_INT32;
522*2912Sartem 			p->v.int_value = strtol(s, NULL, 10);
523*2912Sartem 		} else if (strstr(s1, "(uint64)")) {
524*2912Sartem 			*s1++ = 0;
525*2912Sartem 			p->type = LIBHAL_PROPERTY_TYPE_UINT64;
526*2912Sartem 			p->v.uint64_value = strtoull(s, NULL, 10);
527*2912Sartem 		} else if (strstr(s1, "(double)")) {
528*2912Sartem 			p->type = LIBHAL_PROPERTY_TYPE_DOUBLE;
529*2912Sartem 			p->v.double_value = strtod(s, NULL);
530*2912Sartem 		}
531*2912Sartem 
532*2912Sartem 		s = s1;
533*2912Sartem 	}
534*2912Sartem 
535*2912Sartem 	if (p->type == LIBHAL_PROPERTY_TYPE_INVALID) {
536*2912Sartem 		free(p->key);
537*2912Sartem 		free(p);
538*2912Sartem 	} else {
539*2912Sartem 		p->next = *prop;
540*2912Sartem 		*prop = p;
541*2912Sartem 	}
542*2912Sartem }
543*2912Sartem 
544*2912Sartem 
add_properties(LibHalContext * hal_ctx,new_dev_t * nd,lh_prop_t * prop)545*2912Sartem int add_properties(LibHalContext *hal_ctx, new_dev_t *nd, lh_prop_t *prop)
546*2912Sartem {
547*2912Sartem 	DBusError error;
548*2912Sartem 	lh_prop_t *p;
549*2912Sartem 	char *udi2 = NULL, *udi3 = NULL, **s;
550*2912Sartem 	LibHalPropertyType old_type;
551*2912Sartem 
552*2912Sartem 	dbus_error_init(&error);
553*2912Sartem 
554*2912Sartem 	for(p = prop; p; p = p->next) {
555*2912Sartem 		if (!strcmp(p->key, "udi") && p->type == LIBHAL_PROPERTY_TYPE_STRING) {
556*2912Sartem 			udi2 = p->v.str_value;
557*2912Sartem 			continue;
558*2912Sartem 		}
559*2912Sartem 
560*2912Sartem 		old_type = libhal_device_get_property_type(hal_ctx, nd->real_udi, p->key, &error);
561*2912Sartem 		dbus_error_init(&error);
562*2912Sartem 
563*2912Sartem 		if (old_type != LIBHAL_PROPERTY_TYPE_INVALID &&
564*2912Sartem 		    ( p->type != old_type || p->type == LIBHAL_PROPERTY_TYPE_STRLIST)) {
565*2912Sartem 			if (!libhal_device_remove_property(hal_ctx, nd->real_udi, p->key, &error)) {
566*2912Sartem 				fprintf(stderr, "%s: %s\n", error.name, error.message);
567*2912Sartem 				LIBHAL_FREE_DBUS_ERROR (&error);
568*2912Sartem 				return 41;
569*2912Sartem 			}
570*2912Sartem 		}
571*2912Sartem 
572*2912Sartem 		switch (p->type) {
573*2912Sartem 			case LIBHAL_PROPERTY_TYPE_INVALID:
574*2912Sartem 				break;
575*2912Sartem 			case LIBHAL_PROPERTY_TYPE_BOOLEAN:
576*2912Sartem 				if (!libhal_device_set_property_bool(hal_ctx, nd->real_udi, p->key, p->v.bool_value, &error)) {
577*2912Sartem 					fprintf(stderr, "%s: %s\n", error.name, error.message);
578*2912Sartem 					LIBHAL_FREE_DBUS_ERROR (&error);
579*2912Sartem 					return 42;
580*2912Sartem 				}
581*2912Sartem 				break;
582*2912Sartem 			case LIBHAL_PROPERTY_TYPE_INT32:
583*2912Sartem 				if (!libhal_device_set_property_int(hal_ctx, nd->real_udi, p->key, p->v.int_value, &error)) {
584*2912Sartem 					fprintf(stderr, "%s: %s\n", error.name, error.message);
585*2912Sartem 					LIBHAL_FREE_DBUS_ERROR (&error);
586*2912Sartem 					return 42;
587*2912Sartem 				}
588*2912Sartem 				break;
589*2912Sartem 			case LIBHAL_PROPERTY_TYPE_UINT64:
590*2912Sartem 				if (!libhal_device_set_property_uint64(hal_ctx, nd->real_udi, p->key, p->v.uint64_value, &error)) {
591*2912Sartem 					fprintf(stderr, "%s: %s\n", error.name, error.message);
592*2912Sartem 					LIBHAL_FREE_DBUS_ERROR (&error);
593*2912Sartem 					return 42;
594*2912Sartem 				}
595*2912Sartem 				break;
596*2912Sartem 			case LIBHAL_PROPERTY_TYPE_DOUBLE:
597*2912Sartem 				if (!libhal_device_set_property_double(hal_ctx, nd->real_udi, p->key, p->v.double_value, &error)) {
598*2912Sartem 					fprintf(stderr, "%s: %s\n", error.name, error.message);
599*2912Sartem 					LIBHAL_FREE_DBUS_ERROR (&error);
600*2912Sartem 					return 42;
601*2912Sartem 				}
602*2912Sartem 				break;
603*2912Sartem 			case LIBHAL_PROPERTY_TYPE_STRING:
604*2912Sartem 				if (!strcmp(p->key, "info.udi")) udi3 = p->v.str_value;
605*2912Sartem 				if (!libhal_device_set_property_string(hal_ctx, nd->real_udi, p->key, p->v.str_value, &error)) {
606*2912Sartem 					fprintf(stderr, "%s: %s\n", error.name, error.message);
607*2912Sartem 					LIBHAL_FREE_DBUS_ERROR (&error);
608*2912Sartem 					return 42;
609*2912Sartem 				}
610*2912Sartem 				break;
611*2912Sartem 			case LIBHAL_PROPERTY_TYPE_STRLIST:
612*2912Sartem 				for(s = p->v.strlist_value; *s; s++) {
613*2912Sartem 					if (!libhal_device_property_strlist_append(hal_ctx, nd->real_udi, p->key, *s, &error)) {
614*2912Sartem 						fprintf(stderr, "%s: %s\n", error.name, error.message);
615*2912Sartem 						LIBHAL_FREE_DBUS_ERROR (&error);
616*2912Sartem 						return 42;
617*2912Sartem 					}
618*2912Sartem 				}
619*2912Sartem 				break;
620*2912Sartem 		}
621*2912Sartem 	}
622*2912Sartem 
623*2912Sartem 	if (udi2) udi3 = NULL;
624*2912Sartem 	if (udi3) udi2 = udi3;
625*2912Sartem 
626*2912Sartem 	if (udi2 && !nd->udi)
627*2912Sartem 		nd->udi = strdup(udi2);
628*2912Sartem 
629*2912Sartem 	return 0;
630*2912Sartem }
631*2912Sartem 
632*2912Sartem 
free_properties(lh_prop_t * prop)633*2912Sartem lh_prop_t *free_properties(lh_prop_t *prop)
634*2912Sartem {
635*2912Sartem 	lh_prop_t *next;
636*2912Sartem 	char **s;
637*2912Sartem 
638*2912Sartem 	for(; prop; prop = next) {
639*2912Sartem 		next = prop->next;
640*2912Sartem 
641*2912Sartem 		free(prop->key);
642*2912Sartem 		if (prop->type == LIBHAL_PROPERTY_TYPE_STRING) free(prop->v.str_value);
643*2912Sartem 		if (prop->type == LIBHAL_PROPERTY_TYPE_STRLIST && prop->v.strlist_value) {
644*2912Sartem 			for(s = prop->v.strlist_value; *s; ) free(*s++);
645*2912Sartem 			free(prop->v.strlist_value);
646*2912Sartem 		}
647*2912Sartem 		free(prop);
648*2912Sartem 	}
649*2912Sartem 
650*2912Sartem 	return NULL;
651*2912Sartem }
652