D-Bus  1.6.18
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 */