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 return getenv (varname);
00173 }
00174
00189 dbus_bool_t
00190 _dbus_string_append_int (DBusString *str,
00191 long value)
00192 {
00193
00194 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
00195 int orig_len;
00196 int i;
00197 char *buf;
00198
00199 orig_len = _dbus_string_get_length (str);
00200
00201 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00202 return FALSE;
00203
00204 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00205
00206 snprintf (buf, MAX_LONG_LEN, "%ld", value);
00207
00208 i = 0;
00209 while (*buf)
00210 {
00211 ++buf;
00212 ++i;
00213 }
00214
00215 _dbus_string_shorten (str, MAX_LONG_LEN - i);
00216
00217 return TRUE;
00218 }
00219
00227 dbus_bool_t
00228 _dbus_string_append_uint (DBusString *str,
00229 unsigned long value)
00230 {
00231
00232 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
00233 int orig_len;
00234 int i;
00235 char *buf;
00236
00237 orig_len = _dbus_string_get_length (str);
00238
00239 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
00240 return FALSE;
00241
00242 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
00243
00244 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
00245
00246 i = 0;
00247 while (*buf)
00248 {
00249 ++buf;
00250 ++i;
00251 }
00252
00253 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
00254
00255 return TRUE;
00256 }
00257
00258 #ifdef DBUS_BUILD_TESTS
00259
00266 dbus_bool_t
00267 _dbus_string_append_double (DBusString *str,
00268 double value)
00269 {
00270 #define MAX_DOUBLE_LEN 64
00271 int orig_len;
00272 char *buf;
00273 int i;
00274
00275 orig_len = _dbus_string_get_length (str);
00276
00277 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
00278 return FALSE;
00279
00280 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
00281
00282 snprintf (buf, MAX_LONG_LEN, "%g", value);
00283
00284 i = 0;
00285 while (*buf)
00286 {
00287 ++buf;
00288 ++i;
00289 }
00290
00291 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
00292
00293 return TRUE;
00294 }
00295 #endif
00296
00309 dbus_bool_t
00310 _dbus_string_parse_int (const DBusString *str,
00311 int start,
00312 long *value_return,
00313 int *end_return)
00314 {
00315 long v;
00316 const char *p;
00317 char *end;
00318
00319 p = _dbus_string_get_const_data_len (str, start,
00320 _dbus_string_get_length (str) - start);
00321
00322 end = NULL;
00323 errno = 0;
00324 v = strtol (p, &end, 0);
00325 if (end == NULL || end == p || errno != 0)
00326 return FALSE;
00327
00328 if (value_return)
00329 *value_return = v;
00330 if (end_return)
00331 *end_return = start + (end - p);
00332
00333 return TRUE;
00334 }
00335
00348 dbus_bool_t
00349 _dbus_string_parse_uint (const DBusString *str,
00350 int start,
00351 unsigned long *value_return,
00352 int *end_return)
00353 {
00354 unsigned long v;
00355 const char *p;
00356 char *end;
00357
00358 p = _dbus_string_get_const_data_len (str, start,
00359 _dbus_string_get_length (str) - start);
00360
00361 end = NULL;
00362 errno = 0;
00363 v = strtoul (p, &end, 0);
00364 if (end == NULL || end == p || errno != 0)
00365 return FALSE;
00366
00367 if (value_return)
00368 *value_return = v;
00369 if (end_return)
00370 *end_return = start + (end - p);
00371
00372 return TRUE;
00373 }
00374
00375 #ifdef DBUS_BUILD_TESTS
00376 static dbus_bool_t
00377 ascii_isspace (char c)
00378 {
00379 return (c == ' ' ||
00380 c == '\f' ||
00381 c == '\n' ||
00382 c == '\r' ||
00383 c == '\t' ||
00384 c == '\v');
00385 }
00386 #endif
00387
00388 #ifdef DBUS_BUILD_TESTS
00389 static dbus_bool_t
00390 ascii_isdigit (char c)
00391 {
00392 return c >= '0' && c <= '9';
00393 }
00394 #endif
00395
00396 #ifdef DBUS_BUILD_TESTS
00397 static dbus_bool_t
00398 ascii_isxdigit (char c)
00399 {
00400 return (ascii_isdigit (c) ||
00401 (c >= 'a' && c <= 'f') ||
00402 (c >= 'A' && c <= 'F'));
00403 }
00404 #endif
00405
00406 #ifdef DBUS_BUILD_TESTS
00407
00408
00409
00410
00411
00412 static double
00413 ascii_strtod (const char *nptr,
00414 char **endptr)
00415 {
00416 char *fail_pos;
00417 double val;
00418 struct lconv *locale_data;
00419 const char *decimal_point;
00420 int decimal_point_len;
00421 const char *p, *decimal_point_pos;
00422 const char *end = NULL;
00423
00424 fail_pos = NULL;
00425
00426 locale_data = localeconv ();
00427 decimal_point = locale_data->decimal_point;
00428 decimal_point_len = strlen (decimal_point);
00429
00430 _dbus_assert (decimal_point_len != 0);
00431
00432 decimal_point_pos = NULL;
00433 if (decimal_point[0] != '.' ||
00434 decimal_point[1] != 0)
00435 {
00436 p = nptr;
00437
00438 while (ascii_isspace (*p))
00439 p++;
00440
00441
00442 if (*p == '+' || *p == '-')
00443 p++;
00444
00445 if (p[0] == '0' &&
00446 (p[1] == 'x' || p[1] == 'X'))
00447 {
00448 p += 2;
00449
00450
00451 while (ascii_isxdigit (*p))
00452 p++;
00453
00454 if (*p == '.')
00455 {
00456 decimal_point_pos = p++;
00457
00458 while (ascii_isxdigit (*p))
00459 p++;
00460
00461 if (*p == 'p' || *p == 'P')
00462 p++;
00463 if (*p == '+' || *p == '-')
00464 p++;
00465 while (ascii_isdigit (*p))
00466 p++;
00467 end = p;
00468 }
00469 }
00470 else
00471 {
00472 while (ascii_isdigit (*p))
00473 p++;
00474
00475 if (*p == '.')
00476 {
00477 decimal_point_pos = p++;
00478
00479 while (ascii_isdigit (*p))
00480 p++;
00481
00482 if (*p == 'e' || *p == 'E')
00483 p++;
00484 if (*p == '+' || *p == '-')
00485 p++;
00486 while (ascii_isdigit (*p))
00487 p++;
00488 end = p;
00489 }
00490 }
00491
00492 }
00493
00494
00495
00496 errno = 0;
00497
00498 if (decimal_point_pos)
00499 {
00500 char *copy, *c;
00501
00502
00503 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
00504
00505 c = copy;
00506 memcpy (c, nptr, decimal_point_pos - nptr);
00507 c += decimal_point_pos - nptr;
00508 memcpy (c, decimal_point, decimal_point_len);
00509 c += decimal_point_len;
00510 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
00511 c += end - (decimal_point_pos + 1);
00512 *c = 0;
00513
00514 val = strtod (copy, &fail_pos);
00515
00516 if (fail_pos)
00517 {
00518 if (fail_pos > decimal_point_pos)
00519 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
00520 else
00521 fail_pos = (char *)nptr + (fail_pos - copy);
00522 }
00523
00524 dbus_free (copy);
00525
00526 }
00527 else
00528 val = strtod (nptr, &fail_pos);
00529
00530 if (endptr)
00531 *endptr = fail_pos;
00532
00533 return val;
00534 }
00535 #endif
00536
00537 #ifdef DBUS_BUILD_TESTS
00538
00550 dbus_bool_t
00551 _dbus_string_parse_double (const DBusString *str,
00552 int start,
00553 double *value_return,
00554 int *end_return)
00555 {
00556 double v;
00557 const char *p;
00558 char *end;
00559
00560 p = _dbus_string_get_const_data_len (str, start,
00561 _dbus_string_get_length (str) - start);
00562
00563 end = NULL;
00564 errno = 0;
00565 v = ascii_strtod (p, &end);
00566 if (end == NULL || end == p || errno != 0)
00567 return FALSE;
00568
00569 if (value_return)
00570 *value_return = v;
00571 if (end_return)
00572 *end_return = start + (end - p);
00573
00574 return TRUE;
00575 }
00576 #endif
00577
00579
00590 void
00591 _dbus_user_info_free (DBusUserInfo *info)
00592 {
00593 dbus_free (info->group_ids);
00594 dbus_free (info->username);
00595 dbus_free (info->homedir);
00596 }
00597
00603 void
00604 _dbus_group_info_free (DBusGroupInfo *info)
00605 {
00606 dbus_free (info->groupname);
00607 }
00608
00615 void
00616 _dbus_credentials_clear (DBusCredentials *credentials)
00617 {
00618 credentials->pid = DBUS_PID_UNSET;
00619 credentials->uid = DBUS_UID_UNSET;
00620 credentials->gid = DBUS_GID_UNSET;
00621 }
00622
00631 dbus_bool_t
00632 _dbus_credentials_match (const DBusCredentials *expected_credentials,
00633 const DBusCredentials *provided_credentials)
00634 {
00635 if (provided_credentials->uid == DBUS_UID_UNSET)
00636 return FALSE;
00637 else if (expected_credentials->uid == DBUS_UID_UNSET)
00638 return FALSE;
00639 else if (provided_credentials->uid == 0)
00640 return TRUE;
00641 else if (provided_credentials->uid == expected_credentials->uid)
00642 return TRUE;
00643 else
00644 return FALSE;
00645 }
00646
00647 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
00648
00649 #ifdef DBUS_USE_ATOMIC_INT_486
00650
00651
00652 static inline dbus_int32_t
00653 atomic_exchange_and_add (DBusAtomic *atomic,
00654 volatile dbus_int32_t val)
00655 {
00656 register dbus_int32_t result;
00657
00658 __asm__ __volatile__ ("lock; xaddl %0,%1"
00659 : "=r" (result), "=m" (atomic->value)
00660 : "0" (val), "m" (atomic->value));
00661 return result;
00662 }
00663 #endif
00664
00673 dbus_int32_t
00674 _dbus_atomic_inc (DBusAtomic *atomic)
00675 {
00676 #ifdef DBUS_USE_ATOMIC_INT_486
00677 return atomic_exchange_and_add (atomic, 1);
00678 #else
00679 dbus_int32_t res;
00680 _DBUS_LOCK (atomic);
00681 res = atomic->value;
00682 atomic->value += 1;
00683 _DBUS_UNLOCK (atomic);
00684 return res;
00685 #endif
00686 }
00687
00696 dbus_int32_t
00697 _dbus_atomic_dec (DBusAtomic *atomic)
00698 {
00699 #ifdef DBUS_USE_ATOMIC_INT_486
00700 return atomic_exchange_and_add (atomic, -1);
00701 #else
00702 dbus_int32_t res;
00703
00704 _DBUS_LOCK (atomic);
00705 res = atomic->value;
00706 atomic->value -= 1;
00707 _DBUS_UNLOCK (atomic);
00708 return res;
00709 #endif
00710 }
00711
00712 void
00713 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
00714 int n_bytes)
00715 {
00716 long tv_usec;
00717 int i;
00718
00719
00720 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
00721 n_bytes);
00722
00723 _dbus_get_current_time (NULL, &tv_usec);
00724 srand (tv_usec);
00725
00726 i = 0;
00727 while (i < n_bytes)
00728 {
00729 double r;
00730 unsigned int b;
00731
00732 r = rand ();
00733 b = (r / (double) RAND_MAX) * 255.0;
00734
00735 buffer[i] = b;
00736
00737 ++i;
00738 }
00739 }
00740
00747 void
00748 _dbus_generate_random_bytes_buffer (char *buffer,
00749 int n_bytes)
00750 {
00751 DBusString str;
00752
00753 if (!_dbus_string_init (&str))
00754 {
00755 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00756 return;
00757 }
00758
00759 if (!_dbus_generate_random_bytes (&str, n_bytes))
00760 {
00761 _dbus_string_free (&str);
00762 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00763 return;
00764 }
00765
00766 _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
00767
00768 _dbus_string_free (&str);
00769 }
00770
00779 dbus_bool_t
00780 _dbus_generate_random_ascii (DBusString *str,
00781 int n_bytes)
00782 {
00783 static const char letters[] =
00784 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
00785 int i;
00786 int len;
00787
00788 if (!_dbus_generate_random_bytes (str, n_bytes))
00789 return FALSE;
00790
00791 len = _dbus_string_get_length (str);
00792 i = len - n_bytes;
00793 while (i < len)
00794 {
00795 _dbus_string_set_byte (str, i,
00796 letters[_dbus_string_get_byte (str, i) %
00797 (sizeof (letters) - 1)]);
00798
00799 ++i;
00800 }
00801
00802 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
00803 n_bytes));
00804
00805 return TRUE;
00806 }
00807
00815 dbus_bool_t
00816 _dbus_parse_uid (const DBusString *uid_str,
00817 dbus_uid_t *uid)
00818 {
00819 int end;
00820 long val;
00821
00822 if (_dbus_string_get_length (uid_str) == 0)
00823 {
00824 _dbus_verbose ("UID string was zero length\n");
00825 return FALSE;
00826 }
00827
00828 val = -1;
00829 end = 0;
00830 if (!_dbus_string_parse_int (uid_str, 0, &val,
00831 &end))
00832 {
00833 _dbus_verbose ("could not parse string as a UID\n");
00834 return FALSE;
00835 }
00836
00837 if (end != _dbus_string_get_length (uid_str))
00838 {
00839 _dbus_verbose ("string contained trailing stuff after UID\n");
00840 return FALSE;
00841 }
00842
00843 *uid = val;
00844
00845 return TRUE;
00846 }
00847
00858 const char*
00859 _dbus_error_from_errno (int error_number)
00860 {
00861 switch (error_number)
00862 {
00863 case 0:
00864 return DBUS_ERROR_FAILED;
00865
00866 #ifdef EPROTONOSUPPORT
00867 case EPROTONOSUPPORT:
00868 return DBUS_ERROR_NOT_SUPPORTED;
00869 #endif
00870 #ifdef EAFNOSUPPORT
00871 case EAFNOSUPPORT:
00872 return DBUS_ERROR_NOT_SUPPORTED;
00873 #endif
00874 #ifdef ENFILE
00875 case ENFILE:
00876 return DBUS_ERROR_LIMITS_EXCEEDED;
00877 #endif
00878 #ifdef EMFILE
00879 case EMFILE:
00880 return DBUS_ERROR_LIMITS_EXCEEDED;
00881 #endif
00882 #ifdef EACCES
00883 case EACCES:
00884 return DBUS_ERROR_ACCESS_DENIED;
00885 #endif
00886 #ifdef EPERM
00887 case EPERM:
00888 return DBUS_ERROR_ACCESS_DENIED;
00889 #endif
00890 #ifdef ENOBUFS
00891 case ENOBUFS:
00892 return DBUS_ERROR_NO_MEMORY;
00893 #endif
00894 #ifdef ENOMEM
00895 case ENOMEM:
00896 return DBUS_ERROR_NO_MEMORY;
00897 #endif
00898 #ifdef EINVAL
00899 case EINVAL:
00900 return DBUS_ERROR_FAILED;
00901 #endif
00902 #ifdef EBADF
00903 case EBADF:
00904 return DBUS_ERROR_FAILED;
00905 #endif
00906 #ifdef EFAULT
00907 case EFAULT:
00908 return DBUS_ERROR_FAILED;
00909 #endif
00910 #ifdef ENOTSOCK
00911 case ENOTSOCK:
00912 return DBUS_ERROR_FAILED;
00913 #endif
00914 #ifdef EISCONN
00915 case EISCONN:
00916 return DBUS_ERROR_FAILED;
00917 #endif
00918 #ifdef ECONNREFUSED
00919 case ECONNREFUSED:
00920 return DBUS_ERROR_NO_SERVER;
00921 #endif
00922 #ifdef ETIMEDOUT
00923 case ETIMEDOUT:
00924 return DBUS_ERROR_TIMEOUT;
00925 #endif
00926 #ifdef ENETUNREACH
00927 case ENETUNREACH:
00928 return DBUS_ERROR_NO_NETWORK;
00929 #endif
00930 #ifdef EADDRINUSE
00931 case EADDRINUSE:
00932 return DBUS_ERROR_ADDRESS_IN_USE;
00933 #endif
00934 #ifdef EEXIST
00935 case EEXIST:
00936 return DBUS_ERROR_FILE_EXISTS;
00937 #endif
00938 #ifdef ENOENT
00939 case ENOENT:
00940 return DBUS_ERROR_FILE_NOT_FOUND;
00941 #endif
00942 }
00943
00944 return DBUS_ERROR_FAILED;
00945 }
00946
00949