2002-11-24 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   if (!verbose)
159     return;
160   
161   if (!initted)
162     {
163       verbose = getenv ("DBUS_VERBOSE") != NULL;
164       initted = TRUE;
165     }
166   
167   va_start (args, format);
168   vfprintf (stderr, format, args);
169   va_end (args);
170 }
171
172 /**
173  * A wrapper around strerror() because some platforms
174  * may be lame and not have strerror().
175  *
176  * @param error_number errno.
177  * @returns error description.
178  */
179 const char*
180 _dbus_strerror (int error_number)
181 {
182   return strerror (error_number);
183 }
184
185 /**
186  * Converts a UNIX errno into a DBusResultCode.
187  *
188  * @param error_number the errno.
189  * @returns the result code.
190  */
191 DBusResultCode
192 _dbus_result_from_errno (int error_number)
193 {
194   switch (error_number)
195     {
196     case 0:
197       return DBUS_RESULT_SUCCESS;
198       
199 #ifdef EPROTONOSUPPORT
200     case EPROTONOSUPPORT:
201       return DBUS_RESULT_NOT_SUPPORTED;
202 #endif
203 #ifdef EAFNOSUPPORT
204     case EAFNOSUPPORT:
205       return DBUS_RESULT_NOT_SUPPORTED;
206 #endif
207 #ifdef ENFILE
208     case ENFILE:
209       return DBUS_RESULT_LIMITS_EXCEEDED; /* kernel out of memory */
210 #endif
211 #ifdef EMFILE
212     case EMFILE:
213       return DBUS_RESULT_LIMITS_EXCEEDED;
214 #endif
215 #ifdef EACCES
216     case EACCES:
217       return DBUS_RESULT_ACCESS_DENIED;
218 #endif
219 #ifdef EPERM
220     case EPERM:
221       return DBUS_RESULT_ACCESS_DENIED;
222 #endif
223 #ifdef ENOBUFS
224     case ENOBUFS:
225       return DBUS_RESULT_NO_MEMORY;
226 #endif
227 #ifdef ENOMEM
228     case ENOMEM:
229       return DBUS_RESULT_NO_MEMORY;
230 #endif
231 #ifdef EINVAL
232     case EINVAL:
233       return DBUS_RESULT_FAILED;
234 #endif
235 #ifdef EBADF
236     case EBADF:
237       return DBUS_RESULT_FAILED;
238 #endif
239 #ifdef EFAULT
240     case EFAULT:
241       return DBUS_RESULT_FAILED;
242 #endif
243 #ifdef ENOTSOCK
244     case ENOTSOCK:
245       return DBUS_RESULT_FAILED;
246 #endif
247 #ifdef EISCONN
248     case EISCONN:
249       return DBUS_RESULT_FAILED;
250 #endif
251 #ifdef ECONNREFUSED
252     case ECONNREFUSED:
253       return DBUS_RESULT_NO_SERVER;
254 #endif
255 #ifdef ETIMEDOUT
256     case ETIMEDOUT:
257       return DBUS_RESULT_TIMEOUT;
258 #endif
259 #ifdef ENETUNREACH
260     case ENETUNREACH:
261       return DBUS_RESULT_NO_NETWORK;
262 #endif
263 #ifdef EADDRINUSE
264     case EADDRINUSE:
265       return DBUS_RESULT_ADDRESS_IN_USE;
266 #endif      
267     }
268
269   return DBUS_RESULT_FAILED;
270 }
271
272 /**
273  * Duplicates a string. Result must be freed with
274  * dbus_free(). Returns #NULL if memory allocation fails.
275  * If the string to be duplicated is #NULL, returns #NULL.
276  * 
277  * @param str string to duplicate.
278  * @returns newly-allocated copy.
279  */
280 char*
281 _dbus_strdup (const char *str)
282 {
283   int len;
284   char *copy;
285   
286   if (str == NULL)
287     return NULL;
288   
289   len = strlen (str);
290
291   copy = dbus_malloc (len + 1);
292   if (copy == NULL)
293     return NULL;
294
295   memcpy (copy, str, len + 1);
296   
297   return copy;
298 }
299
300 /**
301  * Sets a file descriptor to be nonblocking.
302  *
303  * @param fd the file descriptor.
304  * @param result address of result code.
305  * @returns #TRUE on success.
306  */
307 dbus_bool_t
308 _dbus_set_fd_nonblocking (int             fd,
309                           DBusResultCode *result)
310 {
311   int val;
312
313   val = fcntl (fd, F_GETFL, 0);
314   if (val < 0)
315     {
316       dbus_set_result (result, _dbus_result_from_errno (errno));
317       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
318                      _dbus_strerror (errno));
319       return FALSE;
320     }
321
322   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
323     {
324       dbus_set_result (result, _dbus_result_from_errno (errno));      
325       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
326                      fd, _dbus_strerror (errno));
327
328       return FALSE;
329     }
330
331   return TRUE;
332 }
333
334 /** @} */