xref: /onnv-gate/usr/src/cmd/hal/tools/lshal.c (revision 3502:2bf49c526f07)
1*2912Sartem /***************************************************************************
2*2912Sartem  * CVSID: $Id$
3*2912Sartem  *
4*2912Sartem  * lshal.c : Show devices managed by HAL
5*2912Sartem  *
6*2912Sartem  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
7*2912Sartem  * Copyright (C) 2005 Pierre Ossman, <drzeus@drzeus.cx>
8*2912Sartem  *
9*2912Sartem  * Licensed under the Academic Free License version 2.1
10*2912Sartem  *
11*2912Sartem  * This program is free software; you can redistribute it and/or modify
12*2912Sartem  * it under the terms of the GNU General Public License as published by
13*2912Sartem  * the Free Software Foundation; either version 2 of the License, or
14*2912Sartem  * (at your option) any later version.
15*2912Sartem  *
16*2912Sartem  * This program is distributed in the hope that it will be useful,
17*2912Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18*2912Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19*2912Sartem  * GNU General Public License for more details.
20*2912Sartem  *
21*2912Sartem  * You should have received a copy of the GNU General Public License
22*2912Sartem  * along with this program; if not, write to the Free Software
23*2912Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
24*2912Sartem  *
25*2912Sartem  **************************************************************************/
26*2912Sartem 
27*2912Sartem 
28*2912Sartem #ifdef HAVE_CONFIG_H
29*2912Sartem #  include <config.h>
30*2912Sartem #endif
31*2912Sartem 
32*2912Sartem #include <stdio.h>
33*2912Sartem #include <stdlib.h>
34*2912Sartem #include <string.h>
35*2912Sartem #include <unistd.h>
36*2912Sartem #include <getopt.h>
37*2912Sartem 
38*2912Sartem #include <glib.h>
39*2912Sartem #include <dbus/dbus-glib-lowlevel.h>
40*2912Sartem #include <dbus/dbus-glib.h>
41*2912Sartem #include <libhal.h>
42*2912Sartem 
43*2912Sartem #ifdef __SUNPRO_C
44*2912Sartem #define __FUNCTION__ __func__
45*2912Sartem #endif
46*2912Sartem 
47*2912Sartem /**
48*2912Sartem  * @defgroup HalLsHal  List HAL devices
49*2912Sartem  * @ingroup HalMisc
50*2912Sartem  *
51*2912Sartem  * @brief A commandline tool, lshal, for displaying and, optionally,
52*2912Sartem  *        monitor the devices managed by the HAL daemon. Uses libhal.
53*2912Sartem  *
54*2912Sartem  * @{
55*2912Sartem  */
56*2912Sartem 
57*2912Sartem /** Macro for terminating the program on an unrecoverable error */
58*2912Sartem #define DIE(expr) do {printf("*** [DIE] %s:%s():%d : ", __FILE__, __FUNCTION__, __LINE__); printf expr; printf("\n"); exit(1); } while(0)
59*2912Sartem 
60*2912Sartem #define UDI_BASE "/org/freedesktop/Hal/devices/"
61*2912Sartem 
62*2912Sartem static LibHalContext *hal_ctx;
63*2912Sartem static dbus_bool_t long_list = FALSE;
64*2912Sartem static dbus_bool_t tree_view = FALSE;
65*2912Sartem static dbus_bool_t short_list = FALSE;
66*2912Sartem static char *show_device = NULL;
67*2912Sartem 
68*2912Sartem struct Device {
69*2912Sartem 	char *name;
70*2912Sartem 	char *parent;
71*2912Sartem };
72*2912Sartem 
73*2912Sartem /** Generate a short name for a device
74*2912Sartem  *
75*2912Sartem  *  @param  udi                 Universal Device Id
76*2912Sartem  */
77*2912Sartem static const char *
short_name(const char * udi)78*2912Sartem short_name (const char *udi)
79*2912Sartem {
80*2912Sartem 	return &udi[sizeof(UDI_BASE) - 1];
81*2912Sartem }
82*2912Sartem 
83*2912Sartem /** Print all properties of a device
84*2912Sartem  *
85*2912Sartem  *  @param  udi                 Universal Device Id
86*2912Sartem  */
87*2912Sartem 
88*2912Sartem static void
print_props(const char * udi)89*2912Sartem print_props (const char *udi)
90*2912Sartem {
91*2912Sartem 	DBusError error;
92*2912Sartem 	LibHalPropertySet *props;
93*2912Sartem 	LibHalPropertySetIterator it;
94*2912Sartem 	int type;
95*2912Sartem 
96*2912Sartem 	dbus_error_init (&error);
97*2912Sartem 
98*2912Sartem 	props = libhal_device_get_all_properties (hal_ctx, udi, &error);
99*2912Sartem 
100*2912Sartem 	/* NOTE : This may be NULL if the device was removed
101*2912Sartem 	 *        in the daemon; this is because
102*2912Sartem 	 *        hal_device_get_all_properties() is a in
103*2912Sartem 	 *        essence an IPC call and other stuff may
104*2912Sartem 	 *        be happening..
105*2912Sartem 	 */
106*2912Sartem 	if (props == NULL) {
107*2912Sartem 		LIBHAL_FREE_DBUS_ERROR (&error);
108*2912Sartem 		return;
109*2912Sartem 	}
110*2912Sartem 
111*2912Sartem 	for (libhal_psi_init (&it, props); libhal_psi_has_more (&it); libhal_psi_next (&it)) {
112*2912Sartem 		type = libhal_psi_get_type (&it);
113*2912Sartem 		switch (type) {
114*2912Sartem 		case LIBHAL_PROPERTY_TYPE_STRING:
115*2912Sartem 			printf ("  %s = '%s'  (string)\n",
116*2912Sartem 				libhal_psi_get_key (&it),
117*2912Sartem 				libhal_psi_get_string (&it));
118*2912Sartem 			break;
119*2912Sartem 
120*2912Sartem 		case LIBHAL_PROPERTY_TYPE_INT32:
121*2912Sartem 			printf ("  %s = %d  (0x%x)  (int)\n",
122*2912Sartem 				libhal_psi_get_key (&it),
123*2912Sartem 				libhal_psi_get_int (&it),
124*2912Sartem 				libhal_psi_get_int (&it));
125*2912Sartem 			break;
126*2912Sartem 
127*2912Sartem 		case LIBHAL_PROPERTY_TYPE_UINT64:
128*2912Sartem 			printf ("  %s = %llu  (0x%llx)  (uint64)\n",
129*2912Sartem 				libhal_psi_get_key (&it),
130*2912Sartem 				(long long unsigned int) libhal_psi_get_uint64 (&it),
131*2912Sartem 				(long long unsigned int) libhal_psi_get_uint64 (&it));
132*2912Sartem 			break;
133*2912Sartem 
134*2912Sartem 		case LIBHAL_PROPERTY_TYPE_DOUBLE:
135*2912Sartem 			printf ("  %s = %g  (double)\n",
136*2912Sartem 				libhal_psi_get_key (&it),
137*2912Sartem 				libhal_psi_get_double (&it));
138*2912Sartem 			break;
139*2912Sartem 
140*2912Sartem 		case LIBHAL_PROPERTY_TYPE_BOOLEAN:
141*2912Sartem 			printf ("  %s = %s  (bool)\n",
142*2912Sartem 				libhal_psi_get_key (&it),
143*2912Sartem 				libhal_psi_get_bool (&it) ? "true" :
144*2912Sartem 				"false");
145*2912Sartem 			break;
146*2912Sartem 
147*2912Sartem 		case LIBHAL_PROPERTY_TYPE_STRLIST:
148*2912Sartem 		{
149*2912Sartem 			unsigned int i;
150*2912Sartem 			char **strlist;
151*2912Sartem 
152*2912Sartem 			printf ("  %s = {", libhal_psi_get_key (&it));
153*2912Sartem 
154*2912Sartem 			strlist = libhal_psi_get_strlist (&it);
155*2912Sartem 			for (i = 0; strlist[i] != 0; i++) {
156*2912Sartem 				printf ("'%s'", strlist[i]);
157*2912Sartem 				if (strlist[i+1] != NULL)
158*2912Sartem 					printf (", ");
159*2912Sartem 			}
160*2912Sartem 			printf ("} (string list)\n");
161*2912Sartem 			break;
162*2912Sartem 		}
163*2912Sartem 
164*2912Sartem 		default:
165*2912Sartem 			printf ("Unknown type %d=0x%02x\n", type, type);
166*2912Sartem 			break;
167*2912Sartem 		}
168*2912Sartem 	}
169*2912Sartem 
170*2912Sartem 	libhal_free_property_set (props);
171*2912Sartem }
172*2912Sartem 
173*2912Sartem /** Dumps information about a single device
174*2912Sartem  *
175*2912Sartem  *  @param  udi                 Universal Device Id
176*2912Sartem  */
177*2912Sartem 
178*2912Sartem static void
dump_device(const char * udi)179*2912Sartem dump_device (const char *udi)
180*2912Sartem {
181*2912Sartem 	DBusError error;
182*2912Sartem 
183*2912Sartem 	dbus_error_init (&error);
184*2912Sartem 
185*2912Sartem 	if (!libhal_device_exists (hal_ctx, udi, &error)) {
186*2912Sartem 		LIBHAL_FREE_DBUS_ERROR (&error);
187*2912Sartem 		return;
188*2912Sartem 	}
189*2912Sartem 
190*2912Sartem 	if (long_list) {
191*2912Sartem 		printf ("udi = '%s'\n", udi);
192*2912Sartem 
193*2912Sartem 		print_props (udi);
194*2912Sartem 		printf ("\n");
195*2912Sartem 	}
196*2912Sartem 	else
197*2912Sartem 		printf ("%s\n", short_name (udi));
198*2912Sartem }
199*2912Sartem 
200*2912Sartem /** Dump all children of device
201*2912Sartem  *
202*2912Sartem  *  @param  udi                 Universal Device Id of parent
203*2912Sartem  *  @param  num_devices         Total number of devices in device list
204*2912Sartem  *  @param  devices             List of devices
205*2912Sartem  *  @param  depth               Current recursion depth
206*2912Sartem  */
207*2912Sartem 
208*2912Sartem static void
dump_children(char * udi,int num_devices,struct Device * devices,int depth)209*2912Sartem dump_children (char *udi, int num_devices, struct Device *devices, int depth)
210*2912Sartem {
211*2912Sartem 	int i;
212*2912Sartem 
213*2912Sartem 	for (i = 0; i < num_devices; i++) {
214*2912Sartem 		if (!udi) {
215*2912Sartem 			if (devices[i].parent)
216*2912Sartem 				continue;
217*2912Sartem 		}
218*2912Sartem 		else {
219*2912Sartem 			if (!devices[i].parent)
220*2912Sartem 				continue;
221*2912Sartem 			if (strcmp (devices[i].parent, udi))
222*2912Sartem 				continue;
223*2912Sartem 		}
224*2912Sartem 
225*2912Sartem 		if (long_list)
226*2912Sartem 			printf ("udi = '%s'\n", devices[i].name);
227*2912Sartem 		else {
228*2912Sartem 			int j;
229*2912Sartem 			if (tree_view) {
230*2912Sartem 				for (j = 0;j < depth;j++)
231*2912Sartem 					printf("  ");
232*2912Sartem 			}
233*2912Sartem 			printf ("%s\n", short_name (devices[i].name));
234*2912Sartem 		}
235*2912Sartem 
236*2912Sartem 		if (long_list) {
237*2912Sartem 			print_props (devices[i].name);
238*2912Sartem 			printf ("\n");
239*2912Sartem 		}
240*2912Sartem 
241*2912Sartem 		dump_children(devices[i].name, num_devices, devices, depth + 1);
242*2912Sartem 	}
243*2912Sartem }
244*2912Sartem 
245*2912Sartem /** Dump all devices to stdout
246*2912Sartem  *
247*2912Sartem  */
248*2912Sartem static void
dump_devices(void)249*2912Sartem dump_devices (void)
250*2912Sartem {
251*2912Sartem 	int i;
252*2912Sartem 	int num_devices;
253*2912Sartem 	char **device_names;
254*2912Sartem 	struct Device *devices;
255*2912Sartem 	DBusError error;
256*2912Sartem 
257*2912Sartem 	dbus_error_init (&error);
258*2912Sartem 
259*2912Sartem 	device_names = libhal_get_all_devices (hal_ctx, &num_devices, &error);
260*2912Sartem 	if (device_names == NULL) {
261*2912Sartem 		LIBHAL_FREE_DBUS_ERROR (&error);
262*2912Sartem 		DIE (("Couldn't obtain list of devices\n"));
263*2912Sartem 	}
264*2912Sartem 
265*2912Sartem 	devices = malloc (sizeof(struct Device) * num_devices);
266*2912Sartem 	if (!devices) {
267*2912Sartem 		libhal_free_string_array (device_names);
268*2912Sartem 		return;
269*2912Sartem 	}
270*2912Sartem 
271*2912Sartem 	for (i = 0;i < num_devices;i++) {
272*2912Sartem 		devices[i].name = device_names[i];
273*2912Sartem 		devices[i].parent = libhal_device_get_property_string (hal_ctx,
274*2912Sartem 				device_names[i], "info.parent", &error);
275*2912Sartem 
276*2912Sartem 		if (dbus_error_is_set (&error)) {
277*2912Sartem 			/* Free the error (which include a dbus_error_init())
278*2912Sartem 			   This should prevent errors if a call above fails */
279*2912Sartem 			dbus_error_free (&error);
280*2912Sartem 		}
281*2912Sartem 	}
282*2912Sartem 
283*2912Sartem 	if (long_list) {
284*2912Sartem 		printf ("\n"
285*2912Sartem 			"Dumping %d device(s) from the Global Device List:\n"
286*2912Sartem 			"-------------------------------------------------\n",
287*2912Sartem 			num_devices);
288*2912Sartem 	}
289*2912Sartem 
290*2912Sartem 	dump_children(NULL, num_devices, devices, 0);
291*2912Sartem 
292*2912Sartem 	for (i = 0;i < num_devices;i++) {
293*2912Sartem 		if (devices[i].parent)
294*2912Sartem 			libhal_free_string (devices[i].parent);
295*2912Sartem 	}
296*2912Sartem 
297*2912Sartem 	free (devices);
298*2912Sartem 	libhal_free_string_array (device_names);
299*2912Sartem 
300*2912Sartem 	if (long_list) {
301*2912Sartem 		printf ("\n"
302*2912Sartem 			"Dumped %d device(s) from the Global Device List.\n"
303*2912Sartem 			"------------------------------------------------\n",
304*2912Sartem 			num_devices);
305*2912Sartem 
306*2912Sartem 		printf ("\n");
307*2912Sartem 	}
308*2912Sartem }
309*2912Sartem 
310*2912Sartem /** Invoked when a device is added to the Global Device List. Simply prints
311*2912Sartem  *  a message on stdout.
312*2912Sartem  *
313*2912Sartem  *  @param  udi                 Universal Device Id
314*2912Sartem  */
315*2912Sartem static void
device_added(LibHalContext * ctx,const char * udi)316*2912Sartem device_added (LibHalContext *ctx,
317*2912Sartem 	      const char *udi)
318*2912Sartem {
319*2912Sartem 	if (show_device && strcmp(show_device, udi))
320*2912Sartem 		return;
321*2912Sartem 
322*2912Sartem 	if (long_list) {
323*2912Sartem 		printf ("*** lshal: device_added, udi='%s'\n", udi);
324*2912Sartem 		print_props (udi);
325*2912Sartem 	} else
326*2912Sartem 		printf ("%s added\n", short_name (udi));
327*2912Sartem }
328*2912Sartem 
329*2912Sartem /** Invoked when a device is removed from the Global Device List. Simply
330*2912Sartem  *  prints a message on stdout.
331*2912Sartem  *
332*2912Sartem  *  @param  udi                 Universal Device Id
333*2912Sartem  */
334*2912Sartem static void
device_removed(LibHalContext * ctx,const char * udi)335*2912Sartem device_removed (LibHalContext *ctx,
336*2912Sartem 		const char *udi)
337*2912Sartem {
338*2912Sartem 	if (show_device && strcmp(show_device, udi))
339*2912Sartem 		return;
340*2912Sartem 
341*2912Sartem 	if (long_list)
342*2912Sartem 		printf ("*** lshal: device_removed, udi='%s'\n", udi);
343*2912Sartem 	else
344*2912Sartem 		printf ("%s removed\n", short_name (udi));
345*2912Sartem }
346*2912Sartem 
347*2912Sartem /** Invoked when device in the Global Device List acquires a new capability.
348*2912Sartem  *  Prints the name of the capability to stdout.
349*2912Sartem  *
350*2912Sartem  *  @param  udi                 Universal Device Id
351*2912Sartem  *  @param  capability          Name of capability
352*2912Sartem  */
353*2912Sartem static void
device_new_capability(LibHalContext * ctx,const char * udi,const char * capability)354*2912Sartem device_new_capability (LibHalContext *ctx,
355*2912Sartem 		       const char *udi,
356*2912Sartem 		       const char *capability)
357*2912Sartem {
358*2912Sartem 	if (show_device && strcmp(show_device, udi))
359*2912Sartem 		return;
360*2912Sartem 
361*2912Sartem 	if (long_list) {
362*2912Sartem 		printf ("*** lshal: new_capability, udi='%s'\n", udi);
363*2912Sartem 		printf ("*** capability: %s\n", capability);
364*2912Sartem 	} else
365*2912Sartem 		printf ("%s capability %s added\n", short_name (udi),
366*2912Sartem 			capability);
367*2912Sartem }
368*2912Sartem 
369*2912Sartem /** Invoked when device in the Global Device List loses a capability.
370*2912Sartem  *  Prints the name of the capability to stdout.
371*2912Sartem  *
372*2912Sartem  *  @param  udi                 Universal Device Id
373*2912Sartem  *  @param  capability          Name of capability
374*2912Sartem  */
375*2912Sartem static void
device_lost_capability(LibHalContext * ctx,const char * udi,const char * capability)376*2912Sartem device_lost_capability (LibHalContext *ctx,
377*2912Sartem 			const char *udi,
378*2912Sartem 			const char *capability)
379*2912Sartem {
380*2912Sartem 	if (show_device && strcmp(show_device, udi))
381*2912Sartem 		return;
382*2912Sartem 
383*2912Sartem 	if (long_list) {
384*2912Sartem 		printf ("*** lshal: lost_capability, udi='%s'\n", udi);
385*2912Sartem 		printf ("*** capability: %s\n", capability);
386*2912Sartem 	} else
387*2912Sartem 		printf ("%s capability %s lost\n", short_name (udi),
388*2912Sartem 			capability);
389*2912Sartem }
390*2912Sartem 
391*2912Sartem /** Acquires and prints the value of of a property to stdout.
392*2912Sartem  *
393*2912Sartem  *  @param  udi                 Universal Device Id
394*2912Sartem  *  @param  key                 Key of property
395*2912Sartem  */
396*2912Sartem static void
print_property(const char * udi,const char * key)397*2912Sartem print_property (const char *udi, const char *key)
398*2912Sartem {
399*2912Sartem 	int type;
400*2912Sartem 	char *str;
401*2912Sartem 	DBusError error;
402*2912Sartem 
403*2912Sartem 	dbus_error_init (&error);
404*2912Sartem 
405*2912Sartem 	type = libhal_device_get_property_type (hal_ctx, udi, key, &error);
406*2912Sartem 
407*2912Sartem 	switch (type) {
408*2912Sartem 	case LIBHAL_PROPERTY_TYPE_STRING:
409*2912Sartem 		str = libhal_device_get_property_string (hal_ctx, udi, key, &error);
410*2912Sartem 		printf (long_list?"*** new value: '%s'  (string)\n":"'%s'", str);
411*2912Sartem 		libhal_free_string (str);
412*2912Sartem 		break;
413*2912Sartem 	case LIBHAL_PROPERTY_TYPE_INT32:
414*2912Sartem 		{
415*2912Sartem 			dbus_int32_t value = libhal_device_get_property_int (hal_ctx, udi, key, &error);
416*2912Sartem 			printf (long_list?"*** new value: %d (0x%x)  (int)\n":"%d (0x%x)",
417*2912Sartem 				 value, value);
418*2912Sartem 		}
419*2912Sartem 		break;
420*2912Sartem 	case LIBHAL_PROPERTY_TYPE_UINT64:
421*2912Sartem 		{
422*2912Sartem 			dbus_uint64_t value = libhal_device_get_property_uint64 (hal_ctx, udi, key, &error);
423*2912Sartem 			printf (long_list?"*** new value: %llu (0x%llx)  (uint64)\n":"%llu (0x%llx)",
424*2912Sartem 				(long long unsigned int) value, (long long unsigned int) value);
425*2912Sartem 		}
426*2912Sartem 		break;
427*2912Sartem 	case LIBHAL_PROPERTY_TYPE_DOUBLE:
428*2912Sartem 		printf (long_list?"*** new value: %g  (double)\n":"%g",
429*2912Sartem 			libhal_device_get_property_double (hal_ctx, udi, key, &error));
430*2912Sartem 		break;
431*2912Sartem 	case LIBHAL_PROPERTY_TYPE_BOOLEAN:
432*2912Sartem 		printf (long_list?"*** new value: %s  (bool)\n":"%s",
433*2912Sartem 			libhal_device_get_property_bool (hal_ctx, udi, key, &error) ? "true" : "false");
434*2912Sartem 		break;
435*2912Sartem 	case LIBHAL_PROPERTY_TYPE_STRLIST:
436*2912Sartem 	{
437*2912Sartem 		unsigned int i;
438*2912Sartem 		char **strlist;
439*2912Sartem 
440*2912Sartem 		if (long_list)
441*2912Sartem 			printf ("*** new value: {");
442*2912Sartem 		else
443*2912Sartem 			printf ("{");
444*2912Sartem 
445*2912Sartem 		strlist = libhal_device_get_property_strlist (hal_ctx, udi, key, &error);
446*2912Sartem 		for (i = 0; strlist[i] != 0; i++) {
447*2912Sartem 			printf ("'%s'", strlist[i]);
448*2912Sartem 			if (strlist[i+1] != NULL)
449*2912Sartem 				printf (", ");
450*2912Sartem 		}
451*2912Sartem 		if (long_list)
452*2912Sartem 			printf ("}  (string list)\n");
453*2912Sartem 		else
454*2912Sartem 			printf ("}");
455*2912Sartem 		libhal_free_string_array (strlist);
456*2912Sartem 		break;
457*2912Sartem 	}
458*2912Sartem 
459*2912Sartem 	default:
460*2912Sartem 		fprintf (stderr, "Unknown type %d='%c'\n", type, type);
461*2912Sartem 		break;
462*2912Sartem 	}
463*2912Sartem 
464*2912Sartem 	if (dbus_error_is_set (&error))
465*2912Sartem 		dbus_error_free (&error);
466*2912Sartem }
467*2912Sartem 
468*2912Sartem /** Invoked when a property of a device in the Global Device List is
469*2912Sartem  *  changed, and we have we have subscribed to changes for that device.
470*2912Sartem  *
471*2912Sartem  *  @param  udi                 Univerisal Device Id
472*2912Sartem  *  @param  key                 Key of property
473*2912Sartem  */
474*2912Sartem static void
property_modified(LibHalContext * ctx,const char * udi,const char * key,dbus_bool_t is_removed,dbus_bool_t is_added)475*2912Sartem property_modified (LibHalContext *ctx,
476*2912Sartem 		   const char *udi,
477*2912Sartem 		   const char *key,
478*2912Sartem 		   dbus_bool_t is_removed,
479*2912Sartem 		   dbus_bool_t is_added)
480*2912Sartem {
481*2912Sartem 	if (show_device && strcmp(show_device, udi))
482*2912Sartem 		return;
483*2912Sartem 
484*2912Sartem 	if (long_list) {
485*2912Sartem 		printf ("*** lshal: property_modified, udi=%s, key=%s\n",
486*2912Sartem 			udi, key);
487*2912Sartem 		printf ("           is_removed=%s, is_added=%s\n",
488*2912Sartem 			is_removed ? "true" : "false",
489*2912Sartem 			is_added ? "true" : "false");
490*2912Sartem 		if (!is_removed)
491*2912Sartem 			print_property (udi, key);
492*2912Sartem 		printf ("\n");
493*2912Sartem 	} else {
494*2912Sartem 		printf ("%s property %s ", short_name (udi), key);
495*2912Sartem 		if (is_removed)
496*2912Sartem 			printf ("removed");
497*2912Sartem 		else {
498*2912Sartem 			printf ("= ");
499*2912Sartem 			print_property (udi, key);
500*2912Sartem 
501*2912Sartem 			if (is_added)
502*2912Sartem 				printf (" (new)");
503*2912Sartem 		}
504*2912Sartem 		printf ("\n");
505*2912Sartem 	}
506*2912Sartem }
507*2912Sartem 
508*2912Sartem 
509*2912Sartem /** Invoked when a property of a device in the Global Device List is
510*2912Sartem  *  changed, and we have we have subscribed to changes for that device.
511*2912Sartem  *
512*2912Sartem  *  @param  udi                 Univerisal Device Id
513*2912Sartem  *  @param  condition_name      Name of condition
514*2912Sartem  *  @param  message             D-BUS message with parameters
515*2912Sartem  */
516*2912Sartem static void
device_condition(LibHalContext * ctx,const char * udi,const char * condition_name,const char * condition_details)517*2912Sartem device_condition (LibHalContext *ctx,
518*2912Sartem 		  const char *udi,
519*2912Sartem 		  const char *condition_name,
520*2912Sartem 		  const char *condition_details)
521*2912Sartem {
522*2912Sartem 	if (show_device && strcmp(show_device, udi))
523*2912Sartem 		return;
524*2912Sartem 
525*2912Sartem 	if (long_list) {
526*2912Sartem 		printf ("*** lshal: device_condition, udi=%s\n", udi);
527*2912Sartem 		printf ("           condition_name=%s\n", condition_name);
528*2912Sartem 		printf ("           condition_details=%s\n", condition_details);
529*2912Sartem 		printf ("\n");
530*2912Sartem 	} else {
531*2912Sartem 		printf ("%s condition %s = %s\n", short_name (udi),
532*2912Sartem 			condition_name, condition_details);
533*2912Sartem 	}
534*2912Sartem }
535*2912Sartem 
536*2912Sartem 
537*2912Sartem /** Print out program usage.
538*2912Sartem  *
539*2912Sartem  *  @param  argc                Number of arguments given to program
540*2912Sartem  *  @param  argv                Arguments given to program
541*2912Sartem  */
542*2912Sartem static void
usage(int argc,char * argv[])543*2912Sartem usage (int argc, char *argv[])
544*2912Sartem {
545*2912Sartem 	fprintf (stderr, "lshal version " PACKAGE_VERSION "\n");
546*2912Sartem 
547*2912Sartem 	fprintf (stderr, "\n" "usage : %s [options]\n", argv[0]);
548*2912Sartem 	fprintf (stderr,
549*2912Sartem 		 "\n"
550*2912Sartem 		 "Options:\n"
551*2912Sartem 		 "    -m, --monitor        Monitor device list\n"
552*2912Sartem 		 "    -s, --short          short output (print only nonstatic part of udi)\n"
553*2912Sartem 		 "    -l, --long           Long output\n"
554*2912Sartem 		 "    -t, --tree           Tree view\n"
555*2912Sartem 		 "    -u, --show <udi>     Show only the specified device\n"
556*2912Sartem 		 "\n"
557*2912Sartem 		 "    -h, --help           Show this information and exit\n"
558*2912Sartem 		 "    -V, --version        Print version number\n"
559*2912Sartem 		 "\n"
560*2912Sartem 		 "Without any given options lshal will start with option --long."
561*2912Sartem 		 "\n"
562*2912Sartem 		 "Shows all devices and their properties. If the --monitor option is given\n"
563*2912Sartem 		 "then the device list and all devices are monitored for changes.\n"
564*2912Sartem 		 "\n");
565*2912Sartem }
566*2912Sartem 
567*2912Sartem /** Entry point
568*2912Sartem  *
569*2912Sartem  *  @param  argc                Number of arguments given to program
570*2912Sartem  *  @param  argv                Arguments given to program
571*2912Sartem  *  @return                     Return code
572*2912Sartem  */
573*2912Sartem int
main(int argc,char * argv[])574*2912Sartem main (int argc, char *argv[])
575*2912Sartem {
576*2912Sartem 	DBusError error;
577*2912Sartem 	dbus_bool_t do_monitor = FALSE;
578*2912Sartem 	GMainLoop *loop;
579*2912Sartem 	DBusConnection *conn;
580*2912Sartem 
581*2912Sartem 	if (argc == 1) {
582*2912Sartem 		/* This is the default case lshal without any options */
583*2912Sartem 		long_list = TRUE;
584*2912Sartem 	}
585*2912Sartem 	else {
586*2912Sartem 		static const struct option long_options[] = {
587*2912Sartem 			{"monitor", no_argument, NULL, 'm'},
588*2912Sartem 			{"long", no_argument, NULL, 'l'},
589*2912Sartem 			{"short", no_argument, NULL, 's'},
590*2912Sartem 			{"tree", no_argument, NULL, 't'},
591*2912Sartem 			{"show", required_argument, NULL, 'u'},
592*2912Sartem 			{"help", no_argument, NULL, 'h'},
593*2912Sartem 			{"usage", no_argument, NULL, 'U'},
594*2912Sartem 			{"version", no_argument, NULL, 'V'},
595*2912Sartem 			{NULL, 0, NULL, 0}
596*2912Sartem 		};
597*2912Sartem 
598*2912Sartem 		while (1) {
599*2912Sartem 			int c;
600*2912Sartem 
601*2912Sartem 			c = getopt_long (argc, argv, "mlstu:hUV", long_options, NULL);
602*2912Sartem 
603*2912Sartem 			if (c == -1) {
604*2912Sartem 				/* this should happen e.g. if 'lshal -' and this is incorrect/incomplete option */
605*2912Sartem 				if (!do_monitor && !long_list && !short_list && !tree_view && !show_device) {
606*2912Sartem 					usage (argc, argv);
607*2912Sartem 					return 1;
608*2912Sartem 				}
609*2912Sartem 
610*2912Sartem 				break;
611*2912Sartem 			}
612*2912Sartem 
613*2912Sartem 			switch (c) {
614*2912Sartem 			case 'm':
615*2912Sartem 				do_monitor = TRUE;
616*2912Sartem 				break;
617*2912Sartem 
618*2912Sartem 			case 'l':
619*2912Sartem 				long_list = TRUE;
620*2912Sartem 				break;
621*2912Sartem 
622*2912Sartem 			case 's':
623*2912Sartem 				short_list = TRUE;
624*2912Sartem 				long_list = FALSE;
625*2912Sartem 				break;
626*2912Sartem 
627*2912Sartem 			case 't':
628*2912Sartem 				tree_view = TRUE;
629*2912Sartem 				break;
630*2912Sartem 
631*2912Sartem 			case 'u':
632*2912Sartem 				if (strchr(optarg, '/') != NULL)
633*2912Sartem 					show_device = strdup(optarg);
634*2912Sartem 				else {
635*2912Sartem 					show_device = malloc(strlen(UDI_BASE) + strlen(optarg) + 1);
636*2912Sartem 					memcpy(show_device, UDI_BASE, strlen(UDI_BASE));
637*2912Sartem 					memcpy(show_device + strlen(UDI_BASE), optarg, strlen(optarg) + 1);
638*2912Sartem 				}
639*2912Sartem 
640*2912Sartem 				break;
641*2912Sartem 
642*2912Sartem 			case 'h':
643*2912Sartem 			case 'U':
644*2912Sartem 				usage (argc, argv);
645*2912Sartem 				return 0;
646*2912Sartem 
647*2912Sartem 			case 'V':
648*2912Sartem 				printf ("lshal version " PACKAGE_VERSION "\n");
649*2912Sartem 				return 0;
650*2912Sartem 
651*2912Sartem 			default:
652*2912Sartem 				usage (argc, argv);
653*2912Sartem 				return 1;
654*2912Sartem 			}
655*2912Sartem 		}
656*2912Sartem 	}
657*2912Sartem 
658*2912Sartem 	if (do_monitor)
659*2912Sartem 		loop = g_main_loop_new (NULL, FALSE);
660*2912Sartem 	else
661*2912Sartem 		loop = NULL;
662*2912Sartem 
663*2912Sartem 	dbus_error_init (&error);
664*2912Sartem 	conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
665*2912Sartem 	if (conn == NULL) {
666*2912Sartem 		fprintf (stderr, "error: dbus_bus_get: %s: %s\n",
667*2912Sartem 			 error.name, error.message);
668*2912Sartem 		LIBHAL_FREE_DBUS_ERROR (&error);
669*2912Sartem 		return 1;
670*2912Sartem 	}
671*2912Sartem 
672*2912Sartem 	if (do_monitor)
673*2912Sartem 		dbus_connection_setup_with_g_main (conn, NULL);
674*2912Sartem 
675*2912Sartem 	if ((hal_ctx = libhal_ctx_new ()) == NULL) {
676*2912Sartem 		fprintf (stderr, "error: libhal_ctx_new\n");
677*2912Sartem 		return 1;
678*2912Sartem 	}
679*2912Sartem 	if (!libhal_ctx_set_dbus_connection (hal_ctx, conn)) {
680*2912Sartem 		fprintf (stderr, "error: libhal_ctx_set_dbus_connection: %s: %s\n",
681*2912Sartem 			 error.name, error.message);
682*2912Sartem 		return 1;
683*2912Sartem 	}
684*2912Sartem 	if (!libhal_ctx_init (hal_ctx, &error)) {
685*2912Sartem 		if (dbus_error_is_set(&error)) {
686*2912Sartem 			fprintf (stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message);
687*2912Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
688*2912Sartem 		}
689*2912Sartem 		fprintf (stderr, "Could not initialise connection to hald.\n"
690*2912Sartem 				 "Normally this means the HAL daemon (hald) is not running or not ready.\n");
691*2912Sartem 		return 1;
692*2912Sartem 	}
693*2912Sartem 
694*2912Sartem 	libhal_ctx_set_device_added (hal_ctx, device_added);
695*2912Sartem 	libhal_ctx_set_device_removed (hal_ctx, device_removed);
696*2912Sartem 	libhal_ctx_set_device_new_capability (hal_ctx, device_new_capability);
697*2912Sartem 	libhal_ctx_set_device_lost_capability (hal_ctx, device_lost_capability);
698*2912Sartem 	libhal_ctx_set_device_property_modified (hal_ctx, property_modified);
699*2912Sartem 	libhal_ctx_set_device_condition (hal_ctx, device_condition);
700*2912Sartem 
701*2912Sartem 	if (show_device)
702*2912Sartem 		dump_device (show_device);
703*2912Sartem 	else if (!do_monitor)
704*2912Sartem 		dump_devices ();
705*2912Sartem 
706*2912Sartem 	/* run the main loop only if we should monitor */
707*2912Sartem 	if (do_monitor && loop != NULL) {
708*2912Sartem 		if( long_list || short_list || tree_view )
709*2912Sartem 			dump_devices ();
710*2912Sartem 
711*2912Sartem 		if ( libhal_device_property_watch_all (hal_ctx, &error) == FALSE) {
712*2912Sartem 			fprintf (stderr, "error: monitoring devicelist - libhal_device_property_watch_all: %s: %s\n",
713*2912Sartem 				 error.name, error.message);
714*2912Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
715*2912Sartem 			return 1;
716*2912Sartem 		}
717*2912Sartem 		printf ("\nStart monitoring devicelist:\n"
718*2912Sartem 			"-------------------------------------------------\n");
719*2912Sartem 		g_main_loop_run (loop);
720*2912Sartem 	}
721*2912Sartem 
722*2912Sartem 	if ( libhal_ctx_shutdown (hal_ctx, &error) == FALSE)
723*2912Sartem 		LIBHAL_FREE_DBUS_ERROR (&error);
724*2912Sartem 	libhal_ctx_free (hal_ctx);
725*2912Sartem 
726*2912Sartem 	dbus_connection_unref (conn);
727*2912Sartem 
728*2912Sartem 	if (show_device)
729*2912Sartem 		free(show_device);
730*2912Sartem 
731*2912Sartem 	return 0;
732*2912Sartem }
733*2912Sartem 
734*2912Sartem /**
735*2912Sartem  * @}
736*2912Sartem  */
737