(linenum→info "unix/slp.c:2238")

dbus/1.0.2/bus/driver.c

    1: /* -*- mode: C; c-file-style: "gnu" -*- */
    2: /* driver.c  Bus client (driver)
    3:  *
    4:  * Copyright (C) 2003 CodeFactory AB
    5:  * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
    6:  *
    7:  * Licensed under the Academic Free License version 2.1
    8:  * 
    9:  * This program is free software; you can redistribute it and/or modify
   10:  * it under the terms of the GNU General Public License as published by
   11:  * the Free Software Foundation; either version 2 of the License, or
   12:  * (at your option) any later version.
   13:  *
   14:  * This program is distributed in the hope that it will be useful,
   15:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17:  * GNU General Public License for more details.
   18:  * 
   19:  * You should have received a copy of the GNU General Public License
   20:  * along with this program; if not, write to the Free Software
   21:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22:  *
   23:  */
   24: 
   25: #include "activation.h"
   26: #include "connection.h"
   27: #include "driver.h"
   28: #include "dispatch.h"
   29: #include "services.h"
   30: #include "selinux.h"
   31: #include "signals.h"
   32: #include "utils.h"
   33: #include <dbus/dbus-string.h>
   34: #include <dbus/dbus-internals.h>
   35: #include <dbus/dbus-marshal-recursive.h>
   36: #include <string.h>
   37: 
   38: static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
   39:                                                     DBusMessage    *hello_message,
   40:                                                     BusTransaction *transaction,
   41:                                                     DBusError      *error);
   42: 
   43: dbus_bool_t
   44: bus_driver_send_service_owner_changed (const char     *service_name,
   45:                                        const char     *old_owner,
   46:                                        const char     *new_owner,
   47:                                        BusTransaction *transaction,
   48:                                        DBusError      *error)
   49: {
   50:   DBusMessage *message;
   51:   dbus_bool_t retval;
   52:   const char *null_service;
   53: 
   54:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   55: 
   56:   null_service = "";
   57:   _dbus_verbose ("sending name owner changed: %s [%s -> %s]\n",
   58:                  service_name, 
   59:                  old_owner ? old_owner : null_service, 
   60:                  new_owner ? new_owner : null_service);
   61: 
   62:   message = dbus_message_new_signal (DBUS_PATH_DBUS,
   63:                                      DBUS_INTERFACE_DBUS,
   64:                                      "NameOwnerChanged");
   65:   
   66:   if (message == NULL)
   67:     {
   68:       BUS_SET_OOM (error);
   69:       return FALSE;
   70:     }
   71:   
   72:   if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
   73:     goto oom;
   74: 
   75:   if (!dbus_message_append_args (message,
   76:                                  DBUS_TYPE_STRING, &service_name,
   77:                                  DBUS_TYPE_STRING, old_owner ? &old_owner : &null_service,
   78:                                  DBUS_TYPE_STRING, new_owner ? &new_owner : &null_service,
   79:                                  DBUS_TYPE_INVALID))
   80:     goto oom;
   81: 
   82:   _dbus_assert (dbus_message_has_signature (message, "sss"));
   83:   
   84:   retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
   85:   dbus_message_unref (message);
   86: 
   87:   return retval;
   88: 
   89:  oom:
   90:   dbus_message_unref (message);
   91:   BUS_SET_OOM (error);
   92:   return FALSE;
   93: }
   94: 
   95: dbus_bool_t
   96: bus_driver_send_service_lost (DBusConnection *connection,
   97:                               const char     *service_name,
   98:                               BusTransaction *transaction,
   99:                               DBusError      *error)
  100: {
  101:   DBusMessage *message;
  102: 
  103:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  104:   
  105:   message = dbus_message_new_signal (DBUS_PATH_DBUS,
  106:                                      DBUS_INTERFACE_DBUS,
  107:                                      "NameLost");
  108:   
  109:   if (message == NULL)
  110:     {
  111:       BUS_SET_OOM (error);
  112:       return FALSE;
  113:     }
  114:   
  115:   if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
  116:       !dbus_message_append_args (message,
  117:                                  DBUS_TYPE_STRING, &service_name,
  118:                                  DBUS_TYPE_INVALID))
  119:     {
  120:       dbus_message_unref (message);
  121:       BUS_SET_OOM (error);
  122:       return FALSE;
  123:     }
  124: 
  125:   if (!bus_transaction_send_from_driver (transaction, connection, message))
  126:     {
  127:       dbus_message_unref (message);
  128:       BUS_SET_OOM (error);
  129:       return FALSE;
  130:     }
  131:   else
  132:     {
  133:       dbus_message_unref (message);
  134:       return TRUE;
  135:     }
  136: }
  137: 
  138: dbus_bool_t
  139: bus_driver_send_service_acquired (DBusConnection *connection,
  140:                                   const char     *service_name,
  141:                                   BusTransaction *transaction,
  142:                                   DBusError      *error)
  143: {
  144:   DBusMessage *message;
  145: 
  146:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  147:   
  148:   message = dbus_message_new_signal (DBUS_PATH_DBUS,
  149:                                      DBUS_INTERFACE_DBUS,
  150:                                      "NameAcquired");
  151: 
  152:   if (message == NULL)
  153:     {
  154:       BUS_SET_OOM (error);
  155:       return FALSE;
  156:     }
  157:   
  158:   if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
  159:       !dbus_message_append_args (message,
  160:                                  DBUS_TYPE_STRING, &service_name,
  161:                                  DBUS_TYPE_INVALID))
  162:     {
  163:       dbus_message_unref (message);
  164:       BUS_SET_OOM (error);
  165:       return FALSE;
  166:     }
  167: 
  168:   if (!bus_transaction_send_from_driver (transaction, connection, message))
  169:     {
  170:       dbus_message_unref (message);
  171:       BUS_SET_OOM (error);
  172:       return FALSE;
  173:     }
  174:   else
  175:     {
  176:       dbus_message_unref (message);
  177:       return TRUE;
  178:     }
  179: }
  180: 
  181: static dbus_bool_t
  182: create_unique_client_name (BusRegistry *registry,
  183:                            DBusString  *str)
  184: {
  185:   /* We never want to use the same unique client name twice, because
  186:    * we want to guarantee that if you send a message to a given unique
  187:    * name, you always get the same application. So we use two numbers
  188:    * for INT_MAX * INT_MAX combinations, should be pretty safe against
  189:    * wraparound.
  190:    */
  191:   /* FIXME these should be in BusRegistry rather than static vars */
  192:   static int next_major_number = 0;
  193:   static int next_minor_number = 0;
  194:   int len;
  195:   
  196:   len = _dbus_string_get_length (str);
  197:   
  198:   while (TRUE)
  199:     {
  200:       /* start out with 1-0, go to 1-1, 1-2, 1-3,
  201:        * up to 1-MAXINT, then 2-0, 2-1, etc.
  202:        */
  203:       if (next_minor_number <= 0)
  204:         {
  205:           next_major_number += 1;
  206:           next_minor_number = 0;
  207:           if (next_major_number <= 0)
  208:             _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added");
  209:         }
  210: 
  211:       _dbus_assert (next_major_number > 0);
  212:       _dbus_assert (next_minor_number >= 0);
  213: 
  214:       /* appname:MAJOR-MINOR */
  215:       
  216:       if (!_dbus_string_append (str, ":"))
  217:         return FALSE;
  218:       
  219:       if (!_dbus_string_append_int (str, next_major_number))
  220:         return FALSE;
  221: 
  222:       if (!_dbus_string_append (str, "."))
  223:         return FALSE;
  224:       
  225:       if (!_dbus_string_append_int (str, next_minor_number))
  226:         return FALSE;
  227: 
  228:       next_minor_number += 1;
  229:       
  230:       /* Check if a client with the name exists */
  231:       if (bus_registry_lookup (registry, str) == NULL)
  232:         break;
  233: 
  234:       /* drop the number again, try the next one. */
  235:       _dbus_string_set_length (str, len);
  236:     }
  237: 
  238:   return TRUE;
  239: }
  240: 
  241: static dbus_bool_t
  242: bus_driver_handle_hello (DBusConnection *connection,
  243:                          BusTransaction *transaction,
  244:                          DBusMessage    *message,
  245:                          DBusError      *error)
  246: {
  247:   DBusString unique_name;
  248:   BusService *service;
  249:   dbus_bool_t retval;
  250:   BusRegistry *registry;
  251:   BusConnections *connections;
  252: 
  253:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  254: 
  255:   if (bus_connection_is_active (connection))
  256:     {
  257:       /* We already handled an Hello message for this connection. */
  258:       dbus_set_error (error, DBUS_ERROR_FAILED,
  259:                       "Already handled an Hello message");
  260:       return FALSE;
  261:     }
  262: 
  263:   /* Note that when these limits are exceeded we don't disconnect the
  264:    * connection; we just sort of leave it hanging there until it times
  265:    * out or disconnects itself or is dropped due to the max number of
  266:    * incomplete connections. It's even OK if the connection wants to
  267:    * retry the hello message, we support that.
  268:    */
  269:   connections = bus_connection_get_connections (connection);
  270:   if (!bus_connections_check_limits (connections, connection,
  271:                                      error))
  272:     {
  273:       _DBUS_ASSERT_ERROR_IS_SET (error);
  274:       return FALSE;
  275:     }
  276:   
  277:   if (!_dbus_string_init (&unique_name))
  278:     {
  279:       BUS_SET_OOM (error);
  280:       return FALSE;
  281:     }
  282: 
  283:   retval = FALSE;
  284: 
  285:   registry = bus_connection_get_registry (connection);
  286:   
  287:   if (!create_unique_client_name (registry, &unique_name))
  288:     {
  289:       BUS_SET_OOM (error);
  290:       goto out_0;
  291:     }
  292: 
  293:   if (!bus_connection_complete (connection, &unique_name, error))
  294:     {
  295:       _DBUS_ASSERT_ERROR_IS_SET (error);
  296:       goto out_0;
  297:     }
  298:   
  299:   if (!dbus_message_set_sender (message,
  300:                                 bus_connection_get_name (connection)))
  301:     {
  302:       BUS_SET_OOM (error);
  303:       goto out_0;
  304:     }
  305:   
  306:   if (!bus_driver_send_welcome_message (connection, message, transaction, error))
  307:     goto out_0;
  308: 
  309:   /* Create the service */
  310:   service = bus_registry_ensure (registry,
  311:                                  &unique_name, connection, 0, transaction, error);
  312:   if (service == NULL)
  313:     goto out_0;
  314:   
  315:   _dbus_assert (bus_connection_is_active (connection));
  316:   retval = TRUE;
  317:   
  318:  out_0:
  319:   _dbus_string_free (&unique_name);
  320:   return retval;
  321: }
  322: 
  323: static dbus_bool_t
  324: bus_driver_send_welcome_message (DBusConnection *connection,
  325:                                  DBusMessage    *hello_message,
  326:                                  BusTransaction *transaction,
  327:                                  DBusError      *error)
  328: {
  329:   DBusMessage *welcome;
  330:   const char *name;
  331: 
  332:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  333:   
  334:   name = bus_connection_get_name (connection);
  335:   _dbus_assert (name != NULL);
  336:   
  337:   welcome = dbus_message_new_method_return (hello_message);
  338:   if (welcome == NULL)
  339:     {
  340:       BUS_SET_OOM (error);
  341:       return FALSE;
  342:     }
  343:   
  344:   if (!dbus_message_append_args (welcome,
  345:                                  DBUS_TYPE_STRING, &name,
  346:                                  DBUS_TYPE_INVALID))
  347:     {
  348:       dbus_message_unref (welcome);
  349:       BUS_SET_OOM (error);
  350:       return FALSE;
  351:     }
  352: 
  353:   _dbus_assert (dbus_message_has_signature (welcome, DBUS_TYPE_STRING_AS_STRING));
  354:   
  355:   if (!bus_transaction_send_from_driver (transaction, connection, welcome))
  356:     {
  357:       dbus_message_unref (welcome);
  358:       BUS_SET_OOM (error);
  359:       return FALSE;
  360:     }
  361:   else
  362:     {
  363:       dbus_message_unref (welcome);
  364:       return TRUE;
  365:     }
  366: }
  367: 
  368: static dbus_bool_t
  369: bus_driver_handle_list_services (DBusConnection *connection,
  370:                                  BusTransaction *transaction,
  371:                                  DBusMessage    *message,
  372:                                  DBusError      *error)
  373: {
  374:   DBusMessage *reply;
  375:   int len;
  376:   char **services;
  377:   BusRegistry *registry;
  378:   int i;
  379:   DBusMessageIter iter;
  380:   DBusMessageIter sub;
  381: 
  382:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  383:   
  384:   registry = bus_connection_get_registry (connection);
  385:   
  386:   reply = dbus_message_new_method_return (message);
  387:   if (reply == NULL)
  388:     {
  389:       BUS_SET_OOM (error);
  390:       return FALSE;
  391:     }
  392: 
  393:   if (!bus_registry_list_services (registry, &services, &len))
  394:     {
  395:       dbus_message_unref (reply);
  396:       BUS_SET_OOM (error);
  397:       return FALSE;
  398:     }
  399: 
  400:   dbus_message_iter_init_append (reply, &iter);
  401:   
  402:   if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
  403:                                          DBUS_TYPE_STRING_AS_STRING,
  404:                                          &sub))
  405:     {
  406:       dbus_free_string_array (services);
  407:       dbus_message_unref (reply);
  408:       BUS_SET_OOM (error);
  409:       return FALSE;
  410:     }
  411: 
  412:   {
  413:     /* Include the bus driver in the list */
  414:     const char *v_STRING = DBUS_SERVICE_DBUS;
  415:     if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
  416:                                          &v_STRING))
  417:       {
  418:         dbus_free_string_array (services);
  419:         dbus_message_unref (reply);
  420:         BUS_SET_OOM (error);
  421:         return FALSE;
  422:       }
  423:   }
  424:   
  425:   i = 0;
  426:   while (i < len)
  427:     {
  428:       if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
  429:                                            &services[i]))
  430:         {
  431:           dbus_free_string_array (services);
  432:           dbus_message_unref (reply);
  433:           BUS_SET_OOM (error);
  434:           return FALSE;
  435:         }
  436:       ++i;
  437:     }
  438: 
  439:   dbus_free_string_array (services);
  440: 
  441:   if (!dbus_message_iter_close_container (&iter, &sub))
  442:     {
  443:       dbus_message_unref (reply);
  444:       BUS_SET_OOM (error);
  445:       return FALSE;
  446:     }
  447:   
  448:   if (!bus_transaction_send_from_driver (transaction, connection, reply))
  449:     {
  450:       dbus_message_unref (reply);
  451:       BUS_SET_OOM (error);
  452:       return FALSE;
  453:     }
  454:   else
  455:     {
  456:       dbus_message_unref (reply);
  457:       return TRUE;
  458:     }
  459: }
  460: 
  461: static dbus_bool_t
  462: bus_driver_handle_list_activatable_services (DBusConnection *connection,
  463:                                              BusTransaction *transaction,
  464:                                              DBusMessage    *message,
  465:                                              DBusError      *error)
  466: {
  467:   DBusMessage *reply;
  468:   int len;
  469:   char **services;
  470:   BusActivation *activation;
  471:   int i;
  472:   DBusMessageIter iter;
  473:   DBusMessageIter sub;
  474: 
  475:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  476: 
  477:   activation = bus_connection_get_activation (connection);
  478: 
  479:   reply = dbus_message_new_method_return (message);
  480:   if (reply == NULL)
  481:     {
  482:       BUS_SET_OOM (error);
  483:       return FALSE;
  484:     }
  485: 
  486:   if (!bus_activation_list_services (activation, &services, &len))
  487:     {
  488:       dbus_message_unref (reply);
  489:       BUS_SET_OOM (error);
  490:       return FALSE;
  491:     }
  492: 
  493:   dbus_message_iter_init_append (reply, &iter);
  494: 
  495:   if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
  496:                                          DBUS_TYPE_STRING_AS_STRING,
  497:                                          &sub))
  498:     {
  499:       dbus_free_string_array (services);
  500:       dbus_message_unref (reply);
  501:       BUS_SET_OOM (error);
  502:       return FALSE;
  503:     }
  504: 
  505:   {
  506:     /* Include the bus driver in the list */
  507:     const char *v_STRING = DBUS_SERVICE_DBUS;
  508:     if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
  509:                                          &v_STRING))
  510:       {
  511:         dbus_free_string_array (services);
  512:         dbus_message_unref (reply);
  513:         BUS_SET_OOM (error);
  514:         return FALSE;
  515:       }
  516:   }
  517: 
  518:   i = 0;
  519:   while (i < len)
  520:     {
  521:       if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
  522:                                            &services[i]))
  523:         {
  524:           dbus_free_string_array (services);
  525:           dbus_message_unref (reply);
  526:           BUS_SET_OOM (error);
  527:           return FALSE;
  528:         }
  529:       ++i;
  530:     }
  531: 
  532:   dbus_free_string_array (services);
  533: 
  534:   if (!dbus_message_iter_close_container (&iter, &sub))
  535:     {
  536:       dbus_message_unref (reply);
  537:       BUS_SET_OOM (error);
  538:       return FALSE;
  539:     }
  540: 
  541:   if (!bus_transaction_send_from_driver (transaction, connection, reply))
  542:     {
  543:       dbus_message_unref (reply);
  544:       BUS_SET_OOM (error);
  545:       return FALSE;
  546:     }
  547:   else
  548:     {
  549:       dbus_message_unref (reply);
  550:       return TRUE;
  551:     }
  552: }
  553: 
  554: static dbus_bool_t
  555: bus_driver_handle_acquire_service (DBusConnection *connection,
  556:                                    BusTransaction *transaction,
  557:                                    DBusMessage    *message,
  558:                                    DBusError      *error)
  559: {
  560:   DBusMessage *reply;
  561:   DBusString service_name;
  562:   const char *name;
  563:   dbus_uint32_t service_reply;
  564:   dbus_uint32_t flags;
  565:   dbus_bool_t retval;
  566:   BusRegistry *registry;
  567: 
  568:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  569:   
  570:   registry = bus_connection_get_registry (connection);
  571:   
  572:   if (!dbus_message_get_args (message, error,
  573:                               DBUS_TYPE_STRING, &name,
  574:                               DBUS_TYPE_UINT32, &flags,
  575:                               DBUS_TYPE_INVALID))
  576:     return FALSE;
  577:   
  578:   _dbus_verbose ("Trying to own name %s with flags 0x%x\n", name, flags);
  579:   
  580:   retval = FALSE;
  581:   reply = NULL;
  582: 
  583:   _dbus_string_init_const (&service_name, name);
  584: 
  585:   if (!bus_registry_acquire_service (registry, connection,
  586:                                      &service_name, flags,
  587:                                      &service_reply, transaction,
  588:                                      error))
  589:     goto out;
  590:   
  591:   reply = dbus_message_new_method_return (message);
  592:   if (reply == NULL)
  593:     {
  594:       BUS_SET_OOM (error);
  595:       goto out;
  596:     }
  597: 
  598:   if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
  599:     {
  600:       BUS_SET_OOM (error);
  601:       goto out;
  602:     }
  603: 
  604:   if (!bus_transaction_send_from_driver (transaction, connection, reply))
  605:     {
  606:       BUS_SET_OOM (error);
  607:       goto out;
  608:     }
  609: 
  610:   retval = TRUE;
  611:   
  612:  out:
  613:   if (reply)
  614:     dbus_message_unref (reply);
  615:   return retval;
  616: } 
  617: 
  618: static dbus_bool_t
  619: bus_driver_handle_release_service (DBusConnection *connection,
  620:                                    BusTransaction *transaction,
  621:                                    DBusMessage    *message,
  622:                                    DBusError      *error)
  623: {
  624:   DBusMessage *reply;
  625:   DBusString service_name;
  626:   const char *name;
  627:   dbus_uint32_t service_reply;
  628:   dbus_bool_t retval;
  629:   BusRegistry *registry;
  630: 
  631:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  632: 
  633:   registry = bus_connection_get_registry (connection);
  634: 
  635:   if (!dbus_message_get_args (message, error,
  636:                               DBUS_TYPE_STRING, &name,
  637:                               DBUS_TYPE_INVALID))
  638:     return FALSE;
  639: 
  640:   _dbus_verbose ("Trying to release name %s\n", name);
  641: 
  642:   retval = FALSE;
  643:   reply = NULL;
  644: 
  645:   _dbus_string_init_const (&service_name, name);
  646: 
  647:   if (!bus_registry_release_service (registry, connection,
  648:                                      &service_name, &service_reply,
  649:                                      transaction, error))
  650:     goto out;
  651: