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