D-Bus  1.7.4
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 
33 /* NOTE: If you include any unix/windows-specific headers here, you are probably doing something
34  * wrong and should be putting some code in dbus-sysdeps-unix.c or dbus-sysdeps-win.c.
35  *
36  * These are the standard ANSI C headers...
37  */
38 #if HAVE_LOCALE_H
39 #include <locale.h>
40 #endif
41 #include <stdlib.h>
42 #include <string.h>
43 #include <stdio.h>
44 
45 #ifdef HAVE_ERRNO_H
46 #include <errno.h>
47 #endif
48 
49 _DBUS_DEFINE_GLOBAL_LOCK (system_users);
50 
51 #ifdef DBUS_WIN
52  #include <stdlib.h>
53 #elif (defined __APPLE__)
54 # include <crt_externs.h>
55 # define environ (*_NSGetEnviron())
56 #else
57 extern char **environ;
58 #endif
59 
77 void
79 {
80  const char *s;
81 
83 
84  s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
85  if (s && *s)
86  {
87  /* don't use _dbus_warn here since it can _dbus_abort() */
88  fprintf (stderr, " Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
89  _dbus_sleep_milliseconds (1000 * 180);
90  }
91 
92  abort ();
93  _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */
94 }
95 
110 _dbus_setenv (const char *varname,
111  const char *value)
112 {
113  _dbus_assert (varname != NULL);
114 
115  if (value == NULL)
116  {
117 #ifdef HAVE_UNSETENV
118  unsetenv (varname);
119  return TRUE;
120 #else
121  char *putenv_value;
122  size_t len;
123 
124  len = strlen (varname);
125 
126  /* Use system malloc to avoid memleaks that dbus_malloc
127  * will get upset about.
128  */
129 
130  putenv_value = malloc (len + 2);
131  if (putenv_value == NULL)
132  return FALSE;
133 
134  strcpy (putenv_value, varname);
135 #if defined(DBUS_WIN)
136  strcat (putenv_value, "=");
137 #endif
138 
139  return (putenv (putenv_value) == 0);
140 #endif
141  }
142  else
143  {
144 #ifdef HAVE_SETENV
145  return (setenv (varname, value, TRUE) == 0);
146 #else
147  char *putenv_value;
148  size_t len;
149  size_t varname_len;
150  size_t value_len;
151 
152  varname_len = strlen (varname);
153  value_len = strlen (value);
154 
155  len = varname_len + value_len + 1 /* '=' */ ;
156 
157  /* Use system malloc to avoid memleaks that dbus_malloc
158  * will get upset about.
159  */
160 
161  putenv_value = malloc (len + 1);
162  if (putenv_value == NULL)
163  return FALSE;
164 
165  strcpy (putenv_value, varname);
166  strcpy (putenv_value + varname_len, "=");
167  strcpy (putenv_value + varname_len + 1, value);
168 
169  return (putenv (putenv_value) == 0);
170 #endif
171  }
172 }
173 
180 const char*
181 _dbus_getenv (const char *varname)
182 {
183  /* Don't respect any environment variables if the current process is
184  * setuid. This is the equivalent of glibc's __secure_getenv().
185  */
186  if (_dbus_check_setuid ())
187  return NULL;
188  return getenv (varname);
189 }
190 
198 {
199  dbus_bool_t rc = TRUE;
200 
201 #ifdef HAVE_CLEARENV
202  if (clearenv () != 0)
203  rc = FALSE;
204 #else
205 
206  if (environ != NULL)
207  environ[0] = NULL;
208 #endif
209 
210  return rc;
211 }
212 
223  const char *suffix,
224  DBusList **dir_list)
225 {
226  int start;
227  int i;
228  int len;
229  char *cpath;
230  DBusString file_suffix;
231 
232  start = 0;
233  i = 0;
234 
235  _dbus_string_init_const (&file_suffix, suffix);
236 
237  len = _dbus_string_get_length (dirs);
238 
239  while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
240  {
241  DBusString path;
242 
243  if (!_dbus_string_init (&path))
244  goto oom;
245 
246  if (!_dbus_string_copy_len (dirs,
247  start,
248  i - start,
249  &path,
250  0))
251  {
252  _dbus_string_free (&path);
253  goto oom;
254  }
255 
256  _dbus_string_chop_white (&path);
257 
258  /* check for an empty path */
259  if (_dbus_string_get_length (&path) == 0)
260  goto next;
261 
262  if (!_dbus_concat_dir_and_file (&path,
263  &file_suffix))
264  {
265  _dbus_string_free (&path);
266  goto oom;
267  }
268 
269  if (!_dbus_string_copy_data(&path, &cpath))
270  {
271  _dbus_string_free (&path);
272  goto oom;
273  }
274 
275  if (!_dbus_list_append (dir_list, cpath))
276  {
277  _dbus_string_free (&path);
278  dbus_free (cpath);
279  goto oom;
280  }
281 
282  next:
283  _dbus_string_free (&path);
284  start = i + 1;
285  }
286 
287  if (start != len)
288  {
289  DBusString path;
290 
291  if (!_dbus_string_init (&path))
292  goto oom;
293 
294  if (!_dbus_string_copy_len (dirs,
295  start,
296  len - start,
297  &path,
298  0))
299  {
300  _dbus_string_free (&path);
301  goto oom;
302  }
303 
304  if (!_dbus_concat_dir_and_file (&path,
305  &file_suffix))
306  {
307  _dbus_string_free (&path);
308  goto oom;
309  }
310 
311  if (!_dbus_string_copy_data(&path, &cpath))
312  {
313  _dbus_string_free (&path);
314  goto oom;
315  }
316 
317  if (!_dbus_list_append (dir_list, cpath))
318  {
319  _dbus_string_free (&path);
320  dbus_free (cpath);
321  goto oom;
322  }
323 
324  _dbus_string_free (&path);
325  }
326 
327  return TRUE;
328 
329  oom:
331  _dbus_list_clear (dir_list);
332  return FALSE;
333 }
334 
351  long value)
352 {
353  /* this calculation is from comp.lang.c faq */
354 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */
355  int orig_len;
356  int i;
357  char *buf;
358 
359  orig_len = _dbus_string_get_length (str);
360 
361  if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
362  return FALSE;
363 
364  buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
365 
366  snprintf (buf, MAX_LONG_LEN, "%ld", value);
367 
368  i = 0;
369  while (*buf)
370  {
371  ++buf;
372  ++i;
373  }
374 
375  _dbus_string_shorten (str, MAX_LONG_LEN - i);
376 
377  return TRUE;
378 }
379 
389  unsigned long value)
390 {
391  /* this is wrong, but definitely on the high side. */
392 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
393  int orig_len;
394  int i;
395  char *buf;
396 
397  orig_len = _dbus_string_get_length (str);
398 
399  if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
400  return FALSE;
401 
402  buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
403 
404  snprintf (buf, MAX_ULONG_LEN, "%lu", value);
405 
406  i = 0;
407  while (*buf)
408  {
409  ++buf;
410  ++i;
411  }
412 
413  _dbus_string_shorten (str, MAX_ULONG_LEN - i);
414 
415  return TRUE;
416 }
417 
432  int start,
433  long *value_return,
434  int *end_return)
435 {
436  long v;
437  const char *p;
438  char *end;
439 
440  p = _dbus_string_get_const_data_len (str, start,
441  _dbus_string_get_length (str) - start);
442 
443  end = NULL;
445  v = strtol (p, &end, 0);
446  if (end == NULL || end == p || errno != 0)
447  return FALSE;
448 
449  if (value_return)
450  *value_return = v;
451  if (end_return)
452  *end_return = start + (end - p);
453 
454  return TRUE;
455 }
456 
471  int start,
472  unsigned long *value_return,
473  int *end_return)
474 {
475  unsigned long v;
476  const char *p;
477  char *end;
478 
479  p = _dbus_string_get_const_data_len (str, start,
480  _dbus_string_get_length (str) - start);
481 
482  end = NULL;
484  v = strtoul (p, &end, 0);
485  if (end == NULL || end == p || errno != 0)
486  return FALSE;
487 
488  if (value_return)
489  *value_return = v;
490  if (end_return)
491  *end_return = start + (end - p);
492 
493  return TRUE;
494 }
495  /* DBusString group */
497 
503 void
505  int n_bytes)
506 {
507  long tv_usec;
508  int i;
509 
510  /* fall back to pseudorandom */
511  _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
512  n_bytes);
513 
514  _dbus_get_real_time (NULL, &tv_usec);
515  srand (tv_usec);
516 
517  i = 0;
518  while (i < n_bytes)
519  {
520  double r;
521  unsigned int b;
522 
523  r = rand ();
524  b = (r / (double) RAND_MAX) * 255.0;
525 
526  buffer[i] = b;
527 
528  ++i;
529  }
530 }
531 
538 void
540  int n_bytes)
541 {
542  DBusString str;
543 
544  if (!_dbus_string_init (&str))
545  {
547  return;
548  }
549 
550  if (!_dbus_generate_random_bytes (&str, n_bytes))
551  {
552  _dbus_string_free (&str);
554  return;
555  }
556 
557  _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
558 
559  _dbus_string_free (&str);
560 }
561 
572  int n_bytes)
573 {
574  static const char letters[] =
575  "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
576  int i;
577  int len;
578 
579  if (!_dbus_generate_random_bytes (str, n_bytes))
580  return FALSE;
581 
582  len = _dbus_string_get_length (str);
583  i = len - n_bytes;
584  while (i < len)
585  {
586  _dbus_string_set_byte (str, i,
587  letters[_dbus_string_get_byte (str, i) %
588  (sizeof (letters) - 1)]);
589 
590  ++i;
591  }
592 
593  _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
594  n_bytes));
595 
596  return TRUE;
597 }
598 
609 const char*
610 _dbus_error_from_errno (int error_number)
611 {
612  switch (error_number)
613  {
614  case 0:
615  return DBUS_ERROR_FAILED;
616 
617 #ifdef EPROTONOSUPPORT
618  case EPROTONOSUPPORT:
620 #elif defined(WSAEPROTONOSUPPORT)
621  case WSAEPROTONOSUPPORT:
623 #endif
624 #ifdef EAFNOSUPPORT
625  case EAFNOSUPPORT:
627 #elif defined(WSAEAFNOSUPPORT)
628  case WSAEAFNOSUPPORT:
630 #endif
631 #ifdef ENFILE
632  case ENFILE:
633  return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
634 #endif
635 #ifdef EMFILE
636  case EMFILE:
638 #endif
639 #ifdef EACCES
640  case EACCES:
642 #endif
643 #ifdef EPERM
644  case EPERM:
646 #endif
647 #ifdef ENOBUFS
648  case ENOBUFS:
649  return DBUS_ERROR_NO_MEMORY;
650 #endif
651 #ifdef ENOMEM
652  case ENOMEM:
653  return DBUS_ERROR_NO_MEMORY;
654 #endif
655 #ifdef ECONNREFUSED
656  case ECONNREFUSED:
657  return DBUS_ERROR_NO_SERVER;
658 #elif defined(WSAECONNREFUSED)
659  case WSAECONNREFUSED:
660  return DBUS_ERROR_NO_SERVER;
661 #endif
662 #ifdef ETIMEDOUT
663  case ETIMEDOUT:
664  return DBUS_ERROR_TIMEOUT;
665 #elif defined(WSAETIMEDOUT)
666  case WSAETIMEDOUT:
667  return DBUS_ERROR_TIMEOUT;
668 #endif
669 #ifdef ENETUNREACH
670  case ENETUNREACH:
671  return DBUS_ERROR_NO_NETWORK;
672 #elif defined(WSAENETUNREACH)
673  case WSAENETUNREACH:
674  return DBUS_ERROR_NO_NETWORK;
675 #endif
676 #ifdef EADDRINUSE
677  case EADDRINUSE:
679 #elif defined(WSAEADDRINUSE)
680  case WSAEADDRINUSE:
682 #endif
683 #ifdef EEXIST
684  case EEXIST:
685  return DBUS_ERROR_FILE_EXISTS;
686 #endif
687 #ifdef ENOENT
688  case ENOENT:
690 #endif
691  }
692 
693  return DBUS_ERROR_FAILED;
694 }
695 
701 const char*
703 {
704  return _dbus_error_from_errno (errno);
705 }
706 
710 void
712 {
713 #ifdef DBUS_WINCE
714  SetLastError (0);
715 #else
716  errno = 0;
717 #endif
718 }
719 
726 {
727  return errno != 0;
728 }
729 
736 {
737  return errno == ENOMEM;
738 }
739 
746 {
747  return errno == EINTR;
748 }
749 
756 {
757  return errno == EPIPE;
758 }
759 
764 const char*
766 {
767  return _dbus_strerror (errno);
768 }
769 
772 /* tests in dbus-sysdeps-util.c */
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:431
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:675
#define DBUS_ERROR_FILE_NOT_FOUND
Missing file.
#define DBUS_ERROR_FILE_EXISTS
Existing file and the operation you&#39;re using does not silently overwrite.
dbus_bool_t _dbus_string_append_uint(DBusString *str, unsigned long value)
Appends an unsigned integer to a DBusString.
Definition: dbus-sysdeps.c:388
#define NULL
A null pointer, defined appropriately for C or C++.
#define DBUS_ERROR_TIMEOUT
Certain timeout errors, possibly ETIMEDOUT on a socket.
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:738
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:701
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn&#39;t supported (like ENOSYS on UNIX).
dbus_bool_t _dbus_string_append_int(DBusString *str, long value)
Appends an integer to a DBusString.
Definition: dbus-sysdeps.c:350
void _dbus_string_chop_white(DBusString *str)
Deletes leading and trailing whitespace.
Definition: dbus-string.c:1986
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
dbus_bool_t _dbus_check_setuid(void)
NOTE: If you modify this function, please also consider making the corresponding change in GLib...
unsigned char _dbus_string_get_byte(const DBusString *str, int start)
Gets the byte at the given position.
Definition: dbus-string.c:540
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:468
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
Definition: dbus-string.c:758
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:1601
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:181
void _dbus_abort(void)
Aborts the program with SIGABRT (dumping core).
Definition: dbus-sysdeps.c:78
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:610
#define DBUS_ERROR_NO_SERVER
Unable to connect to server (probably caused by ECONNREFUSED on a socket).
void _dbus_get_real_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
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_generate_random_ascii(DBusString *str, int n_bytes)
Generates the given number of random bytes, where the bytes are chosen from the alphanumeric ASCII su...
Definition: dbus-sysdeps.c:571
void _dbus_generate_random_bytes_buffer(char *buffer, int n_bytes)
Fills n_bytes of the given buffer with random bytes.
Definition: dbus-sysdeps.c:539
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:650
dbus_bool_t _dbus_setenv(const char *varname, const char *value)
Wrapper for setenv().
Definition: dbus-sysdeps.c:110
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:190
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:259
void _dbus_list_foreach(DBusList **list, DBusForeachFunction function, void *data)
Calls the given function for each element in the list.
Definition: dbus-list.c:748
int _dbus_string_get_length(const DBusString *str)
Gets the length of a string (not including nul termination).
Definition: dbus-string.c:717
dbus_bool_t _dbus_get_is_errno_enomem(void)
See if errno is ENOMEM.
Definition: dbus-sysdeps.c:735
#define DBUS_ERROR_ADDRESS_IN_USE
Can&#39;t bind a socket since its address is in use (i.e.
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:242
#define TRUE
Expands to &quot;1&quot;.
#define DBUS_ERROR_FAILED
A generic error; &quot;something went wrong&quot; - see the error message for more.
#define _DBUS_DEFINE_GLOBAL_LOCK(name)
Defines a global lock variable with the given name.
dbus_bool_t _dbus_get_is_errno_nonzero(void)
See if errno is set.
Definition: dbus-sysdeps.c:725
void _dbus_string_set_byte(DBusString *str, int i, unsigned char byte)
Sets the value of the byte at the given position.
Definition: dbus-string.c:516
const char * _dbus_strerror_from_errno(void)
Get error message from errno.
Definition: dbus-sysdeps.c:765
const char * _dbus_error_from_system_errno(void)
Converts the current system errno value into a DBusError name.
Definition: dbus-sysdeps.c:702
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:197
void _dbus_generate_pseudorandom_bytes_buffer(char *buffer, int n_bytes)
Random numbers.
Definition: dbus-sysdeps.c:504
dbus_bool_t _dbus_get_is_errno_eintr(void)
See if errno is EINTR.
Definition: dbus-sysdeps.c:745
const char * _dbus_string_get_const_data_len(const DBusString *str, int start, int len)
const version of _dbus_string_get_data_len().
Definition: dbus-string.c:492
A node in a linked list.
Definition: dbus-list.h:34
void _dbus_exit(int code)
Exit the process, returning the given value.
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:222
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:470
#define DBUS_ERROR_ACCESS_DENIED
Security restrictions don&#39;t allow doing what you&#39;re trying to do.
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
void(* DBusForeachFunction)(void *element, void *data)
Used to iterate over each item in a collection, such as a DBusList.
#define FALSE
Expands to &quot;0&quot;.
void _dbus_print_backtrace(void)
On GNU libc systems, print a crude backtrace to stderr.
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:1372
#define DBUS_ERROR_NO_NETWORK
No network access (probably ENETUNREACH on a socket).
void _dbus_set_errno_to_zero(void)
Assign 0 to the global errno variable.
Definition: dbus-sysdeps.c:711
dbus_bool_t _dbus_get_is_errno_epipe(void)
See if errno is EPIPE.
Definition: dbus-sysdeps.c:755
#define DBUS_ERROR_LIMITS_EXCEEDED
Some limited resource is exhausted.
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:2447
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
dbus_bool_t _dbus_generate_random_bytes(DBusString *str, int n_bytes)
Generates the given number of random bytes, using the best mechanism we can come up with...
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition: dbus-list.c:531