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
00069 void
00070 _dbus_abort (void)
00071 {
00072 const char *s;
00073
00074 _dbus_print_backtrace ();
00075
00076 s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
00077 if (s && *s)
00078 {
00079
00080 fprintf (stderr, " Process %lu sleeping for gdb attach\n", (unsigned long) _dbus_getpid());
00081 _dbus_sleep_milliseconds (1000 * 180);
00082 }
00083
00084 abort ();
00085 _dbus_exit (1);
00086 }
00087
00101 dbus_bool_t
00102 _dbus_setenv (const char *varname,
00103 const char *value)
00104 {
00105 _dbus_assert (varname != NULL);
00106
00107 if (value == NULL)
00108 {
00109 #ifdef HAVE_UNSETENV
00110 unsetenv (varname);
00111 return TRUE;
00112 #else
00113 char *putenv_value;
00114 size_t len;
00115
00116 len = strlen (varname);
00117
00118
00119
00120
00121
00122 putenv_value = malloc (len + 1);
00123 if (putenv_value == NULL)
00124 return FALSE;
00125
00126 strcpy (putenv_value, varname);
00127
00128 return (putenv (putenv_value) == 0);
00129 #endif
00130 }
00131 else
00132 {
00133 #ifdef HAVE_SETENV
00134 return (setenv (varname, value, TRUE) == 0);
00135 #else
00136 char *putenv_value;
00137 size_t len;
00138 size_t varname_len;
00139 size_t value_len;
00140
00141 varname_len = strlen (varname);
00142 value_len = strlen (value);
00143
00144 len = varname_len + value_len + 1 ;
00145
00146
00147
00148
00149
00150 putenv_value = malloc (len + 1);
00151 if (putenv_value == NULL)
00152 return FALSE;
00153
00154 strcpy (putenv_value, varname);
00155 strcpy (putenv_value + varname_len, "=");
00156 strcpy (putenv_value + varname_len + 1, value);
00157
00158 return (putenv (putenv_value) == 0);
00159 #endif
00160 }
00161 }
00162
00169 const char*
00170 _dbus_getenv (const char *varname)
00171 {
00172
00173
00174
00175 if (_dbus_check_setuid ())
00176 return NULL;
00177 return getenv (varname);
00178 }
00179
00194 dbus_bool_t
00195 _dbus_string_append_int (DBusString *str,
00196 long value)
00197 {
00198
00199 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
00200 int orig_len;
00201 int i;
00202 char *buf;
00203
00204 orig_len = _dbus_string_get_length (str);
00205
00206 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00207 return FALSE;
00208
00209 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00210
00211 snprintf (buf, MAX_LONG_LEN, "%ld", value);
00212
00213 i = 0;
00214 while (*buf)
00215 {
00216 ++buf;
00217 ++i;
00218 }
00219
00220 _dbus_string_shorten (str, MAX_LONG_LEN - i);
00221
00222 return TRUE;
00223 }
00224
00232 dbus_bool_t
00233 _dbus_string_append_uint (DBusString *str,
00234 unsigned long value)
00235 {
00236
00237 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
00238 int orig_len;
00239 int i;
00240 char *buf;
00241
00242 orig_len = _dbus_string_get_length (str);
00243
00244 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
00245 return FALSE;
00246
00247 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
00248
00249 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
00250
00251 i = 0;
00252 while (*buf)
00253 {
00254 ++buf;
00255 ++i;
00256 }
00257
00258 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
00259
00260 return TRUE;
00261 }
00262
00263 #ifdef DBUS_BUILD_TESTS
00264
00271 dbus_bool_t
00272 _dbus_string_append_double (DBusString *str,
00273 double value)
00274 {
00275 #define MAX_DOUBLE_LEN 64
00276 int orig_len;
00277 char *buf;
00278 int i;
00279
00280 orig_len = _dbus_string_get_length (str);
00281
00282 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
00283 return FALSE;
00284
00285 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
00286
00287 snprintf (buf, MAX_LONG_LEN, "%g", value);
00288
00289 i = 0;
00290 while (*buf)
00291 {
00292 ++buf;
00293 ++i;
00294 }
00295
00296 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
00297
00298 return TRUE;
00299 }
00300 #endif
00301
00314 dbus_bool_t
00315 _dbus_string_parse_int (const DBusString *str,
00316 int start,
00317 long *value_return,
00318 int *end_return)
00319 {
00320 long v;
00321 const char *p;
00322 char *end;
00323
00324 p = _dbus_string_get_const_data_len (str, start,
00325 _dbus_string_get_length (str) - start);
00326
00327 end = NULL;
00328 errno = 0;
00329 v = strtol (p, &end, 0);
00330 if (end == NULL || end == p || errno != 0)
00331 return FALSE;
00332
00333 if (value_return)
00334 *value_return = v;
00335 if (end_return)
00336 *end_return = start + (end - p);
00337
00338 return TRUE;
00339 }
00340
00353 dbus_bool_t
00354 _dbus_string_parse_uint (const DBusString *str,
00355 int start,
00356 unsigned long *value_return,
00357 int *end_return)
00358 {
00359 unsigned long v;
00360 const char *p;
00361 char *end;
00362
00363 p = _dbus_string_get_const_data_len (str, start,
00364 _dbus_string_get_length (str) - start);
00365
00366 end = NULL;
00367 errno = 0;
00368 v = strtoul (p, &end, 0);
00369 if (end == NULL || end == p || errno != 0)
00370 return FALSE;
00371
00372 if (value_return)
00373 *value_return = v;
00374 if (end_return)
00375 *end_return = start + (end - p);
00376
00377 return TRUE;
00378 }
00379
00380 #ifdef DBUS_BUILD_TESTS
00381 static dbus_bool_t
00382 ascii_isspace (char c)
00383 {
00384 return (c == ' ' ||
00385 c == '\f' ||
00386 c == '\n' ||
00387 c == '\r' ||
00388 c == '\t' ||
00389 c == '\v');
00390 }
00391 #endif
00392
00393 #ifdef DBUS_BUILD_TESTS
00394 static dbus_bool_t
00395 ascii_isdigit (char c)
00396 {
00397 return c >= '0' && c <= '9';
00398 }
00399 #endif
00400
00401 #ifdef DBUS_BUILD_TESTS
00402 static dbus_bool_t
00403 ascii_isxdigit (char c)
00404 {
00405 return (ascii_isdigit (c) ||
00406 (c >= 'a' && c <= 'f') ||
00407 (c >= 'A' && c <= 'F'));
00408 }
00409 #endif
00410
00411 #ifdef DBUS_BUILD_TESTS
00412
00413
00414
00415
00416
00417 static double
00418 ascii_strtod (const char *nptr,
00419 char **endptr)
00420 {
00421 char *fail_pos;
00422 double val;
00423 struct lconv *locale_data;
00424 const char *decimal_point;
00425 int decimal_point_len;
00426 const char *p, *decimal_point_pos;
00427 const char *end = NULL;
00428
00429 fail_pos = NULL;
00430
00431 locale_data = localeconv ();
00432 decimal_point = locale_data->decimal_point;
00433 decimal_point_len = strlen (decimal_point);
00434
00435 _dbus_assert (decimal_point_len != 0);
00436
00437 decimal_point_pos = NULL;
00438 if (decimal_point[0] != '.' ||
00439 decimal_point[1] != 0)
00440 {
00441 p = nptr;
00442
00443 while (ascii_isspace (*p))
00444 p++;
00445
00446
00447 if (*p == '+' || *p == '-')
00448 p++;
00449
00450 if (p[0] == '0' &&
00451 (p[1] == 'x' || p[1] == 'X'))
00452 {
00453 p += 2;
00454
00455
00456 while (ascii_isxdigit (*p))
00457 p++;
00458
00459 if (*p == '.')
00460 {
00461 decimal_point_pos = p++;
00462
00463 while (ascii_isxdigit (*p))
00464 p++;
00465
00466 if (*p == 'p' || *p == 'P')
00467 p++;
00468 if (*p == '+' || *p == '-')
00469 p++;
00470 while (ascii_isdigit (*p))
00471 p++;
00472 end = p;
00473 }
00474 }
00475 else
00476 {
00477 while (ascii_isdigit (*p))
00478 p++;
00479
00480 if (*p == '.')
00481 {
00482 decimal_point_pos = p++;
00483
00484 while (ascii_isdigit (*p))
00485 p++;
00486
00487 if (*p == 'e' || *p == 'E')
00488 p++;
00489 if (*p == '+' || *p == '-')
00490 p++;
00491 while (ascii_isdigit (*p))
00492 p++;
00493 end = p;
00494 }
00495 }
00496
00497 }
00498
00499
00500
00501 errno = 0;
00502
00503 if (decimal_point_pos)
00504 {
00505 char *copy, *c;
00506
00507
00508 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
00509
00510 c = copy;
00511 memcpy (c, nptr, decimal_point_pos - nptr);
00512 c += decimal_point_pos - nptr;
00513 memcpy (c, decimal_point, decimal_point_len);
00514 c += decimal_point_len;
00515 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
00516 c += end - (decimal_point_pos + 1);
00517 *c = 0;
00518
00519 val = strtod (copy, &fail_pos);
00520
00521 if (fail_pos)
00522 {
00523 if (fail_pos > decimal_point_pos)
00524 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
00525 else
00526 fail_pos = (char *)nptr + (fail_pos - copy);
00527 }
00528
00529 dbus_free (copy);
00530
00531 }
00532 else
00533 val = strtod (nptr, &fail_pos);
00534
00535 if (endptr)
00536 *endptr = fail_pos;
00537
00538 return val;
00539 }
00540 #endif
00541
00542 #ifdef DBUS_BUILD_TESTS
00543
00555 dbus_bool_t
00556 _dbus_string_parse_double (const DBusString *str,
00557 int start,
00558 double *value_return,
00559 int *end_return)
00560 {
00561 double v;
00562 const char *p;
00563 char *end;
00564
00565 p = _dbus_string_get_const_data_len (str, start,
00566 _dbus_string_get_length (str) - start);
00567
00568 end = NULL;
00569 errno = 0;
00570 v = ascii_strtod (p, &end);
00571 if (end == NULL || end == p || errno != 0)
00572 return FALSE;
00573
00574 if (value_return)
00575 *value_return = v;
00576 if (end_return)
00577 *end_return = start + (end - p);
00578
00579 return TRUE;
00580 }
00581 #endif
00582
00584
00595 void
00596 _dbus_user_info_free (DBusUserInfo *info)
00597 {
00598 dbus_free (info->group_ids);
00599 dbus_free (info->username);
00600 dbus_free (info->homedir);
00601 }
00602
00608 void
00609 _dbus_group_info_free (DBusGroupInfo *info)
00610 {
00611 dbus_free (info->groupname);
00612 }
00613
00620 void
00621 _dbus_credentials_clear (DBusCredentials *credentials)
00622 {
00623 credentials->pid = DBUS_PID_UNSET;
00624 credentials->uid = DBUS_UID_UNSET;
00625 credentials->gid = DBUS_GID_UNSET;
00626 }
00627
00636 dbus_bool_t
00637 _dbus_credentials_match (const DBusCredentials *expected_credentials,
00638 const DBusCredentials *provided_credentials)
00639 {
00640 if (provided_credentials->uid == DBUS_UID_UNSET)
00641 return FALSE;
00642 else if (expected_credentials->uid == DBUS_UID_UNSET)
00643 return FALSE;
00644 else if (provided_credentials->uid == 0)
00645 return TRUE;
00646 else if (provided_credentials->uid == expected_credentials->uid)
00647 return TRUE;
00648 else
00649 return FALSE;
00650 }
00651
00652 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
00653
00654 #ifdef DBUS_USE_ATOMIC_INT_486
00655
00656
00657 static inline dbus_int32_t
00658 atomic_exchange_and_add (DBusAtomic *atomic,
00659 volatile dbus_int32_t val)
00660 {
00661 register dbus_int32_t result;
00662
00663 __asm__ __volatile__ ("lock; xaddl %0,%1"
00664 : "=r" (result), "=m" (atomic->value)
00665 : "0" (val), "m" (atomic->value));
00666 return result;
00667 }
00668 #endif
00669
00678 dbus_int32_t
00679 _dbus_atomic_inc (DBusAtomic *atomic)
00680 {
00681 #ifdef DBUS_USE_ATOMIC_INT_486
00682 return atomic_exchange_and_add (atomic, 1);
00683 #else
00684 dbus_int32_t res;
00685 _DBUS_LOCK (atomic);
00686 res = atomic->value;
00687 atomic->value += 1;
00688 _DBUS_UNLOCK (atomic);
00689 return res;
00690 #endif
00691 }
00692
00701 dbus_int32_t
00702 _dbus_atomic_dec (DBusAtomic *atomic)
00703 {
00704 #ifdef DBUS_USE_ATOMIC_INT_486
00705 return atomic_exchange_and_add (atomic, -1);
00706 #else
00707 dbus_int32_t res;
00708
00709 _DBUS_LOCK (atomic);
00710 res = atomic->value;
00711 atomic->value -= 1;
00712 _DBUS_UNLOCK (atomic);
00713 return res;
00714 #endif
00715 }
00716
00717 void
00718 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
00719 int n_bytes)
00720 {
00721 long tv_usec;
00722 int i;
00723
00724
00725 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
00726 n_bytes);
00727
00728 _dbus_get_current_time (NULL, &tv_usec);
00729 srand (tv_usec);
00730
00731 i = 0;
00732 while (i < n_bytes)
00733 {
00734 double r;
00735 unsigned int b;
00736
00737 r = rand ();
00738 b = (r / (double) RAND_MAX) * 255.0;
00739
00740 buffer[i] = b;
00741
00742 ++i;
00743 }
00744 }
00745
00752 void
00753 _dbus_generate_random_bytes_buffer (char *buffer,
00754 int n_bytes)
00755 {
00756 DBusString str;
00757
00758 if (!_dbus_string_init (&str))
00759 {
00760 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00761 return;
00762 }
00763
00764 if (!_dbus_generate_random_bytes (&str, n_bytes))
00765 {
00766 _dbus_string_free (&str);
00767 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00768 return;
00769 }
00770
00771 _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
00772
00773 _dbus_string_free (&str);
00774 }
00775
00784 dbus_bool_t
00785 _dbus_generate_random_ascii (DBusString *str,
00786 int n_bytes)
00787 {
00788 static const char letters[] =
00789 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
00790 int i;
00791 int len;
00792
00793 if (!_dbus_generate_random_bytes (str, n_bytes))
00794 return FALSE;
00795
00796 len = _dbus_string_get_length (str);
00797 i = len - n_bytes;
00798 while (i < len)
00799 {
00800 _dbus_string_set_byte (str, i,
00801 letters[_dbus_string_get_byte (str, i) %
00802 (sizeof (letters) - 1)]);
00803
00804 ++i;
00805 }
00806
00807 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
00808 n_bytes));
00809
00810 return TRUE;
00811 }
00812
00820 dbus_bool_t
00821 _dbus_parse_uid (const DBusString *uid_str,
00822 dbus_uid_t *uid)
00823 {
00824 int end;
00825 long val;
00826
00827 if (_dbus_string_get_length (uid_str) == 0)
00828 {
00829 _dbus_verbose ("UID string was zero length\n");
00830 return FALSE;
00831 }
00832
00833 val = -1;
00834 end = 0;
00835 if (!_dbus_string_parse_int (uid_str, 0, &val,
00836 &end))
00837 {
00838 _dbus_verbose ("could not parse string as a UID\n");
00839 return FALSE;
00840 }
00841
00842 if (end != _dbus_string_get_length (uid_str))
00843 {
00844 _dbus_verbose ("string contained trailing stuff after UID\n");
00845 return FALSE;
00846 }
00847
00848 *uid = val;
00849
00850 return TRUE;
00851 }
00852
00863 const char*
00864 _dbus_error_from_errno (int error_number)
00865 {
00866 switch (error_number)
00867 {
00868 case 0:
00869 return DBUS_ERROR_FAILED;
00870
00871 #ifdef EPROTONOSUPPORT
00872 case EPROTONOSUPPORT:
00873 return DBUS_ERROR_NOT_SUPPORTED;
00874 #endif
00875 #ifdef EAFNOSUPPORT
00876 case EAFNOSUPPORT:
00877 return DBUS_ERROR_NOT_SUPPORTED;
00878 #endif
00879 #ifdef ENFILE
00880 case ENFILE:
00881 return DBUS_ERROR_LIMITS_EXCEEDED;
00882 #endif
00883 #ifdef EMFILE
00884 case EMFILE:
00885 return DBUS_ERROR_LIMITS_EXCEEDED;
00886 #endif
00887 #ifdef EACCES
00888 case EACCES:
00889 return DBUS_ERROR_ACCESS_DENIED;
00890 #endif
00891 #ifdef EPERM
00892 case EPERM:
00893 return DBUS_ERROR_ACCESS_DENIED;
00894 #endif
00895 #ifdef ENOBUFS
00896 case ENOBUFS:
00897 return DBUS_ERROR_NO_MEMORY;
00898 #endif
00899 #ifdef ENOMEM
00900 case ENOMEM:
00901 return DBUS_ERROR_NO_MEMORY;
00902 #endif
00903 #ifdef EINVAL
00904 case EINVAL:
00905 return DBUS_ERROR_FAILED;
00906 #endif
00907 #ifdef EBADF
00908 case EBADF:
00909 return DBUS_ERROR_FAILED;
00910 #endif
00911 #ifdef EFAULT
00912 case EFAULT:
00913 return DBUS_ERROR_FAILED;
00914 #endif
00915 #ifdef ENOTSOCK
00916 case ENOTSOCK:
00917 return DBUS_ERROR_FAILED;
00918 #endif
00919 #ifdef EISCONN
00920 case EISCONN:
00921 return DBUS_ERROR_FAILED;
00922 #endif
00923 #ifdef ECONNREFUSED
00924 case ECONNREFUSED:
00925 return DBUS_ERROR_NO_SERVER;
00926 #endif
00927 #ifdef ETIMEDOUT
00928 case ETIMEDOUT:
00929 return DBUS_ERROR_TIMEOUT;
00930 #endif
00931 #ifdef ENETUNREACH
00932 case ENETUNREACH:
00933 return DBUS_ERROR_NO_NETWORK;
00934 #endif
00935 #ifdef EADDRINUSE
00936 case EADDRINUSE:
00937 return DBUS_ERROR_ADDRESS_IN_USE;
00938 #endif
00939 #ifdef EEXIST
00940 case EEXIST:
00941 return DBUS_ERROR_FILE_EXISTS;
00942 #endif
00943 #ifdef ENOENT
00944 case ENOENT:
00945 return DBUS_ERROR_FILE_NOT_FOUND;
00946 #endif
00947 }
00948
00949 return DBUS_ERROR_FAILED;
00950 }
00951
00954