D-Bus  1.10.12
dbus-sysdeps.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-sysdeps.c Wrappers around system/libc features shared between UNIX and Windows (internal to D-Bus implementation)
00003  * 
00004  * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
00005  * Copyright (C) 2003 CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include <config.h>
00026 #include "dbus-internals.h"
00027 #include "dbus-sysdeps.h"
00028 #include "dbus-threads.h"
00029 #include "dbus-protocol.h"
00030 #include "dbus-string.h"
00031 #include "dbus-list.h"
00032 #include "dbus-misc.h"
00033 
00034 /* NOTE: If you include any unix/windows-specific headers here, you are probably doing something
00035  * wrong and should be putting some code in dbus-sysdeps-unix.c or dbus-sysdeps-win.c.
00036  *
00037  * These are the standard ANSI C headers...
00038  */
00039 #if HAVE_LOCALE_H
00040 #include <locale.h>
00041 #endif
00042 #include <stdlib.h>
00043 #include <string.h>
00044 #include <stdio.h>
00045 
00046 #ifdef HAVE_ERRNO_H
00047 #include <errno.h>
00048 #endif
00049 
00050 #ifdef DBUS_WIN
00051   #include <stdlib.h>
00052 #elif (defined __APPLE__)
00053 # include <crt_externs.h>
00054 # define environ (*_NSGetEnviron())
00055 #else
00056 extern char **environ;
00057 #endif
00058 
00076 void
00077 _dbus_abort (void)
00078 {
00079   const char *s;
00080   
00081   _dbus_print_backtrace ();
00082   
00083   s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
00084   if (s && *s)
00085     {
00086       /* don't use _dbus_warn here since it can _dbus_abort() */
00087       fprintf (stderr, "  Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
00088       _dbus_sleep_milliseconds (1000 * 180);
00089     }
00090   
00091   abort ();
00092   _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */
00093 }
00094 
00113 dbus_bool_t
00114 dbus_setenv (const char *varname,
00115              const char *value)
00116 {
00117   _dbus_assert (varname != NULL);
00118   
00119   if (value == NULL)
00120     {
00121 #ifdef HAVE_UNSETENV
00122       unsetenv (varname);
00123       return TRUE;
00124 #else
00125       char *putenv_value;
00126       size_t len;
00127 
00128       len = strlen (varname);
00129 
00130       /* Use system malloc to avoid memleaks that dbus_malloc
00131        * will get upset about.
00132        */
00133       
00134       putenv_value = malloc (len + 2);
00135       if (putenv_value == NULL)
00136         return FALSE;
00137 
00138       strcpy (putenv_value, varname);
00139 #if defined(DBUS_WIN)
00140       strcat (putenv_value, "=");
00141 #endif
00142       
00143       return (putenv (putenv_value) == 0);
00144 #endif
00145     }
00146   else
00147     {
00148 #ifdef HAVE_SETENV
00149       return (setenv (varname, value, TRUE) == 0);
00150 #else
00151       char *putenv_value;
00152       size_t len;
00153       size_t varname_len;
00154       size_t value_len;
00155 
00156       varname_len = strlen (varname);
00157       value_len = strlen (value);
00158       
00159       len = varname_len + value_len + 1 /* '=' */ ;
00160 
00161       /* Use system malloc to avoid memleaks that dbus_malloc
00162        * will get upset about.
00163        */
00164       
00165       putenv_value = malloc (len + 1);
00166       if (putenv_value == NULL)
00167         return FALSE;
00168 
00169       strcpy (putenv_value, varname);
00170       strcpy (putenv_value + varname_len, "=");
00171       strcpy (putenv_value + varname_len + 1, value);
00172       
00173       return (putenv (putenv_value) == 0);
00174 #endif
00175     }
00176 }
00177 
00184 const char*
00185 _dbus_getenv (const char *varname)
00186 {  
00187   /* Don't respect any environment variables if the current process is
00188    * setuid.  This is the equivalent of glibc's __secure_getenv().
00189    */
00190   if (_dbus_check_setuid ())
00191     return NULL;
00192   return getenv (varname);
00193 }
00194 
00200 dbus_bool_t
00201 _dbus_clearenv (void)
00202 {
00203   dbus_bool_t rc = TRUE;
00204 
00205 #ifdef HAVE_CLEARENV
00206   if (clearenv () != 0)
00207      rc = FALSE;
00208 #else
00209 
00210   if (environ != NULL)
00211     environ[0] = NULL;
00212 #endif
00213 
00214   return rc;
00215 }
00216 
00225 dbus_bool_t
00226 _dbus_split_paths_and_append (DBusString *dirs, 
00227                               const char *suffix, 
00228                               DBusList  **dir_list)
00229 {
00230    int start;
00231    int i;
00232    int len;
00233    char *cpath;
00234    DBusString file_suffix;
00235 
00236    start = 0;
00237    i = 0;
00238 
00239    _dbus_string_init_const (&file_suffix, suffix);
00240 
00241    len = _dbus_string_get_length (dirs);
00242 
00243    while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
00244      {
00245        DBusString path;
00246 
00247        if (!_dbus_string_init (&path))
00248           goto oom;
00249 
00250        if (!_dbus_string_copy_len (dirs,
00251                                    start,
00252                                    i - start,
00253                                    &path,
00254                                    0))
00255           {
00256             _dbus_string_free (&path);
00257             goto oom;
00258           }
00259 
00260         _dbus_string_chop_white (&path);
00261 
00262         /* check for an empty path */
00263         if (_dbus_string_get_length (&path) == 0)
00264           goto next;
00265 
00266         if (!_dbus_concat_dir_and_file (&path,
00267                                         &file_suffix))
00268           {
00269             _dbus_string_free (&path);
00270             goto oom;
00271           }
00272 
00273         if (!_dbus_string_copy_data(&path, &cpath))
00274           {
00275             _dbus_string_free (&path);
00276             goto oom;
00277           }
00278 
00279         if (!_dbus_list_append (dir_list, cpath))
00280           {
00281             _dbus_string_free (&path);              
00282             dbus_free (cpath);
00283             goto oom;
00284           }
00285 
00286        next:
00287         _dbus_string_free (&path);
00288         start = i + 1;
00289     } 
00290       
00291   if (start != len)
00292     { 
00293       DBusString path;
00294 
00295       if (!_dbus_string_init (&path))
00296         goto oom;
00297 
00298       if (!_dbus_string_copy_len (dirs,
00299                                   start,
00300                                   len - start,
00301                                   &path,
00302                                   0))
00303         {
00304           _dbus_string_free (&path);
00305           goto oom;
00306         }
00307 
00308       if (!_dbus_concat_dir_and_file (&path,
00309                                       &file_suffix))
00310         {
00311           _dbus_string_free (&path);
00312           goto oom;
00313         }
00314 
00315       if (!_dbus_string_copy_data(&path, &cpath))
00316         {
00317           _dbus_string_free (&path);
00318           goto oom;
00319         }
00320 
00321       if (!_dbus_list_append (dir_list, cpath))
00322         {
00323           _dbus_string_free (&path);              
00324           dbus_free (cpath);
00325           goto oom;
00326         }
00327 
00328       _dbus_string_free (&path); 
00329     }
00330 
00331   return TRUE;
00332 
00333  oom:
00334   _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); 
00335   _dbus_list_clear (dir_list);
00336   return FALSE;
00337 }
00338 
00353 dbus_bool_t
00354 _dbus_string_append_int (DBusString *str,
00355                          long        value)
00356 {
00357   /* this calculation is from comp.lang.c faq */
00358 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
00359   int orig_len;
00360   int i;
00361   char *buf;
00362   
00363   orig_len = _dbus_string_get_length (str);
00364 
00365   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00366     return FALSE;
00367 
00368   buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00369 
00370   snprintf (buf, MAX_LONG_LEN, "%ld", value);
00371 
00372   i = 0;
00373   while (*buf)
00374     {
00375       ++buf;
00376       ++i;
00377     }
00378   
00379   _dbus_string_shorten (str, MAX_LONG_LEN - i);
00380   
00381   return TRUE;
00382 }
00383 
00391 dbus_bool_t
00392 _dbus_string_append_uint (DBusString    *str,
00393                           unsigned long  value)
00394 {
00395   /* this is wrong, but definitely on the high side. */
00396 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
00397   int orig_len;
00398   int i;
00399   char *buf;
00400   
00401   orig_len = _dbus_string_get_length (str);
00402 
00403   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
00404     return FALSE;
00405 
00406   buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
00407 
00408   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
00409 
00410   i = 0;
00411   while (*buf)
00412     {
00413       ++buf;
00414       ++i;
00415     }
00416   
00417   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
00418   
00419   return TRUE;
00420 }
00421 
00434 dbus_bool_t
00435 _dbus_string_parse_int (const DBusString *str,
00436                         int               start,
00437                         long             *value_return,
00438                         int              *end_return)
00439 {
00440   long v;
00441   const char *p;
00442   char *end;
00443 
00444   p = _dbus_string_get_const_data_len (str, start,
00445                                        _dbus_string_get_length (str) - start);
00446 
00447   end = NULL;
00448   _dbus_set_errno_to_zero ();
00449   v = strtol (p, &end, 0);
00450   if (end == NULL || end == p || errno != 0)
00451     return FALSE;
00452 
00453   if (value_return)
00454     *value_return = v;
00455   if (end_return)
00456     *end_return = start + (end - p);
00457 
00458   return TRUE;
00459 }
00460 
00473 dbus_bool_t
00474 _dbus_string_parse_uint (const DBusString *str,
00475                          int               start,
00476                          unsigned long    *value_return,
00477                          int              *end_return)
00478 {
00479   unsigned long v;
00480   const char *p;
00481   char *end;
00482 
00483   p = _dbus_string_get_const_data_len (str, start,
00484                                        _dbus_string_get_length (str) - start);
00485 
00486   end = NULL;
00487   _dbus_set_errno_to_zero ();
00488   v = strtoul (p, &end, 0);
00489   if (end == NULL || end == p || errno != 0)
00490     return FALSE;
00491 
00492   if (value_return)
00493     *value_return = v;
00494   if (end_return)
00495     *end_return = start + (end - p);
00496 
00497   return TRUE;
00498 }
00499  /* DBusString group */
00501 
00515 dbus_bool_t
00516 _dbus_generate_random_bytes_buffer (char      *buffer,
00517                                     int        n_bytes,
00518                                     DBusError *error)
00519 {
00520   DBusString str;
00521 
00522   if (!_dbus_string_init (&str))
00523     {
00524       _DBUS_SET_OOM (error);
00525       return FALSE;
00526     }
00527 
00528   if (!_dbus_generate_random_bytes (&str, n_bytes, error))
00529     {
00530       _dbus_string_free (&str);
00531       return FALSE;
00532     }
00533 
00534   _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
00535 
00536   _dbus_string_free (&str);
00537   return TRUE;
00538 }
00539 
00549 dbus_bool_t
00550 _dbus_generate_random_ascii (DBusString *str,
00551                              int         n_bytes,
00552                              DBusError  *error)
00553 {
00554   static const char letters[] =
00555     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
00556   int i;
00557   int len;
00558   
00559   if (!_dbus_generate_random_bytes (str, n_bytes, error))
00560     return FALSE;
00561   
00562   len = _dbus_string_get_length (str);
00563   i = len - n_bytes;
00564   while (i < len)
00565     {
00566       _dbus_string_set_byte (str, i,
00567                              letters[_dbus_string_get_byte (str, i) %
00568                                      (sizeof (letters) - 1)]);
00569 
00570       ++i;
00571     }
00572 
00573   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
00574                                              n_bytes));
00575 
00576   return TRUE;
00577 }
00578 
00589 const char*
00590 _dbus_error_from_errno (int error_number)
00591 {
00592   switch (error_number)
00593     {
00594     case 0:
00595       return DBUS_ERROR_FAILED;
00596       
00597 #ifdef EPROTONOSUPPORT
00598     case EPROTONOSUPPORT:
00599       return DBUS_ERROR_NOT_SUPPORTED;
00600 #elif defined(WSAEPROTONOSUPPORT)
00601     case WSAEPROTONOSUPPORT:
00602       return DBUS_ERROR_NOT_SUPPORTED;
00603 #endif
00604 #ifdef EAFNOSUPPORT
00605     case EAFNOSUPPORT:
00606       return DBUS_ERROR_NOT_SUPPORTED;
00607 #elif defined(WSAEAFNOSUPPORT)
00608     case WSAEAFNOSUPPORT:
00609       return DBUS_ERROR_NOT_SUPPORTED;
00610 #endif
00611 #ifdef ENFILE
00612     case ENFILE:
00613       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
00614 #endif
00615 #ifdef EMFILE
00616     case EMFILE:
00617       return DBUS_ERROR_LIMITS_EXCEEDED;
00618 #endif
00619 #ifdef EACCES
00620     case EACCES:
00621       return DBUS_ERROR_ACCESS_DENIED;
00622 #endif
00623 #ifdef EPERM
00624     case EPERM:
00625       return DBUS_ERROR_ACCESS_DENIED;
00626 #endif
00627 #ifdef ENOBUFS
00628     case ENOBUFS:
00629       return DBUS_ERROR_NO_MEMORY;
00630 #endif
00631 #ifdef ENOMEM
00632     case ENOMEM:
00633       return DBUS_ERROR_NO_MEMORY;
00634 #endif
00635 #ifdef ECONNREFUSED
00636     case ECONNREFUSED:
00637       return DBUS_ERROR_NO_SERVER;
00638 #elif defined(WSAECONNREFUSED)
00639     case WSAECONNREFUSED:
00640       return DBUS_ERROR_NO_SERVER;
00641 #endif
00642 #ifdef ETIMEDOUT
00643     case ETIMEDOUT:
00644       return DBUS_ERROR_TIMEOUT;
00645 #elif defined(WSAETIMEDOUT)
00646     case WSAETIMEDOUT:
00647       return DBUS_ERROR_TIMEOUT;
00648 #endif
00649 #ifdef ENETUNREACH
00650     case ENETUNREACH:
00651       return DBUS_ERROR_NO_NETWORK;
00652 #elif defined(WSAENETUNREACH)
00653     case WSAENETUNREACH:
00654       return DBUS_ERROR_NO_NETWORK;
00655 #endif
00656 #ifdef EADDRINUSE
00657     case EADDRINUSE:
00658       return DBUS_ERROR_ADDRESS_IN_USE;
00659 #elif defined(WSAEADDRINUSE)
00660     case WSAEADDRINUSE:
00661       return DBUS_ERROR_ADDRESS_IN_USE;
00662 #endif
00663 #ifdef EEXIST
00664     case EEXIST:
00665       return DBUS_ERROR_FILE_EXISTS;
00666 #endif
00667 #ifdef ENOENT
00668     case ENOENT:
00669       return DBUS_ERROR_FILE_NOT_FOUND;
00670 #endif
00671     }
00672 
00673   return DBUS_ERROR_FAILED;
00674 }
00675 
00681 const char*
00682 _dbus_error_from_system_errno (void)
00683 {
00684   return _dbus_error_from_errno (errno);
00685 }
00686 
00690 void
00691 _dbus_set_errno_to_zero (void)
00692 {
00693 #ifdef DBUS_WINCE
00694   SetLastError (0);
00695 #else
00696   errno = 0;
00697 #endif
00698 }
00699 
00704 dbus_bool_t
00705 _dbus_get_is_errno_enomem (int e)
00706 {
00707   return e == ENOMEM;
00708 }
00709 
00714 dbus_bool_t
00715 _dbus_get_is_errno_eintr (int e)
00716 {
00717   return e == EINTR;
00718 }
00719 
00724 dbus_bool_t
00725 _dbus_get_is_errno_epipe (int e)
00726 {
00727   return e == EPIPE;
00728 }
00729 
00734 dbus_bool_t
00735 _dbus_get_is_errno_etoomanyrefs (int e)
00736 {
00737 #ifdef ETOOMANYREFS
00738   return e == ETOOMANYREFS;
00739 #else
00740   return FALSE;
00741 #endif
00742 }
00743 
00748 const char*
00749 _dbus_strerror_from_errno (void)
00750 {
00751   return _dbus_strerror (errno);
00752 }
00753 
00756 /* tests in dbus-sysdeps-util.c */