1/***************************************************************************
2 * CVSID: $Id$
3 *
4 * hal_get_property.c : Get property for a device
5 *
6 * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
7 *
8 * Licensed under the Academic Free License version 2.1
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23 *
24 **************************************************************************/
25
26
27#ifdef HAVE_CONFIG_H
28#  include <config.h>
29#endif
30
31#include <stdio.h>
32#include <string.h>
33#include <unistd.h>
34#include <getopt.h>
35
36#include <libhal.h>
37
38/**
39 * @defgroup HalGetProperty  Get HAL device property
40 * @ingroup HalMisc
41 *
42 * @brief A commandline tool getting a property of a device. Uses libhal
43 *
44 * @{
45 */
46
47static LibHalContext *hal_ctx;
48
49/** Print out program usage.
50 *
51 *  @param  argc                Number of arguments given to program
52 *  @param  argv                Arguments given to program
53 */
54static void
55usage (int argc, char *argv[])
56{
57	fprintf (stderr,
58 "\n"
59 "usage : hal-get-property --udi <udi> --key <key> \n"
60 "                        [--hex] [--help] [--verbose] [--version]\n");
61	fprintf (stderr,
62 "\n"
63 "        --udi            Unique Device Id\n"
64 "        --key            Key of the property to get\n"
65 "        --hex            Show integer values in hex (without leading 0x)\n"
66 "        --verbose        Be verbose\n"
67 "        --version        Show version and exit\n"
68 "        --help           Show this information and exit\n"
69 "\n"
70 "This program retrieves a property from a device. If the property exist\n"
71 "then it is printed on stdout and this program exits with exit code 0.\n"
72 "On error, the program exits with an exit code different from 0\n"
73 "\n");
74}
75
76/** Entry point
77 *
78 *  @param  argc                Number of arguments given to program
79 *  @param  argv                Arguments given to program
80 *  @return                     Return code
81 */
82int
83main (int argc, char *argv[])
84{
85	char *udi = NULL;
86	char *key = NULL;
87	int type;
88	dbus_bool_t is_hex = FALSE;
89	dbus_bool_t is_verbose = FALSE;
90	dbus_bool_t is_version = FALSE;
91	dbus_bool_t udi_exists = FALSE;
92	char *str;
93	DBusError error;
94
95	if (argc <= 1) {
96		usage (argc, argv);
97		return 1;
98	}
99
100	while (1) {
101		int c;
102		int option_index = 0;
103		const char *opt;
104		static struct option long_options[] = {
105			{"udi", 1, NULL, 0},
106			{"key", 1, NULL, 0},
107			{"hex", 0, NULL, 0},
108			{"verbose", 0, NULL, 0},
109			{"version", 0, NULL, 0},
110			{"help", 0, NULL, 0},
111			{NULL, 0, NULL, 0}
112		};
113
114		c = getopt_long (argc, argv, "",
115				 long_options, &option_index);
116		if (c == -1)
117			break;
118
119		switch (c) {
120		case 0:
121			opt = long_options[option_index].name;
122
123			if (strcmp (opt, "help") == 0) {
124				usage (argc, argv);
125				return 0;
126			} else if (strcmp (opt, "hex") == 0) {
127				is_hex = TRUE;
128			} else if (strcmp (opt, "verbose") == 0) {
129				is_verbose = TRUE;
130			} else if (strcmp (opt, "version") == 0) {
131				is_version = TRUE;
132			} else if (strcmp (opt, "key") == 0) {
133				key = strdup (optarg);
134			} else if (strcmp (opt, "udi") == 0) {
135				udi = strdup (optarg);
136			}
137			break;
138
139		default:
140			usage (argc, argv);
141			return 1;
142			break;
143		}
144	}
145
146	if (is_version) {
147		printf ("hal-get-property " PACKAGE_VERSION "\n");
148		return 0;
149	}
150
151	if (udi == NULL || key == NULL) {
152		usage (argc, argv);
153		return 1;
154	}
155
156	dbus_error_init (&error);
157	if ((hal_ctx = libhal_ctx_new ()) == NULL) {
158		fprintf (stderr, "error: libhal_ctx_new\n");
159		return 1;
160	}
161	if (!libhal_ctx_set_dbus_connection (hal_ctx, dbus_bus_get (DBUS_BUS_SYSTEM, &error))) {
162		fprintf (stderr, "error: libhal_ctx_set_dbus_connection: %s: %s\n", error.name, error.message);
163		LIBHAL_FREE_DBUS_ERROR (&error);
164		return 1;
165	}
166	if (!libhal_ctx_init (hal_ctx, &error)) {
167		if (dbus_error_is_set(&error)) {
168			fprintf (stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message);
169			dbus_error_free (&error);
170		}
171		fprintf (stderr, "Could not initialise connection to hald.\n"
172				 "Normally this means the HAL daemon (hald) is not running or not ready.\n");
173		return 1;
174	}
175
176        /* check UDI exists */
177	udi_exists = libhal_device_exists (hal_ctx, udi, &error);
178	if (!udi_exists) {
179		fprintf (stderr, "error: UDI %s does not exist\n", udi);
180		return 1;
181	}
182        if (dbus_error_is_set(&error)) {
183		fprintf (stderr, "error: libhal_device_exists: %s: %s\n", error.name, error.message);
184		dbus_error_free (&error);
185		return 1;
186	}
187
188
189	type = libhal_device_get_property_type (hal_ctx, udi, key, &error);
190	if (type == LIBHAL_PROPERTY_TYPE_INVALID) {
191		if (dbus_error_is_set(&error)) {
192		        fprintf (stderr, "error: libhal_device_get_property_type: %s: %s\n", error.name, error.message);
193			dbus_error_free (&error);
194		} else {
195		        fprintf (stderr, "error: libhal_device_get_property_type: invalid params.\n");
196		}
197		return 1;
198	}
199	/* emit the value to stdout */
200	switch (type) {
201	case LIBHAL_PROPERTY_TYPE_STRING:
202		str = libhal_device_get_property_string (hal_ctx, udi, key, &error);
203		if (is_verbose)
204			printf ("Type is string\n");
205		printf ("%s\n", str);
206		libhal_free_string (str);
207		break;
208	case LIBHAL_PROPERTY_TYPE_INT32:
209		if (is_verbose)
210			printf ("Type is integer (shown in %s)\n",
211				(is_hex ? "hexadecimal" : "decimal"));
212		printf ((is_hex ? "%x\n" : "%d\n"),
213			libhal_device_get_property_int (hal_ctx, udi, key, &error));
214		break;
215	case LIBHAL_PROPERTY_TYPE_UINT64:
216		if (is_verbose)
217			printf ("Type is uint64 (shown in %s)\n",
218				(is_hex ? "hexadecimal" : "decimal"));
219		printf ((is_hex ? "%llx\n" : "%llu\n"),
220			(long long unsigned int) libhal_device_get_property_uint64 (hal_ctx, udi, key, &error));
221		break;
222	case LIBHAL_PROPERTY_TYPE_DOUBLE:
223		if (is_verbose)
224			printf ("Type is double\n");
225		printf ("%f\n",
226			libhal_device_get_property_double (hal_ctx, udi, key, &error));
227		break;
228	case LIBHAL_PROPERTY_TYPE_BOOLEAN:
229		if (is_verbose)
230			printf ("Type is boolean\n");
231		printf ("%s\n",
232			libhal_device_get_property_bool (hal_ctx, udi, key, &error) ? "true" : "false");
233		break;
234
235	case LIBHAL_PROPERTY_TYPE_STRLIST:
236	{
237		unsigned int i;
238		char **strlist;
239
240		if ((strlist = libhal_device_get_property_strlist (hal_ctx, udi, key, &error)) != NULL) {
241
242			for (i = 0; strlist[i] != 0; i++) {
243				printf ("%s", strlist[i]);
244				if (strlist[i+1] != NULL)
245					printf (" ");
246			}
247		}
248		break;
249	}
250	default:
251		printf ("Unknown type %d='%c'\n", type, type);
252		return 1;
253		break;
254	}
255
256	if (dbus_error_is_set (&error)) {
257		fprintf (stderr, "error: %s: %s\n", error.name, error.message);
258		dbus_error_free (&error);
259		return 1;
260	}
261
262
263	return 0;
264}
265
266/**
267 * @}
268 */
269