Main Page | Modules | Namespace List | Class Hierarchy | Data Structures | Directories | File List | Namespace Members | Data Fields | Related Pages

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 <unistd.h>
00032 #include <fcntl.h>
00033 #include <stdlib.h>
00034 
00195 const char _dbus_no_memory_message[] = "Not enough memory";
00196 
00202 void
00203 _dbus_warn (const char *format,
00204             ...)
00205 {
00206   /* FIXME not portable enough? */
00207   va_list args;
00208 
00209   va_start (args, format);
00210   vfprintf (stderr, format, args);
00211   va_end (args);
00212 }
00213 
00214 #ifdef DBUS_ENABLE_VERBOSE_MODE
00215 
00216 static dbus_bool_t verbose_initted = FALSE;
00217 
00218 #define PTHREAD_IN_VERBOSE 0
00219 #if PTHREAD_IN_VERBOSE
00220 #include <pthread.h>
00221 #endif
00222 
00231 void
00232 _dbus_verbose_real (const char *format,
00233                     ...)
00234 {
00235   va_list args;
00236   static dbus_bool_t verbose = TRUE;
00237   static dbus_bool_t need_pid = TRUE;
00238   int len;
00239   
00240   /* things are written a bit oddly here so that
00241    * in the non-verbose case we just have the one
00242    * conditional and return immediately.
00243    */
00244   if (!verbose)
00245     return;
00246   
00247   if (!verbose_initted)
00248     {
00249       verbose = _dbus_getenv ("DBUS_VERBOSE") != NULL;
00250       verbose_initted = TRUE;
00251       if (!verbose)
00252         return;
00253     }
00254 
00255   /* Print out pid before the line */
00256   if (need_pid)
00257     {
00258 #if PTHREAD_IN_VERBOSE
00259       fprintf (stderr, "%lu: 0x%lx: ", _dbus_getpid (), pthread_self ());
00260 #else
00261       fprintf (stderr, "%lu: ", _dbus_getpid ());
00262 #endif
00263     }
00264       
00265 
00266   /* Only print pid again if the next line is a new line */
00267   len = strlen (format);
00268   if (format[len-1] == '\n')
00269     need_pid = TRUE;
00270   else
00271     need_pid = FALSE;
00272   
00273   va_start (args, format);
00274   vfprintf (stderr, format, args);
00275   va_end (args);
00276 
00277   fflush (stderr);
00278 }
00279 
00286 void
00287 _dbus_verbose_reset_real (void)
00288 {
00289   verbose_initted = FALSE;
00290 }
00291 
00292 #endif /* DBUS_ENABLE_VERBOSE_MODE */
00293 
00302 char*
00303 _dbus_strdup (const char *str)
00304 {
00305   size_t len;
00306   char *copy;
00307   
00308   if (str == NULL)
00309     return NULL;
00310   
00311   len = strlen (str);
00312 
00313   copy = dbus_malloc (len + 1);
00314   if (copy == NULL)
00315     return NULL;
00316 
00317   memcpy (copy, str, len + 1);
00318   
00319   return copy;
00320 }
00321 
00330 void*
00331 _dbus_memdup (const void  *mem,
00332               size_t       n_bytes)
00333 {
00334   void *copy;
00335 
00336   copy = dbus_malloc (n_bytes);
00337   if (copy == NULL)
00338     return NULL;
00339 
00340   memcpy (copy, mem, n_bytes);
00341   
00342   return copy;
00343 }
00344 
00353 char**
00354 _dbus_dup_string_array (const char **array)
00355 {
00356   int len;
00357   int i;
00358   char **copy;
00359   
00360   if (array == NULL)
00361     return NULL;
00362 
00363   for (len = 0; array[len] != NULL; ++len)
00364     ;
00365 
00366   copy = dbus_new0 (char*, len + 1);
00367   if (copy == NULL)
00368     return NULL;
00369 
00370   i = 0;
00371   while (i < len)
00372     {
00373       copy[i] = _dbus_strdup (array[i]);
00374       if (copy[i] == NULL)
00375         {
00376           dbus_free_string_array (copy);
00377           return NULL;
00378         }
00379 
00380       ++i;
00381     }
00382 
00383   return copy;
00384 }
00385 
00393 dbus_bool_t
00394 _dbus_string_array_contains (const char **array,
00395                              const char  *str)
00396 {
00397   int i;
00398 
00399   i = 0;
00400   while (array[i] != NULL)
00401     {
00402       if (strcmp (array[i], str) == 0)
00403         return TRUE;
00404       ++i;
00405     }
00406 
00407   return FALSE;
00408 }
00409 
00410 #ifdef DBUS_BUILD_TESTS
00411 
00417 const char *
00418 _dbus_header_field_to_string (int header_field)
00419 {
00420   switch (header_field)
00421     {
00422     case DBUS_HEADER_FIELD_INVALID:
00423       return "invalid";
00424     case DBUS_HEADER_FIELD_PATH:
00425       return "path";
00426     case DBUS_HEADER_FIELD_INTERFACE:
00427       return "interface";
00428     case DBUS_HEADER_FIELD_MEMBER:
00429       return "member";
00430     case DBUS_HEADER_FIELD_ERROR_NAME:
00431       return "error-name";
00432     case DBUS_HEADER_FIELD_REPLY_SERIAL:
00433       return "reply-serial";
00434     case DBUS_HEADER_FIELD_DESTINATION:
00435       return "destination";
00436     case DBUS_HEADER_FIELD_SENDER:
00437       return "sender";
00438     case DBUS_HEADER_FIELD_SIGNATURE:
00439       return "signature";
00440     default:
00441       return "unknown";
00442     }
00443 }
00444 #endif /* DBUS_BUILD_TESTS */
00445 
00446 #ifndef DBUS_DISABLE_CHECKS
00447 
00448 const char _dbus_return_if_fail_warning_format[] =
00449 "%lu: arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
00450 "This is normally a bug in some application using the D-BUS library.\n";
00451 #endif
00452 
00453 #ifndef DBUS_DISABLE_ASSERT
00454 
00466 void
00467 _dbus_real_assert (dbus_bool_t  condition,
00468                    const char  *condition_text,
00469                    const char  *file,
00470                    int          line,
00471                    const char  *func)
00472 {
00473   if (_DBUS_UNLIKELY (!condition))
00474     {
00475       _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
00476                   _dbus_getpid (), condition_text, file, line, func);
00477       _dbus_abort ();
00478     }
00479 }
00480 
00491 void
00492 _dbus_real_assert_not_reached (const char *explanation,
00493                                const char *file,
00494                                int         line)
00495 {
00496   _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
00497               file, line, _dbus_getpid (), explanation);
00498   _dbus_abort ();
00499 }
00500 #endif /* DBUS_DISABLE_ASSERT */
00501   
00502 #ifdef DBUS_BUILD_TESTS
00503 static dbus_bool_t
00504 run_failing_each_malloc (int                    n_mallocs,
00505                          const char            *description,
00506                          DBusTestMemoryFunction func,
00507                          void                  *data)
00508 {
00509   n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */
00510   
00511   while (n_mallocs >= 0)
00512     {      
00513       _dbus_set_fail_alloc_counter (n_mallocs);
00514 
00515       _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n",
00516                      description, n_mallocs,
00517                      _dbus_get_fail_alloc_failures ());
00518 
00519       if (!(* func) (data))
00520         return FALSE;
00521       
00522       n_mallocs -= 1;
00523     }
00524 
00525   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00526 
00527   return TRUE;
00528 }                        
00529 
00543 dbus_bool_t
00544 _dbus_test_oom_handling (const char             *description,
00545                          DBusTestMemoryFunction  func,
00546                          void                   *data)
00547 {
00548   int approx_mallocs;
00549   const char *setting;
00550   int max_failures_to_try;
00551   int i;
00552 
00553   /* Run once to see about how many mallocs are involved */
00554   
00555   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00556 
00557   _dbus_verbose ("Running once to count mallocs\n");
00558   
00559   if (!(* func) (data))
00560     return FALSE;
00561   
00562   approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
00563 
00564   _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n",
00565                  description, approx_mallocs);
00566 
00567   setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES");
00568   if (setting != NULL)
00569     {
00570       DBusString str;
00571       long v;
00572       _dbus_string_init_const (&str, setting);
00573       v = 4;
00574       if (!_dbus_string_parse_int (&str, 0, &v, NULL))
00575         _dbus_warn ("couldn't parse '%s' as integer\n", setting);
00576       max_failures_to_try = v;
00577     }
00578   else
00579     {
00580       max_failures_to_try = 4;
00581     }
00582 
00583   i = setting ? max_failures_to_try - 1 : 1;
00584   while (i < max_failures_to_try)
00585     {
00586       _dbus_set_fail_alloc_failures (i);
00587       if (!run_failing_each_malloc (approx_mallocs, description, func, data))
00588         return FALSE;
00589       ++i;
00590     }
00591   
00592   _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n",
00593                  description);
00594 
00595   return TRUE;
00596 }
00597 #endif /* DBUS_BUILD_TESTS */
00598 

Generated on Tue Sep 13 01:28:06 2005 for D-BUS by  doxygen 1.4.4