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

main.c

00001 /***************************************************************************
00002  * CVSID: $Id: main.c,v 1.19 2004/01/16 13:26:47 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 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         /* only return devices in the GDL */
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     /* add to the GDL */
01280     ds_gdl_add(d);
01281 
01282     /* Ok, send out a signal on the Manager interface that we added
01283      * this device to the gdl */
01284     /*manager_send_signal_device_added(new_udi);*/
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     /* Ok, send out a signal on the Manager interface that we removed
01343      * this device from the gdl */
01344     /*
01345     manager_send_signal_device_removed(udi);
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     HAL_INFO(("obj_path=%s interface=%s method=%s", 
01530               dbus_message_get_path(message), 
01531               dbus_message_get_interface(message),
01532               dbus_message_get_member(message)));
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             /* count number of updates for this device */
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             /* prepare message */
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                     /* signal this is already processed */
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         } /* for all updates */
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     HAL_INFO(("Entering, udi=%s, key=%s, in_gdl=%s, removed=%s added=%s",
01888               device->udi, key, 
01889               in_gdl ? "true" : "false",
01890               removed ? "true" : "false",
01891               added ? "true" : "false"));
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     /* We require root to sniff mii registers */
01999     /*opt_run_as = HAL_USER;*/
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             /* child */
02078 
02079             dev_null_fd = open("/dev/null", O_RDWR);
02080             /* ignore if we can't open /dev/null */
02081             if( dev_null_fd>0 )
02082             {
02083                 /* attach /dev/null to stdout, stdin and stderr */
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             /* parent */
02097             exit(0);
02098             break;
02099         }
02100         
02101         /* Create session */
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     /* initialize the device store */
02137     ds_init();
02138 
02139     /* add callbacks from device store */
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     /* initialize operating system specific parts */
02169     osspec_init(dbus_connection);
02170     /* and detect devices */
02171     osspec_probe();
02172 
02173     /* run the main loop and serve clients */
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 

Generated on Sat Feb 7 22:11:48 2004 for HAL by doxygen 1.3.5