Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

main.c

00001 /***************************************************************************
00002  * CVSID: $Id: main.c,v 1.20 2004/03/03 17:56:56 david Exp $
00003  *
00004  * main.c : main() for HAL daemon
00005  *
00006  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
00007  *
00008  * Licensed under the Academic Free License version 2.0
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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>  /* for common defines etc. */
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         /* only return devices in the GDL */
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     /* add to the GDL */
01275     ds_gdl_add (d);
01276 
01277     /* Ok, send out a signal on the Manager interface that we added
01278      * this device to the gdl */
01279     /*manager_send_signal_device_added(new_udi); */
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     /* Ok, send out a signal on the Manager interface that we removed
01336      * this device from the gdl */
01337     /*
01338        manager_send_signal_device_removed(udi);
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     HAL_INFO (("obj_path=%s interface=%s method=%s", 
01517     dbus_message_get_path(message), 
01518     dbus_message_get_interface(message),
01519     dbus_message_get_member(message)));
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             /* count number of updates for this device */
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             /* prepare message */
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                     /* signal this is already processed */
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         }       /* for all updates */
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     HAL_INFO(("Entering, udi=%s, key=%s, in_gdl=%s, removed=%s added=%s",
01832               device->udi, key, 
01833               in_gdl ? "true" : "false",
01834               removed ? "true" : "false",
01835               added ? "true" : "false"));
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     /* We require root to sniff mii registers */
01942     /*opt_run_as = HAL_USER; */
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             /* child */
02008 
02009             dev_null_fd = open ("/dev/null", O_RDWR);
02010             /* ignore if we can't open /dev/null */
02011             if (dev_null_fd > 0) {
02012                 /* attach /dev/null to stdout, stdin, stderr */
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             /* parent */
02026             exit (0);
02027             break;
02028         }
02029 
02030         /* Create session */
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     /* initialize the device store */
02064     ds_init ();
02065 
02066     /* add callbacks from device store */
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     /* initialize operating system specific parts */
02096     osspec_init (dbus_connection);
02097     /* and detect devices */
02098     osspec_probe ();
02099 
02100     /* run the main loop and serve clients */
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 

Generated on Thu Mar 11 21:32:23 2004 for HAL by doxygen 1.3.6-20040222