|
D-Bus
1.5.10
|
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 return getenv (varname); 00186 } 00187 00193 dbus_bool_t 00194 _dbus_clearenv (void) 00195 { 00196 dbus_bool_t rc = TRUE; 00197 00198 #ifdef HAVE_CLEARENV 00199 if (clearenv () != 0) 00200 rc = FALSE; 00201 #else 00202 00203 if (environ != NULL) 00204 environ[0] = NULL; 00205 #endif 00206 00207 return rc; 00208 } 00209 00218 dbus_bool_t 00219 _dbus_split_paths_and_append (DBusString *dirs, 00220 const char *suffix, 00221 DBusList **dir_list) 00222 { 00223 int start; 00224 int i; 00225 int len; 00226 char *cpath; 00227 DBusString file_suffix; 00228 00229 start = 0; 00230 i = 0; 00231 00232 _dbus_string_init_const (&file_suffix, suffix); 00233 00234 len = _dbus_string_get_length (dirs); 00235 00236 while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i)) 00237 { 00238 DBusString path; 00239 00240 if (!_dbus_string_init (&path)) 00241 goto oom; 00242 00243 if (!_dbus_string_copy_len (dirs, 00244 start, 00245 i - start, 00246 &path, 00247 0)) 00248 { 00249 _dbus_string_free (&path); 00250 goto oom; 00251 } 00252 00253 _dbus_string_chop_white (&path); 00254 00255 /* check for an empty path */ 00256 if (_dbus_string_get_length (&path) == 0) 00257 goto next; 00258 00259 if (!_dbus_concat_dir_and_file (&path, 00260 &file_suffix)) 00261 { 00262 _dbus_string_free (&path); 00263 goto oom; 00264 } 00265 00266 if (!_dbus_string_copy_data(&path, &cpath)) 00267 { 00268 _dbus_string_free (&path); 00269 goto oom; 00270 } 00271 00272 if (!_dbus_list_append (dir_list, cpath)) 00273 { 00274 _dbus_string_free (&path); 00275 dbus_free (cpath); 00276 goto oom; 00277 } 00278 00279 next: 00280 _dbus_string_free (&path); 00281 start = i + 1; 00282 } 00283 00284 if (start != len) 00285 { 00286 DBusString path; 00287 00288 if (!_dbus_string_init (&path)) 00289 goto oom; 00290 00291 if (!_dbus_string_copy_len (dirs, 00292 start, 00293 len - start, 00294 &path, 00295 0)) 00296 { 00297 _dbus_string_free (&path); 00298 goto oom; 00299 } 00300 00301 if (!_dbus_concat_dir_and_file (&path, 00302 &file_suffix)) 00303 { 00304 _dbus_string_free (&path); 00305 goto oom; 00306 } 00307 00308 if (!_dbus_string_copy_data(&path, &cpath)) 00309 { 00310 _dbus_string_free (&path); 00311 goto oom; 00312 } 00313 00314 if (!_dbus_list_append (dir_list, cpath)) 00315 { 00316 _dbus_string_free (&path); 00317 dbus_free (cpath); 00318 goto oom; 00319 } 00320 00321 _dbus_string_free (&path); 00322 } 00323 00324 return TRUE; 00325 00326 oom: 00327 _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); 00328 _dbus_list_clear (dir_list); 00329 return FALSE; 00330 } 00331 00346 dbus_bool_t 00347 _dbus_string_append_int (DBusString *str, 00348 long value) 00349 { 00350 /* this calculation is from comp.lang.c faq */ 00351 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */ 00352 int orig_len; 00353 int i; 00354 char *buf; 00355 00356 orig_len = _dbus_string_get_length (str); 00357 00358 if (!_dbus_string_lengthen (str, MAX_LONG_LEN)) 00359 return FALSE; 00360 00361 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN); 00362 00363 snprintf (buf, MAX_LONG_LEN, "%ld", value); 00364 00365 i = 0; 00366 while (*buf) 00367 { 00368 ++buf; 00369 ++i; 00370 } 00371 00372 _dbus_string_shorten (str, MAX_LONG_LEN - i); 00373 00374 return TRUE; 00375 } 00376 00384 dbus_bool_t 00385 _dbus_string_append_uint (DBusString *str, 00386 unsigned long value) 00387 { 00388 /* this is wrong, but definitely on the high side. */ 00389 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2) 00390 int orig_len; 00391 int i; 00392 char *buf; 00393 00394 orig_len = _dbus_string_get_length (str); 00395 00396 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN)) 00397 return FALSE; 00398 00399 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN); 00400 00401 snprintf (buf, MAX_ULONG_LEN, "%lu", value); 00402 00403 i = 0; 00404 while (*buf) 00405 { 00406 ++buf; 00407 ++i; 00408 } 00409 00410 _dbus_string_shorten (str, MAX_ULONG_LEN - i); 00411 00412 return TRUE; 00413 } 00414 00427 dbus_bool_t 00428 _dbus_string_parse_int (const DBusString *str, 00429 int start, 00430 long *value_return, 00431 int *end_return) 00432 { 00433 long v; 00434 const char *p; 00435 char *end; 00436 00437 p = _dbus_string_get_const_data_len (str, start, 00438 _dbus_string_get_length (str) - start); 00439 00440 end = NULL; 00441 _dbus_set_errno_to_zero (); 00442 v = strtol (p, &end, 0); 00443 if (end == NULL || end == p || errno != 0) 00444 return FALSE; 00445 00446 if (value_return) 00447 *value_return = v; 00448 if (end_return) 00449 *end_return = start + (end - p); 00450 00451 return TRUE; 00452 } 00453 00466 dbus_bool_t 00467 _dbus_string_parse_uint (const DBusString *str, 00468 int start, 00469 unsigned long *value_return, 00470 int *end_return) 00471 { 00472 unsigned long v; 00473 const char *p; 00474 char *end; 00475 00476 p = _dbus_string_get_const_data_len (str, start, 00477 _dbus_string_get_length (str) - start); 00478 00479 end = NULL; 00480 _dbus_set_errno_to_zero (); 00481 v = strtoul (p, &end, 0); 00482 if (end == NULL || end == p || errno != 0) 00483 return FALSE; 00484 00485 if (value_return) 00486 *value_return = v; 00487 if (end_return) 00488 *end_return = start + (end - p); 00489 00490 return TRUE; 00491 } 00492 /* DBusString group */ 00494 00500 void 00501 _dbus_generate_pseudorandom_bytes_buffer (char *buffer, 00502 int n_bytes) 00503 { 00504 long tv_usec; 00505 int i; 00506 00507 /* fall back to pseudorandom */ 00508 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n", 00509 n_bytes); 00510 00511 _dbus_get_current_time (NULL, &tv_usec); 00512 srand (tv_usec); 00513 00514 i = 0; 00515 while (i < n_bytes) 00516 { 00517 double r; 00518 unsigned int b; 00519 00520 r = rand (); 00521 b = (r / (double) RAND_MAX) * 255.0; 00522 00523 buffer[i] = b; 00524 00525 ++i; 00526 } 00527 } 00528 00535 void 00536 _dbus_generate_random_bytes_buffer (char *buffer, 00537 int n_bytes) 00538 { 00539 DBusString str; 00540 00541 if (!_dbus_string_init (&str)) 00542 { 00543 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes); 00544 return; 00545 } 00546 00547 if (!_dbus_generate_random_bytes (&str, n_bytes)) 00548 { 00549 _dbus_string_free (&str); 00550 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes); 00551 return; 00552 } 00553 00554 _dbus_string_copy_to_buffer (&str, buffer, n_bytes); 00555 00556 _dbus_string_free (&str); 00557 } 00558 00567 dbus_bool_t 00568 _dbus_generate_random_ascii (DBusString *str, 00569 int n_bytes) 00570 { 00571 static const char letters[] = 00572 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; 00573 int i; 00574 int len; 00575 00576 if (!_dbus_generate_random_bytes (str, n_bytes)) 00577 return FALSE; 00578 00579 len = _dbus_string_get_length (str); 00580 i = len - n_bytes; 00581 while (i < len) 00582 { 00583 _dbus_string_set_byte (str, i, 00584 letters[_dbus_string_get_byte (str, i) % 00585 (sizeof (letters) - 1)]); 00586 00587 ++i; 00588 } 00589 00590 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes, 00591 n_bytes)); 00592 00593 return TRUE; 00594 } 00595 00606 const char* 00607 _dbus_error_from_errno (int error_number) 00608 { 00609 switch (error_number) 00610 { 00611 case 0: 00612 return DBUS_ERROR_FAILED; 00613 00614 #ifdef EPROTONOSUPPORT 00615 case EPROTONOSUPPORT: 00616 return DBUS_ERROR_NOT_SUPPORTED; 00617 #endif 00618 #ifdef WSAEPROTONOSUPPORT 00619 case WSAEPROTONOSUPPORT: 00620 return DBUS_ERROR_NOT_SUPPORTED; 00621 #endif 00622 #ifdef EAFNOSUPPORT 00623 case EAFNOSUPPORT: 00624 return DBUS_ERROR_NOT_SUPPORTED; 00625 #endif 00626 #ifdef 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 #endif 00658 #ifdef WSAECONNREFUSED 00659 case WSAECONNREFUSED: 00660 return DBUS_ERROR_NO_SERVER; 00661 #endif 00662 #ifdef ETIMEDOUT 00663 case ETIMEDOUT: 00664 return DBUS_ERROR_TIMEOUT; 00665 #endif 00666 #ifdef WSAETIMEDOUT 00667 case WSAETIMEDOUT: 00668 return DBUS_ERROR_TIMEOUT; 00669 #endif 00670 #ifdef ENETUNREACH 00671 case ENETUNREACH: 00672 return DBUS_ERROR_NO_NETWORK; 00673 #endif 00674 #ifdef 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 #endif 00682 #ifdef WSAEADDRINUSE 00683 case WSAEADDRINUSE: 00684 return DBUS_ERROR_ADDRESS_IN_USE; 00685 #endif 00686 #ifdef EEXIST 00687 case EEXIST: 00688 return DBUS_ERROR_FILE_EXISTS; 00689 #endif 00690 #ifdef ENOENT 00691 case ENOENT: 00692 return DBUS_ERROR_FILE_NOT_FOUND; 00693 #endif 00694 } 00695 00696 return DBUS_ERROR_FAILED; 00697 } 00698 00704 const char* 00705 _dbus_error_from_system_errno (void) 00706 { 00707 return _dbus_error_from_errno (errno); 00708 } 00709 00713 void 00714 _dbus_set_errno_to_zero (void) 00715 { 00716 #ifdef DBUS_WINCE 00717 SetLastError (0); 00718 #else 00719 errno = 0; 00720 #endif 00721 } 00722 00727 dbus_bool_t 00728 _dbus_get_is_errno_nonzero (void) 00729 { 00730 return errno != 0; 00731 } 00732 00737 dbus_bool_t 00738 _dbus_get_is_errno_enomem (void) 00739 { 00740 return errno == ENOMEM; 00741 } 00742 00747 dbus_bool_t 00748 _dbus_get_is_errno_eintr (void) 00749 { 00750 return errno == EINTR; 00751 } 00752 00757 dbus_bool_t 00758 _dbus_get_is_errno_epipe (void) 00759 { 00760 return errno == EPIPE; 00761 } 00762 00767 const char* 00768 _dbus_strerror_from_errno (void) 00769 { 00770 return _dbus_strerror (errno); 00771 } 00772 00775 /* tests in dbus-sysdeps-util.c */
1.7.6.1