os/ossrv/ofdbus/dbus/bus/activation.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/* -*- mode: C; c-file-style: "gnu" -*- */
sl@0
     2
/* activation.c  Activation of services
sl@0
     3
 *
sl@0
     4
 * Copyright (C) 2003  CodeFactory AB
sl@0
     5
 * Copyright (C) 2003  Red Hat, Inc.
sl@0
     6
 * Copyright (C) 2004  Imendio HB
sl@0
     7
 * Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
sl@0
     8
 *
sl@0
     9
 * Licensed under the Academic Free License version 2.1
sl@0
    10
 * 
sl@0
    11
 * This program is free software; you can redistribute it and/or modify
sl@0
    12
 * it under the terms of the GNU General Public License as published by
sl@0
    13
 * the Free Software Foundation; either version 2 of the License, or
sl@0
    14
 * (at your option) any later version.
sl@0
    15
 *
sl@0
    16
 * This program is distributed in the hope that it will be useful,
sl@0
    17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
sl@0
    18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
sl@0
    19
 * GNU General Public License for more details.
sl@0
    20
 * 
sl@0
    21
 * You should have received a copy of the GNU General Public License
sl@0
    22
 * along with this program; if not, write to the Free Software
sl@0
    23
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
sl@0
    24
 *
sl@0
    25
 */ 
sl@0
    26
#include "activation.h"
sl@0
    27
#include "desktop-file.h" 
sl@0
    28
#include "services.h"
sl@0
    29
#include "test.h"
sl@0
    30
#include "utils.h"
sl@0
    31
sl@0
    32
#ifndef __SYMBIAN32__
sl@0
    33
#include <dbus/dbus-internals.h>
sl@0
    34
#include <dbus/dbus-hash.h>
sl@0
    35
#include <dbus/dbus-list.h>
sl@0
    36
#include <dbus/dbus-shell.h>
sl@0
    37
#include <dbus/dbus-spawn.h>
sl@0
    38
#include <dbus/dbus-timeout.h>
sl@0
    39
#include <dbus/dbus-sysdeps.h>
sl@0
    40
#else
sl@0
    41
#include "dbus-internals.h"
sl@0
    42
#include "dbus-hash.h"
sl@0
    43
#include "dbus-list.h"
sl@0
    44
#include "dbus-shell.h"
sl@0
    45
#include "dbus-spawn.h"
sl@0
    46
#include "dbus-timeout.h"
sl@0
    47
#include "dbus-sysdeps.h"
sl@0
    48
#endif //__SYMBIAN32__
sl@0
    49
#include <dirent.h>
sl@0
    50
#include <errno.h>
sl@0
    51
sl@0
    52
#define DBUS_SERVICE_SECTION "D-BUS Service"
sl@0
    53
#define DBUS_SERVICE_NAME "Name"
sl@0
    54
#define DBUS_SERVICE_EXEC "Exec"
sl@0
    55
sl@0
    56
struct BusActivation
sl@0
    57
{
sl@0
    58
  int refcount;
sl@0
    59
  DBusHashTable *entries;
sl@0
    60
  DBusHashTable *pending_activations;
sl@0
    61
  char *server_address;
sl@0
    62
  BusContext *context;
sl@0
    63
  int n_pending_activations; /**< This is in fact the number of BusPendingActivationEntry,
sl@0
    64
                              * i.e. number of pending activation requests, not pending
sl@0
    65
                              * activations per se
sl@0
    66
                              */
sl@0
    67
  DBusHashTable *directories;
sl@0
    68
};
sl@0
    69
sl@0
    70
typedef struct
sl@0
    71
{
sl@0
    72
  int refcount;
sl@0
    73
  char *dir_c;
sl@0
    74
  DBusHashTable *entries;
sl@0
    75
} BusServiceDirectory;
sl@0
    76
sl@0
    77
typedef struct
sl@0
    78
{
sl@0
    79
  int refcount;
sl@0
    80
  char *name;
sl@0
    81
  char *exec;
sl@0
    82
  unsigned long mtime;
sl@0
    83
  BusServiceDirectory *s_dir;
sl@0
    84
  char *filename;
sl@0
    85
} BusActivationEntry;
sl@0
    86
sl@0
    87
typedef struct BusPendingActivationEntry BusPendingActivationEntry;
sl@0
    88
sl@0
    89
struct BusPendingActivationEntry
sl@0
    90
{
sl@0
    91
  DBusMessage *activation_message;
sl@0
    92
  DBusConnection *connection;
sl@0
    93
sl@0
    94
  dbus_bool_t auto_activation;
sl@0
    95
};
sl@0
    96
sl@0
    97
typedef struct
sl@0
    98
{
sl@0
    99
  int refcount;
sl@0
   100
  BusActivation *activation;
sl@0
   101
  char *service_name;
sl@0
   102
  char *exec;
sl@0
   103
  DBusList *entries;
sl@0
   104
  int n_entries;
sl@0
   105
  DBusBabysitter *babysitter;
sl@0
   106
  DBusTimeout *timeout;
sl@0
   107
  unsigned int timeout_added : 1;
sl@0
   108
} BusPendingActivation;
sl@0
   109
sl@0
   110
#if 0
sl@0
   111
static BusServiceDirectory *
sl@0
   112
bus_service_directory_ref (BusServiceDirectory *dir)
sl@0
   113
{
sl@0
   114
  _dbus_assert (dir->refcount);
sl@0
   115
  
sl@0
   116
  dir->refcount++;
sl@0
   117
sl@0
   118
  return dir;
sl@0
   119
}
sl@0
   120
#endif
sl@0
   121
sl@0
   122
static void
sl@0
   123
bus_service_directory_unref (BusServiceDirectory *dir)
sl@0
   124
{
sl@0
   125
  if (dir == NULL) 
sl@0
   126
    return; 
sl@0
   127
sl@0
   128
  _dbus_assert (dir->refcount > 0);
sl@0
   129
  dir->refcount--;
sl@0
   130
sl@0
   131
  if (dir->refcount > 0)
sl@0
   132
    return;
sl@0
   133
sl@0
   134
  if (dir->entries)
sl@0
   135
    _dbus_hash_table_unref (dir->entries);
sl@0
   136
sl@0
   137
  dbus_free (dir->dir_c);
sl@0
   138
  dbus_free (dir);
sl@0
   139
}
sl@0
   140
sl@0
   141
static void
sl@0
   142
bus_pending_activation_entry_free (BusPendingActivationEntry *entry)
sl@0
   143
{
sl@0
   144
  if (entry->activation_message)
sl@0
   145
    dbus_message_unref (entry->activation_message);
sl@0
   146
  
sl@0
   147
  if (entry->connection)
sl@0
   148
    dbus_connection_unref (entry->connection);
sl@0
   149
  
sl@0
   150
  dbus_free (entry);
sl@0
   151
}
sl@0
   152
sl@0
   153
static void
sl@0
   154
handle_timeout_callback (DBusTimeout   *timeout,
sl@0
   155
                         void          *data)
sl@0
   156
{
sl@0
   157
  BusPendingActivation *pending_activation = data;
sl@0
   158
sl@0
   159
  while (!dbus_timeout_handle (pending_activation->timeout))
sl@0
   160
    _dbus_wait_for_memory ();
sl@0
   161
}
sl@0
   162
sl@0
   163
static BusPendingActivation * 
sl@0
   164
bus_pending_activation_ref (BusPendingActivation *pending_activation)
sl@0
   165
{
sl@0
   166
  _dbus_assert (pending_activation->refcount > 0);
sl@0
   167
  pending_activation->refcount += 1;
sl@0
   168
sl@0
   169
  return pending_activation;
sl@0
   170
}
sl@0
   171
sl@0
   172
static void
sl@0
   173
bus_pending_activation_unref (BusPendingActivation *pending_activation)
sl@0
   174
{
sl@0
   175
  DBusList *link;
sl@0
   176
  
sl@0
   177
  if (pending_activation == NULL) /* hash table requires this */
sl@0
   178
    return;
sl@0
   179
sl@0
   180
  _dbus_assert (pending_activation->refcount > 0);
sl@0
   181
  pending_activation->refcount -= 1;
sl@0
   182
sl@0
   183
  if (pending_activation->refcount > 0)
sl@0
   184
    return;
sl@0
   185
  
sl@0
   186
  if (pending_activation->timeout_added)
sl@0
   187
    {
sl@0
   188
      _dbus_loop_remove_timeout (bus_context_get_loop (pending_activation->activation->context),
sl@0
   189
                                 pending_activation->timeout,
sl@0
   190
                                 handle_timeout_callback, pending_activation);
sl@0
   191
      pending_activation->timeout_added = FALSE;
sl@0
   192
    }
sl@0
   193
sl@0
   194
  if (pending_activation->timeout)
sl@0
   195
    _dbus_timeout_unref (pending_activation->timeout);
sl@0
   196
  
sl@0
   197
  if (pending_activation->babysitter)
sl@0
   198
    {
sl@0
   199
      if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
sl@0
   200
                                                 NULL, NULL, NULL,
sl@0
   201
                                                 pending_activation->babysitter,
sl@0
   202
                                                 NULL))
sl@0
   203
        _dbus_assert_not_reached ("setting watch functions to NULL failed");
sl@0
   204
      
sl@0
   205
      _dbus_babysitter_unref (pending_activation->babysitter);
sl@0
   206
    }
sl@0
   207
  
sl@0
   208
  dbus_free (pending_activation->service_name);
sl@0
   209
  dbus_free (pending_activation->exec);
sl@0
   210
sl@0
   211
  link = _dbus_list_get_first_link (&pending_activation->entries);
sl@0
   212
sl@0
   213
  while (link != NULL)
sl@0
   214
    {
sl@0
   215
      BusPendingActivationEntry *entry = link->data;
sl@0
   216
sl@0
   217
      bus_pending_activation_entry_free (entry);
sl@0
   218
sl@0
   219
      link = _dbus_list_get_next_link (&pending_activation->entries, link);
sl@0
   220
    }
sl@0
   221
  _dbus_list_clear (&pending_activation->entries);
sl@0
   222
sl@0
   223
  pending_activation->activation->n_pending_activations -=
sl@0
   224
    pending_activation->n_entries;
sl@0
   225
sl@0
   226
  _dbus_assert (pending_activation->activation->n_pending_activations >= 0);
sl@0
   227
  
sl@0
   228
  dbus_free (pending_activation);
sl@0
   229
}
sl@0
   230
sl@0
   231
static BusActivationEntry *
sl@0
   232
bus_activation_entry_ref (BusActivationEntry *entry)
sl@0
   233
{
sl@0
   234
  _dbus_assert (entry->refcount > 0);
sl@0
   235
  entry->refcount++;
sl@0
   236
sl@0
   237
  return entry;
sl@0
   238
}
sl@0
   239
sl@0
   240
static void
sl@0
   241
bus_activation_entry_unref (BusActivationEntry *entry)
sl@0
   242
{
sl@0
   243
  if (entry == NULL) /* hash table requires this */
sl@0
   244
    return;
sl@0
   245
  
sl@0
   246
  _dbus_assert (entry->refcount > 0);
sl@0
   247
  entry->refcount--;
sl@0
   248
  
sl@0
   249
  if (entry->refcount > 0) 
sl@0
   250
    return;
sl@0
   251
  
sl@0
   252
  dbus_free (entry->name);
sl@0
   253
  dbus_free (entry->exec);
sl@0
   254
  dbus_free (entry->filename);
sl@0
   255
sl@0
   256
  dbus_free (entry);
sl@0
   257
}
sl@0
   258
sl@0
   259
static dbus_bool_t
sl@0
   260
update_desktop_file_entry (BusActivation       *activation,
sl@0
   261
                           BusServiceDirectory *s_dir,
sl@0
   262
                           DBusString          *filename,
sl@0
   263
                           BusDesktopFile      *desktop_file,
sl@0
   264
                           DBusError           *error)
sl@0
   265
{
sl@0
   266
  char *name, *exec;
sl@0
   267
  BusActivationEntry *entry;
sl@0
   268
  DBusStat stat_buf;
sl@0
   269
  DBusString file_path;
sl@0
   270
sl@0
   271
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
sl@0
   272
  
sl@0
   273
  name = NULL;
sl@0
   274
  exec = NULL;
sl@0
   275
  entry = NULL;
sl@0
   276
  
sl@0
   277
  if (!_dbus_string_init (&file_path))
sl@0
   278
    {
sl@0
   279
      BUS_SET_OOM (error);
sl@0
   280
      return FALSE;
sl@0
   281
    }
sl@0
   282
 
sl@0
   283
  if (!_dbus_string_append (&file_path, s_dir->dir_c) ||
sl@0
   284
      !_dbus_concat_dir_and_file (&file_path, filename))
sl@0
   285
    {
sl@0
   286
      BUS_SET_OOM (error);
sl@0
   287
      goto failed;
sl@0
   288
    }
sl@0
   289
 
sl@0
   290
  if (!_dbus_stat (&file_path, &stat_buf, NULL)) 
sl@0
   291
    {
sl@0
   292
      dbus_set_error (error, DBUS_ERROR_FAILED,
sl@0
   293
                      "Can't stat the service file\n");
sl@0
   294
      goto failed;
sl@0
   295
    }
sl@0
   296
 
sl@0
   297
  if (!bus_desktop_file_get_string (desktop_file,
sl@0
   298
                                    DBUS_SERVICE_SECTION,
sl@0
   299
                                    DBUS_SERVICE_NAME,
sl@0
   300
                                    &name,
sl@0
   301
                                    error))
sl@0
   302
    goto failed;
sl@0
   303
sl@0
   304
  if (!bus_desktop_file_get_string (desktop_file,
sl@0
   305
                                    DBUS_SERVICE_SECTION,
sl@0
   306
                                    DBUS_SERVICE_EXEC,
sl@0
   307
                                    &exec,
sl@0
   308
                                    error))
sl@0
   309
    goto failed;
sl@0
   310
sl@0
   311
  entry = _dbus_hash_table_lookup_string (s_dir->entries, 
sl@0
   312
                                          _dbus_string_get_const_data (filename));
sl@0
   313
  if (entry == NULL) /* New file */
sl@0
   314
    { 
sl@0
   315
      /* FIXME we need a better-defined algorithm for which service file to
sl@0
   316
       * pick than "whichever one is first in the directory listing"
sl@0
   317
       */
sl@0
   318
      if (_dbus_hash_table_lookup_string (activation->entries, name))
sl@0
   319
        {
sl@0
   320
          dbus_set_error (error, DBUS_ERROR_FAILED,
sl@0
   321
                          "Service %s already exists in activation entry list\n", name);
sl@0
   322
          goto failed;
sl@0
   323
        }
sl@0
   324
      
sl@0
   325
      entry = dbus_new0 (BusActivationEntry, 1);
sl@0
   326
      if (entry == NULL)
sl@0
   327
        {
sl@0
   328
          BUS_SET_OOM (error);
sl@0
   329
          goto failed;
sl@0
   330
        }
sl@0
   331
     
sl@0
   332
      entry->name = name;
sl@0
   333
      entry->exec = exec;
sl@0
   334
      entry->refcount = 1;
sl@0
   335
    
sl@0
   336
      entry->s_dir = s_dir;
sl@0
   337
      entry->filename = _dbus_strdup (_dbus_string_get_const_data (filename));
sl@0
   338
      if (!entry->filename)
sl@0
   339
        {
sl@0
   340
          BUS_SET_OOM (error);
sl@0
   341
          goto failed;
sl@0
   342
        }
sl@0
   343
sl@0
   344
      if (!_dbus_hash_table_insert_string (activation->entries, entry->name, bus_activation_entry_ref (entry)))
sl@0
   345
        {
sl@0
   346
          BUS_SET_OOM (error);
sl@0
   347
          goto failed;
sl@0
   348
        }
sl@0
   349
     
sl@0
   350
      if (!_dbus_hash_table_insert_string (s_dir->entries, entry->filename, bus_activation_entry_ref (entry)))
sl@0
   351
        {
sl@0
   352
          /* Revert the insertion in the entries table */
sl@0
   353
          _dbus_hash_table_remove_string (activation->entries, entry->name);
sl@0
   354
          BUS_SET_OOM (error);
sl@0
   355
          goto failed;
sl@0
   356
        }
sl@0
   357
sl@0
   358
      _dbus_verbose ("Added \"%s\" to list of services\n", entry->name);
sl@0
   359
    }
sl@0
   360
  else /* Just update the entry */
sl@0
   361
    {
sl@0
   362
      bus_activation_entry_ref (entry);
sl@0
   363
      _dbus_hash_table_remove_string (activation->entries, entry->name);
sl@0
   364
sl@0
   365
      if (_dbus_hash_table_lookup_string (activation->entries, name))
sl@0
   366
        {
sl@0
   367
          _dbus_verbose ("The new service name \"%s\" of service file \"%s\" already in cache, ignoring\n",
sl@0
   368
                         name, _dbus_string_get_const_data (&file_path));
sl@0
   369
          goto failed;
sl@0
   370
        }
sl@0
   371
 
sl@0
   372
      dbus_free (entry->name);
sl@0
   373
      dbus_free (entry->exec);
sl@0
   374
      entry->name = name;
sl@0
   375
      entry->exec = exec;
sl@0
   376
      if (!_dbus_hash_table_insert_string (activation->entries,
sl@0
   377
                                           entry->name, bus_activation_entry_ref(entry)))
sl@0
   378
        {
sl@0
   379
          BUS_SET_OOM (error);
sl@0
   380
          /* Also remove path to entries hash since we want this in sync with
sl@0
   381
           * the entries hash table */
sl@0
   382
          _dbus_hash_table_remove_string (entry->s_dir->entries, 
sl@0
   383
                                          entry->filename);
sl@0
   384
          bus_activation_entry_unref (entry);
sl@0
   385
          return FALSE;
sl@0
   386
        }
sl@0
   387
    }
sl@0
   388
  
sl@0
   389
  entry->mtime = stat_buf.mtime;
sl@0
   390
  
sl@0
   391
  _dbus_string_free (&file_path);
sl@0
   392
  bus_activation_entry_unref (entry);
sl@0
   393
sl@0
   394
  return TRUE;
sl@0
   395
sl@0
   396
failed:
sl@0
   397
  dbus_free (name);
sl@0
   398
  dbus_free (exec);
sl@0
   399
  _dbus_string_free (&file_path);
sl@0
   400
sl@0
   401
  if (entry)
sl@0
   402
    bus_activation_entry_unref (entry);
sl@0
   403
  
sl@0
   404
  return FALSE;
sl@0
   405
}
sl@0
   406
sl@0
   407
static dbus_bool_t
sl@0
   408
check_service_file (BusActivation       *activation,
sl@0
   409
                    BusActivationEntry  *entry,
sl@0
   410
                    BusActivationEntry **updated_entry,
sl@0
   411
                    DBusError           *error)
sl@0
   412
{
sl@0
   413
  DBusStat stat_buf;
sl@0
   414
  dbus_bool_t retval;
sl@0
   415
  BusActivationEntry *tmp_entry;
sl@0
   416
  DBusString file_path;
sl@0
   417
  DBusString filename;
sl@0
   418
sl@0
   419
  retval = TRUE;
sl@0
   420
  tmp_entry = entry;
sl@0
   421
  
sl@0
   422
  _dbus_string_init_const (&filename, entry->filename);
sl@0
   423
  
sl@0
   424
  if (!_dbus_string_init (&file_path))
sl@0
   425
    {
sl@0
   426
      BUS_SET_OOM (error);
sl@0
   427
      return FALSE;
sl@0
   428
    }
sl@0
   429
 
sl@0
   430
  if (!_dbus_string_append (&file_path, entry->s_dir->dir_c) ||
sl@0
   431
      !_dbus_concat_dir_and_file (&file_path, &filename))
sl@0
   432
    {
sl@0
   433
      BUS_SET_OOM (error);
sl@0
   434
      retval = FALSE;
sl@0
   435
      goto out;
sl@0
   436
    }
sl@0
   437
  
sl@0
   438
  if (!_dbus_stat (&file_path, &stat_buf, NULL))
sl@0
   439
    {
sl@0
   440
      _dbus_verbose ("****** Can't stat file \"%s\", removing from cache\n",
sl@0
   441
                     _dbus_string_get_const_data (&file_path));
sl@0
   442
sl@0
   443
      _dbus_hash_table_remove_string (activation->entries, entry->name);
sl@0
   444
      _dbus_hash_table_remove_string (entry->s_dir->entries, entry->filename);
sl@0
   445
sl@0
   446
      tmp_entry = NULL;
sl@0
   447
      retval = TRUE;
sl@0
   448
      goto out;
sl@0
   449
    }
sl@0
   450
  else 
sl@0
   451
    {
sl@0
   452
      if (stat_buf.mtime > entry->mtime) 
sl@0
   453
        {
sl@0
   454
          BusDesktopFile *desktop_file;
sl@0
   455
          DBusError tmp_error;
sl@0
   456
          
sl@0
   457
          dbus_error_init (&tmp_error);
sl@0
   458
          
sl@0
   459
          desktop_file = bus_desktop_file_load (&file_path, &tmp_error);
sl@0
   460
          if (desktop_file == NULL)
sl@0
   461
            {
sl@0
   462
              _dbus_verbose ("Could not load %s: %s\n",
sl@0
   463
                             _dbus_string_get_const_data (&file_path), 
sl@0
   464
                             tmp_error.message);
sl@0
   465
              if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
sl@0
   466
                {
sl@0
   467
                  dbus_move_error (&tmp_error, error);
sl@0
   468
                  retval = FALSE;
sl@0
   469
                  goto out;
sl@0
   470
                }
sl@0
   471
              dbus_error_free (&tmp_error);
sl@0
   472
              retval = TRUE;
sl@0
   473
              goto out;
sl@0
   474
            }
sl@0
   475
         
sl@0
   476
          /* @todo We can return OOM or a DBUS_ERROR_FAILED error 
sl@0
   477
           *       Handle these both better
sl@0
   478
           */ 
sl@0
   479
          if (!update_desktop_file_entry (activation, entry->s_dir, &filename, desktop_file, &tmp_error))
sl@0
   480
            {
sl@0
   481
              bus_desktop_file_free (desktop_file);
sl@0
   482
              if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
sl@0
   483
                {
sl@0
   484
                  dbus_move_error (&tmp_error, error);
sl@0
   485
                  retval = FALSE;
sl@0
   486
                  goto out;
sl@0
   487
                }
sl@0
   488
              dbus_error_free (&tmp_error);
sl@0
   489
              retval = TRUE;
sl@0
   490
              goto out;
sl@0
   491
            }
sl@0
   492
         
sl@0
   493
          bus_desktop_file_free (desktop_file);
sl@0
   494
          retval = TRUE;
sl@0
   495
        }
sl@0
   496
    }
sl@0
   497
  
sl@0
   498
out:
sl@0
   499
  _dbus_string_free (&file_path);
sl@0
   500
sl@0
   501
  if (updated_entry != NULL)
sl@0
   502
    *updated_entry = tmp_entry;
sl@0
   503
  return retval;
sl@0
   504
}
sl@0
   505
sl@0
   506
sl@0
   507
/* warning: this doesn't fully "undo" itself on failure, i.e. doesn't strip
sl@0
   508
 * hash entries it already added.
sl@0
   509
 */
sl@0
   510
static dbus_bool_t
sl@0
   511
update_directory (BusActivation       *activation,
sl@0
   512
                  BusServiceDirectory *s_dir,
sl@0
   513
                  DBusError           *error)
sl@0
   514
{
sl@0
   515
  DBusDirIter *iter;
sl@0
   516
  DBusString dir, filename;
sl@0
   517
  BusDesktopFile *desktop_file;
sl@0
   518
  DBusError tmp_error;
sl@0
   519
  dbus_bool_t retval;
sl@0
   520
  BusActivationEntry *entry;
sl@0
   521
  DBusString full_path;
sl@0
   522
  
sl@0
   523
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
sl@0
   524
  
sl@0
   525
  iter = NULL;
sl@0
   526
  desktop_file = NULL;
sl@0
   527
  
sl@0
   528
  _dbus_string_init_const (&dir, s_dir->dir_c);
sl@0
   529
  
sl@0
   530
  if (!_dbus_string_init (&filename))
sl@0
   531
    {
sl@0
   532
      BUS_SET_OOM (error);
sl@0
   533
      return FALSE;
sl@0
   534
    }
sl@0
   535
sl@0
   536
  if (!_dbus_string_init (&full_path))
sl@0
   537
    {
sl@0
   538
      BUS_SET_OOM (error);
sl@0
   539
      _dbus_string_free (&filename);
sl@0
   540
      return FALSE;
sl@0
   541
    }
sl@0
   542
sl@0
   543
  retval = FALSE;
sl@0
   544
sl@0
   545
  /* from this point it's safe to "goto out" */
sl@0
   546
  
sl@0
   547
  iter = _dbus_directory_open (&dir, error);
sl@0
   548
  if (iter == NULL)
sl@0
   549
    {
sl@0
   550
      _dbus_verbose ("Failed to open directory %s: %s\n",
sl@0
   551
                     s_dir->dir_c, 
sl@0
   552
                     error ? error->message : "unknown");
sl@0
   553
      goto out;
sl@0
   554
    }
sl@0
   555
  
sl@0
   556
  /* Now read the files */
sl@0
   557
  dbus_error_init (&tmp_error);
sl@0
   558
  while (_dbus_directory_get_next_file (iter, &filename, &tmp_error))
sl@0
   559
    {
sl@0
   560
      _dbus_assert (!dbus_error_is_set (&tmp_error));
sl@0
   561
      
sl@0
   562
      _dbus_string_set_length (&full_path, 0);
sl@0
   563
      
sl@0
   564
      if (!_dbus_string_ends_with_c_str (&filename, ".service"))
sl@0
   565
        {
sl@0
   566
          _dbus_verbose ("Skipping non-.service file %s\n",
sl@0
   567
                         _dbus_string_get_const_data (&filename));
sl@0
   568
          continue;
sl@0
   569
        }
sl@0
   570
sl@0
   571
      entry = _dbus_hash_table_lookup_string (s_dir->entries, _dbus_string_get_const_data (&filename));
sl@0
   572
      if (entry) /* Already has this service file in the cache */ 
sl@0
   573
        {
sl@0
   574
          if (!check_service_file (activation, entry, NULL, error))
sl@0
   575
            goto out;
sl@0
   576
sl@0
   577
          continue;
sl@0
   578
        }
sl@0
   579
      
sl@0
   580
      if (!_dbus_string_append (&full_path, s_dir->dir_c) ||
sl@0
   581
          !_dbus_concat_dir_and_file (&full_path, &filename))
sl@0
   582
        {
sl@0
   583
          BUS_SET_OOM (error);
sl@0
   584
          goto out;
sl@0
   585
        }
sl@0
   586
          
sl@0
   587
      /* New file */
sl@0
   588
      desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
sl@0
   589
      if (desktop_file == NULL)
sl@0
   590
        {
sl@0
   591
          _dbus_verbose ("Could not load %s: %s\n",
sl@0
   592
                         _dbus_string_get_const_data (&full_path),
sl@0
   593
                         tmp_error.message);
sl@0
   594
sl@0
   595
          if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
sl@0
   596
            {
sl@0
   597
              dbus_move_error (&tmp_error, error);
sl@0
   598
              goto out;
sl@0
   599
            }
sl@0
   600
          
sl@0
   601
          dbus_error_free (&tmp_error);
sl@0
   602
          continue;
sl@0
   603
        }
sl@0
   604
sl@0
   605
      /* @todo We can return OOM or a DBUS_ERROR_FAILED error 
sl@0
   606
       *       Handle these both better
sl@0
   607
       */ 
sl@0
   608
      if (!update_desktop_file_entry (activation, s_dir, &filename, desktop_file, &tmp_error))
sl@0
   609
        {
sl@0
   610
          bus_desktop_file_free (desktop_file);
sl@0
   611
          desktop_file = NULL;
sl@0
   612
          
sl@0
   613
          _dbus_verbose ("Could not add %s to activation entry list: %s\n",
sl@0
   614
                         _dbus_string_get_const_data (&full_path), tmp_error.message);
sl@0
   615
sl@0
   616
          if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
sl@0
   617
            {
sl@0
   618
              dbus_move_error (&tmp_error, error);
sl@0
   619
              goto out;
sl@0
   620
            }
sl@0
   621
sl@0
   622
          dbus_error_free (&tmp_error);
sl@0
   623
          continue;
sl@0
   624
        }
sl@0
   625
      else
sl@0
   626
        {
sl@0
   627
          bus_desktop_file_free (desktop_file);
sl@0
   628
          desktop_file = NULL;
sl@0
   629
          continue;
sl@0
   630
        }
sl@0
   631
    }
sl@0
   632
sl@0
   633
  if (dbus_error_is_set (&tmp_error))
sl@0
   634
    {
sl@0
   635
      dbus_move_error (&tmp_error, error);
sl@0
   636
      goto out;
sl@0
   637
    }
sl@0
   638
  
sl@0
   639
  retval = TRUE;
sl@0
   640
sl@0
   641
 out:
sl@0
   642
  if (!retval)
sl@0
   643
    _DBUS_ASSERT_ERROR_IS_SET (error);
sl@0
   644
  else
sl@0
   645
    _DBUS_ASSERT_ERROR_IS_CLEAR (error);
sl@0
   646
  
sl@0
   647
  if (iter != NULL)
sl@0
   648
    _dbus_directory_close (iter);
sl@0
   649
  _dbus_string_free (&filename);
sl@0
   650
  _dbus_string_free (&full_path);
sl@0
   651
  
sl@0
   652
  return retval;
sl@0
   653
}
sl@0
   654
sl@0
   655
BusActivation*
sl@0
   656
bus_activation_new (BusContext        *context,
sl@0
   657
                    const DBusString  *address,
sl@0
   658
                    DBusList         **directories,
sl@0
   659
                    DBusError         *error)
sl@0
   660
{
sl@0
   661
  BusActivation *activation;
sl@0
   662
  DBusList      *link;
sl@0
   663
  char          *dir;
sl@0
   664
  
sl@0
   665
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
sl@0
   666
  
sl@0
   667
  activation = dbus_new0 (BusActivation, 1);
sl@0
   668
  if (activation == NULL)
sl@0
   669
    {
sl@0
   670
      BUS_SET_OOM (error);
sl@0
   671
      return NULL;
sl@0
   672
    }
sl@0
   673
  
sl@0
   674
  activation->refcount = 1;
sl@0
   675
  activation->context = context;
sl@0
   676
  activation->n_pending_activations = 0;
sl@0
   677
  
sl@0
   678
  if (!_dbus_string_copy_data (address, &activation->server_address))
sl@0
   679
    {
sl@0
   680
      BUS_SET_OOM (error);
sl@0
   681
      goto failed;
sl@0
   682
    }
sl@0
   683
  
sl@0
   684
  activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
sl@0
   685
                                             (DBusFreeFunction)bus_activation_entry_unref);
sl@0
   686
  if (activation->entries == NULL)
sl@0
   687
    {      
sl@0
   688
      BUS_SET_OOM (error);
sl@0
   689
      goto failed;
sl@0
   690
    }
sl@0
   691
sl@0
   692
  activation->pending_activations = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
sl@0
   693
                                                          (DBusFreeFunction)bus_pending_activation_unref);
sl@0
   694
sl@0
   695
  if (activation->pending_activations == NULL)
sl@0
   696
    {
sl@0
   697
      BUS_SET_OOM (error);
sl@0
   698
      goto failed;
sl@0
   699
    }
sl@0
   700
sl@0
   701
  activation->directories = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
sl@0
   702
                                                  (DBusFreeFunction)bus_service_directory_unref);
sl@0
   703
  
sl@0
   704
  if (activation->directories == NULL) 
sl@0
   705
    {
sl@0
   706
      BUS_SET_OOM (error);
sl@0
   707
      goto failed;
sl@0
   708
    }
sl@0
   709
 
sl@0
   710
  /* Load service files */
sl@0
   711
  link = _dbus_list_get_first_link (directories);
sl@0
   712
  while (link != NULL)
sl@0
   713
    {
sl@0
   714
      BusServiceDirectory *s_dir;
sl@0
   715
      
sl@0
   716
      dir = _dbus_strdup ((const char *) link->data);
sl@0
   717
      if (!dir)
sl@0
   718
        {
sl@0
   719
          BUS_SET_OOM (error);
sl@0
   720
          goto failed;
sl@0
   721
        }
sl@0
   722
      
sl@0
   723
      s_dir = dbus_new0 (BusServiceDirectory, 1);
sl@0
   724
      if (!s_dir)
sl@0
   725
        {
sl@0
   726
          dbus_free (dir);
sl@0
   727
          BUS_SET_OOM (error);
sl@0
   728
          goto failed;
sl@0
   729
        }
sl@0
   730
sl@0
   731
      s_dir->refcount = 1;
sl@0
   732
      s_dir->dir_c = dir;
sl@0
   733
      
sl@0
   734
      s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
sl@0
   735
                                             (DBusFreeFunction)bus_activation_entry_unref);
sl@0
   736
sl@0
   737
      if (!s_dir->entries)
sl@0
   738
        {
sl@0
   739
          bus_service_directory_unref (s_dir);
sl@0
   740
          BUS_SET_OOM (error);
sl@0
   741
          goto failed;
sl@0
   742
        }
sl@0
   743
sl@0
   744
      if (!_dbus_hash_table_insert_string (activation->directories, s_dir->dir_c, s_dir))
sl@0
   745
        {
sl@0
   746
          bus_service_directory_unref (s_dir);
sl@0
   747
          BUS_SET_OOM (error);
sl@0
   748
          goto failed;
sl@0
   749
        }
sl@0
   750
sl@0
   751
      /* only fail on OOM, it is ok if we can't read the directory */
sl@0
   752
      if (!update_directory (activation, s_dir, error))
sl@0
   753
        { 
sl@0
   754
          if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY)) 
sl@0
   755
            goto failed;
sl@0
   756
          else
sl@0
   757
            dbus_error_free (error);
sl@0
   758
        }
sl@0
   759
sl@0
   760
      link = _dbus_list_get_next_link (directories, link);
sl@0
   761
    }
sl@0
   762
sl@0
   763
  return activation;
sl@0
   764
  
sl@0
   765
 failed:
sl@0
   766
  bus_activation_unref (activation);  
sl@0
   767
  return NULL;
sl@0
   768
}
sl@0
   769
sl@0
   770
BusActivation *
sl@0
   771
bus_activation_ref (BusActivation *activation)
sl@0
   772
{
sl@0
   773
  _dbus_assert (activation->refcount > 0);
sl@0
   774
  
sl@0
   775
  activation->refcount += 1;
sl@0
   776
sl@0
   777
  return activation;
sl@0
   778
}
sl@0
   779
sl@0
   780
void
sl@0
   781
bus_activation_unref (BusActivation *activation)
sl@0
   782
{
sl@0
   783
  _dbus_assert (activation->refcount > 0);
sl@0
   784
sl@0
   785
  activation->refcount -= 1;
sl@0
   786
sl@0
   787
  if (activation->refcount > 0)
sl@0
   788
    return;
sl@0
   789
  
sl@0
   790
  dbus_free (activation->server_address);
sl@0
   791
  if (activation->entries)
sl@0
   792
    _dbus_hash_table_unref (activation->entries);
sl@0
   793
  if (activation->pending_activations)
sl@0
   794
    _dbus_hash_table_unref (activation->pending_activations);
sl@0
   795
  if (activation->directories)  
sl@0
   796
    _dbus_hash_table_unref (activation->directories);
sl@0
   797
  
sl@0
   798
  dbus_free (activation);
sl@0
   799
}
sl@0
   800
sl@0
   801
static void
sl@0
   802
child_setup (void *data)
sl@0
   803
{
sl@0
   804
  BusActivation *activation = data;
sl@0
   805
  const char *type;
sl@0
   806
  
sl@0
   807
  /* If no memory, we simply have the child exit, so it won't try
sl@0
   808
   * to connect to the wrong thing.
sl@0
   809
   */
sl@0
   810
  if (!_dbus_setenv ("DBUS_STARTER_ADDRESS", activation->server_address))
sl@0
   811
    _dbus_exit (1);
sl@0
   812
  
sl@0
   813
  type = bus_context_get_type (activation->context);
sl@0
   814
  if (type != NULL)
sl@0
   815
    {
sl@0
   816
      if (!_dbus_setenv ("DBUS_STARTER_BUS_TYPE", type))
sl@0
   817
        _dbus_exit (1);
sl@0
   818
sl@0
   819
      if (strcmp (type, "session") == 0)
sl@0
   820
        {
sl@0
   821
          if (!_dbus_setenv ("DBUS_SESSION_BUS_ADDRESS",
sl@0
   822
                             activation->server_address))
sl@0
   823
            _dbus_exit (1);
sl@0
   824
        }
sl@0
   825
      else if (strcmp (type, "system") == 0)
sl@0
   826
        {
sl@0
   827
          if (!_dbus_setenv ("DBUS_SYSTEM_BUS_ADDRESS",
sl@0
   828
                             activation->server_address))
sl@0
   829
            _dbus_exit (1);
sl@0
   830
        }
sl@0
   831
    }
sl@0
   832
}
sl@0
   833
sl@0
   834
typedef struct
sl@0
   835
{
sl@0
   836
  BusPendingActivation *pending_activation;
sl@0
   837
  DBusPreallocatedHash *hash_entry;
sl@0
   838
} RestorePendingData;
sl@0
   839
sl@0
   840
static void
sl@0
   841
restore_pending (void *data)
sl@0
   842
{
sl@0
   843
  RestorePendingData *d = data;
sl@0
   844
sl@0
   845
  _dbus_assert (d->pending_activation != NULL);
sl@0
   846
  _dbus_assert (d->hash_entry != NULL);
sl@0
   847
sl@0
   848
  _dbus_verbose ("Restoring pending activation for service %s, has timeout = %d\n",
sl@0
   849
                 d->pending_activation->service_name,
sl@0
   850
                 d->pending_activation->timeout_added);
sl@0
   851
  
sl@0
   852
  _dbus_hash_table_insert_string_preallocated (d->pending_activation->activation->pending_activations,
sl@0
   853
                                               d->hash_entry,
sl@0
   854
                                               d->pending_activation->service_name, d->pending_activation);
sl@0
   855
sl@0
   856
  bus_pending_activation_ref (d->pending_activation);
sl@0
   857
  
sl@0
   858
  d->hash_entry = NULL;
sl@0
   859
}
sl@0
   860
sl@0
   861
static void
sl@0
   862
free_pending_restore_data (void *data)
sl@0
   863
{
sl@0
   864
  RestorePendingData *d = data;
sl@0
   865
sl@0
   866
  if (d->hash_entry)
sl@0
   867
    _dbus_hash_table_free_preallocated_entry (d->pending_activation->activation->pending_activations,
sl@0
   868
                                              d->hash_entry);
sl@0
   869
sl@0
   870
  bus_pending_activation_unref (d->pending_activation);
sl@0
   871
  
sl@0
   872
  dbus_free (d);
sl@0
   873
}
sl@0
   874
sl@0
   875
static dbus_bool_t
sl@0
   876
add_restore_pending_to_transaction (BusTransaction       *transaction,
sl@0
   877
                                    BusPendingActivation *pending_activation)
sl@0
   878
{
sl@0
   879
  RestorePendingData *d;
sl@0
   880
sl@0
   881
  d = dbus_new (RestorePendingData, 1);
sl@0
   882
  if (d == NULL)
sl@0
   883
    return FALSE;
sl@0
   884
  
sl@0
   885
  d->pending_activation = pending_activation;
sl@0
   886
  d->hash_entry = _dbus_hash_table_preallocate_entry (d->pending_activation->activation->pending_activations);
sl@0
   887
  
sl@0
   888
  bus_pending_activation_ref (d->pending_activation);
sl@0
   889
  
sl@0
   890
  if (d->hash_entry == NULL ||
sl@0
   891
      !bus_transaction_add_cancel_hook (transaction, restore_pending, d,
sl@0
   892
                                        free_pending_restore_data))
sl@0
   893
    {
sl@0
   894
      free_pending_restore_data (d);
sl@0
   895
      return FALSE;
sl@0
   896
    }
sl@0
   897
sl@0
   898
  _dbus_verbose ("Saved pending activation to be restored if the transaction fails\n");
sl@0
   899
  
sl@0
   900
  return TRUE;
sl@0
   901
}
sl@0
   902
sl@0
   903
dbus_bool_t
sl@0
   904
bus_activation_service_created (BusActivation  *activation,
sl@0
   905
                                const char     *service_name,
sl@0
   906
                                BusTransaction *transaction,
sl@0
   907
                                DBusError      *error)
sl@0
   908
{
sl@0
   909
  BusPendingActivation *pending_activation;
sl@0
   910
  DBusMessage *message;
sl@0
   911
  DBusList *link;
sl@0
   912
sl@0
   913
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
sl@0
   914
  
sl@0
   915
  /* Check if it's a pending activation */
sl@0
   916
  pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
sl@0
   917
sl@0
   918
  if (!pending_activation)
sl@0
   919
    return TRUE;
sl@0
   920
sl@0
   921
  link = _dbus_list_get_first_link (&pending_activation->entries);
sl@0
   922
  while (link != NULL)
sl@0
   923
    {
sl@0
   924
      BusPendingActivationEntry *entry = link->data;
sl@0
   925
      DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
sl@0
   926
      
sl@0
   927
      if (dbus_connection_get_is_connected (entry->connection))
sl@0
   928
        {
sl@0
   929
          /* Only send activation replies to regular activation requests. */
sl@0
   930
          if (!entry->auto_activation)
sl@0
   931
            {
sl@0
   932
              dbus_uint32_t result;
sl@0
   933
              
sl@0
   934
              message = dbus_message_new_method_return (entry->activation_message);
sl@0
   935
              if (!message)
sl@0
   936
                {
sl@0
   937
                  BUS_SET_OOM (error);
sl@0
   938
                  goto error;
sl@0
   939
                }
sl@0
   940
sl@0
   941
              result = DBUS_START_REPLY_SUCCESS;
sl@0
   942
              
sl@0
   943
              if (!dbus_message_append_args (message,
sl@0
   944
                                             DBUS_TYPE_UINT32, &result,
sl@0
   945
                                             DBUS_TYPE_INVALID))
sl@0
   946
                {
sl@0
   947
                  dbus_message_unref (message);
sl@0
   948
                  BUS_SET_OOM (error);
sl@0
   949
                  goto error;
sl@0
   950
                }
sl@0
   951
              
sl@0
   952
              if (!bus_transaction_send_from_driver (transaction, entry->connection, message))
sl@0
   953
                {
sl@0
   954
                  dbus_message_unref (message);
sl@0
   955
                  BUS_SET_OOM (error);
sl@0
   956
                  goto error;
sl@0
   957
                }
sl@0
   958
              
sl@0
   959
              dbus_message_unref (message);
sl@0
   960
            }
sl@0
   961
        }
sl@0
   962
      
sl@0
   963
      link = next;
sl@0
   964
    }
sl@0
   965
sl@0
   966
  return TRUE;
sl@0
   967
sl@0
   968
 error:
sl@0
   969
  return FALSE;
sl@0
   970
}
sl@0
   971
sl@0
   972
dbus_bool_t
sl@0
   973
bus_activation_send_pending_auto_activation_messages (BusActivation  *activation,
sl@0
   974
                                                      BusService     *service,
sl@0
   975
                                                      BusTransaction *transaction,
sl@0
   976
                                                      DBusError      *error)
sl@0
   977
{
sl@0
   978
  BusPendingActivation *pending_activation;
sl@0
   979
  DBusList *link;
sl@0
   980
sl@0
   981
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
sl@0
   982
  
sl@0
   983
  /* Check if it's a pending activation */
sl@0
   984
  pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations,
sl@0
   985
                                                       bus_service_get_name (service));
sl@0
   986
sl@0
   987
  if (!pending_activation)
sl@0
   988
    return TRUE;
sl@0
   989
sl@0
   990
  link = _dbus_list_get_first_link (&pending_activation->entries);
sl@0
   991
  while (link != NULL)
sl@0
   992
    {
sl@0
   993
      BusPendingActivationEntry *entry = link->data;
sl@0
   994
      DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
sl@0
   995
sl@0
   996
      if (entry->auto_activation && dbus_connection_get_is_connected (entry->connection))
sl@0
   997
        {
sl@0
   998
          DBusConnection *addressed_recipient;
sl@0
   999
          
sl@0
  1000
          addressed_recipient = bus_service_get_primary_owners_connection (service);
sl@0
  1001
sl@0
  1002
          /* Check the security policy, which has the side-effect of adding an
sl@0
  1003
           * expected pending reply.
sl@0
  1004
           */
sl@0
  1005
          if (!bus_context_check_security_policy (activation->context, transaction,
sl@0
  1006
                                                  entry->connection,
sl@0
  1007
                                                  addressed_recipient,
sl@0
  1008
                                                  addressed_recipient,
sl@0
  1009
                                                  entry->activation_message, error))
sl@0
  1010
            goto error;
sl@0
  1011
sl@0
  1012
          if (!bus_transaction_send (transaction, addressed_recipient, entry->activation_message))
sl@0
  1013
            {
sl@0
  1014
              BUS_SET_OOM (error);
sl@0
  1015
              goto error;
sl@0
  1016
            }
sl@0
  1017
        }
sl@0
  1018
sl@0
  1019
      link = next;
sl@0
  1020
    }
sl@0
  1021
sl@0
  1022
  if (!add_restore_pending_to_transaction (transaction, pending_activation))
sl@0
  1023
    {
sl@0
  1024
      _dbus_verbose ("Could not add cancel hook to transaction to revert removing pending activation\n");
sl@0
  1025
      BUS_SET_OOM (error);
sl@0
  1026
      goto error;
sl@0
  1027
    }
sl@0
  1028
  
sl@0
  1029
  _dbus_hash_table_remove_string (activation->pending_activations, bus_service_get_name (service));
sl@0
  1030
sl@0
  1031
  return TRUE;
sl@0
  1032
sl@0
  1033
 error:
sl@0
  1034
  return FALSE;
sl@0
  1035
}
sl@0
  1036
sl@0
  1037
/**
sl@0
  1038
 * FIXME @todo the error messages here would ideally be preallocated
sl@0
  1039
 * so we don't need to allocate memory to send them.
sl@0
  1040
 * Using the usual tactic, prealloc an OOM message, then
sl@0
  1041
 * if we can't alloc the real error send the OOM error instead.
sl@0
  1042
 */
sl@0
  1043
static dbus_bool_t
sl@0
  1044
try_send_activation_failure (BusPendingActivation *pending_activation,
sl@0
  1045
                             const DBusError      *how)
sl@0
  1046
{
sl@0
  1047
  BusActivation *activation;
sl@0
  1048
  DBusList *link;
sl@0
  1049
  BusTransaction *transaction;
sl@0
  1050
  
sl@0
  1051
  activation = pending_activation->activation;
sl@0
  1052
sl@0
  1053
  transaction = bus_transaction_new (activation->context);
sl@0
  1054
  if (transaction == NULL)
sl@0
  1055
    return FALSE;
sl@0
  1056
  
sl@0
  1057
  link = _dbus_list_get_first_link (&pending_activation->entries);
sl@0
  1058
  while (link != NULL)
sl@0
  1059
    {
sl@0
  1060
      BusPendingActivationEntry *entry = link->data;
sl@0
  1061
      DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
sl@0
  1062
      
sl@0
  1063
      if (dbus_connection_get_is_connected (entry->connection))
sl@0
  1064
        {
sl@0
  1065
          if (!bus_transaction_send_error_reply (transaction,
sl@0
  1066
                                                 entry->connection,
sl@0
  1067
                                                 how,
sl@0
  1068
                                                 entry->activation_message))
sl@0
  1069
            goto error;
sl@0
  1070
        }
sl@0
  1071
      
sl@0
  1072
      link = next;
sl@0
  1073
    }
sl@0
  1074
sl@0
  1075
  bus_transaction_execute_and_free (transaction);
sl@0
  1076
  
sl@0
  1077
  return TRUE;
sl@0
  1078
sl@0
  1079
 error:
sl@0
  1080
  if (transaction)
sl@0
  1081
    bus_transaction_cancel_and_free (transaction);
sl@0
  1082
  return FALSE;
sl@0
  1083
}
sl@0
  1084
sl@0
  1085
/**
sl@0
  1086
 * Free the pending activation and send an error message to all the
sl@0
  1087
 * connections that were waiting for it.
sl@0
  1088
 */
sl@0
  1089
static void
sl@0
  1090
pending_activation_failed (BusPendingActivation *pending_activation,
sl@0
  1091
                           const DBusError      *how)
sl@0
  1092
{
sl@0
  1093
  /* FIXME use preallocated OOM messages instead of bus_wait_for_memory() */
sl@0
  1094
  while (!try_send_activation_failure (pending_activation, how))
sl@0
  1095
    _dbus_wait_for_memory ();
sl@0
  1096
sl@0
  1097
  /* Destroy this pending activation */
sl@0
  1098
  _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
sl@0
  1099
                                  pending_activation->service_name);
sl@0
  1100
}
sl@0
  1101
sl@0
  1102
static dbus_bool_t
sl@0
  1103
babysitter_watch_callback (DBusWatch     *watch,
sl@0
  1104
                           unsigned int   condition,
sl@0
  1105
                           void          *data)
sl@0
  1106
{
sl@0
  1107
  BusPendingActivation *pending_activation = data;
sl@0
  1108
  dbus_bool_t retval;
sl@0
  1109
  DBusBabysitter *babysitter;
sl@0
  1110
sl@0
  1111
  babysitter = pending_activation->babysitter;
sl@0
  1112
  
sl@0
  1113
  _dbus_babysitter_ref (babysitter);
sl@0
  1114
  
sl@0
  1115
  retval = dbus_watch_handle (watch, condition);
sl@0
  1116
sl@0
  1117
  /* FIXME this is broken in the same way that
sl@0
  1118
   * connection watches used to be; there should be
sl@0
  1119
   * a separate callback for status change, instead
sl@0
  1120
   * of doing "if we handled a watch status might
sl@0
  1121
   * have changed"
sl@0
  1122
   *
sl@0
  1123
   * Fixing this lets us move dbus_watch_handle
sl@0
  1124
   * calls into dbus-mainloop.c
sl@0
  1125
   */
sl@0
  1126
  
sl@0
  1127
  if (_dbus_babysitter_get_child_exited (babysitter))
sl@0
  1128
    {
sl@0
  1129
      DBusError error;
sl@0
  1130
      DBusHashIter iter;
sl@0
  1131
      
sl@0
  1132
      dbus_error_init (&error);
sl@0
  1133
      _dbus_babysitter_set_child_exit_error (babysitter, &error);
sl@0
  1134
sl@0
  1135
      /* Destroy all pending activations with the same exec */
sl@0
  1136
      _dbus_hash_iter_init (pending_activation->activation->pending_activations,
sl@0
  1137
                            &iter);
sl@0
  1138
      while (_dbus_hash_iter_next (&iter))
sl@0
  1139
        {
sl@0
  1140
          BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
sl@0
  1141
         
sl@0
  1142
          if (p != pending_activation && strcmp (p->exec, pending_activation->exec) == 0)
sl@0
  1143
            pending_activation_failed (p, &error);
sl@0
  1144
        }
sl@0
  1145
      
sl@0
  1146
      /* Destroys the pending activation */
sl@0
  1147
      pending_activation_failed (pending_activation, &error);
sl@0
  1148
sl@0
  1149
      dbus_error_free (&error);
sl@0
  1150
    }
sl@0
  1151
  
sl@0
  1152
  _dbus_babysitter_unref (babysitter);
sl@0
  1153
sl@0
  1154
  return retval;
sl@0
  1155
}
sl@0
  1156
sl@0
  1157
static dbus_bool_t
sl@0
  1158
add_babysitter_watch (DBusWatch      *watch,
sl@0
  1159
                      void           *data)
sl@0
  1160
{
sl@0
  1161
  BusPendingActivation *pending_activation = data;
sl@0
  1162
sl@0
  1163
  return _dbus_loop_add_watch (bus_context_get_loop (pending_activation->activation->context),
sl@0
  1164
                               watch, babysitter_watch_callback, pending_activation,
sl@0
  1165
                               NULL);
sl@0
  1166
}
sl@0
  1167
sl@0
  1168
static void
sl@0
  1169
remove_babysitter_watch (DBusWatch      *watch,
sl@0
  1170
                         void           *data)
sl@0
  1171
{
sl@0
  1172
  BusPendingActivation *pending_activation = data;
sl@0
  1173
  
sl@0
  1174
  _dbus_loop_remove_watch (bus_context_get_loop (pending_activation->activation->context),
sl@0
  1175
                           watch, babysitter_watch_callback, pending_activation);
sl@0
  1176
}
sl@0
  1177
sl@0
  1178
static dbus_bool_t
sl@0
  1179
pending_activation_timed_out (void *data)
sl@0
  1180
{
sl@0
  1181
  BusPendingActivation *pending_activation = data;
sl@0
  1182
  DBusError error;
sl@0
  1183
  
sl@0
  1184
  /* Kill the spawned process, since it sucks
sl@0
  1185
   * (not sure this is what we want to do, but
sl@0
  1186
   * may as well try it for now)
sl@0
  1187
   */
sl@0
  1188
  if (pending_activation->babysitter) 
sl@0
  1189
    _dbus_babysitter_kill_child (pending_activation->babysitter);
sl@0
  1190
sl@0
  1191
  dbus_error_init (&error);
sl@0
  1192
sl@0
  1193
  dbus_set_error (&error, DBUS_ERROR_TIMED_OUT,
sl@0
  1194
                  "Activation of %s timed out",
sl@0
  1195
                  pending_activation->service_name);
sl@0
  1196
sl@0
  1197
  pending_activation_failed (pending_activation, &error);
sl@0
  1198
sl@0
  1199
  dbus_error_free (&error);
sl@0
  1200
sl@0
  1201
  return TRUE;
sl@0
  1202
}
sl@0
  1203
sl@0
  1204
static void
sl@0
  1205
cancel_pending (void *data)
sl@0
  1206
{
sl@0
  1207
  BusPendingActivation *pending_activation = data;
sl@0
  1208
sl@0
  1209
  _dbus_verbose ("Canceling pending activation of %s\n",
sl@0
  1210
                 pending_activation->service_name);
sl@0
  1211
sl@0
  1212
  if (pending_activation->babysitter)
sl@0
  1213
    _dbus_babysitter_kill_child (pending_activation->babysitter);
sl@0
  1214
  
sl@0
  1215
  _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
sl@0
  1216
                                  pending_activation->service_name);
sl@0
  1217
}
sl@0
  1218
sl@0
  1219
static void
sl@0
  1220
free_pending_cancel_data (void *data)
sl@0
  1221
{
sl@0
  1222
  BusPendingActivation *pending_activation = data;
sl@0
  1223
  
sl@0
  1224
  bus_pending_activation_unref (pending_activation);
sl@0
  1225
}
sl@0
  1226
sl@0
  1227
static dbus_bool_t
sl@0
  1228
add_cancel_pending_to_transaction (BusTransaction       *transaction,
sl@0
  1229
                                   BusPendingActivation *pending_activation)
sl@0
  1230
{  
sl@0
  1231
  if (!bus_transaction_add_cancel_hook (transaction, cancel_pending,
sl@0
  1232
                                        pending_activation,
sl@0
  1233
                                        free_pending_cancel_data))
sl@0
  1234
    return FALSE;
sl@0
  1235
sl@0
  1236
  bus_pending_activation_ref (pending_activation); 
sl@0
  1237
  
sl@0
  1238
  _dbus_verbose ("Saved pending activation to be canceled if the transaction fails\n");
sl@0
  1239
  
sl@0
  1240
  return TRUE;
sl@0
  1241
}
sl@0
  1242
sl@0
  1243
static dbus_bool_t 
sl@0
  1244
update_service_cache (BusActivation *activation, DBusError *error)
sl@0
  1245
{
sl@0
  1246
  DBusHashIter iter;
sl@0
  1247
 
sl@0
  1248
  _dbus_hash_iter_init (activation->directories, &iter);
sl@0
  1249
  while (_dbus_hash_iter_next (&iter))
sl@0
  1250
    {
sl@0
  1251
      DBusError tmp_error;
sl@0
  1252
      BusServiceDirectory *s_dir;
sl@0
  1253
sl@0
  1254
      s_dir = _dbus_hash_iter_get_value (&iter);
sl@0
  1255
sl@0
  1256
      dbus_error_init (&tmp_error);
sl@0
  1257
      if (!update_directory (activation, s_dir, &tmp_error))
sl@0
  1258
        {
sl@0
  1259
          if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
sl@0
  1260
            {
sl@0
  1261
              dbus_move_error (&tmp_error, error);
sl@0
  1262
              return FALSE;
sl@0
  1263
            }
sl@0
  1264
sl@0
  1265
          dbus_error_free (&tmp_error);
sl@0
  1266
          continue;
sl@0
  1267
        }
sl@0
  1268
    }
sl@0
  1269
  
sl@0
  1270
  return TRUE;
sl@0
  1271
}
sl@0
  1272
sl@0
  1273
static BusActivationEntry *
sl@0
  1274
activation_find_entry (BusActivation *activation, 
sl@0
  1275
                       const char    *service_name,
sl@0
  1276
                       DBusError     *error)
sl@0
  1277
{
sl@0
  1278
  BusActivationEntry *entry;
sl@0
  1279
  
sl@0
  1280
  entry = _dbus_hash_table_lookup_string (activation->entries, service_name);
sl@0
  1281
  if (!entry)
sl@0
  1282
    { 
sl@0
  1283
      if (!update_service_cache (activation, error)) 
sl@0
  1284
        return NULL;
sl@0
  1285
sl@0
  1286
      entry = _dbus_hash_table_lookup_string (activation->entries,
sl@0
  1287
                                              service_name);
sl@0
  1288
    }
sl@0
  1289
  else 
sl@0
  1290
    {
sl@0
  1291
      BusActivationEntry *updated_entry;
sl@0
  1292
sl@0
  1293
      if (!check_service_file (activation, entry, &updated_entry, error)) 
sl@0
  1294
        return NULL;
sl@0
  1295
sl@0
  1296
      entry = updated_entry;
sl@0
  1297
    }
sl@0
  1298
sl@0
  1299
  if (!entry) 
sl@0
  1300
    {
sl@0
  1301
      dbus_set_error (error, DBUS_ERROR_SERVICE_UNKNOWN,
sl@0
  1302
                      "The name %s was not provided by any .service files",
sl@0
  1303
                      service_name);
sl@0
  1304
      return NULL;
sl@0
  1305
    }
sl@0
  1306
sl@0
  1307
  return entry;
sl@0
  1308
}
sl@0
  1309
sl@0
  1310
dbus_bool_t
sl@0
  1311
bus_activation_activate_service (BusActivation  *activation,
sl@0
  1312
                                 DBusConnection *connection,
sl@0
  1313
                                 BusTransaction *transaction,
sl@0
  1314
                                 dbus_bool_t     auto_activation,
sl@0
  1315
                                 DBusMessage    *activation_message,
sl@0
  1316
                                 const char     *service_name,
sl@0
  1317
                                 DBusError      *error)
sl@0
  1318
{
sl@0
  1319
  BusActivationEntry *entry;
sl@0
  1320
  BusPendingActivation *pending_activation;
sl@0
  1321
  BusPendingActivationEntry *pending_activation_entry;
sl@0
  1322
  DBusMessage *message;
sl@0
  1323
  DBusString service_str;
sl@0
  1324
  char **argv;
sl@0
  1325
  int argc;
sl@0
  1326
  dbus_bool_t retval;
sl@0
  1327
  DBusHashIter iter;
sl@0
  1328
  dbus_bool_t activated;
sl@0
  1329
  
sl@0
  1330
  activated = TRUE;
sl@0
  1331
sl@0
  1332
  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
sl@0
  1333
sl@0
  1334
  if (activation->n_pending_activations >=
sl@0
  1335
      bus_context_get_max_pending_activations (activation->context))
sl@0
  1336
    {
sl@0
  1337
      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
sl@0
  1338
                      "The maximum number of pending activations has been reached, activation of %s failed",
sl@0
  1339
                      service_name);
sl@0
  1340
      return FALSE;
sl@0
  1341
    }
sl@0
  1342
sl@0
  1343
  entry = activation_find_entry (activation, service_name, error);
sl@0
  1344
  if (!entry) 
sl@0
  1345
    return FALSE;
sl@0
  1346
sl@0
  1347
  /* Bypass the registry lookup if we're auto-activating, bus_dispatch would not
sl@0
  1348
   * call us if the service is already active.
sl@0
  1349
   */
sl@0
  1350
  if (!auto_activation)
sl@0
  1351
    {
sl@0
  1352
      /* Check if the service is active */
sl@0
  1353
      _dbus_string_init_const (&service_str, service_name);
sl@0
  1354
      if (bus_registry_lookup (bus_context_get_registry (activation->context), &service_str) != NULL)
sl@0
  1355
        {
sl@0
  1356
          dbus_uint32_t result;
sl@0
  1357
          
sl@0
  1358
          _dbus_verbose ("Service \"%s\" is already active\n", service_name);
sl@0
  1359
      
sl@0
  1360
          message = dbus_message_new_method_return (activation_message);
sl@0
  1361
sl@0
  1362
          if (!message)
sl@0
  1363
            {
sl@0
  1364
              _dbus_verbose ("No memory to create reply to activate message\n");
sl@0
  1365
              BUS_SET_OOM (error);
sl@0
  1366
              return FALSE;
sl@0
  1367
            }
sl@0
  1368
sl@0
  1369
          result = DBUS_START_REPLY_ALREADY_RUNNING;
sl@0
  1370
          
sl@0
  1371
          if (!dbus_message_append_args (message,
sl@0
  1372
                                         DBUS_TYPE_UINT32, &result,
sl@0
  1373
                                         DBUS_TYPE_INVALID))
sl@0
  1374
            {
sl@0
  1375
              _dbus_verbose ("No memory to set args of reply to activate message\n");
sl@0
  1376
              BUS_SET_OOM (error);
sl@0
  1377
              dbus_message_unref (message);
sl@0
  1378
              return FALSE;
sl@0
  1379
            }
sl@0
  1380
sl@0
  1381
          retval = bus_transaction_send_from_driver (transaction, connection, message);
sl@0
  1382
          dbus_message_unref (message);
sl@0
  1383
          if (!retval)
sl@0
  1384
            {
sl@0
  1385
              _dbus_verbose ("Failed to send reply\n");
sl@0
  1386
              BUS_SET_OOM (error);
sl@0
  1387
            }
sl@0
  1388
sl@0
  1389
          return retval;
sl@0
  1390
        }
sl@0
  1391
    }
sl@0
  1392
  
sl@0
  1393
  pending_activation_entry = dbus_new0 (BusPendingActivationEntry, 1);
sl@0
  1394
  if (!pending_activation_entry)
sl@0
  1395
    {
sl@0
  1396
      _dbus_verbose ("Failed to create pending activation entry\n");
sl@0
  1397
      BUS_SET_OOM (error);
sl@0
  1398
      return FALSE;
sl@0
  1399
    }
sl@0
  1400
sl@0
  1401
  pending_activation_entry->auto_activation = auto_activation;
sl@0
  1402
sl@0
  1403
  pending_activation_entry->activation_message = activation_message;
sl@0
  1404
  dbus_message_ref (activation_message);
sl@0
  1405
  pending_activation_entry->connection = connection;
sl@0
  1406
  dbus_connection_ref (connection);
sl@0
  1407
  
sl@0
  1408
  /* Check if the service is being activated */
sl@0
  1409
  pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
sl@0
  1410
  if (pending_activation)
sl@0
  1411
    {
sl@0
  1412
      if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
sl@0
  1413
        {
sl@0
  1414
          _dbus_verbose ("Failed to append a new entry to pending activation\n");
sl@0
  1415
          
sl@0
  1416
          BUS_SET_OOM (error);
sl@0
  1417
          bus_pending_activation_entry_free (pending_activation_entry);
sl@0
  1418
          return FALSE;
sl@0
  1419
        }
sl@0
  1420
sl@0
  1421
      pending_activation->n_entries += 1;
sl@0
  1422
      pending_activation->activation->n_pending_activations += 1;
sl@0
  1423
    }
sl@0
  1424
  else
sl@0
  1425
    {
sl@0
  1426
      pending_activation = dbus_new0 (BusPendingActivation, 1);
sl@0
  1427
      if (!pending_activation)
sl@0
  1428
        {
sl@0
  1429
          _dbus_verbose ("Failed to create pending activation\n");
sl@0
  1430
          
sl@0
  1431
          BUS_SET_OOM (error);
sl@0
  1432
          bus_pending_activation_entry_free (pending_activation_entry);          
sl@0
  1433
          return FALSE;
sl@0
  1434
        }
sl@0
  1435
sl@0
  1436
      pending_activation->activation = activation;
sl@0
  1437
      pending_activation->refcount = 1;
sl@0
  1438
      
sl@0
  1439
      pending_activation->service_name = _dbus_strdup (service_name);
sl@0
  1440
      if (!pending_activation->service_name)
sl@0
  1441
        {
sl@0
  1442
          _dbus_verbose ("Failed to copy service name for pending activation\n");
sl@0
  1443
          
sl@0
  1444
          BUS_SET_OOM (error);
sl@0
  1445
          bus_pending_activation_unref (pending_activation);
sl@0
  1446
          bus_pending_activation_entry_free (pending_activation_entry);          
sl@0
  1447
          return FALSE;
sl@0
  1448
        }
sl@0
  1449
sl@0
  1450
      pending_activation->exec = _dbus_strdup (entry->exec);
sl@0
  1451
      if (!pending_activation->exec)
sl@0
  1452
        {
sl@0
  1453
          _dbus_verbose ("Failed to copy service exec for pending activation\n");
sl@0
  1454
          BUS_SET_OOM (error);
sl@0
  1455
          bus_pending_activation_unref (pending_activation);
sl@0
  1456
          bus_pending_activation_entry_free (pending_activation_entry);
sl@0
  1457
          return FALSE;
sl@0
  1458
        }
sl@0
  1459
sl@0
  1460
      pending_activation->timeout =
sl@0
  1461
        _dbus_timeout_new (bus_context_get_activation_timeout (activation->context),
sl@0
  1462
                           pending_activation_timed_out,
sl@0
  1463
                           pending_activation,
sl@0
  1464
                           NULL);
sl@0
  1465
      if (!pending_activation->timeout)
sl@0
  1466
        {
sl@0
  1467
          _dbus_verbose ("Failed to create timeout for pending activation\n");
sl@0
  1468
          
sl@0
  1469
          BUS_SET_OOM (error);
sl@0
  1470
          bus_pending_activation_unref (pending_activation);
sl@0
  1471
          bus_pending_activation_entry_free (pending_activation_entry);
sl@0
  1472
          return FALSE;
sl@0
  1473
        }
sl@0
  1474
sl@0
  1475
      if (!_dbus_loop_add_timeout (bus_context_get_loop (activation->context),
sl@0
  1476
                                   pending_activation->timeout,
sl@0
  1477
                                   handle_timeout_callback,
sl@0
  1478
                                   pending_activation,
sl@0
  1479
                                   NULL))
sl@0
  1480
        {
sl@0
  1481
          _dbus_verbose ("Failed to add timeout for pending activation\n");
sl@0
  1482
          
sl@0
  1483
          BUS_SET_OOM (error);
sl@0
  1484
          bus_pending_activation_unref (pending_activation);
sl@0
  1485
          bus_pending_activation_entry_free (pending_activation_entry);          
sl@0
  1486
          return FALSE;
sl@0
  1487
        }
sl@0
  1488
sl@0
  1489
      pending_activation->timeout_added = TRUE;
sl@0
  1490
      
sl@0
  1491
      if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
sl@0
  1492
        {
sl@0
  1493
          _dbus_verbose ("Failed to add entry to just-created pending activation\n");
sl@0
  1494
          
sl@0
  1495
          BUS_SET_OOM (error);
sl@0
  1496
          bus_pending_activation_unref (pending_activation);
sl@0
  1497
          bus_pending_activation_entry_free (pending_activation_entry);          
sl@0
  1498
          return FALSE;
sl@0
  1499
        }
sl@0
  1500
sl@0
  1501
      pending_activation->n_entries += 1;
sl@0
  1502
      pending_activation->activation->n_pending_activations += 1;
sl@0
  1503
    
sl@0
  1504
      activated = FALSE;
sl@0
  1505
      _dbus_hash_iter_init (activation->pending_activations, &iter);
sl@0
  1506
      while (_dbus_hash_iter_next (&iter))
sl@0
  1507
        {
sl@0
  1508
          BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
sl@0
  1509
          
sl@0
  1510
          if (strcmp (p->exec, entry->exec) == 0) 
sl@0
  1511
            {
sl@0
  1512
              activated = TRUE;
sl@0
  1513
              break;
sl@0
  1514
            }
sl@0
  1515
        }
sl@0
  1516
     
sl@0
  1517
      if (!_dbus_hash_table_insert_string (activation->pending_activations,
sl@0
  1518
                                           pending_activation->service_name,
sl@0
  1519
                                           pending_activation))
sl@0
  1520
        {
sl@0
  1521
          _dbus_verbose ("Failed to put pending activation in hash table\n");
sl@0
  1522
          
sl@0
  1523
          BUS_SET_OOM (error);
sl@0
  1524
          bus_pending_activation_unref (pending_activation);
sl@0
  1525
          return FALSE;
sl@0
  1526
        }
sl@0
  1527
    }
sl@0
  1528
  
sl@0
  1529
  if (!add_cancel_pending_to_transaction (transaction, pending_activation))
sl@0
  1530
    {
sl@0
  1531
      _dbus_verbose ("Failed to add pending activation cancel hook to transaction\n");
sl@0
  1532
      BUS_SET_OOM (error);
sl@0
  1533
      _dbus_hash_table_remove_string (activation->pending_activations,
sl@0
  1534
                                      pending_activation->service_name);
sl@0
  1535
sl@0
  1536
      return FALSE;
sl@0
  1537
    }
sl@0
  1538
  
sl@0
  1539
  if (activated)
sl@0
  1540
    return TRUE;
sl@0
  1541
  #ifndef __SYMBIAN32__
sl@0
  1542
sl@0
  1543
  /* Now try to spawn the process */
sl@0
  1544
  if (!_dbus_shell_parse_argv (entry->exec, &argc, &argv, error))
sl@0
  1545
    {
sl@0
  1546
      _dbus_verbose ("Failed to parse command line: %s\n", entry->exec);
sl@0
  1547
      _DBUS_ASSERT_ERROR_IS_SET (error);
sl@0
  1548
      
sl@0
  1549
      _dbus_hash_table_remove_string (activation->pending_activations,
sl@0
  1550
                                      pending_activation->service_name);
sl@0
  1551
sl@0
  1552
      return FALSE;
sl@0
  1553
    }
sl@0
  1554
sl@0
  1555
  _dbus_verbose ("Spawning %s ...\n", argv[0]);
sl@0
  1556
  #else
sl@0
  1557
  
sl@0
  1558
   _dbus_verbose ("Spawning %s ...\n", entry->exec);
sl@0
  1559
   #endif
sl@0
  1560
   
sl@0
  1561
   #ifdef __SYMBIAN32__
sl@0
  1562
   if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter, &entry->exec,
sl@0
  1563
                                          child_setup, activation, 
sl@0
  1564
                                          error))
sl@0
  1565
   #else
sl@0
  1566
  if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter, argv,
sl@0
  1567
                                          child_setup, activation, 
sl@0
  1568
                                          error))
sl@0
  1569
    {
sl@0
  1570
      _dbus_verbose ("Failed to spawn child\n");
sl@0
  1571
      _DBUS_ASSERT_ERROR_IS_SET (error);
sl@0
  1572
      dbus_free_string_array (argv);
sl@0
  1573
sl@0
  1574
      return FALSE;
sl@0
  1575
    }
sl@0
  1576
sl@0
  1577
  dbus_free_string_array (argv);
sl@0
  1578
sl@0
  1579
  _dbus_assert (pending_activation->babysitter != NULL);
sl@0
  1580
  
sl@0
  1581
  if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
sl@0
  1582
                                             add_babysitter_watch,
sl@0
  1583
                                             remove_babysitter_watch,
sl@0
  1584
                                             NULL,
sl@0
  1585
                                             pending_activation,
sl@0
  1586
                                             NULL))
sl@0
  1587
    {
sl@0
  1588
      BUS_SET_OOM (error);
sl@0
  1589
      _dbus_verbose ("Failed to set babysitter watch functions\n");
sl@0
  1590
      return FALSE;
sl@0
  1591
    }
sl@0
  1592
   #endif  
sl@0
  1593
  return TRUE;
sl@0
  1594
}
sl@0
  1595
sl@0
  1596
dbus_bool_t
sl@0
  1597
bus_activation_list_services (BusActivation *activation,
sl@0
  1598
			      char        ***listp,
sl@0
  1599
			      int           *array_len)
sl@0
  1600
{
sl@0
  1601
  int i, j, len;
sl@0
  1602
  char **retval;
sl@0
  1603
  DBusHashIter iter;
sl@0
  1604
sl@0
  1605
  len = _dbus_hash_table_get_n_entries (activation->entries);
sl@0
  1606
  retval = dbus_new (char *, len + 1);
sl@0
  1607
sl@0
  1608
  if (retval == NULL)
sl@0
  1609
    return FALSE;
sl@0
  1610
sl@0
  1611
  _dbus_hash_iter_init (activation->entries, &iter);
sl@0
  1612
  i = 0;
sl@0
  1613
  while (_dbus_hash_iter_next (&iter))
sl@0
  1614
    {
sl@0
  1615
      BusActivationEntry *entry = _dbus_hash_iter_get_value (&iter);
sl@0
  1616
sl@0
  1617
      retval[i] = _dbus_strdup (entry->name);
sl@0
  1618
      if (retval[i] == NULL)
sl@0
  1619
	goto error;
sl@0
  1620
sl@0
  1621
      i++;
sl@0
  1622
    }
sl@0
  1623
sl@0
  1624
  retval[i] = NULL;
sl@0
  1625
sl@0
  1626
  if (array_len)
sl@0
  1627
    *array_len = len;
sl@0
  1628
sl@0
  1629
  *listp = retval;
sl@0
  1630
  return TRUE;
sl@0
  1631
sl@0
  1632
 error:
sl@0
  1633
  for (j = 0; j < i; j++)
sl@0
  1634
    dbus_free (retval[i]);
sl@0
  1635
  dbus_free (retval);
sl@0
  1636
sl@0
  1637
  return FALSE;
sl@0
  1638
}
sl@0
  1639
  
sl@0
  1640
sl@0
  1641
#ifdef DBUS_BUILD_TESTS
sl@0
  1642
sl@0
  1643
#include <stdio.h>
sl@0
  1644
sl@0
  1645
#define SERVICE_NAME_1 "MyService1"
sl@0
  1646
#define SERVICE_NAME_2 "MyService2"
sl@0
  1647
#define SERVICE_NAME_3 "MyService3"
sl@0
  1648
sl@0
  1649
#define SERVICE_FILE_1 "service-1.service"
sl@0
  1650
#define SERVICE_FILE_2 "service-2.service"
sl@0
  1651
#define SERVICE_FILE_3 "service-3.service"
sl@0
  1652
sl@0
  1653
static dbus_bool_t
sl@0
  1654
test_create_service_file (DBusString *dir,
sl@0
  1655
                          const char *filename, 
sl@0
  1656
                          const char *name, 
sl@0
  1657
                          const char *exec)
sl@0
  1658
{
sl@0
  1659
  DBusString  file_name, full_path;
sl@0
  1660
  FILE        *file;
sl@0
  1661
  dbus_bool_t  ret_val;
sl@0
  1662
sl@0
  1663
  ret_val = TRUE;
sl@0
  1664
  _dbus_string_init_const (&file_name, filename);
sl@0
  1665
sl@0
  1666
  if (!_dbus_string_init (&full_path))
sl@0
  1667
    return FALSE;
sl@0
  1668
sl@0
  1669
  if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
sl@0
  1670
      !_dbus_concat_dir_and_file (&full_path, &file_name))
sl@0
  1671
    {
sl@0
  1672
      ret_val = FALSE;
sl@0
  1673
      goto out;
sl@0
  1674
    }
sl@0
  1675
  
sl@0
  1676
  file = fopen (_dbus_string_get_const_data (&full_path), "w");
sl@0
  1677
  if (!file)
sl@0
  1678
    {
sl@0
  1679
      ret_val = FALSE;
sl@0
  1680
      goto out;
sl@0
  1681
    }
sl@0
  1682
sl@0
  1683
  fprintf (file, "[D-BUS Service]\nName=%s\nExec=%s\n", name, exec);
sl@0
  1684
  fclose (file);
sl@0
  1685
sl@0
  1686
out:
sl@0
  1687
  _dbus_string_free (&full_path);
sl@0
  1688
  return ret_val;
sl@0
  1689
}
sl@0
  1690
sl@0
  1691
static dbus_bool_t
sl@0
  1692
test_remove_service_file (DBusString *dir, const char *filename)
sl@0
  1693
{
sl@0
  1694
  DBusString  file_name, full_path;
sl@0
  1695
  dbus_bool_t ret_val;
sl@0
  1696
  
sl@0
  1697
  ret_val = TRUE;
sl@0
  1698
 
sl@0
  1699
  _dbus_string_init_const (&file_name, filename);
sl@0
  1700
sl@0
  1701
  if (!_dbus_string_init (&full_path))
sl@0
  1702
    return FALSE;
sl@0
  1703
sl@0
  1704
  if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
sl@0
  1705
      !_dbus_concat_dir_and_file (&full_path, &file_name))
sl@0
  1706
    {
sl@0
  1707
      ret_val = FALSE;
sl@0
  1708
      goto out;
sl@0
  1709
    }
sl@0
  1710
sl@0
  1711
  if (!_dbus_delete_file (&full_path, NULL))
sl@0
  1712
    {
sl@0
  1713
      ret_val = FALSE;
sl@0
  1714
      goto out;
sl@0
  1715
    }
sl@0
  1716
sl@0
  1717
out:
sl@0
  1718
  _dbus_string_free (&full_path);
sl@0
  1719
  return ret_val;
sl@0
  1720
}
sl@0
  1721
sl@0
  1722
static dbus_bool_t
sl@0
  1723
test_remove_directory (DBusString *dir)
sl@0
  1724
{
sl@0
  1725
  DBusDirIter *iter;
sl@0
  1726
  DBusString   filename, full_path;
sl@0
  1727
  dbus_bool_t  ret_val;
sl@0
  1728
  
sl@0
  1729
  ret_val = TRUE;
sl@0
  1730
  
sl@0
  1731
  if (!_dbus_string_init (&filename))
sl@0
  1732
    return FALSE;
sl@0
  1733
sl@0
  1734
  if (!_dbus_string_init (&full_path))
sl@0
  1735
    {
sl@0
  1736
      _dbus_string_free (&filename);
sl@0
  1737
      return FALSE;
sl@0
  1738
    }
sl@0
  1739
    
sl@0
  1740
  iter = _dbus_directory_open (dir, NULL);
sl@0
  1741
  if (iter == NULL)
sl@0
  1742
    {
sl@0
  1743
      ret_val = FALSE;
sl@0
  1744
      goto out;
sl@0
  1745
    }
sl@0
  1746
  
sl@0
  1747
  while (_dbus_directory_get_next_file (iter, &filename, NULL)) 
sl@0
  1748
    {
sl@0
  1749
      if (!test_remove_service_file (dir, _dbus_string_get_const_data (&filename)))
sl@0
  1750
        {
sl@0
  1751
          ret_val = FALSE;
sl@0
  1752
          goto out;
sl@0
  1753
        }
sl@0
  1754
    }
sl@0
  1755
  _dbus_directory_close (iter);
sl@0
  1756
sl@0
  1757
  if (!_dbus_delete_directory (dir, NULL))
sl@0
  1758
    {
sl@0
  1759
      ret_val = FALSE;
sl@0
  1760
      goto out;
sl@0
  1761
    }
sl@0
  1762
sl@0
  1763
out:
sl@0
  1764
  _dbus_string_free (&filename);
sl@0
  1765
  _dbus_string_free (&full_path);
sl@0
  1766
sl@0
  1767
  return ret_val;
sl@0
  1768
}
sl@0
  1769
sl@0
  1770
static dbus_bool_t
sl@0
  1771
init_service_reload_test (DBusString *dir)
sl@0
  1772
{
sl@0
  1773
  DBusStat stat_buf;
sl@0
  1774
 
sl@0
  1775
  if (!_dbus_stat (dir, &stat_buf, NULL))
sl@0
  1776
    {
sl@0
  1777
      if (!_dbus_create_directory (dir, NULL))
sl@0
  1778
        return FALSE;
sl@0
  1779
    }
sl@0
  1780
  else 
sl@0
  1781
    {
sl@0
  1782
      if (!test_remove_directory (dir))
sl@0
  1783
        return FALSE;
sl@0
  1784
sl@0
  1785
      if (!_dbus_create_directory (dir, NULL))
sl@0
  1786
        return FALSE;
sl@0
  1787
    }
sl@0
  1788
sl@0
  1789
  /* Create one initial file */
sl@0
  1790
  if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_1, "exec-1"))
sl@0
  1791
    return FALSE;
sl@0
  1792
sl@0
  1793
  return TRUE;
sl@0
  1794
}
sl@0
  1795
sl@0
  1796
static dbus_bool_t
sl@0
  1797
cleanup_service_reload_test (DBusString *dir)
sl@0
  1798
{
sl@0
  1799
  if (!test_remove_directory (dir))
sl@0
  1800
    return FALSE;
sl@0
  1801
sl@0
  1802
  return TRUE;
sl@0
  1803
}
sl@0
  1804
sl@0
  1805
typedef struct 
sl@0
  1806
{
sl@0
  1807
  BusActivation *activation;
sl@0
  1808
  const char    *service_name;
sl@0
  1809
  dbus_bool_t    expecting_find;
sl@0
  1810
} CheckData;
sl@0
  1811
sl@0
  1812
static dbus_bool_t
sl@0
  1813
check_func (void *data)
sl@0
  1814
{
sl@0
  1815
  CheckData          *d;
sl@0
  1816
  BusActivationEntry *entry;
sl@0
  1817
  DBusError           error;
sl@0
  1818
  dbus_bool_t         ret_val;
sl@0
  1819
  
sl@0
  1820
  ret_val = TRUE;
sl@0
  1821
  d = data;
sl@0
  1822
  
sl@0
  1823
  dbus_error_init (&error);
sl@0
  1824
 
sl@0
  1825
  entry = activation_find_entry (d->activation, d->service_name, &error);
sl@0
  1826
  if (entry == NULL)
sl@0
  1827
    {
sl@0
  1828
      if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 
sl@0
  1829
        {
sl@0
  1830
          ret_val = TRUE;
sl@0
  1831
        }
sl@0
  1832
      else
sl@0
  1833
        {
sl@0
  1834
          if (d->expecting_find)
sl@0
  1835
            ret_val = FALSE;
sl@0
  1836
        }
sl@0
  1837
      
sl@0
  1838
      dbus_error_free (&error);
sl@0
  1839
    }
sl@0
  1840
  else 
sl@0
  1841
    {
sl@0
  1842
      if (!d->expecting_find)
sl@0
  1843
        ret_val = FALSE;
sl@0
  1844
    }
sl@0
  1845
sl@0
  1846
  return ret_val;
sl@0
  1847
}
sl@0
  1848
sl@0
  1849
static dbus_bool_t
sl@0
  1850
do_test (const char *description, dbus_bool_t oom_test, CheckData *data)
sl@0
  1851
{
sl@0
  1852
  dbus_bool_t err;
sl@0
  1853
sl@0
  1854
  if (oom_test)
sl@0
  1855
    err = !_dbus_test_oom_handling (description, check_func, data);
sl@0
  1856
  else
sl@0
  1857
    err = !check_func (data);
sl@0
  1858
sl@0
  1859
  if (err) 
sl@0
  1860
    _dbus_assert_not_reached ("Test failed");
sl@0
  1861
sl@0
  1862
  return TRUE;
sl@0
  1863
}
sl@0
  1864
sl@0
  1865
static dbus_bool_t
sl@0
  1866
do_service_reload_test (DBusString *dir, dbus_bool_t oom_test)
sl@0
  1867
{
sl@0
  1868
  BusActivation *activation;
sl@0
  1869
  DBusString     address;
sl@0
  1870
  DBusList      *directories;
sl@0
  1871
  CheckData      d;
sl@0
  1872
  
sl@0
  1873
  directories = NULL;
sl@0
  1874
  _dbus_string_init_const (&address, "");
sl@0
  1875
 
sl@0
  1876
  if (!_dbus_list_append (&directories, _dbus_string_get_data (dir)))
sl@0
  1877
    return FALSE; 
sl@0
  1878
sl@0
  1879
  activation = bus_activation_new (NULL, &address, &directories, NULL);
sl@0
  1880
  if (!activation)
sl@0
  1881
    return FALSE;
sl@0
  1882
sl@0
  1883
  d.activation = activation;
sl@0
  1884
  
sl@0
  1885
  /* Check for existing service file */
sl@0
  1886
  d.expecting_find = TRUE;
sl@0
  1887
  d.service_name = SERVICE_NAME_1;
sl@0
  1888
sl@0
  1889
  if (!do_test ("Existing service file", oom_test, &d))
sl@0
  1890
    return FALSE;
sl@0
  1891
sl@0
  1892
  /* Check for non-existing service file */
sl@0
  1893
  d.expecting_find = FALSE;
sl@0
  1894
  d.service_name = SERVICE_NAME_3;
sl@0
  1895
sl@0
  1896
  if (!do_test ("Nonexisting service file", oom_test, &d))
sl@0
  1897
    return FALSE;
sl@0
  1898
sl@0
  1899
  /* Check for added service file */
sl@0
  1900
  if (!test_create_service_file (dir, SERVICE_FILE_2, SERVICE_NAME_2, "exec-2"))
sl@0
  1901
    return FALSE;
sl@0
  1902
sl@0
  1903
  d.expecting_find = TRUE;
sl@0
  1904
  d.service_name = SERVICE_NAME_2;
sl@0
  1905
  
sl@0
  1906
  if (!do_test ("Added service file", oom_test, &d))
sl@0
  1907
    return FALSE;
sl@0
  1908
  
sl@0
  1909
  /* Check for removed service file */
sl@0
  1910
  if (!test_remove_service_file (dir, SERVICE_FILE_2))
sl@0
  1911
    return FALSE;
sl@0
  1912
sl@0
  1913
  d.expecting_find = FALSE;
sl@0
  1914
  d.service_name = SERVICE_FILE_2;
sl@0
  1915
sl@0
  1916
  if (!do_test ("Removed service file", oom_test, &d))
sl@0
  1917
    return FALSE;
sl@0
  1918
  
sl@0
  1919
  /* Check for updated service file */
sl@0
  1920
  
sl@0
  1921
  _dbus_sleep_milliseconds (1000); /* Sleep a second to make sure the mtime is updated */
sl@0
  1922
sl@0
  1923
  if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_3, "exec-3"))
sl@0
  1924
    return FALSE;
sl@0
  1925
sl@0
  1926
  d.expecting_find = TRUE;
sl@0
  1927
  d.service_name = SERVICE_NAME_3;
sl@0
  1928
sl@0
  1929
  if (!do_test ("Updated service file, part 1", oom_test, &d))
sl@0
  1930
    return FALSE;
sl@0
  1931
sl@0
  1932
  d.expecting_find = FALSE;
sl@0
  1933
  d.service_name = SERVICE_NAME_1;
sl@0
  1934
sl@0
  1935
  if (!do_test ("Updated service file, part 2", oom_test, &d))
sl@0
  1936
    return FALSE; 
sl@0
  1937
sl@0
  1938
  bus_activation_unref (activation);
sl@0
  1939
  _dbus_list_clear (&directories);
sl@0
  1940
sl@0
  1941
  return TRUE;
sl@0
  1942
}
sl@0
  1943
sl@0
  1944
dbus_bool_t
sl@0
  1945
bus_activation_service_reload_test (const DBusString *test_data_dir)
sl@0
  1946
{
sl@0
  1947
  DBusString directory;
sl@0
  1948
  DBusStat stat_buf;	
sl@0
  1949
  if (!_dbus_string_init (&directory))
sl@0
  1950
    return FALSE;
sl@0
  1951
  
sl@0
  1952
  if (!_dbus_string_append (&directory, _dbus_get_tmpdir()))
sl@0
  1953
    return FALSE;
sl@0
  1954
  if (!_dbus_stat (&directory, &stat_buf, NULL))
sl@0
  1955
    {
sl@0
  1956
      if (!_dbus_create_directory (&directory, NULL))
sl@0
  1957
        return FALSE;
sl@0
  1958
    }
sl@0
  1959
  
sl@0
  1960
  if (!_dbus_string_append (&directory, "/dbus-reload-test-") ||
sl@0
  1961
      !_dbus_generate_random_ascii (&directory, 6))
sl@0
  1962
     {
sl@0
  1963
       return FALSE;
sl@0
  1964
     }
sl@0
  1965
   
sl@0
  1966
  /* Do normal tests */
sl@0
  1967
  if (!init_service_reload_test (&directory))
sl@0
  1968
    _dbus_assert_not_reached ("could not initiate service reload test");
sl@0
  1969
 
sl@0
  1970
  if (!do_service_reload_test (&directory, FALSE))
sl@0
  1971
    ; /* Do nothing? */
sl@0
  1972
  
sl@0
  1973
  /* Do OOM tests */
sl@0
  1974
  if (!init_service_reload_test (&directory))
sl@0
  1975
    _dbus_assert_not_reached ("could not initiate service reload test");
sl@0
  1976
 
sl@0
  1977
  if (!do_service_reload_test (&directory, TRUE))
sl@0
  1978
    ; /* Do nothing? */
sl@0
  1979
 
sl@0
  1980
  /* Cleanup test directory */
sl@0
  1981
  if (!cleanup_service_reload_test (&directory))
sl@0
  1982
    return FALSE;
sl@0
  1983
  
sl@0
  1984
  _dbus_string_free (&directory);
sl@0
  1985
  
sl@0
  1986
  return TRUE;
sl@0
  1987
}
sl@0
  1988
sl@0
  1989
#endif /* DBUS_BUILD_TESTS */