D-Bus 1.12.20
dbus-sysdeps.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-sysdeps.c Wrappers around system/libc features shared between UNIX and Windows (internal to D-Bus implementation)
3 *
4 * Copyright (C) 2002, 2003, 2006 Red Hat, Inc.
5 * Copyright (C) 2003 CodeFactory AB
6 *
7 * Licensed under the Academic Free License version 2.1
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25#include <config.h>
26#include "dbus-internals.h"
27#include "dbus-sysdeps.h"
28#include "dbus-threads.h"
29#include "dbus-protocol.h"
30#include "dbus-string.h"
31#include "dbus-list.h"
32#include "dbus-misc.h"
33
34/* NOTE: If you include any unix/windows-specific headers here, you are probably doing something
35 * wrong and should be putting some code in dbus-sysdeps-unix.c or dbus-sysdeps-win.c.
36 *
37 * These are the standard ANSI C headers...
38 */
39#if HAVE_LOCALE_H
40#include <locale.h>
41#endif
42#include <stdlib.h>
43#include <string.h>
44#include <stdio.h>
45
46#ifdef HAVE_ERRNO_H
47#include <errno.h>
48#endif
49
50#ifdef DBUS_WIN
51 #include <stdlib.h>
52#elif (defined __APPLE__)
53# include <crt_externs.h>
54# define environ (*_NSGetEnviron())
55#elif HAVE_DECL_ENVIRON && defined(HAVE_UNISTD_H)
56# include <unistd.h>
57#else
58extern char **environ;
59#endif
60
78void
80{
81 const char *s;
82
84
85 s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
86 if (s && *s)
87 {
88 /* don't use _dbus_warn here since it can _dbus_abort() */
89 fprintf (stderr, " Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
90 _dbus_sleep_milliseconds (1000 * 180);
91 }
92
93 abort ();
94 _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */
95}
96
116dbus_setenv (const char *varname,
117 const char *value)
118{
119 _dbus_assert (varname != NULL);
120
121 if (value == NULL)
122 {
123#ifdef HAVE_UNSETENV
124 unsetenv (varname);
125 return TRUE;
126#else
127 char *putenv_value;
128 size_t len;
129
130 len = strlen (varname);
131
132 /* Use system malloc to avoid memleaks that dbus_malloc
133 * will get upset about.
134 */
135
136 putenv_value = malloc (len + 2);
137 if (putenv_value == NULL)
138 return FALSE;
139
140 strcpy (putenv_value, varname);
141#if defined(DBUS_WIN)
142 strcat (putenv_value, "=");
143#endif
144
145 return (putenv (putenv_value) == 0);
146#endif
147 }
148 else
149 {
150#ifdef HAVE_SETENV
151 return (setenv (varname, value, TRUE) == 0);
152#else
153 char *putenv_value;
154 size_t len;
155 size_t varname_len;
156 size_t value_len;
157
158 varname_len = strlen (varname);
159 value_len = strlen (value);
160
161 len = varname_len + value_len + 1 /* '=' */ ;
162
163 /* Use system malloc to avoid memleaks that dbus_malloc
164 * will get upset about.
165 */
166
167 putenv_value = malloc (len + 1);
168 if (putenv_value == NULL)
169 return FALSE;
170
171 strcpy (putenv_value, varname);
172 strcpy (putenv_value + varname_len, "=");
173 strcpy (putenv_value + varname_len + 1, value);
174
175 return (putenv (putenv_value) == 0);
176#endif
177 }
178}
179
186const char*
187_dbus_getenv (const char *varname)
188{
189 /* Don't respect any environment variables if the current process is
190 * setuid. This is the equivalent of glibc's __secure_getenv().
191 */
192 if (_dbus_check_setuid ())
193 return NULL;
194 return getenv (varname);
195}
196
204{
205 dbus_bool_t rc = TRUE;
206
207#ifdef HAVE_CLEARENV
208 if (clearenv () != 0)
209 rc = FALSE;
210#else
211
212 if (environ != NULL)
213 environ[0] = NULL;
214#endif
215
216 return rc;
217}
218
229 const char *suffix,
230 DBusList **dir_list)
231{
232 int start;
233 int i;
234 int len;
235 char *cpath;
236 DBusString file_suffix;
237
238 start = 0;
239 i = 0;
240
241 _dbus_string_init_const (&file_suffix, suffix);
242
243 len = _dbus_string_get_length (dirs);
244
245 while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
246 {
247 DBusString path;
248
249 if (!_dbus_string_init (&path))
250 goto oom;
251
252 if (!_dbus_string_copy_len (dirs,
253 start,
254 i - start,
255 &path,
256 0))
257 {
258 _dbus_string_free (&path);
259 goto oom;
260 }
261
263
264 /* check for an empty path */
265 if (_dbus_string_get_length (&path) == 0)
266 goto next;
267
268 if (!_dbus_concat_dir_and_file (&path,
269 &file_suffix))
270 {
271 _dbus_string_free (&path);
272 goto oom;
273 }
274
275 if (!_dbus_string_copy_data(&path, &cpath))
276 {
277 _dbus_string_free (&path);
278 goto oom;
279 }
280
281 if (!_dbus_list_append (dir_list, cpath))
282 {
283 _dbus_string_free (&path);
284 dbus_free (cpath);
285 goto oom;
286 }
287
288 next:
289 _dbus_string_free (&path);
290 start = i + 1;
291 }
292
293 if (start != len)
294 {
295 DBusString path;
296
297 if (!_dbus_string_init (&path))
298 goto oom;
299
300 if (!_dbus_string_copy_len (dirs,
301 start,
302 len - start,
303 &path,
304 0))
305 {
306 _dbus_string_free (&path);
307 goto oom;
308 }
309
310 if (!_dbus_concat_dir_and_file (&path,
311 &file_suffix))
312 {
313 _dbus_string_free (&path);
314 goto oom;
315 }
316
317 if (!_dbus_string_copy_data(&path, &cpath))
318 {
319 _dbus_string_free (&path);
320 goto oom;
321 }
322
323 if (!_dbus_list_append (dir_list, cpath))
324 {
325 _dbus_string_free (&path);
326 dbus_free (cpath);
327 goto oom;
328 }
329
330 _dbus_string_free (&path);
331 }
332
333 return TRUE;
334
335 oom:
337 _dbus_list_clear (dir_list);
338 return FALSE;
339}
340
357 long value)
358{
359 /* this calculation is from comp.lang.c faq */
360#define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */
361 int orig_len;
362 int i;
363 char *buf;
364
365 orig_len = _dbus_string_get_length (str);
366
367 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
368 return FALSE;
369
370 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
371
372 snprintf (buf, MAX_LONG_LEN, "%ld", value);
373
374 i = 0;
375 while (*buf)
376 {
377 ++buf;
378 ++i;
379 }
380
381 _dbus_string_shorten (str, MAX_LONG_LEN - i);
382
383 return TRUE;
384}
385
395 unsigned long value)
396{
397 /* this is wrong, but definitely on the high side. */
398#define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
399 int orig_len;
400 int i;
401 char *buf;
402
403 orig_len = _dbus_string_get_length (str);
404
405 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
406 return FALSE;
407
408 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
409
410 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
411
412 i = 0;
413 while (*buf)
414 {
415 ++buf;
416 ++i;
417 }
418
419 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
420
421 return TRUE;
422}
423
438 int start,
439 long *value_return,
440 int *end_return)
441{
442 long v;
443 const char *p;
444 char *end;
445
446 p = _dbus_string_get_const_data_len (str, start,
447 _dbus_string_get_length (str) - start);
448
449 end = NULL;
451 v = strtol (p, &end, 0);
452 if (end == NULL || end == p || errno != 0)
453 return FALSE;
454
455 if (value_return)
456 *value_return = v;
457 if (end_return)
458 *end_return = start + (end - p);
459
460 return TRUE;
461}
462
477 int start,
478 unsigned long *value_return,
479 int *end_return)
480{
481 unsigned long v;
482 const char *p;
483 char *end;
484
485 p = _dbus_string_get_const_data_len (str, start,
486 _dbus_string_get_length (str) - start);
487
488 end = NULL;
490 v = strtoul (p, &end, 0);
491 if (end == NULL || end == p || errno != 0)
492 return FALSE;
493
494 if (value_return)
495 *value_return = v;
496 if (end_return)
497 *end_return = start + (end - p);
498
499 return TRUE;
500}
501 /* DBusString group */
503
519 int n_bytes,
520 DBusError *error)
521{
522 DBusString str;
523
524 if (!_dbus_string_init (&str))
525 {
526 _DBUS_SET_OOM (error);
527 return FALSE;
528 }
529
530 if (!_dbus_generate_random_bytes (&str, n_bytes, error))
531 {
532 _dbus_string_free (&str);
533 return FALSE;
534 }
535
536 _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
537
538 _dbus_string_free (&str);
539 return TRUE;
540}
541
553 int n_bytes,
554 DBusError *error)
555{
556 static const char letters[] =
557 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
558 int i;
559 int len;
560
561 if (!_dbus_generate_random_bytes (str, n_bytes, error))
562 return FALSE;
563
564 len = _dbus_string_get_length (str);
565 i = len - n_bytes;
566 while (i < len)
567 {
568 _dbus_string_set_byte (str, i,
569 letters[_dbus_string_get_byte (str, i) %
570 (sizeof (letters) - 1)]);
571
572 ++i;
573 }
574
575 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
576 n_bytes));
577
578 return TRUE;
579}
580
591const char*
592_dbus_error_from_errno (int error_number)
593{
594 switch (error_number)
595 {
596 case 0:
597 return DBUS_ERROR_FAILED;
598
599#ifdef EPROTONOSUPPORT
600 case EPROTONOSUPPORT:
602#elif defined(WSAEPROTONOSUPPORT)
603 case WSAEPROTONOSUPPORT:
605#endif
606#ifdef EAFNOSUPPORT
607 case EAFNOSUPPORT:
609#elif defined(WSAEAFNOSUPPORT)
610 case WSAEAFNOSUPPORT:
612#endif
613#ifdef ENFILE
614 case ENFILE:
615 return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
616#endif
617#ifdef EMFILE
618 case EMFILE:
620#endif
621#ifdef EACCES
622 case EACCES:
624#endif
625#ifdef EPERM
626 case EPERM:
628#endif
629#ifdef ENOBUFS
630 case ENOBUFS:
632#endif
633#ifdef ENOMEM
634 case ENOMEM:
636#endif
637#ifdef ECONNREFUSED
638 case ECONNREFUSED:
640#elif defined(WSAECONNREFUSED)
641 case WSAECONNREFUSED:
643#endif
644#ifdef ETIMEDOUT
645 case ETIMEDOUT:
646 return DBUS_ERROR_TIMEOUT;
647#elif defined(WSAETIMEDOUT)
648 case WSAETIMEDOUT:
649 return DBUS_ERROR_TIMEOUT;
650#endif
651#ifdef ENETUNREACH
652 case ENETUNREACH:
654#elif defined(WSAENETUNREACH)
655 case WSAENETUNREACH:
657#endif
658#ifdef EADDRINUSE
659 case EADDRINUSE:
661#elif defined(WSAEADDRINUSE)
662 case WSAEADDRINUSE:
664#endif
665#ifdef EEXIST
666 case EEXIST:
668#endif
669#ifdef ENOENT
670 case ENOENT:
672#endif
673 default:
674 return DBUS_ERROR_FAILED;
675 }
676}
677
683const char*
685{
686 return _dbus_error_from_errno (errno);
687}
688
692void
694{
695#ifdef DBUS_WINCE
696 SetLastError (0);
697#else
698 errno = 0;
699#endif
700}
701
708{
709 return e == ENOMEM;
710}
711
718{
719 return e == EINTR;
720}
721
728{
729 return e == EPIPE;
730}
731
738{
739#ifdef ETOOMANYREFS
740 return e == ETOOMANYREFS;
741#else
742 return FALSE;
743#endif
744}
745
750const char*
752{
753 return _dbus_strerror (errno);
754}
755
762void
763_dbus_log (DBusSystemLogSeverity severity,
764 const char *msg,
765 ...)
766{
767 va_list args;
768
769 va_start (args, msg);
770
771 _dbus_logv (severity, msg, args);
772
773 va_end (args);
774}
775
778/* tests in dbus-sysdeps-util.c */
dbus_bool_t _dbus_get_is_errno_epipe(int e)
See if errno is EPIPE.
Definition: dbus-sysdeps.c:727
dbus_bool_t _dbus_get_is_errno_etoomanyrefs(int e)
See if errno is ETOOMANYREFS.
Definition: dbus-sysdeps.c:737
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
void _dbus_log(DBusSystemLogSeverity severity, const char *msg,...)
Log a message to the system log file (e.g.
Definition: dbus-sysdeps.c:763
const char * _dbus_error_from_errno(int error_number)
Converts a UNIX errno, or Windows errno or WinSock error value into a DBusError name.
Definition: dbus-sysdeps.c:592
void(* DBusForeachFunction)(void *element, void *data)
Used to iterate over each item in a collection, such as a DBusList.
dbus_bool_t _dbus_generate_random_ascii(DBusString *str, int n_bytes, DBusError *error)
Generates the given number of random bytes, where the bytes are chosen from the alphanumeric ASCII su...
Definition: dbus-sysdeps.c:552
const char * _dbus_error_from_system_errno(void)
Converts the current system errno value into a DBusError name.
Definition: dbus-sysdeps.c:684
const char * _dbus_strerror_from_errno(void)
Get error message from errno.
Definition: dbus-sysdeps.c:751
dbus_bool_t _dbus_get_is_errno_eintr(int e)
See if errno is EINTR.
Definition: dbus-sysdeps.c:717
void _dbus_set_errno_to_zero(void)
Assign 0 to the global errno variable.
Definition: dbus-sysdeps.c:693
dbus_bool_t _dbus_get_is_errno_enomem(int e)
See if errno is ENOMEM.
Definition: dbus-sysdeps.c:707
dbus_bool_t _dbus_generate_random_bytes_buffer(char *buffer, int n_bytes, DBusError *error)
Fills n_bytes of the given buffer with random bytes.
Definition: dbus-sysdeps.c:518
void _dbus_list_foreach(DBusList **list, DBusForeachFunction function, void *data)
Calls the given function for each element in the list.
Definition: dbus-list.c:759
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition: dbus-list.c:542
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:270
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:702
dbus_bool_t dbus_setenv(const char *varname, const char *value)
Wrapper for setenv().
Definition: dbus-sysdeps.c:116
#define DBUS_ERROR_TIMEOUT
Certain timeout errors, possibly ETIMEDOUT on a socket.
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn't supported (like ENOSYS on UNIX).
#define DBUS_ERROR_ADDRESS_IN_USE
Can't bind a socket since its address is in use (i.e.
#define DBUS_ERROR_ACCESS_DENIED
Security restrictions don't allow doing what you're trying to do.
#define DBUS_ERROR_NO_SERVER
Unable to connect to server (probably caused by ECONNREFUSED on a socket).
#define DBUS_ERROR_FILE_EXISTS
Existing file and the operation you're using does not silently overwrite.
#define DBUS_ERROR_LIMITS_EXCEEDED
Some limited resource is exhausted.
#define DBUS_ERROR_NO_NETWORK
No network access (probably ENETUNREACH on a socket).
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
#define DBUS_ERROR_FILE_NOT_FOUND
Missing file.
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:190
dbus_bool_t _dbus_string_append_int(DBusString *str, long value)
Appends an integer to a DBusString.
Definition: dbus-sysdeps.c:356
dbus_bool_t _dbus_string_find(const DBusString *str, int start, const char *substr, int *found)
Finds the given substring in the string, returning TRUE and filling in the byte index where the subst...
Definition: dbus-string.c:1604
char * _dbus_string_get_data_len(DBusString *str, int start, int len)
Gets a sub-portion of the raw character buffer from the string.
Definition: dbus-string.c:490
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:259
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
Definition: dbus-string.c:780
dbus_bool_t _dbus_string_copy_data(const DBusString *str, char **data_return)
Copies the data from the string into a char*.
Definition: dbus-string.c:672
dbus_bool_t _dbus_string_parse_uint(const DBusString *str, int start, unsigned long *value_return, int *end_return)
Parses an unsigned integer contained in a DBusString.
Definition: dbus-sysdeps.c:476
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
Definition: dbus-string.c:760
dbus_bool_t _dbus_string_parse_int(const DBusString *str, int start, long *value_return, int *end_return)
Parses an integer contained in a DBusString.
Definition: dbus-sysdeps.c:437
dbus_bool_t _dbus_string_validate_ascii(const DBusString *str, int start, int len)
Checks that the given range of the string is valid ASCII with no nul bytes.
Definition: dbus-string.c:2450
dbus_bool_t _dbus_string_append_uint(DBusString *str, unsigned long value)
Appends an unsigned integer to a DBusString.
Definition: dbus-sysdeps.c:394
void _dbus_string_chop_white(DBusString *str)
Deletes leading and trailing whitespace.
Definition: dbus-string.c:1989
dbus_bool_t _dbus_string_copy_len(const DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_copy(), but can copy a segment from the middle of the source string.
Definition: dbus-string.c:1375
void _dbus_string_copy_to_buffer(const DBusString *str, char *buffer, int avail_len)
Copies the contents of a DBusString into a different buffer.
Definition: dbus-string.c:697
void _dbus_logv(DBusSystemLogSeverity severity, const char *msg, va_list args)
Log a message to the system log file (e.g.
unsigned long _dbus_pid_for_log(void)
The only reason this is separate from _dbus_getpid() is to allow it on Windows for logging but not fo...
dbus_bool_t _dbus_clearenv(void)
Wrapper for clearenv().
Definition: dbus-sysdeps.c:203
void _dbus_exit(int code)
Exit the process, returning the given value.
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:187
dbus_bool_t _dbus_check_setuid(void)
NOTE: If you modify this function, please also consider making the corresponding change in GLib.
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
dbus_bool_t _dbus_generate_random_bytes(DBusString *str, int n_bytes, DBusError *error)
Generates the given number of securely random bytes, using the best mechanism we can come up with.
void _dbus_abort(void)
Aborts the program with SIGABRT (dumping core).
Definition: dbus-sysdeps.c:79
dbus_bool_t _dbus_concat_dir_and_file(DBusString *dir, const DBusString *next_component)
Appends the given filename to the given directory.
dbus_bool_t _dbus_split_paths_and_append(DBusString *dirs, const char *suffix, DBusList **dir_list)
Split paths into a list of char strings.
Definition: dbus-sysdeps.c:228
void _dbus_print_backtrace(void)
On GNU libc systems, print a crude backtrace to stderr.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
Object representing an exception.
Definition: dbus-errors.h:49
A node in a linked list.
Definition: dbus-list.h:35