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