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 "dbus-internals.h"
00026 #include "dbus-sysdeps.h"
00027 #include "dbus-threads.h"
00028 #include "dbus-protocol.h"
00029 #include "dbus-string.h"
00030
00031
00032
00033
00034
00035
00036 #include <locale.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <stdio.h>
00040
00041
00042
00043
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
00056 #ifndef DBUS_DISABLE_ASSERT
00057
00060 void
00061 _dbus_abort (void)
00062 {
00063 #ifdef DBUS_ENABLE_VERBOSE_MODE
00064 const char *s;
00065 s = _dbus_getenv ("DBUS_PRINT_BACKTRACE");
00066 if (s && *s)
00067 _dbus_print_backtrace ();
00068 #endif
00069 abort ();
00070 _dbus_exit (1);
00071 }
00072 #endif
00073
00087 dbus_bool_t
00088 _dbus_setenv (const char *varname,
00089 const char *value)
00090 {
00091 _dbus_assert (varname != NULL);
00092
00093 if (value == NULL)
00094 {
00095 #ifdef HAVE_UNSETENV
00096 unsetenv (varname);
00097 return TRUE;
00098 #else
00099 char *putenv_value;
00100 size_t len;
00101
00102 len = strlen (varname);
00103
00104
00105
00106
00107
00108 putenv_value = malloc (len + 1);
00109 if (putenv_value == NULL)
00110 return FALSE;
00111
00112 strcpy (putenv_value, varname);
00113
00114 return (putenv (putenv_value) == 0);
00115 #endif
00116 }
00117 else
00118 {
00119 #ifdef HAVE_SETENV
00120 return (setenv (varname, value, TRUE) == 0);
00121 #else
00122 char *putenv_value;
00123 size_t len;
00124 size_t varname_len;
00125 size_t value_len;
00126
00127 varname_len = strlen (varname);
00128 value_len = strlen (value);
00129
00130 len = varname_len + value_len + 1 ;
00131
00132
00133
00134
00135
00136 putenv_value = malloc (len + 1);
00137 if (putenv_value == NULL)
00138 return FALSE;
00139
00140 strcpy (putenv_value, varname);
00141 strcpy (putenv_value + varname_len, "=");
00142 strcpy (putenv_value + varname_len + 1, value);
00143
00144 return (putenv (putenv_value) == 0);
00145 #endif
00146 }
00147 }
00148
00155 const char*
00156 _dbus_getenv (const char *varname)
00157 {
00158 return getenv (varname);
00159 }
00160
00175 dbus_bool_t
00176 _dbus_string_append_int (DBusString *str,
00177 long value)
00178 {
00179
00180 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
00181 int orig_len;
00182 int i;
00183 char *buf;
00184
00185 orig_len = _dbus_string_get_length (str);
00186
00187 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00188 return FALSE;
00189
00190 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00191
00192 snprintf (buf, MAX_LONG_LEN, "%ld", value);
00193
00194 i = 0;
00195 while (*buf)
00196 {
00197 ++buf;
00198 ++i;
00199 }
00200
00201 _dbus_string_shorten (str, MAX_LONG_LEN - i);
00202
00203 return TRUE;
00204 }
00205
00213 dbus_bool_t
00214 _dbus_string_append_uint (DBusString *str,
00215 unsigned long value)
00216 {
00217
00218 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
00219 int orig_len;
00220 int i;
00221 char *buf;
00222
00223 orig_len = _dbus_string_get_length (str);
00224
00225 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
00226 return FALSE;
00227
00228 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
00229
00230 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
00231
00232 i = 0;
00233 while (*buf)
00234 {
00235 ++buf;
00236 ++i;
00237 }
00238
00239 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
00240
00241 return TRUE;
00242 }
00243
00244 #ifdef DBUS_BUILD_TESTS
00245
00252 dbus_bool_t
00253 _dbus_string_append_double (DBusString *str,
00254 double value)
00255 {
00256 #define MAX_DOUBLE_LEN 64
00257 int orig_len;
00258 char *buf;
00259 int i;
00260
00261 orig_len = _dbus_string_get_length (str);
00262
00263 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
00264 return FALSE;
00265
00266 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
00267
00268 snprintf (buf, MAX_LONG_LEN, "%g", value);
00269
00270 i = 0;
00271 while (*buf)
00272 {
00273 ++buf;
00274 ++i;
00275 }
00276
00277 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
00278
00279 return TRUE;
00280 }
00281 #endif
00282
00295 dbus_bool_t
00296 _dbus_string_parse_int (const DBusString *str,
00297 int start,
00298 long *value_return,
00299 int *end_return)
00300 {
00301 long v;
00302 const char *p;
00303 char *end;
00304
00305 p = _dbus_string_get_const_data_len (str, start,
00306 _dbus_string_get_length (str) - start);
00307
00308 end = NULL;
00309 errno = 0;
00310 v = strtol (p, &end, 0);
00311 if (end == NULL || end == p || errno != 0)
00312 return FALSE;
00313
00314 if (value_return)
00315 *value_return = v;
00316 if (end_return)
00317 *end_return = start + (end - p);
00318
00319 return TRUE;
00320 }
00321
00334 dbus_bool_t
00335 _dbus_string_parse_uint (const DBusString *str,
00336 int start,
00337 unsigned long *value_return,
00338 int *end_return)
00339 {
00340 unsigned long v;
00341 const char *p;
00342 char *end;
00343
00344 p = _dbus_string_get_const_data_len (str, start,
00345 _dbus_string_get_length (str) - start);
00346
00347 end = NULL;
00348 errno = 0;
00349 v = strtoul (p, &end, 0);
00350 if (end == NULL || end == p || errno != 0)
00351 return FALSE;
00352
00353 if (value_return)
00354 *value_return = v;
00355 if (end_return)
00356 *end_return = start + (end - p);
00357
00358 return TRUE;
00359 }
00360
00361 #ifdef DBUS_BUILD_TESTS
00362 static dbus_bool_t
00363 ascii_isspace (char c)
00364 {
00365 return (c == ' ' ||
00366 c == '\f' ||
00367 c == '\n' ||
00368 c == '\r' ||
00369 c == '\t' ||
00370 c == '\v');
00371 }
00372 #endif
00373
00374 #ifdef DBUS_BUILD_TESTS
00375 static dbus_bool_t
00376 ascii_isdigit (char c)
00377 {
00378 return c >= '0' && c <= '9';
00379 }
00380 #endif
00381
00382 #ifdef DBUS_BUILD_TESTS
00383 static dbus_bool_t
00384 ascii_isxdigit (char c)
00385 {
00386 return (ascii_isdigit (c) ||
00387 (c >= 'a' && c <= 'f') ||
00388 (c >= 'A' && c <= 'F'));
00389 }
00390 #endif
00391
00392 #ifdef DBUS_BUILD_TESTS
00393
00394
00395
00396
00397
00398 static double
00399 ascii_strtod (const char *nptr,
00400 char **endptr)
00401 {
00402 char *fail_pos;
00403 double val;
00404 struct lconv *locale_data;
00405 const char *decimal_point;
00406 int decimal_point_len;
00407 const char *p, *decimal_point_pos;
00408 const char *end = NULL;
00409
00410 fail_pos = NULL;
00411
00412 locale_data = localeconv ();
00413 decimal_point = locale_data->decimal_point;
00414 decimal_point_len = strlen (decimal_point);
00415
00416 _dbus_assert (decimal_point_len != 0);
00417
00418 decimal_point_pos = NULL;
00419 if (decimal_point[0] != '.' ||
00420 decimal_point[1] != 0)
00421 {
00422 p = nptr;
00423
00424 while (ascii_isspace (*p))
00425 p++;
00426
00427
00428 if (*p == '+' || *p == '-')
00429 p++;
00430
00431 if (p[0] == '0' &&
00432 (p[1] == 'x' || p[1] == 'X'))
00433 {
00434 p += 2;
00435
00436
00437 while (ascii_isxdigit (*p))
00438 p++;
00439
00440 if (*p == '.')
00441 {
00442 decimal_point_pos = p++;
00443
00444 while (ascii_isxdigit (*p))
00445 p++;
00446
00447 if (*p == 'p' || *p == 'P')
00448 p++;
00449 if (*p == '+' || *p == '-')
00450 p++;
00451 while (ascii_isdigit (*p))
00452 p++;
00453 end = p;
00454 }
00455 }
00456 else
00457 {
00458 while (ascii_isdigit (*p))
00459 p++;
00460
00461 if (*p == '.')
00462 {
00463 decimal_point_pos = p++;
00464
00465 while (ascii_isdigit (*p))
00466 p++;
00467
00468 if (*p == 'e' || *p == 'E')
00469 p++;
00470 if (*p == '+' || *p == '-')
00471 p++;
00472 while (ascii_isdigit (*p))
00473 p++;
00474 end = p;
00475 }
00476 }
00477
00478 }
00479
00480
00481
00482 errno = 0;
00483
00484 if (decimal_point_pos)
00485 {
00486 char *copy, *c;
00487
00488
00489 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
00490
00491 c = copy;
00492 memcpy (c, nptr, decimal_point_pos - nptr);
00493 c += decimal_point_pos - nptr;
00494 memcpy (c, decimal_point, decimal_point_len);
00495 c += decimal_point_len;
00496 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
00497 c += end - (decimal_point_pos + 1);
00498 *c = 0;
00499
00500 val = strtod (copy, &fail_pos);
00501
00502 if (fail_pos)
00503 {
00504 if (fail_pos > decimal_point_pos)
00505 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
00506 else
00507 fail_pos = (char *)nptr + (fail_pos - copy);
00508 }
00509
00510 dbus_free (copy);
00511
00512 }
00513 else
00514 val = strtod (nptr, &fail_pos);
00515
00516 if (endptr)
00517 *endptr = fail_pos;
00518
00519 return val;
00520 }
00521 #endif
00522
00523 #ifdef DBUS_BUILD_TESTS
00524
00536 dbus_bool_t
00537 _dbus_string_parse_double (const DBusString *str,
00538 int start,
00539 double *value_return,
00540 int *end_return)
00541 {
00542 double v;
00543 const char *p;
00544 char *end;
00545
00546 p = _dbus_string_get_const_data_len (str, start,
00547 _dbus_string_get_length (str) - start);
00548
00549 end = NULL;
00550 errno = 0;
00551 v = ascii_strtod (p, &end);
00552 if (end == NULL || end == p || errno != 0)
00553 return FALSE;
00554
00555 if (value_return)
00556 *value_return = v;
00557 if (end_return)
00558 *end_return = start + (end - p);
00559
00560 return TRUE;
00561 }
00562 #endif
00563
00565
00576 void
00577 _dbus_user_info_free (DBusUserInfo *info)
00578 {
00579 dbus_free (info->group_ids);
00580 dbus_free (info->username);
00581 dbus_free (info->homedir);
00582 }
00583
00589 void
00590 _dbus_group_info_free (DBusGroupInfo *info)
00591 {
00592 dbus_free (info->groupname);
00593 }
00594
00601 void
00602 _dbus_credentials_clear (DBusCredentials *credentials)
00603 {
00604 credentials->pid = DBUS_PID_UNSET;
00605 credentials->uid = DBUS_UID_UNSET;
00606 credentials->gid = DBUS_GID_UNSET;
00607 }
00608
00617 dbus_bool_t
00618 _dbus_credentials_match (const DBusCredentials *expected_credentials,
00619 const DBusCredentials *provided_credentials)
00620 {
00621 if (provided_credentials->uid == DBUS_UID_UNSET)
00622 return FALSE;
00623 else if (expected_credentials->uid == DBUS_UID_UNSET)
00624 return FALSE;
00625 else if (provided_credentials->uid == 0)
00626 return TRUE;
00627 else if (provided_credentials->uid == expected_credentials->uid)
00628 return TRUE;
00629 else
00630 return FALSE;
00631 }
00632
00633 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
00634
00635 #ifdef DBUS_USE_ATOMIC_INT_486
00636
00637
00638 static inline dbus_int32_t
00639 atomic_exchange_and_add (DBusAtomic *atomic,
00640 volatile dbus_int32_t val)
00641 {
00642 register dbus_int32_t result;
00643
00644 __asm__ __volatile__ ("lock; xaddl %0,%1"
00645 : "=r" (result), "=m" (atomic->value)
00646 : "0" (val), "m" (atomic->value));
00647 return result;
00648 }
00649 #endif
00650
00659 dbus_int32_t
00660 _dbus_atomic_inc (DBusAtomic *atomic)
00661 {
00662 #ifdef DBUS_USE_ATOMIC_INT_486
00663 return atomic_exchange_and_add (atomic, 1);
00664 #else
00665 dbus_int32_t res;
00666 _DBUS_LOCK (atomic);
00667 res = atomic->value;
00668 atomic->value += 1;
00669 _DBUS_UNLOCK (atomic);
00670 return res;
00671 #endif
00672 }
00673
00682 dbus_int32_t
00683 _dbus_atomic_dec (DBusAtomic *atomic)
00684 {
00685 #ifdef DBUS_USE_ATOMIC_INT_486
00686 return atomic_exchange_and_add (atomic, -1);
00687 #else
00688 dbus_int32_t res;
00689
00690 _DBUS_LOCK (atomic);
00691 res = atomic->value;
00692 atomic->value -= 1;
00693 _DBUS_UNLOCK (atomic);
00694 return res;
00695 #endif
00696 }
00697
00698 void
00699 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
00700 int n_bytes)
00701 {
00702 long tv_usec;
00703 int i;
00704
00705
00706 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
00707 n_bytes);
00708
00709 _dbus_get_current_time (NULL, &tv_usec);
00710 srand (tv_usec);
00711
00712 i = 0;
00713 while (i < n_bytes)
00714 {
00715 double r;
00716 unsigned int b;
00717
00718 r = rand ();
00719 b = (r / (double) RAND_MAX) * 255.0;
00720
00721 buffer[i] = b;
00722
00723 ++i;
00724 }
00725 }
00726
00733 void
00734 _dbus_generate_random_bytes_buffer (char *buffer,
00735 int n_bytes)
00736 {
00737 DBusString str;
00738
00739 if (!_dbus_string_init (&str))
00740 {
00741 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00742 return;
00743 }
00744
00745 if (!_dbus_generate_random_bytes (&str, n_bytes))
00746 {
00747 _dbus_string_free (&str);
00748 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00749 return;
00750 }
00751
00752 _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
00753
00754 _dbus_string_free (&str);
00755 }
00756
00765 dbus_bool_t
00766 _dbus_generate_random_ascii (DBusString *str,
00767 int n_bytes)
00768 {
00769 static const char letters[] =
00770 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
00771 int i;
00772 int len;
00773
00774 if (!_dbus_generate_random_bytes (str, n_bytes))
00775 return FALSE;
00776
00777 len = _dbus_string_get_length (str);
00778 i = len - n_bytes;
00779 while (i < len)
00780 {
00781 _dbus_string_set_byte (str, i,
00782 letters[_dbus_string_get_byte (str, i) %
00783 (sizeof (letters) - 1)]);
00784
00785 ++i;
00786 }
00787
00788 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
00789 n_bytes));
00790
00791 return TRUE;
00792 }
00793
00801 dbus_bool_t
00802 _dbus_parse_uid (const DBusString *uid_str,
00803 dbus_uid_t *uid)
00804 {
00805 int end;
00806 long val;
00807
00808 if (_dbus_string_get_length (uid_str) == 0)
00809 {
00810 _dbus_verbose ("UID string was zero length\n");
00811 return FALSE;
00812 }
00813
00814 val = -1;
00815 end = 0;
00816 if (!_dbus_string_parse_int (uid_str, 0, &val,
00817 &end))
00818 {
00819 _dbus_verbose ("could not parse string as a UID\n");
00820 return FALSE;
00821 }
00822
00823 if (end != _dbus_string_get_length (uid_str))
00824 {
00825 _dbus_verbose ("string contained trailing stuff after UID\n");
00826 return FALSE;
00827 }
00828
00829 *uid = val;
00830
00831 return TRUE;
00832 }
00833
00844 const char*
00845 _dbus_error_from_errno (int error_number)
00846 {
00847 switch (error_number)
00848 {
00849 case 0:
00850 return DBUS_ERROR_FAILED;
00851
00852 #ifdef EPROTONOSUPPORT
00853 case EPROTONOSUPPORT:
00854 return DBUS_ERROR_NOT_SUPPORTED;
00855 #endif
00856 #ifdef EAFNOSUPPORT
00857 case EAFNOSUPPORT:
00858 return DBUS_ERROR_NOT_SUPPORTED;
00859 #endif
00860 #ifdef ENFILE
00861 case ENFILE:
00862 return DBUS_ERROR_LIMITS_EXCEEDED;
00863 #endif
00864 #ifdef EMFILE
00865 case EMFILE:
00866 return DBUS_ERROR_LIMITS_EXCEEDED;
00867 #endif
00868 #ifdef EACCES
00869 case EACCES:
00870 return DBUS_ERROR_ACCESS_DENIED;
00871 #endif
00872 #ifdef EPERM
00873 case EPERM:
00874 return DBUS_ERROR_ACCESS_DENIED;
00875 #endif
00876 #ifdef ENOBUFS
00877 case ENOBUFS:
00878 return DBUS_ERROR_NO_MEMORY;
00879 #endif
00880 #ifdef ENOMEM
00881 case ENOMEM:
00882 return DBUS_ERROR_NO_MEMORY;
00883 #endif
00884 #ifdef EINVAL
00885 case EINVAL:
00886 return DBUS_ERROR_FAILED;
00887 #endif
00888 #ifdef EBADF
00889 case EBADF:
00890 return DBUS_ERROR_FAILED;
00891 #endif
00892 #ifdef EFAULT
00893 case EFAULT:
00894 return DBUS_ERROR_FAILED;
00895 #endif
00896 #ifdef ENOTSOCK
00897 case ENOTSOCK:
00898 return DBUS_ERROR_FAILED;
00899 #endif
00900 #ifdef EISCONN
00901 case EISCONN:
00902 return DBUS_ERROR_FAILED;
00903 #endif
00904 #ifdef ECONNREFUSED
00905 case ECONNREFUSED:
00906 return DBUS_ERROR_NO_SERVER;
00907 #endif
00908 #ifdef ETIMEDOUT
00909 case ETIMEDOUT:
00910 return DBUS_ERROR_TIMEOUT;
00911 #endif
00912 #ifdef ENETUNREACH
00913 case ENETUNREACH:
00914 return DBUS_ERROR_NO_NETWORK;
00915 #endif
00916 #ifdef EADDRINUSE
00917 case EADDRINUSE:
00918 return DBUS_ERROR_ADDRESS_IN_USE;
00919 #endif
00920 #ifdef EEXIST
00921 case EEXIST:
00922 return DBUS_ERROR_FILE_NOT_FOUND;
00923 #endif
00924 #ifdef ENOENT
00925 case ENOENT:
00926 return DBUS_ERROR_FILE_NOT_FOUND;
00927 #endif
00928 }
00929
00930 return DBUS_ERROR_FAILED;
00931 }
00932
00935