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 #ifdef DBUS_WIN
50  #include <stdlib.h>
51 #elif (defined __APPLE__)
52 # include <crt_externs.h>
53 # define environ (*_NSGetEnviron())
54 #else
55 extern char **environ;
56 #endif
57 
75 void
77 {
78  const char *s;
79 
81 
82  s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
83  if (s && *s)
84  {
85  /* don't use _dbus_warn here since it can _dbus_abort() */
86  fprintf (stderr, " Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
87  _dbus_sleep_milliseconds (1000 * 180);
88  }
89 
90  abort ();
91  _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */
92 }
93 
108 _dbus_setenv (const char *varname,
109  const char *value)
110 {
111  _dbus_assert (varname != NULL);
112 
113  if (value == NULL)
114  {
115 #ifdef HAVE_UNSETENV
116  unsetenv (varname);
117  return TRUE;
118 #else
119  char *putenv_value;
120  size_t len;
121 
122  len = strlen (varname);
123 
124  /* Use system malloc to avoid memleaks that dbus_malloc
125  * will get upset about.
126  */
127 
128  putenv_value = malloc (len + 2);
129  if (putenv_value == NULL)
130  return FALSE;
131 
132  strcpy (putenv_value, varname);
133 #if defined(DBUS_WIN)
134  strcat (putenv_value, "=");
135 #endif
136 
137  return (putenv (putenv_value) == 0);
138 #endif
139  }
140  else
141  {
142 #ifdef HAVE_SETENV
143  return (setenv (varname, value, TRUE) == 0);
144 #else
145  char *putenv_value;
146  size_t len;
147  size_t varname_len;
148  size_t value_len;
149 
150  varname_len = strlen (varname);
151  value_len = strlen (value);
152 
153  len = varname_len + value_len + 1 /* '=' */ ;
154 
155  /* Use system malloc to avoid memleaks that dbus_malloc
156  * will get upset about.
157  */
158 
159  putenv_value = malloc (len + 1);
160  if (putenv_value == NULL)
161  return FALSE;
162 
163  strcpy (putenv_value, varname);
164  strcpy (putenv_value + varname_len, "=");
165  strcpy (putenv_value + varname_len + 1, value);
166 
167  return (putenv (putenv_value) == 0);
168 #endif
169  }
170 }
171 
178 const char*
179 _dbus_getenv (const char *varname)
180 {
181  /* Don't respect any environment variables if the current process is
182  * setuid. This is the equivalent of glibc's __secure_getenv().
183  */
184  if (_dbus_check_setuid ())
185  return NULL;
186  return getenv (varname);
187 }
188 
196 {
197  dbus_bool_t rc = TRUE;
198 
199 #ifdef HAVE_CLEARENV
200  if (clearenv () != 0)
201  rc = FALSE;
202 #else
203 
204  if (environ != NULL)
205  environ[0] = NULL;
206 #endif
207 
208  return rc;
209 }
210 
221  const char *suffix,
222  DBusList **dir_list)
223 {
224  int start;
225  int i;
226  int len;
227  char *cpath;
228  DBusString file_suffix;
229 
230  start = 0;
231  i = 0;
232 
233  _dbus_string_init_const (&file_suffix, suffix);
234 
235  len = _dbus_string_get_length (dirs);
236 
237  while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
238  {
239  DBusString path;
240 
241  if (!_dbus_string_init (&path))
242  goto oom;
243 
244  if (!_dbus_string_copy_len (dirs,
245  start,
246  i - start,
247  &path,
248  0))
249  {
250  _dbus_string_free (&path);
251  goto oom;
252  }
253 
254  _dbus_string_chop_white (&path);
255 
256  /* check for an empty path */
257  if (_dbus_string_get_length (&path) == 0)
258  goto next;
259 
260  if (!_dbus_concat_dir_and_file (&path,
261  &file_suffix))
262  {
263  _dbus_string_free (&path);
264  goto oom;
265  }
266 
267  if (!_dbus_string_copy_data(&path, &cpath))
268  {
269  _dbus_string_free (&path);
270  goto oom;
271  }
272 
273  if (!_dbus_list_append (dir_list, cpath))
274  {
275  _dbus_string_free (&path);
276  dbus_free (cpath);
277  goto oom;
278  }
279 
280  next:
281  _dbus_string_free (&path);
282  start = i + 1;
283  }
284 
285  if (start != len)
286  {
287  DBusString path;
288 
289  if (!_dbus_string_init (&path))
290  goto oom;
291 
292  if (!_dbus_string_copy_len (dirs,
293  start,
294  len - start,
295  &path,
296  0))
297  {
298  _dbus_string_free (&path);
299  goto oom;
300  }
301 
302  if (!_dbus_concat_dir_and_file (&path,
303  &file_suffix))
304  {
305  _dbus_string_free (&path);
306  goto oom;
307  }
308 
309  if (!_dbus_string_copy_data(&path, &cpath))
310  {
311  _dbus_string_free (&path);
312  goto oom;
313  }
314 
315  if (!_dbus_list_append (dir_list, cpath))
316  {
317  _dbus_string_free (&path);
318  dbus_free (cpath);
319  goto oom;
320  }
321 
322  _dbus_string_free (&path);
323  }
324 
325  return TRUE;
326 
327  oom:
329  _dbus_list_clear (dir_list);
330  return FALSE;
331 }
332 
349  long value)
350 {
351  /* this calculation is from comp.lang.c faq */
352 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */
353  int orig_len;
354  int i;
355  char *buf;
356 
357  orig_len = _dbus_string_get_length (str);
358 
359  if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
360  return FALSE;
361 
362  buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
363 
364  snprintf (buf, MAX_LONG_LEN, "%ld", value);
365 
366  i = 0;
367  while (*buf)
368  {
369  ++buf;
370  ++i;
371  }
372 
373  _dbus_string_shorten (str, MAX_LONG_LEN - i);
374 
375  return TRUE;
376 }
377 
387  unsigned long value)
388 {
389  /* this is wrong, but definitely on the high side. */
390 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
391  int orig_len;
392  int i;
393  char *buf;
394 
395  orig_len = _dbus_string_get_length (str);
396 
397  if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
398  return FALSE;
399 
400  buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
401 
402  snprintf (buf, MAX_ULONG_LEN, "%lu", value);
403 
404  i = 0;
405  while (*buf)
406  {
407  ++buf;
408  ++i;
409  }
410 
411  _dbus_string_shorten (str, MAX_ULONG_LEN - i);
412 
413  return TRUE;
414 }
415 
430  int start,
431  long *value_return,
432  int *end_return)
433 {
434  long v;
435  const char *p;
436  char *end;
437 
438  p = _dbus_string_get_const_data_len (str, start,
439  _dbus_string_get_length (str) - start);
440 
441  end = NULL;
443  v = strtol (p, &end, 0);
444  if (end == NULL || end == p || errno != 0)
445  return FALSE;
446 
447  if (value_return)
448  *value_return = v;
449  if (end_return)
450  *end_return = start + (end - p);
451 
452  return TRUE;
453 }
454 
469  int start,
470  unsigned long *value_return,
471  int *end_return)
472 {
473  unsigned long v;
474  const char *p;
475  char *end;
476 
477  p = _dbus_string_get_const_data_len (str, start,
478  _dbus_string_get_length (str) - start);
479 
480  end = NULL;
482  v = strtoul (p, &end, 0);
483  if (end == NULL || end == p || errno != 0)
484  return FALSE;
485 
486  if (value_return)
487  *value_return = v;
488  if (end_return)
489  *end_return = start + (end - p);
490 
491  return TRUE;
492 }
493  /* DBusString group */
495 
501 void
503  int n_bytes)
504 {
505  long tv_usec;
506  int i;
507 
508  /* fall back to pseudorandom */
509  _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
510  n_bytes);
511 
512  _dbus_get_real_time (NULL, &tv_usec);
513  srand (tv_usec);
514 
515  i = 0;
516  while (i < n_bytes)
517  {
518  double r;
519  unsigned int b;
520 
521  r = rand ();
522  b = (r / (double) RAND_MAX) * 255.0;
523 
524  buffer[i] = b;
525 
526  ++i;
527  }
528 }
529 
536 void
538  int n_bytes)
539 {
540  DBusString str;
541 
542  if (!_dbus_string_init (&str))
543  {
545  return;
546  }
547 
548  if (!_dbus_generate_random_bytes (&str, n_bytes))
549  {
550  _dbus_string_free (&str);
552  return;
553  }
554 
555  _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
556 
557  _dbus_string_free (&str);
558 }
559 
570  int n_bytes)
571 {
572  static const char letters[] =
573  "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
574  int i;
575  int len;
576 
577  if (!_dbus_generate_random_bytes (str, n_bytes))
578  return FALSE;
579 
580  len = _dbus_string_get_length (str);
581  i = len - n_bytes;
582  while (i < len)
583  {
584  _dbus_string_set_byte (str, i,
585  letters[_dbus_string_get_byte (str, i) %
586  (sizeof (letters) - 1)]);
587 
588  ++i;
589  }
590 
591  _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
592  n_bytes));
593 
594  return TRUE;
595 }
596 
607 const char*
608 _dbus_error_from_errno (int error_number)
609 {
610  switch (error_number)
611  {
612  case 0:
613  return DBUS_ERROR_FAILED;
614 
615 #ifdef EPROTONOSUPPORT
616  case EPROTONOSUPPORT:
618 #elif defined(WSAEPROTONOSUPPORT)
619  case WSAEPROTONOSUPPORT:
621 #endif
622 #ifdef EAFNOSUPPORT
623  case EAFNOSUPPORT:
625 #elif defined(WSAEAFNOSUPPORT)
626  case WSAEAFNOSUPPORT:
628 #endif
629 #ifdef ENFILE
630  case ENFILE:
631  return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
632 #endif
633 #ifdef EMFILE
634  case EMFILE:
636 #endif
637 #ifdef EACCES
638  case EACCES:
640 #endif
641 #ifdef EPERM
642  case EPERM:
644 #endif
645 #ifdef ENOBUFS
646  case ENOBUFS:
647  return DBUS_ERROR_NO_MEMORY;
648 #endif
649 #ifdef ENOMEM
650  case ENOMEM:
651  return DBUS_ERROR_NO_MEMORY;
652 #endif
653 #ifdef ECONNREFUSED
654  case ECONNREFUSED:
655  return DBUS_ERROR_NO_SERVER;
656 #elif defined(WSAECONNREFUSED)
657  case WSAECONNREFUSED:
658  return DBUS_ERROR_NO_SERVER;
659 #endif
660 #ifdef ETIMEDOUT
661  case ETIMEDOUT:
662  return DBUS_ERROR_TIMEOUT;
663 #elif defined(WSAETIMEDOUT)
664  case WSAETIMEDOUT:
665  return DBUS_ERROR_TIMEOUT;
666 #endif
667 #ifdef ENETUNREACH
668  case ENETUNREACH:
669  return DBUS_ERROR_NO_NETWORK;
670 #elif defined(WSAENETUNREACH)
671  case WSAENETUNREACH:
672  return DBUS_ERROR_NO_NETWORK;
673 #endif
674 #ifdef EADDRINUSE
675  case EADDRINUSE:
677 #elif defined(WSAEADDRINUSE)
678  case WSAEADDRINUSE:
680 #endif
681 #ifdef EEXIST
682  case EEXIST:
683  return DBUS_ERROR_FILE_EXISTS;
684 #endif
685 #ifdef ENOENT
686  case ENOENT:
688 #endif
689  }
690 
691  return DBUS_ERROR_FAILED;
692 }
693 
699 const char*
701 {
702  return _dbus_error_from_errno (errno);
703 }
704 
708 void
710 {
711 #ifdef DBUS_WINCE
712  SetLastError (0);
713 #else
714  errno = 0;
715 #endif
716 }
717 
724 {
725  return errno != 0;
726 }
727 
734 {
735  return errno == ENOMEM;
736 }
737 
744 {
745  return errno == EINTR;
746 }
747 
754 {
755  return errno == EPIPE;
756 }
757 
762 const char*
764 {
765  return _dbus_strerror (errno);
766 }
767 
770 /* tests in dbus-sysdeps-util.c */