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 #include "dbus-list.h"
00031
00032
00033
00034
00035
00036
00037 #include <locale.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #include <stdio.h>
00041
00042
00043
00044
00045
00046 #ifdef HAVE_ERRNO_H
00047 #include <errno.h>
00048 #endif
00049
00050 _DBUS_DEFINE_GLOBAL_LOCK (win_fds);
00051 _DBUS_DEFINE_GLOBAL_LOCK (sid_atom_cache);
00052 _DBUS_DEFINE_GLOBAL_LOCK (system_users);
00053
00071 void
00072 _dbus_abort (void)
00073 {
00074 const char *s;
00075
00076 _dbus_print_backtrace ();
00077
00078 s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
00079 if (s && *s)
00080 {
00081
00082 fprintf (stderr, " Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
00083 _dbus_sleep_milliseconds (1000 * 180);
00084 }
00085
00086 abort ();
00087 _dbus_exit (1);
00088 }
00089
00103 dbus_bool_t
00104 _dbus_setenv (const char *varname,
00105 const char *value)
00106 {
00107 _dbus_assert (varname != NULL);
00108
00109 if (value == NULL)
00110 {
00111 #ifdef HAVE_UNSETENV
00112 unsetenv (varname);
00113 return TRUE;
00114 #else
00115 char *putenv_value;
00116 size_t len;
00117
00118 len = strlen (varname);
00119
00120
00121
00122
00123
00124 putenv_value = malloc (len + 2);
00125 if (putenv_value == NULL)
00126 return FALSE;
00127
00128 strcpy (putenv_value, varname);
00129 #if defined(DBUS_WIN)
00130 strcat (putenv_value, "=");
00131 #endif
00132
00133 return (putenv (putenv_value) == 0);
00134 #endif
00135 }
00136 else
00137 {
00138 #ifdef HAVE_SETENV
00139 return (setenv (varname, value, TRUE) == 0);
00140 #else
00141 char *putenv_value;
00142 size_t len;
00143 size_t varname_len;
00144 size_t value_len;
00145
00146 varname_len = strlen (varname);
00147 value_len = strlen (value);
00148
00149 len = varname_len + value_len + 1 ;
00150
00151
00152
00153
00154
00155 putenv_value = malloc (len + 1);
00156 if (putenv_value == NULL)
00157 return FALSE;
00158
00159 strcpy (putenv_value, varname);
00160 strcpy (putenv_value + varname_len, "=");
00161 strcpy (putenv_value + varname_len + 1, value);
00162
00163 return (putenv (putenv_value) == 0);
00164 #endif
00165 }
00166 }
00167
00174 const char*
00175 _dbus_getenv (const char *varname)
00176 {
00177 return getenv (varname);
00178 }
00179
00185 dbus_bool_t
00186 _dbus_clearenv (void)
00187 {
00188 dbus_bool_t rc = TRUE;
00189
00190 #ifdef HAVE_CLEARENV
00191 if (clearenv () != 0)
00192 rc = FALSE;
00193 #else
00194 extern char **environ;
00195
00196 if (environ != NULL)
00197 environ[0] = NULL;
00198 #endif
00199
00200 return rc;
00201 }
00202
00209 char **
00210 _dbus_get_environment (void)
00211 {
00212 int i, length;
00213 extern char **environ;
00214 char **environment;
00215
00216 _dbus_assert (environ != NULL);
00217
00218 for (length = 0; environ[length] != NULL; length++);
00219
00220
00221 length++;
00222
00223 environment = dbus_new0 (char *, length);
00224
00225 if (environment == NULL)
00226 return NULL;
00227
00228 for (i = 0; environ[i] != NULL; i++)
00229 {
00230 environment[i] = _dbus_strdup (environ[i]);
00231
00232 if (environment[i] == NULL)
00233 break;
00234 }
00235
00236 if (environ[i] != NULL)
00237 {
00238 dbus_free_string_array (environment);
00239 environment = NULL;
00240 }
00241
00242 return environment;
00243 }
00244
00245
00246
00247
00248
00249
00250
00251 void
00252 _dbus_pipe_init (DBusPipe *pipe,
00253 int fd)
00254 {
00255 pipe->fd_or_handle = fd;
00256 }
00257
00263 void
00264 _dbus_pipe_init_stdout (DBusPipe *pipe)
00265 {
00266 _dbus_pipe_init (pipe, 1);
00267 }
00268
00276 dbus_bool_t
00277 _dbus_pipe_is_valid(DBusPipe *pipe)
00278 {
00279 return pipe->fd_or_handle >= 0;
00280 }
00281
00288 dbus_bool_t
00289 _dbus_pipe_is_stdout_or_stderr (DBusPipe *pipe)
00290 {
00291 return pipe->fd_or_handle == 1 || pipe->fd_or_handle == 2;
00292 }
00293
00298 void
00299 _dbus_pipe_invalidate (DBusPipe *pipe)
00300 {
00301 pipe->fd_or_handle = -1;
00302 }
00303
00312 dbus_bool_t
00313 _dbus_split_paths_and_append (DBusString *dirs,
00314 const char *suffix,
00315 DBusList **dir_list)
00316 {
00317 int start;
00318 int i;
00319 int len;
00320 char *cpath;
00321 DBusString file_suffix;
00322
00323 start = 0;
00324 i = 0;
00325
00326 _dbus_string_init_const (&file_suffix, suffix);
00327
00328 len = _dbus_string_get_length (dirs);
00329
00330 while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
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 i - start,
00340 &path,
00341 0))
00342 {
00343 _dbus_string_free (&path);
00344 goto oom;
00345 }
00346
00347 _dbus_string_chop_white (&path);
00348
00349
00350 if (_dbus_string_get_length (&path) == 0)
00351 goto next;
00352
00353 if (!_dbus_concat_dir_and_file (&path,
00354 &file_suffix))
00355 {
00356 _dbus_string_free (&path);
00357 goto oom;
00358 }
00359
00360 if (!_dbus_string_copy_data(&path, &cpath))
00361 {
00362 _dbus_string_free (&path);
00363 goto oom;
00364 }
00365
00366 if (!_dbus_list_append (dir_list, cpath))
00367 {
00368 _dbus_string_free (&path);
00369 dbus_free (cpath);
00370 goto oom;
00371 }
00372
00373 next:
00374 _dbus_string_free (&path);
00375 start = i + 1;
00376 }
00377
00378 if (start != len)
00379 {
00380 DBusString path;
00381
00382 if (!_dbus_string_init (&path))
00383 goto oom;
00384
00385 if (!_dbus_string_copy_len (dirs,
00386 start,
00387 len - start,
00388 &path,
00389 0))
00390 {
00391 _dbus_string_free (&path);
00392 goto oom;
00393 }
00394
00395 if (!_dbus_concat_dir_and_file (&path,
00396 &file_suffix))
00397 {
00398 _dbus_string_free (&path);
00399 goto oom;
00400 }
00401
00402 if (!_dbus_string_copy_data(&path, &cpath))
00403 {
00404 _dbus_string_free (&path);
00405 goto oom;
00406 }
00407
00408 if (!_dbus_list_append (dir_list, cpath))
00409 {
00410 _dbus_string_free (&path);
00411 dbus_free (cpath);
00412 goto oom;
00413 }
00414
00415 _dbus_string_free (&path);
00416 }
00417
00418 return TRUE;
00419
00420 oom:
00421 _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL);
00422 _dbus_list_clear (dir_list);
00423 return FALSE;
00424 }
00425
00440 dbus_bool_t
00441 _dbus_string_append_int (DBusString *str,
00442 long value)
00443 {
00444
00445 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
00446 int orig_len;
00447 int i;
00448 char *buf;
00449
00450 orig_len = _dbus_string_get_length (str);
00451
00452 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00453 return FALSE;
00454
00455 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00456
00457 snprintf (buf, MAX_LONG_LEN, "%ld", value);
00458
00459 i = 0;
00460 while (*buf)
00461 {
00462 ++buf;
00463 ++i;
00464 }
00465
00466 _dbus_string_shorten (str, MAX_LONG_LEN - i);
00467
00468 return TRUE;
00469 }
00470
00478 dbus_bool_t
00479 _dbus_string_append_uint (DBusString *str,
00480 unsigned long value)
00481 {
00482
00483 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
00484 int orig_len;
00485 int i;
00486 char *buf;
00487
00488 orig_len = _dbus_string_get_length (str);
00489
00490 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
00491 return FALSE;
00492
00493 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
00494
00495 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
00496
00497 i = 0;
00498 while (*buf)
00499 {
00500 ++buf;
00501 ++i;
00502 }
00503
00504 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
00505
00506 return TRUE;
00507 }
00508
00509 #ifdef DBUS_BUILD_TESTS
00510
00517 dbus_bool_t
00518 _dbus_string_append_double (DBusString *str,
00519 double value)
00520 {
00521 #define MAX_DOUBLE_LEN 64
00522 int orig_len;
00523 char *buf;
00524 int i;
00525
00526 orig_len = _dbus_string_get_length (str);
00527
00528 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
00529 return FALSE;
00530
00531 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
00532
00533 snprintf (buf, MAX_LONG_LEN, "%g", value);
00534
00535 i = 0;
00536 while (*buf)
00537 {
00538 ++buf;
00539 ++i;
00540 }
00541
00542 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
00543
00544 return TRUE;
00545 }
00546 #endif
00547
00560 dbus_bool_t
00561 _dbus_string_parse_int (const DBusString *str,
00562 int start,
00563 long *value_return,
00564 int *end_return)
00565 {
00566 long v;
00567 const char *p;
00568 char *end;
00569
00570 p = _dbus_string_get_const_data_len (str, start,
00571 _dbus_string_get_length (str) - start);
00572
00573 end = NULL;
00574 errno = 0;
00575 v = strtol (p, &end, 0);
00576 if (end == NULL || end == p || errno != 0)
00577 return FALSE;
00578
00579 if (value_return)
00580 *value_return = v;
00581 if (end_return)
00582 *end_return = start + (end - p);
00583
00584 return TRUE;
00585 }
00586
00599 dbus_bool_t
00600 _dbus_string_parse_uint (const DBusString *str,
00601 int start,
00602 unsigned long *value_return,
00603 int *end_return)
00604 {
00605 unsigned long v;
00606 const char *p;
00607 char *end;
00608
00609 p = _dbus_string_get_const_data_len (str, start,
00610 _dbus_string_get_length (str) - start);
00611
00612 end = NULL;
00613 errno = 0;
00614 v = strtoul (p, &end, 0);
00615 if (end == NULL || end == p || errno != 0)
00616 return FALSE;
00617
00618 if (value_return)
00619 *value_return = v;
00620 if (end_return)
00621 *end_return = start + (end - p);
00622
00623 return TRUE;
00624 }
00625
00626 #ifdef DBUS_BUILD_TESTS
00627 static dbus_bool_t
00628 ascii_isspace (char c)
00629 {
00630 return (c == ' ' ||
00631 c == '\f' ||
00632 c == '\n' ||
00633 c == '\r' ||
00634 c == '\t' ||
00635 c == '\v');
00636 }
00637 #endif
00638
00639 #ifdef DBUS_BUILD_TESTS
00640 static dbus_bool_t
00641 ascii_isdigit (char c)
00642 {
00643 return c >= '0' && c <= '9';
00644 }
00645 #endif
00646
00647 #ifdef DBUS_BUILD_TESTS
00648 static dbus_bool_t
00649 ascii_isxdigit (char c)
00650 {
00651 return (ascii_isdigit (c) ||
00652 (c >= 'a' && c <= 'f') ||
00653 (c >= 'A' && c <= 'F'));
00654 }
00655 #endif
00656
00657 #ifdef DBUS_BUILD_TESTS
00658
00659
00660
00661
00662
00663 static double
00664 ascii_strtod (const char *nptr,
00665 char **endptr)
00666 {
00667
00668
00669
00670
00671 char *fail_pos;
00672 double val;
00673 struct lconv *locale_data;
00674 const char *decimal_point;
00675 int decimal_point_len;
00676 const char *p, *decimal_point_pos;
00677 const char *end = NULL;
00678
00679 fail_pos = NULL;
00680
00681 locale_data = localeconv ();
00682 decimal_point = locale_data->decimal_point;
00683 decimal_point_len = strlen (decimal_point);
00684
00685 _dbus_assert (decimal_point_len != 0);
00686
00687 decimal_point_pos = NULL;
00688 if (decimal_point[0] != '.' ||
00689 decimal_point[1] != 0)
00690 {
00691 p = nptr;
00692
00693 while (ascii_isspace (*p))
00694 p++;
00695
00696
00697 if (*p == '+' || *p == '-')
00698 p++;
00699
00700 if (p[0] == '0' &&
00701 (p[1] == 'x' || p[1] == 'X'))
00702 {
00703 p += 2;
00704
00705
00706 while (ascii_isxdigit (*p))
00707 p++;
00708
00709 if (*p == '.')
00710 {
00711 decimal_point_pos = p++;
00712
00713 while (ascii_isxdigit (*p))
00714 p++;
00715
00716 if (*p == 'p' || *p == 'P')
00717 p++;
00718 if (*p == '+' || *p == '-')
00719 p++;
00720 while (ascii_isdigit (*p))
00721 p++;
00722 end = p;
00723 }
00724 }
00725 else
00726 {
00727 while (ascii_isdigit (*p))
00728 p++;
00729
00730 if (*p == '.')
00731 {
00732 decimal_point_pos = p++;
00733
00734 while (ascii_isdigit (*p))
00735 p++;
00736
00737 if (*p == 'e' || *p == 'E')
00738 p++;
00739 if (*p == '+' || *p == '-')
00740 p++;
00741 while (ascii_isdigit (*p))
00742 p++;
00743 end = p;
00744 }
00745 }
00746
00747 }
00748
00749
00750
00751 errno = 0;
00752
00753 if (decimal_point_pos)
00754 {
00755 char *copy, *c;
00756
00757
00758 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
00759
00760 c = copy;
00761 memcpy (c, nptr, decimal_point_pos - nptr);
00762 c += decimal_point_pos - nptr;
00763 memcpy (c, decimal_point, decimal_point_len);
00764 c += decimal_point_len;
00765 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
00766 c += end - (decimal_point_pos + 1);
00767 *c = 0;
00768
00769 val = strtod (copy, &fail_pos);
00770
00771 if (fail_pos)
00772 {
00773 if (fail_pos > decimal_point_pos)
00774 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
00775 else
00776 fail_pos = (char *)nptr + (fail_pos - copy);
00777 }
00778
00779 dbus_free (copy);
00780
00781 }
00782 else
00783 val = strtod (nptr, &fail_pos);
00784
00785 if (endptr)
00786 *endptr = fail_pos;
00787
00788 return val;
00789 }
00790 #endif
00791
00792 #ifdef DBUS_BUILD_TESTS
00793
00805 dbus_bool_t
00806 _dbus_string_parse_double (const DBusString *str,
00807 int start,
00808 double *value_return,
00809 int *end_return)
00810 {
00811 double v;
00812 const char *p;
00813 char *end;
00814
00815 p = _dbus_string_get_const_data_len (str, start,
00816 _dbus_string_get_length (str) - start);
00817
00818
00819
00820
00821 if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
00822 return FALSE;
00823
00824 end = NULL;
00825 errno = 0;
00826 v = ascii_strtod (p, &end);
00827 if (end == NULL || end == p || errno != 0)
00828 return FALSE;
00829
00830 if (value_return)
00831 *value_return = v;
00832 if (end_return)
00833 *end_return = start + (end - p);
00834
00835 return TRUE;
00836 }
00837 #endif
00838
00840
00846 void
00847 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
00848 int n_bytes)
00849 {
00850 long tv_usec;
00851 int i;
00852
00853
00854 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
00855 n_bytes);
00856
00857 _dbus_get_current_time (NULL, &tv_usec);
00858 srand (tv_usec);
00859
00860 i = 0;
00861 while (i < n_bytes)
00862 {
00863 double r;
00864 unsigned int b;
00865
00866 r = rand ();
00867 b = (r / (double) RAND_MAX) * 255.0;
00868
00869 buffer[i] = b;
00870
00871 ++i;
00872 }
00873 }
00874
00881 void
00882 _dbus_generate_random_bytes_buffer (char *buffer,
00883 int n_bytes)
00884 {
00885 DBusString str;
00886
00887 if (!_dbus_string_init (&str))
00888 {
00889 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00890 return;
00891 }
00892
00893 if (!_dbus_generate_random_bytes (&str, n_bytes))
00894 {
00895 _dbus_string_free (&str);
00896 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00897 return;
00898 }
00899
00900 _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
00901
00902 _dbus_string_free (&str);
00903 }
00904
00913 dbus_bool_t
00914 _dbus_generate_random_ascii (DBusString *str,
00915 int n_bytes)
00916 {
00917 static const char letters[] =
00918 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
00919 int i;
00920 int len;
00921
00922 if (!_dbus_generate_random_bytes (str, n_bytes))
00923 return FALSE;
00924
00925 len = _dbus_string_get_length (str);
00926 i = len - n_bytes;
00927 while (i < len)
00928 {
00929 _dbus_string_set_byte (str, i,
00930 letters[_dbus_string_get_byte (str, i) %
00931 (sizeof (letters) - 1)]);
00932
00933 ++i;
00934 }
00935
00936 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
00937 n_bytes));
00938
00939 return TRUE;
00940 }
00941
00952 const char*
00953 _dbus_error_from_errno (int error_number)
00954 {
00955 switch (error_number)
00956 {
00957 case 0:
00958 return DBUS_ERROR_FAILED;
00959
00960 #ifdef EPROTONOSUPPORT
00961 case EPROTONOSUPPORT:
00962 return DBUS_ERROR_NOT_SUPPORTED;
00963 #endif
00964 #ifdef EAFNOSUPPORT
00965 case EAFNOSUPPORT:
00966 return DBUS_ERROR_NOT_SUPPORTED;
00967 #endif
00968 #ifdef ENFILE
00969 case ENFILE:
00970 return DBUS_ERROR_LIMITS_EXCEEDED;
00971 #endif
00972 #ifdef EMFILE
00973 case EMFILE:
00974 return DBUS_ERROR_LIMITS_EXCEEDED;
00975 #endif
00976 #ifdef EACCES
00977 case EACCES:
00978 return DBUS_ERROR_ACCESS_DENIED;
00979 #endif
00980 #ifdef EPERM
00981 case EPERM:
00982 return DBUS_ERROR_ACCESS_DENIED;
00983 #endif
00984 #ifdef ENOBUFS
00985 case ENOBUFS:
00986 return DBUS_ERROR_NO_MEMORY;
00987 #endif
00988 #ifdef ENOMEM
00989 case ENOMEM:
00990 return DBUS_ERROR_NO_MEMORY;
00991 #endif
00992 #ifdef EINVAL
00993 case EINVAL:
00994 return DBUS_ERROR_FAILED;
00995 #endif
00996 #ifdef EBADF
00997 case EBADF:
00998 return DBUS_ERROR_FAILED;
00999 #endif
01000 #ifdef EFAULT
01001 case EFAULT:
01002 return DBUS_ERROR_FAILED;
01003 #endif
01004 #ifdef ENOTSOCK
01005 case ENOTSOCK:
01006 return DBUS_ERROR_FAILED;
01007 #endif
01008 #ifdef EISCONN
01009 case EISCONN:
01010 return DBUS_ERROR_FAILED;
01011 #endif
01012 #ifdef ECONNREFUSED
01013 case ECONNREFUSED:
01014 return DBUS_ERROR_NO_SERVER;
01015 #endif
01016 #ifdef ETIMEDOUT
01017 case ETIMEDOUT:
01018 return DBUS_ERROR_TIMEOUT;
01019 #endif
01020 #ifdef ENETUNREACH
01021 case ENETUNREACH:
01022 return DBUS_ERROR_NO_NETWORK;
01023 #endif
01024 #ifdef EADDRINUSE
01025 case EADDRINUSE:
01026 return DBUS_ERROR_ADDRESS_IN_USE;
01027 #endif
01028 #ifdef EEXIST
01029 case EEXIST:
01030 return DBUS_ERROR_FILE_EXISTS;
01031 #endif
01032 #ifdef ENOENT
01033 case ENOENT:
01034 return DBUS_ERROR_FILE_NOT_FOUND;
01035 #endif
01036 }
01037
01038 return DBUS_ERROR_FAILED;
01039 }
01040
01044 void
01045 _dbus_set_errno_to_zero (void)
01046 {
01047 errno = 0;
01048 }
01049
01054 dbus_bool_t
01055 _dbus_get_is_errno_nonzero (void)
01056 {
01057 return errno != 0;
01058 }
01059
01064 dbus_bool_t
01065 _dbus_get_is_errno_enomem (void)
01066 {
01067 return errno == ENOMEM;
01068 }
01069
01074 dbus_bool_t
01075 _dbus_get_is_errno_eintr (void)
01076 {
01077 return errno == EINTR;
01078 }
01079
01084 const char*
01085 _dbus_strerror_from_errno (void)
01086 {
01087 return _dbus_strerror (errno);
01088 }
01089
01092