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
00178
00179
00180 if (_dbus_check_setuid ())
00181 return NULL;
00182 return getenv (varname);
00183 }
00184
00190 dbus_bool_t
00191 _dbus_clearenv (void)
00192 {
00193 dbus_bool_t rc = TRUE;
00194
00195 #ifdef HAVE_CLEARENV
00196 if (clearenv () != 0)
00197 rc = FALSE;
00198 #else
00199 extern char **environ;
00200
00201 if (environ != NULL)
00202 environ[0] = NULL;
00203 #endif
00204
00205 return rc;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214 void
00215 _dbus_pipe_init (DBusPipe *pipe,
00216 int fd)
00217 {
00218 pipe->fd_or_handle = fd;
00219 }
00220
00226 void
00227 _dbus_pipe_init_stdout (DBusPipe *pipe)
00228 {
00229 _dbus_pipe_init (pipe, 1);
00230 }
00231
00239 dbus_bool_t
00240 _dbus_pipe_is_valid(DBusPipe *pipe)
00241 {
00242 return pipe->fd_or_handle >= 0;
00243 }
00244
00251 dbus_bool_t
00252 _dbus_pipe_is_stdout_or_stderr (DBusPipe *pipe)
00253 {
00254 return pipe->fd_or_handle == 1 || pipe->fd_or_handle == 2;
00255 }
00256
00261 void
00262 _dbus_pipe_invalidate (DBusPipe *pipe)
00263 {
00264 pipe->fd_or_handle = -1;
00265 }
00266
00275 dbus_bool_t
00276 _dbus_split_paths_and_append (DBusString *dirs,
00277 const char *suffix,
00278 DBusList **dir_list)
00279 {
00280 int start;
00281 int i;
00282 int len;
00283 char *cpath;
00284 DBusString file_suffix;
00285
00286 start = 0;
00287 i = 0;
00288
00289 _dbus_string_init_const (&file_suffix, suffix);
00290
00291 len = _dbus_string_get_length (dirs);
00292
00293 while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
00294 {
00295 DBusString path;
00296
00297 if (!_dbus_string_init (&path))
00298 goto oom;
00299
00300 if (!_dbus_string_copy_len (dirs,
00301 start,
00302 i - start,
00303 &path,
00304 0))
00305 {
00306 _dbus_string_free (&path);
00307 goto oom;
00308 }
00309
00310 _dbus_string_chop_white (&path);
00311
00312
00313 if (_dbus_string_get_length (&path) == 0)
00314 goto next;
00315
00316 if (!_dbus_concat_dir_and_file (&path,
00317 &file_suffix))
00318 {
00319 _dbus_string_free (&path);
00320 goto oom;
00321 }
00322
00323 if (!_dbus_string_copy_data(&path, &cpath))
00324 {
00325 _dbus_string_free (&path);
00326 goto oom;
00327 }
00328
00329 if (!_dbus_list_append (dir_list, cpath))
00330 {
00331 _dbus_string_free (&path);
00332 dbus_free (cpath);
00333 goto oom;
00334 }
00335
00336 next:
00337 _dbus_string_free (&path);
00338 start = i + 1;
00339 }
00340
00341 if (start != len)
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 len - start,
00351 &path,
00352 0))
00353 {
00354 _dbus_string_free (&path);
00355 goto oom;
00356 }
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 _dbus_string_free (&path);
00379 }
00380
00381 return TRUE;
00382
00383 oom:
00384 _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL);
00385 _dbus_list_clear (dir_list);
00386 return FALSE;
00387 }
00388
00403 dbus_bool_t
00404 _dbus_string_append_int (DBusString *str,
00405 long value)
00406 {
00407
00408 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
00409 int orig_len;
00410 int i;
00411 char *buf;
00412
00413 orig_len = _dbus_string_get_length (str);
00414
00415 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
00416 return FALSE;
00417
00418 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
00419
00420 snprintf (buf, MAX_LONG_LEN, "%ld", value);
00421
00422 i = 0;
00423 while (*buf)
00424 {
00425 ++buf;
00426 ++i;
00427 }
00428
00429 _dbus_string_shorten (str, MAX_LONG_LEN - i);
00430
00431 return TRUE;
00432 }
00433
00441 dbus_bool_t
00442 _dbus_string_append_uint (DBusString *str,
00443 unsigned long value)
00444 {
00445
00446 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
00447 int orig_len;
00448 int i;
00449 char *buf;
00450
00451 orig_len = _dbus_string_get_length (str);
00452
00453 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
00454 return FALSE;
00455
00456 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
00457
00458 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
00459
00460 i = 0;
00461 while (*buf)
00462 {
00463 ++buf;
00464 ++i;
00465 }
00466
00467 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
00468
00469 return TRUE;
00470 }
00471
00472 #ifdef DBUS_BUILD_TESTS
00473
00480 dbus_bool_t
00481 _dbus_string_append_double (DBusString *str,
00482 double value)
00483 {
00484 #define MAX_DOUBLE_LEN 64
00485 int orig_len;
00486 char *buf;
00487 int i;
00488
00489 orig_len = _dbus_string_get_length (str);
00490
00491 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
00492 return FALSE;
00493
00494 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
00495
00496 snprintf (buf, MAX_LONG_LEN, "%g", value);
00497
00498 i = 0;
00499 while (*buf)
00500 {
00501 ++buf;
00502 ++i;
00503 }
00504
00505 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
00506
00507 return TRUE;
00508 }
00509 #endif
00510
00523 dbus_bool_t
00524 _dbus_string_parse_int (const DBusString *str,
00525 int start,
00526 long *value_return,
00527 int *end_return)
00528 {
00529 long v;
00530 const char *p;
00531 char *end;
00532
00533 p = _dbus_string_get_const_data_len (str, start,
00534 _dbus_string_get_length (str) - start);
00535
00536 end = NULL;
00537 errno = 0;
00538 v = strtol (p, &end, 0);
00539 if (end == NULL || end == p || errno != 0)
00540 return FALSE;
00541
00542 if (value_return)
00543 *value_return = v;
00544 if (end_return)
00545 *end_return = start + (end - p);
00546
00547 return TRUE;
00548 }
00549
00562 dbus_bool_t
00563 _dbus_string_parse_uint (const DBusString *str,
00564 int start,
00565 unsigned long *value_return,
00566 int *end_return)
00567 {
00568 unsigned long v;
00569 const char *p;
00570 char *end;
00571
00572 p = _dbus_string_get_const_data_len (str, start,
00573 _dbus_string_get_length (str) - start);
00574
00575 end = NULL;
00576 errno = 0;
00577 v = strtoul (p, &end, 0);
00578 if (end == NULL || end == p || errno != 0)
00579 return FALSE;
00580
00581 if (value_return)
00582 *value_return = v;
00583 if (end_return)
00584 *end_return = start + (end - p);
00585
00586 return TRUE;
00587 }
00588
00589 #ifdef DBUS_BUILD_TESTS
00590 static dbus_bool_t
00591 ascii_isspace (char c)
00592 {
00593 return (c == ' ' ||
00594 c == '\f' ||
00595 c == '\n' ||
00596 c == '\r' ||
00597 c == '\t' ||
00598 c == '\v');
00599 }
00600 #endif
00601
00602 #ifdef DBUS_BUILD_TESTS
00603 static dbus_bool_t
00604 ascii_isdigit (char c)
00605 {
00606 return c >= '0' && c <= '9';
00607 }
00608 #endif
00609
00610 #ifdef DBUS_BUILD_TESTS
00611 static dbus_bool_t
00612 ascii_isxdigit (char c)
00613 {
00614 return (ascii_isdigit (c) ||
00615 (c >= 'a' && c <= 'f') ||
00616 (c >= 'A' && c <= 'F'));
00617 }
00618 #endif
00619
00620 #ifdef DBUS_BUILD_TESTS
00621
00622
00623
00624
00625
00626 static double
00627 ascii_strtod (const char *nptr,
00628 char **endptr)
00629 {
00630
00631
00632
00633
00634 char *fail_pos;
00635 double val;
00636 struct lconv *locale_data;
00637 const char *decimal_point;
00638 int decimal_point_len;
00639 const char *p, *decimal_point_pos;
00640 const char *end = NULL;
00641
00642 fail_pos = NULL;
00643
00644 locale_data = localeconv ();
00645 decimal_point = locale_data->decimal_point;
00646 decimal_point_len = strlen (decimal_point);
00647
00648 _dbus_assert (decimal_point_len != 0);
00649
00650 decimal_point_pos = NULL;
00651 if (decimal_point[0] != '.' ||
00652 decimal_point[1] != 0)
00653 {
00654 p = nptr;
00655
00656 while (ascii_isspace (*p))
00657 p++;
00658
00659
00660 if (*p == '+' || *p == '-')
00661 p++;
00662
00663 if (p[0] == '0' &&
00664 (p[1] == 'x' || p[1] == 'X'))
00665 {
00666 p += 2;
00667
00668
00669 while (ascii_isxdigit (*p))
00670 p++;
00671
00672 if (*p == '.')
00673 {
00674 decimal_point_pos = p++;
00675
00676 while (ascii_isxdigit (*p))
00677 p++;
00678
00679 if (*p == 'p' || *p == 'P')
00680 p++;
00681 if (*p == '+' || *p == '-')
00682 p++;
00683 while (ascii_isdigit (*p))
00684 p++;
00685 end = p;
00686 }
00687 }
00688 else
00689 {
00690 while (ascii_isdigit (*p))
00691 p++;
00692
00693 if (*p == '.')
00694 {
00695 decimal_point_pos = p++;
00696
00697 while (ascii_isdigit (*p))
00698 p++;
00699
00700 if (*p == 'e' || *p == 'E')
00701 p++;
00702 if (*p == '+' || *p == '-')
00703 p++;
00704 while (ascii_isdigit (*p))
00705 p++;
00706 end = p;
00707 }
00708 }
00709
00710 }
00711
00712
00713
00714 errno = 0;
00715
00716 if (decimal_point_pos)
00717 {
00718 char *copy, *c;
00719
00720
00721 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
00722
00723 c = copy;
00724 memcpy (c, nptr, decimal_point_pos - nptr);
00725 c += decimal_point_pos - nptr;
00726 memcpy (c, decimal_point, decimal_point_len);
00727 c += decimal_point_len;
00728 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
00729 c += end - (decimal_point_pos + 1);
00730 *c = 0;
00731
00732 val = strtod (copy, &fail_pos);
00733
00734 if (fail_pos)
00735 {
00736 if (fail_pos > decimal_point_pos)
00737 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
00738 else
00739 fail_pos = (char *)nptr + (fail_pos - copy);
00740 }
00741
00742 dbus_free (copy);
00743
00744 }
00745 else
00746 val = strtod (nptr, &fail_pos);
00747
00748 if (endptr)
00749 *endptr = fail_pos;
00750
00751 return val;
00752 }
00753 #endif
00754
00755 #ifdef DBUS_BUILD_TESTS
00756
00768 dbus_bool_t
00769 _dbus_string_parse_double (const DBusString *str,
00770 int start,
00771 double *value_return,
00772 int *end_return)
00773 {
00774 double v;
00775 const char *p;
00776 char *end;
00777
00778 p = _dbus_string_get_const_data_len (str, start,
00779 _dbus_string_get_length (str) - start);
00780
00781
00782
00783
00784 if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
00785 return FALSE;
00786
00787 end = NULL;
00788 errno = 0;
00789 v = ascii_strtod (p, &end);
00790 if (end == NULL || end == p || errno != 0)
00791 return FALSE;
00792
00793 if (value_return)
00794 *value_return = v;
00795 if (end_return)
00796 *end_return = start + (end - p);
00797
00798 return TRUE;
00799 }
00800 #endif
00801
00803
00809 void
00810 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
00811 int n_bytes)
00812 {
00813 long tv_usec;
00814 int i;
00815
00816
00817 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
00818 n_bytes);
00819
00820 _dbus_get_current_time (NULL, &tv_usec);
00821 srand (tv_usec);
00822
00823 i = 0;
00824 while (i < n_bytes)
00825 {
00826 double r;
00827 unsigned int b;
00828
00829 r = rand ();
00830 b = (r / (double) RAND_MAX) * 255.0;
00831
00832 buffer[i] = b;
00833
00834 ++i;
00835 }
00836 }
00837
00844 void
00845 _dbus_generate_random_bytes_buffer (char *buffer,
00846 int n_bytes)
00847 {
00848 DBusString str;
00849
00850 if (!_dbus_string_init (&str))
00851 {
00852 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00853 return;
00854 }
00855
00856 if (!_dbus_generate_random_bytes (&str, n_bytes))
00857 {
00858 _dbus_string_free (&str);
00859 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
00860 return;
00861 }
00862
00863 _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
00864
00865 _dbus_string_free (&str);
00866 }
00867
00876 dbus_bool_t
00877 _dbus_generate_random_ascii (DBusString *str,
00878 int n_bytes)
00879 {
00880 static const char letters[] =
00881 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
00882 int i;
00883 int len;
00884
00885 if (!_dbus_generate_random_bytes (str, n_bytes))
00886 return FALSE;
00887
00888 len = _dbus_string_get_length (str);
00889 i = len - n_bytes;
00890 while (i < len)
00891 {
00892 _dbus_string_set_byte (str, i,
00893 letters[_dbus_string_get_byte (str, i) %
00894 (sizeof (letters) - 1)]);
00895
00896 ++i;
00897 }
00898
00899 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
00900 n_bytes));
00901
00902 return TRUE;
00903 }
00904
00915 const char*
00916 _dbus_error_from_errno (int error_number)
00917 {
00918 switch (error_number)
00919 {
00920 case 0:
00921 return DBUS_ERROR_FAILED;
00922
00923 #ifdef EPROTONOSUPPORT
00924 case EPROTONOSUPPORT:
00925 return DBUS_ERROR_NOT_SUPPORTED;
00926 #endif
00927 #ifdef EAFNOSUPPORT
00928 case EAFNOSUPPORT:
00929 return DBUS_ERROR_NOT_SUPPORTED;
00930 #endif
00931 #ifdef ENFILE
00932 case ENFILE:
00933 return DBUS_ERROR_LIMITS_EXCEEDED;
00934 #endif
00935 #ifdef EMFILE
00936 case EMFILE:
00937 return DBUS_ERROR_LIMITS_EXCEEDED;
00938 #endif
00939 #ifdef EACCES
00940 case EACCES:
00941 return DBUS_ERROR_ACCESS_DENIED;
00942 #endif
00943 #ifdef EPERM
00944 case EPERM:
00945 return DBUS_ERROR_ACCESS_DENIED;
00946 #endif
00947 #ifdef ENOBUFS
00948 case ENOBUFS:
00949 return DBUS_ERROR_NO_MEMORY;
00950 #endif
00951 #ifdef ENOMEM
00952 case ENOMEM:
00953 return DBUS_ERROR_NO_MEMORY;
00954 #endif
00955 #ifdef EINVAL
00956 case EINVAL:
00957 return DBUS_ERROR_FAILED;
00958 #endif
00959 #ifdef EBADF
00960 case EBADF:
00961 return DBUS_ERROR_FAILED;
00962 #endif
00963 #ifdef EFAULT
00964 case EFAULT:
00965 return DBUS_ERROR_FAILED;
00966 #endif
00967 #ifdef ENOTSOCK
00968 case ENOTSOCK:
00969 return DBUS_ERROR_FAILED;
00970 #endif
00971 #ifdef EISCONN
00972 case EISCONN:
00973 return DBUS_ERROR_FAILED;
00974 #endif
00975 #ifdef ECONNREFUSED
00976 case ECONNREFUSED:
00977 return DBUS_ERROR_NO_SERVER;
00978 #endif
00979 #ifdef ETIMEDOUT
00980 case ETIMEDOUT:
00981 return DBUS_ERROR_TIMEOUT;
00982 #endif
00983 #ifdef ENETUNREACH
00984 case ENETUNREACH:
00985 return DBUS_ERROR_NO_NETWORK;
00986 #endif
00987 #ifdef EADDRINUSE
00988 case EADDRINUSE:
00989 return DBUS_ERROR_ADDRESS_IN_USE;
00990 #endif
00991 #ifdef EEXIST
00992 case EEXIST:
00993 return DBUS_ERROR_FILE_EXISTS;
00994 #endif
00995 #ifdef ENOENT
00996 case ENOENT:
00997 return DBUS_ERROR_FILE_NOT_FOUND;
00998 #endif
00999 }
01000
01001 return DBUS_ERROR_FAILED;
01002 }
01003
01007 void
01008 _dbus_set_errno_to_zero (void)
01009 {
01010 errno = 0;
01011 }
01012
01017 dbus_bool_t
01018 _dbus_get_is_errno_nonzero (void)
01019 {
01020 return errno != 0;
01021 }
01022
01027 dbus_bool_t
01028 _dbus_get_is_errno_enomem (void)
01029 {
01030 return errno == ENOMEM;
01031 }
01032
01037 dbus_bool_t
01038 _dbus_get_is_errno_eintr (void)
01039 {
01040 return errno == EINTR;
01041 }
01042
01047 const char*
01048 _dbus_strerror_from_errno (void)
01049 {
01050 return _dbus_strerror (errno);
01051 }
01052
01055