00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00033
00034
00035
00036
00037
00038 #if HAVE_LOCALE_H
00039 #include <locale.h>
00040 #endif
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include <stdio.h>
00044
00045 #ifdef HAVE_ERRNO_H
00046 #include <errno.h>
00047 #endif
00048
00049 _DBUS_DEFINE_GLOBAL_LOCK (win_fds);
00050 _DBUS_DEFINE_GLOBAL_LOCK (sid_atom_cache);
00051 _DBUS_DEFINE_GLOBAL_LOCK (system_users);
00052
00053 #ifdef DBUS_WIN
00054 #include <stdlib.h>
00055 #elif (defined __APPLE__)
00056 # include <crt_externs.h>
00057 # define environ (*_NSGetEnviron())
00058 #else
00059 extern char **environ;
00060 #endif
00061
00079 void
00080 _dbus_abort (void)
00081 {
00082 const char *s;
00083
00084 _dbus_print_backtrace ();
00085
00086 s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
00087 if (s && *s)
00088 {
00089
00090 fprintf (stderr, " Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
00091 _dbus_sleep_milliseconds (1000 * 180);
00092 }
00093
00094 abort ();
00095 _dbus_exit (1);
00096 }
00097
00111 dbus_bool_t
00112 _dbus_setenv (const char *varname,
00113 const char *value)
00114 {
00115 _dbus_assert (varname != NULL);
00116
00117 if (value == NULL)
00118 {
00119 #ifdef HAVE_UNSETENV
00120 unsetenv (varname);
00121 return TRUE;
00122 #else
00123 char *putenv_value;
00124 size_t len;
00125
00126 len = strlen (varname);
00127
00128
00129
00130
00131
00132 putenv_value = malloc (len + 2);
00133 if (putenv_value == NULL)
00134 return FALSE;
00135
00136 strcpy (putenv_value, varname);
00137 #if defined(DBUS_WIN)
00138 strcat (putenv_value, "=");
00139 #endif
00140
00141 return (putenv (putenv_value) == 0);
00142 #endif
00143 }
00144 else
00145 {
00146 #ifdef HAVE_SETENV
00147 return (setenv (varname, value, TRUE) == 0);
00148 #else
00149 char *putenv_value;
00150 size_t len;
00151 size_t varname_len;
00152 size_t value_len;
00153
00154 varname_len = strlen (varname);
00155 value_len = strlen (value);
00156
00157 len = varname_len + value_len + 1 ;
00158
00159
00160
00161
00162
00163 putenv_value = malloc (len + 1);
00164 if (putenv_value == NULL)
00165 return FALSE;
00166
00167 strcpy (putenv_value, varname);
00168 strcpy (putenv_value + varname_len, "=");
00169 strcpy (putenv_value + varname_len + 1, value);
00170
00171 return (putenv (putenv_value) == 0);
00172 #endif
00173 }
00174 }
00175
00182 const char*
00183 _dbus_getenv (const char *varname)
00184 {
00185
00186
00187
00188 if (_dbus_check_setuid ())
00189 return NULL;
00190 return getenv (varname);
00191 }
00192
00198 dbus_bool_t
00199 _dbus_clearenv (void)
00200 {
00201 dbus_bool_t rc = TRUE;
00202
00203 #ifdef HAVE_CLEARENV
00204 if (clearenv () != 0)
00205 rc = FALSE;
00206 #else
00207
00208 if (environ != NULL)
00209 environ[0] = NULL;
00210 #endif
00211
00212 return rc;
00213 }
00214
00221 char **
00222 _dbus_get_environment (void)
00223 {
00224 int i, length;
00225 char **environment;
00226
00227 _dbus_assert (environ != NULL);
00228
00229 for (length = 0; environ[length] != NULL; length++);
00230
00231
00232 length++;
00233
00234 environment = dbus_new0 (char *, length);
00235
00236 if (environment == NULL)
00237 return NULL;
00238
00239 for (i = 0; environ[i] != NULL; i++)
00240 {
00241 environment[i] = _dbus_strdup (environ[i]);
00242
00243 if (environment[i] == NULL)
00244 break;
00245 }
00246
00247 if (environ[i] != NULL)
00248 {
00249 dbus_free_string_array (environment);
00250 environment = NULL;
00251 }
00252
00253 return environment;
00254 }
00255
00264 dbus_bool_t
00265 _dbus_split_paths_and_append (DBusString *dirs,
00266 const char *suffix,
00267 DBusList **dir_list)
00268 {
00269 int start;
00270 int i;
00271 int len;
00272 char *cpath;
00273 DBusString file_suffix;
00274
00275 start = 0;
00276 i = 0;
00277
00278 _dbus_string_init_const (&file_suffix, suffix);
00279
00280 len = _dbus_string_get_length (dirs);
00281
00282 while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
00283 {
00284 DBusString path;
00285
00286 if (!_dbus_string_init (&path))
00287 goto oom;
00288
00289 if (!_dbus_string_copy_len (dirs,
00290 start,
00291 i - start,
00292 &path,
00293 0))
00294 {
00295 _dbus_string_free (&path);
00296 goto oom;
00297 }
00298
00299 _dbus_string_chop_white (&path);
00300
00301
00302 if (_dbus_string_get_length (&path) == 0)
00303 goto next;
00304
00305 if (!_dbus_concat_dir_and_file (&path,
00306 &file_suffix))
00307 {
00308 _dbus_string_free (&path);
00309 goto oom;
00310 }
00311
00312 if (!_dbus_string_copy_data(&path, &cpath))
00313 {
00314 _dbus_string_free (&path);
00315 goto oom;
00316 }
00317
00318 if (!_dbus_list_append (dir_list, cpath))
00319 {
00320 _dbus_string_free (&path);
00321 dbus_free (cpath);
00322 goto oom;
00323 }
00324
00325 next:
00326 _dbus_string_free (&path);
00327 start = i + 1;
00328 }
00329
00330 if (start != len)
00331 {
00332 DBusString path;
00333
00334 if (!_dbus_string_init (&path))
00335 goto oom;
00336
00337 if (!_dbus_string_copy_len (dirs,
00338 start,
00339 len - start,
00340 &path,
00341 0))
00342 {
00343 _dbus_string_free (&path);
00344 goto oom;
00345 }
00346
00347 if (!_dbus_concat_dir_and_file (&path,
00348 &file_suffix))
00349 {
00350 _dbus_string_free (&path);
00351 goto oom;
00352 }
00353
00354 if (!_dbus_string_copy_data(&path, &cpath))
00355 {
00356 _dbus_string_free (&path);
00357 goto oom;
00358 }
00359
00360 if (!_dbus_list_append (dir_list, cpath))
00361 {
00362 _dbus_string_free (&path);
00363 dbus_free (cpath);
00364 goto oom;
00365 }
00366
00367 _dbus_string_free (&path);
00368 }
00369
00370 return TRUE;
00371
00372 oom:
00373 _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL);
00374 _dbus_list_clear (dir_list);
00375 return FALSE;
00376 }
00377
00392 dbus_bool_t
00393 _dbus_string_append_int (DBusString *str,
00394 long value)
00395 {
00396
00397 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
00398 int orig_len;
00399 int i;
00400 char *buf;
00401
00402 orig_len = _dbus_string_get_length (str);
00403
00404 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00405 return FALSE;
00406
00407 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00408
00409 snprintf (buf, MAX_LONG_LEN, "%ld", value);
00410
00411 i = 0;
00412 while (*buf)
00413 {
00414 ++buf;
00415 ++i;
00416 }
00417
00418 _dbus_string_shorten (str, MAX_LONG_LEN - i);
00419
00420 return TRUE;
00421 }
00422
00430 dbus_bool_t
00431 _dbus_string_append_uint (DBusString *str,
00432 unsigned long value)
00433 {
00434
00435 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
00436 int orig_len;
00437 int i;
00438 char *buf;
00439
00440 orig_len = _dbus_string_get_length (str);
00441
00442 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
00443 return FALSE;
00444
00445 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
00446
00447 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
00448
00449 i = 0;
00450 while (*buf)
00451 {
00452 ++buf;
00453 ++i;
00454 }
00455
00456 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
00457
00458 return TRUE;
00459 }
00460
00461 #ifdef DBUS_BUILD_TESTS
00462
00469 dbus_bool_t
00470 _dbus_string_append_double (DBusString *str,
00471 double value)
00472 {
00473 #define MAX_DOUBLE_LEN 64
00474 int orig_len;
00475 char *buf;
00476 int i;
00477
00478 orig_len = _dbus_string_get_length (str);
00479
00480 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
00481 return FALSE;
00482
00483 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
00484
00485 snprintf (buf, MAX_LONG_LEN, "%g", value);
00486
00487 i = 0;
00488 while (*buf)
00489 {
00490 ++buf;
00491 ++i;
00492 }
00493
00494 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
00495
00496 return TRUE;
00497 }
00498 #endif
00499
00512 dbus_bool_t
00513 _dbus_string_parse_int (const DBusString *str,
00514 int start,
00515 long *value_return,
00516 int *end_return)
00517 {
00518 long v;
00519 const char *p;
00520 char *end;
00521
00522 p = _dbus_string_get_const_data_len (str, start,
00523 _dbus_string_get_length (str) - start);
00524
00525 end = NULL;
00526 _dbus_set_errno_to_zero ();
00527 v = strtol (p, &end, 0);
00528 if (end == NULL || end == p || errno != 0)
00529 return FALSE;
00530
00531 if (value_return)
00532 *value_return = v;
00533 if (end_return)
00534 *end_return = start + (end - p);
00535
00536 return TRUE;
00537 }
00538
00551 dbus_bool_t
00552 _dbus_string_parse_uint (const DBusString *str,
00553 int start,
00554 unsigned long *value_return,
00555 int *end_return)
00556 {
00557 unsigned long v;
00558 const char *p;
00559 char *end;
00560
00561 p = _dbus_string_get_const_data_len (str, start,
00562 _dbus_string_get_length (str) - start);
00563
00564 end = NULL;
00565 _dbus_set_errno_to_zero ();
00566 v = strtoul (p, &end, 0);
00567 if (end == NULL || end == p || errno != 0)
00568 return FALSE;
00569
00570 if (value_return)
00571 *value_return = v;
00572 if (end_return)
00573 *end_return = start + (end - p);
00574
00575 return TRUE;
00576 }
00577
00578 #ifdef DBUS_BUILD_TESTS
00579 static dbus_bool_t
00580 ascii_isspace (char c)
00581 {
00582 return (c == ' ' ||
00583 c == '\f' ||
00584 c == '\n' ||
00585 c == '\r' ||
00586 c == '\t' ||
00587 c == '\v');
00588 }
00589 #endif
00590
00591 #ifdef DBUS_BUILD_TESTS
00592 static dbus_bool_t
00593 ascii_isdigit (char c)
00594 {
00595 return c >= '0' && c <= '9';
00596 }
00597 #endif
00598
00599 #ifdef DBUS_BUILD_TESTS
00600 static dbus_bool_t
00601 ascii_isxdigit (char c)
00602 {
00603 return (ascii_isdigit (c) ||
00604 (c >= 'a' && c <= 'f') ||
00605 (c >= 'A' && c <= 'F'));
00606 }
00607 #endif
00608
00609 #ifdef DBUS_BUILD_TESTS
00610
00611
00612
00613
00614
00615 static double
00616 ascii_strtod (const char *nptr,
00617 char **endptr)
00618 {
00619
00620
00621
00622
00623 char *fail_pos;
00624 double val;
00625 struct lconv *locale_data;
00626 const char *decimal_point;
00627 int decimal_point_len;
00628 const char *p, *decimal_point_pos;
00629 const char *end = NULL;
00630
00631 fail_pos = NULL;
00632
00633 #if HAVE_LOCALECONV
00634 locale_data = localeconv ();
00635 decimal_point = locale_data->decimal_point;
00636 #else
00637 decimal_point = ".";
00638 #endif
00639
00640 decimal_point_len = strlen (decimal_point);
00641 _dbus_assert (decimal_point_len != 0);
00642
00643 decimal_point_pos = NULL;
00644 if (decimal_point[0] != '.' ||
00645 decimal_point[1] != 0)
00646 {
00647 p = nptr;
00648
00649 while (ascii_isspace (*p))
00650 p++;
00651
00652
00653 if (*p == '+' || *p == '-')
00654 p++;
00655
00656 if (p[0] == '0' &&
00657 (p[1] == 'x' || p[1] == 'X'))
00658 {
00659 p += 2;
00660
00661
00662 while (ascii_isxdigit (*p))
00663 p++;
00664
00665 if (*p == '.')
00666 {
00667 decimal_point_pos = p++;
00668
00669 while (ascii_isxdigit (*p))
00670 p++;
00671
00672 if (*p == 'p' || *p == 'P')
00673 p++;
00674 if (*p == '+' || *p == '-')
00675 p++;
00676 while (ascii_isdigit (*p))
00677 p++;
00678 end = p;
00679 }
00680 }
00681 else
00682 {
00683 while (ascii_isdigit (*p))
00684 p++;
00685
00686 if (*p == '.')
00687 {
00688 decimal_point_pos = p++;
00689
00690 while (ascii_isdigit (*p))
00691 p++;
00692
00693 if (*p == 'e' || *p == 'E')
00694 p++;
00695 if (*p == '+' || *p == '-')
00696 p++;
00697 while (ascii_isdigit (*p))
00698 p++;
00699 end = p;
00700 }
00701 }
00702
00703 }
00704
00705
00706
00707 _dbus_set_errno_to_zero ();
00708
00709 if (decimal_point_pos)
00710 {
00711 char *copy, *c;
00712
00713
00714 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
00715
00716 c = copy;
00717 memcpy (c, nptr, decimal_point_pos - nptr);
00718 c += decimal_point_pos - nptr;
00719 memcpy (c, decimal_point, decimal_point_len);
00720 c += decimal_point_len;
00721 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
00722 c += end - (decimal_point_pos + 1);
00723 *c = 0;
00724
00725 val = strtod (copy, &fail_pos);
00726
00727 if (fail_pos)
00728 {
00729 if (fail_pos > decimal_point_pos)
00730 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
00731 else
00732 fail_pos = (char *)nptr + (fail_pos - copy);
00733 }
00734
00735 dbus_free (copy);
00736
00737 }
00738 else
00739 val = strtod (nptr, &fail_pos);
00740
00741 if (endptr)
00742 *endptr = fail_pos;
00743
00744 return val;
00745 }
00746 #endif
00747
00748 #ifdef DBUS_BUILD_TESTS
00749
00761 dbus_bool_t
00762 _dbus_string_parse_double (const DBusString *str,
00763 int start,
00764 double *value_return,
00765 int *end_return)
00766 {
00767 double v;
00768 const char *p;
00769 char *end;
00770
00771 p = _dbus_string_get_const_data_len (str, start,
00772 _dbus_string_get_length (str) - start);
00773
00774
00775
00776
00777 if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
00778 return FALSE;
00779
00780 end = NULL;
00781 _dbus_set_errno_to_zero ();
00782 v = ascii_strtod (p, &end);
00783 if (end == NULL || end == p || errno != 0)
00784 return FALSE;
00785
00786 if (value_return)
00787 *value_return = v;
00788 if (end_return)
00789 *end_return = start + (end - p);
00790
00791 return TRUE;
00792 }
00793 #endif
00794
00796
00802 void
00803 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
00804 int n_bytes)
00805 {
00806 long tv_usec;
00807 int i;
00808
00809
00810 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
00811 n_bytes);
00812
00813 _dbus_get_current_time (NULL, &tv_usec);
00814 srand (tv_usec);
00815
00816 i = 0;
00817 while (i < n_bytes)
00818 {
00819 double r;
00820 unsigned int b;
00821
00822 r = rand ();
00823 b = (r / (double) RAND_MAX) * 255.0;
00824
00825 buffer[i] = b;
00826
00827 ++i;
00828 }
00829 }
00830
00837 void
00838 _dbus_generate_random_bytes_buffer (char *buffer,
00839 int n_bytes)
00840 {
00841 DBusString str;
00842
00843 if (!_dbus_string_init (&str))
00844 {
00845 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00846 return;
00847 }
00848
00849 if (!_dbus_generate_random_bytes (&str, n_bytes))
00850 {
00851 _dbus_string_free (&str);
00852 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00853 return;
00854 }
00855
00856 _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
00857
00858 _dbus_string_free (&str);
00859 }
00860
00869 dbus_bool_t
00870 _dbus_generate_random_ascii (DBusString *str,
00871 int n_bytes)
00872 {
00873 static const char letters[] =
00874 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
00875 int i;
00876 int len;
00877
00878 if (!_dbus_generate_random_bytes (str, n_bytes))
00879 return FALSE;
00880
00881 len = _dbus_string_get_length (str);
00882 i = len - n_bytes;
00883 while (i < len)
00884 {
00885 _dbus_string_set_byte (str, i,
00886 letters[_dbus_string_get_byte (str, i) %
00887 (sizeof (letters) - 1)]);
00888
00889 ++i;
00890 }
00891
00892 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
00893 n_bytes));
00894
00895 return TRUE;
00896 }
00897
00908 const char*
00909 _dbus_error_from_errno (int error_number)
00910 {
00911 switch (error_number)
00912 {
00913 case 0:
00914 return DBUS_ERROR_FAILED;
00915
00916 #ifdef EPROTONOSUPPORT
00917 case EPROTONOSUPPORT:
00918 return DBUS_ERROR_NOT_SUPPORTED;
00919 #endif
00920 #ifdef WSAEPROTONOSUPPORT
00921 case WSAEPROTONOSUPPORT:
00922 return DBUS_ERROR_NOT_SUPPORTED;
00923 #endif
00924 #ifdef EAFNOSUPPORT
00925 case EAFNOSUPPORT:
00926 return DBUS_ERROR_NOT_SUPPORTED;
00927 #endif
00928 #ifdef WSAEAFNOSUPPORT
00929 case WSAEAFNOSUPPORT:
00930 return DBUS_ERROR_NOT_SUPPORTED;
00931 #endif
00932 #ifdef ENFILE
00933 case ENFILE:
00934 return DBUS_ERROR_LIMITS_EXCEEDED;
00935 #endif
00936 #ifdef EMFILE
00937 case EMFILE:
00938 return DBUS_ERROR_LIMITS_EXCEEDED;
00939 #endif
00940 #ifdef EACCES
00941 case EACCES:
00942 return DBUS_ERROR_ACCESS_DENIED;
00943 #endif
00944 #ifdef EPERM
00945 case EPERM:
00946 return DBUS_ERROR_ACCESS_DENIED;
00947 #endif
00948 #ifdef ENOBUFS
00949 case ENOBUFS:
00950 return DBUS_ERROR_NO_MEMORY;
00951 #endif
00952 #ifdef ENOMEM
00953 case ENOMEM:
00954 return DBUS_ERROR_NO_MEMORY;
00955 #endif
00956 #ifdef ECONNREFUSED
00957 case ECONNREFUSED:
00958 return DBUS_ERROR_NO_SERVER;
00959 #endif
00960 #ifdef WSAECONNREFUSED
00961 case WSAECONNREFUSED:
00962 return DBUS_ERROR_NO_SERVER;
00963 #endif
00964 #ifdef ETIMEDOUT
00965 case ETIMEDOUT:
00966 return DBUS_ERROR_TIMEOUT;
00967 #endif
00968 #ifdef WSAETIMEDOUT
00969 case WSAETIMEDOUT:
00970 return DBUS_ERROR_TIMEOUT;
00971 #endif
00972 #ifdef ENETUNREACH
00973 case ENETUNREACH:
00974 return DBUS_ERROR_NO_NETWORK;
00975 #endif
00976 #ifdef WSAENETUNREACH
00977 case WSAENETUNREACH:
00978 return DBUS_ERROR_NO_NETWORK;
00979 #endif
00980 #ifdef EADDRINUSE
00981 case EADDRINUSE:
00982 return DBUS_ERROR_ADDRESS_IN_USE;
00983 #endif
00984 #ifdef WSAEADDRINUSE
00985 case WSAEADDRINUSE:
00986 return DBUS_ERROR_ADDRESS_IN_USE;
00987 #endif
00988 #ifdef EEXIST
00989 case EEXIST:
00990 return DBUS_ERROR_FILE_EXISTS;
00991 #endif
00992 #ifdef ENOENT
00993 case ENOENT:
00994 return DBUS_ERROR_FILE_NOT_FOUND;
00995 #endif
00996 }
00997
00998 return DBUS_ERROR_FAILED;
00999 }
01000
01006 const char*
01007 _dbus_error_from_system_errno (void)
01008 {
01009 return _dbus_error_from_errno (errno);
01010 }
01011
01015 void
01016 _dbus_set_errno_to_zero (void)
01017 {
01018 #ifdef DBUS_WINCE
01019 SetLastError (0);
01020 #else
01021 errno = 0;
01022 #endif
01023 }
01024
01029 dbus_bool_t
01030 _dbus_get_is_errno_nonzero (void)
01031 {
01032 return errno != 0;
01033 }
01034
01039 dbus_bool_t
01040 _dbus_get_is_errno_enomem (void)
01041 {
01042 return errno == ENOMEM;
01043 }
01044
01049 dbus_bool_t
01050 _dbus_get_is_errno_eintr (void)
01051 {
01052 return errno == EINTR;
01053 }
01054
01059 dbus_bool_t
01060 _dbus_get_is_errno_epipe (void)
01061 {
01062 return errno == EPIPE;
01063 }
01064
01069 dbus_bool_t
01070 _dbus_get_is_errno_etoomanyrefs (void)
01071 {
01072 #ifdef ETOOMANYREFS
01073 return errno == ETOOMANYREFS;
01074 #else
01075 return FALSE;
01076 #endif
01077 }
01078
01083 const char*
01084 _dbus_strerror_from_errno (void)
01085 {
01086 return _dbus_strerror (errno);
01087 }
01088
01091