D-Bus
1.10.12
|
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 /* Don't respect any environment variables if the current process is 00188 * setuid. This is the equivalent of glibc's __secure_getenv(). 00189 */ 00190 if (_dbus_check_setuid ()) 00191 return NULL; 00192 return getenv (varname); 00193 } 00194 00200 dbus_bool_t 00201 _dbus_clearenv (void) 00202 { 00203 dbus_bool_t rc = TRUE; 00204 00205 #ifdef HAVE_CLEARENV 00206 if (clearenv () != 0) 00207 rc = FALSE; 00208 #else 00209 00210 if (environ != NULL) 00211 environ[0] = NULL; 00212 #endif 00213 00214 return rc; 00215 } 00216 00225 dbus_bool_t 00226 _dbus_split_paths_and_append (DBusString *dirs, 00227 const char *suffix, 00228 DBusList **dir_list) 00229 { 00230 int start; 00231 int i; 00232 int len; 00233 char *cpath; 00234 DBusString file_suffix; 00235 00236 start = 0; 00237 i = 0; 00238 00239 _dbus_string_init_const (&file_suffix, suffix); 00240 00241 len = _dbus_string_get_length (dirs); 00242 00243 while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i)) 00244 { 00245 DBusString path; 00246 00247 if (!_dbus_string_init (&path)) 00248 goto oom; 00249 00250 if (!_dbus_string_copy_len (dirs, 00251 start, 00252 i - start, 00253 &path, 00254 0)) 00255 { 00256 _dbus_string_free (&path); 00257 goto oom; 00258 } 00259 00260 _dbus_string_chop_white (&path); 00261 00262 /* check for an empty path */ 00263 if (_dbus_string_get_length (&path) == 0) 00264 goto next; 00265 00266 if (!_dbus_concat_dir_and_file (&path, 00267 &file_suffix)) 00268 { 00269 _dbus_string_free (&path); 00270 goto oom; 00271 } 00272 00273 if (!_dbus_string_copy_data(&path, &cpath)) 00274 { 00275 _dbus_string_free (&path); 00276 goto oom; 00277 } 00278 00279 if (!_dbus_list_append (dir_list, cpath)) 00280 { 00281 _dbus_string_free (&path); 00282 dbus_free (cpath); 00283 goto oom; 00284 } 00285 00286 next: 00287 _dbus_string_free (&path); 00288 start = i + 1; 00289 } 00290 00291 if (start != len) 00292 { 00293 DBusString path; 00294 00295 if (!_dbus_string_init (&path)) 00296 goto oom; 00297 00298 if (!_dbus_string_copy_len (dirs, 00299 start, 00300 len - start, 00301 &path, 00302 0)) 00303 { 00304 _dbus_string_free (&path); 00305 goto oom; 00306 } 00307 00308 if (!_dbus_concat_dir_and_file (&path, 00309 &file_suffix)) 00310 { 00311 _dbus_string_free (&path); 00312 goto oom; 00313 } 00314 00315 if (!_dbus_string_copy_data(&path, &cpath)) 00316 { 00317 _dbus_string_free (&path); 00318 goto oom; 00319 } 00320 00321 if (!_dbus_list_append (dir_list, cpath)) 00322 { 00323 _dbus_string_free (&path); 00324 dbus_free (cpath); 00325 goto oom; 00326 } 00327 00328 _dbus_string_free (&path); 00329 } 00330 00331 return TRUE; 00332 00333 oom: 00334 _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); 00335 _dbus_list_clear (dir_list); 00336 return FALSE; 00337 } 00338 00353 dbus_bool_t 00354 _dbus_string_append_int (DBusString *str, 00355 long value) 00356 { 00357 /* this calculation is from comp.lang.c faq */ 00358 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */ 00359 int orig_len; 00360 int i; 00361 char *buf; 00362 00363 orig_len = _dbus_string_get_length (str); 00364 00365 if (!_dbus_string_lengthen (str, MAX_LONG_LEN)) 00366 return FALSE; 00367 00368 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN); 00369 00370 snprintf (buf, MAX_LONG_LEN, "%ld", value); 00371 00372 i = 0; 00373 while (*buf) 00374 { 00375 ++buf; 00376 ++i; 00377 } 00378 00379 _dbus_string_shorten (str, MAX_LONG_LEN - i); 00380 00381 return TRUE; 00382 } 00383 00391 dbus_bool_t 00392 _dbus_string_append_uint (DBusString *str, 00393 unsigned long value) 00394 { 00395 /* this is wrong, but definitely on the high side. */ 00396 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2) 00397 int orig_len; 00398 int i; 00399 char *buf; 00400 00401 orig_len = _dbus_string_get_length (str); 00402 00403 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN)) 00404 return FALSE; 00405 00406 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN); 00407 00408 snprintf (buf, MAX_ULONG_LEN, "%lu", value); 00409 00410 i = 0; 00411 while (*buf) 00412 { 00413 ++buf; 00414 ++i; 00415 } 00416 00417 _dbus_string_shorten (str, MAX_ULONG_LEN - i); 00418 00419 return TRUE; 00420 } 00421 00434 dbus_bool_t 00435 _dbus_string_parse_int (const DBusString *str, 00436 int start, 00437 long *value_return, 00438 int *end_return) 00439 { 00440 long v; 00441 const char *p; 00442 char *end; 00443 00444 p = _dbus_string_get_const_data_len (str, start, 00445 _dbus_string_get_length (str) - start); 00446 00447 end = NULL; 00448 _dbus_set_errno_to_zero (); 00449 v = strtol (p, &end, 0); 00450 if (end == NULL || end == p || errno != 0) 00451 return FALSE; 00452 00453 if (value_return) 00454 *value_return = v; 00455 if (end_return) 00456 *end_return = start + (end - p); 00457 00458 return TRUE; 00459 } 00460 00473 dbus_bool_t 00474 _dbus_string_parse_uint (const DBusString *str, 00475 int start, 00476 unsigned long *value_return, 00477 int *end_return) 00478 { 00479 unsigned long v; 00480 const char *p; 00481 char *end; 00482 00483 p = _dbus_string_get_const_data_len (str, start, 00484 _dbus_string_get_length (str) - start); 00485 00486 end = NULL; 00487 _dbus_set_errno_to_zero (); 00488 v = strtoul (p, &end, 0); 00489 if (end == NULL || end == p || errno != 0) 00490 return FALSE; 00491 00492 if (value_return) 00493 *value_return = v; 00494 if (end_return) 00495 *end_return = start + (end - p); 00496 00497 return TRUE; 00498 } 00499 /* DBusString group */ 00501 00515 dbus_bool_t 00516 _dbus_generate_random_bytes_buffer (char *buffer, 00517 int n_bytes, 00518 DBusError *error) 00519 { 00520 DBusString str; 00521 00522 if (!_dbus_string_init (&str)) 00523 { 00524 _DBUS_SET_OOM (error); 00525 return FALSE; 00526 } 00527 00528 if (!_dbus_generate_random_bytes (&str, n_bytes, error)) 00529 { 00530 _dbus_string_free (&str); 00531 return FALSE; 00532 } 00533 00534 _dbus_string_copy_to_buffer (&str, buffer, n_bytes); 00535 00536 _dbus_string_free (&str); 00537 return TRUE; 00538 } 00539 00549 dbus_bool_t 00550 _dbus_generate_random_ascii (DBusString *str, 00551 int n_bytes, 00552 DBusError *error) 00553 { 00554 static const char letters[] = 00555 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; 00556 int i; 00557 int len; 00558 00559 if (!_dbus_generate_random_bytes (str, n_bytes, error)) 00560 return FALSE; 00561 00562 len = _dbus_string_get_length (str); 00563 i = len - n_bytes; 00564 while (i < len) 00565 { 00566 _dbus_string_set_byte (str, i, 00567 letters[_dbus_string_get_byte (str, i) % 00568 (sizeof (letters) - 1)]); 00569 00570 ++i; 00571 } 00572 00573 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes, 00574 n_bytes)); 00575 00576 return TRUE; 00577 } 00578 00589 const char* 00590 _dbus_error_from_errno (int error_number) 00591 { 00592 switch (error_number) 00593 { 00594 case 0: 00595 return DBUS_ERROR_FAILED; 00596 00597 #ifdef EPROTONOSUPPORT 00598 case EPROTONOSUPPORT: 00599 return DBUS_ERROR_NOT_SUPPORTED; 00600 #elif defined(WSAEPROTONOSUPPORT) 00601 case WSAEPROTONOSUPPORT: 00602 return DBUS_ERROR_NOT_SUPPORTED; 00603 #endif 00604 #ifdef EAFNOSUPPORT 00605 case EAFNOSUPPORT: 00606 return DBUS_ERROR_NOT_SUPPORTED; 00607 #elif defined(WSAEAFNOSUPPORT) 00608 case WSAEAFNOSUPPORT: 00609 return DBUS_ERROR_NOT_SUPPORTED; 00610 #endif 00611 #ifdef ENFILE 00612 case ENFILE: 00613 return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */ 00614 #endif 00615 #ifdef EMFILE 00616 case EMFILE: 00617 return DBUS_ERROR_LIMITS_EXCEEDED; 00618 #endif 00619 #ifdef EACCES 00620 case EACCES: 00621 return DBUS_ERROR_ACCESS_DENIED; 00622 #endif 00623 #ifdef EPERM 00624 case EPERM: 00625 return DBUS_ERROR_ACCESS_DENIED; 00626 #endif 00627 #ifdef ENOBUFS 00628 case ENOBUFS: 00629 return DBUS_ERROR_NO_MEMORY; 00630 #endif 00631 #ifdef ENOMEM 00632 case ENOMEM: 00633 return DBUS_ERROR_NO_MEMORY; 00634 #endif 00635 #ifdef ECONNREFUSED 00636 case ECONNREFUSED: 00637 return DBUS_ERROR_NO_SERVER; 00638 #elif defined(WSAECONNREFUSED) 00639 case WSAECONNREFUSED: 00640 return DBUS_ERROR_NO_SERVER; 00641 #endif 00642 #ifdef ETIMEDOUT 00643 case ETIMEDOUT: 00644 return DBUS_ERROR_TIMEOUT; 00645 #elif defined(WSAETIMEDOUT) 00646 case WSAETIMEDOUT: 00647 return DBUS_ERROR_TIMEOUT; 00648 #endif 00649 #ifdef ENETUNREACH 00650 case ENETUNREACH: 00651 return DBUS_ERROR_NO_NETWORK; 00652 #elif defined(WSAENETUNREACH) 00653 case WSAENETUNREACH: 00654 return DBUS_ERROR_NO_NETWORK; 00655 #endif 00656 #ifdef EADDRINUSE 00657 case EADDRINUSE: 00658 return DBUS_ERROR_ADDRESS_IN_USE; 00659 #elif defined(WSAEADDRINUSE) 00660 case WSAEADDRINUSE: 00661 return DBUS_ERROR_ADDRESS_IN_USE; 00662 #endif 00663 #ifdef EEXIST 00664 case EEXIST: 00665 return DBUS_ERROR_FILE_EXISTS; 00666 #endif 00667 #ifdef ENOENT 00668 case ENOENT: 00669 return DBUS_ERROR_FILE_NOT_FOUND; 00670 #endif 00671 } 00672 00673 return DBUS_ERROR_FAILED; 00674 } 00675 00681 const char* 00682 _dbus_error_from_system_errno (void) 00683 { 00684 return _dbus_error_from_errno (errno); 00685 } 00686 00690 void 00691 _dbus_set_errno_to_zero (void) 00692 { 00693 #ifdef DBUS_WINCE 00694 SetLastError (0); 00695 #else 00696 errno = 0; 00697 #endif 00698 } 00699 00704 dbus_bool_t 00705 _dbus_get_is_errno_enomem (int e) 00706 { 00707 return e == ENOMEM; 00708 } 00709 00714 dbus_bool_t 00715 _dbus_get_is_errno_eintr (int e) 00716 { 00717 return e == EINTR; 00718 } 00719 00724 dbus_bool_t 00725 _dbus_get_is_errno_epipe (int e) 00726 { 00727 return e == EPIPE; 00728 } 00729 00734 dbus_bool_t 00735 _dbus_get_is_errno_etoomanyrefs (int e) 00736 { 00737 #ifdef ETOOMANYREFS 00738 return e == ETOOMANYREFS; 00739 #else 00740 return FALSE; 00741 #endif 00742 } 00743 00748 const char* 00749 _dbus_strerror_from_errno (void) 00750 { 00751 return _dbus_strerror (errno); 00752 } 00753 00756 /* tests in dbus-sysdeps-util.c */