00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <unistd.h>
00034 #include <getopt.h>
00035 #include <pwd.h>
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <fcntl.h>
00039 #include <errno.h>
00040 #include <signal.h>
00041
00042 #include <dbus/dbus.h>
00043 #include <dbus/dbus-glib.h>
00044
00045 #include <libhal/libhal.h>
00046
00047 #include "logger.h"
00048 #include "hald.h"
00049 #include "device_store.h"
00050 #include "device_info.h"
00051 #include "osspec.h"
00052
00053
00061 static DBusConnection *dbus_connection;
00062
00076 static void
00077 raise_no_such_device (DBusConnection * connection,
00078 DBusMessage * in_reply_to, const char *udi)
00079 {
00080 char buf[512];
00081 DBusMessage *reply;
00082
00083 snprintf (buf, 511, "No device with id %s", udi);
00084 HAL_WARNING ((buf));
00085 reply = dbus_message_new_error (in_reply_to,
00086 "org.freedesktop.Hal.NoSuchDevice",
00087 buf);
00088 if (reply == NULL)
00089 DIE (("No memory"));
00090 if (!dbus_connection_send (connection, reply, NULL))
00091 DIE (("No memory"));
00092 dbus_message_unref (reply);
00093 }
00094
00101 static void
00102 raise_udi_in_use (DBusConnection * connection,
00103 DBusMessage * in_reply_to, const char *udi)
00104 {
00105 char buf[512];
00106 DBusMessage *reply;
00107
00108 snprintf (buf, 511, "Unique device id '%s' is already in use",
00109 udi);
00110 HAL_WARNING ((buf));
00111 reply = dbus_message_new_error (in_reply_to,
00112 "org.freedesktop.Hal.UdiInUse",
00113 buf);
00114 if (reply == NULL)
00115 DIE (("No memory"));
00116 if (!dbus_connection_send (connection, reply, NULL))
00117 DIE (("No memory"));
00118 dbus_message_unref (reply);
00119 }
00120
00128 static void
00129 raise_no_such_property (DBusConnection * connection,
00130 DBusMessage * in_reply_to,
00131 const char *device_id, const char *key)
00132 {
00133 char buf[512];
00134 DBusMessage *reply;
00135
00136 snprintf (buf, 511, "No property %s on device with id %s", key,
00137 device_id);
00138 HAL_WARNING ((buf));
00139 reply = dbus_message_new_error (in_reply_to,
00140 "org.freedesktop.Hal.NoSuchProperty",
00141 buf);
00142 if (reply == NULL)
00143 DIE (("No memory"));
00144 if (!dbus_connection_send (connection, reply, NULL))
00145 DIE (("No memory"));
00146 dbus_message_unref (reply);
00147 }
00148
00156 static void
00157 raise_property_type_error (DBusConnection * connection,
00158 DBusMessage * in_reply_to,
00159 const char *device_id, const char *key)
00160 {
00161 char buf[512];
00162 DBusMessage *reply;
00163
00164 snprintf (buf, 511,
00165 "Type mismatch setting property %s on device with id %s",
00166 key, device_id);
00167 HAL_WARNING ((buf));
00168 reply = dbus_message_new_error (in_reply_to,
00169 "org.freedesktop.Hal.TypeMismatch",
00170 buf);
00171 if (reply == NULL)
00172 DIE (("No memory"));
00173 if (!dbus_connection_send (connection, reply, NULL))
00174 DIE (("No memory"));
00175 dbus_message_unref (reply);
00176 }
00177
00185 static void
00186 raise_syntax (DBusConnection * connection,
00187 DBusMessage * in_reply_to, const char *method_name)
00188 {
00189 char buf[512];
00190 DBusMessage *reply;
00191
00192 snprintf (buf, 511,
00193 "There is a syntax error in the invocation of "
00194 "the method %s", method_name);
00195 HAL_WARNING ((buf));
00196 reply = dbus_message_new_error (in_reply_to,
00197 "org.freedesktop.Hal.SyntaxError",
00198 buf);
00199 if (reply == NULL)
00200 DIE (("No memory"));
00201 if (!dbus_connection_send (connection, reply, NULL))
00202 DIE (("No memory"));
00203 dbus_message_unref (reply);
00204 }
00205
00226 static DBusHandlerResult
00227 manager_get_all_devices (DBusConnection * connection,
00228 DBusMessage * message)
00229 {
00230 DBusMessage *reply;
00231 DBusMessageIter iter;
00232 DBusMessageIter iter_array;
00233 HalDevice *d;
00234 const char *udi;
00235 HalDeviceIterator iter_device;
00236
00237 HAL_TRACE (("entering"));
00238
00239 reply = dbus_message_new_method_return (message);
00240 if (reply == NULL)
00241 DIE (("No memory"));
00242
00243 dbus_message_iter_init (reply, &iter);
00244 dbus_message_iter_append_array (&iter, &iter_array,
00245 DBUS_TYPE_STRING);
00246
00247 for (ds_device_iter_begin (&iter_device);
00248 ds_device_iter_has_more (&iter_device);
00249 ds_device_iter_next (&iter_device)) {
00250 d = ds_device_iter_get (&iter_device);
00251
00252 if (d->in_gdl) {
00253 udi = ds_device_get_udi (d);
00254 dbus_message_iter_append_string (&iter_array, udi);
00255 }
00256 }
00257
00258 if (!dbus_connection_send (connection, reply, NULL))
00259 DIE (("No memory"));
00260
00261 dbus_message_unref (reply);
00262
00263 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00264 }
00265
00266
00279 static DBusHandlerResult
00280 manager_find_device_string_match (DBusConnection * connection,
00281 DBusMessage * message)
00282 {
00283 DBusMessage *reply;
00284 DBusMessageIter iter;
00285 DBusMessageIter iter_array;
00286 DBusError error;
00287 const char *key;
00288 const char *value;
00289 HalDeviceIterator iter_device;
00290 int type;
00291 HalDevice *device;
00292
00293 HAL_TRACE (("entering"));
00294
00295 dbus_error_init (&error);
00296 if (!dbus_message_get_args (message, &error,
00297 DBUS_TYPE_STRING, &key,
00298 DBUS_TYPE_STRING, &value,
00299 DBUS_TYPE_INVALID)) {
00300 raise_syntax (connection, message,
00301 "Manager.FindDeviceStringMatch");
00302 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00303 }
00304
00305 reply = dbus_message_new_method_return (message);
00306 if (reply == NULL)
00307 DIE (("No memory"));
00308
00309 dbus_message_iter_init (reply, &iter);
00310 dbus_message_iter_append_array (&iter, &iter_array,
00311 DBUS_TYPE_STRING);
00312
00313 for (ds_device_iter_begin (&iter_device);
00314 ds_device_iter_has_more (&iter_device);
00315 ds_device_iter_next (&iter_device)) {
00316 device = ds_device_iter_get (&iter_device);
00317
00318 if (!device->in_gdl)
00319 continue;
00320
00321 type = ds_property_get_type (device, key);
00322 if (type == DBUS_TYPE_STRING) {
00323 if (strcmp (ds_property_get_string (device, key),
00324 value) == 0)
00325 dbus_message_iter_append_string
00326 (&iter_array, device->udi);
00327 }
00328 }
00329
00330
00331 if (!dbus_connection_send (connection, reply, NULL))
00332 DIE (("No memory"));
00333
00334 dbus_message_unref (reply);
00335
00336 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00337 }
00338
00339
00350 static DBusHandlerResult
00351 manager_find_device_by_capability (DBusConnection * connection,
00352 DBusMessage * message)
00353 {
00354 DBusMessage *reply;
00355 DBusMessageIter iter;
00356 DBusMessageIter iter_array;
00357 DBusError error;
00358 const char *capability;
00359 HalDeviceIterator iter_device;
00360 int type;
00361 HalDevice *device;
00362
00363 HAL_TRACE (("entering"));
00364
00365 dbus_error_init (&error);
00366 if (!dbus_message_get_args (message, &error,
00367 DBUS_TYPE_STRING, &capability,
00368 DBUS_TYPE_INVALID)) {
00369 raise_syntax (connection, message,
00370 "Manager.FindDeviceByCapability");
00371 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00372 }
00373
00374 reply = dbus_message_new_method_return (message);
00375 if (reply == NULL)
00376 DIE (("No memory"));
00377
00378 dbus_message_iter_init (reply, &iter);
00379 dbus_message_iter_append_array (&iter, &iter_array,
00380 DBUS_TYPE_STRING);
00381
00382 for (ds_device_iter_begin (&iter_device);
00383 ds_device_iter_has_more (&iter_device);
00384 ds_device_iter_next (&iter_device)) {
00385 device = ds_device_iter_get (&iter_device);
00386
00387 if (!device->in_gdl)
00388 continue;
00389
00390 type = ds_property_get_type (device, "info.capabilities");
00391 if (type == DBUS_TYPE_STRING) {
00392 if (strstr
00393 (ds_property_get_string
00394 (device, "info.capabilities"),
00395 capability) != NULL)
00396 dbus_message_iter_append_string
00397 (&iter_array, device->udi);
00398 }
00399 }
00400
00401 if (!dbus_connection_send (connection, reply, NULL))
00402 DIE (("No memory"));
00403
00404 dbus_message_unref (reply);
00405
00406 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00407 }
00408
00409
00420 static DBusHandlerResult
00421 manager_device_exists (DBusConnection * connection, DBusMessage * message)
00422 {
00423 DBusMessage *reply;
00424 DBusMessageIter iter;
00425 DBusError error;
00426 HalDevice *d;
00427 const char *udi;
00428
00429 dbus_error_init (&error);
00430 if (!dbus_message_get_args (message, &error,
00431 DBUS_TYPE_STRING, &udi,
00432 DBUS_TYPE_INVALID)) {
00433 raise_syntax (connection, message, "Manager.DeviceExists");
00434 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00435 }
00436
00437 HAL_TRACE (("entering, udi=%s", udi));
00438
00439 d = ds_device_find (udi);
00440
00441 reply = dbus_message_new_method_return (message);
00442 dbus_message_iter_init (reply, &iter);
00443 dbus_message_iter_append_boolean (&iter, d != NULL);
00444
00445 if (reply == NULL)
00446 DIE (("No memory"));
00447
00448 if (!dbus_connection_send (connection, reply, NULL))
00449 DIE (("No memory"));
00450
00451 dbus_message_unref (reply);
00452 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00453 }
00454
00460 static void
00461 manager_send_signal_device_added (const char *udi)
00462 {
00463 DBusMessage *message;
00464 DBusMessageIter iter;
00465
00466 HAL_TRACE (("entering, udi=%s", udi));
00467
00468 message = dbus_message_new_signal ("/org/freedesktop/Hal/Manager",
00469 "org.freedesktop.Hal.Manager",
00470 "DeviceAdded");
00471
00472 dbus_message_iter_init (message, &iter);
00473 dbus_message_iter_append_string (&iter, udi);
00474
00475 if (!dbus_connection_send (dbus_connection, message, NULL))
00476 DIE (("error broadcasting message"));
00477
00478 dbus_message_unref (message);
00479 }
00480
00486 static void
00487 manager_send_signal_device_removed (const char *udi)
00488 {
00489 DBusMessage *message;
00490 DBusMessageIter iter;
00491
00492 HAL_TRACE (("entering, udi=%s", udi));
00493
00494 message = dbus_message_new_signal ("/org/freedesktop/Hal/Manager",
00495 "org.freedesktop.Hal.Manager",
00496 "DeviceRemoved");
00497
00498 dbus_message_iter_init (message, &iter);
00499 dbus_message_iter_append_string (&iter, udi);
00500
00501 if (!dbus_connection_send (dbus_connection, message, NULL))
00502 DIE (("error broadcasting message"));
00503
00504 dbus_message_unref (message);
00505 }
00506
00514 static void
00515 manager_send_signal_new_capability (const char *udi,
00516 const char *capability)
00517 {
00518 DBusMessage *message;
00519 DBusMessageIter iter;
00520
00521 HAL_TRACE (("entering, udi=%s, cap=%s", udi, capability));
00522
00523 message = dbus_message_new_signal ("/org/freedesktop/Hal/Manager",
00524 "org.freedesktop.Hal.Manager",
00525 "NewCapability");
00526
00527 dbus_message_iter_init (message, &iter);
00528 dbus_message_iter_append_string (&iter, udi);
00529 dbus_message_iter_append_string (&iter, capability);
00530
00531 if (!dbus_connection_send (dbus_connection, message, NULL))
00532 DIE (("error broadcasting message"));
00533
00534 dbus_message_unref (message);
00535 }
00536
00558 static DBusHandlerResult
00559 device_get_all_properties (DBusConnection * connection,
00560 DBusMessage * message)
00561 {
00562 DBusMessage *reply;
00563 DBusMessageIter iter;
00564 DBusMessageIter iter_dict;
00565 HalDevice *d;
00566 const char *udi;
00567 HalPropertyIterator iter_prop;
00568
00569 udi = dbus_message_get_path (message);
00570
00571 HAL_TRACE (("entering, udi=%s", udi));
00572
00573 d = ds_device_find (udi);
00574 if (d == NULL) {
00575 raise_no_such_device (connection, message, udi);
00576 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00577 }
00578
00579 reply = dbus_message_new_method_return (message);
00580 if (reply == NULL)
00581 DIE (("No memory"));
00582
00583 dbus_message_iter_init (reply, &iter);
00584 dbus_message_iter_append_dict (&iter, &iter_dict);
00585
00586 for (ds_property_iter_begin (d, &iter_prop);
00587 ds_property_iter_has_more (&iter_prop);
00588 ds_property_iter_next (&iter_prop)) {
00589 int type;
00590 HalProperty *p;
00591 const char *key;
00592
00593 p = ds_property_iter_get (&iter_prop);
00594 key = ds_property_iter_get_key (p);
00595 type = ds_property_iter_get_type (p);
00596
00597 dbus_message_iter_append_dict_key (&iter_dict, key);
00598
00599 switch (type) {
00600 case DBUS_TYPE_STRING:
00601 dbus_message_iter_append_string
00602 (&iter_dict,
00603 ds_property_iter_get_string (p));
00604 break;
00605 case DBUS_TYPE_INT32:
00606 dbus_message_iter_append_int32
00607 (&iter_dict,
00608 ds_property_iter_get_int (p));
00609 break;
00610 case DBUS_TYPE_DOUBLE:
00611 dbus_message_iter_append_double (
00612 &iter_dict,
00613 ds_property_iter_get_double (p));
00614 break;
00615 case DBUS_TYPE_BOOLEAN:
00616 dbus_message_iter_append_boolean
00617 (&iter_dict,
00618 ds_property_iter_get_bool (p));
00619 break;
00620
00621 default:
00622 HAL_WARNING (("Unknown property type %d", type));
00623 break;
00624 }
00625 }
00626
00627 if (!dbus_connection_send (connection, reply, NULL))
00628 DIE (("No memory"));
00629
00630 dbus_message_unref (reply);
00631
00632 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00633 }
00634
00635
00653 static DBusHandlerResult
00654 device_get_property (DBusConnection * connection, DBusMessage * message)
00655 {
00656 DBusMessage *reply;
00657 DBusMessageIter iter;
00658 DBusError error;
00659 HalDevice *d;
00660 const char *udi;
00661 char *key;
00662 int type;
00663 HalProperty *p;
00664
00665 udi = dbus_message_get_path (message);
00666
00667 HAL_TRACE (("entering, udi=%s", udi));
00668
00669 d = ds_device_find (udi);
00670 if (d == NULL) {
00671 raise_no_such_device (connection, message, udi);
00672 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00673 }
00674
00675 dbus_error_init (&error);
00676 if (!dbus_message_get_args (message, &error,
00677 DBUS_TYPE_STRING, &key,
00678 DBUS_TYPE_INVALID)) {
00679 raise_syntax (connection, message, "GetProperty");
00680 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00681 }
00682
00683 p = ds_property_find (d, key);
00684 if (p == NULL) {
00685 raise_no_such_property (connection, message, udi, key);
00686 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00687 }
00688
00689 reply = dbus_message_new_method_return (message);
00690 if (reply == NULL)
00691 DIE (("No memory"));
00692
00693 dbus_message_iter_init (reply, &iter);
00694
00695 type = ds_property_iter_get_type (p);
00696 switch (type) {
00697 case DBUS_TYPE_STRING:
00698 dbus_message_iter_append_string (&iter,
00699 ds_property_iter_get_string
00700 (p));
00701 break;
00702 case DBUS_TYPE_INT32:
00703 dbus_message_iter_append_int32 (&iter,
00704 ds_property_iter_get_int
00705 (p));
00706 break;
00707 case DBUS_TYPE_DOUBLE:
00708 dbus_message_iter_append_double (&iter,
00709 ds_property_iter_get_double
00710 (p));
00711 break;
00712 case DBUS_TYPE_BOOLEAN:
00713 dbus_message_iter_append_boolean (&iter,
00714 ds_property_iter_get_bool
00715 (p));
00716 break;
00717
00718 default:
00719 HAL_WARNING (("Unknown property type %d", type));
00720 break;
00721 }
00722
00723 if (!dbus_connection_send (connection, reply, NULL))
00724 DIE (("No memory"));
00725
00726 dbus_message_unref (reply);
00727
00728 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00729 }
00730
00731
00745 static DBusHandlerResult
00746 device_get_property_type (DBusConnection * connection,
00747 DBusMessage * message)
00748 {
00749 DBusMessage *reply;
00750 DBusMessageIter iter;
00751 DBusError error;
00752 HalDevice *d;
00753 const char *udi;
00754 char *key;
00755 HalProperty *p;
00756
00757 udi = dbus_message_get_path (message);
00758
00759 HAL_TRACE (("entering, udi=%s", udi));
00760
00761 d = ds_device_find (udi);
00762 if (d == NULL) {
00763 raise_no_such_device (connection, message, udi);
00764 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00765 }
00766
00767 dbus_error_init (&error);
00768 if (!dbus_message_get_args (message, &error,
00769 DBUS_TYPE_STRING, &key,
00770 DBUS_TYPE_INVALID)) {
00771 raise_syntax (connection, message, "GetPropertyType");
00772 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00773 }
00774
00775 p = ds_property_find (d, key);
00776 if (p == NULL) {
00777 raise_no_such_property (connection, message, udi, key);
00778 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00779 }
00780
00781 reply = dbus_message_new_method_return (message);
00782 if (reply == NULL)
00783 DIE (("No memory"));
00784
00785 dbus_message_iter_init (reply, &iter);
00786 dbus_message_iter_append_int32 (&iter,
00787 ds_property_iter_get_type (p));
00788
00789 if (!dbus_connection_send (connection, reply, NULL))
00790 DIE (("No memory"));
00791
00792 dbus_message_unref (reply);
00793
00794 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00795 }
00796
00797
00798
00817 static DBusHandlerResult
00818 device_set_property (DBusConnection * connection, DBusMessage * message)
00819 {
00820 const char *udi;
00821 char *key;
00822 int type;
00823 dbus_bool_t rc;
00824 HalDevice *device;
00825 DBusMessageIter iter;
00826 DBusMessage *reply;
00827
00828 HAL_TRACE (("entering"));
00829
00830 udi = dbus_message_get_path (message);
00831
00832 dbus_message_iter_init (message, &iter);
00833 type = dbus_message_iter_get_arg_type (&iter);
00834 if (type != DBUS_TYPE_STRING) {
00835 raise_syntax (connection, message, "SetProperty");
00836 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00837 }
00838 key = dbus_message_iter_get_string (&iter);
00839
00840 HAL_DEBUG (("udi=%s, key=%s", udi, key));
00841
00842 device = ds_device_find (udi);
00843 if (device == NULL) {
00844 raise_no_such_device (connection, message, udi);
00845 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00846 }
00847 dbus_message_iter_next (&iter);
00848
00851 type = dbus_message_iter_get_arg_type (&iter);
00852 rc = FALSE;
00853 switch (type) {
00854 case DBUS_TYPE_STRING:
00855 rc = ds_property_set_string (device, key,
00856 dbus_message_iter_get_string
00857 (&iter));
00858 break;
00859 case DBUS_TYPE_INT32:
00860 rc = ds_property_set_int (device, key,
00861 dbus_message_iter_get_int32
00862 (&iter));
00863 break;
00864 case DBUS_TYPE_DOUBLE:
00865 rc = ds_property_set_double (device, key,
00866 dbus_message_iter_get_double
00867 (&iter));
00868 break;
00869 case DBUS_TYPE_BOOLEAN:
00870 rc = ds_property_set_bool (device, key,
00871 dbus_message_iter_get_boolean
00872 (&iter));
00873 break;
00874
00875 default:
00876 HAL_WARNING (("Unsupported property type %d", type));
00877 break;
00878 }
00879
00880 if (!rc) {
00881 raise_property_type_error (connection, message, udi, key);
00882 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00883 }
00884
00885 reply = dbus_message_new_method_return (message);
00886 if (reply == NULL)
00887 DIE (("No memory"));
00888
00889 if (!dbus_connection_send (connection, reply, NULL))
00890 DIE (("No memory"));
00891
00892 dbus_message_unref (reply);
00893 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00894 }
00895
00896
00898 #define MAX_CAP_SIZE 2048
00899
00926 static DBusHandlerResult
00927 device_add_capability (DBusConnection * connection, DBusMessage * message)
00928 {
00929 const char *udi;
00930 const char *capability;
00931 const char *caps;
00932 HalDevice *d;
00933 DBusMessage *reply;
00934 DBusError error;
00935 char buf[MAX_CAP_SIZE];
00936
00937 HAL_TRACE (("entering"));
00938
00939 udi = dbus_message_get_path (message);
00940
00941 d = ds_device_find (udi);
00942 if (d == NULL) {
00943 raise_no_such_device (connection, message, udi);
00944 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00945 }
00946
00947 dbus_error_init (&error);
00948 if (!dbus_message_get_args (message, &error,
00949 DBUS_TYPE_STRING, &capability,
00950 DBUS_TYPE_INVALID)) {
00951 raise_syntax (connection, message, "AddCapability");
00952 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00953 }
00954
00955
00956 caps = ds_property_get_string (d, "info.capabilities");
00957 if (caps == NULL) {
00958 ds_property_set_string (d, "info.capabilities",
00959 capability);
00960 } else {
00961 if (strstr (caps, capability) == NULL) {
00962 snprintf (buf, MAX_CAP_SIZE, "%s %s", caps,
00963 capability);
00964 ds_property_set_string (d, "info.capabilities",
00965 buf);
00966 }
00967 }
00968
00969 if (d->in_gdl) {
00970 manager_send_signal_new_capability (udi, capability);
00971 }
00972
00973
00974 reply = dbus_message_new_method_return (message);
00975 if (reply == NULL)
00976 DIE (("No memory"));
00977
00978 if (!dbus_connection_send (connection, reply, NULL))
00979 DIE (("No memory"));
00980
00981 dbus_message_unref (reply);
00982 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00983 }
00984
00985
00986
01000 static DBusHandlerResult
01001 device_remove_property (DBusConnection * connection, DBusMessage * message)
01002 {
01003 const char *udi;
01004 char *key;
01005 HalDevice *d;
01006 DBusMessage *reply;
01007 DBusError error;
01008
01009 HAL_TRACE (("entering"));
01010
01011 udi = dbus_message_get_path (message);
01012
01013 d = ds_device_find (udi);
01014 if (d == NULL) {
01015 raise_no_such_device (connection, message, udi);
01016 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01017 }
01018
01019 dbus_error_init (&error);
01020 if (!dbus_message_get_args (message, &error,
01021 DBUS_TYPE_STRING, &key,
01022 DBUS_TYPE_INVALID)) {
01023 raise_syntax (connection, message, "RemoveProperty");
01024 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01025 }
01026
01027 if (!ds_property_remove (d, key)) {
01028 raise_no_such_property (connection, message, udi, key);
01029 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01030 }
01031
01032
01033 reply = dbus_message_new_method_return (message);
01034 if (reply == NULL)
01035 DIE (("No memory"));
01036
01037 if (!dbus_connection_send (connection, reply, NULL))
01038 DIE (("No memory"));
01039
01040 dbus_message_unref (reply);
01041 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01042 }
01043
01044
01057 static DBusHandlerResult
01058 device_property_exists (DBusConnection * connection, DBusMessage * message)
01059 {
01060 const char *udi;
01061 char *key;
01062 HalDevice *d;
01063 DBusMessage *reply;
01064 DBusError error;
01065 DBusMessageIter iter;
01066
01067 HAL_TRACE (("entering"));
01068
01069 udi = dbus_message_get_path (message);
01070
01071 d = ds_device_find (udi);
01072 if (d == NULL) {
01073 raise_no_such_device (connection, message, udi);
01074 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01075 }
01076
01077 dbus_error_init (&error);
01078 if (!dbus_message_get_args (message, &error,
01079 DBUS_TYPE_STRING, &key,
01080 DBUS_TYPE_INVALID)) {
01081 raise_syntax (connection, message, "RemoveProperty");
01082 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01083 }
01084
01085 reply = dbus_message_new_method_return (message);
01086 if (reply == NULL)
01087 DIE (("No memory"));
01088
01089 dbus_message_iter_init (reply, &iter);
01090 dbus_message_iter_append_boolean (&iter,
01091 ds_property_exists (d, key));
01092
01093 if (!dbus_connection_send (connection, reply, NULL))
01094 DIE (("No memory"));
01095
01096 dbus_message_unref (reply);
01097 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01098 }
01099
01100
01113 static DBusHandlerResult
01114 device_query_capability (DBusConnection * connection,
01115 DBusMessage * message)
01116 {
01117 dbus_bool_t rc;
01118 const char *udi;
01119 const char *caps;
01120 char *capability;
01121 HalDevice *d;
01122 DBusMessage *reply;
01123 DBusError error;
01124 DBusMessageIter iter;
01125
01126 HAL_TRACE (("entering"));
01127
01128 udi = dbus_message_get_path (message);
01129
01130 d = ds_device_find (udi);
01131 if (d == NULL) {
01132 raise_no_such_device (connection, message, udi);
01133 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01134 }
01135
01136 dbus_error_init (&error);
01137 if (!dbus_message_get_args (message, &error,
01138 DBUS_TYPE_STRING, &capability,
01139 DBUS_TYPE_INVALID)) {
01140 raise_syntax (connection, message, "QueryCapability");
01141 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01142 }
01143
01144 reply = dbus_message_new_method_return (message);
01145 if (reply == NULL)
01146 DIE (("No memory"));
01147
01148 rc = FALSE;
01149 caps = ds_property_get_string (d, "info.capabilities");
01150 if (caps != NULL) {
01151 if (strstr (caps, capability) != NULL)
01152 rc = TRUE;
01153 }
01154
01155 dbus_message_iter_init (reply, &iter);
01156 dbus_message_iter_append_boolean (&iter, rc);
01157
01158 if (!dbus_connection_send (connection, reply, NULL))
01159 DIE (("No memory"));
01160
01161 dbus_message_unref (reply);
01162 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01163 }
01164
01165
01189 static DBusHandlerResult
01190 agent_manager_new_device (DBusConnection * connection,
01191 DBusMessage * message)
01192 {
01193 HalDevice *d;
01194 DBusMessage *reply;
01195 DBusMessageIter iter;
01196 const char *udi;
01197
01198 HAL_TRACE (("entering"));
01199
01200 reply = dbus_message_new_method_return (message);
01201 if (reply == NULL)
01202 DIE (("No memory"));
01203
01204 d = ds_device_new ();
01205 udi = ds_device_get_udi (d);
01206
01207 HAL_TRACE (("udi=%s", udi));
01208
01209 dbus_message_iter_init (reply, &iter);
01210 dbus_message_iter_append_string (&iter, udi);
01211
01212 if (!dbus_connection_send (connection, reply, NULL))
01213 DIE (("No memory"));
01214
01215 dbus_message_unref (reply);
01216
01217 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01218 }
01219
01242 static DBusHandlerResult
01243 agent_manager_commit_to_gdl (DBusConnection * connection,
01244 DBusMessage * message)
01245 {
01246 DBusMessage *reply;
01247 DBusError error;
01248 HalDevice *d;
01249 const char *old_udi;
01250 const char *new_udi;
01251
01252 dbus_error_init (&error);
01253 if (!dbus_message_get_args (message, &error,
01254 DBUS_TYPE_STRING, &old_udi,
01255 DBUS_TYPE_STRING, &new_udi,
01256 DBUS_TYPE_INVALID)) {
01257 raise_syntax (connection, message, "CommitToGdl");
01258 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01259 }
01260
01261 HAL_TRACE (("entering, old_udi=%s, new_udi=%s", old_udi, new_udi));
01262
01263 d = ds_device_find (old_udi);
01264 if (d == NULL) {
01265 raise_no_such_device (connection, message, old_udi);
01266 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01267 }
01268
01269 if (!ds_device_set_udi (d, new_udi)) {
01270 raise_udi_in_use (connection, message, new_udi);
01271 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01272 }
01273
01274
01275 ds_gdl_add (d);
01276
01277
01278
01279
01280
01281 reply = dbus_message_new_method_return (message);
01282 if (reply == NULL)
01283 DIE (("No memory"));
01284
01285 if (!dbus_connection_send (connection, reply, NULL))
01286 DIE (("No memory"));
01287
01288 dbus_message_unref (reply);
01289 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01290 }
01291
01292
01309 static DBusHandlerResult
01310 agent_manager_remove (DBusConnection * connection, DBusMessage * message)
01311 {
01312 DBusMessage *reply;
01313 DBusError error;
01314 HalDevice *d;
01315 const char *udi;
01316
01317 dbus_error_init (&error);
01318 if (!dbus_message_get_args (message, &error,
01319 DBUS_TYPE_STRING, &udi,
01320 DBUS_TYPE_INVALID)) {
01321 raise_syntax (connection, message, "Remove");
01322 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01323 }
01324
01325 HAL_INFO (("entering, udi=%s", udi));
01326
01327 d = ds_device_find (udi);
01328 if (d == NULL) {
01329 raise_no_such_device (connection, message, udi);
01330 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01331 }
01332
01333 ds_device_destroy (d);
01334
01335
01336
01337
01338
01339
01340
01341 reply = dbus_message_new_method_return (message);
01342 if (reply == NULL)
01343 DIE (("No memory"));
01344
01345 if (!dbus_connection_send (connection, reply, NULL))
01346 DIE (("No memory"));
01347
01348 dbus_message_unref (reply);
01349 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01350 }
01351
01352
01353
01367 static DBusHandlerResult
01368 agent_merge_properties (DBusConnection * connection, DBusMessage * message)
01369 {
01370 DBusMessage *reply;
01371 DBusError error;
01372 HalDevice *target_d;
01373 HalDevice *source_d;
01374 const char *target_udi;
01375 const char *source_udi;
01376
01377 dbus_error_init (&error);
01378 if (!dbus_message_get_args (message, &error,
01379 DBUS_TYPE_STRING, &target_udi,
01380 DBUS_TYPE_STRING, &source_udi,
01381 DBUS_TYPE_INVALID)) {
01382 raise_syntax (connection, message, "MergeProperties");
01383 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01384 }
01385
01386 HAL_TRACE (("entering, target_udi=%s, source_udi=%s",
01387 target_udi, source_udi));
01388
01389 target_d = ds_device_find (target_udi);
01390 if (target_d == NULL) {
01391 raise_no_such_device (connection, message, target_udi);
01392 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01393 }
01394
01395 source_d = ds_device_find (source_udi);
01396 if (source_d == NULL) {
01397 raise_no_such_device (connection, message, source_udi);
01398 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01399 }
01400
01401 ds_device_merge (target_d, source_d);
01402
01403 reply = dbus_message_new_method_return (message);
01404 if (reply == NULL)
01405 DIE (("No memory"));
01406
01407 if (!dbus_connection_send (connection, reply, NULL))
01408 DIE (("No memory"));
01409
01410 dbus_message_unref (reply);
01411 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01412 }
01413
01414
01437 static DBusHandlerResult
01438 agent_device_matches (DBusConnection * connection, DBusMessage * message)
01439 {
01440 DBusMessage *reply;
01441 DBusError error;
01442 HalDevice *d1;
01443 HalDevice *d2;
01444 const char *udi1;
01445 const char *udi2;
01446 const char *namespace;
01447 dbus_bool_t rc;
01448 DBusMessageIter iter;
01449
01450 dbus_error_init (&error);
01451 if (!dbus_message_get_args (message, &error,
01452 DBUS_TYPE_STRING, &udi1,
01453 DBUS_TYPE_STRING, &udi2,
01454 DBUS_TYPE_STRING, &namespace,
01455 DBUS_TYPE_INVALID)) {
01456 raise_syntax (connection, message, "DeviceMatches");
01457 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01458 }
01459
01460 HAL_TRACE (("entering, udi1=%s, udi2=%s, namespace=%s",
01461 udi1, udi2, namespace));
01462
01463 d1 = ds_device_find (udi1);
01464 if (d1 == NULL) {
01465 raise_no_such_device (connection, message, udi1);
01466 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01467 }
01468
01469 d2 = ds_device_find (udi2);
01470 if (d2 == NULL) {
01471 raise_no_such_device (connection, message, udi2);
01472 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01473 }
01474
01475 rc = ds_device_matches (d1, d2, namespace);
01476
01477 reply = dbus_message_new_method_return (message);
01478 if (reply == NULL)
01479 DIE (("No memory"));
01480
01481 dbus_message_iter_init (reply, &iter);
01482 dbus_message_iter_append_boolean (&iter, rc);
01483
01484 if (!dbus_connection_send (connection, reply, NULL))
01485 DIE (("No memory"));
01486
01487 dbus_message_unref (reply);
01488 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01489 }
01490
01491
01511 static DBusHandlerResult
01512 filter_function (DBusConnection * connection,
01513 DBusMessage * message, void *user_data)
01514 {
01515
01516
01517
01518
01519
01520
01521
01522 if (dbus_message_is_method_call (message,
01523 "org.freedesktop.Hal.Manager",
01524 "GetAllDevices") &&
01525 strcmp (dbus_message_get_path (message),
01526 "/org/freedesktop/Hal/Manager") == 0) {
01527 return manager_get_all_devices (connection, message);
01528 } else if (dbus_message_is_method_call (message,
01529 "org.freedesktop.Hal.Manager",
01530 "DeviceExists") &&
01531 strcmp (dbus_message_get_path (message),
01532 "/org/freedesktop/Hal/Manager") == 0) {
01533 return manager_device_exists (connection, message);
01534 } else if (dbus_message_is_method_call (message,
01535 "org.freedesktop.Hal.Manager",
01536 "FindDeviceStringMatch") &&
01537 strcmp (dbus_message_get_path (message),
01538 "/org/freedesktop/Hal/Manager") == 0) {
01539 return manager_find_device_string_match (connection,
01540 message);
01541 } else
01542 if (dbus_message_is_method_call
01543 (message, "org.freedesktop.Hal.Manager",
01544 "FindDeviceByCapability")
01545 && strcmp (dbus_message_get_path (message),
01546 "/org/freedesktop/Hal/Manager") == 0) {
01547 return manager_find_device_by_capability (connection,
01548 message);
01549 }
01550
01551 else if (dbus_message_is_method_call (message,
01552 "org.freedesktop.Hal.AgentManager",
01553 "NewDevice") &&
01554 strcmp (dbus_message_get_path (message),
01555 "/org/freedesktop/Hal/Manager") == 0) {
01556 return agent_manager_new_device (connection, message);
01557 } else if (dbus_message_is_method_call (message,
01558 "org.freedesktop.Hal.AgentManager",
01559 "CommitToGdl") &&
01560 strcmp (dbus_message_get_path (message),
01561 "/org/freedesktop/Hal/Manager") == 0) {
01562 return agent_manager_commit_to_gdl (connection, message);
01563 } else if (dbus_message_is_method_call (message,
01564 "org.freedesktop.Hal.AgentManager",
01565 "Remove") &&
01566 strcmp (dbus_message_get_path (message),
01567 "/org/freedesktop/Hal/Manager") == 0) {
01568 return agent_manager_remove (connection, message);
01569 } else if (dbus_message_is_method_call (message,
01570 "org.freedesktop.Hal.AgentManager",
01571 "MergeProperties") &&
01572 strcmp (dbus_message_get_path (message),
01573 "/org/freedesktop/Hal/Manager") == 0) {
01574 return agent_merge_properties (connection, message);
01575 } else if (dbus_message_is_method_call (message,
01576 "org.freedesktop.Hal.AgentManager",
01577 "DeviceMatches") &&
01578 strcmp (dbus_message_get_path (message),
01579 "/org/freedesktop/Hal/Manager") == 0) {
01580 return agent_device_matches (connection, message);
01581 }
01582
01583
01584 else if (dbus_message_is_method_call (message,
01585 "org.freedesktop.Hal.Device",
01586 "GetAllProperties")) {
01587 return device_get_all_properties (connection, message);
01588 } else if (dbus_message_is_method_call (message,
01589 "org.freedesktop.Hal.Device",
01590 "GetProperty")) {
01591 return device_get_property (connection, message);
01592 } else if (dbus_message_is_method_call (message,
01593 "org.freedesktop.Hal.Device",
01594 "GetPropertyString")) {
01595 return device_get_property (connection, message);
01596 } else if (dbus_message_is_method_call (message,
01597 "org.freedesktop.Hal.Device",
01598 "GetPropertyInteger")) {
01599 return device_get_property (connection, message);
01600 } else if (dbus_message_is_method_call (message,
01601 "org.freedesktop.Hal.Device",
01602 "GetPropertyBoolean")) {
01603 return device_get_property (connection, message);
01604 } else if (dbus_message_is_method_call (message,
01605 "org.freedesktop.Hal.Device",
01606 "GetPropertyDouble")) {
01607 return device_get_property (connection, message);
01608 } else if (dbus_message_is_method_call (message,
01609 "org.freedesktop.Hal.Device",
01610 "SetProperty")) {
01611 return device_set_property (connection, message);
01612 } else if (dbus_message_is_method_call (message,
01613 "org.freedesktop.Hal.Device",
01614 "SetPropertyString")) {
01615 return device_set_property (connection, message);
01616 } else if (dbus_message_is_method_call (message,
01617 "org.freedesktop.Hal.Device",
01618 "SetPropertyInteger")) {
01619 return device_set_property (connection, message);
01620 } else if (dbus_message_is_method_call (message,
01621 "org.freedesktop.Hal.Device",
01622 "SetPropertyBoolean")) {
01623 return device_set_property (connection, message);
01624 } else if (dbus_message_is_method_call (message,
01625 "org.freedesktop.Hal.Device",
01626 "SetPropertyDouble")) {
01627 return device_set_property (connection, message);
01628 } else if (dbus_message_is_method_call (message,
01629 "org.freedesktop.Hal.Device",
01630 "RemoveProperty")) {
01631 return device_remove_property (connection, message);
01632 } else if (dbus_message_is_method_call (message,
01633 "org.freedesktop.Hal.Device",
01634 "GetPropertyType")) {
01635 return device_get_property_type (connection, message);
01636 } else if (dbus_message_is_method_call (message,
01637 "org.freedesktop.Hal.Device",
01638 "PropertyExists")) {
01639 return device_property_exists (connection, message);
01640 } else if (dbus_message_is_method_call (message,
01641 "org.freedesktop.Hal.Device",
01642 "AddCapability")) {
01643 return device_add_capability (connection, message);
01644 } else if (dbus_message_is_method_call (message,
01645 "org.freedesktop.Hal.Device",
01646 "QueryCapability")) {
01647 return device_query_capability (connection, message);
01648 } else
01649 osspec_filter_function (connection, message, user_data);
01650
01651 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01652 }
01653
01655 static int atomic_count = 0;
01656
01662 void
01663 property_atomic_update_begin ()
01664 {
01665 atomic_count++;
01666 }
01667
01669 static int num_pending_updates = 0;
01670
01672 typedef struct PendingUpdate_s {
01673 HalDevice *device;
01674 char *key;
01675 dbus_bool_t removed;
01676 dbus_bool_t added;
01677 struct PendingUpdate_s *next;
01678 } PendingUpdate;
01679
01680 static PendingUpdate *pending_updates_head = NULL;
01681
01686 void
01687 property_atomic_update_end ()
01688 {
01689 PendingUpdate *pu_iter = NULL;
01690 PendingUpdate *pu_iter_next = NULL;
01691 PendingUpdate *pu_iter2 = NULL;
01692
01693 --atomic_count;
01694
01695 if (atomic_count < 0) {
01696 HAL_WARNING (("*** atomic_count = %d < 0 !!",
01697 atomic_count));
01698 atomic_count = 0;
01699 }
01700
01701 if (atomic_count == 0 && num_pending_updates > 0) {
01702 DBusMessage *message;
01703 DBusMessageIter iter;
01704
01705 for (pu_iter = pending_updates_head;
01706 pu_iter != NULL; pu_iter = pu_iter_next) {
01707 int num_updates_this;
01708
01709 pu_iter_next = pu_iter->next;
01710
01711 if (pu_iter->device == NULL)
01712 goto have_processed;
01713
01714
01715 num_updates_this = 0;
01716 for (pu_iter2 = pu_iter;
01717 pu_iter2 != NULL; pu_iter2 = pu_iter2->next) {
01718 if (pu_iter2->device == pu_iter->device)
01719 num_updates_this++;
01720 }
01721
01722
01723 message =
01724 dbus_message_new_signal
01725 (pu_iter->device->udi,
01726 "org.freedesktop.Hal.Device",
01727 "PropertyModified");
01728 dbus_message_iter_init (message, &iter);
01729 dbus_message_iter_append_int32 (&iter,
01730 num_updates_this);
01731 for (pu_iter2 = pu_iter; pu_iter2 != NULL;
01732 pu_iter2 = pu_iter2->next) {
01733 if (pu_iter2->device == pu_iter->device) {
01734 dbus_message_iter_append_string
01735 (&iter, pu_iter2->key);
01736 dbus_message_iter_append_boolean
01737 (&iter, pu_iter2->removed);
01738 dbus_message_iter_append_boolean
01739 (&iter, pu_iter2->added);
01740
01741
01742 if (pu_iter2 != pu_iter)
01743 pu_iter2->device = NULL;
01744 }
01745 }
01746
01747
01748 if (!dbus_connection_send
01749 (dbus_connection, message, NULL))
01750 DIE (("error broadcasting message"));
01751
01752 dbus_message_unref (message);
01753
01754 have_processed:
01755 free (pu_iter->key);
01756 free (pu_iter);
01757 }
01758
01759 num_pending_updates = 0;
01760 pending_updates_head = NULL;
01761 }
01762 }
01763
01783 void
01784 emit_condition (HalDevice * device, const char *condition_name,
01785 int first_arg_type, ...)
01786 {
01787 DBusMessage *message;
01788 DBusMessageIter iter;
01789 va_list var_args;
01790
01791 if (!device->in_gdl)
01792 return;
01793
01794 message = dbus_message_new_signal (device->udi,
01795 "org.freedesktop.Hal.Device",
01796 "Condition");
01797 dbus_message_iter_init (message, &iter);
01798 dbus_message_iter_append_string (&iter, condition_name);
01799
01800 va_start (var_args, first_arg_type);
01801 dbus_message_append_args_valist (message, first_arg_type,
01802 var_args);
01803 va_end (var_args);
01804
01805 if (!dbus_connection_send (dbus_connection, message, NULL))
01806 DIE (("error broadcasting message"));
01807
01808 dbus_message_unref (message);
01809 }
01810
01821 static void
01822 property_changed (HalDevice * device,
01823 const char *key,
01824 dbus_bool_t in_gdl,
01825 dbus_bool_t removed, dbus_bool_t added)
01826 {
01827 DBusMessage *message;
01828 DBusMessageIter iter;
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838 if (!in_gdl)
01839 return;
01840
01841 if (atomic_count > 0) {
01842 PendingUpdate *pu;
01843
01844 pu = xmalloc (sizeof (PendingUpdate));
01845 pu->device = device;
01846 pu->key = xstrdup (key);
01847 pu->removed = removed;
01848 pu->added = added;
01849 pu->next = pending_updates_head;
01850
01851 pending_updates_head = pu;
01852 num_pending_updates++;
01853 } else {
01854 message = dbus_message_new_signal (device->udi,
01855 "org.freedesktop.Hal.Device",
01856 "PropertyModified");
01857
01858 dbus_message_iter_init (message, &iter);
01859 dbus_message_iter_append_int32 (&iter, 1);
01860 dbus_message_iter_append_string (&iter, key);
01861 dbus_message_iter_append_boolean (&iter, removed);
01862 dbus_message_iter_append_boolean (&iter, added);
01863
01864 if (!dbus_connection_send (dbus_connection, message, NULL))
01865 DIE (("error broadcasting message"));
01866
01867 dbus_message_unref (message);
01868 }
01869 }
01870
01876 static void
01877 gdl_changed (HalDevice * device, dbus_bool_t is_added)
01878 {
01879 if (is_added)
01880 manager_send_signal_device_added (device->udi);
01881 else
01882 manager_send_signal_device_removed (device->udi);
01883 }
01884
01892 static void
01893 new_capability (HalDevice * device, const char *capability,
01894 dbus_bool_t in_gdl)
01895 {
01896 if (!in_gdl)
01897 return;
01898
01899 manager_send_signal_new_capability (device->udi, capability);
01900 }
01901
01905 static void
01906 usage ()
01907 {
01908 fprintf (stderr, "\n" "usage : hald [--daemon=yes|no] [--help]\n");
01909 fprintf (stderr,
01910 "\n"
01911 " --daemon=yes|no Become a daemon\n"
01912 " --help Show this information and exit\n"
01913 "\n"
01914 "The HAL daemon detects devices present in the system and provides the\n"
01915 "org.freedesktop.Hal service through D-BUS. The commandline options given\n"
01916 "overrides the configuration given in "
01917 PACKAGE_SYSCONF_DIR "/hald.conf\n" "\n"
01918 "For more information visit http://freedesktop.org/Software/hal\n"
01919 "\n");
01920 }
01921
01922
01924 static dbus_bool_t opt_become_daemon = TRUE;
01925
01927 static char *opt_run_as = NULL;
01928
01935 int
01936 main (int argc, char *argv[])
01937 {
01938 GMainLoop *loop;
01939 DBusError dbus_error;
01940
01941
01942
01943
01944 while (1) {
01945 int c;
01946 int option_index = 0;
01947 const char *opt;
01948 static struct option long_options[] = {
01949 {"daemon", 1, NULL, 0},
01950 {"help", 0, NULL, 0},
01951 {NULL, 0, NULL, 0}
01952 };
01953
01954 c = getopt_long (argc, argv, "",
01955 long_options, &option_index);
01956 if (c == -1)
01957 break;
01958
01959 switch (c) {
01960 case 0:
01961 opt = long_options[option_index].name;
01962
01963 if (strcmp (opt, "help") == 0) {
01964 usage ();
01965 return 0;
01966 } else if (strcmp (opt, "daemon") == 0) {
01967 if (strcmp ("yes", optarg) == 0) {
01968 opt_become_daemon = TRUE;
01969 } else if (strcmp ("no", optarg) == 0) {
01970 opt_become_daemon = FALSE;
01971 } else {
01972 usage ();
01973 return 1;
01974 }
01975 }
01976 break;
01977
01978 default:
01979 usage ();
01980 return 1;
01981 break;
01982 }
01983 }
01984
01985 logger_init ();
01986 HAL_INFO (("HAL daemon version " PACKAGE_VERSION " starting up"));
01987
01988 HAL_DEBUG (("opt_become_daemon = %d", opt_become_daemon));
01989
01990 if (opt_become_daemon) {
01991 int child_pid;
01992 int dev_null_fd;
01993
01994 if (chdir ("/") < 0) {
01995 HAL_ERROR (("Could not chdir to /, errno=%d",
01996 errno));
01997 return 1;
01998 }
01999
02000 child_pid = fork ();
02001 switch (child_pid) {
02002 case -1:
02003 HAL_ERROR (("Cannot fork(), errno=%d", errno));
02004 break;
02005
02006 case 0:
02007
02008
02009 dev_null_fd = open ("/dev/null", O_RDWR);
02010
02011 if (dev_null_fd > 0) {
02012
02013 dup2 (dev_null_fd, 0);
02014 dup2 (dev_null_fd, 1);
02015 dup2 (dev_null_fd, 2);
02016 }
02017
02018 umask (022);
02019
02022 break;
02023
02024 default:
02025
02026 exit (0);
02027 break;
02028 }
02029
02030
02031 setsid ();
02032 }
02033
02034 if (opt_run_as != NULL) {
02035 uid_t uid;
02036 gid_t gid;
02037 struct passwd *pw;
02038
02039
02040 if ((pw = getpwnam (opt_run_as)) == NULL) {
02041 HAL_ERROR (("Could not lookup user %s, errno=%d",
02042 opt_run_as, errno));
02043 exit (1);
02044 }
02045
02046 uid = pw->pw_uid;
02047 gid = pw->pw_gid;
02048
02049 if (setgid (gid) < 0) {
02050 HAL_ERROR (("Failed to set GID to %d, errno=%d",
02051 gid, errno));
02052 exit (1);
02053 }
02054
02055 if (setuid (uid) < 0) {
02056 HAL_ERROR (("Failed to set UID to %d, errno=%d",
02057 uid, errno));
02058 exit (1);
02059 }
02060
02061 }
02062
02063
02064 ds_init ();
02065
02066
02067 ds_add_cb_newcap (new_capability);
02068 ds_add_cb_gdl_changed (gdl_changed);
02069 ds_add_cb_property_changed (property_changed);
02070
02071 loop = g_main_loop_new (NULL, FALSE);
02072
02073 dbus_connection_set_change_sigpipe (TRUE);
02074
02075 dbus_error_init (&dbus_error);
02076 dbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error);
02077 if (dbus_connection == NULL) {
02078 HAL_ERROR (("dbus_bus_get(): '%s'", dbus_error.message));
02079 exit (1);
02080 }
02081
02082 dbus_connection_setup_with_g_main (dbus_connection, NULL);
02083
02084 dbus_bus_acquire_service (dbus_connection, "org.freedesktop.Hal",
02085 0, &dbus_error);
02086 if (dbus_error_is_set (&dbus_error)) {
02087 HAL_ERROR (("dbus_bus_acquire_service(): '%s'",
02088 dbus_error.message));
02089 exit (1);
02090 }
02091
02092 dbus_connection_add_filter (dbus_connection, filter_function, NULL,
02093 NULL);
02094
02095
02096 osspec_init (dbus_connection);
02097
02098 osspec_probe ();
02099
02100
02101 g_main_loop_run (loop);
02102
02103 return 0;
02104 }
02105
02111 void *
02112 xmalloc (unsigned int how_much)
02113 {
02114 void *p = malloc (how_much);
02115 if (!p)
02116 DIE (("Unable to allocate %d bytes of memory", how_much));
02117 return p;
02118 }
02119
02125 char *
02126 xstrdup (const char *str)
02127 {
02128 char *p = strdup (str);
02129 if (!p)
02130 DIE (("Unable to duplicate string '%s'", str));
02131 return p;
02132 }
02133