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 #include "dbus-misc.h"
00032
00033
00034
00035
00036
00037
00038 #include <locale.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <stdio.h>
00042
00043
00044
00045
00046
00047 #ifdef HAVE_ERRNO_H
00048 #include <errno.h>
00049 #endif
00050
00051 _DBUS_DEFINE_GLOBAL_LOCK (win_fds);
00052 _DBUS_DEFINE_GLOBAL_LOCK (sid_atom_cache);
00053 _DBUS_DEFINE_GLOBAL_LOCK (system_users);
00054
00055 extern char **environ;
00056
00074 void
00075 _dbus_abort (void)
00076 {
00077 const char *s;
00078
00079 _dbus_print_backtrace ();
00080
00081 s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
00082 if (s && *s)
00083 {
00084
00085 fprintf (stderr, " Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
00086 _dbus_sleep_milliseconds (1000 * 180);
00087 }
00088
00089 abort ();
00090 _dbus_exit (1);
00091 }
00092
00111 dbus_bool_t
00112 dbus_setenv (const char *varname,
00113 const char *value)
00114 {
00115 _dbus_assert (varname != NULL);
00116
00117 if (value == NULL)
00118 {
00119 #ifdef HAVE_UNSETENV
00120 unsetenv (varname);
00121 return TRUE;
00122 #else
00123 char *putenv_value;
00124 size_t len;
00125
00126 len = strlen (varname);
00127
00128
00129
00130
00131
00132 putenv_value = malloc (len + 2);
00133 if (putenv_value == NULL)
00134 return FALSE;
00135
00136 strcpy (putenv_value, varname);
00137 #if defined(DBUS_WIN)
00138 strcat (putenv_value, "=");
00139 #endif
00140
00141 return (putenv (putenv_value) == 0);
00142 #endif
00143 }
00144 else
00145 {
00146 #ifdef HAVE_SETENV
00147 return (setenv (varname, value, TRUE) == 0);
00148 #else
00149 char *putenv_value;
00150 size_t len;
00151 size_t varname_len;
00152 size_t value_len;
00153
00154 varname_len = strlen (varname);
00155 value_len = strlen (value);
00156
00157 len = varname_len + value_len + 1 ;
00158
00159
00160
00161
00162
00163 putenv_value = malloc (len + 1);
00164 if (putenv_value == NULL)
00165 return FALSE;
00166
00167 strcpy (putenv_value, varname);
00168 strcpy (putenv_value + varname_len, "=");
00169 strcpy (putenv_value + varname_len + 1, value);
00170
00171 return (putenv (putenv_value) == 0);
00172 #endif
00173 }
00174 }
00175
00182 const char*
00183 _dbus_getenv (const char *varname)
00184 {
00185
00186
00187
00188 if (_dbus_check_setuid ())
00189 return NULL;
00190 return getenv (varname);
00191 }
00192
00198 dbus_bool_t
00199 _dbus_clearenv (void)
00200 {
00201 dbus_bool_t rc = TRUE;
00202
00203 #ifdef HAVE_CLEARENV
00204 if (clearenv () != 0)
00205 rc = FALSE;
00206 #else
00207
00208 if (environ != NULL)
00209 environ[0] = NULL;
00210 #endif
00211
00212 return rc;
00213 }
00214
00221 char **
00222 _dbus_get_environment (void)
00223 {
00224 int i, length;
00225 char **environment;
00226
00227 _dbus_assert (environ != NULL);
00228
00229 for (length = 0; environ[length] != NULL; length++);
00230
00231
00232 length++;
00233
00234 environment = dbus_new0 (char *, length);
00235
00236 if (environment == NULL)
00237 return NULL;
00238
00239 for (i = 0; environ[i] != NULL; i++)
00240 {
00241 environment[i] = _dbus_strdup (environ[i]);
00242
00243 if (environment[i] == NULL)
00244 break;
00245 }
00246
00247 if (environ[i] != NULL)
00248 {
00249 dbus_free_string_array (environment);
00250 environment = NULL;
00251 }
00252
00253 return environment;
00254 }
00255
00256
00257
00258
00259
00260
00261
00262 void
00263 _dbus_pipe_init (DBusPipe *pipe,
00264 int fd)
00265 {
00266 pipe->fd_or_handle = fd;
00267 }
00268
00274 void
00275 _dbus_pipe_init_stdout (DBusPipe *pipe)
00276 {
00277 _dbus_pipe_init (pipe, 1);
00278 }
00279
00287 dbus_bool_t
00288 _dbus_pipe_is_valid(DBusPipe *pipe)
00289 {
00290 return pipe->fd_or_handle >= 0;
00291 }
00292
00299 dbus_bool_t
00300 _dbus_pipe_is_stdout_or_stderr (DBusPipe *pipe)
00301 {
00302 return pipe->fd_or_handle == 1 || pipe->fd_or_handle == 2;
00303 }
00304
00309 void
00310 _dbus_pipe_invalidate (DBusPipe *pipe)
00311 {
00312 pipe->fd_or_handle = -1;
00313 }
00314
00323 dbus_bool_t
00324 _dbus_split_paths_and_append (DBusString *dirs,
00325 const char *suffix,
00326 DBusList **dir_list)
00327 {
00328 int start;
00329 int i;
00330 int len;
00331 char *cpath;
00332 DBusString file_suffix;
00333
00334 start = 0;
00335 i = 0;
00336
00337 _dbus_string_init_const (&file_suffix, suffix);
00338
00339 len = _dbus_string_get_length (dirs);
00340
00341 while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
00342 {
00343 DBusString path;
00344
00345 if (!_dbus_string_init (&path))
00346 goto oom;
00347
00348 if (!_dbus_string_copy_len (dirs,
00349 start,
00350 i - start,
00351 &path,
00352 0))
00353 {
00354 _dbus_string_free (&path);
00355 goto oom;
00356 }
00357
00358 _dbus_string_chop_white (&path);
00359
00360
00361 if (_dbus_string_get_length (&path) == 0)
00362 goto next;
00363
00364 if (!_dbus_concat_dir_and_file (&path,
00365 &file_suffix))
00366 {
00367 _dbus_string_free (&path);
00368 goto oom;
00369 }
00370
00371 if (!_dbus_string_copy_data(&path, &cpath))
00372 {
00373 _dbus_string_free (&path);
00374 goto oom;
00375 }
00376
00377 if (!_dbus_list_append (dir_list, cpath))
00378 {
00379 _dbus_string_free (&path);
00380 dbus_free (cpath);
00381 goto oom;
00382 }
00383
00384 next:
00385 _dbus_string_free (&path);
00386 start = i + 1;
00387 }
00388
00389 if (start != len)
00390 {
00391 DBusString path;
00392
00393 if (!_dbus_string_init (&path))
00394 goto oom;
00395
00396 if (!_dbus_string_copy_len (dirs,
00397 start,
00398 len - start,
00399 &path,
00400 0))
00401 {
00402 _dbus_string_free (&path);
00403 goto oom;
00404 }
00405
00406 if (!_dbus_concat_dir_and_file (&path,
00407 &file_suffix))
00408 {
00409 _dbus_string_free (&path);
00410 goto oom;
00411 }
00412
00413 if (!_dbus_string_copy_data(&path, &cpath))
00414 {
00415 _dbus_string_free (&path);
00416 goto oom;
00417 }
00418
00419 if (!_dbus_list_append (dir_list, cpath))
00420 {
00421 _dbus_string_free (&path);
00422 dbus_free (cpath);
00423 goto oom;
00424 }
00425
00426 _dbus_string_free (&path);
00427 }
00428
00429 return TRUE;
00430
00431 oom:
00432 _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL);
00433 _dbus_list_clear (dir_list);
00434 return FALSE;
00435 }
00436
00451 dbus_bool_t
00452 _dbus_string_append_int (DBusString *str,
00453 long value)
00454 {
00455
00456 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
00457 int orig_len;
00458 int i;
00459 char *buf;
00460
00461 orig_len = _dbus_string_get_length (str);
00462
00463 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00464 return FALSE;
00465
00466 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00467
00468 snprintf (buf, MAX_LONG_LEN, "%ld", value);
00469
00470 i = 0;
00471 while (*buf)
00472 {
00473 ++buf;
00474 ++i;
00475 }
00476
00477 _dbus_string_shorten (str, MAX_LONG_LEN - i);
00478
00479 return TRUE;
00480 }
00481
00489 dbus_bool_t
00490 _dbus_string_append_uint (DBusString *str,
00491 unsigned long value)
00492 {
00493
00494 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
00495 int orig_len;
00496 int i;
00497 char *buf;
00498
00499 orig_len = _dbus_string_get_length (str);
00500
00501 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
00502 return FALSE;
00503
00504 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
00505
00506 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
00507
00508 i = 0;
00509 while (*buf)
00510 {
00511 ++buf;
00512 ++i;
00513 }
00514
00515 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
00516
00517 return TRUE;
00518 }
00519
00520 #ifdef DBUS_BUILD_TESTS
00521
00528 dbus_bool_t
00529 _dbus_string_append_double (DBusString *str,
00530 double value)
00531 {
00532 #define MAX_DOUBLE_LEN 64
00533 int orig_len;
00534 char *buf;
00535 int i;
00536
00537 orig_len = _dbus_string_get_length (str);
00538
00539 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
00540 return FALSE;
00541
00542 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
00543
00544 snprintf (buf, MAX_LONG_LEN, "%g", value);
00545
00546 i = 0;
00547 while (*buf)
00548 {
00549 ++buf;
00550 ++i;
00551 }
00552
00553 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
00554
00555 return TRUE;
00556 }
00557 #endif
00558
00571 dbus_bool_t
00572 _dbus_string_parse_int (const DBusString *str,
00573 int start,
00574 long *value_return,
00575 int *end_return)
00576 {
00577 long v;
00578 const char *p;
00579 char *end;
00580
00581 p = _dbus_string_get_const_data_len (str, start,
00582 _dbus_string_get_length (str) - start);
00583
00584 end = NULL;
00585 errno = 0;
00586 v = strtol (p, &end, 0);
00587 if (end == NULL || end == p || errno != 0)
00588 return FALSE;
00589
00590 if (value_return)
00591 *value_return = v;
00592 if (end_return)
00593 *end_return = start + (end - p);
00594
00595 return TRUE;
00596 }
00597
00610 dbus_bool_t
00611 _dbus_string_parse_uint (const DBusString *str,
00612 int start,
00613 unsigned long *value_return,
00614 int *end_return)
00615 {
00616 unsigned long v;
00617 const char *p;
00618 char *end;
00619
00620 p = _dbus_string_get_const_data_len (str, start,
00621 _dbus_string_get_length (str) - start);
00622
00623 end = NULL;
00624 errno = 0;
00625 v = strtoul (p, &end, 0);
00626 if (end == NULL || end == p || errno != 0)
00627 return FALSE;
00628
00629 if (value_return)
00630 *value_return = v;
00631 if (end_return)
00632 *end_return = start + (end - p);
00633
00634 return TRUE;
00635 }
00636
00637 #ifdef DBUS_BUILD_TESTS
00638 static dbus_bool_t
00639 ascii_isspace (char c)
00640 {
00641 return (c == ' ' ||
00642 c == '\f' ||
00643 c == '\n' ||
00644 c == '\r' ||
00645 c == '\t' ||
00646 c == '\v');
00647 }
00648 #endif
00649
00650 #ifdef DBUS_BUILD_TESTS
00651 static dbus_bool_t
00652 ascii_isdigit (char c)
00653 {
00654 return c >= '0' && c <= '9';
00655 }
00656 #endif
00657
00658 #ifdef DBUS_BUILD_TESTS
00659 static dbus_bool_t
00660 ascii_isxdigit (char c)
00661 {
00662 return (ascii_isdigit (c) ||
00663 (c >= 'a' && c <= 'f') ||
00664 (c >= 'A' && c <= 'F'));
00665 }
00666 #endif
00667
00668 #ifdef DBUS_BUILD_TESTS
00669
00670
00671
00672
00673
00674 static double
00675 ascii_strtod (const char *nptr,
00676 char **endptr)
00677 {
00678
00679
00680
00681
00682 char *fail_pos;
00683 double val;
00684 struct lconv *locale_data;
00685 const char *decimal_point;
00686 int decimal_point_len;
00687 const char *p, *decimal_point_pos;
00688 const char *end = NULL;
00689
00690 fail_pos = NULL;
00691
00692 locale_data = localeconv ();
00693 decimal_point = locale_data->decimal_point;
00694 decimal_point_len = strlen (decimal_point);
00695
00696 _dbus_assert (decimal_point_len != 0);
00697
00698 decimal_point_pos = NULL;
00699 if (decimal_point[0] != '.' ||
00700 decimal_point[1] != 0)
00701 {
00702 p = nptr;
00703
00704 while (ascii_isspace (*p))
00705 p++;
00706
00707
00708 if (*p == '+' || *p == '-')
00709 p++;
00710
00711 if (p[0] == '0' &&
00712 (p[1] == 'x' || p[1] == 'X'))
00713 {
00714 p += 2;
00715
00716
00717 while (ascii_isxdigit (*p))
00718 p++;
00719
00720 if (*p == '.')
00721 {
00722 decimal_point_pos = p++;
00723
00724 while (ascii_isxdigit (*p))
00725 p++;
00726
00727 if (*p == 'p' || *p == 'P')
00728 p++;
00729 if (*p == '+' || *p == '-')
00730 p++;
00731 while (ascii_isdigit (*p))
00732 p++;
00733 end = p;
00734 }
00735 }
00736 else
00737 {
00738 while (ascii_isdigit (*p))
00739 p++;
00740
00741 if (*p == '.')
00742 {
00743 decimal_point_pos = p++;
00744
00745 while (ascii_isdigit (*p))
00746 p++;
00747
00748 if (*p == 'e' || *p == 'E')
00749 p++;
00750 if (*p == '+' || *p == '-')
00751 p++;
00752 while (ascii_isdigit (*p))
00753 p++;
00754 end = p;
00755 }
00756 }
00757
00758 }
00759
00760
00761
00762 errno = 0;
00763
00764 if (decimal_point_pos)
00765 {
00766 char *copy, *c;
00767
00768
00769 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
00770
00771 c = copy;
00772 memcpy (c, nptr, decimal_point_pos - nptr);
00773 c += decimal_point_pos - nptr;
00774 memcpy (c, decimal_point, decimal_point_len);
00775 c += decimal_point_len;
00776 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
00777 c += end - (decimal_point_pos + 1);
00778 *c = 0;
00779
00780 val = strtod (copy, &fail_pos);
00781
00782 if (fail_pos)
00783 {
00784 if (fail_pos > decimal_point_pos)
00785 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
00786 else
00787 fail_pos = (char *)nptr + (fail_pos - copy);
00788 }
00789
00790 dbus_free (copy);
00791
00792 }
00793 else
00794 val = strtod (nptr, &fail_pos);
00795
00796 if (endptr)
00797 *endptr = fail_pos;
00798
00799 return val;
00800 }
00801 #endif
00802
00803 #ifdef DBUS_BUILD_TESTS
00804
00816 dbus_bool_t
00817 _dbus_string_parse_double (const DBusString *str,
00818 int start,
00819 double *value_return,
00820 int *end_return)
00821 {
00822 double v;
00823 const char *p;
00824 char *end;
00825
00826 p = _dbus_string_get_const_data_len (str, start,
00827 _dbus_string_get_length (str) - start);
00828
00829
00830
00831
00832 if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
00833 return FALSE;
00834
00835 end = NULL;
00836 errno = 0;
00837 v = ascii_strtod (p, &end);
00838 if (end == NULL || end == p || errno != 0)
00839 return FALSE;
00840
00841 if (value_return)
00842 *value_return = v;
00843 if (end_return)
00844 *end_return = start + (end - p);
00845
00846 return TRUE;
00847 }
00848 #endif
00849
00851
00857 void
00858 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
00859 int n_bytes)
00860 {
00861 long tv_usec;
00862 int i;
00863
00864
00865 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
00866 n_bytes);
00867
00868 _dbus_get_current_time (NULL, &tv_usec);
00869 srand (tv_usec);
00870
00871 i = 0;
00872 while (i < n_bytes)
00873 {
00874 double r;
00875 unsigned int b;
00876
00877 r = rand ();
00878 b = (r / (double) RAND_MAX) * 255.0;
00879
00880 buffer[i] = b;
00881
00882 ++i;
00883 }
00884 }
00885
00892 void
00893 _dbus_generate_random_bytes_buffer (char *buffer,
00894 int n_bytes)
00895 {
00896 DBusString str;
00897
00898 if (!_dbus_string_init (&str))
00899 {
00900 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00901 return;
00902 }
00903
00904 if (!_dbus_generate_random_bytes (&str, n_bytes))
00905 {
00906 _dbus_string_free (&str);
00907 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00908 return;
00909 }
00910
00911 _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
00912
00913 _dbus_string_free (&str);
00914 }
00915
00924 dbus_bool_t
00925 _dbus_generate_random_ascii (DBusString *str,
00926 int n_bytes)
00927 {
00928 static const char letters[] =
00929 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
00930 int i;
00931 int len;
00932
00933 if (!_dbus_generate_random_bytes (str, n_bytes))
00934 return FALSE;
00935
00936 len = _dbus_string_get_length (str);
00937 i = len - n_bytes;
00938 while (i < len)
00939 {
00940 _dbus_string_set_byte (str, i,
00941 letters[_dbus_string_get_byte (str, i) %
00942 (sizeof (letters) - 1)]);
00943
00944 ++i;
00945 }
00946
00947 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
00948 n_bytes));
00949
00950 return TRUE;
00951 }
00952
00963 const char*
00964 _dbus_error_from_errno (int error_number)
00965 {
00966 switch (error_number)
00967 {
00968 case 0:
00969 return DBUS_ERROR_FAILED;
00970
00971 #ifdef EPROTONOSUPPORT
00972 case EPROTONOSUPPORT:
00973 return DBUS_ERROR_NOT_SUPPORTED;
00974 #endif
00975 #ifdef EAFNOSUPPORT
00976 case EAFNOSUPPORT:
00977 return DBUS_ERROR_NOT_SUPPORTED;
00978 #endif
00979 #ifdef ENFILE
00980 case ENFILE:
00981 return DBUS_ERROR_LIMITS_EXCEEDED;
00982 #endif
00983 #ifdef EMFILE
00984 case EMFILE:
00985 return DBUS_ERROR_LIMITS_EXCEEDED;
00986 #endif
00987 #ifdef EACCES
00988 case EACCES:
00989 return DBUS_ERROR_ACCESS_DENIED;
00990 #endif
00991 #ifdef EPERM
00992 case EPERM:
00993 return DBUS_ERROR_ACCESS_DENIED;
00994 #endif
00995 #ifdef ENOBUFS
00996 case ENOBUFS:
00997 return DBUS_ERROR_NO_MEMORY;
00998 #endif
00999 #ifdef ENOMEM
01000 case ENOMEM:
01001 return DBUS_ERROR_NO_MEMORY;
01002 #endif
01003 #ifdef EINVAL
01004 case EINVAL:
01005 return DBUS_ERROR_FAILED;
01006 #endif
01007 #ifdef EBADF
01008 case EBADF:
01009 return DBUS_ERROR_FAILED;
01010 #endif
01011 #ifdef EFAULT
01012 case EFAULT:
01013 return DBUS_ERROR_FAILED;
01014 #endif
01015 #ifdef ENOTSOCK
01016 case ENOTSOCK:
01017 return DBUS_ERROR_FAILED;
01018 #endif
01019 #ifdef EISCONN
01020 case EISCONN:
01021 return DBUS_ERROR_FAILED;
01022 #endif
01023 #ifdef ECONNREFUSED
01024 case ECONNREFUSED:
01025 return DBUS_ERROR_NO_SERVER;
01026 #endif
01027 #ifdef ETIMEDOUT
01028 case ETIMEDOUT:
01029 return DBUS_ERROR_TIMEOUT;
01030 #endif
01031 #ifdef ENETUNREACH
01032 case ENETUNREACH:
01033 return DBUS_ERROR_NO_NETWORK;
01034 #endif
01035 #ifdef EADDRINUSE
01036 case EADDRINUSE:
01037 return DBUS_ERROR_ADDRESS_IN_USE;
01038 #endif
01039 #ifdef EEXIST
01040 case EEXIST:
01041 return DBUS_ERROR_FILE_EXISTS;
01042 #endif
01043 #ifdef ENOENT
01044 case ENOENT:
01045 return DBUS_ERROR_FILE_NOT_FOUND;
01046 #endif
01047 }
01048
01049 return DBUS_ERROR_FAILED;
01050 }
01051
01055 void
01056 _dbus_set_errno_to_zero (void)
01057 {
01058 errno = 0;
01059 }
01060
01065 dbus_bool_t
01066 _dbus_get_is_errno_nonzero (void)
01067 {
01068 return errno != 0;
01069 }
01070
01075 dbus_bool_t
01076 _dbus_get_is_errno_enomem (void)
01077 {
01078 return errno == ENOMEM;
01079 }
01080
01085 dbus_bool_t
01086 _dbus_get_is_errno_eintr (void)
01087 {
01088 return errno == EINTR;
01089 }
01090
01095 dbus_bool_t
01096 _dbus_get_is_errno_epipe (void)
01097 {
01098 return errno == EPIPE;
01099 }
01100
01105 const char*
01106 _dbus_strerror_from_errno (void)
01107 {
01108 return _dbus_strerror (errno);
01109 }
01110
01113