* dbus/dbus-internal.c: Add dbus_is_verbose so we can have more
[platform/upstream/dbus.git] / dbus / dbus-internals.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-internals.c  random utility stuff (internal to D-Bus implementation)
3  *
4  * Copyright (C) 2002, 2003  Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23 #include "dbus-internals.h"
24 #include "dbus-protocol.h"
25 #include "dbus-test.h"
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <stdlib.h>
33
34 /**
35  * @defgroup DBusInternals D-Bus internal implementation details
36  * @brief Documentation useful when developing or debugging D-Bus itself.
37  * 
38  */
39
40 /**
41  * @defgroup DBusInternalsUtils Utilities and portability
42  * @ingroup DBusInternals
43  * @brief Utility functions (_dbus_assert(), _dbus_warn(), etc.)
44  * @{
45  */
46
47 /**
48  * @def _dbus_assert
49  *
50  * Aborts with an error message if the condition is false.
51  * 
52  * @param condition condition which must be true.
53  */
54
55 /**
56  * @def _dbus_assert_not_reached
57  *
58  * Aborts with an error message if called.
59  * The given explanation will be printed.
60  * 
61  * @param explanation explanation of what happened if the code was reached.
62  */
63
64 /**
65  * @def _DBUS_N_ELEMENTS
66  *
67  * Computes the number of elements in a fixed-size array using
68  * sizeof().
69  *
70  * @param array the array to count elements in.
71  */
72
73 /**
74  * @def _DBUS_POINTER_TO_INT
75  *
76  * Safely casts a void* to an integer; should only be used on void*
77  * that actually contain integers, for example one created with
78  * _DBUS_INT_TO_POINTER.  Only guaranteed to preserve 32 bits.
79  * (i.e. it's used to store 32-bit ints in pointers, but
80  * can't be used to store 64-bit pointers in ints.)
81  *
82  * @param pointer pointer to extract an integer from.
83  */
84 /**
85  * @def _DBUS_INT_TO_POINTER
86  *
87  * Safely stuffs an integer into a pointer, to be extracted later with
88  * _DBUS_POINTER_TO_INT. Only guaranteed to preserve 32 bits.
89  *
90  * @param integer the integer to stuff into a pointer.
91  */
92 /**
93  * @def _DBUS_ZERO
94  *
95  * Sets all bits in an object to zero.
96  *
97  * @param object the object to be zeroed.
98  */
99 /**
100  * @def _DBUS_INT16_MIN
101  *
102  * Minimum value of type "int16"
103  */
104 /**
105  * @def _DBUS_INT16_MAX
106  *
107  * Maximum value of type "int16"
108  */
109 /**
110  * @def _DBUS_UINT16_MAX
111  *
112  * Maximum value of type "uint16"
113  */
114
115 /**
116  * @def _DBUS_INT32_MIN
117  *
118  * Minimum value of type "int32"
119  */
120 /**
121  * @def _DBUS_INT32_MAX
122  *
123  * Maximum value of type "int32"
124  */
125 /**
126  * @def _DBUS_UINT32_MAX
127  *
128  * Maximum value of type "uint32"
129  */
130
131 /**
132  * @def _DBUS_INT_MIN
133  *
134  * Minimum value of type "int"
135  */
136 /**
137  * @def _DBUS_INT_MAX
138  *
139  * Maximum value of type "int"
140  */
141 /**
142  * @def _DBUS_UINT_MAX
143  *
144  * Maximum value of type "uint"
145  */
146
147 /**
148  * @typedef DBusForeachFunction
149  * 
150  * Used to iterate over each item in a collection, such as
151  * a DBusList.
152  */
153
154 /**
155  * @def _DBUS_LOCK_NAME
156  *
157  * Expands to name of a global lock variable.
158  */
159
160 /**
161  * @def _DBUS_DEFINE_GLOBAL_LOCK
162  *
163  * Defines a global lock variable with the given name.
164  * The lock must be added to the list to initialize
165  * in dbus_threads_init().
166  */
167
168 /**
169  * @def _DBUS_DECLARE_GLOBAL_LOCK
170  *
171  * Expands to declaration of a global lock defined
172  * with _DBUS_DEFINE_GLOBAL_LOCK.
173  * The lock must be added to the list to initialize
174  * in dbus_threads_init().
175  */
176
177 /**
178  * @def _DBUS_LOCK
179  *
180  * Locks a global lock
181  */
182
183 /**
184  * @def _DBUS_UNLOCK
185  *
186  * Unlocks a global lock
187  */
188
189 /**
190  * Fixed "out of memory" error message, just to avoid
191  * making up a different string every time and wasting
192  * space.
193  */
194 const char _dbus_no_memory_message[] = "Not enough memory";
195
196 /**
197  * Prints a warning message to stderr.
198  *
199  * @param format printf-style format string.
200  */
201 void
202 _dbus_warn (const char *format,
203             ...)
204 {
205   /* FIXME not portable enough? */
206   va_list args;
207
208   va_start (args, format);
209   vfprintf (stderr, format, args);
210   va_end (args);
211 }
212
213 #ifdef DBUS_ENABLE_VERBOSE_MODE
214
215 static dbus_bool_t verbose_initted = FALSE;
216 static dbus_bool_t verbose = TRUE;
217
218 #define PTHREAD_IN_VERBOSE 0
219 #if PTHREAD_IN_VERBOSE
220 #include <pthread.h>
221 #endif
222
223 static inline void
224 _dbus_verbose_init (void)
225 {
226   if (!verbose_initted)
227     {
228       const char *p = _dbus_getenv ("DBUS_VERBOSE"); 
229       verbose = p != NULL && *p == '1';
230       verbose_initted = TRUE;
231     }
232 }
233
234 dbus_bool_t
235 _dbus_is_verbose_real (void)
236 {
237   _dbus_verbose_init ();
238   return verbose;
239 }
240
241 /**
242  * Prints a warning message to stderr
243  * if the user has enabled verbose mode.
244  * This is the real function implementation,
245  * use _dbus_verbose() macro in code.
246  *
247  * @param format printf-style format string.
248  */
249 void
250 _dbus_verbose_real (const char *format,
251                     ...)
252 {
253   va_list args;
254   static dbus_bool_t need_pid = TRUE;
255   int len;
256   
257   /* things are written a bit oddly here so that
258    * in the non-verbose case we just have the one
259    * conditional and return immediately.
260    */
261   if (!_dbus_is_verbose_real())
262     return;
263
264   /* Print out pid before the line */
265   if (need_pid)
266     {
267 #if PTHREAD_IN_VERBOSE
268       fprintf (stderr, "%lu: 0x%lx: ", _dbus_getpid (), pthread_self ());
269 #else
270       fprintf (stderr, "%lu: ", _dbus_getpid ());
271 #endif
272     }
273       
274
275   /* Only print pid again if the next line is a new line */
276   len = strlen (format);
277   if (format[len-1] == '\n')
278     need_pid = TRUE;
279   else
280     need_pid = FALSE;
281   
282   va_start (args, format);
283   vfprintf (stderr, format, args);
284   va_end (args);
285
286   fflush (stderr);
287 }
288
289 /**
290  * Reinitializes the verbose logging code, used
291  * as a hack in dbus-spawn.c so that a child
292  * process re-reads its pid
293  *
294  */
295 void
296 _dbus_verbose_reset_real (void)
297 {
298   verbose_initted = FALSE;
299 }
300
301 #endif /* DBUS_ENABLE_VERBOSE_MODE */
302
303 /**
304  * Duplicates a string. Result must be freed with
305  * dbus_free(). Returns #NULL if memory allocation fails.
306  * If the string to be duplicated is #NULL, returns #NULL.
307  * 
308  * @param str string to duplicate.
309  * @returns newly-allocated copy.
310  */
311 char*
312 _dbus_strdup (const char *str)
313 {
314   size_t len;
315   char *copy;
316   
317   if (str == NULL)
318     return NULL;
319   
320   len = strlen (str);
321
322   copy = dbus_malloc (len + 1);
323   if (copy == NULL)
324     return NULL;
325
326   memcpy (copy, str, len + 1);
327   
328   return copy;
329 }
330
331 /**
332  * Duplicates a block of memory. Returns
333  * #NULL on failure.
334  *
335  * @param mem memory to copy
336  * @param n_bytes number of bytes to copy
337  * @returns the copy
338  */
339 void*
340 _dbus_memdup (const void  *mem,
341               size_t       n_bytes)
342 {
343   void *copy;
344
345   copy = dbus_malloc (n_bytes);
346   if (copy == NULL)
347     return NULL;
348
349   memcpy (copy, mem, n_bytes);
350   
351   return copy;
352 }
353
354 /**
355  * Duplicates a string array. Result may be freed with
356  * dbus_free_string_array(). Returns #NULL if memory allocation fails.
357  * If the array to be duplicated is #NULL, returns #NULL.
358  * 
359  * @param array array to duplicate.
360  * @returns newly-allocated copy.
361  */
362 char**
363 _dbus_dup_string_array (const char **array)
364 {
365   int len;
366   int i;
367   char **copy;
368   
369   if (array == NULL)
370     return NULL;
371
372   for (len = 0; array[len] != NULL; ++len)
373     ;
374
375   copy = dbus_new0 (char*, len + 1);
376   if (copy == NULL)
377     return NULL;
378
379   i = 0;
380   while (i < len)
381     {
382       copy[i] = _dbus_strdup (array[i]);
383       if (copy[i] == NULL)
384         {
385           dbus_free_string_array (copy);
386           return NULL;
387         }
388
389       ++i;
390     }
391
392   return copy;
393 }
394
395 /**
396  * Checks whether a string array contains the given string.
397  * 
398  * @param array array to search.
399  * @param str string to look for
400  * @returns #TRUE if array contains string
401  */
402 dbus_bool_t
403 _dbus_string_array_contains (const char **array,
404                              const char  *str)
405 {
406   int i;
407
408   i = 0;
409   while (array[i] != NULL)
410     {
411       if (strcmp (array[i], str) == 0)
412         return TRUE;
413       ++i;
414     }
415
416   return FALSE;
417 }
418
419 #ifdef DBUS_BUILD_TESTS
420 /**
421  * Returns a string describing the given name.
422  *
423  * @param header_field the field to describe
424  * @returns a constant string describing the field
425  */
426 const char *
427 _dbus_header_field_to_string (int header_field)
428 {
429   switch (header_field)
430     {
431     case DBUS_HEADER_FIELD_INVALID:
432       return "invalid";
433     case DBUS_HEADER_FIELD_PATH:
434       return "path";
435     case DBUS_HEADER_FIELD_INTERFACE:
436       return "interface";
437     case DBUS_HEADER_FIELD_MEMBER:
438       return "member";
439     case DBUS_HEADER_FIELD_ERROR_NAME:
440       return "error-name";
441     case DBUS_HEADER_FIELD_REPLY_SERIAL:
442       return "reply-serial";
443     case DBUS_HEADER_FIELD_DESTINATION:
444       return "destination";
445     case DBUS_HEADER_FIELD_SENDER:
446       return "sender";
447     case DBUS_HEADER_FIELD_SIGNATURE:
448       return "signature";
449     default:
450       return "unknown";
451     }
452 }
453 #endif /* DBUS_BUILD_TESTS */
454
455 #ifndef DBUS_DISABLE_CHECKS
456 /** String used in _dbus_return_if_fail macro */
457 const char _dbus_return_if_fail_warning_format[] =
458 "%lu: arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
459 "This is normally a bug in some application using the D-Bus library.\n";
460 #endif
461
462 #ifndef DBUS_DISABLE_ASSERT
463 /**
464  * Internals of _dbus_assert(); it's a function
465  * rather than a macro with the inline code so
466  * that the assertion failure blocks don't show up
467  * in test suite coverage, and to shrink code size.
468  *
469  * @param condition TRUE if assertion succeeded
470  * @param condition_text condition as a string
471  * @param file file the assertion is in
472  * @param line line the assertion is in
473  * @param func function the assertion is in
474  */
475 void
476 _dbus_real_assert (dbus_bool_t  condition,
477                    const char  *condition_text,
478                    const char  *file,
479                    int          line,
480                    const char  *func)
481 {
482   if (_DBUS_UNLIKELY (!condition))
483     {
484       _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
485                   _dbus_getpid (), condition_text, file, line, func);
486       _dbus_abort ();
487     }
488 }
489
490 /**
491  * Internals of _dbus_assert_not_reached(); it's a function
492  * rather than a macro with the inline code so
493  * that the assertion failure blocks don't show up
494  * in test suite coverage, and to shrink code size.
495  *
496  * @param explanation what was reached that shouldn't have been
497  * @param file file the assertion is in
498  * @param line line the assertion is in
499  */
500 void
501 _dbus_real_assert_not_reached (const char *explanation,
502                                const char *file,
503                                int         line)
504 {
505   _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
506               file, line, _dbus_getpid (), explanation);
507   _dbus_abort ();
508 }
509 #endif /* DBUS_DISABLE_ASSERT */
510   
511 #ifdef DBUS_BUILD_TESTS
512 static dbus_bool_t
513 run_failing_each_malloc (int                    n_mallocs,
514                          const char            *description,
515                          DBusTestMemoryFunction func,
516                          void                  *data)
517 {
518   n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */
519   
520   while (n_mallocs >= 0)
521     {      
522       _dbus_set_fail_alloc_counter (n_mallocs);
523
524       _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n",
525                      description, n_mallocs,
526                      _dbus_get_fail_alloc_failures ());
527
528       if (!(* func) (data))
529         return FALSE;
530       
531       n_mallocs -= 1;
532     }
533
534   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
535
536   return TRUE;
537 }                        
538
539 /**
540  * Tests how well the given function responds to out-of-memory
541  * situations. Calls the function repeatedly, failing a different
542  * call to malloc() each time. If the function ever returns #FALSE,
543  * the test fails. The function should return #TRUE whenever something
544  * valid (such as returning an error, or succeeding) occurs, and #FALSE
545  * if it gets confused in some way.
546  *
547  * @param description description of the test used in verbose output
548  * @param func function to call
549  * @param data data to pass to function
550  * @returns #TRUE if the function never returns FALSE
551  */
552 dbus_bool_t
553 _dbus_test_oom_handling (const char             *description,
554                          DBusTestMemoryFunction  func,
555                          void                   *data)
556 {
557   int approx_mallocs;
558   const char *setting;
559   int max_failures_to_try;
560   int i;
561
562   /* Run once to see about how many mallocs are involved */
563   
564   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
565
566   _dbus_verbose ("Running once to count mallocs\n");
567   
568   if (!(* func) (data))
569     return FALSE;
570   
571   approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
572
573   _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n",
574                  description, approx_mallocs);
575
576   setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES");
577   if (setting != NULL)
578     {
579       DBusString str;
580       long v;
581       _dbus_string_init_const (&str, setting);
582       v = 4;
583       if (!_dbus_string_parse_int (&str, 0, &v, NULL))
584         _dbus_warn ("couldn't parse '%s' as integer\n", setting);
585       max_failures_to_try = v;
586     }
587   else
588     {
589       max_failures_to_try = 4;
590     }
591
592   i = setting ? max_failures_to_try - 1 : 1;
593   while (i < max_failures_to_try)
594     {
595       _dbus_set_fail_alloc_failures (i);
596       if (!run_failing_each_malloc (approx_mallocs, description, func, data))
597         return FALSE;
598       ++i;
599     }
600   
601   _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n",
602                  description);
603
604   return TRUE;
605 }
606 #endif /* DBUS_BUILD_TESTS */
607
608 /** @} */