D-Bus  1.12.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 #elif HAVE_DECL_ENVIRON && defined(HAVE_UNISTD_H)
56 # include <unistd.h>
57 #else
58 extern char **environ;
59 #endif
60 
78 void
80 {
81  const char *s;
82 
84 
85  s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
86  if (s && *s)
87  {
88  /* don't use _dbus_warn here since it can _dbus_abort() */
89  fprintf (stderr, " Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
90  _dbus_sleep_milliseconds (1000 * 180);
91  }
92 
93  abort ();
94  _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */
95 }
96 
116 dbus_setenv (const char *varname,
117  const char *value)
118 {
119  _dbus_assert (varname != NULL);
120 
121  if (value == NULL)
122  {
123 #ifdef HAVE_UNSETENV
124  unsetenv (varname);
125  return TRUE;
126 #else
127  char *putenv_value;
128  size_t len;
129 
130  len = strlen (varname);
131 
132  /* Use system malloc to avoid memleaks that dbus_malloc
133  * will get upset about.
134  */
135 
136  putenv_value = malloc (len + 2);
137  if (putenv_value == NULL)
138  return FALSE;
139 
140  strcpy (putenv_value, varname);
141 #if defined(DBUS_WIN)
142  strcat (putenv_value, "=");
143 #endif
144 
145  return (putenv (putenv_value) == 0);
146 #endif
147  }
148  else
149  {
150 #ifdef HAVE_SETENV
151  return (setenv (varname, value, TRUE) == 0);
152 #else
153  char *putenv_value;
154  size_t len;
155  size_t varname_len;
156  size_t value_len;
157 
158  varname_len = strlen (varname);
159  value_len = strlen (value);
160 
161  len = varname_len + value_len + 1 /* '=' */ ;
162 
163  /* Use system malloc to avoid memleaks that dbus_malloc
164  * will get upset about.
165  */
166 
167  putenv_value = malloc (len + 1);
168  if (putenv_value == NULL)
169  return FALSE;
170 
171  strcpy (putenv_value, varname);
172  strcpy (putenv_value + varname_len, "=");
173  strcpy (putenv_value + varname_len + 1, value);
174 
175  return (putenv (putenv_value) == 0);
176 #endif
177  }
178 }
179 
186 const char*
187 _dbus_getenv (const char *varname)
188 {
189  /* Don't respect any environment variables if the current process is
190  * setuid. This is the equivalent of glibc's __secure_getenv().
191  */
192  if (_dbus_check_setuid ())
193  return NULL;
194  return getenv (varname);
195 }
196 
204 {
205  dbus_bool_t rc = TRUE;
206 
207 #ifdef HAVE_CLEARENV
208  if (clearenv () != 0)
209  rc = FALSE;
210 #else
211 
212  if (environ != NULL)
213  environ[0] = NULL;
214 #endif
215 
216  return rc;
217 }
218 
229  const char *suffix,
230  DBusList **dir_list)
231 {
232  int start;
233  int i;
234  int len;
235  char *cpath;
236  DBusString file_suffix;
237 
238  start = 0;
239  i = 0;
240 
241  _dbus_string_init_const (&file_suffix, suffix);
242 
243  len = _dbus_string_get_length (dirs);
244 
245  while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
246  {
247  DBusString path;
248 
249  if (!_dbus_string_init (&path))
250  goto oom;
251 
252  if (!_dbus_string_copy_len (dirs,
253  start,
254  i - start,
255  &path,
256  0))
257  {
258  _dbus_string_free (&path);
259  goto oom;
260  }
261 
262  _dbus_string_chop_white (&path);
263 
264  /* check for an empty path */
265  if (_dbus_string_get_length (&path) == 0)
266  goto next;
267 
268  if (!_dbus_concat_dir_and_file (&path,
269  &file_suffix))
270  {
271  _dbus_string_free (&path);
272  goto oom;
273  }
274 
275  if (!_dbus_string_copy_data(&path, &cpath))
276  {
277  _dbus_string_free (&path);
278  goto oom;
279  }
280 
281  if (!_dbus_list_append (dir_list, cpath))
282  {
283  _dbus_string_free (&path);
284  dbus_free (cpath);
285  goto oom;
286  }
287 
288  next:
289  _dbus_string_free (&path);
290  start = i + 1;
291  }
292 
293  if (start != len)
294  {
295  DBusString path;
296 
297  if (!_dbus_string_init (&path))
298  goto oom;
299 
300  if (!_dbus_string_copy_len (dirs,
301  start,
302  len - start,
303  &path,
304  0))
305  {
306  _dbus_string_free (&path);
307  goto oom;
308  }
309 
310  if (!_dbus_concat_dir_and_file (&path,
311  &file_suffix))
312  {
313  _dbus_string_free (&path);
314  goto oom;
315  }
316 
317  if (!_dbus_string_copy_data(&path, &cpath))
318  {
319  _dbus_string_free (&path);
320  goto oom;
321  }
322 
323  if (!_dbus_list_append (dir_list, cpath))
324  {
325  _dbus_string_free (&path);
326  dbus_free (cpath);
327  goto oom;
328  }
329 
330  _dbus_string_free (&path);
331  }
332 
333  return TRUE;
334 
335  oom:
337  _dbus_list_clear (dir_list);
338  return FALSE;
339 }
340 
357  long value)
358 {
359  /* this calculation is from comp.lang.c faq */
360 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */
361  int orig_len;
362  int i;
363  char *buf;
364 
365  orig_len = _dbus_string_get_length (str);
366 
367  if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
368  return FALSE;
369 
370  buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
371 
372  snprintf (buf, MAX_LONG_LEN, "%ld", value);
373 
374  i = 0;
375  while (*buf)
376  {
377  ++buf;
378  ++i;
379  }
380 
381  _dbus_string_shorten (str, MAX_LONG_LEN - i);
382 
383  return TRUE;
384 }
385 
395  unsigned long value)
396 {
397  /* this is wrong, but definitely on the high side. */
398 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
399  int orig_len;
400  int i;
401  char *buf;
402 
403  orig_len = _dbus_string_get_length (str);
404 
405  if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
406  return FALSE;
407 
408  buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
409 
410  snprintf (buf, MAX_ULONG_LEN, "%lu", value);
411 
412  i = 0;
413  while (*buf)
414  {
415  ++buf;
416  ++i;
417  }
418 
419  _dbus_string_shorten (str, MAX_ULONG_LEN - i);
420 
421  return TRUE;
422 }
423 
438  int start,
439  long *value_return,
440  int *end_return)
441 {
442  long v;
443  const char *p;
444  char *end;
445 
446  p = _dbus_string_get_const_data_len (str, start,
447  _dbus_string_get_length (str) - start);
448 
449  end = NULL;
451  v = strtol (p, &end, 0);
452  if (end == NULL || end == p || errno != 0)
453  return FALSE;
454 
455  if (value_return)
456  *value_return = v;
457  if (end_return)
458  *end_return = start + (end - p);
459 
460  return TRUE;
461 }
462 
477  int start,
478  unsigned long *value_return,
479  int *end_return)
480 {
481  unsigned long v;
482  const char *p;
483  char *end;
484 
485  p = _dbus_string_get_const_data_len (str, start,
486  _dbus_string_get_length (str) - start);
487 
488  end = NULL;
490  v = strtoul (p, &end, 0);
491  if (end == NULL || end == p || errno != 0)
492  return FALSE;
493 
494  if (value_return)
495  *value_return = v;
496  if (end_return)
497  *end_return = start + (end - p);
498 
499  return TRUE;
500 }
501  /* DBusString group */
503 
519  int n_bytes,
520  DBusError *error)
521 {
522  DBusString str;
523 
524  if (!_dbus_string_init (&str))
525  {
526  _DBUS_SET_OOM (error);
527  return FALSE;
528  }
529 
530  if (!_dbus_generate_random_bytes (&str, n_bytes, error))
531  {
532  _dbus_string_free (&str);
533  return FALSE;
534  }
535 
536  _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
537 
538  _dbus_string_free (&str);
539  return TRUE;
540 }
541 
553  int n_bytes,
554  DBusError *error)
555 {
556  static const char letters[] =
557  "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
558  int i;
559  int len;
560 
561  if (!_dbus_generate_random_bytes (str, n_bytes, error))
562  return FALSE;
563 
564  len = _dbus_string_get_length (str);
565  i = len - n_bytes;
566  while (i < len)
567  {
568  _dbus_string_set_byte (str, i,
569  letters[_dbus_string_get_byte (str, i) %
570  (sizeof (letters) - 1)]);
571 
572  ++i;
573  }
574 
575  _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
576  n_bytes));
577 
578  return TRUE;
579 }
580 
591 const char*
592 _dbus_error_from_errno (int error_number)
593 {
594  switch (error_number)
595  {
596  case 0:
597  return DBUS_ERROR_FAILED;
598 
599 #ifdef EPROTONOSUPPORT
600  case EPROTONOSUPPORT:
602 #elif defined(WSAEPROTONOSUPPORT)
603  case WSAEPROTONOSUPPORT:
605 #endif
606 #ifdef EAFNOSUPPORT
607  case EAFNOSUPPORT:
609 #elif defined(WSAEAFNOSUPPORT)
610  case WSAEAFNOSUPPORT:
612 #endif
613 #ifdef ENFILE
614  case ENFILE:
615  return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
616 #endif
617 #ifdef EMFILE
618  case EMFILE:
620 #endif
621 #ifdef EACCES
622  case EACCES:
624 #endif
625 #ifdef EPERM
626  case EPERM:
628 #endif
629 #ifdef ENOBUFS
630  case ENOBUFS:
631  return DBUS_ERROR_NO_MEMORY;
632 #endif
633 #ifdef ENOMEM
634  case ENOMEM:
635  return DBUS_ERROR_NO_MEMORY;
636 #endif
637 #ifdef ECONNREFUSED
638  case ECONNREFUSED:
639  return DBUS_ERROR_NO_SERVER;
640 #elif defined(WSAECONNREFUSED)
641  case WSAECONNREFUSED:
642  return DBUS_ERROR_NO_SERVER;
643 #endif
644 #ifdef ETIMEDOUT
645  case ETIMEDOUT:
646  return DBUS_ERROR_TIMEOUT;
647 #elif defined(WSAETIMEDOUT)
648  case WSAETIMEDOUT:
649  return DBUS_ERROR_TIMEOUT;
650 #endif
651 #ifdef ENETUNREACH
652  case ENETUNREACH:
653  return DBUS_ERROR_NO_NETWORK;
654 #elif defined(WSAENETUNREACH)
655  case WSAENETUNREACH:
656  return DBUS_ERROR_NO_NETWORK;
657 #endif
658 #ifdef EADDRINUSE
659  case EADDRINUSE:
661 #elif defined(WSAEADDRINUSE)
662  case WSAEADDRINUSE:
664 #endif
665 #ifdef EEXIST
666  case EEXIST:
667  return DBUS_ERROR_FILE_EXISTS;
668 #endif
669 #ifdef ENOENT
670  case ENOENT:
672 #endif
673  default:
674  return DBUS_ERROR_FAILED;
675  }
676 }
677 
683 const char*
685 {
686  return _dbus_error_from_errno (errno);
687 }
688 
692 void
694 {
695 #ifdef DBUS_WINCE
696  SetLastError (0);
697 #else
698  errno = 0;
699 #endif
700 }
701 
708 {
709  return e == ENOMEM;
710 }
711 
718 {
719  return e == EINTR;
720 }
721 
728 {
729  return e == EPIPE;
730 }
731 
738 {
739 #ifdef ETOOMANYREFS
740  return e == ETOOMANYREFS;
741 #else
742  return FALSE;
743 #endif
744 }
745 
750 const char*
752 {
753  return _dbus_strerror (errno);
754 }
755 
762 void
763 _dbus_log (DBusSystemLogSeverity severity,
764  const char *msg,
765  ...)
766 {
767  va_list args;
768 
769  va_start (args, msg);
770 
771  _dbus_logv (severity, msg, args);
772 
773  va_end (args);
774 }
775 
778 /* tests in dbus-sysdeps-util.c */