D-Bus  1.8.16
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 #else
56 extern char **environ;
57 #endif
58 
76 void
78 {
79  const char *s;
80 
82 
83  s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
84  if (s && *s)
85  {
86  /* don't use _dbus_warn here since it can _dbus_abort() */
87  fprintf (stderr, " Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
88  _dbus_sleep_milliseconds (1000 * 180);
89  }
90 
91  abort ();
92  _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */
93 }
94 
114 dbus_setenv (const char *varname,
115  const char *value)
116 {
117  _dbus_assert (varname != NULL);
118 
119  if (value == NULL)
120  {
121 #ifdef HAVE_UNSETENV
122  unsetenv (varname);
123  return TRUE;
124 #else
125  char *putenv_value;
126  size_t len;
127 
128  len = strlen (varname);
129 
130  /* Use system malloc to avoid memleaks that dbus_malloc
131  * will get upset about.
132  */
133 
134  putenv_value = malloc (len + 2);
135  if (putenv_value == NULL)
136  return FALSE;
137 
138  strcpy (putenv_value, varname);
139 #if defined(DBUS_WIN)
140  strcat (putenv_value, "=");
141 #endif
142 
143  return (putenv (putenv_value) == 0);
144 #endif
145  }
146  else
147  {
148 #ifdef HAVE_SETENV
149  return (setenv (varname, value, TRUE) == 0);
150 #else
151  char *putenv_value;
152  size_t len;
153  size_t varname_len;
154  size_t value_len;
155 
156  varname_len = strlen (varname);
157  value_len = strlen (value);
158 
159  len = varname_len + value_len + 1 /* '=' */ ;
160 
161  /* Use system malloc to avoid memleaks that dbus_malloc
162  * will get upset about.
163  */
164 
165  putenv_value = malloc (len + 1);
166  if (putenv_value == NULL)
167  return FALSE;
168 
169  strcpy (putenv_value, varname);
170  strcpy (putenv_value + varname_len, "=");
171  strcpy (putenv_value + varname_len + 1, value);
172 
173  return (putenv (putenv_value) == 0);
174 #endif
175  }
176 }
177 
184 const char*
185 _dbus_getenv (const char *varname)
186 {
187  /* Don't respect any environment variables if the current process is
188  * setuid. This is the equivalent of glibc's __secure_getenv().
189  */
190  if (_dbus_check_setuid ())
191  return NULL;
192  return getenv (varname);
193 }
194 
202 {
203  dbus_bool_t rc = TRUE;
204 
205 #ifdef HAVE_CLEARENV
206  if (clearenv () != 0)
207  rc = FALSE;
208 #else
209 
210  if (environ != NULL)
211  environ[0] = NULL;
212 #endif
213 
214  return rc;
215 }
216 
227  const char *suffix,
228  DBusList **dir_list)
229 {
230  int start;
231  int i;
232  int len;
233  char *cpath;
234  DBusString file_suffix;
235 
236  start = 0;
237  i = 0;
238 
239  _dbus_string_init_const (&file_suffix, suffix);
240 
241  len = _dbus_string_get_length (dirs);
242 
243  while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
244  {
245  DBusString path;
246 
247  if (!_dbus_string_init (&path))
248  goto oom;
249 
250  if (!_dbus_string_copy_len (dirs,
251  start,
252  i - start,
253  &path,
254  0))
255  {
256  _dbus_string_free (&path);
257  goto oom;
258  }
259 
260  _dbus_string_chop_white (&path);
261 
262  /* check for an empty path */
263  if (_dbus_string_get_length (&path) == 0)
264  goto next;
265 
266  if (!_dbus_concat_dir_and_file (&path,
267  &file_suffix))
268  {
269  _dbus_string_free (&path);
270  goto oom;
271  }
272 
273  if (!_dbus_string_copy_data(&path, &cpath))
274  {
275  _dbus_string_free (&path);
276  goto oom;
277  }
278 
279  if (!_dbus_list_append (dir_list, cpath))
280  {
281  _dbus_string_free (&path);
282  dbus_free (cpath);
283  goto oom;
284  }
285 
286  next:
287  _dbus_string_free (&path);
288  start = i + 1;
289  }
290 
291  if (start != len)
292  {
293  DBusString path;
294 
295  if (!_dbus_string_init (&path))
296  goto oom;
297 
298  if (!_dbus_string_copy_len (dirs,
299  start,
300  len - start,
301  &path,
302  0))
303  {
304  _dbus_string_free (&path);
305  goto oom;
306  }
307 
308  if (!_dbus_concat_dir_and_file (&path,
309  &file_suffix))
310  {
311  _dbus_string_free (&path);
312  goto oom;
313  }
314 
315  if (!_dbus_string_copy_data(&path, &cpath))
316  {
317  _dbus_string_free (&path);
318  goto oom;
319  }
320 
321  if (!_dbus_list_append (dir_list, cpath))
322  {
323  _dbus_string_free (&path);
324  dbus_free (cpath);
325  goto oom;
326  }
327 
328  _dbus_string_free (&path);
329  }
330 
331  return TRUE;
332 
333  oom:
335  _dbus_list_clear (dir_list);
336  return FALSE;
337 }
338 
355  long value)
356 {
357  /* this calculation is from comp.lang.c faq */
358 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */
359  int orig_len;
360  int i;
361  char *buf;
362 
363  orig_len = _dbus_string_get_length (str);
364 
365  if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
366  return FALSE;
367 
368  buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
369 
370  snprintf (buf, MAX_LONG_LEN, "%ld", value);
371 
372  i = 0;
373  while (*buf)
374  {
375  ++buf;
376  ++i;
377  }
378 
379  _dbus_string_shorten (str, MAX_LONG_LEN - i);
380 
381  return TRUE;
382 }
383 
393  unsigned long value)
394 {
395  /* this is wrong, but definitely on the high side. */
396 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
397  int orig_len;
398  int i;
399  char *buf;
400 
401  orig_len = _dbus_string_get_length (str);
402 
403  if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
404  return FALSE;
405 
406  buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
407 
408  snprintf (buf, MAX_ULONG_LEN, "%lu", value);
409 
410  i = 0;
411  while (*buf)
412  {
413  ++buf;
414  ++i;
415  }
416 
417  _dbus_string_shorten (str, MAX_ULONG_LEN - i);
418 
419  return TRUE;
420 }
421 
436  int start,
437  long *value_return,
438  int *end_return)
439 {
440  long v;
441  const char *p;
442  char *end;
443 
444  p = _dbus_string_get_const_data_len (str, start,
445  _dbus_string_get_length (str) - start);
446 
447  end = NULL;
449  v = strtol (p, &end, 0);
450  if (end == NULL || end == p || errno != 0)
451  return FALSE;
452 
453  if (value_return)
454  *value_return = v;
455  if (end_return)
456  *end_return = start + (end - p);
457 
458  return TRUE;
459 }
460 
475  int start,
476  unsigned long *value_return,
477  int *end_return)
478 {
479  unsigned long v;
480  const char *p;
481  char *end;
482 
483  p = _dbus_string_get_const_data_len (str, start,
484  _dbus_string_get_length (str) - start);
485 
486  end = NULL;
488  v = strtoul (p, &end, 0);
489  if (end == NULL || end == p || errno != 0)
490  return FALSE;
491 
492  if (value_return)
493  *value_return = v;
494  if (end_return)
495  *end_return = start + (end - p);
496 
497  return TRUE;
498 }
499  /* DBusString group */
501 
507 void
509  int n_bytes)
510 {
511  long tv_usec;
512  int i;
513 
514  /* fall back to pseudorandom */
515  _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
516  n_bytes);
517 
518  _dbus_get_real_time (NULL, &tv_usec);
519  srand (tv_usec);
520 
521  i = 0;
522  while (i < n_bytes)
523  {
524  double r;
525  unsigned int b;
526 
527  r = rand ();
528  b = (r / (double) RAND_MAX) * 255.0;
529 
530  buffer[i] = b;
531 
532  ++i;
533  }
534 }
535 
542 void
544  int n_bytes)
545 {
546  DBusString str;
547 
548  if (!_dbus_string_init (&str))
549  {
551  return;
552  }
553 
554  if (!_dbus_generate_random_bytes (&str, n_bytes))
555  {
556  _dbus_string_free (&str);
558  return;
559  }
560 
561  _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
562 
563  _dbus_string_free (&str);
564 }
565 
576  int n_bytes)
577 {
578  static const char letters[] =
579  "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
580  int i;
581  int len;
582 
583  if (!_dbus_generate_random_bytes (str, n_bytes))
584  return FALSE;
585 
586  len = _dbus_string_get_length (str);
587  i = len - n_bytes;
588  while (i < len)
589  {
590  _dbus_string_set_byte (str, i,
591  letters[_dbus_string_get_byte (str, i) %
592  (sizeof (letters) - 1)]);
593 
594  ++i;
595  }
596 
597  _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
598  n_bytes));
599 
600  return TRUE;
601 }
602 
613 const char*
614 _dbus_error_from_errno (int error_number)
615 {
616  switch (error_number)
617  {
618  case 0:
619  return DBUS_ERROR_FAILED;
620 
621 #ifdef EPROTONOSUPPORT
622  case EPROTONOSUPPORT:
624 #elif defined(WSAEPROTONOSUPPORT)
625  case WSAEPROTONOSUPPORT:
627 #endif
628 #ifdef EAFNOSUPPORT
629  case EAFNOSUPPORT:
631 #elif defined(WSAEAFNOSUPPORT)
632  case WSAEAFNOSUPPORT:
634 #endif
635 #ifdef ENFILE
636  case ENFILE:
637  return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
638 #endif
639 #ifdef EMFILE
640  case EMFILE:
642 #endif
643 #ifdef EACCES
644  case EACCES:
646 #endif
647 #ifdef EPERM
648  case EPERM:
650 #endif
651 #ifdef ENOBUFS
652  case ENOBUFS:
653  return DBUS_ERROR_NO_MEMORY;
654 #endif
655 #ifdef ENOMEM
656  case ENOMEM:
657  return DBUS_ERROR_NO_MEMORY;
658 #endif
659 #ifdef ECONNREFUSED
660  case ECONNREFUSED:
661  return DBUS_ERROR_NO_SERVER;
662 #elif defined(WSAECONNREFUSED)
663  case WSAECONNREFUSED:
664  return DBUS_ERROR_NO_SERVER;
665 #endif
666 #ifdef ETIMEDOUT
667  case ETIMEDOUT:
668  return DBUS_ERROR_TIMEOUT;
669 #elif defined(WSAETIMEDOUT)
670  case WSAETIMEDOUT:
671  return DBUS_ERROR_TIMEOUT;
672 #endif
673 #ifdef ENETUNREACH
674  case ENETUNREACH:
675  return DBUS_ERROR_NO_NETWORK;
676 #elif defined(WSAENETUNREACH)
677  case WSAENETUNREACH:
678  return DBUS_ERROR_NO_NETWORK;
679 #endif
680 #ifdef EADDRINUSE
681  case EADDRINUSE:
683 #elif defined(WSAEADDRINUSE)
684  case WSAEADDRINUSE:
686 #endif
687 #ifdef EEXIST
688  case EEXIST:
689  return DBUS_ERROR_FILE_EXISTS;
690 #endif
691 #ifdef ENOENT
692  case ENOENT:
694 #endif
695  }
696 
697  return DBUS_ERROR_FAILED;
698 }
699 
705 const char*
707 {
708  return _dbus_error_from_errno (errno);
709 }
710 
714 void
716 {
717 #ifdef DBUS_WINCE
718  SetLastError (0);
719 #else
720  errno = 0;
721 #endif
722 }
723 
730 {
731  return errno != 0;
732 }
733 
740 {
741  return errno == ENOMEM;
742 }
743 
750 {
751  return errno == EINTR;
752 }
753 
760 {
761  return errno == EPIPE;
762 }
763 
770 {
771 #ifdef ETOOMANYREFS
772  return errno == ETOOMANYREFS;
773 #else
774  return FALSE;
775 #endif
776 }
777 
782 const char*
784 {
785  return _dbus_strerror (errno);
786 }
787 
790 /* 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:435
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:680
#define DBUS_ERROR_FILE_NOT_FOUND
Missing file.
#define DBUS_ERROR_FILE_EXISTS
Existing file and the operation you'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:392
#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:743
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'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:354
void _dbus_string_chop_white(DBusString *str)
Deletes leading and trailing whitespace.
Definition: dbus-string.c:1971
#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...
dbus_bool_t _dbus_get_is_errno_etoomanyrefs(void)
See if errno is ETOOMANYREFS.
Definition: dbus-sysdeps.c:769
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:473
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:763
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:1586
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:185
void _dbus_abort(void)
Aborts the program with SIGABRT (dumping core).
Definition: dbus-sysdeps.c:77
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:614
#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:575
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:543
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:655
dbus_bool_t dbus_setenv(const char *varname, const char *value)
Wrapper for setenv().
Definition: dbus-sysdeps.c:114
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:270
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
dbus_bool_t _dbus_get_is_errno_enomem(void)
See if errno is ENOMEM.
Definition: dbus-sysdeps.c:739
#define DBUS_ERROR_ADDRESS_IN_USE
Can'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 "1".
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
dbus_bool_t _dbus_get_is_errno_nonzero(void)
See if errno is set.
Definition: dbus-sysdeps.c:729
const char * _dbus_strerror_from_errno(void)
Get error message from errno.
Definition: dbus-sysdeps.c:783
const char * _dbus_error_from_system_errno(void)
Converts the current system errno value into a DBusError name.
Definition: dbus-sysdeps.c:706
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:201
void _dbus_generate_pseudorandom_bytes_buffer(char *buffer, int n_bytes)
Random numbers.
Definition: dbus-sysdeps.c:508
dbus_bool_t _dbus_get_is_errno_eintr(void)
See if errno is EINTR.
Definition: dbus-sysdeps.c:749
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:226
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:474
#define DBUS_ERROR_ACCESS_DENIED
Security restrictions don't allow doing what you'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 "0".
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:1357
#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:715
dbus_bool_t _dbus_get_is_errno_epipe(void)
See if errno is EPIPE.
Definition: dbus-sysdeps.c:759
#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:2432
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:542