xref: /illumos-gate/usr/src/cmd/hal/tools/hal-device.c (revision f2f489c1)
118c2aff7Sartem /***************************************************************************
218c2aff7Sartem  * CVSID: $Id$
318c2aff7Sartem  *
418c2aff7Sartem  * hal-device.c : add devices HAL
518c2aff7Sartem  *
618c2aff7Sartem  * Copyright (C) 2005 SuSE Linux Gmbh
718c2aff7Sartem  *
818c2aff7Sartem  * Authors:
918c2aff7Sartem  *	Steffen Winterfeldt <snwint@suse.de>
1018c2aff7Sartem  *
1118c2aff7Sartem  * Licensed under the Academic Free License version 2.1
1218c2aff7Sartem  *
1318c2aff7Sartem  * This program is free software; you can redistribute it and/or modify
1418c2aff7Sartem  * it under the terms of the GNU General Public License as published by
1518c2aff7Sartem  * the Free Software Foundation; either version 2 of the License, or
1618c2aff7Sartem  * (at your option) any later version.
1718c2aff7Sartem  *
1818c2aff7Sartem  * This program is distributed in the hope that it will be useful,
1918c2aff7Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
2018c2aff7Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2118c2aff7Sartem  * GNU General Public License for more details.
2218c2aff7Sartem  *
2318c2aff7Sartem  * You should have received a copy of the GNU General Public License
2418c2aff7Sartem  * along with this program; if not, write to the Free Software
2518c2aff7Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2618c2aff7Sartem  *
2718c2aff7Sartem  */
2818c2aff7Sartem 
2918c2aff7Sartem #define _GNU_SOURCE
3018c2aff7Sartem 
3118c2aff7Sartem #ifdef HAVE_CONFIG_H
3218c2aff7Sartem #  include <config.h>
3318c2aff7Sartem #endif
3418c2aff7Sartem 
3518c2aff7Sartem #include <stdio.h>
3618c2aff7Sartem #include <string.h>
3718c2aff7Sartem #include <unistd.h>
3818c2aff7Sartem #include <stdlib.h>
3918c2aff7Sartem #include <ctype.h>
4018c2aff7Sartem #include <inttypes.h>
4118c2aff7Sartem #include <getopt.h>
4218c2aff7Sartem 
4318c2aff7Sartem #ifndef DBUS_API_SUBJECT_TO_CHANGE
4418c2aff7Sartem #define DBUS_API_SUBJECT_TO_CHANGE 1
4518c2aff7Sartem #endif
4618c2aff7Sartem 
4718c2aff7Sartem #include <dbus/dbus.h>
4818c2aff7Sartem #include <libhal.h>
4918c2aff7Sartem 
5018c2aff7Sartem typedef struct {
5118c2aff7Sartem 	char *udi;
5218c2aff7Sartem 	char *real_udi;
5318c2aff7Sartem } new_dev_t;
5418c2aff7Sartem 
5518c2aff7Sartem typedef struct lh_prop_s {
5618c2aff7Sartem 	struct lh_prop_s *next;
5718c2aff7Sartem 	LibHalPropertyType type;
5818c2aff7Sartem 	char *key;
5918c2aff7Sartem 	union {
6018c2aff7Sartem 		char *str_value;
6118c2aff7Sartem 		dbus_int32_t int_value;
6218c2aff7Sartem 		dbus_uint64_t uint64_value;
6318c2aff7Sartem 		double double_value;
6418c2aff7Sartem 		dbus_bool_t bool_value;
6518c2aff7Sartem 		char **strlist_value;
6618c2aff7Sartem 	} v;
6718c2aff7Sartem } lh_prop_t;
6818c2aff7Sartem 
6918c2aff7Sartem 
7018c2aff7Sartem void help(void);
7118c2aff7Sartem int dump_devices(LibHalContext *hal_ctx, char *arg);
7218c2aff7Sartem int remove_udi(LibHalContext *hal_ctx, char *arg);
7318c2aff7Sartem int add_udi(LibHalContext *hal_ctx, char *arg);
7418c2aff7Sartem void process_property(LibHalContext *hal_ctx, char *buf, lh_prop_t **prop);
7518c2aff7Sartem int add_properties(LibHalContext *hal_ctx, new_dev_t *nd, lh_prop_t *prop);
7618c2aff7Sartem lh_prop_t *free_properties(lh_prop_t *prop);
7718c2aff7Sartem static char *skip_space(char *s);
7818c2aff7Sartem static char *skip_non_eq_or_space(char *s);
7918c2aff7Sartem static char *skip_number(char *s);
8018c2aff7Sartem static char *skip_nonquote(char *s);
8118c2aff7Sartem 
8218c2aff7Sartem 
8318c2aff7Sartem new_dev_t new_dev;
8418c2aff7Sartem 
8518c2aff7Sartem struct {
8618c2aff7Sartem 	unsigned remove:1;
8718c2aff7Sartem 	unsigned add:1;
8818c2aff7Sartem 	unsigned list:1;
8918c2aff7Sartem 	char *udi;
9018c2aff7Sartem } opt;
9118c2aff7Sartem 
9218c2aff7Sartem struct option options[] = {
9318c2aff7Sartem 	{ "remove", 1, NULL, 'r' },
9418c2aff7Sartem 	{ "add", 1, NULL, 'a' },
9518c2aff7Sartem 	{ "help", 0, NULL, 'h' },
9618c2aff7Sartem 	{ 0, 0, 0, 0 }
9718c2aff7Sartem };
9818c2aff7Sartem 
9918c2aff7Sartem 
main(int argc,char ** argv)10018c2aff7Sartem int main(int argc, char **argv)
10118c2aff7Sartem {
10218c2aff7Sartem 	DBusError error;
10318c2aff7Sartem 	DBusConnection *conn;
10418c2aff7Sartem 	LibHalContext *hal_ctx;
10518c2aff7Sartem 	int i, err;
10618c2aff7Sartem 
10718c2aff7Sartem 	opterr = 0;
10818c2aff7Sartem 	opt.list = 1;
10918c2aff7Sartem 
11018c2aff7Sartem 	while ((i = getopt_long(argc, argv, "a:hr:", options, NULL)) != -1) {
11118c2aff7Sartem 		switch (i) {
11218c2aff7Sartem 		case 'a':
11318c2aff7Sartem 			opt.add = 1;
11418c2aff7Sartem 			opt.list = 0;
11518c2aff7Sartem 			opt.udi = optarg;
11618c2aff7Sartem 			break;
11718c2aff7Sartem 		case 'r':
11818c2aff7Sartem 			opt.remove = 1;
11918c2aff7Sartem 			opt.list = 0;
12018c2aff7Sartem 			opt.udi = optarg;
12118c2aff7Sartem 			break;
12218c2aff7Sartem 		case 'h':
12318c2aff7Sartem 			help();
12418c2aff7Sartem 			return 0;
12518c2aff7Sartem 		default:
12618c2aff7Sartem 			help();
12718c2aff7Sartem 			return 1;
12818c2aff7Sartem 		}
12918c2aff7Sartem 	}
13018c2aff7Sartem 
13118c2aff7Sartem 	dbus_error_init(&error);
13218c2aff7Sartem 
13318c2aff7Sartem 	if (!(conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
13418c2aff7Sartem 		fprintf(stderr, "error: dbus_bus_get: %s: %s\n", error.name, error.message);
13518c2aff7Sartem 		LIBHAL_FREE_DBUS_ERROR (&error);
13618c2aff7Sartem 		return 2;
13718c2aff7Sartem 	}
13818c2aff7Sartem 
13918c2aff7Sartem 	/* fprintf(stderr, "connected to: %s\n", dbus_bus_get_unique_name(conn)); */
14018c2aff7Sartem 	if (!(hal_ctx = libhal_ctx_new())) return 3;
14118c2aff7Sartem 	if (!libhal_ctx_set_dbus_connection(hal_ctx, conn)) return 4;
14218c2aff7Sartem 	if (!libhal_ctx_init(hal_ctx, &error)) {
14318c2aff7Sartem 		if (dbus_error_is_set(&error)) {
14418c2aff7Sartem 			fprintf (stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message);
14518c2aff7Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
14618c2aff7Sartem 		}
14718c2aff7Sartem 		fprintf (stderr, "Could not initialise connection to hald.\n"
14818c2aff7Sartem 				 "Normally this means the HAL daemon (hald) is not running or not ready.\n");
14918c2aff7Sartem 		return 5;
15018c2aff7Sartem 	}
15118c2aff7Sartem 
15218c2aff7Sartem 	err = 0;
15318c2aff7Sartem 	if (opt.list)
15418c2aff7Sartem 		err = dump_devices(hal_ctx, argv[optind]);
15518c2aff7Sartem 	else if (opt.remove)
15618c2aff7Sartem 		err = remove_udi(hal_ctx, opt.udi);
15718c2aff7Sartem 	else if (opt.add)
15818c2aff7Sartem 		err = add_udi(hal_ctx, opt.udi);
15918c2aff7Sartem 	else
16018c2aff7Sartem 		err = 6;
16118c2aff7Sartem 
16218c2aff7Sartem 	libhal_ctx_shutdown(hal_ctx, &error);
16318c2aff7Sartem 	libhal_ctx_free(hal_ctx);
16418c2aff7Sartem 	dbus_connection_unref(conn);
16518c2aff7Sartem 	dbus_error_free(&error);
16618c2aff7Sartem 
16718c2aff7Sartem 	return err;
16818c2aff7Sartem }
16918c2aff7Sartem 
17018c2aff7Sartem 
help()17118c2aff7Sartem void help()
17218c2aff7Sartem {
17318c2aff7Sartem 	fprintf(stderr,
17418c2aff7Sartem 		"usage: hal-device [--help] [--add udi] [--remove udi] [udi]\n"
17518c2aff7Sartem 		"Create, remove, or show HAL device. If no udi is given, shows all devices.\n"
17618c2aff7Sartem 		"If udi doesn't start with a '/', '/org/freedesktop/Hal/devices/' is prepended.\n"
17718c2aff7Sartem 		"  -a, --add udi\t\tAdd new device.\n"
17818c2aff7Sartem 		"  \t\t\tReads property list in 'lshal' syntax from stdin.\n"
17918c2aff7Sartem 		"  -r, --remove udi\tRemove device.\n"
18018c2aff7Sartem 		"  -h, --help\t\tShow this text.\n"
18118c2aff7Sartem 	);
18218c2aff7Sartem }
18318c2aff7Sartem 
18418c2aff7Sartem 
18518c2aff7Sartem /*
18618c2aff7Sartem  * Dump all devices.
18718c2aff7Sartem  */
dump_devices(LibHalContext * hal_ctx,char * arg)18818c2aff7Sartem int dump_devices(LibHalContext *hal_ctx, char *arg)
18918c2aff7Sartem {
19018c2aff7Sartem 	int i;
19118c2aff7Sartem 	int num_devices;
19218c2aff7Sartem 	char **device_names;
19318c2aff7Sartem 	DBusError error;
19418c2aff7Sartem 	char *udi = NULL;
19518c2aff7Sartem 
19618c2aff7Sartem 	if (arg) {
19718c2aff7Sartem 		if (*arg == '/') {
19818c2aff7Sartem 			udi = arg;
19918c2aff7Sartem 		} else {
20018c2aff7Sartem #ifdef HAVE_ASPRINTF
20118c2aff7Sartem 			asprintf(&udi, "/org/freedesktop/Hal/devices/%s", arg);
20218c2aff7Sartem #else
20318c2aff7Sartem 			udi = calloc(1, sizeof ("/org/freedesktop/Hal/devices/%s") + strlen(arg));
20418c2aff7Sartem 			sprintf(udi, "/org/freedesktop/Hal/devices/%s", arg);
20518c2aff7Sartem 
20618c2aff7Sartem #endif
20718c2aff7Sartem 		}
20818c2aff7Sartem 	}
20918c2aff7Sartem 
21018c2aff7Sartem 	dbus_error_init(&error);
21118c2aff7Sartem 
21218c2aff7Sartem 	if (!udi) {
21318c2aff7Sartem 		if (!(device_names = libhal_get_all_devices(hal_ctx, &num_devices, &error))) {
21418c2aff7Sartem 			fprintf(stderr, "Empty HAL device list.\n");
21518c2aff7Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
21618c2aff7Sartem 			return 31;
21718c2aff7Sartem 		}
21818c2aff7Sartem 	} else {
21918c2aff7Sartem 		device_names = calloc(2, sizeof *device_names);
22018c2aff7Sartem 		device_names[0] = strdup(udi);
22118c2aff7Sartem 		num_devices = 1;
22218c2aff7Sartem 	}
22318c2aff7Sartem 
22418c2aff7Sartem 	for(i = 0; i < num_devices; i++) {
22518c2aff7Sartem 		LibHalPropertySet *props;
22618c2aff7Sartem 		LibHalPropertySetIterator it;
22718c2aff7Sartem 		int type;
22818c2aff7Sartem 
22918c2aff7Sartem 		if (!(props = libhal_device_get_all_properties(hal_ctx, device_names[i], &error))) {
23018c2aff7Sartem 			fprintf(stderr, "%s: %s\n", error.name, error.message);
23118c2aff7Sartem 			dbus_error_init(&error);
23218c2aff7Sartem 			continue;
23318c2aff7Sartem 		}
23418c2aff7Sartem 
23518c2aff7Sartem 		if (!udi)
23618c2aff7Sartem 			printf("%d: ", i);
23718c2aff7Sartem 		printf("udi = '%s'\n", device_names[i]);
23818c2aff7Sartem 
23918c2aff7Sartem 		for(libhal_psi_init(&it, props); libhal_psi_has_more(&it); libhal_psi_next(&it)) {
24018c2aff7Sartem 			type = libhal_psi_get_type(&it);
24118c2aff7Sartem 			switch (type) {
24218c2aff7Sartem 			case LIBHAL_PROPERTY_TYPE_STRING:
24318c2aff7Sartem 				printf("  %s = '%s'  (string)\n",
24418c2aff7Sartem 					libhal_psi_get_key(&it),
24518c2aff7Sartem 					libhal_psi_get_string(&it)
24618c2aff7Sartem 				);
24718c2aff7Sartem 				break;
24818c2aff7Sartem 			case LIBHAL_PROPERTY_TYPE_INT32:
24918c2aff7Sartem 				printf("  %s = %d  (0x%x)  (int)\n",
25018c2aff7Sartem 					libhal_psi_get_key(&it),
25118c2aff7Sartem 					libhal_psi_get_int(&it),
25218c2aff7Sartem 					libhal_psi_get_int(&it)
25318c2aff7Sartem 				);
25418c2aff7Sartem 				break;
25518c2aff7Sartem 			case LIBHAL_PROPERTY_TYPE_UINT64:
25618c2aff7Sartem 				printf("  %s = %lld  (0x%llx)  (uint64)\n",
25718c2aff7Sartem 					libhal_psi_get_key(&it),
25818c2aff7Sartem 					(long long) libhal_psi_get_uint64(&it),
25918c2aff7Sartem 					(long long) libhal_psi_get_uint64(&it)
26018c2aff7Sartem 				);
26118c2aff7Sartem 				break;
26218c2aff7Sartem 			case LIBHAL_PROPERTY_TYPE_DOUBLE:
26318c2aff7Sartem 				printf("  %s = %g  (double)\n",
26418c2aff7Sartem 					libhal_psi_get_key(&it),
26518c2aff7Sartem 					libhal_psi_get_double(&it)
26618c2aff7Sartem 				);
26718c2aff7Sartem 				break;
26818c2aff7Sartem 			case LIBHAL_PROPERTY_TYPE_BOOLEAN:
26918c2aff7Sartem 				printf("  %s = %s  (bool)\n",
27018c2aff7Sartem 					libhal_psi_get_key(&it),
27118c2aff7Sartem 					libhal_psi_get_bool(&it) ? "true" : "false"
27218c2aff7Sartem 				);
27318c2aff7Sartem 				break;
27418c2aff7Sartem 			case LIBHAL_PROPERTY_TYPE_STRLIST:
27518c2aff7Sartem 				{
27618c2aff7Sartem 					char **strlist;
27718c2aff7Sartem 
27818c2aff7Sartem 					printf ("  %s = { ", libhal_psi_get_key(&it));
27918c2aff7Sartem 					strlist = libhal_psi_get_strlist(&it);
28018c2aff7Sartem 					while (*strlist) {
28118c2aff7Sartem 						printf("'%s'%s", *strlist, strlist[1] ? ", " : "");
28218c2aff7Sartem 						strlist++;
28318c2aff7Sartem 					}
28418c2aff7Sartem 					printf(" } (string list)\n");
28518c2aff7Sartem 				}
28618c2aff7Sartem 				break;
28718c2aff7Sartem 			default:
28818c2aff7Sartem 				printf("Unknown type %d = 0x%02x\n", type, type);
28918c2aff7Sartem 				break;
29018c2aff7Sartem 			}
29118c2aff7Sartem 		}
29218c2aff7Sartem 
29318c2aff7Sartem 		libhal_free_property_set(props);
29418c2aff7Sartem 		printf("\n");
29518c2aff7Sartem 	}
29618c2aff7Sartem 
29718c2aff7Sartem 	libhal_free_string_array(device_names);
29818c2aff7Sartem 	dbus_error_free(&error);
29918c2aff7Sartem 
30018c2aff7Sartem 	return 0;
30118c2aff7Sartem }
30218c2aff7Sartem 
30318c2aff7Sartem 
remove_udi(LibHalContext * hal_ctx,char * arg)30418c2aff7Sartem int remove_udi(LibHalContext *hal_ctx, char *arg)
30518c2aff7Sartem {
30618c2aff7Sartem 	DBusError error;
30718c2aff7Sartem 	char *udi;
30818c2aff7Sartem 
30918c2aff7Sartem 	if (!arg) return 11;
31018c2aff7Sartem 
31118c2aff7Sartem 	if (*arg == '/') {
31218c2aff7Sartem 		udi = arg;
31318c2aff7Sartem 	} else {
31418c2aff7Sartem #ifdef HAVE_ASPRINTF
31518c2aff7Sartem 		asprintf(&udi, "/org/freedesktop/Hal/devices/%s", arg);
31618c2aff7Sartem #else
31718c2aff7Sartem 		udi = calloc(1, sizeof ("/org/freedesktop/Hal/devices/%s") + strlen(arg));
31818c2aff7Sartem 		sprintf(udi, "/org/freedesktop/Hal/devices/%s", arg);
31918c2aff7Sartem #endif
32018c2aff7Sartem 
32118c2aff7Sartem 	}
32218c2aff7Sartem 
32318c2aff7Sartem 	dbus_error_init(&error);
32418c2aff7Sartem 
32518c2aff7Sartem 	if (opt.remove) {
32618c2aff7Sartem 		if (!libhal_remove_device(hal_ctx, udi, &error)) {
32718c2aff7Sartem 			fprintf(stderr, "%s: %s\n", error.name, error.message);
32818c2aff7Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
32918c2aff7Sartem 			return 12;
33018c2aff7Sartem 		}
33118c2aff7Sartem 
33218c2aff7Sartem 		fprintf(stderr, "removed: %s\n", udi);
33318c2aff7Sartem 		return 13;
33418c2aff7Sartem 	}
33518c2aff7Sartem 
33618c2aff7Sartem 	return 0;
33718c2aff7Sartem }
33818c2aff7Sartem 
33918c2aff7Sartem 
add_udi(LibHalContext * hal_ctx,char * arg)34018c2aff7Sartem int add_udi(LibHalContext *hal_ctx, char *arg)
34118c2aff7Sartem {
34218c2aff7Sartem 	DBusError error;
34318c2aff7Sartem 	dbus_bool_t dev_exists = FALSE;
34418c2aff7Sartem 	char *udi = NULL, buf[1024];
34518c2aff7Sartem 	lh_prop_t *prop;
34618c2aff7Sartem 	int err;
34718c2aff7Sartem 
34818c2aff7Sartem 	if (!arg)
34918c2aff7Sartem 		return 21;
35018c2aff7Sartem 
35118c2aff7Sartem 	if (*arg == '/') {
35218c2aff7Sartem 		udi = arg;
35318c2aff7Sartem 	} else {
35418c2aff7Sartem #ifdef HAVE_ASPRINTF
35518c2aff7Sartem 		asprintf(&udi, "/org/freedesktop/Hal/devices/%s", arg);
35618c2aff7Sartem #else
35718c2aff7Sartem 		udi = calloc(1, sizeof ("/org/freedesktop/Hal/devices/%s") + strlen(arg));
35818c2aff7Sartem 		sprintf(udi, "/org/freedesktop/Hal/devices/%s", arg);
35918c2aff7Sartem #endif
36018c2aff7Sartem 	}
36118c2aff7Sartem 
36218c2aff7Sartem 	if (udi)
36318c2aff7Sartem 		new_dev.udi = strdup(udi);
36418c2aff7Sartem 
36518c2aff7Sartem 	dbus_error_init(&error);
36618c2aff7Sartem 
36718c2aff7Sartem 	if (udi)
36818c2aff7Sartem 		dev_exists = libhal_device_exists(hal_ctx, udi, &error);
36918c2aff7Sartem 
37018c2aff7Sartem 	if (dev_exists) {
37118c2aff7Sartem 		new_dev.real_udi = strdup(new_dev.udi);
37218c2aff7Sartem 	} else {
37318c2aff7Sartem 		new_dev.real_udi = libhal_new_device(hal_ctx, &error);
37418c2aff7Sartem 
37518c2aff7Sartem 		if (!new_dev.real_udi) {
37618c2aff7Sartem 			fprintf(stderr, "%s: %s\n", error.name, error.message);
37718c2aff7Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
37818c2aff7Sartem 			free(new_dev.real_udi);
37918c2aff7Sartem 
38018c2aff7Sartem 			return 22;
38118c2aff7Sartem 		}
38218c2aff7Sartem 
38318c2aff7Sartem 		printf("tmp udi: %s\n", new_dev.real_udi);
38418c2aff7Sartem 	}
38518c2aff7Sartem 
38618c2aff7Sartem 	prop = NULL;
38718c2aff7Sartem 
38818c2aff7Sartem 	while (fgets(buf, sizeof buf, stdin)) {
38918c2aff7Sartem 		process_property(hal_ctx, buf, &prop);
39018c2aff7Sartem 	}
39118c2aff7Sartem 
39218c2aff7Sartem 	err = add_properties(hal_ctx, &new_dev, prop);
39318c2aff7Sartem 
39418c2aff7Sartem 	prop = free_properties(prop);
39518c2aff7Sartem 
39618c2aff7Sartem 	if (!dev_exists) {
39718c2aff7Sartem 		if (!libhal_device_commit_to_gdl(hal_ctx, new_dev.real_udi, new_dev.udi, &error)) {
39818c2aff7Sartem 			fprintf(stderr, "%s: %s\n", error.name, error.message);
39918c2aff7Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
40018c2aff7Sartem 			free(new_dev.real_udi);
40118c2aff7Sartem 
40218c2aff7Sartem 			err = err ? err : 23;
40318c2aff7Sartem 		}
40418c2aff7Sartem 	}
40518c2aff7Sartem 
40618c2aff7Sartem 	printf("%s: %s\n", dev_exists ? "merged": "created", new_dev.udi);
40718c2aff7Sartem 
40818c2aff7Sartem 	return err;
40918c2aff7Sartem }
41018c2aff7Sartem 
41118c2aff7Sartem 
skip_space(char * s)41218c2aff7Sartem char *skip_space(char *s)
41318c2aff7Sartem {
41418c2aff7Sartem 	while (isspace(*s)) s++;
41518c2aff7Sartem 
41618c2aff7Sartem 	return s;
41718c2aff7Sartem }
41818c2aff7Sartem 
41918c2aff7Sartem 
skip_non_eq_or_space(char * s)42018c2aff7Sartem char *skip_non_eq_or_space(char *s)
42118c2aff7Sartem {
42218c2aff7Sartem 	while (*s && *s != '=' && !isspace(*s))
42318c2aff7Sartem 		s++;
42418c2aff7Sartem 
42518c2aff7Sartem 	return s;
42618c2aff7Sartem }
42718c2aff7Sartem 
42818c2aff7Sartem 
skip_number(char * s)42918c2aff7Sartem char *skip_number(char *s)
43018c2aff7Sartem {
43118c2aff7Sartem 	while (*s == '-' || *s == '+' || *s == '.' || isdigit(*s))
43218c2aff7Sartem 		s++;
43318c2aff7Sartem 
43418c2aff7Sartem 	return s;
43518c2aff7Sartem }
43618c2aff7Sartem 
43718c2aff7Sartem 
skip_nonquote(char * s)43818c2aff7Sartem char *skip_nonquote(char *s)
43918c2aff7Sartem {
44018c2aff7Sartem 	while (*s && *s != '\'')
44118c2aff7Sartem 		s++;
44218c2aff7Sartem 
44318c2aff7Sartem 	return s;
44418c2aff7Sartem }
44518c2aff7Sartem 
44618c2aff7Sartem 
process_property(LibHalContext * hal_ctx,char * buf,lh_prop_t ** prop)44718c2aff7Sartem void process_property(LibHalContext *hal_ctx, char *buf, lh_prop_t **prop)
44818c2aff7Sartem {
44918c2aff7Sartem 	char *s, *s1;
45018c2aff7Sartem 	char *key, *s_val = NULL;
45118c2aff7Sartem 	lh_prop_t *p;
45218c2aff7Sartem 	unsigned len;
45318c2aff7Sartem 	int remove = 0;
45418c2aff7Sartem 
45518c2aff7Sartem 	s = skip_space(buf);
45618c2aff7Sartem 
45718c2aff7Sartem 	if (*s == '-') {
45818c2aff7Sartem 		remove = 1;
45918c2aff7Sartem 		s = skip_space(s + 1);
46018c2aff7Sartem 	}
46118c2aff7Sartem 
46218c2aff7Sartem 	if ((s1 = skip_number(s), s1 != s) && *s1 == ':') s = skip_space(s1 + 1);
46318c2aff7Sartem 
46418c2aff7Sartem 	s = skip_non_eq_or_space(key = s);
46518c2aff7Sartem 	*s++ = 0;
46618c2aff7Sartem 	if (!*key)
46718c2aff7Sartem 		return;
46818c2aff7Sartem 
46918c2aff7Sartem 	if (*key == '#')
47018c2aff7Sartem 		return;
47118c2aff7Sartem 
47218c2aff7Sartem 	if (*s == '=')
47318c2aff7Sartem 		s++;
47418c2aff7Sartem 	s = skip_space(s);
47518c2aff7Sartem 
47618c2aff7Sartem 	if (!*s)
47718c2aff7Sartem 		remove = 1;
47818c2aff7Sartem 
47918c2aff7Sartem 	p = calloc(1, sizeof *p);
48018c2aff7Sartem 	p->type = LIBHAL_PROPERTY_TYPE_INVALID;
48118c2aff7Sartem 	p->key = strdup(key);
48218c2aff7Sartem 
48318c2aff7Sartem 	if (remove) {
48418c2aff7Sartem 		p->next = *prop;
48518c2aff7Sartem 		*prop = p;
48618c2aff7Sartem 		return;
48718c2aff7Sartem 	}
48818c2aff7Sartem 
48918c2aff7Sartem 	if (*s == '\'') {
49018c2aff7Sartem 		s_val = s + 1;
49118c2aff7Sartem 		s = strrchr(s_val, '\'');
49218c2aff7Sartem 		*(s ? s : s_val) = 0;
49318c2aff7Sartem 		p->type = LIBHAL_PROPERTY_TYPE_STRING;
49418c2aff7Sartem 		p->v.str_value = strdup(s_val);
49518c2aff7Sartem 	} else if (*s == '{') {
49618c2aff7Sartem 		s_val = s + 1;
49718c2aff7Sartem 		s1 = strrchr(s_val, '}');
49818c2aff7Sartem 		if (s1) *s1 = 0;
49918c2aff7Sartem 		p->type = LIBHAL_PROPERTY_TYPE_STRLIST;
50018c2aff7Sartem 		len = 0;
50118c2aff7Sartem 		p->v.strlist_value = calloc(1, sizeof *p->v.strlist_value);
50218c2aff7Sartem 		while (*s_val++ == '\'') {
50318c2aff7Sartem 			s = skip_nonquote(s_val);
50418c2aff7Sartem 			if (*s) *s++ = 0;
50518c2aff7Sartem 			p->v.strlist_value = realloc(p->v.strlist_value, (len + 2) * sizeof *p->v.strlist_value);
50618c2aff7Sartem 			p->v.strlist_value[len] = strdup(s_val);
50718c2aff7Sartem 			p->v.strlist_value[++len] = NULL;
50818c2aff7Sartem 			s_val = skip_nonquote(s);
50918c2aff7Sartem 		}
51018c2aff7Sartem 	} else if (!strncmp(s, "true", 4)) {
51118c2aff7Sartem 		s += 4;
51218c2aff7Sartem 		p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
51318c2aff7Sartem 		p->v.bool_value = TRUE;
51418c2aff7Sartem 	} else if (!strncmp(s, "false", 5)) {
51518c2aff7Sartem 		s += 5;
51618c2aff7Sartem 		p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
51718c2aff7Sartem 		p->v.bool_value = FALSE;
51818c2aff7Sartem 	} else if ((s1 = skip_number(s)) != s) {
51918c2aff7Sartem 		if (strstr(s1, "(int)")) {
52018c2aff7Sartem 			*s1++ = 0;
52118c2aff7Sartem 			p->type = LIBHAL_PROPERTY_TYPE_INT32;
52218c2aff7Sartem 			p->v.int_value = strtol(s, NULL, 10);
52318c2aff7Sartem 		} else if (strstr(s1, "(uint64)")) {
52418c2aff7Sartem 			*s1++ = 0;
52518c2aff7Sartem 			p->type = LIBHAL_PROPERTY_TYPE_UINT64;
52618c2aff7Sartem 			p->v.uint64_value = strtoull(s, NULL, 10);
52718c2aff7Sartem 		} else if (strstr(s1, "(double)")) {
52818c2aff7Sartem 			p->type = LIBHAL_PROPERTY_TYPE_DOUBLE;
52918c2aff7Sartem 			p->v.double_value = strtod(s, NULL);
53018c2aff7Sartem 		}
53118c2aff7Sartem 
53218c2aff7Sartem 		s = s1;
53318c2aff7Sartem 	}
53418c2aff7Sartem 
53518c2aff7Sartem 	if (p->type == LIBHAL_PROPERTY_TYPE_INVALID) {
53618c2aff7Sartem 		free(p->key);
53718c2aff7Sartem 		free(p);
53818c2aff7Sartem 	} else {
53918c2aff7Sartem 		p->next = *prop;
54018c2aff7Sartem 		*prop = p;
54118c2aff7Sartem 	}
54218c2aff7Sartem }
54318c2aff7Sartem 
54418c2aff7Sartem 
add_properties(LibHalContext * hal_ctx,new_dev_t * nd,lh_prop_t * prop)54518c2aff7Sartem int add_properties(LibHalContext *hal_ctx, new_dev_t *nd, lh_prop_t *prop)
54618c2aff7Sartem {
54718c2aff7Sartem 	DBusError error;
54818c2aff7Sartem 	lh_prop_t *p;
54918c2aff7Sartem 	char *udi2 = NULL, *udi3 = NULL, **s;
55018c2aff7Sartem 	LibHalPropertyType old_type;
55118c2aff7Sartem 
55218c2aff7Sartem 	dbus_error_init(&error);
55318c2aff7Sartem 
55418c2aff7Sartem 	for(p = prop; p; p = p->next) {
55518c2aff7Sartem 		if (!strcmp(p->key, "udi") && p->type == LIBHAL_PROPERTY_TYPE_STRING) {
55618c2aff7Sartem 			udi2 = p->v.str_value;
55718c2aff7Sartem 			continue;
55818c2aff7Sartem 		}
55918c2aff7Sartem 
56018c2aff7Sartem 		old_type = libhal_device_get_property_type(hal_ctx, nd->real_udi, p->key, &error);
56118c2aff7Sartem 		dbus_error_init(&error);
56218c2aff7Sartem 
56318c2aff7Sartem 		if (old_type != LIBHAL_PROPERTY_TYPE_INVALID &&
56418c2aff7Sartem 		    ( p->type != old_type || p->type == LIBHAL_PROPERTY_TYPE_STRLIST)) {
56518c2aff7Sartem 			if (!libhal_device_remove_property(hal_ctx, nd->real_udi, p->key, &error)) {
56618c2aff7Sartem 				fprintf(stderr, "%s: %s\n", error.name, error.message);
56718c2aff7Sartem 				LIBHAL_FREE_DBUS_ERROR (&error);
56818c2aff7Sartem 				return 41;
56918c2aff7Sartem 			}
57018c2aff7Sartem 		}
57118c2aff7Sartem 
57218c2aff7Sartem 		switch (p->type) {
57318c2aff7Sartem 			case LIBHAL_PROPERTY_TYPE_BOOLEAN:
57418c2aff7Sartem 				if (!libhal_device_set_property_bool(hal_ctx, nd->real_udi, p->key, p->v.bool_value, &error)) {
57518c2aff7Sartem 					fprintf(stderr, "%s: %s\n", error.name, error.message);
57618c2aff7Sartem 					LIBHAL_FREE_DBUS_ERROR (&error);
57718c2aff7Sartem 					return 42;
57818c2aff7Sartem 				}
57918c2aff7Sartem 				break;
58018c2aff7Sartem 			case LIBHAL_PROPERTY_TYPE_INT32:
58118c2aff7Sartem 				if (!libhal_device_set_property_int(hal_ctx, nd->real_udi, p->key, p->v.int_value, &error)) {
58218c2aff7Sartem 					fprintf(stderr, "%s: %s\n", error.name, error.message);
58318c2aff7Sartem 					LIBHAL_FREE_DBUS_ERROR (&error);
58418c2aff7Sartem 					return 42;
58518c2aff7Sartem 				}
58618c2aff7Sartem 				break;
58718c2aff7Sartem 			case LIBHAL_PROPERTY_TYPE_UINT64:
58818c2aff7Sartem 				if (!libhal_device_set_property_uint64(hal_ctx, nd->real_udi, p->key, p->v.uint64_value, &error)) {
58918c2aff7Sartem 					fprintf(stderr, "%s: %s\n", error.name, error.message);
59018c2aff7Sartem 					LIBHAL_FREE_DBUS_ERROR (&error);
59118c2aff7Sartem 					return 42;
59218c2aff7Sartem 				}
59318c2aff7Sartem 				break;
59418c2aff7Sartem 			case LIBHAL_PROPERTY_TYPE_DOUBLE:
59518c2aff7Sartem 				if (!libhal_device_set_property_double(hal_ctx, nd->real_udi, p->key, p->v.double_value, &error)) {
59618c2aff7Sartem 					fprintf(stderr, "%s: %s\n", error.name, error.message);
59718c2aff7Sartem 					LIBHAL_FREE_DBUS_ERROR (&error);
59818c2aff7Sartem 					return 42;
59918c2aff7Sartem 				}
60018c2aff7Sartem 				break;
60118c2aff7Sartem 			case LIBHAL_PROPERTY_TYPE_STRING:
60218c2aff7Sartem 				if (!strcmp(p->key, "info.udi")) udi3 = p->v.str_value;
60318c2aff7Sartem 				if (!libhal_device_set_property_string(hal_ctx, nd->real_udi, p->key, p->v.str_value, &error)) {
60418c2aff7Sartem 					fprintf(stderr, "%s: %s\n", error.name, error.message);
60518c2aff7Sartem 					LIBHAL_FREE_DBUS_ERROR (&error);
60618c2aff7Sartem 					return 42;
60718c2aff7Sartem 				}
60818c2aff7Sartem 				break;
60918c2aff7Sartem 			case LIBHAL_PROPERTY_TYPE_STRLIST:
61018c2aff7Sartem 				for(s = p->v.strlist_value; *s; s++) {
61118c2aff7Sartem 					if (!libhal_device_property_strlist_append(hal_ctx, nd->real_udi, p->key, *s, &error)) {
61218c2aff7Sartem 						fprintf(stderr, "%s: %s\n", error.name, error.message);
61318c2aff7Sartem 						LIBHAL_FREE_DBUS_ERROR (&error);
61418c2aff7Sartem 						return 42;
61518c2aff7Sartem 					}
61618c2aff7Sartem 				}
61718c2aff7Sartem 				break;
618*f2f489c1SToomas Soome 			default:
619*f2f489c1SToomas Soome 				break;
62018c2aff7Sartem 		}
62118c2aff7Sartem 	}
62218c2aff7Sartem 
62318c2aff7Sartem 	if (udi2) udi3 = NULL;
62418c2aff7Sartem 	if (udi3) udi2 = udi3;
62518c2aff7Sartem 
62618c2aff7Sartem 	if (udi2 && !nd->udi)
62718c2aff7Sartem 		nd->udi = strdup(udi2);
62818c2aff7Sartem 
62918c2aff7Sartem 	return 0;
63018c2aff7Sartem }
63118c2aff7Sartem 
63218c2aff7Sartem 
free_properties(lh_prop_t * prop)63318c2aff7Sartem lh_prop_t *free_properties(lh_prop_t *prop)
63418c2aff7Sartem {
63518c2aff7Sartem 	lh_prop_t *next;
63618c2aff7Sartem 	char **s;
63718c2aff7Sartem 
63818c2aff7Sartem 	for(; prop; prop = next) {
63918c2aff7Sartem 		next = prop->next;
64018c2aff7Sartem 
64118c2aff7Sartem 		free(prop->key);
64218c2aff7Sartem 		if (prop->type == LIBHAL_PROPERTY_TYPE_STRING) free(prop->v.str_value);
64318c2aff7Sartem 		if (prop->type == LIBHAL_PROPERTY_TYPE_STRLIST && prop->v.strlist_value) {
64418c2aff7Sartem 			for(s = prop->v.strlist_value; *s; ) free(*s++);
64518c2aff7Sartem 			free(prop->v.strlist_value);
64618c2aff7Sartem 		}
64718c2aff7Sartem 		free(prop);
64818c2aff7Sartem 	}
64918c2aff7Sartem 
65018c2aff7Sartem 	return NULL;
65118c2aff7Sartem }
652