2003-01-08 Anders Carlsson <andersca@codefactory.se>
[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  Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 1.2
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 <stdio.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <sys/types.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32
33 /**
34  * @defgroup DBusInternals D-BUS internal implementation details
35  * @brief Documentation useful when developing or debugging D-BUS itself.
36  * 
37  */
38
39 /**
40  * @defgroup DBusInternalsUtils Utilities and portability
41  * @ingroup DBusInternals
42  * @brief Utility functions (_dbus_assert(), _dbus_warn(), etc.)
43  * @{
44  */
45
46 /**
47  * @def _dbus_assert
48  *
49  * Aborts with an error message if the condition is false.
50  * 
51  * @param condition condition which must be true.
52  */
53
54 /**
55  * @def _dbus_assert_not_reached
56  *
57  * Aborts with an error message if called.
58  * The given explanation will be printed.
59  * 
60  * @param explanation explanation of what happened if the code was reached.
61  */
62
63 /**
64  * @def _DBUS_N_ELEMENTS
65  *
66  * Computes the number of elements in a fixed-size array using
67  * sizeof().
68  *
69  * @param array the array to count elements in.
70  */
71
72 /**
73  * @def _DBUS_POINTER_TO_INT
74  *
75  * Safely casts a void* to an integer; should only be used on void*
76  * that actually contain integers, for example one created with
77  * _DBUS_INT_TO_POINTER.  Only guaranteed to preserve 32 bits.
78  * (i.e. it's used to store 32-bit ints in pointers, but
79  * can't be used to store 64-bit pointers in ints.)
80  *
81  * @param pointer pointer to extract an integer from.
82  */
83 /**
84  * @def _DBUS_INT_TO_POINTER
85  *
86  * Safely stuffs an integer into a pointer, to be extracted later with
87  * _DBUS_POINTER_TO_INT. Only guaranteed to preserve 32 bits.
88  *
89  * @param integer the integer to stuff into a pointer.
90  */
91 /**
92  * @def _DBUS_ZERO
93  *
94  * Sets all bits in an object to zero.
95  *
96  * @param object the object to be zeroed.
97  */
98 /**
99  * @def _DBUS_INT_MIN
100  *
101  * Minimum value of type "int"
102  */
103 /**
104  * @def _DBUS_INT_MAX
105  *
106  * Maximum value of type "int"
107  */
108 /**
109  * @def _DBUS_MAX_SUN_PATH_LENGTH
110  *
111  * Maximum length of the path to a UNIX domain socket,
112  * sockaddr_un::sun_path member. POSIX requires that all systems
113  * support at least 100 bytes here, including the nul termination.
114  * We use 99 for the max value to allow for the nul.
115  *
116  * We could probably also do sizeof (addr.sun_path)
117  * but this way we are the same on all platforms
118  * which is probably a good idea.
119  */
120
121 /**
122  * @typedef DBusForeachFunction
123  * 
124  * Used to iterate over each item in a collection, such as
125  * a DBusList.
126  */
127
128 /**
129  * Prints a warning message to stderr.
130  *
131  * @param format printf-style format string.
132  */
133 void
134 _dbus_warn (const char *format,
135             ...)
136 {
137   /* FIXME not portable enough? */
138   va_list args;
139
140   va_start (args, format);
141   vfprintf (stderr, format, args);
142   va_end (args);
143 }
144
145 /**
146  * Prints a warning message to stderr
147  * if the user has enabled verbose mode.
148  *
149  * @param format printf-style format string.
150  */
151 void
152 _dbus_verbose (const char *format,
153                ...)
154 {
155   va_list args;
156   static dbus_bool_t verbose = TRUE;
157   static dbus_bool_t initted = FALSE;
158
159   /* things are written a bit oddly here so that
160    * in the non-verbose case we just have the one
161    * conditional and return immediately.
162    */
163   if (!verbose)
164     return;
165   
166   if (!initted)
167     {
168       verbose = _dbus_getenv ("DBUS_VERBOSE") != NULL;
169       initted = TRUE;
170       if (!verbose)
171         return;
172     }
173   
174   va_start (args, format);
175   vfprintf (stderr, format, args);
176   va_end (args);
177 }
178
179 /**
180  * A wrapper around strerror() because some platforms
181  * may be lame and not have strerror().
182  *
183  * @param error_number errno.
184  * @returns error description.
185  */
186 const char*
187 _dbus_strerror (int error_number)
188 {
189   return strerror (error_number);
190 }
191
192 /**
193  * Converts a UNIX errno into a DBusResultCode.
194  *
195  * @param error_number the errno.
196  * @returns the result code.
197  */
198 DBusResultCode
199 _dbus_result_from_errno (int error_number)
200 {
201   switch (error_number)
202     {
203     case 0:
204       return DBUS_RESULT_SUCCESS;
205       
206 #ifdef EPROTONOSUPPORT
207     case EPROTONOSUPPORT:
208       return DBUS_RESULT_NOT_SUPPORTED;
209 #endif
210 #ifdef EAFNOSUPPORT
211     case EAFNOSUPPORT:
212       return DBUS_RESULT_NOT_SUPPORTED;
213 #endif
214 #ifdef ENFILE
215     case ENFILE:
216       return DBUS_RESULT_LIMITS_EXCEEDED; /* kernel out of memory */
217 #endif
218 #ifdef EMFILE
219     case EMFILE:
220       return DBUS_RESULT_LIMITS_EXCEEDED;
221 #endif
222 #ifdef EACCES
223     case EACCES:
224       return DBUS_RESULT_ACCESS_DENIED;
225 #endif
226 #ifdef EPERM
227     case EPERM:
228       return DBUS_RESULT_ACCESS_DENIED;
229 #endif
230 #ifdef ENOBUFS
231     case ENOBUFS:
232       return DBUS_RESULT_NO_MEMORY;
233 #endif
234 #ifdef ENOMEM
235     case ENOMEM:
236       return DBUS_RESULT_NO_MEMORY;
237 #endif
238 #ifdef EINVAL
239     case EINVAL:
240       return DBUS_RESULT_FAILED;
241 #endif
242 #ifdef EBADF
243     case EBADF:
244       return DBUS_RESULT_FAILED;
245 #endif
246 #ifdef EFAULT
247     case EFAULT:
248       return DBUS_RESULT_FAILED;
249 #endif
250 #ifdef ENOTSOCK
251     case ENOTSOCK:
252       return DBUS_RESULT_FAILED;
253 #endif
254 #ifdef EISCONN
255     case EISCONN:
256       return DBUS_RESULT_FAILED;
257 #endif
258 #ifdef ECONNREFUSED
259     case ECONNREFUSED:
260       return DBUS_RESULT_NO_SERVER;
261 #endif
262 #ifdef ETIMEDOUT
263     case ETIMEDOUT:
264       return DBUS_RESULT_TIMEOUT;
265 #endif
266 #ifdef ENETUNREACH
267     case ENETUNREACH:
268       return DBUS_RESULT_NO_NETWORK;
269 #endif
270 #ifdef EADDRINUSE
271     case EADDRINUSE:
272       return DBUS_RESULT_ADDRESS_IN_USE;
273 #endif      
274     }
275
276   return DBUS_RESULT_FAILED;
277 }
278
279 /**
280  * Duplicates a string. Result must be freed with
281  * dbus_free(). Returns #NULL if memory allocation fails.
282  * If the string to be duplicated is #NULL, returns #NULL.
283  * 
284  * @param str string to duplicate.
285  * @returns newly-allocated copy.
286  */
287 char*
288 _dbus_strdup (const char *str)
289 {
290   int len;
291   char *copy;
292   
293   if (str == NULL)
294     return NULL;
295   
296   len = strlen (str);
297
298   copy = dbus_malloc (len + 1);
299   if (copy == NULL)
300     return NULL;
301
302   memcpy (copy, str, len + 1);
303   
304   return copy;
305 }
306
307 /**
308  * Sets a file descriptor to be nonblocking.
309  *
310  * @param fd the file descriptor.
311  * @param result address of result code.
312  * @returns #TRUE on success.
313  */
314 dbus_bool_t
315 _dbus_set_fd_nonblocking (int             fd,
316                           DBusResultCode *result)
317 {
318   int val;
319
320   val = fcntl (fd, F_GETFL, 0);
321   if (val < 0)
322     {
323       dbus_set_result (result, _dbus_result_from_errno (errno));
324       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
325                      _dbus_strerror (errno));
326       return FALSE;
327     }
328
329   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
330     {
331       dbus_set_result (result, _dbus_result_from_errno (errno));      
332       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
333                      fd, _dbus_strerror (errno));
334
335       return FALSE;
336     }
337
338   return TRUE;
339 }
340
341 /**
342  * Returns a string describing the given type.
343  *
344  * @param type the type to describe
345  * @returns a constant string describing the type
346  */
347 const char *
348 _dbus_type_to_string (int type)
349 {
350   switch (type)
351     {
352     case DBUS_TYPE_INT32:
353       return "int32";
354     case DBUS_TYPE_UINT32:
355       return "uint32";
356     case DBUS_TYPE_DOUBLE:
357       return "double";
358     case DBUS_TYPE_STRING:
359       return "string";
360     default:
361       return "unknown";
362     }
363 }
364
365 /** @} */