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 raise_no_such_device(DBusConnection* connection,
00077 DBusMessage* in_reply_to,
00078 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 raise_udi_in_use(DBusConnection* connection,
00102 DBusMessage* in_reply_to,
00103 const char* udi)
00104 {
00105 char buf[512];
00106 DBusMessage *reply;
00107
00108 snprintf(buf, 511, "Unique device id '%s' is already in use", udi);
00109 HAL_WARNING((buf));
00110 reply = dbus_message_new_error(in_reply_to,
00111 "org.freedesktop.Hal.UdiInUse",
00112 buf);
00113 if( reply==NULL )
00114 DIE(("No memory"));
00115 if( !dbus_connection_send(connection, reply, NULL) )
00116 DIE(("No memory"));
00117 dbus_message_unref(reply);
00118 }
00119
00127 static void raise_no_such_property(DBusConnection* connection,
00128 DBusMessage* in_reply_to,
00129 const char* device_id,
00130 const char* key)
00131 {
00132 char buf[512];
00133 DBusMessage *reply;
00134
00135 snprintf(buf, 511, "No property %s on device with id %s", key, device_id);
00136 HAL_WARNING((buf));
00137 reply = dbus_message_new_error(in_reply_to,
00138 "org.freedesktop.Hal.NoSuchProperty",
00139 buf);
00140 if( reply==NULL )
00141 DIE(("No memory"));
00142 if( !dbus_connection_send(connection, reply, NULL) )
00143 DIE(("No memory"));
00144 dbus_message_unref(reply);
00145 }
00146
00154 static void raise_property_type_error(DBusConnection* connection,
00155 DBusMessage* in_reply_to,
00156 const char* device_id,
00157 const char* key)
00158 {
00159 char buf[512];
00160 DBusMessage *reply;
00161
00162 snprintf(buf, 511,
00163 "Type mismatch setting property %s on device with id %s",
00164 key, device_id);
00165 HAL_WARNING((buf));
00166 reply = dbus_message_new_error(in_reply_to,
00167 "org.freedesktop.Hal.TypeMismatch",
00168 buf);
00169 if( reply==NULL )
00170 DIE(("No memory"));
00171 if( !dbus_connection_send(connection, reply, NULL) )
00172 DIE(("No memory"));
00173 dbus_message_unref(reply);
00174 }
00175
00183 static void raise_syntax(DBusConnection* connection,
00184 DBusMessage* in_reply_to,
00185 const char* method_name)
00186 {
00187 char buf[512];
00188 DBusMessage *reply;
00189
00190 snprintf(buf, 511,
00191 "There is a syntax error in the invocation of "
00192 "the method %s", method_name);
00193 HAL_WARNING((buf));
00194 reply = dbus_message_new_error(in_reply_to,
00195 "org.freedesktop.Hal.SyntaxError",
00196 buf);
00197 if( reply==NULL )
00198 DIE(("No memory"));
00199 if( !dbus_connection_send(connection, reply, NULL) )
00200 DIE(("No memory"));
00201 dbus_message_unref(reply);
00202 }
00203
00224 static DBusHandlerResult manager_get_all_devices(DBusConnection* connection,
00225 DBusMessage* message)
00226 {
00227 DBusMessage* reply;
00228 DBusMessageIter iter;
00229 DBusMessageIter iter_array;
00230 HalDevice* d;
00231 const char* udi;
00232 HalDeviceIterator iter_device;
00233
00234 HAL_TRACE(("entering"));
00235
00236 reply = dbus_message_new_method_return(message);
00237 if( reply==NULL )
00238 DIE(("No memory"));
00239
00240 dbus_message_iter_init(reply, &iter);
00241 dbus_message_iter_append_array(&iter, &iter_array, DBUS_TYPE_STRING);
00242
00243 for(ds_device_iter_begin(&iter_device);
00244 ds_device_iter_has_more(&iter_device);
00245 ds_device_iter_next(&iter_device))
00246 {
00247 d = ds_device_iter_get(&iter_device);
00248
00249 if( d->in_gdl )
00250 {
00251 udi = ds_device_get_udi(d);
00252 dbus_message_iter_append_string(&iter_array, udi);
00253 }
00254 }
00255
00256 if( !dbus_connection_send(connection, reply, NULL) )
00257 DIE(("No memory"));
00258
00259 dbus_message_unref (reply);
00260
00261 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00262 }
00263
00264
00277 static DBusHandlerResult manager_find_device_string_match(
00278 DBusConnection* connection,
00279 DBusMessage* message)
00280 {
00281 DBusMessage* reply;
00282 DBusMessageIter iter;
00283 DBusMessageIter iter_array;
00284 DBusError error;
00285 const char* key;
00286 const char* value;
00287 HalDeviceIterator iter_device;
00288 int type;
00289 HalDevice* device;
00290
00291 HAL_TRACE(("entering"));
00292
00293 dbus_error_init(&error);
00294 if( !dbus_message_get_args(message, &error,
00295 DBUS_TYPE_STRING, &key,
00296 DBUS_TYPE_STRING, &value,
00297 DBUS_TYPE_INVALID) )
00298 {
00299 raise_syntax(connection, message, "Manager.FindDeviceStringMatch");
00300 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00301 }
00302
00303 reply = dbus_message_new_method_return(message);
00304 if( reply==NULL )
00305 DIE(("No memory"));
00306
00307 dbus_message_iter_init(reply, &iter);
00308 dbus_message_iter_append_array(&iter, &iter_array, DBUS_TYPE_STRING);
00309
00310 for(ds_device_iter_begin(&iter_device);
00311 ds_device_iter_has_more(&iter_device);
00312 ds_device_iter_next(&iter_device))
00313 {
00314 device = ds_device_iter_get(&iter_device);
00315
00316 if( !device->in_gdl )
00317 continue;
00318
00319 type = ds_property_get_type(device, key);
00320 if( type==DBUS_TYPE_STRING )
00321 {
00322 if( strcmp(ds_property_get_string(device, key),
00323 value)==0 )
00324 dbus_message_iter_append_string(&iter_array, device->udi);
00325 }
00326 }
00327
00328
00329 if( !dbus_connection_send(connection, reply, NULL) )
00330 DIE(("No memory"));
00331
00332 dbus_message_unref (reply);
00333
00334 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00335 }
00336
00337
00348 static DBusHandlerResult manager_find_device_by_capability(
00349 DBusConnection* connection,
00350 DBusMessage* message)
00351 {
00352 DBusMessage* reply;
00353 DBusMessageIter iter;
00354 DBusMessageIter iter_array;
00355 DBusError error;
00356 const char* capability;
00357 HalDeviceIterator iter_device;
00358 int type;
00359 HalDevice* device;
00360
00361 HAL_TRACE(("entering"));
00362
00363 dbus_error_init(&error);
00364 if( !dbus_message_get_args(message, &error,
00365 DBUS_TYPE_STRING, &capability,
00366 DBUS_TYPE_INVALID) )
00367 {
00368 raise_syntax(connection, message, "Manager.FindDeviceByCapability");
00369 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00370 }
00371
00372 reply = dbus_message_new_method_return(message);
00373 if( reply==NULL )
00374 DIE(("No memory"));
00375
00376 dbus_message_iter_init(reply, &iter);
00377 dbus_message_iter_append_array(&iter, &iter_array, DBUS_TYPE_STRING);
00378
00379 for(ds_device_iter_begin(&iter_device);
00380 ds_device_iter_has_more(&iter_device);
00381 ds_device_iter_next(&iter_device))
00382 {
00383 device = ds_device_iter_get(&iter_device);
00384
00385 if( !device->in_gdl )
00386 continue;
00387
00388 type = ds_property_get_type(device, "info.capabilities");
00389 if( type==DBUS_TYPE_STRING )
00390 {
00391 if( strstr(ds_property_get_string(device, "info.capabilities"),
00392 capability)!=NULL )
00393 dbus_message_iter_append_string(&iter_array, device->udi);
00394 }
00395 }
00396
00397 if( !dbus_connection_send(connection, reply, NULL) )
00398 DIE(("No memory"));
00399
00400 dbus_message_unref (reply);
00401
00402 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00403 }
00404
00405
00416 static DBusHandlerResult manager_device_exists(DBusConnection* connection,
00417 DBusMessage* message)
00418 {
00419 DBusMessage* reply;
00420 DBusMessageIter iter;
00421 DBusError error;
00422 HalDevice* d;
00423 const char* udi;
00424
00425 dbus_error_init(&error);
00426 if( !dbus_message_get_args(message, &error,
00427 DBUS_TYPE_STRING, &udi,
00428 DBUS_TYPE_INVALID) )
00429 {
00430 raise_syntax(connection, message, "Manager.DeviceExists");
00431 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00432 }
00433
00434 HAL_TRACE(("entering, udi=%s", udi));
00435
00436 d = ds_device_find(udi);
00437
00438 reply = dbus_message_new_method_return(message);
00439 dbus_message_iter_init(reply, &iter);
00440 dbus_message_iter_append_boolean(&iter, d!=NULL);
00441
00442 if( reply==NULL )
00443 DIE(("No memory"));
00444
00445 if( !dbus_connection_send(connection, reply, NULL) )
00446 DIE(("No memory"));
00447
00448 dbus_message_unref(reply);
00449 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00450 }
00451
00457 static void manager_send_signal_device_added(const char* udi)
00458 {
00459 DBusMessage* message;
00460 DBusMessageIter iter;
00461
00462 HAL_TRACE(("entering, udi=%s", udi));
00463
00464 message = dbus_message_new_signal("/org/freedesktop/Hal/Manager",
00465 "org.freedesktop.Hal.Manager",
00466 "DeviceAdded");
00467
00468 dbus_message_iter_init(message, &iter);
00469 dbus_message_iter_append_string(&iter, udi);
00470
00471 if( !dbus_connection_send(dbus_connection,message, NULL) )
00472 DIE(("error broadcasting message"));
00473
00474 dbus_message_unref(message);
00475 }
00476
00482 static void manager_send_signal_device_removed(const char* udi)
00483 {
00484 DBusMessage* message;
00485 DBusMessageIter iter;
00486
00487 HAL_TRACE(("entering, udi=%s", udi));
00488
00489 message = dbus_message_new_signal("/org/freedesktop/Hal/Manager",
00490 "org.freedesktop.Hal.Manager",
00491 "DeviceRemoved");
00492
00493 dbus_message_iter_init(message, &iter);
00494 dbus_message_iter_append_string(&iter, udi);
00495
00496 if( !dbus_connection_send(dbus_connection,message, NULL) )
00497 DIE(("error broadcasting message"));
00498
00499 dbus_message_unref(message);
00500 }
00501
00509 static void manager_send_signal_new_capability(const char* udi,
00510 const char* capability)
00511 {
00512 DBusMessage* message;
00513 DBusMessageIter iter;
00514
00515 HAL_TRACE(("entering, udi=%s, cap=%s", udi, capability));
00516
00517 message = dbus_message_new_signal("/org/freedesktop/Hal/Manager",
00518 "org.freedesktop.Hal.Manager",
00519 "NewCapability");
00520
00521 dbus_message_iter_init(message, &iter);
00522 dbus_message_iter_append_string(&iter, udi);
00523 dbus_message_iter_append_string(&iter, capability);
00524
00525 if( !dbus_connection_send(dbus_connection,message, NULL) )
00526 DIE(("error broadcasting message"));
00527
00528 dbus_message_unref(message);
00529 }
00530
00552 static DBusHandlerResult device_get_all_properties(DBusConnection* connection,
00553 DBusMessage* message)
00554 {
00555 DBusMessage* reply;
00556 DBusMessageIter iter;
00557 DBusMessageIter iter_dict;
00558 HalDevice* d;
00559 const char* udi;
00560 HalPropertyIterator iter_prop;
00561
00562 udi = dbus_message_get_path(message);
00563
00564 HAL_TRACE(("entering, udi=%s", udi));
00565
00566 d = ds_device_find(udi);
00567 if( d==NULL )
00568 {
00569 raise_no_such_device(connection, message, udi);
00570 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00571 }
00572
00573 reply = dbus_message_new_method_return(message);
00574 if( reply==NULL )
00575 DIE(("No memory"));
00576
00577 dbus_message_iter_init(reply, &iter);
00578 dbus_message_iter_append_dict(&iter, &iter_dict);
00579
00580 for(ds_property_iter_begin(d, &iter_prop);
00581 ds_property_iter_has_more(&iter_prop);
00582 ds_property_iter_next(&iter_prop))
00583 {
00584 int type;
00585 HalProperty* p;
00586 const char* key;
00587
00588 p = ds_property_iter_get(&iter_prop);
00589 key = ds_property_iter_get_key(p);
00590 type = ds_property_iter_get_type(p);
00591
00592 dbus_message_iter_append_dict_key(&iter_dict, key);
00593
00594 switch( type )
00595 {
00596 case DBUS_TYPE_STRING:
00597 dbus_message_iter_append_string(&iter_dict,
00598 ds_property_iter_get_string(p));
00599 break;
00600 case DBUS_TYPE_INT32:
00601 dbus_message_iter_append_int32(&iter_dict,
00602 ds_property_iter_get_int(p));
00603 break;
00604 case DBUS_TYPE_DOUBLE:
00605 dbus_message_iter_append_double(&iter_dict,
00606 ds_property_iter_get_double(p));
00607 break;
00608 case DBUS_TYPE_BOOLEAN:
00609 dbus_message_iter_append_boolean(&iter_dict,
00610 ds_property_iter_get_bool(p));
00611 break;
00612
00613 default:
00614 HAL_WARNING(("Unknown property type %d", type));
00615 break;
00616 }
00617 }
00618
00619 if( !dbus_connection_send(connection, reply, NULL) )
00620 DIE(("No memory"));
00621
00622 dbus_message_unref(reply);
00623
00624 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00625 }
00626
00627
00645 static DBusHandlerResult device_get_property(DBusConnection* connection,
00646 DBusMessage* message)
00647 {
00648 DBusMessage* reply;
00649 DBusMessageIter iter;
00650 DBusError error;
00651 HalDevice* d;
00652 const char* udi;
00653 char* key;
00654 int type;
00655 HalProperty* p;
00656
00657 udi = dbus_message_get_path(message);
00658
00659 HAL_TRACE(("entering, udi=%s", udi));
00660
00661 d = ds_device_find(udi);
00662 if( d==NULL )
00663 {
00664 raise_no_such_device(connection, message, udi);
00665 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00666 }
00667
00668 dbus_error_init(&error);
00669 if( !dbus_message_get_args(message, &error,
00670 DBUS_TYPE_STRING, &key,
00671 DBUS_TYPE_INVALID) )
00672 {
00673 raise_syntax(connection, message, "GetProperty");
00674 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00675 }
00676
00677 p = ds_property_find(d, key);
00678 if( p==NULL )
00679 {
00680 raise_no_such_property(connection, message, udi, key);
00681 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00682 }
00683
00684 reply = dbus_message_new_method_return(message);
00685 if( reply==NULL )
00686 DIE(("No memory"));
00687
00688 dbus_message_iter_init(reply, &iter);
00689
00690 type = ds_property_iter_get_type(p);
00691 switch( type )
00692 {
00693 case DBUS_TYPE_STRING:
00694 dbus_message_iter_append_string(&iter,
00695 ds_property_iter_get_string(p));
00696 break;
00697 case DBUS_TYPE_INT32:
00698 dbus_message_iter_append_int32(&iter,
00699 ds_property_iter_get_int(p));
00700 break;
00701 case DBUS_TYPE_DOUBLE:
00702 dbus_message_iter_append_double(&iter,
00703 ds_property_iter_get_double(p));
00704 break;
00705 case DBUS_TYPE_BOOLEAN:
00706 dbus_message_iter_append_boolean(&iter,
00707 ds_property_iter_get_bool(p));
00708 break;
00709
00710 default:
00711 HAL_WARNING(("Unknown property type %d", type));
00712 break;
00713 }
00714
00715 if( !dbus_connection_send(connection, reply, NULL) )
00716 DIE(("No memory"));
00717
00718 dbus_message_unref(reply);
00719
00720 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00721 }
00722
00723
00737 static DBusHandlerResult device_get_property_type(DBusConnection* connection,
00738 DBusMessage* message)
00739 {
00740 DBusMessage* reply;
00741 DBusMessageIter iter;
00742 DBusError error;
00743 HalDevice* d;
00744 const char* udi;
00745 char* key;
00746 HalProperty* p;
00747
00748 udi = dbus_message_get_path(message);
00749
00750 HAL_TRACE(("entering, udi=%s", udi));
00751
00752 d = ds_device_find(udi);
00753 if( d==NULL )
00754 {
00755 raise_no_such_device(connection, message, udi);
00756 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00757 }
00758
00759 dbus_error_init(&error);
00760 if( !dbus_message_get_args(message, &error,
00761 DBUS_TYPE_STRING, &key,
00762 DBUS_TYPE_INVALID) )
00763 {
00764 raise_syntax(connection, message, "GetPropertyType");
00765 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00766 }
00767
00768 p = ds_property_find(d, key);
00769 if( p==NULL )
00770 {
00771 raise_no_such_property(connection, message, udi, key);
00772 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00773 }
00774
00775 reply = dbus_message_new_method_return(message);
00776 if( reply==NULL )
00777 DIE(("No memory"));
00778
00779 dbus_message_iter_init(reply, &iter);
00780 dbus_message_iter_append_int32(&iter, ds_property_iter_get_type(p));
00781
00782 if( !dbus_connection_send(connection, reply, NULL) )
00783 DIE(("No memory"));
00784
00785 dbus_message_unref(reply);
00786
00787 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00788 }
00789
00790
00791
00810 static DBusHandlerResult device_set_property(DBusConnection* connection,
00811 DBusMessage* message)
00812 {
00813 const char* udi;
00814 char* key;
00815 int type;
00816 dbus_bool_t rc;
00817 HalDevice* device;
00818 DBusMessageIter iter;
00819 DBusMessage *reply;
00820
00821 HAL_TRACE(("entering"));
00822
00823 udi = dbus_message_get_path(message);
00824
00825 dbus_message_iter_init(message, &iter);
00826 type = dbus_message_iter_get_arg_type(&iter);
00827 if( type!=DBUS_TYPE_STRING )
00828 {
00829 raise_syntax(connection, message, "SetProperty");
00830 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00831 }
00832 key = dbus_message_iter_get_string(&iter);
00833
00834 HAL_DEBUG(("udi=%s, key=%s", udi, key));
00835
00836 device = ds_device_find(udi);
00837 if( device==NULL )
00838 {
00839 raise_no_such_device(connection, message, udi);
00840 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00841 }
00842 dbus_message_iter_next(&iter);
00843
00846 type = dbus_message_iter_get_arg_type(&iter);
00847 rc = FALSE;
00848 switch( type )
00849 {
00850 case DBUS_TYPE_STRING:
00851 rc = ds_property_set_string(device, key,
00852 dbus_message_iter_get_string(&iter));
00853 break;
00854 case DBUS_TYPE_INT32:
00855 rc = ds_property_set_int(device, key,
00856 dbus_message_iter_get_int32(&iter));
00857 break;
00858 case DBUS_TYPE_DOUBLE:
00859 rc = ds_property_set_double(device, key,
00860 dbus_message_iter_get_double(&iter));
00861 break;
00862 case DBUS_TYPE_BOOLEAN:
00863 rc = ds_property_set_bool(device, key,
00864 dbus_message_iter_get_boolean(&iter));
00865 break;
00866
00867 default:
00868 HAL_WARNING(("Unsupported property type %d", type));
00869 break;
00870 }
00871
00872 if( !rc )
00873 {
00874 raise_property_type_error(connection, message, udi, key);
00875 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00876 }
00877
00878 reply = dbus_message_new_method_return(message);
00879 if( reply==NULL )
00880 DIE(("No memory"));
00881
00882 if( !dbus_connection_send(connection, reply, NULL) )
00883 DIE(("No memory"));
00884
00885 dbus_message_unref(reply);
00886 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00887 }
00888
00889
00891 #define MAX_CAP_SIZE 2048
00892
00919 static DBusHandlerResult device_add_capability(DBusConnection* connection,
00920 DBusMessage* message)
00921 {
00922 const char* udi;
00923 const char* capability;
00924 const char* caps;
00925 HalDevice* d;
00926 DBusMessage *reply;
00927 DBusError error;
00928 char buf[MAX_CAP_SIZE];
00929
00930 HAL_TRACE(("entering"));
00931
00932 udi = dbus_message_get_path(message);
00933
00934 d = ds_device_find(udi);
00935 if( d==NULL )
00936 {
00937 raise_no_such_device(connection, message, udi);
00938 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00939 }
00940
00941 dbus_error_init(&error);
00942 if( !dbus_message_get_args(message, &error,
00943 DBUS_TYPE_STRING, &capability,
00944 DBUS_TYPE_INVALID) )
00945 {
00946 raise_syntax(connection, message, "AddCapability");
00947 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00948 }
00949
00950
00951 caps = ds_property_get_string(d, "info.capabilities");
00952 if( caps==NULL )
00953 {
00954 ds_property_set_string(d, "info.capabilities", capability);
00955 }
00956 else
00957 {
00958 if( strstr(caps, capability)==NULL )
00959 {
00960 snprintf(buf, MAX_CAP_SIZE, "%s %s", caps, capability);
00961 ds_property_set_string(d, "info.capabilities", buf);
00962 }
00963 }
00964
00965 if( d->in_gdl )
00966 {
00967 manager_send_signal_new_capability(udi, capability);
00968 }
00969
00970
00971 reply = dbus_message_new_method_return(message);
00972 if( reply==NULL )
00973 DIE(("No memory"));
00974
00975 if( !dbus_connection_send(connection, reply, NULL) )
00976 DIE(("No memory"));
00977
00978 dbus_message_unref(reply);
00979 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00980 }
00981
00982
00983
00997 static DBusHandlerResult device_remove_property(DBusConnection* connection,
00998 DBusMessage* message)
00999 {
01000 const char* udi;
01001 char* key;
01002 HalDevice* d;
01003 DBusMessage *reply;
01004 DBusError error;
01005
01006 HAL_TRACE(("entering"));
01007
01008 udi = dbus_message_get_path(message);
01009
01010 d = ds_device_find(udi);
01011 if( d==NULL )
01012 {
01013 raise_no_such_device(connection, message, udi);
01014 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01015 }
01016
01017 dbus_error_init(&error);
01018 if( !dbus_message_get_args(message, &error,
01019 DBUS_TYPE_STRING, &key,
01020 DBUS_TYPE_INVALID) )
01021 {
01022 raise_syntax(connection, message, "RemoveProperty");
01023 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01024 }
01025
01026 if( !ds_property_remove(d, key) )
01027 {
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 device_property_exists(DBusConnection* connection,
01058 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 {
01074 raise_no_such_device(connection, message, udi);
01075 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01076 }
01077
01078 dbus_error_init(&error);
01079 if( !dbus_message_get_args(message, &error,
01080 DBUS_TYPE_STRING, &key,
01081 DBUS_TYPE_INVALID) )
01082 {
01083 raise_syntax(connection, message, "RemoveProperty");
01084 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01085 }
01086
01087 reply = dbus_message_new_method_return(message);
01088 if( reply==NULL )
01089 DIE(("No memory"));
01090
01091 dbus_message_iter_init(reply, &iter);
01092 dbus_message_iter_append_boolean(&iter, ds_property_exists(d, key));
01093
01094 if( !dbus_connection_send(connection, reply, NULL) )
01095 DIE(("No memory"));
01096
01097 dbus_message_unref(reply);
01098 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01099 }
01100
01101
01114 static DBusHandlerResult 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 {
01133 raise_no_such_device(connection, message, udi);
01134 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01135 }
01136
01137 dbus_error_init(&error);
01138 if( !dbus_message_get_args(message, &error,
01139 DBUS_TYPE_STRING, &capability,
01140 DBUS_TYPE_INVALID) )
01141 {
01142 raise_syntax(connection, message, "QueryCapability");
01143 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01144 }
01145
01146 reply = dbus_message_new_method_return(message);
01147 if( reply==NULL )
01148 DIE(("No memory"));
01149
01150 rc = FALSE;
01151 caps = ds_property_get_string(d, "info.capabilities");
01152 if( caps!=NULL )
01153 {
01154 if( strstr(caps, capability)!=NULL )
01155 rc = TRUE;
01156 }
01157
01158 dbus_message_iter_init(reply, &iter);
01159 dbus_message_iter_append_boolean(&iter, rc);
01160
01161 if( !dbus_connection_send(connection, reply, NULL) )
01162 DIE(("No memory"));
01163
01164 dbus_message_unref(reply);
01165 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01166 }
01167
01168
01192 static DBusHandlerResult agent_manager_new_device(DBusConnection* connection,
01193 DBusMessage* message)
01194 {
01195 HalDevice* d;
01196 DBusMessage* reply;
01197 DBusMessageIter iter;
01198 const char* udi;
01199
01200 HAL_TRACE(("entering"));
01201
01202 reply = dbus_message_new_method_return(message);
01203 if( reply==NULL )
01204 DIE(("No memory"));
01205
01206 d = ds_device_new();
01207 udi = ds_device_get_udi(d);
01208
01209 HAL_TRACE(("udi=%s", udi));
01210
01211 dbus_message_iter_init(reply, &iter);
01212 dbus_message_iter_append_string(&iter, udi);
01213
01214 if( !dbus_connection_send(connection, reply, NULL) )
01215 DIE(("No memory"));
01216
01217 dbus_message_unref (reply);
01218
01219 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01220 }
01221
01244 static DBusHandlerResult agent_manager_commit_to_gdl(
01245 DBusConnection* connection,
01246 DBusMessage* message)
01247 {
01248 DBusMessage* reply;
01249 DBusError error;
01250 HalDevice* d;
01251 const char* old_udi;
01252 const char* new_udi;
01253
01254 dbus_error_init(&error);
01255 if( !dbus_message_get_args(message, &error,
01256 DBUS_TYPE_STRING, &old_udi,
01257 DBUS_TYPE_STRING, &new_udi,
01258 DBUS_TYPE_INVALID) )
01259 {
01260 raise_syntax(connection, message, "CommitToGdl");
01261 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01262 }
01263
01264 HAL_TRACE(("entering, old_udi=%s, new_udi=%s", old_udi, new_udi));
01265
01266 d = ds_device_find(old_udi);
01267 if( d==NULL )
01268 {
01269 raise_no_such_device(connection, message, old_udi);
01270 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01271 }
01272
01273 if( !ds_device_set_udi(d, new_udi) )
01274 {
01275 raise_udi_in_use(connection, message, new_udi);
01276 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01277 }
01278
01279
01280 ds_gdl_add(d);
01281
01282
01283
01284
01285
01286 reply = dbus_message_new_method_return(message);
01287 if( reply==NULL )
01288 DIE(("No memory"));
01289
01290 if( !dbus_connection_send(connection, reply, NULL) )
01291 DIE(("No memory"));
01292
01293 dbus_message_unref(reply);
01294 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01295 }
01296
01297
01314 static DBusHandlerResult agent_manager_remove(DBusConnection* connection,
01315 DBusMessage* message)
01316 {
01317 DBusMessage* reply;
01318 DBusError error;
01319 HalDevice* d;
01320 const char* udi;
01321
01322 dbus_error_init(&error);
01323 if( !dbus_message_get_args(message, &error,
01324 DBUS_TYPE_STRING, &udi,
01325 DBUS_TYPE_INVALID) )
01326 {
01327 raise_syntax(connection, message, "Remove");
01328 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01329 }
01330
01331 HAL_INFO(("entering, udi=%s", udi));
01332
01333 d = ds_device_find(udi);
01334 if( d==NULL )
01335 {
01336 raise_no_such_device(connection, message, udi);
01337 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01338 }
01339
01340 ds_device_destroy(d);
01341
01342
01343
01344
01345
01346
01347
01348 reply = dbus_message_new_method_return(message);
01349 if( reply==NULL )
01350 DIE(("No memory"));
01351
01352 if( !dbus_connection_send(connection, reply, NULL) )
01353 DIE(("No memory"));
01354
01355 dbus_message_unref(reply);
01356 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01357 }
01358
01359
01360
01374 static DBusHandlerResult agent_merge_properties(DBusConnection* connection,
01375 DBusMessage* message)
01376 {
01377 DBusMessage* reply;
01378 DBusError error;
01379 HalDevice* target_d;
01380 HalDevice* source_d;
01381 const char* target_udi;
01382 const char* source_udi;
01383
01384 dbus_error_init(&error);
01385 if( !dbus_message_get_args(message, &error,
01386 DBUS_TYPE_STRING, &target_udi,
01387 DBUS_TYPE_STRING, &source_udi,
01388 DBUS_TYPE_INVALID) )
01389 {
01390 raise_syntax(connection, message, "MergeProperties");
01391 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01392 }
01393
01394 HAL_TRACE(("entering, target_udi=%s, source_udi=%s",
01395 target_udi, source_udi));
01396
01397 target_d = ds_device_find(target_udi);
01398 if( target_d==NULL )
01399 {
01400 raise_no_such_device(connection, message, target_udi);
01401 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01402 }
01403
01404 source_d = ds_device_find(source_udi);
01405 if( source_d==NULL )
01406 {
01407 raise_no_such_device(connection, message, source_udi);
01408 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01409 }
01410
01411 ds_device_merge(target_d, source_d);
01412
01413 reply = dbus_message_new_method_return(message);
01414 if( reply==NULL )
01415 DIE(("No memory"));
01416
01417 if( !dbus_connection_send(connection, reply, NULL) )
01418 DIE(("No memory"));
01419
01420 dbus_message_unref(reply);
01421 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01422 }
01423
01424
01447 static DBusHandlerResult agent_device_matches(DBusConnection* connection,
01448 DBusMessage* message)
01449 {
01450 DBusMessage* reply;
01451 DBusError error;
01452 HalDevice* d1;
01453 HalDevice* d2;
01454 const char* udi1;
01455 const char* udi2;
01456 const char* namespace;
01457 dbus_bool_t rc;
01458 DBusMessageIter iter;
01459
01460 dbus_error_init(&error);
01461 if( !dbus_message_get_args(message, &error,
01462 DBUS_TYPE_STRING, &udi1,
01463 DBUS_TYPE_STRING, &udi2,
01464 DBUS_TYPE_STRING, &namespace,
01465 DBUS_TYPE_INVALID) )
01466 {
01467 raise_syntax(connection, message, "DeviceMatches");
01468 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01469 }
01470
01471 HAL_TRACE(("entering, udi1=%s, udi2=%s, namespace=%s",
01472 udi1, udi2, namespace));
01473
01474 d1 = ds_device_find(udi1);
01475 if( d1==NULL )
01476 {
01477 raise_no_such_device(connection, message, udi1);
01478 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01479 }
01480
01481 d2 = ds_device_find(udi2);
01482 if( d2==NULL )
01483 {
01484 raise_no_such_device(connection, message, udi2);
01485 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01486 }
01487
01488 rc = ds_device_matches(d1, d2, namespace);
01489
01490 reply = dbus_message_new_method_return(message);
01491 if( reply==NULL )
01492 DIE(("No memory"));
01493
01494 dbus_message_iter_init(reply, &iter);
01495 dbus_message_iter_append_boolean(&iter, rc);
01496
01497 if( !dbus_connection_send(connection, reply, NULL) )
01498 DIE(("No memory"));
01499
01500 dbus_message_unref(reply);
01501 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01502 }
01503
01504
01524 static DBusHandlerResult filter_function(DBusConnection* connection,
01525 DBusMessage* message,
01526 void* user_data)
01527 {
01528
01529
01530
01531
01532
01533
01534
01535 if( dbus_message_is_method_call(message,
01536 "org.freedesktop.Hal.Manager",
01537 "GetAllDevices") &&
01538 strcmp(dbus_message_get_path(message),
01539 "/org/freedesktop/Hal/Manager")==0 )
01540 {
01541 return manager_get_all_devices(connection, message);
01542 }
01543 else if( dbus_message_is_method_call(message,
01544 "org.freedesktop.Hal.Manager",
01545 "DeviceExists") &&
01546 strcmp(dbus_message_get_path(message),
01547 "/org/freedesktop/Hal/Manager")==0 )
01548 {
01549 return manager_device_exists(connection, message);
01550 }
01551 else if( dbus_message_is_method_call(message,
01552 "org.freedesktop.Hal.Manager",
01553 "FindDeviceStringMatch") &&
01554 strcmp(dbus_message_get_path(message),
01555 "/org/freedesktop/Hal/Manager")==0 )
01556 {
01557 return manager_find_device_string_match(connection, message);
01558 }
01559 else if( dbus_message_is_method_call(message,
01560 "org.freedesktop.Hal.Manager",
01561 "FindDeviceByCapability") &&
01562 strcmp(dbus_message_get_path(message),
01563 "/org/freedesktop/Hal/Manager")==0 )
01564 {
01565 return manager_find_device_by_capability(connection, message);
01566 }
01567
01568 else if( dbus_message_is_method_call(message,
01569 "org.freedesktop.Hal.AgentManager",
01570 "NewDevice") &&
01571 strcmp(dbus_message_get_path(message),
01572 "/org/freedesktop/Hal/Manager")==0 )
01573 {
01574 return agent_manager_new_device(connection, message);
01575 }
01576 else if( dbus_message_is_method_call(message,
01577 "org.freedesktop.Hal.AgentManager",
01578 "CommitToGdl") &&
01579 strcmp(dbus_message_get_path(message),
01580 "/org/freedesktop/Hal/Manager")==0 )
01581 {
01582 return agent_manager_commit_to_gdl(connection, message);
01583 }
01584 else if( dbus_message_is_method_call(message,
01585 "org.freedesktop.Hal.AgentManager",
01586 "Remove") &&
01587 strcmp(dbus_message_get_path(message),
01588 "/org/freedesktop/Hal/Manager")==0 )
01589 {
01590 return agent_manager_remove(connection, message);
01591 }
01592 else if( dbus_message_is_method_call(message,
01593 "org.freedesktop.Hal.AgentManager",
01594 "MergeProperties") &&
01595 strcmp(dbus_message_get_path(message),
01596 "/org/freedesktop/Hal/Manager")==0 )
01597 {
01598 return agent_merge_properties(connection, message);
01599 }
01600 else if( dbus_message_is_method_call(message,
01601 "org.freedesktop.Hal.AgentManager",
01602 "DeviceMatches") &&
01603 strcmp(dbus_message_get_path(message),
01604 "/org/freedesktop/Hal/Manager")==0 )
01605 {
01606 return agent_device_matches(connection, message);
01607 }
01608
01609
01610 else if( dbus_message_is_method_call(message,
01611 "org.freedesktop.Hal.Device",
01612 "GetAllProperties") )
01613 {
01614 return device_get_all_properties(connection, message);
01615 }
01616 else if( dbus_message_is_method_call(message,
01617 "org.freedesktop.Hal.Device",
01618 "GetProperty") )
01619 {
01620 return device_get_property(connection, message);
01621 }
01622 else if( dbus_message_is_method_call(message,
01623 "org.freedesktop.Hal.Device",
01624 "GetPropertyString") )
01625 {
01626 return device_get_property(connection, message);
01627 }
01628 else if( dbus_message_is_method_call(message,
01629 "org.freedesktop.Hal.Device",
01630 "GetPropertyInteger") )
01631 {
01632 return device_get_property(connection, message);
01633 }
01634 else if( dbus_message_is_method_call(message,
01635 "org.freedesktop.Hal.Device",
01636 "GetPropertyBoolean") )
01637 {
01638 return device_get_property(connection, message);
01639 }
01640 else if( dbus_message_is_method_call(message,
01641 "org.freedesktop.Hal.Device",
01642 "GetPropertyDouble") )
01643 {
01644 return device_get_property(connection, message);
01645 }
01646 else if( dbus_message_is_method_call(message,
01647 "org.freedesktop.Hal.Device",
01648 "SetProperty") )
01649 {
01650 return device_set_property(connection, message);
01651 }
01652 else if( dbus_message_is_method_call(message,
01653 "org.freedesktop.Hal.Device",
01654 "SetPropertyString") )
01655 {
01656 return device_set_property(connection, message);
01657 }
01658 else if( dbus_message_is_method_call(message,
01659 "org.freedesktop.Hal.Device",
01660 "SetPropertyInteger") )
01661 {
01662 return device_set_property(connection, message);
01663 }
01664 else if( dbus_message_is_method_call(message,
01665 "org.freedesktop.Hal.Device",
01666 "SetPropertyBoolean") )
01667 {
01668 return device_set_property(connection, message);
01669 }
01670 else if( dbus_message_is_method_call(message,
01671 "org.freedesktop.Hal.Device",
01672 "SetPropertyDouble") )
01673 {
01674 return device_set_property(connection, message);
01675 }
01676 else if( dbus_message_is_method_call(message,
01677 "org.freedesktop.Hal.Device",
01678 "RemoveProperty") )
01679 {
01680 return device_remove_property(connection, message);
01681 }
01682 else if( dbus_message_is_method_call(message,
01683 "org.freedesktop.Hal.Device",
01684 "GetPropertyType") )
01685 {
01686 return device_get_property_type(connection, message);
01687 }
01688 else if( dbus_message_is_method_call(message,
01689 "org.freedesktop.Hal.Device",
01690 "PropertyExists") )
01691 {
01692 return device_property_exists(connection, message);
01693 }
01694 else if( dbus_message_is_method_call(message,
01695 "org.freedesktop.Hal.Device",
01696 "AddCapability") )
01697 {
01698 return device_add_capability(connection, message);
01699 }
01700 else if( dbus_message_is_method_call(message,
01701 "org.freedesktop.Hal.Device",
01702 "QueryCapability") )
01703 {
01704 return device_query_capability(connection, message);
01705 }
01706 else
01707 osspec_filter_function(connection, message, user_data);
01708
01709 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01710 }
01711
01713 static int atomic_count = 0;
01714
01720 void property_atomic_update_begin()
01721 {
01722 atomic_count++;
01723 }
01724
01726 static int num_pending_updates = 0;
01727
01729 typedef struct PendingUpdate_s
01730 {
01731 HalDevice* device;
01732 char* key;
01733 dbus_bool_t removed;
01734 dbus_bool_t added;
01735 struct PendingUpdate_s* next;
01736 } PendingUpdate;
01737
01738 static PendingUpdate* pending_updates_head = NULL;
01739
01744 void property_atomic_update_end()
01745 {
01746 PendingUpdate* pu_iter = NULL;
01747 PendingUpdate* pu_iter_next = NULL;
01748 PendingUpdate* pu_iter2 = NULL;
01749
01750 --atomic_count;
01751
01752 if( atomic_count<0 )
01753 {
01754 HAL_WARNING(("*** atomic_count = %d < 0 !!", atomic_count));
01755 atomic_count=0;
01756 }
01757
01758 if( atomic_count==0 && num_pending_updates>0 )
01759 {
01760 DBusMessage* message;
01761 DBusMessageIter iter;
01762
01763 for(pu_iter=pending_updates_head;
01764 pu_iter!=NULL;
01765 pu_iter=pu_iter_next)
01766 {
01767 int num_updates_this;
01768
01769 pu_iter_next = pu_iter->next;
01770
01771 if( pu_iter->device==NULL )
01772 goto have_processed;
01773
01774
01775 num_updates_this = 0;
01776 for(pu_iter2=pu_iter;
01777 pu_iter2!=NULL;
01778 pu_iter2=pu_iter2->next)
01779 {
01780 if( pu_iter2->device==pu_iter->device )
01781 num_updates_this++;
01782 }
01783
01784
01785 message = dbus_message_new_signal(pu_iter->device->udi,
01786 "org.freedesktop.Hal.Device",
01787 "PropertyModified");
01788 dbus_message_iter_init(message, &iter);
01789 dbus_message_iter_append_int32(&iter, num_updates_this);
01790 for(pu_iter2=pu_iter;
01791 pu_iter2!=NULL;
01792 pu_iter2=pu_iter2->next)
01793 {
01794 if( pu_iter2->device==pu_iter->device )
01795 {
01796 dbus_message_iter_append_string(&iter, pu_iter2->key);
01797 dbus_message_iter_append_boolean(&iter, pu_iter2->removed);
01798 dbus_message_iter_append_boolean(&iter, pu_iter2->added);
01799
01800
01801 if( pu_iter2!=pu_iter )
01802 pu_iter2->device = NULL;
01803 }
01804 }
01805
01806
01807 if( !dbus_connection_send(dbus_connection,message, NULL) )
01808 DIE(("error broadcasting message"));
01809
01810 dbus_message_unref(message);
01811
01812 have_processed:
01813 free(pu_iter->key);
01814 free(pu_iter);
01815 }
01816
01817 num_pending_updates = 0;
01818 pending_updates_head = NULL;
01819 }
01820 }
01821
01841 void emit_condition(HalDevice* device, const char* condition_name,
01842 int first_arg_type, ... )
01843 {
01844 DBusMessage* message;
01845 DBusMessageIter iter;
01846 va_list var_args;
01847
01848 if( !device->in_gdl )
01849 return;
01850
01851 message = dbus_message_new_signal(device->udi,
01852 "org.freedesktop.Hal.Device",
01853 "Condition");
01854 dbus_message_iter_init(message, &iter);
01855 dbus_message_iter_append_string(&iter, condition_name);
01856
01857 va_start(var_args, first_arg_type);
01858 dbus_message_append_args_valist(message, first_arg_type, var_args);
01859 va_end(var_args);
01860
01861 if( !dbus_connection_send(dbus_connection,message, NULL) )
01862 DIE(("error broadcasting message"));
01863
01864 dbus_message_unref(message);
01865 }
01866
01877 static void property_changed(HalDevice* device,
01878 const char* key,
01879 dbus_bool_t in_gdl,
01880 dbus_bool_t removed,
01881 dbus_bool_t added)
01882 {
01883 DBusMessage* message;
01884 DBusMessageIter iter;
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894 if( !in_gdl )
01895 return;
01896
01897 if( atomic_count>0 )
01898 {
01899 PendingUpdate* pu;
01900
01901 pu = xmalloc(sizeof(PendingUpdate));
01902 pu->device = device;
01903 pu->key = xstrdup(key);
01904 pu->removed = removed;
01905 pu->added = added;
01906 pu->next = pending_updates_head;
01907
01908 pending_updates_head = pu;
01909 num_pending_updates++;
01910 }
01911 else
01912 {
01913 message = dbus_message_new_signal(device->udi,
01914 "org.freedesktop.Hal.Device",
01915 "PropertyModified");
01916
01917 dbus_message_iter_init(message, &iter);
01918 dbus_message_iter_append_int32(&iter, 1);
01919 dbus_message_iter_append_string(&iter, key);
01920 dbus_message_iter_append_boolean(&iter, removed);
01921 dbus_message_iter_append_boolean(&iter, added);
01922
01923 if( !dbus_connection_send(dbus_connection,message, NULL) )
01924 DIE(("error broadcasting message"));
01925
01926 dbus_message_unref(message);
01927 }
01928 }
01929
01935 static void gdl_changed(HalDevice* device, dbus_bool_t is_added)
01936 {
01937 if( is_added )
01938 manager_send_signal_device_added(device->udi);
01939 else
01940 manager_send_signal_device_removed(device->udi);
01941 }
01942
01950 static void new_capability(HalDevice* device, const char* capability,
01951 dbus_bool_t in_gdl)
01952 {
01953 if( !in_gdl )
01954 return;
01955
01956 manager_send_signal_new_capability(device->udi, capability);
01957 }
01958
01962 static void usage()
01963 {
01964 fprintf(stderr,
01965 "\n"
01966 "usage : hald [--daemon=yes|no] [--help]\n");
01967 fprintf(stderr,
01968 "\n"
01969 " --daemon=yes|no Become a daemon\n"
01970 " --help Show this information and exit\n"
01971 "\n"
01972 "The HAL daemon detects devices present in the system and provides the\n"
01973 "org.freedesktop.Hal service through D-BUS. The commandline options given\n"
01974 "overrides the configuration given in " PACKAGE_SYSCONF_DIR "/hald.conf\n"
01975 "\n"
01976 "For more information visit http://freedesktop.org/Software/hal\n"
01977 "\n");
01978 }
01979
01980
01982 static dbus_bool_t opt_become_daemon = TRUE;
01983
01985 static char* opt_run_as = NULL;
01986
01993 int main(int argc, char* argv[])
01994 {
01995 GMainLoop* loop;
01996 DBusError dbus_error;
01997
01998
01999
02000
02001 while(1)
02002 {
02003 int c;
02004 int option_index = 0;
02005 const char* opt;
02006 static struct option long_options[] =
02007 {
02008 {"daemon", 1, NULL, 0},
02009 {"help", 0, NULL, 0},
02010 {NULL, 0, NULL, 0}
02011 };
02012
02013 c = getopt_long(argc, argv, "",
02014 long_options, &option_index);
02015 if (c == -1)
02016 break;
02017
02018 switch(c)
02019 {
02020 case 0:
02021 opt = long_options[option_index].name;
02022
02023 if( strcmp(opt, "help")==0 )
02024 {
02025 usage();
02026 return 0;
02027 }
02028 else if( strcmp(opt, "daemon")==0 )
02029 {
02030 if( strcmp("yes", optarg)==0 )
02031 {
02032 opt_become_daemon = TRUE;
02033 }
02034 else if( strcmp("no", optarg)==0 )
02035 {
02036 opt_become_daemon = FALSE;
02037 }
02038 else
02039 {
02040 usage();
02041 return 1;
02042 }
02043 }
02044 break;
02045
02046 default:
02047 usage();
02048 return 1;
02049 break;
02050 }
02051 }
02052
02053 logger_init();
02054 HAL_INFO(("HAL daemon version " PACKAGE_VERSION " starting up"));
02055
02056 HAL_DEBUG(("opt_become_daemon = %d", opt_become_daemon));
02057
02058 if( opt_become_daemon )
02059 {
02060 int child_pid;
02061 int dev_null_fd;
02062
02063 if( chdir("/")<0 )
02064 {
02065 HAL_ERROR(("Could not chdir to /, errno=%d", errno));
02066 return 1;
02067 }
02068
02069 child_pid = fork();
02070 switch( child_pid )
02071 {
02072 case -1:
02073 HAL_ERROR(("Cannot fork(), errno=%d", errno));
02074 break;
02075
02076 case 0:
02077
02078
02079 dev_null_fd = open("/dev/null", O_RDWR);
02080
02081 if( dev_null_fd>0 )
02082 {
02083
02084 dup2(dev_null_fd, 0);
02085 dup2(dev_null_fd, 1);
02086 dup2(dev_null_fd, 2);
02087 }
02088
02089 umask(022);
02090
02093 break;
02094
02095 default:
02096
02097 exit(0);
02098 break;
02099 }
02100
02101
02102 setsid();
02103 }
02104
02105 if( opt_run_as!=NULL )
02106 {
02107 uid_t uid;
02108 gid_t gid;
02109 struct passwd* pw;
02110
02111
02112 if( (pw = getpwnam(opt_run_as)) == NULL )
02113 {
02114 HAL_ERROR(("Could not lookup user %s, errno=%d",
02115 opt_run_as, errno));
02116 exit(1);
02117 }
02118
02119 uid = pw->pw_uid;
02120 gid = pw->pw_gid;
02121
02122 if( setgid(gid)<0 )
02123 {
02124 HAL_ERROR(("Failed to set GID to %d, errno=%d", gid, errno));
02125 exit(1);
02126 }
02127
02128 if( setuid(uid)<0 )
02129 {
02130 HAL_ERROR(("Failed to set UID to %d, errno=%d", uid, errno));
02131 exit(1);
02132 }
02133
02134 }
02135
02136
02137 ds_init();
02138
02139
02140 ds_add_cb_newcap(new_capability);
02141 ds_add_cb_gdl_changed(gdl_changed);
02142 ds_add_cb_property_changed(property_changed);
02143
02144 loop = g_main_loop_new (NULL, FALSE);
02145
02146 dbus_connection_set_change_sigpipe(TRUE);
02147
02148 dbus_error_init(&dbus_error);
02149 dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
02150 if( dbus_connection==NULL )
02151 {
02152 HAL_ERROR(("dbus_bus_get(): '%s'", dbus_error.message));
02153 exit(1);
02154 }
02155
02156 dbus_connection_setup_with_g_main(dbus_connection, NULL);
02157
02158 dbus_bus_acquire_service(dbus_connection, "org.freedesktop.Hal",
02159 0, &dbus_error);
02160 if( dbus_error_is_set(&dbus_error) )
02161 {
02162 HAL_ERROR(("dbus_bus_acquire_service(): '%s'", dbus_error.message));
02163 exit(1);
02164 }
02165
02166 dbus_connection_add_filter(dbus_connection, filter_function, NULL, NULL);
02167
02168
02169 osspec_init(dbus_connection);
02170
02171 osspec_probe();
02172
02173
02174 g_main_loop_run (loop);
02175
02176 return 0;
02177 }
02178
02184 void* xmalloc(unsigned int how_much)
02185 {
02186 void* p = malloc(how_much);
02187 if( !p )
02188 DIE(("Unable to allocate %d bytes of memory", how_much));
02189 return p;
02190 }
02191
02197 char* xstrdup(const char* str)
02198 {
02199 char* p = strdup(str);
02200 if( !p )
02201 DIE(("Unable to duplicate string '%s'", str));
02202 return p;
02203 }
02204