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