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 return getenv (varname);
00186 }
00187
00193 dbus_bool_t
00194 _dbus_clearenv (void)
00195 {
00196 dbus_bool_t rc = TRUE;
00197
00198 #ifdef HAVE_CLEARENV
00199 if (clearenv () != 0)
00200 rc = FALSE;
00201 #else
00202
00203 if (environ != NULL)
00204 environ[0] = NULL;
00205 #endif
00206
00207 return rc;
00208 }
00209
00216 char **
00217 _dbus_get_environment (void)
00218 {
00219 int i, length;
00220 char **environment;
00221
00222 _dbus_assert (environ != NULL);
00223
00224 for (length = 0; environ[length] != NULL; length++);
00225
00226
00227 length++;
00228
00229 environment = dbus_new0 (char *, length);
00230
00231 if (environment == NULL)
00232 return NULL;
00233
00234 for (i = 0; environ[i] != NULL; i++)
00235 {
00236 environment[i] = _dbus_strdup (environ[i]);
00237
00238 if (environment[i] == NULL)
00239 break;
00240 }
00241
00242 if (environ[i] != NULL)
00243 {
00244 dbus_free_string_array (environment);
00245 environment = NULL;
00246 }
00247
00248 return environment;
00249 }
00250
00259 dbus_bool_t
00260 _dbus_split_paths_and_append (DBusString *dirs,
00261 const char *suffix,
00262 DBusList **dir_list)
00263 {
00264 int start;
00265 int i;
00266 int len;
00267 char *cpath;
00268 DBusString file_suffix;
00269
00270 start = 0;
00271 i = 0;
00272
00273 _dbus_string_init_const (&file_suffix, suffix);
00274
00275 len = _dbus_string_get_length (dirs);
00276
00277 while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
00278 {
00279 DBusString path;
00280
00281 if (!_dbus_string_init (&path))
00282 goto oom;
00283
00284 if (!_dbus_string_copy_len (dirs,
00285 start,
00286 i - start,
00287 &path,
00288 0))
00289 {
00290 _dbus_string_free (&path);
00291 goto oom;
00292 }
00293
00294 _dbus_string_chop_white (&path);
00295
00296
00297 if (_dbus_string_get_length (&path) == 0)
00298 goto next;
00299
00300 if (!_dbus_concat_dir_and_file (&path,
00301 &file_suffix))
00302 {
00303 _dbus_string_free (&path);
00304 goto oom;
00305 }
00306
00307 if (!_dbus_string_copy_data(&path, &cpath))
00308 {
00309 _dbus_string_free (&path);
00310 goto oom;
00311 }
00312
00313 if (!_dbus_list_append (dir_list, cpath))
00314 {
00315 _dbus_string_free (&path);
00316 dbus_free (cpath);
00317 goto oom;
00318 }
00319
00320 next:
00321 _dbus_string_free (&path);
00322 start = i + 1;
00323 }
00324
00325 if (start != len)
00326 {
00327 DBusString path;
00328
00329 if (!_dbus_string_init (&path))
00330 goto oom;
00331
00332 if (!_dbus_string_copy_len (dirs,
00333 start,
00334 len - start,
00335 &path,
00336 0))
00337 {
00338 _dbus_string_free (&path);
00339 goto oom;
00340 }
00341
00342 if (!_dbus_concat_dir_and_file (&path,
00343 &file_suffix))
00344 {
00345 _dbus_string_free (&path);
00346 goto oom;
00347 }
00348
00349 if (!_dbus_string_copy_data(&path, &cpath))
00350 {
00351 _dbus_string_free (&path);
00352 goto oom;
00353 }
00354
00355 if (!_dbus_list_append (dir_list, cpath))
00356 {
00357 _dbus_string_free (&path);
00358 dbus_free (cpath);
00359 goto oom;
00360 }
00361
00362 _dbus_string_free (&path);
00363 }
00364
00365 return TRUE;
00366
00367 oom:
00368 _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL);
00369 _dbus_list_clear (dir_list);
00370 return FALSE;
00371 }
00372
00387 dbus_bool_t
00388 _dbus_string_append_int (DBusString *str,
00389 long value)
00390 {
00391
00392 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
00393 int orig_len;
00394 int i;
00395 char *buf;
00396
00397 orig_len = _dbus_string_get_length (str);
00398
00399 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00400 return FALSE;
00401
00402 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00403
00404 snprintf (buf, MAX_LONG_LEN, "%ld", value);
00405
00406 i = 0;
00407 while (*buf)
00408 {
00409 ++buf;
00410 ++i;
00411 }
00412
00413 _dbus_string_shorten (str, MAX_LONG_LEN - i);
00414
00415 return TRUE;
00416 }
00417
00425 dbus_bool_t
00426 _dbus_string_append_uint (DBusString *str,
00427 unsigned long value)
00428 {
00429
00430 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
00431 int orig_len;
00432 int i;
00433 char *buf;
00434
00435 orig_len = _dbus_string_get_length (str);
00436
00437 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
00438 return FALSE;
00439
00440 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
00441
00442 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
00443
00444 i = 0;
00445 while (*buf)
00446 {
00447 ++buf;
00448 ++i;
00449 }
00450
00451 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
00452
00453 return TRUE;
00454 }
00455
00456 #ifdef DBUS_BUILD_TESTS
00457
00464 dbus_bool_t
00465 _dbus_string_append_double (DBusString *str,
00466 double value)
00467 {
00468 #define MAX_DOUBLE_LEN 64
00469 int orig_len;
00470 char *buf;
00471 int i;
00472
00473 orig_len = _dbus_string_get_length (str);
00474
00475 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
00476 return FALSE;
00477
00478 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
00479
00480 snprintf (buf, MAX_LONG_LEN, "%g", value);
00481
00482 i = 0;
00483 while (*buf)
00484 {
00485 ++buf;
00486 ++i;
00487 }
00488
00489 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
00490
00491 return TRUE;
00492 }
00493 #endif
00494
00507 dbus_bool_t
00508 _dbus_string_parse_int (const DBusString *str,
00509 int start,
00510 long *value_return,
00511 int *end_return)
00512 {
00513 long v;
00514 const char *p;
00515 char *end;
00516
00517 p = _dbus_string_get_const_data_len (str, start,
00518 _dbus_string_get_length (str) - start);
00519
00520 end = NULL;
00521 _dbus_set_errno_to_zero ();
00522 v = strtol (p, &end, 0);
00523 if (end == NULL || end == p || errno != 0)
00524 return FALSE;
00525
00526 if (value_return)
00527 *value_return = v;
00528 if (end_return)
00529 *end_return = start + (end - p);
00530
00531 return TRUE;
00532 }
00533
00546 dbus_bool_t
00547 _dbus_string_parse_uint (const DBusString *str,
00548 int start,
00549 unsigned long *value_return,
00550 int *end_return)
00551 {
00552 unsigned long v;
00553 const char *p;
00554 char *end;
00555
00556 p = _dbus_string_get_const_data_len (str, start,
00557 _dbus_string_get_length (str) - start);
00558
00559 end = NULL;
00560 _dbus_set_errno_to_zero ();
00561 v = strtoul (p, &end, 0);
00562 if (end == NULL || end == p || errno != 0)
00563 return FALSE;
00564
00565 if (value_return)
00566 *value_return = v;
00567 if (end_return)
00568 *end_return = start + (end - p);
00569
00570 return TRUE;
00571 }
00572
00573 #ifdef DBUS_BUILD_TESTS
00574 static dbus_bool_t
00575 ascii_isspace (char c)
00576 {
00577 return (c == ' ' ||
00578 c == '\f' ||
00579 c == '\n' ||
00580 c == '\r' ||
00581 c == '\t' ||
00582 c == '\v');
00583 }
00584 #endif
00585
00586 #ifdef DBUS_BUILD_TESTS
00587 static dbus_bool_t
00588 ascii_isdigit (char c)
00589 {
00590 return c >= '0' && c <= '9';
00591 }
00592 #endif
00593
00594 #ifdef DBUS_BUILD_TESTS
00595 static dbus_bool_t
00596 ascii_isxdigit (char c)
00597 {
00598 return (ascii_isdigit (c) ||
00599 (c >= 'a' && c <= 'f') ||
00600 (c >= 'A' && c <= 'F'));
00601 }
00602 #endif
00603
00604 #ifdef DBUS_BUILD_TESTS
00605
00606
00607
00608
00609
00610 static double
00611 ascii_strtod (const char *nptr,
00612 char **endptr)
00613 {
00614
00615
00616
00617
00618 char *fail_pos;
00619 double val;
00620 struct lconv *locale_data;
00621 const char *decimal_point;
00622 int decimal_point_len;
00623 const char *p, *decimal_point_pos;
00624 const char *end = NULL;
00625
00626 fail_pos = NULL;
00627
00628 #if HAVE_LOCALECONV
00629 locale_data = localeconv ();
00630 decimal_point = locale_data->decimal_point;
00631 #else
00632 decimal_point = ".";
00633 #endif
00634
00635 decimal_point_len = strlen (decimal_point);
00636 _dbus_assert (decimal_point_len != 0);
00637
00638 decimal_point_pos = NULL;
00639 if (decimal_point[0] != '.' ||
00640 decimal_point[1] != 0)
00641 {
00642 p = nptr;
00643
00644 while (ascii_isspace (*p))
00645 p++;
00646
00647
00648 if (*p == '+' || *p == '-')
00649 p++;
00650
00651 if (p[0] == '0' &&
00652 (p[1] == 'x' || p[1] == 'X'))
00653 {
00654 p += 2;
00655
00656
00657 while (ascii_isxdigit (*p))
00658 p++;
00659
00660 if (*p == '.')
00661 {
00662 decimal_point_pos = p++;
00663
00664 while (ascii_isxdigit (*p))
00665 p++;
00666
00667 if (*p == 'p' || *p == 'P')
00668 p++;
00669 if (*p == '+' || *p == '-')
00670 p++;
00671 while (ascii_isdigit (*p))
00672 p++;
00673 end = p;
00674 }
00675 }
00676 else
00677 {
00678 while (ascii_isdigit (*p))
00679 p++;
00680
00681 if (*p == '.')
00682 {
00683 decimal_point_pos = p++;
00684
00685 while (ascii_isdigit (*p))
00686 p++;
00687
00688 if (*p == 'e' || *p == 'E')
00689 p++;
00690 if (*p == '+' || *p == '-')
00691 p++;
00692 while (ascii_isdigit (*p))
00693 p++;
00694 end = p;
00695 }
00696 }
00697
00698 }
00699
00700
00701
00702 _dbus_set_errno_to_zero ();
00703
00704 if (decimal_point_pos)
00705 {
00706 char *copy, *c;
00707
00708
00709 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
00710
00711 c = copy;
00712 memcpy (c, nptr, decimal_point_pos - nptr);
00713 c += decimal_point_pos - nptr;
00714 memcpy (c, decimal_point, decimal_point_len);
00715 c += decimal_point_len;
00716 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
00717 c += end - (decimal_point_pos + 1);
00718 *c = 0;
00719
00720 val = strtod (copy, &fail_pos);
00721
00722 if (fail_pos)
00723 {
00724 if (fail_pos > decimal_point_pos)
00725 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
00726 else
00727 fail_pos = (char *)nptr + (fail_pos - copy);
00728 }
00729
00730 dbus_free (copy);
00731
00732 }
00733 else
00734 val = strtod (nptr, &fail_pos);
00735
00736 if (endptr)
00737 *endptr = fail_pos;
00738
00739 return val;
00740 }
00741 #endif
00742
00743 #ifdef DBUS_BUILD_TESTS
00744
00756 dbus_bool_t
00757 _dbus_string_parse_double (const DBusString *str,
00758 int start,
00759 double *value_return,
00760 int *end_return)
00761 {
00762 double v;
00763 const char *p;
00764 char *end;
00765
00766 p = _dbus_string_get_const_data_len (str, start,
00767 _dbus_string_get_length (str) - start);
00768
00769
00770
00771
00772 if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
00773 return FALSE;
00774
00775 end = NULL;
00776 _dbus_set_errno_to_zero ();
00777 v = ascii_strtod (p, &end);
00778 if (end == NULL || end == p || errno != 0)
00779 return FALSE;
00780
00781 if (value_return)
00782 *value_return = v;
00783 if (end_return)
00784 *end_return = start + (end - p);
00785
00786 return TRUE;
00787 }
00788 #endif
00789
00791
00797 void
00798 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
00799 int n_bytes)
00800 {
00801 long tv_usec;
00802 int i;
00803
00804
00805 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
00806 n_bytes);
00807
00808 _dbus_get_current_time (NULL, &tv_usec);
00809 srand (tv_usec);
00810
00811 i = 0;
00812 while (i < n_bytes)
00813 {
00814 double r;
00815 unsigned int b;
00816
00817 r = rand ();
00818 b = (r / (double) RAND_MAX) * 255.0;
00819
00820 buffer[i] = b;
00821
00822 ++i;
00823 }
00824 }
00825
00832 void
00833 _dbus_generate_random_bytes_buffer (char *buffer,
00834 int n_bytes)
00835 {
00836 DBusString str;
00837
00838 if (!_dbus_string_init (&str))
00839 {
00840 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00841 return;
00842 }
00843
00844 if (!_dbus_generate_random_bytes (&str, n_bytes))
00845 {
00846 _dbus_string_free (&str);
00847 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00848 return;
00849 }
00850
00851 _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
00852
00853 _dbus_string_free (&str);
00854 }
00855
00864 dbus_bool_t
00865 _dbus_generate_random_ascii (DBusString *str,
00866 int n_bytes)
00867 {
00868 static const char letters[] =
00869 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
00870 int i;
00871 int len;
00872
00873 if (!_dbus_generate_random_bytes (str, n_bytes))
00874 return FALSE;
00875
00876 len = _dbus_string_get_length (str);
00877 i = len - n_bytes;
00878 while (i < len)
00879 {
00880 _dbus_string_set_byte (str, i,
00881 letters[_dbus_string_get_byte (str, i) %
00882 (sizeof (letters) - 1)]);
00883
00884 ++i;
00885 }
00886
00887 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
00888 n_bytes));
00889
00890 return TRUE;
00891 }
00892
00903 const char*
00904 _dbus_error_from_errno (int error_number)
00905 {
00906 switch (error_number)
00907 {
00908 case 0:
00909 return DBUS_ERROR_FAILED;
00910
00911 #ifdef EPROTONOSUPPORT
00912 case EPROTONOSUPPORT:
00913 return DBUS_ERROR_NOT_SUPPORTED;
00914 #endif
00915 #ifdef WSAEPROTONOSUPPORT
00916 case WSAEPROTONOSUPPORT:
00917 return DBUS_ERROR_NOT_SUPPORTED;
00918 #endif
00919 #ifdef EAFNOSUPPORT
00920 case EAFNOSUPPORT:
00921 return DBUS_ERROR_NOT_SUPPORTED;
00922 #endif
00923 #ifdef WSAEAFNOSUPPORT
00924 case WSAEAFNOSUPPORT:
00925 return DBUS_ERROR_NOT_SUPPORTED;
00926 #endif
00927 #ifdef ENFILE
00928 case ENFILE:
00929 return DBUS_ERROR_LIMITS_EXCEEDED;
00930 #endif
00931 #ifdef EMFILE
00932 case EMFILE:
00933 return DBUS_ERROR_LIMITS_EXCEEDED;
00934 #endif
00935 #ifdef EACCES
00936 case EACCES:
00937 return DBUS_ERROR_ACCESS_DENIED;
00938 #endif
00939 #ifdef EPERM
00940 case EPERM:
00941 return DBUS_ERROR_ACCESS_DENIED;
00942 #endif
00943 #ifdef ENOBUFS
00944 case ENOBUFS:
00945 return DBUS_ERROR_NO_MEMORY;
00946 #endif
00947 #ifdef ENOMEM
00948 case ENOMEM:
00949 return DBUS_ERROR_NO_MEMORY;
00950 #endif
00951 #ifdef ECONNREFUSED
00952 case ECONNREFUSED:
00953 return DBUS_ERROR_NO_SERVER;
00954 #endif
00955 #ifdef WSAECONNREFUSED
00956 case WSAECONNREFUSED:
00957 return DBUS_ERROR_NO_SERVER;
00958 #endif
00959 #ifdef ETIMEDOUT
00960 case ETIMEDOUT:
00961 return DBUS_ERROR_TIMEOUT;
00962 #endif
00963 #ifdef WSAETIMEDOUT
00964 case WSAETIMEDOUT:
00965 return DBUS_ERROR_TIMEOUT;
00966 #endif
00967 #ifdef ENETUNREACH
00968 case ENETUNREACH:
00969 return DBUS_ERROR_NO_NETWORK;
00970 #endif
00971 #ifdef WSAENETUNREACH
00972 case WSAENETUNREACH:
00973 return DBUS_ERROR_NO_NETWORK;
00974 #endif
00975 #ifdef EADDRINUSE
00976 case EADDRINUSE:
00977 return DBUS_ERROR_ADDRESS_IN_USE;
00978 #endif
00979 #ifdef WSAEADDRINUSE
00980 case WSAEADDRINUSE:
00981 return DBUS_ERROR_ADDRESS_IN_USE;
00982 #endif
00983 #ifdef EEXIST
00984 case EEXIST:
00985 return DBUS_ERROR_FILE_EXISTS;
00986 #endif
00987 #ifdef ENOENT
00988 case ENOENT:
00989 return DBUS_ERROR_FILE_NOT_FOUND;
00990 #endif
00991 }
00992
00993 return DBUS_ERROR_FAILED;
00994 }
00995
01001 const char*
01002 _dbus_error_from_system_errno (void)
01003 {
01004 return _dbus_error_from_errno (errno);
01005 }
01006
01010 void
01011 _dbus_set_errno_to_zero (void)
01012 {
01013 #ifdef DBUS_WINCE
01014 SetLastError (0);
01015 #else
01016 errno = 0;
01017 #endif
01018 }
01019
01024 dbus_bool_t
01025 _dbus_get_is_errno_nonzero (void)
01026 {
01027 return errno != 0;
01028 }
01029
01034 dbus_bool_t
01035 _dbus_get_is_errno_enomem (void)
01036 {
01037 return errno == ENOMEM;
01038 }
01039
01044 dbus_bool_t
01045 _dbus_get_is_errno_eintr (void)
01046 {
01047 return errno == EINTR;
01048 }
01049
01054 dbus_bool_t
01055 _dbus_get_is_errno_epipe (void)
01056 {
01057 return errno == EPIPE;
01058 }
01059
01064 const char*
01065 _dbus_strerror_from_errno (void)
01066 {
01067 return _dbus_strerror (errno);
01068 }
01069
01072