1*2912Sartem /***************************************************************************
2*2912Sartem  * CVSID: $Id$
3*2912Sartem  *
4*2912Sartem  * hal_set_property.c : Set property for a device
5*2912Sartem  *
6*2912Sartem  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
7*2912Sartem  *
8*2912Sartem  * Licensed under the Academic Free License version 2.1
9*2912Sartem  *
10*2912Sartem  * This program is free software; you can redistribute it and/or modify
11*2912Sartem  * it under the terms of the GNU General Public License as published by
12*2912Sartem  * the Free Software Foundation; either version 2 of the License, or
13*2912Sartem  * (at your option) any later version.
14*2912Sartem  *
15*2912Sartem  * This program is distributed in the hope that it will be useful,
16*2912Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*2912Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*2912Sartem  * GNU General Public License for more details.
19*2912Sartem  *
20*2912Sartem  * You should have received a copy of the GNU General Public License
21*2912Sartem  * along with this program; if not, write to the Free Software
22*2912Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23*2912Sartem  *
24*2912Sartem  **************************************************************************/
25*2912Sartem 
26*2912Sartem 
27*2912Sartem #ifdef HAVE_CONFIG_H
28*2912Sartem #  include <config.h>
29*2912Sartem #endif
30*2912Sartem 
31*2912Sartem #include <stdio.h>
32*2912Sartem #include <stdlib.h>
33*2912Sartem #include <string.h>
34*2912Sartem #include <unistd.h>
35*2912Sartem #include <getopt.h>
36*2912Sartem 
37*2912Sartem #include <libhal.h>
38*2912Sartem 
39*2912Sartem static LibHalContext *hal_ctx;
40*2912Sartem 
41*2912Sartem enum property_op {
42*2912Sartem 	PROP_INT,
43*2912Sartem 	PROP_UINT64,
44*2912Sartem 	PROP_STRING,
45*2912Sartem 	PROP_DOUBLE,
46*2912Sartem 	PROP_BOOL,
47*2912Sartem 	PROP_STRLIST_PRE,
48*2912Sartem 	PROP_STRLIST_POST,
49*2912Sartem 	PROP_STRLIST_REM,
50*2912Sartem 	PROP_INVALID
51*2912Sartem };
52*2912Sartem 
53*2912Sartem /**
54*2912Sartem  * @defgroup HalSetProperty  Set HAL device property
55*2912Sartem  * @ingroup HalMisc
56*2912Sartem  *
57*2912Sartem  * @brief A commandline tool setting a property of a device. Uses libhal
58*2912Sartem  *
59*2912Sartem  * @{
60*2912Sartem  */
61*2912Sartem 
62*2912Sartem /** Print out program usage.
63*2912Sartem  *
64*2912Sartem  *  @param  argc                Number of arguments given to program
65*2912Sartem  *  @param  argv                Arguments given to program
66*2912Sartem  */
67*2912Sartem static void
68*2912Sartem usage (int argc, char *argv[])
69*2912Sartem {
70*2912Sartem 	fprintf (stderr,
71*2912Sartem  "\n"
72*2912Sartem  "usage : hal-set-property --udi <udi> --key <key>\n"
73*2912Sartem  "           (--int <value> | --string <value> | --bool <value> |\n"
74*2912Sartem  "            --strlist-pre <value> | --strlist-post <value> |\n"
75*2912Sartem  "            --strlist-rem <value> | --double <value> | --remove)\n"
76*2912Sartem  "           [--help] [--version]\n");
77*2912Sartem 	fprintf (stderr,
78*2912Sartem  "\n" "        --udi            Unique Device Id\n"
79*2912Sartem  "        --key            Key of the property to set\n"
80*2912Sartem  "        --int            Set value to an integer. Accepts decimal and "
81*2912Sartem  "                         hexadecimal prefixed with 0x or x\n"
82*2912Sartem  "        --uint64         Set value to an integer. Accepts decimal and "
83*2912Sartem  "                         hexadecimal prefixed with 0x or x\n"
84*2912Sartem  "        --string         Set value to a string\n"
85*2912Sartem  "        --double         Set value to a floating point number\n"
86*2912Sartem  "        --bool           Set value to a boolean, ie. true or false\n"
87*2912Sartem  "        --strlist-pre    Prepend a string to a list\n"
88*2912Sartem  "        --strlist-post   Append a string to a list\n"
89*2912Sartem  "        --strlist-rem    Remove a string from a list\n"
90*2912Sartem  "        --remove         Indicates that the property should be removed\n"
91*2912Sartem  "        --version        Show version and exit\n"
92*2912Sartem  "        --help           Show this information and exit\n"
93*2912Sartem  "\n"
94*2912Sartem  "This program attempts to set property for a device. Note that, due to\n"
95*2912Sartem  "security considerations, it may not be possible to set a property; on\n"
96*2912Sartem  "success this program exits with exit code 0. On error, the program exits\n"
97*2912Sartem  "with an exit code different from 0\n" "\n");
98*2912Sartem }
99*2912Sartem 
100*2912Sartem /** Entry point
101*2912Sartem  *
102*2912Sartem  *  @param  argc                Number of arguments given to program
103*2912Sartem  *  @param  argv                Arguments given to program
104*2912Sartem  *  @return                     Return code
105*2912Sartem  */
106*2912Sartem int
107*2912Sartem main (int argc, char *argv[])
108*2912Sartem {
109*2912Sartem 	dbus_bool_t rc = 0;
110*2912Sartem 	char *udi = NULL;
111*2912Sartem 	char *key = NULL;
112*2912Sartem 	char *str_value = NULL;
113*2912Sartem 	dbus_int32_t int_value = 0;
114*2912Sartem 	dbus_uint64_t uint64_value = 0;
115*2912Sartem 	double double_value = 0.0f;
116*2912Sartem 	dbus_bool_t bool_value = TRUE;
117*2912Sartem 	dbus_bool_t remove = FALSE;
118*2912Sartem 	dbus_bool_t is_version = FALSE;
119*2912Sartem 	int type = PROP_INVALID;
120*2912Sartem 	DBusError error;
121*2912Sartem 
122*2912Sartem 	if (argc <= 1) {
123*2912Sartem 		usage (argc, argv);
124*2912Sartem 		return 1;
125*2912Sartem 	}
126*2912Sartem 
127*2912Sartem 	while (1) {
128*2912Sartem 		int c;
129*2912Sartem 		int option_index = 0;
130*2912Sartem 		const char *opt;
131*2912Sartem 		static struct option long_options[] = {
132*2912Sartem 			{"udi", 1, NULL, 0},
133*2912Sartem 			{"key", 1, NULL, 0},
134*2912Sartem 			{"int", 1, NULL, 0},
135*2912Sartem 			{"uint64", 1, NULL, 0},
136*2912Sartem 			{"string", 1, NULL, 0},
137*2912Sartem 			{"double", 1, NULL, 0},
138*2912Sartem 			{"bool", 1, NULL, 0},
139*2912Sartem 			{"strlist-pre", 1, NULL, 0},
140*2912Sartem 			{"strlist-post", 1, NULL, 0},
141*2912Sartem 			{"strlist-rem", 1, NULL, 0},
142*2912Sartem 			{"remove", 0, NULL, 0},
143*2912Sartem 			{"version", 0, NULL, 0},
144*2912Sartem 			{"help", 0, NULL, 0},
145*2912Sartem 			{NULL, 0, NULL, 0}
146*2912Sartem 		};
147*2912Sartem 
148*2912Sartem 		c = getopt_long (argc, argv, "",
149*2912Sartem 				 long_options, &option_index);
150*2912Sartem 		if (c == -1)
151*2912Sartem 			break;
152*2912Sartem 
153*2912Sartem 		switch (c) {
154*2912Sartem 		case 0:
155*2912Sartem 			opt = long_options[option_index].name;
156*2912Sartem 
157*2912Sartem 			if (strcmp (opt, "help") == 0) {
158*2912Sartem 				usage (argc, argv);
159*2912Sartem 				return 0;
160*2912Sartem 			} else if (strcmp (opt, "key") == 0) {
161*2912Sartem 				key = strdup (optarg);
162*2912Sartem 			} else if (strcmp (opt, "string") == 0) {
163*2912Sartem 				str_value = strdup (optarg);
164*2912Sartem 				type = PROP_STRING;
165*2912Sartem 			} else if (strcmp (opt, "int") == 0) {
166*2912Sartem 				int_value = strtol (optarg, NULL, 0);
167*2912Sartem 				type = PROP_INT;
168*2912Sartem 			} else if (strcmp (opt, "uint64") == 0) {
169*2912Sartem 				uint64_value = strtoull (optarg, NULL, 0);
170*2912Sartem 				type = PROP_UINT64;
171*2912Sartem 			} else if (strcmp (opt, "double") == 0) {
172*2912Sartem 				double_value = (double) atof (optarg);
173*2912Sartem 				type = PROP_DOUBLE;
174*2912Sartem 			} else if (strcmp (opt, "bool") == 0) {
175*2912Sartem 				if (strcmp (optarg, "true") == 0)
176*2912Sartem 					bool_value = TRUE;
177*2912Sartem 				else if (strcmp (optarg, "false") == 0)
178*2912Sartem 					bool_value = FALSE;
179*2912Sartem 				else {
180*2912Sartem 					usage (argc, argv);
181*2912Sartem 					return 1;
182*2912Sartem 				}
183*2912Sartem 				type = PROP_BOOL;
184*2912Sartem 			} else if (strcmp (opt, "strlist-pre") == 0) {
185*2912Sartem 				str_value = strdup (optarg);
186*2912Sartem 				type = PROP_STRLIST_PRE;
187*2912Sartem 			} else if (strcmp (opt, "strlist-post") == 0) {
188*2912Sartem 				str_value = strdup (optarg);
189*2912Sartem 				type = PROP_STRLIST_POST;
190*2912Sartem 			} else if (strcmp (opt, "strlist-rem") == 0) {
191*2912Sartem 				str_value = strdup (optarg);
192*2912Sartem 				type = PROP_STRLIST_REM;
193*2912Sartem 			} else if (strcmp (opt, "remove") == 0) {
194*2912Sartem 				remove = TRUE;
195*2912Sartem 			} else if (strcmp (opt, "udi") == 0) {
196*2912Sartem 				udi = strdup (optarg);
197*2912Sartem 			} else if (strcmp (opt, "version") == 0) {
198*2912Sartem 				is_version = TRUE;
199*2912Sartem 			}
200*2912Sartem 			break;
201*2912Sartem 
202*2912Sartem 		default:
203*2912Sartem 			usage (argc, argv);
204*2912Sartem 			return 1;
205*2912Sartem 			break;
206*2912Sartem 		}
207*2912Sartem 	}
208*2912Sartem 
209*2912Sartem 	if (is_version) {
210*2912Sartem 		printf ("hal-set-property " PACKAGE_VERSION "\n");
211*2912Sartem 		return 0;
212*2912Sartem 	}
213*2912Sartem 
214*2912Sartem 	/* must have at least one, but not neither or both */
215*2912Sartem 	if ((remove && type != PROP_INVALID) || ((!remove) && type == PROP_INVALID)) {
216*2912Sartem 		usage (argc, argv);
217*2912Sartem 		return 1;
218*2912Sartem 	}
219*2912Sartem 
220*2912Sartem 	fprintf (stderr, "\n");
221*2912Sartem 
222*2912Sartem 	dbus_error_init (&error);
223*2912Sartem 	if ((hal_ctx = libhal_ctx_new ()) == NULL) {
224*2912Sartem 		fprintf (stderr, "error: libhal_ctx_new\n");
225*2912Sartem 		return 1;
226*2912Sartem 	}
227*2912Sartem 	if (!libhal_ctx_set_dbus_connection (hal_ctx, dbus_bus_get (DBUS_BUS_SYSTEM, &error))) {
228*2912Sartem 		fprintf (stderr, "error: libhal_ctx_set_dbus_connection: %s: %s\n", error.name, error.message);
229*2912Sartem 		LIBHAL_FREE_DBUS_ERROR (&error);
230*2912Sartem 		return 1;
231*2912Sartem 	}
232*2912Sartem 	if (!libhal_ctx_init (hal_ctx, &error)) {
233*2912Sartem 		if (dbus_error_is_set(&error)) {
234*2912Sartem 			fprintf (stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message);
235*2912Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
236*2912Sartem 		}
237*2912Sartem 		fprintf (stderr, "Could not initialise connection to hald.\n"
238*2912Sartem 				 "Normally this means the HAL daemon (hald) is not running or not ready.\n");
239*2912Sartem 		return 1;
240*2912Sartem 	}
241*2912Sartem 
242*2912Sartem 	if (remove) {
243*2912Sartem 		rc = libhal_device_remove_property (hal_ctx, udi, key, &error);
244*2912Sartem 		if (!rc) {
245*2912Sartem 			fprintf (stderr, "error: libhal_device_remove_property: %s: %s\n", error.name, error.message);
246*2912Sartem 			LIBHAL_FREE_DBUS_ERROR (&error);
247*2912Sartem 			return 1;
248*2912Sartem 		}
249*2912Sartem 	} else {
250*2912Sartem 		switch (type) {
251*2912Sartem 		case PROP_STRING:
252*2912Sartem 			rc = libhal_device_set_property_string (hal_ctx, udi, key, str_value, &error);
253*2912Sartem 			break;
254*2912Sartem 		case PROP_INT:
255*2912Sartem 			rc = libhal_device_set_property_int (hal_ctx, udi, key, int_value, &error);
256*2912Sartem 			break;
257*2912Sartem 		case PROP_UINT64:
258*2912Sartem 			rc = libhal_device_set_property_uint64 (hal_ctx, udi, key, uint64_value, &error);
259*2912Sartem 			break;
260*2912Sartem 		case PROP_DOUBLE:
261*2912Sartem 			rc = libhal_device_set_property_double (hal_ctx, udi, key, double_value, &error);
262*2912Sartem 			break;
263*2912Sartem 		case PROP_BOOL:
264*2912Sartem 			rc = libhal_device_set_property_bool (hal_ctx, udi, key, bool_value, &error);
265*2912Sartem 			break;
266*2912Sartem 		case PROP_STRLIST_PRE:
267*2912Sartem 			rc = libhal_device_property_strlist_prepend (hal_ctx, udi, key, str_value, &error);
268*2912Sartem 			break;
269*2912Sartem 		case PROP_STRLIST_POST:
270*2912Sartem 			rc = libhal_device_property_strlist_append (hal_ctx, udi, key, str_value, &error);
271*2912Sartem 			break;
272*2912Sartem 		case PROP_STRLIST_REM:
273*2912Sartem 			rc = libhal_device_property_strlist_remove (hal_ctx, udi, key, str_value, &error);
274*2912Sartem 			break;
275*2912Sartem 		}
276*2912Sartem 		if (!rc) {
277*2912Sartem 			fprintf (stderr, "error: libhal_device_set_property: %s: %s\n", error.name, error.message);
278*2912Sartem 			dbus_error_free (&error);
279*2912Sartem 			return 1;
280*2912Sartem 		}
281*2912Sartem 	}
282*2912Sartem 
283*2912Sartem 	return rc ? 0 : 1;
284*2912Sartem }
285*2912Sartem 
286*2912Sartem /**
287*2912Sartem  * @}
288*2912Sartem  */
289