dbus-internals.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-internals.c  random utility stuff (internal to D-Bus implementation)
00003  *
00004  * Copyright (C) 2002, 2003  Red Hat, Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 #include "dbus-internals.h"
00024 #include "dbus-protocol.h"
00025 #include "dbus-test.h"
00026 #include <stdio.h>
00027 #include <stdarg.h>
00028 #include <string.h>
00029 #include <sys/types.h>
00030 #include <errno.h>
00031 #include <fcntl.h>
00032 #include <stdlib.h>
00033 
00194 const char _dbus_no_memory_message[] = "Not enough memory";
00195 
00201 void
00202 _dbus_warn (const char *format,
00203             ...)
00204 {
00205   /* FIXME not portable enough? */
00206   va_list args;
00207 
00208   va_start (args, format);
00209   vfprintf (stderr, format, args);
00210   va_end (args);
00211 }
00212 
00213 #ifdef DBUS_ENABLE_VERBOSE_MODE
00214 
00215 static dbus_bool_t verbose_initted = FALSE;
00216 static dbus_bool_t verbose = TRUE;
00217 
00218 #define PTHREAD_IN_VERBOSE 0
00219 #if PTHREAD_IN_VERBOSE
00220 #include <pthread.h>
00221 #endif
00222 
00223 static inline void
00224 _dbus_verbose_init (void)
00225 {
00226   if (!verbose_initted)
00227     {
00228       const char *p = _dbus_getenv ("DBUS_VERBOSE"); 
00229       verbose = p != NULL && *p == '1';
00230       verbose_initted = TRUE;
00231     }
00232 }
00233 
00234 dbus_bool_t
00235 _dbus_is_verbose_real (void)
00236 {
00237   _dbus_verbose_init ();
00238   return verbose;
00239 }
00240 
00249 void
00250 _dbus_verbose_real (const char *format,
00251                     ...)
00252 {
00253   va_list args;
00254   static dbus_bool_t need_pid = TRUE;
00255   int len;
00256   
00257   /* things are written a bit oddly here so that
00258    * in the non-verbose case we just have the one
00259    * conditional and return immediately.
00260    */
00261   if (!_dbus_is_verbose_real())
00262     return;
00263 
00264   /* Print out pid before the line */
00265   if (need_pid)
00266     {
00267 #if PTHREAD_IN_VERBOSE
00268       fprintf (stderr, "%lu: 0x%lx: ", _dbus_getpid (), pthread_self ());
00269 #else
00270       fprintf (stderr, "%lu: ", _dbus_getpid ());
00271 #endif
00272     }
00273       
00274 
00275   /* Only print pid again if the next line is a new line */
00276   len = strlen (format);
00277   if (format[len-1] == '\n')
00278     need_pid = TRUE;
00279   else
00280     need_pid = FALSE;
00281   
00282   va_start (args, format);
00283   vfprintf (stderr, format, args);
00284   va_end (args);
00285 
00286   fflush (stderr);
00287 }
00288 
00295 void
00296 _dbus_verbose_reset_real (void)
00297 {
00298   verbose_initted = FALSE;
00299 }
00300 
00301 #endif /* DBUS_ENABLE_VERBOSE_MODE */
00302 
00311 char*
00312 _dbus_strdup (const char *str)
00313 {
00314   size_t len;
00315   char *copy;
00316   
00317   if (str == NULL)
00318     return NULL;
00319   
00320   len = strlen (str);
00321 
00322   copy = dbus_malloc (len + 1);
00323   if (copy == NULL)
00324     return NULL;
00325 
00326   memcpy (copy, str, len + 1);
00327   
00328   return copy;
00329 }
00330 
00339 void*
00340 _dbus_memdup (const void  *mem,
00341               size_t       n_bytes)
00342 {
00343   void *copy;
00344 
00345   copy = dbus_malloc (n_bytes);
00346   if (copy == NULL)
00347     return NULL;
00348 
00349   memcpy (copy, mem, n_bytes);
00350   
00351   return copy;
00352 }
00353 
00362 char**
00363 _dbus_dup_string_array (const char **array)
00364 {
00365   int len;
00366   int i;
00367   char **copy;
00368   
00369   if (array == NULL)
00370     return NULL;
00371 
00372   for (len = 0; array[len] != NULL; ++len)
00373     ;
00374 
00375   copy = dbus_new0 (char*, len + 1);
00376   if (copy == NULL)
00377     return NULL;
00378 
00379   i = 0;
00380   while (i < len)
00381     {
00382       copy[i] = _dbus_strdup (array[i]);
00383       if (copy[i] == NULL)
00384         {
00385           dbus_free_string_array (copy);
00386           return NULL;
00387         }
00388 
00389       ++i;
00390     }
00391 
00392   return copy;
00393 }
00394 
00402 dbus_bool_t
00403 _dbus_string_array_contains (const char **array,
00404                              const char  *str)
00405 {
00406   int i;
00407 
00408   i = 0;
00409   while (array[i] != NULL)
00410     {
00411       if (strcmp (array[i], str) == 0)
00412         return TRUE;
00413       ++i;
00414     }
00415 
00416   return FALSE;
00417 }
00418 
00419 #ifdef DBUS_BUILD_TESTS
00420 
00426 const char *
00427 _dbus_header_field_to_string (int header_field)
00428 {
00429   switch (header_field)
00430     {
00431     case DBUS_HEADER_FIELD_INVALID:
00432       return "invalid";
00433     case DBUS_HEADER_FIELD_PATH:
00434       return "path";
00435     case DBUS_HEADER_FIELD_INTERFACE:
00436       return "interface";
00437     case DBUS_HEADER_FIELD_MEMBER:
00438       return "member";
00439     case DBUS_HEADER_FIELD_ERROR_NAME:
00440       return "error-name";
00441     case DBUS_HEADER_FIELD_REPLY_SERIAL:
00442       return "reply-serial";
00443     case DBUS_HEADER_FIELD_DESTINATION:
00444       return "destination";
00445     case DBUS_HEADER_FIELD_SENDER:
00446       return "sender";
00447     case DBUS_HEADER_FIELD_SIGNATURE:
00448       return "signature";
00449     default:
00450       return "unknown";
00451     }
00452 }
00453 #endif /* DBUS_BUILD_TESTS */
00454 
00455 #ifndef DBUS_DISABLE_CHECKS
00456 
00457 const char _dbus_return_if_fail_warning_format[] =
00458 "%lu: arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
00459 "This is normally a bug in some application using the D-Bus library.\n";
00460 #endif
00461 
00462 #ifndef DBUS_DISABLE_ASSERT
00463 
00475 void
00476 _dbus_real_assert (dbus_bool_t  condition,
00477                    const char  *condition_text,
00478                    const char  *file,
00479                    int          line,
00480                    const char  *func)
00481 {
00482   if (_DBUS_UNLIKELY (!condition))
00483     {
00484       _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
00485                   _dbus_getpid (), condition_text, file, line, func);
00486       _dbus_abort ();
00487     }
00488 }
00489 
00500 void
00501 _dbus_real_assert_not_reached (const char *explanation,
00502                                const char *file,
00503                                int         line)
00504 {
00505   _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
00506               file, line, _dbus_getpid (), explanation);
00507   _dbus_abort ();
00508 }
00509 #endif /* DBUS_DISABLE_ASSERT */
00510   
00511 #ifdef DBUS_BUILD_TESTS
00512 static dbus_bool_t
00513 run_failing_each_malloc (int                    n_mallocs,
00514                          const char            *description,
00515                          DBusTestMemoryFunction func,
00516                          void                  *data)
00517 {
00518   n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */
00519   
00520   while (n_mallocs >= 0)
00521     {      
00522       _dbus_set_fail_alloc_counter (n_mallocs);
00523 
00524       _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n",
00525                      description, n_mallocs,
00526                      _dbus_get_fail_alloc_failures ());
00527 
00528       if (!(* func) (data))
00529         return FALSE;
00530       
00531       n_mallocs -= 1;
00532     }
00533 
00534   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00535 
00536   return TRUE;
00537 }                        
00538 
00552 dbus_bool_t
00553 _dbus_test_oom_handling (const char             *description,
00554                          DBusTestMemoryFunction  func,
00555                          void                   *data)
00556 {
00557   int approx_mallocs;
00558   const char *setting;
00559   int max_failures_to_try;
00560   int i;
00561 
00562   /* Run once to see about how many mallocs are involved */
00563   
00564   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00565 
00566   _dbus_verbose ("Running once to count mallocs\n");
00567   
00568   if (!(* func) (data))
00569     return FALSE;
00570   
00571   approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
00572 
00573   _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n",
00574                  description, approx_mallocs);
00575 
00576   setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES");
00577   if (setting != NULL)
00578     {
00579       DBusString str;
00580       long v;
00581       _dbus_string_init_const (&str, setting);
00582       v = 4;
00583       if (!_dbus_string_parse_int (&str, 0, &v, NULL))
00584         _dbus_warn ("couldn't parse '%s' as integer\n", setting);
00585       max_failures_to_try = v;
00586     }
00587   else
00588     {
00589       max_failures_to_try = 4;
00590     }
00591 
00592   i = setting ? max_failures_to_try - 1 : 1;
00593   while (i < max_failures_to_try)
00594     {
00595       _dbus_set_fail_alloc_failures (i);
00596       if (!run_failing_each_malloc (approx_mallocs, description, func, data))
00597         return FALSE;
00598       ++i;
00599     }
00600   
00601   _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n",
00602                  description);
00603 
00604   return TRUE;
00605 }
00606 #endif /* DBUS_BUILD_TESTS */
00607 

Generated on Fri Oct 20 11:46:23 2006 for D-Bus by  doxygen 1.4.7