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
00054 extern char **environ;
00055
00073 void
00074 _dbus_abort (void)
00075 {
00076 const char *s;
00077
00078 _dbus_print_backtrace ();
00079
00080 s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
00081 if (s && *s)
00082 {
00083
00084 fprintf (stderr, " Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
00085 _dbus_sleep_milliseconds (1000 * 180);
00086 }
00087
00088 abort ();
00089 _dbus_exit (1);
00090 }
00091
00105 dbus_bool_t
00106 _dbus_setenv (const char *varname,
00107 const char *value)
00108 {
00109 _dbus_assert (varname != NULL);
00110
00111 if (value == NULL)
00112 {
00113 #ifdef HAVE_UNSETENV
00114 unsetenv (varname);
00115 return TRUE;
00116 #else
00117 char *putenv_value;
00118 size_t len;
00119
00120 len = strlen (varname);
00121
00122
00123
00124
00125
00126 putenv_value = malloc (len + 2);
00127 if (putenv_value == NULL)
00128 return FALSE;
00129
00130 strcpy (putenv_value, varname);
00131 #if defined(DBUS_WIN)
00132 strcat (putenv_value, "=");
00133 #endif
00134
00135 return (putenv (putenv_value) == 0);
00136 #endif
00137 }
00138 else
00139 {
00140 #ifdef HAVE_SETENV
00141 return (setenv (varname, value, TRUE) == 0);
00142 #else
00143 char *putenv_value;
00144 size_t len;
00145 size_t varname_len;
00146 size_t value_len;
00147
00148 varname_len = strlen (varname);
00149 value_len = strlen (value);
00150
00151 len = varname_len + value_len + 1 ;
00152
00153
00154
00155
00156
00157 putenv_value = malloc (len + 1);
00158 if (putenv_value == NULL)
00159 return FALSE;
00160
00161 strcpy (putenv_value, varname);
00162 strcpy (putenv_value + varname_len, "=");
00163 strcpy (putenv_value + varname_len + 1, value);
00164
00165 return (putenv (putenv_value) == 0);
00166 #endif
00167 }
00168 }
00169
00176 const char*
00177 _dbus_getenv (const char *varname)
00178 {
00179
00180
00181
00182 if (_dbus_check_setuid ())
00183 return NULL;
00184 return getenv (varname);
00185 }
00186
00192 dbus_bool_t
00193 _dbus_clearenv (void)
00194 {
00195 dbus_bool_t rc = TRUE;
00196
00197 #ifdef HAVE_CLEARENV
00198 if (clearenv () != 0)
00199 rc = FALSE;
00200 #else
00201
00202 if (environ != NULL)
00203 environ[0] = NULL;
00204 #endif
00205
00206 return rc;
00207 }
00208
00215 char **
00216 _dbus_get_environment (void)
00217 {
00218 int i, length;
00219 char **environment;
00220
00221 _dbus_assert (environ != NULL);
00222
00223 for (length = 0; environ[length] != NULL; length++);
00224
00225
00226 length++;
00227
00228 environment = dbus_new0 (char *, length);
00229
00230 if (environment == NULL)
00231 return NULL;
00232
00233 for (i = 0; environ[i] != NULL; i++)
00234 {
00235 environment[i] = _dbus_strdup (environ[i]);
00236
00237 if (environment[i] == NULL)
00238 break;
00239 }
00240
00241 if (environ[i] != NULL)
00242 {
00243 dbus_free_string_array (environment);
00244 environment = NULL;
00245 }
00246
00247 return environment;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256 void
00257 _dbus_pipe_init (DBusPipe *pipe,
00258 int fd)
00259 {
00260 pipe->fd_or_handle = fd;
00261 }
00262
00268 void
00269 _dbus_pipe_init_stdout (DBusPipe *pipe)
00270 {
00271 _dbus_pipe_init (pipe, 1);
00272 }
00273
00281 dbus_bool_t
00282 _dbus_pipe_is_valid(DBusPipe *pipe)
00283 {
00284 return pipe->fd_or_handle >= 0;
00285 }
00286
00293 dbus_bool_t
00294 _dbus_pipe_is_stdout_or_stderr (DBusPipe *pipe)
00295 {
00296 return pipe->fd_or_handle == 1 || pipe->fd_or_handle == 2;
00297 }
00298
00303 void
00304 _dbus_pipe_invalidate (DBusPipe *pipe)
00305 {
00306 pipe->fd_or_handle = -1;
00307 }
00308
00317 dbus_bool_t
00318 _dbus_split_paths_and_append (DBusString *dirs,
00319 const char *suffix,
00320 DBusList **dir_list)
00321 {
00322 int start;
00323 int i;
00324 int len;
00325 char *cpath;
00326 DBusString file_suffix;
00327
00328 start = 0;
00329 i = 0;
00330
00331 _dbus_string_init_const (&file_suffix, suffix);
00332
00333 len = _dbus_string_get_length (dirs);
00334
00335 while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
00336 {
00337 DBusString path;
00338
00339 if (!_dbus_string_init (&path))
00340 goto oom;
00341
00342 if (!_dbus_string_copy_len (dirs,
00343 start,
00344 i - start,
00345 &path,
00346 0))
00347 {
00348 _dbus_string_free (&path);
00349 goto oom;
00350 }
00351
00352 _dbus_string_chop_white (&path);
00353
00354
00355 if (_dbus_string_get_length (&path) == 0)
00356 goto next;
00357
00358 if (!_dbus_concat_dir_and_file (&path,
00359 &file_suffix))
00360 {
00361 _dbus_string_free (&path);
00362 goto oom;
00363 }
00364
00365 if (!_dbus_string_copy_data(&path, &cpath))
00366 {
00367 _dbus_string_free (&path);
00368 goto oom;
00369 }
00370
00371 if (!_dbus_list_append (dir_list, cpath))
00372 {
00373 _dbus_string_free (&path);
00374 dbus_free (cpath);
00375 goto oom;
00376 }
00377
00378 next:
00379 _dbus_string_free (&path);
00380 start = i + 1;
00381 }
00382
00383 if (start != len)
00384 {
00385 DBusString path;
00386
00387 if (!_dbus_string_init (&path))
00388 goto oom;
00389
00390 if (!_dbus_string_copy_len (dirs,
00391 start,
00392 len - start,
00393 &path,
00394 0))
00395 {
00396 _dbus_string_free (&path);
00397 goto oom;
00398 }
00399
00400 if (!_dbus_concat_dir_and_file (&path,
00401 &file_suffix))
00402 {
00403 _dbus_string_free (&path);
00404 goto oom;
00405 }
00406
00407 if (!_dbus_string_copy_data(&path, &cpath))
00408 {
00409 _dbus_string_free (&path);
00410 goto oom;
00411 }
00412
00413 if (!_dbus_list_append (dir_list, cpath))
00414 {
00415 _dbus_string_free (&path);
00416 dbus_free (cpath);
00417 goto oom;
00418 }
00419
00420 _dbus_string_free (&path);
00421 }
00422
00423 return TRUE;
00424
00425 oom:
00426 _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL);
00427 _dbus_list_clear (dir_list);
00428 return FALSE;
00429 }
00430
00445 dbus_bool_t
00446 _dbus_string_append_int (DBusString *str,
00447 long value)
00448 {
00449
00450 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
00451 int orig_len;
00452 int i;
00453 char *buf;
00454
00455 orig_len = _dbus_string_get_length (str);
00456
00457 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00458 return FALSE;
00459
00460 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00461
00462 snprintf (buf, MAX_LONG_LEN, "%ld", value);
00463
00464 i = 0;
00465 while (*buf)
00466 {
00467 ++buf;
00468 ++i;
00469 }
00470
00471 _dbus_string_shorten (str, MAX_LONG_LEN - i);
00472
00473 return TRUE;
00474 }
00475
00483 dbus_bool_t
00484 _dbus_string_append_uint (DBusString *str,
00485 unsigned long value)
00486 {
00487
00488 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
00489 int orig_len;
00490 int i;
00491 char *buf;
00492
00493 orig_len = _dbus_string_get_length (str);
00494
00495 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
00496 return FALSE;
00497
00498 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
00499
00500 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
00501
00502 i = 0;
00503 while (*buf)
00504 {
00505 ++buf;
00506 ++i;
00507 }
00508
00509 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
00510
00511 return TRUE;
00512 }
00513
00514 #ifdef DBUS_BUILD_TESTS
00515
00522 dbus_bool_t
00523 _dbus_string_append_double (DBusString *str,
00524 double value)
00525 {
00526 #define MAX_DOUBLE_LEN 64
00527 int orig_len;
00528 char *buf;
00529 int i;
00530
00531 orig_len = _dbus_string_get_length (str);
00532
00533 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
00534 return FALSE;
00535
00536 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
00537
00538 snprintf (buf, MAX_LONG_LEN, "%g", value);
00539
00540 i = 0;
00541 while (*buf)
00542 {
00543 ++buf;
00544 ++i;
00545 }
00546
00547 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
00548
00549 return TRUE;
00550 }
00551 #endif
00552
00565 dbus_bool_t
00566 _dbus_string_parse_int (const DBusString *str,
00567 int start,
00568 long *value_return,
00569 int *end_return)
00570 {
00571 long v;
00572 const char *p;
00573 char *end;
00574
00575 p = _dbus_string_get_const_data_len (str, start,
00576 _dbus_string_get_length (str) - start);
00577
00578 end = NULL;
00579 errno = 0;
00580 v = strtol (p, &end, 0);
00581 if (end == NULL || end == p || errno != 0)
00582 return FALSE;
00583
00584 if (value_return)
00585 *value_return = v;
00586 if (end_return)
00587 *end_return = start + (end - p);
00588
00589 return TRUE;
00590 }
00591
00604 dbus_bool_t
00605 _dbus_string_parse_uint (const DBusString *str,
00606 int start,
00607 unsigned long *value_return,
00608 int *end_return)
00609 {
00610 unsigned long v;
00611 const char *p;
00612 char *end;
00613
00614 p = _dbus_string_get_const_data_len (str, start,
00615 _dbus_string_get_length (str) - start);
00616
00617 end = NULL;
00618 errno = 0;
00619 v = strtoul (p, &end, 0);
00620 if (end == NULL || end == p || errno != 0)
00621 return FALSE;
00622
00623 if (value_return)
00624 *value_return = v;
00625 if (end_return)
00626 *end_return = start + (end - p);
00627
00628 return TRUE;
00629 }
00630
00631 #ifdef DBUS_BUILD_TESTS
00632 static dbus_bool_t
00633 ascii_isspace (char c)
00634 {
00635 return (c == ' ' ||
00636 c == '\f' ||
00637 c == '\n' ||
00638 c == '\r' ||
00639 c == '\t' ||
00640 c == '\v');
00641 }
00642 #endif
00643
00644 #ifdef DBUS_BUILD_TESTS
00645 static dbus_bool_t
00646 ascii_isdigit (char c)
00647 {
00648 return c >= '0' && c <= '9';
00649 }
00650 #endif
00651
00652 #ifdef DBUS_BUILD_TESTS
00653 static dbus_bool_t
00654 ascii_isxdigit (char c)
00655 {
00656 return (ascii_isdigit (c) ||
00657 (c >= 'a' && c <= 'f') ||
00658 (c >= 'A' && c <= 'F'));
00659 }
00660 #endif
00661
00662 #ifdef DBUS_BUILD_TESTS
00663
00664
00665
00666
00667
00668 static double
00669 ascii_strtod (const char *nptr,
00670 char **endptr)
00671 {
00672
00673
00674
00675
00676 char *fail_pos;
00677 double val;
00678 struct lconv *locale_data;
00679 const char *decimal_point;
00680 int decimal_point_len;
00681 const char *p, *decimal_point_pos;
00682 const char *end = NULL;
00683
00684 fail_pos = NULL;
00685
00686 locale_data = localeconv ();
00687 decimal_point = locale_data->decimal_point;
00688 decimal_point_len = strlen (decimal_point);
00689
00690 _dbus_assert (decimal_point_len != 0);
00691
00692 decimal_point_pos = NULL;
00693 if (decimal_point[0] != '.' ||
00694 decimal_point[1] != 0)
00695 {
00696 p = nptr;
00697
00698 while (ascii_isspace (*p))
00699 p++;
00700
00701
00702 if (*p == '+' || *p == '-')
00703 p++;
00704
00705 if (p[0] == '0' &&
00706 (p[1] == 'x' || p[1] == 'X'))
00707 {
00708 p += 2;
00709
00710
00711 while (ascii_isxdigit (*p))
00712 p++;
00713
00714 if (*p == '.')
00715 {
00716 decimal_point_pos = p++;
00717
00718 while (ascii_isxdigit (*p))
00719 p++;
00720
00721 if (*p == 'p' || *p == 'P')
00722 p++;
00723 if (*p == '+' || *p == '-')
00724 p++;
00725 while (ascii_isdigit (*p))
00726 p++;
00727 end = p;
00728 }
00729 }
00730 else
00731 {
00732 while (ascii_isdigit (*p))
00733 p++;
00734
00735 if (*p == '.')
00736 {
00737 decimal_point_pos = p++;
00738
00739 while (ascii_isdigit (*p))
00740 p++;
00741
00742 if (*p == 'e' || *p == 'E')
00743 p++;
00744 if (*p == '+' || *p == '-')
00745 p++;
00746 while (ascii_isdigit (*p))
00747 p++;
00748 end = p;
00749 }
00750 }
00751
00752 }
00753
00754
00755
00756 errno = 0;
00757
00758 if (decimal_point_pos)
00759 {
00760 char *copy, *c;
00761
00762
00763 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
00764
00765 c = copy;
00766 memcpy (c, nptr, decimal_point_pos - nptr);
00767 c += decimal_point_pos - nptr;
00768 memcpy (c, decimal_point, decimal_point_len);
00769 c += decimal_point_len;
00770 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
00771 c += end - (decimal_point_pos + 1);
00772 *c = 0;
00773
00774 val = strtod (copy, &fail_pos);
00775
00776 if (fail_pos)
00777 {
00778 if (fail_pos > decimal_point_pos)
00779 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
00780 else
00781 fail_pos = (char *)nptr + (fail_pos - copy);
00782 }
00783
00784 dbus_free (copy);
00785
00786 }
00787 else
00788 val = strtod (nptr, &fail_pos);
00789
00790 if (endptr)
00791 *endptr = fail_pos;
00792
00793 return val;
00794 }
00795 #endif
00796
00797 #ifdef DBUS_BUILD_TESTS
00798
00810 dbus_bool_t
00811 _dbus_string_parse_double (const DBusString *str,
00812 int start,
00813 double *value_return,
00814 int *end_return)
00815 {
00816 double v;
00817 const char *p;
00818 char *end;
00819
00820 p = _dbus_string_get_const_data_len (str, start,
00821 _dbus_string_get_length (str) - start);
00822
00823
00824
00825
00826 if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
00827 return FALSE;
00828
00829 end = NULL;
00830 errno = 0;
00831 v = ascii_strtod (p, &end);
00832 if (end == NULL || end == p || errno != 0)
00833 return FALSE;
00834
00835 if (value_return)
00836 *value_return = v;
00837 if (end_return)
00838 *end_return = start + (end - p);
00839
00840 return TRUE;
00841 }
00842 #endif
00843
00845
00851 void
00852 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
00853 int n_bytes)
00854 {
00855 long tv_usec;
00856 int i;
00857
00858
00859 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
00860 n_bytes);
00861
00862 _dbus_get_current_time (NULL, &tv_usec);
00863 srand (tv_usec);
00864
00865 i = 0;
00866 while (i < n_bytes)
00867 {
00868 double r;
00869 unsigned int b;
00870
00871 r = rand ();
00872 b = (r / (double) RAND_MAX) * 255.0;
00873
00874 buffer[i] = b;
00875
00876 ++i;
00877 }
00878 }
00879
00886 void
00887 _dbus_generate_random_bytes_buffer (char *buffer,
00888 int n_bytes)
00889 {
00890 DBusString str;
00891
00892 if (!_dbus_string_init (&str))
00893 {
00894 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00895 return;
00896 }
00897
00898 if (!_dbus_generate_random_bytes (&str, n_bytes))
00899 {
00900 _dbus_string_free (&str);
00901 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00902 return;
00903 }
00904
00905 _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
00906
00907 _dbus_string_free (&str);
00908 }
00909
00918 dbus_bool_t
00919 _dbus_generate_random_ascii (DBusString *str,
00920 int n_bytes)
00921 {
00922 static const char letters[] =
00923 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
00924 int i;
00925 int len;
00926
00927 if (!_dbus_generate_random_bytes (str, n_bytes))
00928 return FALSE;
00929
00930 len = _dbus_string_get_length (str);
00931 i = len - n_bytes;
00932 while (i < len)
00933 {
00934 _dbus_string_set_byte (str, i,
00935 letters[_dbus_string_get_byte (str, i) %
00936 (sizeof (letters) - 1)]);
00937
00938 ++i;
00939 }
00940
00941 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
00942 n_bytes));
00943
00944 return TRUE;
00945 }
00946
00957 const char*
00958 _dbus_error_from_errno (int error_number)
00959 {
00960 switch (error_number)
00961 {
00962 case 0:
00963 return DBUS_ERROR_FAILED;
00964
00965 #ifdef EPROTONOSUPPORT
00966 case EPROTONOSUPPORT:
00967 return DBUS_ERROR_NOT_SUPPORTED;
00968 #endif
00969 #ifdef EAFNOSUPPORT
00970 case EAFNOSUPPORT:
00971 return DBUS_ERROR_NOT_SUPPORTED;
00972 #endif
00973 #ifdef ENFILE
00974 case ENFILE:
00975 return DBUS_ERROR_LIMITS_EXCEEDED;
00976 #endif
00977 #ifdef EMFILE
00978 case EMFILE:
00979 return DBUS_ERROR_LIMITS_EXCEEDED;
00980 #endif
00981 #ifdef EACCES
00982 case EACCES:
00983 return DBUS_ERROR_ACCESS_DENIED;
00984 #endif
00985 #ifdef EPERM
00986 case EPERM:
00987 return DBUS_ERROR_ACCESS_DENIED;
00988 #endif
00989 #ifdef ENOBUFS
00990 case ENOBUFS:
00991 return DBUS_ERROR_NO_MEMORY;
00992 #endif
00993 #ifdef ENOMEM
00994 case ENOMEM:
00995 return DBUS_ERROR_NO_MEMORY;
00996 #endif
00997 #ifdef EINVAL
00998 case EINVAL:
00999 return DBUS_ERROR_FAILED;
01000 #endif
01001 #ifdef EBADF
01002 case EBADF:
01003 return DBUS_ERROR_FAILED;
01004 #endif
01005 #ifdef EFAULT
01006 case EFAULT:
01007 return DBUS_ERROR_FAILED;
01008 #endif
01009 #ifdef ENOTSOCK
01010 case ENOTSOCK:
01011 return DBUS_ERROR_FAILED;
01012 #endif
01013 #ifdef EISCONN
01014 case EISCONN:
01015 return DBUS_ERROR_FAILED;
01016 #endif
01017 #ifdef ECONNREFUSED
01018 case ECONNREFUSED:
01019 return DBUS_ERROR_NO_SERVER;
01020 #endif
01021 #ifdef ETIMEDOUT
01022 case ETIMEDOUT:
01023 return DBUS_ERROR_TIMEOUT;
01024 #endif
01025 #ifdef ENETUNREACH
01026 case ENETUNREACH:
01027 return DBUS_ERROR_NO_NETWORK;
01028 #endif
01029 #ifdef EADDRINUSE
01030 case EADDRINUSE:
01031 return DBUS_ERROR_ADDRESS_IN_USE;
01032 #endif
01033 #ifdef EEXIST
01034 case EEXIST:
01035 return DBUS_ERROR_FILE_EXISTS;
01036 #endif
01037 #ifdef ENOENT
01038 case ENOENT:
01039 return DBUS_ERROR_FILE_NOT_FOUND;
01040 #endif
01041 }
01042
01043 return DBUS_ERROR_FAILED;
01044 }
01045
01049 void
01050 _dbus_set_errno_to_zero (void)
01051 {
01052 errno = 0;
01053 }
01054
01059 dbus_bool_t
01060 _dbus_get_is_errno_nonzero (void)
01061 {
01062 return errno != 0;
01063 }
01064
01069 dbus_bool_t
01070 _dbus_get_is_errno_enomem (void)
01071 {
01072 return errno == ENOMEM;
01073 }
01074
01079 dbus_bool_t
01080 _dbus_get_is_errno_eintr (void)
01081 {
01082 return errno == EINTR;
01083 }
01084
01089 dbus_bool_t
01090 _dbus_get_is_errno_epipe (void)
01091 {
01092 return errno == EPIPE;
01093 }
01094
01099 const char*
01100 _dbus_strerror_from_errno (void)
01101 {
01102 return _dbus_strerror (errno);
01103 }
01104
01107