D-Bus  1.6.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 (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  return getenv (varname);
186 }
187 
195 {
196  dbus_bool_t rc = TRUE;
197 
198 #ifdef HAVE_CLEARENV
199  if (clearenv () != 0)
200  rc = FALSE;
201 #else
202 
203  if (environ != NULL)
204  environ[0] = NULL;
205 #endif
206 
207  return rc;
208 }
209 
220  const char *suffix,
221  DBusList **dir_list)
222 {
223  int start;
224  int i;
225  int len;
226  char *cpath;
227  DBusString file_suffix;
228 
229  start = 0;
230  i = 0;
231 
232  _dbus_string_init_const (&file_suffix, suffix);
233 
234  len = _dbus_string_get_length (dirs);
235 
236  while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
237  {
238  DBusString path;
239 
240  if (!_dbus_string_init (&path))
241  goto oom;
242 
243  if (!_dbus_string_copy_len (dirs,
244  start,
245  i - start,
246  &path,
247  0))
248  {
249  _dbus_string_free (&path);
250  goto oom;
251  }
252 
253  _dbus_string_chop_white (&path);
254 
255  /* check for an empty path */
256  if (_dbus_string_get_length (&path) == 0)
257  goto next;
258 
259  if (!_dbus_concat_dir_and_file (&path,
260  &file_suffix))
261  {
262  _dbus_string_free (&path);
263  goto oom;
264  }
265 
266  if (!_dbus_string_copy_data(&path, &cpath))
267  {
268  _dbus_string_free (&path);
269  goto oom;
270  }
271 
272  if (!_dbus_list_append (dir_list, cpath))
273  {
274  _dbus_string_free (&path);
275  dbus_free (cpath);
276  goto oom;
277  }
278 
279  next:
280  _dbus_string_free (&path);
281  start = i + 1;
282  }
283 
284  if (start != len)
285  {
286  DBusString path;
287 
288  if (!_dbus_string_init (&path))
289  goto oom;
290 
291  if (!_dbus_string_copy_len (dirs,
292  start,
293  len - start,
294  &path,
295  0))
296  {
297  _dbus_string_free (&path);
298  goto oom;
299  }
300 
301  if (!_dbus_concat_dir_and_file (&path,
302  &file_suffix))
303  {
304  _dbus_string_free (&path);
305  goto oom;
306  }
307 
308  if (!_dbus_string_copy_data(&path, &cpath))
309  {
310  _dbus_string_free (&path);
311  goto oom;
312  }
313 
314  if (!_dbus_list_append (dir_list, cpath))
315  {
316  _dbus_string_free (&path);
317  dbus_free (cpath);
318  goto oom;
319  }
320 
321  _dbus_string_free (&path);
322  }
323 
324  return TRUE;
325 
326  oom:
328  _dbus_list_clear (dir_list);
329  return FALSE;
330 }
331 
348  long value)
349 {
350  /* this calculation is from comp.lang.c faq */
351 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */
352  int orig_len;
353  int i;
354  char *buf;
355 
356  orig_len = _dbus_string_get_length (str);
357 
358  if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
359  return FALSE;
360 
361  buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
362 
363  snprintf (buf, MAX_LONG_LEN, "%ld", value);
364 
365  i = 0;
366  while (*buf)
367  {
368  ++buf;
369  ++i;
370  }
371 
372  _dbus_string_shorten (str, MAX_LONG_LEN - i);
373 
374  return TRUE;
375 }
376 
386  unsigned long value)
387 {
388  /* this is wrong, but definitely on the high side. */
389 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
390  int orig_len;
391  int i;
392  char *buf;
393 
394  orig_len = _dbus_string_get_length (str);
395 
396  if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
397  return FALSE;
398 
399  buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
400 
401  snprintf (buf, MAX_ULONG_LEN, "%lu", value);
402 
403  i = 0;
404  while (*buf)
405  {
406  ++buf;
407  ++i;
408  }
409 
410  _dbus_string_shorten (str, MAX_ULONG_LEN - i);
411 
412  return TRUE;
413 }
414 
429  int start,
430  long *value_return,
431  int *end_return)
432 {
433  long v;
434  const char *p;
435  char *end;
436 
437  p = _dbus_string_get_const_data_len (str, start,
438  _dbus_string_get_length (str) - start);
439 
440  end = NULL;
442  v = strtol (p, &end, 0);
443  if (end == NULL || end == p || errno != 0)
444  return FALSE;
445 
446  if (value_return)
447  *value_return = v;
448  if (end_return)
449  *end_return = start + (end - p);
450 
451  return TRUE;
452 }
453 
468  int start,
469  unsigned long *value_return,
470  int *end_return)
471 {
472  unsigned long v;
473  const char *p;
474  char *end;
475 
476  p = _dbus_string_get_const_data_len (str, start,
477  _dbus_string_get_length (str) - start);
478 
479  end = NULL;
481  v = strtoul (p, &end, 0);
482  if (end == NULL || end == p || errno != 0)
483  return FALSE;
484 
485  if (value_return)
486  *value_return = v;
487  if (end_return)
488  *end_return = start + (end - p);
489 
490  return TRUE;
491 }
492  /* DBusString group */
494 
500 void
502  int n_bytes)
503 {
504  long tv_usec;
505  int i;
506 
507  /* fall back to pseudorandom */
508  _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
509  n_bytes);
510 
511  _dbus_get_real_time (NULL, &tv_usec);
512  srand (tv_usec);
513 
514  i = 0;
515  while (i < n_bytes)
516  {
517  double r;
518  unsigned int b;
519 
520  r = rand ();
521  b = (r / (double) RAND_MAX) * 255.0;
522 
523  buffer[i] = b;
524 
525  ++i;
526  }
527 }
528 
535 void
537  int n_bytes)
538 {
539  DBusString str;
540 
541  if (!_dbus_string_init (&str))
542  {
544  return;
545  }
546 
547  if (!_dbus_generate_random_bytes (&str, n_bytes))
548  {
549  _dbus_string_free (&str);
551  return;
552  }
553 
554  _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
555 
556  _dbus_string_free (&str);
557 }
558 
569  int n_bytes)
570 {
571  static const char letters[] =
572  "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
573  int i;
574  int len;
575 
576  if (!_dbus_generate_random_bytes (str, n_bytes))
577  return FALSE;
578 
579  len = _dbus_string_get_length (str);
580  i = len - n_bytes;
581  while (i < len)
582  {
583  _dbus_string_set_byte (str, i,
584  letters[_dbus_string_get_byte (str, i) %
585  (sizeof (letters) - 1)]);
586 
587  ++i;
588  }
589 
590  _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
591  n_bytes));
592 
593  return TRUE;
594 }
595 
606 const char*
607 _dbus_error_from_errno (int error_number)
608 {
609  switch (error_number)
610  {
611  case 0:
612  return DBUS_ERROR_FAILED;
613 
614 #ifdef EPROTONOSUPPORT
615  case EPROTONOSUPPORT:
617 #elif defined(WSAEPROTONOSUPPORT)
618  case WSAEPROTONOSUPPORT:
620 #endif
621 #ifdef EAFNOSUPPORT
622  case EAFNOSUPPORT:
624 #elif defined(WSAEAFNOSUPPORT)
625  case WSAEAFNOSUPPORT:
627 #endif
628 #ifdef ENFILE
629  case ENFILE:
630  return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
631 #endif
632 #ifdef EMFILE
633  case EMFILE:
635 #endif
636 #ifdef EACCES
637  case EACCES:
639 #endif
640 #ifdef EPERM
641  case EPERM:
643 #endif
644 #ifdef ENOBUFS
645  case ENOBUFS:
646  return DBUS_ERROR_NO_MEMORY;
647 #endif
648 #ifdef ENOMEM
649  case ENOMEM:
650  return DBUS_ERROR_NO_MEMORY;
651 #endif
652 #ifdef ECONNREFUSED
653  case ECONNREFUSED:
654  return DBUS_ERROR_NO_SERVER;
655 #elif defined(WSAECONNREFUSED)
656  case WSAECONNREFUSED:
657  return DBUS_ERROR_NO_SERVER;
658 #endif
659 #ifdef ETIMEDOUT
660  case ETIMEDOUT:
661  return DBUS_ERROR_TIMEOUT;
662 #elif defined(WSAETIMEDOUT)
663  case WSAETIMEDOUT:
664  return DBUS_ERROR_TIMEOUT;
665 #endif
666 #ifdef ENETUNREACH
667  case ENETUNREACH:
668  return DBUS_ERROR_NO_NETWORK;
669 #elif defined(WSAENETUNREACH)
670  case WSAENETUNREACH:
671  return DBUS_ERROR_NO_NETWORK;
672 #endif
673 #ifdef EADDRINUSE
674  case EADDRINUSE:
676 #elif defined(WSAEADDRINUSE)
677  case WSAEADDRINUSE:
679 #endif
680 #ifdef EEXIST
681  case EEXIST:
682  return DBUS_ERROR_FILE_EXISTS;
683 #endif
684 #ifdef ENOENT
685  case ENOENT:
687 #endif
688  }
689 
690  return DBUS_ERROR_FAILED;
691 }
692 
698 const char*
700 {
701  return _dbus_error_from_errno (errno);
702 }
703 
707 void
709 {
710 #ifdef DBUS_WINCE
711  SetLastError (0);
712 #else
713  errno = 0;
714 #endif
715 }
716 
723 {
724  return errno != 0;
725 }
726 
733 {
734  return errno == ENOMEM;
735 }
736 
743 {
744  return errno == EINTR;
745 }
746 
753 {
754  return errno == EPIPE;
755 }
756 
761 const char*
763 {
764  return _dbus_strerror (errno);
765 }
766 
769 /* tests in dbus-sysdeps-util.c */