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_unref(conn); 165*18c2aff7Sartem dbus_error_free(&error); 166*18c2aff7Sartem 167*18c2aff7Sartem return err; 168*18c2aff7Sartem } 169*18c2aff7Sartem 170*18c2aff7Sartem 171*18c2aff7Sartem void help() 172*18c2aff7Sartem { 173*18c2aff7Sartem fprintf(stderr, 174*18c2aff7Sartem "usage: hal-device [--help] [--add udi] [--remove udi] [udi]\n" 175*18c2aff7Sartem "Create, remove, or show HAL device. If no udi is given, shows all devices.\n" 176*18c2aff7Sartem "If udi doesn't start with a '/', '/org/freedesktop/Hal/devices/' is prepended.\n" 177*18c2aff7Sartem " -a, --add udi\t\tAdd new device.\n" 178*18c2aff7Sartem " \t\t\tReads property list in 'lshal' syntax from stdin.\n" 179*18c2aff7Sartem " -r, --remove udi\tRemove device.\n" 180*18c2aff7Sartem " -h, --help\t\tShow this text.\n" 181*18c2aff7Sartem ); 182*18c2aff7Sartem } 183*18c2aff7Sartem 184*18c2aff7Sartem 185*18c2aff7Sartem /* 186*18c2aff7Sartem * Dump all devices. 187*18c2aff7Sartem */ 188*18c2aff7Sartem int dump_devices(LibHalContext *hal_ctx, char *arg) 189*18c2aff7Sartem { 190*18c2aff7Sartem int i; 191*18c2aff7Sartem int num_devices; 192*18c2aff7Sartem char **device_names; 193*18c2aff7Sartem DBusError error; 194*18c2aff7Sartem char *udi = NULL; 195*18c2aff7Sartem 196*18c2aff7Sartem if (arg) { 197*18c2aff7Sartem if (*arg == '/') { 198*18c2aff7Sartem udi = arg; 199*18c2aff7Sartem } else { 200*18c2aff7Sartem #ifdef HAVE_ASPRINTF 201*18c2aff7Sartem asprintf(&udi, "/org/freedesktop/Hal/devices/%s", arg); 202*18c2aff7Sartem #else 203*18c2aff7Sartem udi = calloc(1, sizeof ("/org/freedesktop/Hal/devices/%s") + strlen(arg)); 204*18c2aff7Sartem sprintf(udi, "/org/freedesktop/Hal/devices/%s", arg); 205*18c2aff7Sartem 206*18c2aff7Sartem #endif 207*18c2aff7Sartem } 208*18c2aff7Sartem } 209*18c2aff7Sartem 210*18c2aff7Sartem dbus_error_init(&error); 211*18c2aff7Sartem 212*18c2aff7Sartem if (!udi) { 213*18c2aff7Sartem if (!(device_names = libhal_get_all_devices(hal_ctx, &num_devices, &error))) { 214*18c2aff7Sartem fprintf(stderr, "Empty HAL device list.\n"); 215*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 216*18c2aff7Sartem return 31; 217*18c2aff7Sartem } 218*18c2aff7Sartem } else { 219*18c2aff7Sartem device_names = calloc(2, sizeof *device_names); 220*18c2aff7Sartem device_names[0] = strdup(udi); 221*18c2aff7Sartem num_devices = 1; 222*18c2aff7Sartem } 223*18c2aff7Sartem 224*18c2aff7Sartem for(i = 0; i < num_devices; i++) { 225*18c2aff7Sartem LibHalPropertySet *props; 226*18c2aff7Sartem LibHalPropertySetIterator it; 227*18c2aff7Sartem int type; 228*18c2aff7Sartem 229*18c2aff7Sartem if (!(props = libhal_device_get_all_properties(hal_ctx, device_names[i], &error))) { 230*18c2aff7Sartem fprintf(stderr, "%s: %s\n", error.name, error.message); 231*18c2aff7Sartem dbus_error_init(&error); 232*18c2aff7Sartem continue; 233*18c2aff7Sartem } 234*18c2aff7Sartem 235*18c2aff7Sartem if (!udi) 236*18c2aff7Sartem printf("%d: ", i); 237*18c2aff7Sartem printf("udi = '%s'\n", device_names[i]); 238*18c2aff7Sartem 239*18c2aff7Sartem for(libhal_psi_init(&it, props); libhal_psi_has_more(&it); libhal_psi_next(&it)) { 240*18c2aff7Sartem type = libhal_psi_get_type(&it); 241*18c2aff7Sartem switch (type) { 242*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_STRING: 243*18c2aff7Sartem printf(" %s = '%s' (string)\n", 244*18c2aff7Sartem libhal_psi_get_key(&it), 245*18c2aff7Sartem libhal_psi_get_string(&it) 246*18c2aff7Sartem ); 247*18c2aff7Sartem break; 248*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_INT32: 249*18c2aff7Sartem printf(" %s = %d (0x%x) (int)\n", 250*18c2aff7Sartem libhal_psi_get_key(&it), 251*18c2aff7Sartem libhal_psi_get_int(&it), 252*18c2aff7Sartem libhal_psi_get_int(&it) 253*18c2aff7Sartem ); 254*18c2aff7Sartem break; 255*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_UINT64: 256*18c2aff7Sartem printf(" %s = %lld (0x%llx) (uint64)\n", 257*18c2aff7Sartem libhal_psi_get_key(&it), 258*18c2aff7Sartem (long long) libhal_psi_get_uint64(&it), 259*18c2aff7Sartem (long long) libhal_psi_get_uint64(&it) 260*18c2aff7Sartem ); 261*18c2aff7Sartem break; 262*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_DOUBLE: 263*18c2aff7Sartem printf(" %s = %g (double)\n", 264*18c2aff7Sartem libhal_psi_get_key(&it), 265*18c2aff7Sartem libhal_psi_get_double(&it) 266*18c2aff7Sartem ); 267*18c2aff7Sartem break; 268*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_BOOLEAN: 269*18c2aff7Sartem printf(" %s = %s (bool)\n", 270*18c2aff7Sartem libhal_psi_get_key(&it), 271*18c2aff7Sartem libhal_psi_get_bool(&it) ? "true" : "false" 272*18c2aff7Sartem ); 273*18c2aff7Sartem break; 274*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_STRLIST: 275*18c2aff7Sartem { 276*18c2aff7Sartem char **strlist; 277*18c2aff7Sartem 278*18c2aff7Sartem printf (" %s = { ", libhal_psi_get_key(&it)); 279*18c2aff7Sartem strlist = libhal_psi_get_strlist(&it); 280*18c2aff7Sartem while (*strlist) { 281*18c2aff7Sartem printf("'%s'%s", *strlist, strlist[1] ? ", " : ""); 282*18c2aff7Sartem strlist++; 283*18c2aff7Sartem } 284*18c2aff7Sartem printf(" } (string list)\n"); 285*18c2aff7Sartem } 286*18c2aff7Sartem break; 287*18c2aff7Sartem default: 288*18c2aff7Sartem printf("Unknown type %d = 0x%02x\n", type, type); 289*18c2aff7Sartem break; 290*18c2aff7Sartem } 291*18c2aff7Sartem } 292*18c2aff7Sartem 293*18c2aff7Sartem libhal_free_property_set(props); 294*18c2aff7Sartem printf("\n"); 295*18c2aff7Sartem } 296*18c2aff7Sartem 297*18c2aff7Sartem libhal_free_string_array(device_names); 298*18c2aff7Sartem dbus_error_free(&error); 299*18c2aff7Sartem 300*18c2aff7Sartem return 0; 301*18c2aff7Sartem } 302*18c2aff7Sartem 303*18c2aff7Sartem 304*18c2aff7Sartem int remove_udi(LibHalContext *hal_ctx, char *arg) 305*18c2aff7Sartem { 306*18c2aff7Sartem DBusError error; 307*18c2aff7Sartem char *udi; 308*18c2aff7Sartem 309*18c2aff7Sartem if (!arg) return 11; 310*18c2aff7Sartem 311*18c2aff7Sartem if (*arg == '/') { 312*18c2aff7Sartem udi = arg; 313*18c2aff7Sartem } else { 314*18c2aff7Sartem #ifdef HAVE_ASPRINTF 315*18c2aff7Sartem asprintf(&udi, "/org/freedesktop/Hal/devices/%s", arg); 316*18c2aff7Sartem #else 317*18c2aff7Sartem udi = calloc(1, sizeof ("/org/freedesktop/Hal/devices/%s") + strlen(arg)); 318*18c2aff7Sartem sprintf(udi, "/org/freedesktop/Hal/devices/%s", arg); 319*18c2aff7Sartem #endif 320*18c2aff7Sartem 321*18c2aff7Sartem } 322*18c2aff7Sartem 323*18c2aff7Sartem dbus_error_init(&error); 324*18c2aff7Sartem 325*18c2aff7Sartem if (opt.remove) { 326*18c2aff7Sartem if (!libhal_remove_device(hal_ctx, udi, &error)) { 327*18c2aff7Sartem fprintf(stderr, "%s: %s\n", error.name, error.message); 328*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 329*18c2aff7Sartem return 12; 330*18c2aff7Sartem } 331*18c2aff7Sartem 332*18c2aff7Sartem fprintf(stderr, "removed: %s\n", udi); 333*18c2aff7Sartem return 13; 334*18c2aff7Sartem } 335*18c2aff7Sartem 336*18c2aff7Sartem return 0; 337*18c2aff7Sartem } 338*18c2aff7Sartem 339*18c2aff7Sartem 340*18c2aff7Sartem int add_udi(LibHalContext *hal_ctx, char *arg) 341*18c2aff7Sartem { 342*18c2aff7Sartem DBusError error; 343*18c2aff7Sartem dbus_bool_t dev_exists = FALSE; 344*18c2aff7Sartem char *udi = NULL, buf[1024]; 345*18c2aff7Sartem lh_prop_t *prop; 346*18c2aff7Sartem int err; 347*18c2aff7Sartem 348*18c2aff7Sartem if (!arg) 349*18c2aff7Sartem return 21; 350*18c2aff7Sartem 351*18c2aff7Sartem if (*arg == '/') { 352*18c2aff7Sartem udi = arg; 353*18c2aff7Sartem } else { 354*18c2aff7Sartem #ifdef HAVE_ASPRINTF 355*18c2aff7Sartem asprintf(&udi, "/org/freedesktop/Hal/devices/%s", arg); 356*18c2aff7Sartem #else 357*18c2aff7Sartem udi = calloc(1, sizeof ("/org/freedesktop/Hal/devices/%s") + strlen(arg)); 358*18c2aff7Sartem sprintf(udi, "/org/freedesktop/Hal/devices/%s", arg); 359*18c2aff7Sartem #endif 360*18c2aff7Sartem } 361*18c2aff7Sartem 362*18c2aff7Sartem if (udi) 363*18c2aff7Sartem new_dev.udi = strdup(udi); 364*18c2aff7Sartem 365*18c2aff7Sartem dbus_error_init(&error); 366*18c2aff7Sartem 367*18c2aff7Sartem if (udi) 368*18c2aff7Sartem dev_exists = libhal_device_exists(hal_ctx, udi, &error); 369*18c2aff7Sartem 370*18c2aff7Sartem if (dev_exists) { 371*18c2aff7Sartem new_dev.real_udi = strdup(new_dev.udi); 372*18c2aff7Sartem } else { 373*18c2aff7Sartem new_dev.real_udi = libhal_new_device(hal_ctx, &error); 374*18c2aff7Sartem 375*18c2aff7Sartem if (!new_dev.real_udi) { 376*18c2aff7Sartem fprintf(stderr, "%s: %s\n", error.name, error.message); 377*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 378*18c2aff7Sartem free(new_dev.real_udi); 379*18c2aff7Sartem 380*18c2aff7Sartem return 22; 381*18c2aff7Sartem } 382*18c2aff7Sartem 383*18c2aff7Sartem printf("tmp udi: %s\n", new_dev.real_udi); 384*18c2aff7Sartem } 385*18c2aff7Sartem 386*18c2aff7Sartem prop = NULL; 387*18c2aff7Sartem 388*18c2aff7Sartem while (fgets(buf, sizeof buf, stdin)) { 389*18c2aff7Sartem process_property(hal_ctx, buf, &prop); 390*18c2aff7Sartem } 391*18c2aff7Sartem 392*18c2aff7Sartem err = add_properties(hal_ctx, &new_dev, prop); 393*18c2aff7Sartem 394*18c2aff7Sartem prop = free_properties(prop); 395*18c2aff7Sartem 396*18c2aff7Sartem if (!dev_exists) { 397*18c2aff7Sartem if (!libhal_device_commit_to_gdl(hal_ctx, new_dev.real_udi, new_dev.udi, &error)) { 398*18c2aff7Sartem fprintf(stderr, "%s: %s\n", error.name, error.message); 399*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 400*18c2aff7Sartem free(new_dev.real_udi); 401*18c2aff7Sartem 402*18c2aff7Sartem err = err ? err : 23; 403*18c2aff7Sartem } 404*18c2aff7Sartem } 405*18c2aff7Sartem 406*18c2aff7Sartem printf("%s: %s\n", dev_exists ? "merged": "created", new_dev.udi); 407*18c2aff7Sartem 408*18c2aff7Sartem return err; 409*18c2aff7Sartem } 410*18c2aff7Sartem 411*18c2aff7Sartem 412*18c2aff7Sartem char *skip_space(char *s) 413*18c2aff7Sartem { 414*18c2aff7Sartem while (isspace(*s)) s++; 415*18c2aff7Sartem 416*18c2aff7Sartem return s; 417*18c2aff7Sartem } 418*18c2aff7Sartem 419*18c2aff7Sartem 420*18c2aff7Sartem char *skip_non_eq_or_space(char *s) 421*18c2aff7Sartem { 422*18c2aff7Sartem while (*s && *s != '=' && !isspace(*s)) 423*18c2aff7Sartem s++; 424*18c2aff7Sartem 425*18c2aff7Sartem return s; 426*18c2aff7Sartem } 427*18c2aff7Sartem 428*18c2aff7Sartem 429*18c2aff7Sartem char *skip_number(char *s) 430*18c2aff7Sartem { 431*18c2aff7Sartem while (*s == '-' || *s == '+' || *s == '.' || isdigit(*s)) 432*18c2aff7Sartem s++; 433*18c2aff7Sartem 434*18c2aff7Sartem return s; 435*18c2aff7Sartem } 436*18c2aff7Sartem 437*18c2aff7Sartem 438*18c2aff7Sartem char *skip_nonquote(char *s) 439*18c2aff7Sartem { 440*18c2aff7Sartem while (*s && *s != '\'') 441*18c2aff7Sartem s++; 442*18c2aff7Sartem 443*18c2aff7Sartem return s; 444*18c2aff7Sartem } 445*18c2aff7Sartem 446*18c2aff7Sartem 447*18c2aff7Sartem void process_property(LibHalContext *hal_ctx, char *buf, lh_prop_t **prop) 448*18c2aff7Sartem { 449*18c2aff7Sartem char *s, *s1; 450*18c2aff7Sartem char *key, *s_val = NULL; 451*18c2aff7Sartem lh_prop_t *p; 452*18c2aff7Sartem unsigned len; 453*18c2aff7Sartem int remove = 0; 454*18c2aff7Sartem 455*18c2aff7Sartem s = skip_space(buf); 456*18c2aff7Sartem 457*18c2aff7Sartem if (*s == '-') { 458*18c2aff7Sartem remove = 1; 459*18c2aff7Sartem s = skip_space(s + 1); 460*18c2aff7Sartem } 461*18c2aff7Sartem 462*18c2aff7Sartem if ((s1 = skip_number(s), s1 != s) && *s1 == ':') s = skip_space(s1 + 1); 463*18c2aff7Sartem 464*18c2aff7Sartem s = skip_non_eq_or_space(key = s); 465*18c2aff7Sartem *s++ = 0; 466*18c2aff7Sartem if (!*key) 467*18c2aff7Sartem return; 468*18c2aff7Sartem 469*18c2aff7Sartem if (*key == '#') 470*18c2aff7Sartem return; 471*18c2aff7Sartem 472*18c2aff7Sartem if (*s == '=') 473*18c2aff7Sartem s++; 474*18c2aff7Sartem s = skip_space(s); 475*18c2aff7Sartem 476*18c2aff7Sartem if (!*s) 477*18c2aff7Sartem remove = 1; 478*18c2aff7Sartem 479*18c2aff7Sartem p = calloc(1, sizeof *p); 480*18c2aff7Sartem p->type = LIBHAL_PROPERTY_TYPE_INVALID; 481*18c2aff7Sartem p->key = strdup(key); 482*18c2aff7Sartem 483*18c2aff7Sartem if (remove) { 484*18c2aff7Sartem p->next = *prop; 485*18c2aff7Sartem *prop = p; 486*18c2aff7Sartem return; 487*18c2aff7Sartem } 488*18c2aff7Sartem 489*18c2aff7Sartem if (*s == '\'') { 490*18c2aff7Sartem s_val = s + 1; 491*18c2aff7Sartem s = strrchr(s_val, '\''); 492*18c2aff7Sartem *(s ? s : s_val) = 0; 493*18c2aff7Sartem p->type = LIBHAL_PROPERTY_TYPE_STRING; 494*18c2aff7Sartem p->v.str_value = strdup(s_val); 495*18c2aff7Sartem } else if (*s == '{') { 496*18c2aff7Sartem s_val = s + 1; 497*18c2aff7Sartem s1 = strrchr(s_val, '}'); 498*18c2aff7Sartem if (s1) *s1 = 0; 499*18c2aff7Sartem p->type = LIBHAL_PROPERTY_TYPE_STRLIST; 500*18c2aff7Sartem len = 0; 501*18c2aff7Sartem p->v.strlist_value = calloc(1, sizeof *p->v.strlist_value); 502*18c2aff7Sartem while (*s_val++ == '\'') { 503*18c2aff7Sartem s = skip_nonquote(s_val); 504*18c2aff7Sartem if (*s) *s++ = 0; 505*18c2aff7Sartem p->v.strlist_value = realloc(p->v.strlist_value, (len + 2) * sizeof *p->v.strlist_value); 506*18c2aff7Sartem p->v.strlist_value[len] = strdup(s_val); 507*18c2aff7Sartem p->v.strlist_value[++len] = NULL; 508*18c2aff7Sartem s_val = skip_nonquote(s); 509*18c2aff7Sartem } 510*18c2aff7Sartem } else if (!strncmp(s, "true", 4)) { 511*18c2aff7Sartem s += 4; 512*18c2aff7Sartem p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN; 513*18c2aff7Sartem p->v.bool_value = TRUE; 514*18c2aff7Sartem } else if (!strncmp(s, "false", 5)) { 515*18c2aff7Sartem s += 5; 516*18c2aff7Sartem p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN; 517*18c2aff7Sartem p->v.bool_value = FALSE; 518*18c2aff7Sartem } else if ((s1 = skip_number(s)) != s) { 519*18c2aff7Sartem if (strstr(s1, "(int)")) { 520*18c2aff7Sartem *s1++ = 0; 521*18c2aff7Sartem p->type = LIBHAL_PROPERTY_TYPE_INT32; 522*18c2aff7Sartem p->v.int_value = strtol(s, NULL, 10); 523*18c2aff7Sartem } else if (strstr(s1, "(uint64)")) { 524*18c2aff7Sartem *s1++ = 0; 525*18c2aff7Sartem p->type = LIBHAL_PROPERTY_TYPE_UINT64; 526*18c2aff7Sartem p->v.uint64_value = strtoull(s, NULL, 10); 527*18c2aff7Sartem } else if (strstr(s1, "(double)")) { 528*18c2aff7Sartem p->type = LIBHAL_PROPERTY_TYPE_DOUBLE; 529*18c2aff7Sartem p->v.double_value = strtod(s, NULL); 530*18c2aff7Sartem } 531*18c2aff7Sartem 532*18c2aff7Sartem s = s1; 533*18c2aff7Sartem } 534*18c2aff7Sartem 535*18c2aff7Sartem if (p->type == LIBHAL_PROPERTY_TYPE_INVALID) { 536*18c2aff7Sartem free(p->key); 537*18c2aff7Sartem free(p); 538*18c2aff7Sartem } else { 539*18c2aff7Sartem p->next = *prop; 540*18c2aff7Sartem *prop = p; 541*18c2aff7Sartem } 542*18c2aff7Sartem } 543*18c2aff7Sartem 544*18c2aff7Sartem 545*18c2aff7Sartem int add_properties(LibHalContext *hal_ctx, new_dev_t *nd, lh_prop_t *prop) 546*18c2aff7Sartem { 547*18c2aff7Sartem DBusError error; 548*18c2aff7Sartem lh_prop_t *p; 549*18c2aff7Sartem char *udi2 = NULL, *udi3 = NULL, **s; 550*18c2aff7Sartem LibHalPropertyType old_type; 551*18c2aff7Sartem 552*18c2aff7Sartem dbus_error_init(&error); 553*18c2aff7Sartem 554*18c2aff7Sartem for(p = prop; p; p = p->next) { 555*18c2aff7Sartem if (!strcmp(p->key, "udi") && p->type == LIBHAL_PROPERTY_TYPE_STRING) { 556*18c2aff7Sartem udi2 = p->v.str_value; 557*18c2aff7Sartem continue; 558*18c2aff7Sartem } 559*18c2aff7Sartem 560*18c2aff7Sartem old_type = libhal_device_get_property_type(hal_ctx, nd->real_udi, p->key, &error); 561*18c2aff7Sartem dbus_error_init(&error); 562*18c2aff7Sartem 563*18c2aff7Sartem if (old_type != LIBHAL_PROPERTY_TYPE_INVALID && 564*18c2aff7Sartem ( p->type != old_type || p->type == LIBHAL_PROPERTY_TYPE_STRLIST)) { 565*18c2aff7Sartem if (!libhal_device_remove_property(hal_ctx, nd->real_udi, p->key, &error)) { 566*18c2aff7Sartem fprintf(stderr, "%s: %s\n", error.name, error.message); 567*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 568*18c2aff7Sartem return 41; 569*18c2aff7Sartem } 570*18c2aff7Sartem } 571*18c2aff7Sartem 572*18c2aff7Sartem switch (p->type) { 573*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_INVALID: 574*18c2aff7Sartem break; 575*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_BOOLEAN: 576*18c2aff7Sartem if (!libhal_device_set_property_bool(hal_ctx, nd->real_udi, p->key, p->v.bool_value, &error)) { 577*18c2aff7Sartem fprintf(stderr, "%s: %s\n", error.name, error.message); 578*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 579*18c2aff7Sartem return 42; 580*18c2aff7Sartem } 581*18c2aff7Sartem break; 582*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_INT32: 583*18c2aff7Sartem if (!libhal_device_set_property_int(hal_ctx, nd->real_udi, p->key, p->v.int_value, &error)) { 584*18c2aff7Sartem fprintf(stderr, "%s: %s\n", error.name, error.message); 585*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 586*18c2aff7Sartem return 42; 587*18c2aff7Sartem } 588*18c2aff7Sartem break; 589*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_UINT64: 590*18c2aff7Sartem if (!libhal_device_set_property_uint64(hal_ctx, nd->real_udi, p->key, p->v.uint64_value, &error)) { 591*18c2aff7Sartem fprintf(stderr, "%s: %s\n", error.name, error.message); 592*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 593*18c2aff7Sartem return 42; 594*18c2aff7Sartem } 595*18c2aff7Sartem break; 596*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_DOUBLE: 597*18c2aff7Sartem if (!libhal_device_set_property_double(hal_ctx, nd->real_udi, p->key, p->v.double_value, &error)) { 598*18c2aff7Sartem fprintf(stderr, "%s: %s\n", error.name, error.message); 599*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 600*18c2aff7Sartem return 42; 601*18c2aff7Sartem } 602*18c2aff7Sartem break; 603*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_STRING: 604*18c2aff7Sartem if (!strcmp(p->key, "info.udi")) udi3 = p->v.str_value; 605*18c2aff7Sartem if (!libhal_device_set_property_string(hal_ctx, nd->real_udi, p->key, p->v.str_value, &error)) { 606*18c2aff7Sartem fprintf(stderr, "%s: %s\n", error.name, error.message); 607*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 608*18c2aff7Sartem return 42; 609*18c2aff7Sartem } 610*18c2aff7Sartem break; 611*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_STRLIST: 612*18c2aff7Sartem for(s = p->v.strlist_value; *s; s++) { 613*18c2aff7Sartem if (!libhal_device_property_strlist_append(hal_ctx, nd->real_udi, p->key, *s, &error)) { 614*18c2aff7Sartem fprintf(stderr, "%s: %s\n", error.name, error.message); 615*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error); 616*18c2aff7Sartem return 42; 617*18c2aff7Sartem } 618*18c2aff7Sartem } 619*18c2aff7Sartem break; 620*18c2aff7Sartem } 621*18c2aff7Sartem } 622*18c2aff7Sartem 623*18c2aff7Sartem if (udi2) udi3 = NULL; 624*18c2aff7Sartem if (udi3) udi2 = udi3; 625*18c2aff7Sartem 626*18c2aff7Sartem if (udi2 && !nd->udi) 627*18c2aff7Sartem nd->udi = strdup(udi2); 628*18c2aff7Sartem 629*18c2aff7Sartem return 0; 630*18c2aff7Sartem } 631*18c2aff7Sartem 632*18c2aff7Sartem 633*18c2aff7Sartem lh_prop_t *free_properties(lh_prop_t *prop) 634*18c2aff7Sartem { 635*18c2aff7Sartem lh_prop_t *next; 636*18c2aff7Sartem char **s; 637*18c2aff7Sartem 638*18c2aff7Sartem for(; prop; prop = next) { 639*18c2aff7Sartem next = prop->next; 640*18c2aff7Sartem 641*18c2aff7Sartem free(prop->key); 642*18c2aff7Sartem if (prop->type == LIBHAL_PROPERTY_TYPE_STRING) free(prop->v.str_value); 643*18c2aff7Sartem if (prop->type == LIBHAL_PROPERTY_TYPE_STRLIST && prop->v.strlist_value) { 644*18c2aff7Sartem for(s = prop->v.strlist_value; *s; ) free(*s++); 645*18c2aff7Sartem free(prop->v.strlist_value); 646*18c2aff7Sartem } 647*18c2aff7Sartem free(prop); 648*18c2aff7Sartem } 649*18c2aff7Sartem 650*18c2aff7Sartem return NULL; 651*18c2aff7Sartem } 652