D-Bus
1.6.8
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-sysdeps.c Wrappers around system/libc features shared between UNIX and Windows (internal to D-Bus implementation) 00003 * 00004 * Copyright (C) 2002, 2003, 2006 Red Hat, Inc. 00005 * Copyright (C) 2003 CodeFactory AB 00006 * 00007 * Licensed under the Academic Free License version 2.1 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 */ 00024 00025 #include <config.h> 00026 #include "dbus-internals.h" 00027 #include "dbus-sysdeps.h" 00028 #include "dbus-threads.h" 00029 #include "dbus-protocol.h" 00030 #include "dbus-string.h" 00031 #include "dbus-list.h" 00032 00033 /* NOTE: If you include any unix/windows-specific headers here, you are probably doing something 00034 * wrong and should be putting some code in dbus-sysdeps-unix.c or dbus-sysdeps-win.c. 00035 * 00036 * These are the standard ANSI C headers... 00037 */ 00038 #if HAVE_LOCALE_H 00039 #include <locale.h> 00040 #endif 00041 #include <stdlib.h> 00042 #include <string.h> 00043 #include <stdio.h> 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 _DBUS_DEFINE_GLOBAL_LOCK (system_users); 00052 00053 #ifdef DBUS_WIN 00054 #include <stdlib.h> 00055 #elif (defined __APPLE__) 00056 # include <crt_externs.h> 00057 # define environ (*_NSGetEnviron()) 00058 #else 00059 extern char **environ; 00060 #endif 00061 00079 void 00080 _dbus_abort (void) 00081 { 00082 const char *s; 00083 00084 _dbus_print_backtrace (); 00085 00086 s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT"); 00087 if (s && *s) 00088 { 00089 /* don't use _dbus_warn here since it can _dbus_abort() */ 00090 fprintf (stderr, " Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ()); 00091 _dbus_sleep_milliseconds (1000 * 180); 00092 } 00093 00094 abort (); 00095 _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */ 00096 } 00097 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 /* Use system malloc to avoid memleaks that dbus_malloc 00129 * will get upset about. 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 /* Use system malloc to avoid memleaks that dbus_malloc 00160 * will get upset about. 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 /* Don't respect any environment variables if the current process is 00186 * setuid. This is the equivalent of glibc's __secure_getenv(). 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 00223 dbus_bool_t 00224 _dbus_split_paths_and_append (DBusString *dirs, 00225 const char *suffix, 00226 DBusList **dir_list) 00227 { 00228 int start; 00229 int i; 00230 int len; 00231 char *cpath; 00232 DBusString file_suffix; 00233 00234 start = 0; 00235 i = 0; 00236 00237 _dbus_string_init_const (&file_suffix, suffix); 00238 00239 len = _dbus_string_get_length (dirs); 00240 00241 while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i)) 00242 { 00243 DBusString path; 00244 00245 if (!_dbus_string_init (&path)) 00246 goto oom; 00247 00248 if (!_dbus_string_copy_len (dirs, 00249 start, 00250 i - start, 00251 &path, 00252 0)) 00253 { 00254 _dbus_string_free (&path); 00255 goto oom; 00256 } 00257 00258 _dbus_string_chop_white (&path); 00259 00260 /* check for an empty path */ 00261 if (_dbus_string_get_length (&path) == 0) 00262 goto next; 00263 00264 if (!_dbus_concat_dir_and_file (&path, 00265 &file_suffix)) 00266 { 00267 _dbus_string_free (&path); 00268 goto oom; 00269 } 00270 00271 if (!_dbus_string_copy_data(&path, &cpath)) 00272 { 00273 _dbus_string_free (&path); 00274 goto oom; 00275 } 00276 00277 if (!_dbus_list_append (dir_list, cpath)) 00278 { 00279 _dbus_string_free (&path); 00280 dbus_free (cpath); 00281 goto oom; 00282 } 00283 00284 next: 00285 _dbus_string_free (&path); 00286 start = i + 1; 00287 } 00288 00289 if (start != len) 00290 { 00291 DBusString path; 00292 00293 if (!_dbus_string_init (&path)) 00294 goto oom; 00295 00296 if (!_dbus_string_copy_len (dirs, 00297 start, 00298 len - start, 00299 &path, 00300 0)) 00301 { 00302 _dbus_string_free (&path); 00303 goto oom; 00304 } 00305 00306 if (!_dbus_concat_dir_and_file (&path, 00307 &file_suffix)) 00308 { 00309 _dbus_string_free (&path); 00310 goto oom; 00311 } 00312 00313 if (!_dbus_string_copy_data(&path, &cpath)) 00314 { 00315 _dbus_string_free (&path); 00316 goto oom; 00317 } 00318 00319 if (!_dbus_list_append (dir_list, cpath)) 00320 { 00321 _dbus_string_free (&path); 00322 dbus_free (cpath); 00323 goto oom; 00324 } 00325 00326 _dbus_string_free (&path); 00327 } 00328 00329 return TRUE; 00330 00331 oom: 00332 _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); 00333 _dbus_list_clear (dir_list); 00334 return FALSE; 00335 } 00336 00351 dbus_bool_t 00352 _dbus_string_append_int (DBusString *str, 00353 long value) 00354 { 00355 /* this calculation is from comp.lang.c faq */ 00356 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */ 00357 int orig_len; 00358 int i; 00359 char *buf; 00360 00361 orig_len = _dbus_string_get_length (str); 00362 00363 if (!_dbus_string_lengthen (str, MAX_LONG_LEN)) 00364 return FALSE; 00365 00366 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN); 00367 00368 snprintf (buf, MAX_LONG_LEN, "%ld", value); 00369 00370 i = 0; 00371 while (*buf) 00372 { 00373 ++buf; 00374 ++i; 00375 } 00376 00377 _dbus_string_shorten (str, MAX_LONG_LEN - i); 00378 00379 return TRUE; 00380 } 00381 00389 dbus_bool_t 00390 _dbus_string_append_uint (DBusString *str, 00391 unsigned long value) 00392 { 00393 /* this is wrong, but definitely on the high side. */ 00394 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2) 00395 int orig_len; 00396 int i; 00397 char *buf; 00398 00399 orig_len = _dbus_string_get_length (str); 00400 00401 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN)) 00402 return FALSE; 00403 00404 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN); 00405 00406 snprintf (buf, MAX_ULONG_LEN, "%lu", value); 00407 00408 i = 0; 00409 while (*buf) 00410 { 00411 ++buf; 00412 ++i; 00413 } 00414 00415 _dbus_string_shorten (str, MAX_ULONG_LEN - i); 00416 00417 return TRUE; 00418 } 00419 00432 dbus_bool_t 00433 _dbus_string_parse_int (const DBusString *str, 00434 int start, 00435 long *value_return, 00436 int *end_return) 00437 { 00438 long v; 00439 const char *p; 00440 char *end; 00441 00442 p = _dbus_string_get_const_data_len (str, start, 00443 _dbus_string_get_length (str) - start); 00444 00445 end = NULL; 00446 _dbus_set_errno_to_zero (); 00447 v = strtol (p, &end, 0); 00448 if (end == NULL || end == p || errno != 0) 00449 return FALSE; 00450 00451 if (value_return) 00452 *value_return = v; 00453 if (end_return) 00454 *end_return = start + (end - p); 00455 00456 return TRUE; 00457 } 00458 00471 dbus_bool_t 00472 _dbus_string_parse_uint (const DBusString *str, 00473 int start, 00474 unsigned long *value_return, 00475 int *end_return) 00476 { 00477 unsigned long v; 00478 const char *p; 00479 char *end; 00480 00481 p = _dbus_string_get_const_data_len (str, start, 00482 _dbus_string_get_length (str) - start); 00483 00484 end = NULL; 00485 _dbus_set_errno_to_zero (); 00486 v = strtoul (p, &end, 0); 00487 if (end == NULL || end == p || errno != 0) 00488 return FALSE; 00489 00490 if (value_return) 00491 *value_return = v; 00492 if (end_return) 00493 *end_return = start + (end - p); 00494 00495 return TRUE; 00496 } 00497 /* DBusString group */ 00499 00505 void 00506 _dbus_generate_pseudorandom_bytes_buffer (char *buffer, 00507 int n_bytes) 00508 { 00509 long tv_usec; 00510 int i; 00511 00512 /* fall back to pseudorandom */ 00513 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n", 00514 n_bytes); 00515 00516 _dbus_get_real_time (NULL, &tv_usec); 00517 srand (tv_usec); 00518 00519 i = 0; 00520 while (i < n_bytes) 00521 { 00522 double r; 00523 unsigned int b; 00524 00525 r = rand (); 00526 b = (r / (double) RAND_MAX) * 255.0; 00527 00528 buffer[i] = b; 00529 00530 ++i; 00531 } 00532 } 00533 00540 void 00541 _dbus_generate_random_bytes_buffer (char *buffer, 00542 int n_bytes) 00543 { 00544 DBusString str; 00545 00546 if (!_dbus_string_init (&str)) 00547 { 00548 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes); 00549 return; 00550 } 00551 00552 if (!_dbus_generate_random_bytes (&str, n_bytes)) 00553 { 00554 _dbus_string_free (&str); 00555 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes); 00556 return; 00557 } 00558 00559 _dbus_string_copy_to_buffer (&str, buffer, n_bytes); 00560 00561 _dbus_string_free (&str); 00562 } 00563 00572 dbus_bool_t 00573 _dbus_generate_random_ascii (DBusString *str, 00574 int n_bytes) 00575 { 00576 static const char letters[] = 00577 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; 00578 int i; 00579 int len; 00580 00581 if (!_dbus_generate_random_bytes (str, n_bytes)) 00582 return FALSE; 00583 00584 len = _dbus_string_get_length (str); 00585 i = len - n_bytes; 00586 while (i < len) 00587 { 00588 _dbus_string_set_byte (str, i, 00589 letters[_dbus_string_get_byte (str, i) % 00590 (sizeof (letters) - 1)]); 00591 00592 ++i; 00593 } 00594 00595 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes, 00596 n_bytes)); 00597 00598 return TRUE; 00599 } 00600 00611 const char* 00612 _dbus_error_from_errno (int error_number) 00613 { 00614 switch (error_number) 00615 { 00616 case 0: 00617 return DBUS_ERROR_FAILED; 00618 00619 #ifdef EPROTONOSUPPORT 00620 case EPROTONOSUPPORT: 00621 return DBUS_ERROR_NOT_SUPPORTED; 00622 #elif defined(WSAEPROTONOSUPPORT) 00623 case WSAEPROTONOSUPPORT: 00624 return DBUS_ERROR_NOT_SUPPORTED; 00625 #endif 00626 #ifdef EAFNOSUPPORT 00627 case EAFNOSUPPORT: 00628 return DBUS_ERROR_NOT_SUPPORTED; 00629 #elif defined(WSAEAFNOSUPPORT) 00630 case WSAEAFNOSUPPORT: 00631 return DBUS_ERROR_NOT_SUPPORTED; 00632 #endif 00633 #ifdef ENFILE 00634 case ENFILE: 00635 return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */ 00636 #endif 00637 #ifdef EMFILE 00638 case EMFILE: 00639 return DBUS_ERROR_LIMITS_EXCEEDED; 00640 #endif 00641 #ifdef EACCES 00642 case EACCES: 00643 return DBUS_ERROR_ACCESS_DENIED; 00644 #endif 00645 #ifdef EPERM 00646 case EPERM: 00647 return DBUS_ERROR_ACCESS_DENIED; 00648 #endif 00649 #ifdef ENOBUFS 00650 case ENOBUFS: 00651 return DBUS_ERROR_NO_MEMORY; 00652 #endif 00653 #ifdef ENOMEM 00654 case ENOMEM: 00655 return DBUS_ERROR_NO_MEMORY; 00656 #endif 00657 #ifdef ECONNREFUSED 00658 case ECONNREFUSED: 00659 return DBUS_ERROR_NO_SERVER; 00660 #elif defined(WSAECONNREFUSED) 00661 case WSAECONNREFUSED: 00662 return DBUS_ERROR_NO_SERVER; 00663 #endif 00664 #ifdef ETIMEDOUT 00665 case ETIMEDOUT: 00666 return DBUS_ERROR_TIMEOUT; 00667 #elif defined(WSAETIMEDOUT) 00668 case WSAETIMEDOUT: 00669 return DBUS_ERROR_TIMEOUT; 00670 #endif 00671 #ifdef ENETUNREACH 00672 case ENETUNREACH: 00673 return DBUS_ERROR_NO_NETWORK; 00674 #elif defined(WSAENETUNREACH) 00675 case WSAENETUNREACH: 00676 return DBUS_ERROR_NO_NETWORK; 00677 #endif 00678 #ifdef EADDRINUSE 00679 case EADDRINUSE: 00680 return DBUS_ERROR_ADDRESS_IN_USE; 00681 #elif defined(WSAEADDRINUSE) 00682 case WSAEADDRINUSE: 00683 return DBUS_ERROR_ADDRESS_IN_USE; 00684 #endif 00685 #ifdef EEXIST 00686 case EEXIST: 00687 return DBUS_ERROR_FILE_EXISTS; 00688 #endif 00689 #ifdef ENOENT 00690 case ENOENT: 00691 return DBUS_ERROR_FILE_NOT_FOUND; 00692 #endif 00693 } 00694 00695 return DBUS_ERROR_FAILED; 00696 } 00697 00703 const char* 00704 _dbus_error_from_system_errno (void) 00705 { 00706 return _dbus_error_from_errno (errno); 00707 } 00708 00712 void 00713 _dbus_set_errno_to_zero (void) 00714 { 00715 #ifdef DBUS_WINCE 00716 SetLastError (0); 00717 #else 00718 errno = 0; 00719 #endif 00720 } 00721 00726 dbus_bool_t 00727 _dbus_get_is_errno_nonzero (void) 00728 { 00729 return errno != 0; 00730 } 00731 00736 dbus_bool_t 00737 _dbus_get_is_errno_enomem (void) 00738 { 00739 return errno == ENOMEM; 00740 } 00741 00746 dbus_bool_t 00747 _dbus_get_is_errno_eintr (void) 00748 { 00749 return errno == EINTR; 00750 } 00751 00756 dbus_bool_t 00757 _dbus_get_is_errno_epipe (void) 00758 { 00759 return errno == EPIPE; 00760 } 00761 00766 const char* 00767 _dbus_strerror_from_errno (void) 00768 { 00769 return _dbus_strerror (errno); 00770 } 00771 00774 /* tests in dbus-sysdeps-util.c */