|
D-Bus
1.8.20
|
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 #include "dbus-misc.h" 00033 00034 /* NOTE: If you include any unix/windows-specific headers here, you are probably doing something 00035 * wrong and should be putting some code in dbus-sysdeps-unix.c or dbus-sysdeps-win.c. 00036 * 00037 * These are the standard ANSI C headers... 00038 */ 00039 #if HAVE_LOCALE_H 00040 #include <locale.h> 00041 #endif 00042 #include <stdlib.h> 00043 #include <string.h> 00044 #include <stdio.h> 00045 00046 #ifdef HAVE_ERRNO_H 00047 #include <errno.h> 00048 #endif 00049 00050 #ifdef DBUS_WIN 00051 #include <stdlib.h> 00052 #elif (defined __APPLE__) 00053 # include <crt_externs.h> 00054 # define environ (*_NSGetEnviron()) 00055 #else 00056 extern char **environ; 00057 #endif 00058 00076 void 00077 _dbus_abort (void) 00078 { 00079 const char *s; 00080 00081 _dbus_print_backtrace (); 00082 00083 s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT"); 00084 if (s && *s) 00085 { 00086 /* don't use _dbus_warn here since it can _dbus_abort() */ 00087 fprintf (stderr, " Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ()); 00088 _dbus_sleep_milliseconds (1000 * 180); 00089 } 00090 00091 abort (); 00092 _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */ 00093 } 00094 00113 dbus_bool_t 00114 dbus_setenv (const char *varname, 00115 const char *value) 00116 { 00117 _dbus_assert (varname != NULL); 00118 00119 if (value == NULL) 00120 { 00121 #ifdef HAVE_UNSETENV 00122 unsetenv (varname); 00123 return TRUE; 00124 #else 00125 char *putenv_value; 00126 size_t len; 00127 00128 len = strlen (varname); 00129 00130 /* Use system malloc to avoid memleaks that dbus_malloc 00131 * will get upset about. 00132 */ 00133 00134 putenv_value = malloc (len + 2); 00135 if (putenv_value == NULL) 00136 return FALSE; 00137 00138 strcpy (putenv_value, varname); 00139 #if defined(DBUS_WIN) 00140 strcat (putenv_value, "="); 00141 #endif 00142 00143 return (putenv (putenv_value) == 0); 00144 #endif 00145 } 00146 else 00147 { 00148 #ifdef HAVE_SETENV 00149 return (setenv (varname, value, TRUE) == 0); 00150 #else 00151 char *putenv_value; 00152 size_t len; 00153 size_t varname_len; 00154 size_t value_len; 00155 00156 varname_len = strlen (varname); 00157 value_len = strlen (value); 00158 00159 len = varname_len + value_len + 1 /* '=' */ ; 00160 00161 /* Use system malloc to avoid memleaks that dbus_malloc 00162 * will get upset about. 00163 */ 00164 00165 putenv_value = malloc (len + 1); 00166 if (putenv_value == NULL) 00167 return FALSE; 00168 00169 strcpy (putenv_value, varname); 00170 strcpy (putenv_value + varname_len, "="); 00171 strcpy (putenv_value + varname_len + 1, value); 00172 00173 return (putenv (putenv_value) == 0); 00174 #endif 00175 } 00176 } 00177 00184 const char* 00185 _dbus_getenv (const char *varname) 00186 { 00187 return getenv (varname); 00188 } 00189 00195 dbus_bool_t 00196 _dbus_clearenv (void) 00197 { 00198 dbus_bool_t rc = TRUE; 00199 00200 #ifdef HAVE_CLEARENV 00201 if (clearenv () != 0) 00202 rc = FALSE; 00203 #else 00204 00205 if (environ != NULL) 00206 environ[0] = NULL; 00207 #endif 00208 00209 return rc; 00210 } 00211 00220 dbus_bool_t 00221 _dbus_split_paths_and_append (DBusString *dirs, 00222 const char *suffix, 00223 DBusList **dir_list) 00224 { 00225 int start; 00226 int i; 00227 int len; 00228 char *cpath; 00229 DBusString file_suffix; 00230 00231 start = 0; 00232 i = 0; 00233 00234 _dbus_string_init_const (&file_suffix, suffix); 00235 00236 len = _dbus_string_get_length (dirs); 00237 00238 while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i)) 00239 { 00240 DBusString path; 00241 00242 if (!_dbus_string_init (&path)) 00243 goto oom; 00244 00245 if (!_dbus_string_copy_len (dirs, 00246 start, 00247 i - start, 00248 &path, 00249 0)) 00250 { 00251 _dbus_string_free (&path); 00252 goto oom; 00253 } 00254 00255 _dbus_string_chop_white (&path); 00256 00257 /* check for an empty path */ 00258 if (_dbus_string_get_length (&path) == 0) 00259 goto next; 00260 00261 if (!_dbus_concat_dir_and_file (&path, 00262 &file_suffix)) 00263 { 00264 _dbus_string_free (&path); 00265 goto oom; 00266 } 00267 00268 if (!_dbus_string_copy_data(&path, &cpath)) 00269 { 00270 _dbus_string_free (&path); 00271 goto oom; 00272 } 00273 00274 if (!_dbus_list_append (dir_list, cpath)) 00275 { 00276 _dbus_string_free (&path); 00277 dbus_free (cpath); 00278 goto oom; 00279 } 00280 00281 next: 00282 _dbus_string_free (&path); 00283 start = i + 1; 00284 } 00285 00286 if (start != len) 00287 { 00288 DBusString path; 00289 00290 if (!_dbus_string_init (&path)) 00291 goto oom; 00292 00293 if (!_dbus_string_copy_len (dirs, 00294 start, 00295 len - start, 00296 &path, 00297 0)) 00298 { 00299 _dbus_string_free (&path); 00300 goto oom; 00301 } 00302 00303 if (!_dbus_concat_dir_and_file (&path, 00304 &file_suffix)) 00305 { 00306 _dbus_string_free (&path); 00307 goto oom; 00308 } 00309 00310 if (!_dbus_string_copy_data(&path, &cpath)) 00311 { 00312 _dbus_string_free (&path); 00313 goto oom; 00314 } 00315 00316 if (!_dbus_list_append (dir_list, cpath)) 00317 { 00318 _dbus_string_free (&path); 00319 dbus_free (cpath); 00320 goto oom; 00321 } 00322 00323 _dbus_string_free (&path); 00324 } 00325 00326 return TRUE; 00327 00328 oom: 00329 _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); 00330 _dbus_list_clear (dir_list); 00331 return FALSE; 00332 } 00333 00348 dbus_bool_t 00349 _dbus_string_append_int (DBusString *str, 00350 long value) 00351 { 00352 /* this calculation is from comp.lang.c faq */ 00353 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */ 00354 int orig_len; 00355 int i; 00356 char *buf; 00357 00358 orig_len = _dbus_string_get_length (str); 00359 00360 if (!_dbus_string_lengthen (str, MAX_LONG_LEN)) 00361 return FALSE; 00362 00363 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN); 00364 00365 snprintf (buf, MAX_LONG_LEN, "%ld", value); 00366 00367 i = 0; 00368 while (*buf) 00369 { 00370 ++buf; 00371 ++i; 00372 } 00373 00374 _dbus_string_shorten (str, MAX_LONG_LEN - i); 00375 00376 return TRUE; 00377 } 00378 00386 dbus_bool_t 00387 _dbus_string_append_uint (DBusString *str, 00388 unsigned long value) 00389 { 00390 /* this is wrong, but definitely on the high side. */ 00391 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2) 00392 int orig_len; 00393 int i; 00394 char *buf; 00395 00396 orig_len = _dbus_string_get_length (str); 00397 00398 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN)) 00399 return FALSE; 00400 00401 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN); 00402 00403 snprintf (buf, MAX_ULONG_LEN, "%lu", value); 00404 00405 i = 0; 00406 while (*buf) 00407 { 00408 ++buf; 00409 ++i; 00410 } 00411 00412 _dbus_string_shorten (str, MAX_ULONG_LEN - i); 00413 00414 return TRUE; 00415 } 00416 00429 dbus_bool_t 00430 _dbus_string_parse_int (const DBusString *str, 00431 int start, 00432 long *value_return, 00433 int *end_return) 00434 { 00435 long v; 00436 const char *p; 00437 char *end; 00438 00439 p = _dbus_string_get_const_data_len (str, start, 00440 _dbus_string_get_length (str) - start); 00441 00442 end = NULL; 00443 _dbus_set_errno_to_zero (); 00444 v = strtol (p, &end, 0); 00445 if (end == NULL || end == p || errno != 0) 00446 return FALSE; 00447 00448 if (value_return) 00449 *value_return = v; 00450 if (end_return) 00451 *end_return = start + (end - p); 00452 00453 return TRUE; 00454 } 00455 00468 dbus_bool_t 00469 _dbus_string_parse_uint (const DBusString *str, 00470 int start, 00471 unsigned long *value_return, 00472 int *end_return) 00473 { 00474 unsigned long v; 00475 const char *p; 00476 char *end; 00477 00478 p = _dbus_string_get_const_data_len (str, start, 00479 _dbus_string_get_length (str) - start); 00480 00481 end = NULL; 00482 _dbus_set_errno_to_zero (); 00483 v = strtoul (p, &end, 0); 00484 if (end == NULL || end == p || errno != 0) 00485 return FALSE; 00486 00487 if (value_return) 00488 *value_return = v; 00489 if (end_return) 00490 *end_return = start + (end - p); 00491 00492 return TRUE; 00493 } 00494 /* DBusString group */ 00496 00502 void 00503 _dbus_generate_pseudorandom_bytes_buffer (char *buffer, 00504 int n_bytes) 00505 { 00506 long tv_usec; 00507 int i; 00508 00509 /* fall back to pseudorandom */ 00510 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n", 00511 n_bytes); 00512 00513 _dbus_get_real_time (NULL, &tv_usec); 00514 srand (tv_usec); 00515 00516 i = 0; 00517 while (i < n_bytes) 00518 { 00519 double r; 00520 unsigned int b; 00521 00522 r = rand (); 00523 b = (r / (double) RAND_MAX) * 255.0; 00524 00525 buffer[i] = b; 00526 00527 ++i; 00528 } 00529 } 00530 00537 void 00538 _dbus_generate_random_bytes_buffer (char *buffer, 00539 int n_bytes) 00540 { 00541 DBusString str; 00542 00543 if (!_dbus_string_init (&str)) 00544 { 00545 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes); 00546 return; 00547 } 00548 00549 if (!_dbus_generate_random_bytes (&str, n_bytes)) 00550 { 00551 _dbus_string_free (&str); 00552 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes); 00553 return; 00554 } 00555 00556 _dbus_string_copy_to_buffer (&str, buffer, n_bytes); 00557 00558 _dbus_string_free (&str); 00559 } 00560 00569 dbus_bool_t 00570 _dbus_generate_random_ascii (DBusString *str, 00571 int n_bytes) 00572 { 00573 static const char letters[] = 00574 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; 00575 int i; 00576 int len; 00577 00578 if (!_dbus_generate_random_bytes (str, n_bytes)) 00579 return FALSE; 00580 00581 len = _dbus_string_get_length (str); 00582 i = len - n_bytes; 00583 while (i < len) 00584 { 00585 _dbus_string_set_byte (str, i, 00586 letters[_dbus_string_get_byte (str, i) % 00587 (sizeof (letters) - 1)]); 00588 00589 ++i; 00590 } 00591 00592 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes, 00593 n_bytes)); 00594 00595 return TRUE; 00596 } 00597 00608 const char* 00609 _dbus_error_from_errno (int error_number) 00610 { 00611 switch (error_number) 00612 { 00613 case 0: 00614 return DBUS_ERROR_FAILED; 00615 00616 #ifdef EPROTONOSUPPORT 00617 case EPROTONOSUPPORT: 00618 return DBUS_ERROR_NOT_SUPPORTED; 00619 #elif defined(WSAEPROTONOSUPPORT) 00620 case WSAEPROTONOSUPPORT: 00621 return DBUS_ERROR_NOT_SUPPORTED; 00622 #endif 00623 #ifdef EAFNOSUPPORT 00624 case EAFNOSUPPORT: 00625 return DBUS_ERROR_NOT_SUPPORTED; 00626 #elif defined(WSAEAFNOSUPPORT) 00627 case WSAEAFNOSUPPORT: 00628 return DBUS_ERROR_NOT_SUPPORTED; 00629 #endif 00630 #ifdef ENFILE 00631 case ENFILE: 00632 return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */ 00633 #endif 00634 #ifdef EMFILE 00635 case EMFILE: 00636 return DBUS_ERROR_LIMITS_EXCEEDED; 00637 #endif 00638 #ifdef EACCES 00639 case EACCES: 00640 return DBUS_ERROR_ACCESS_DENIED; 00641 #endif 00642 #ifdef EPERM 00643 case EPERM: 00644 return DBUS_ERROR_ACCESS_DENIED; 00645 #endif 00646 #ifdef ENOBUFS 00647 case ENOBUFS: 00648 return DBUS_ERROR_NO_MEMORY; 00649 #endif 00650 #ifdef ENOMEM 00651 case ENOMEM: 00652 return DBUS_ERROR_NO_MEMORY; 00653 #endif 00654 #ifdef ECONNREFUSED 00655 case ECONNREFUSED: 00656 return DBUS_ERROR_NO_SERVER; 00657 #elif defined(WSAECONNREFUSED) 00658 case WSAECONNREFUSED: 00659 return DBUS_ERROR_NO_SERVER; 00660 #endif 00661 #ifdef ETIMEDOUT 00662 case ETIMEDOUT: 00663 return DBUS_ERROR_TIMEOUT; 00664 #elif defined(WSAETIMEDOUT) 00665 case WSAETIMEDOUT: 00666 return DBUS_ERROR_TIMEOUT; 00667 #endif 00668 #ifdef ENETUNREACH 00669 case ENETUNREACH: 00670 return DBUS_ERROR_NO_NETWORK; 00671 #elif defined(WSAENETUNREACH) 00672 case WSAENETUNREACH: 00673 return DBUS_ERROR_NO_NETWORK; 00674 #endif 00675 #ifdef EADDRINUSE 00676 case EADDRINUSE: 00677 return DBUS_ERROR_ADDRESS_IN_USE; 00678 #elif defined(WSAEADDRINUSE) 00679 case WSAEADDRINUSE: 00680 return DBUS_ERROR_ADDRESS_IN_USE; 00681 #endif 00682 #ifdef EEXIST 00683 case EEXIST: 00684 return DBUS_ERROR_FILE_EXISTS; 00685 #endif 00686 #ifdef ENOENT 00687 case ENOENT: 00688 return DBUS_ERROR_FILE_NOT_FOUND; 00689 #endif 00690 } 00691 00692 return DBUS_ERROR_FAILED; 00693 } 00694 00700 const char* 00701 _dbus_error_from_system_errno (void) 00702 { 00703 return _dbus_error_from_errno (errno); 00704 } 00705 00709 void 00710 _dbus_set_errno_to_zero (void) 00711 { 00712 #ifdef DBUS_WINCE 00713 SetLastError (0); 00714 #else 00715 errno = 0; 00716 #endif 00717 } 00718 00723 dbus_bool_t 00724 _dbus_get_is_errno_nonzero (void) 00725 { 00726 return errno != 0; 00727 } 00728 00733 dbus_bool_t 00734 _dbus_get_is_errno_enomem (void) 00735 { 00736 return errno == ENOMEM; 00737 } 00738 00743 dbus_bool_t 00744 _dbus_get_is_errno_eintr (void) 00745 { 00746 return errno == EINTR; 00747 } 00748 00753 dbus_bool_t 00754 _dbus_get_is_errno_epipe (void) 00755 { 00756 return errno == EPIPE; 00757 } 00758 00763 dbus_bool_t 00764 _dbus_get_is_errno_etoomanyrefs (void) 00765 { 00766 #ifdef ETOOMANYREFS 00767 return errno == ETOOMANYREFS; 00768 #else 00769 return FALSE; 00770 #endif 00771 } 00772 00777 const char* 00778 _dbus_strerror_from_errno (void) 00779 { 00780 return _dbus_strerror (errno); 00781 } 00782 00785 /* tests in dbus-sysdeps-util.c */
1.7.6.1