From d4b870e7f91b7018524f7b85dc00b90cc64453bf Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 12 Dec 2002 04:26:46 +0000 Subject: 2002-12-11 Havoc Pennington * dbus/dbus-types.h: add dbus_unichar * dbus/dbus-internals.c (_dbus_verbose): use _dbus_getenv * dbus/dbus-connection.c (dbus_connection_send_message): return TRUE on success * dbus/dbus-transport.c: include dbus-watch.h * dbus/dbus-connection.c: include dbus-message-internal.h * HACKING: add file with coding guidelines stuff. * dbus/dbus-string.h, dbus/dbus-string.c: Encapsulate all string handling here, for security purposes (as in vsftpd). Not actually using this class yet. * dbus/dbus-sysdeps.h, dbus/dbus-sysdeps.c: Encapsulate all system/libc usage here, as in vsftpd, for ease of auditing (and should also simplify portability). Haven't actually moved all the system/libc usage into here yet. --- ChangeLog | 24 + HACKING | 62 +++ dbus/Makefile.am | 6 +- dbus/dbus-connection.c | 3 + dbus/dbus-hash.c | 2 +- dbus/dbus-internals.c | 2 +- dbus/dbus-internals.h | 9 +- dbus/dbus-string.c | 1224 ++++++++++++++++++++++++++++++++++++++++++++++++ dbus/dbus-string.h | 136 ++++++ dbus/dbus-sysdeps.c | 223 +++++++++ dbus/dbus-sysdeps.h | 51 ++ dbus/dbus-test.c | 5 + dbus/dbus-test.h | 5 +- dbus/dbus-transport.c | 1 + dbus/dbus-types.h | 8 +- 15 files changed, 1747 insertions(+), 14 deletions(-) create mode 100644 HACKING create mode 100644 dbus/dbus-string.c create mode 100644 dbus/dbus-string.h create mode 100644 dbus/dbus-sysdeps.c create mode 100644 dbus/dbus-sysdeps.h diff --git a/ChangeLog b/ChangeLog index dce9ece7..f9e61326 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2002-12-11 Havoc Pennington + + * dbus/dbus-types.h: add dbus_unichar + + * dbus/dbus-internals.c (_dbus_verbose): use _dbus_getenv + + * dbus/dbus-connection.c (dbus_connection_send_message): return + TRUE on success + + * dbus/dbus-transport.c: include dbus-watch.h + + * dbus/dbus-connection.c: include dbus-message-internal.h + + * HACKING: add file with coding guidelines stuff. + + * dbus/dbus-string.h, dbus/dbus-string.c: Encapsulate all string + handling here, for security purposes (as in vsftpd). Not actually + using this class yet. + + * dbus/dbus-sysdeps.h, dbus/dbus-sysdeps.c: Encapsulate all + system/libc usage here, as in vsftpd, for ease of auditing (and + should also simplify portability). Haven't actually moved all the + system/libc usage into here yet. + 2002-11-25 Havoc Pennington * dbus/dbus-internals.c (_dbus_verbose): fix to not diff --git a/HACKING b/HACKING new file mode 100644 index 00000000..8d0b1756 --- /dev/null +++ b/HACKING @@ -0,0 +1,62 @@ +The guidelines in this file are the ideals; it's better to send a +not-fully-following-guidelines patch than no patch at all, though. We +can always polish it up. + +Mailing list +=== + +The D-BUS mailing list is message-bus-list@freedesktop.org; discussion +of patches, etc. should go there. + +Security +=== + +Most of D-BUS is security sensitive. Guidelines related to that: + + - avoid memcpy(), sprintf(), strlen(), snprintf, strlcat(), + strstr(), strtok(), or any of this stuff. Use DBusString. + If DBusString doesn't have the feature you need, add it + to DBusString. + + There are some exceptions, for example + if your strings are just used to index a hash table + and you don't do any parsing/modification of them, perhaps + DBusString is wasteful and wouldn't help much. But definitely + if you're doing any parsing, reallocation, etc. use DBusString. + + - do not include system headers outside of dbus-memory.c, + dbus-sysdeps.c, and other places where they are already + included. This gives us one place to audit all external + dependencies on features in libc, etc. + + - do not use libc features that are "complicated" + and may contain security holes. For example, you probably shouldn't + try to use regcomp() to compile an untrusted regular expression. + Regular expressions are just too complicated, and there are many + different libc's out there. + + - we need to design the message bus daemon (and any similar features) + to use limited privileges, run in a chroot jail, and so on. + +http://vsftpd.beasts.org/ has other good security suggestions. + +Coding Style +=== + + - The C library uses GNU coding conventions, with GLib-like + extensions (e.g. lining up function arguments). The + Qt wrapper uses KDE coding conventions. + + - Write docs for all non-static functions and structs and so on. try + "doxygen Doxyfile" prior to commit and be sure there are no + warnings printed. + + - All external interfaces (network protocols, file formats, etc.) + should have documented specifications sufficient to allow an + alternative implementation to be written. Our implementation should + be strict about specification compliance (should not for example + heuristically parse a file and accept not-well-formed + data). Avoiding heuristics is also important for security reasons; + if it looks funny, ignore it (or exit, or disconnect). + + diff --git a/dbus/Makefile.am b/dbus/Makefile.am index f830bb7b..f74c8bef 100644 --- a/dbus/Makefile.am +++ b/dbus/Makefile.am @@ -48,7 +48,11 @@ libdbus_convenience_la_SOURCES= \ dbus-internals.c \ dbus-internals.h \ dbus-list.c \ - dbus-list.h + dbus-list.h \ + dbus-string.c \ + dbus-string.h \ + dbus-sysdeps.c \ + dbus-sysdeps.h libdbus_1_la_LIBADD= $(DBUS_CLIENT_LIBS) libdbus-convenience.la ## don't export symbols that start with "_" (we use this diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index f60e53a9..3c6df57f 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -27,6 +27,7 @@ #include "dbus-watch.h" #include "dbus-connection-internal.h" #include "dbus-list.h" +#include "dbus-message-internal.h" /** * @defgroup DBusConnection DBusConnection @@ -465,6 +466,8 @@ dbus_connection_send_message (DBusConnection *connection, if (connection->n_outgoing == 1) _dbus_transport_messages_pending (connection->transport, connection->n_outgoing); + + return TRUE; } /** diff --git a/dbus/dbus-hash.c b/dbus/dbus-hash.c index 48e96ca6..f4a22586 100644 --- a/dbus/dbus-hash.c +++ b/dbus/dbus-hash.c @@ -1405,4 +1405,4 @@ _dbus_hash_test (void) return TRUE; } -#endif +#endif /* DBUS_BUILD_TESTS */ diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c index 0fd01c29..f3527eb2 100644 --- a/dbus/dbus-internals.c +++ b/dbus/dbus-internals.c @@ -164,7 +164,7 @@ _dbus_verbose (const char *format, if (!initted) { - verbose = getenv ("DBUS_VERBOSE") != NULL; + verbose = _dbus_getenv ("DBUS_VERBOSE") != NULL; initted = TRUE; if (!verbose) return; diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h index 5d001397..fd54a5f1 100644 --- a/dbus/dbus-internals.h +++ b/dbus/dbus-internals.h @@ -32,8 +32,7 @@ #include #include #include -#include /* for abort() */ -#include /* just so it's there in every file */ +#include DBUS_BEGIN_DECLS; @@ -52,7 +51,7 @@ do { \ { \ _dbus_warn ("Assertion failed \"%s\" file \"%s\" line %d\n", \ #condition, __FILE__, __LINE__); \ - abort (); \ + _dbus_abort (); \ } \ } while (0) @@ -60,10 +59,10 @@ do { \ do { \ _dbus_warn ("File \"%s\" line %d should not have been reached: %s\n", \ __FILE__, __LINE__, (explanation)); \ - abort (); \ + _dbus_abort (); \ } while (0) -#define _DBUS_N_ELEMENTS(array) (sizeof ((array)) / sizeof ((array)[0])) +#define _DBUS_N_ELEMENTS(array) ((int) (sizeof ((array)) / sizeof ((array)[0]))) #define _DBUS_POINTER_TO_INT(pointer) ((long)(pointer)) #define _DBUS_INT_TO_POINTER(integer) ((void*)((long)(integer))) diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c new file mode 100644 index 00000000..088ca35c --- /dev/null +++ b/dbus/dbus-string.c @@ -0,0 +1,1224 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-string.c String utility class (internal to D-BUS implementation) + * + * Copyright (C) 2002 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "dbus-string.h" +/* we allow a system header here, for speed/convenience */ +#include + +/** + * @defgroup DBusString string class + * @ingroup DBusInternals + * @brief DBusString data structure + * + * Types and functions related to DBusString. DBusString is intended + * to be a string class that makes it hard to mess up security issues + * (and just in general harder to write buggy code). It should be + * used (or extended and then used) rather than the libc stuff in + * string.h. The string class is a bit inconvenient at spots because + * it handles out-of-memory failures and tries to be extra-robust. + * + * A DBusString has a maximum length set at initialization time; this + * can be used to ensure that a buffer doesn't get too big. The + * _dbus_string_lengthen() method checks for overflow, and for max + * length being exceeded. + * + * Try to avoid conversion to a plain C string, i.e. add methods on + * the string object instead, only convert to C string when passing + * things out to the public API. In particular, no sprintf, strcpy, + * strcat, any of that should be used. The GString feature of + * accepting negative numbers for "length of string" is also absent, + * because it could keep us from detecting bogus huge lengths. i.e. if + * we passed in some bogus huge length it would be taken to mean + * "current length of string" instead of "broken crack" + */ + +/** + * @defgroup DBusStringInternals DBusString implementation details + * @ingroup DBusInternals + * @brief DBusString implementation details + * + * The guts of DBusString. + * + * @{ + */ + +/** + * @brief Internals of DBusString. + * + * DBusString internals. DBusString is an opaque objects, it must be + * used via accessor functions. + */ +typedef struct +{ + unsigned char *str; /**< String data, plus nul termination */ + int len; /**< Length without nul */ + int allocated; /**< Allocated size of data */ + int max_length; /**< Max length of this string. */ + unsigned int constant : 1; /**< String data is not owned by DBusString */ + unsigned int locked : 1; /**< DBusString has been locked and can't be changed */ + unsigned int invalid : 1; /**< DBusString is invalid (e.g. already freed) */ +} DBusRealString; + +/** + * Checks a bunch of assertions about a string object + * + * @param real the DBusRealString + */ +#define DBUS_GENERIC_STRING_PREAMBLE(real) _dbus_assert ((real) != NULL); _dbus_assert (!(real)->invalid); _dbus_assert ((real)->len >= 0); _dbus_assert ((real)->allocated >= 0); _dbus_assert ((real)->max_length >= 0); _dbus_assert ((real)->len <= (real)->allocated); _dbus_assert ((real)->len <= (real)->max_length) + +/** + * Checks assertions about a string object that needs to be + * modifiable - may not be locked or const. Also declares + * the "real" variable pointing to DBusRealString. + * @param str the string + */ +#define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \ + DBUS_GENERIC_STRING_PREAMBLE (real); \ + _dbus_assert (!(real)->constant); \ + _dbus_assert (!(real)->locked) + +/** + * Checks assertions about a string object that may be locked but + * can't be const. i.e. a string object that we can free. Also + * declares the "real" variable pointing to DBusRealString. + * + * @param str the string + */ +#define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \ + DBUS_GENERIC_STRING_PREAMBLE (real); \ + _dbus_assert (!(real)->constant) + +/** + * Checks assertions about a string that may be const or locked. Also + * declares the "real" variable pointing to DBusRealString. + * @param str the string. + */ +#define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \ + DBUS_GENERIC_STRING_PREAMBLE (real) + +/** @} */ + +/** + * @addtogroup DBusString + * @{ + */ + +/** + * Initializes a string. The maximum length may be _DBUS_INT_MAX for + * no maximum. The string starts life with zero length. + * The string must eventually be freed with _dbus_string_free(). + * + * @param str memory to hold the string + * @param max_length the maximum size of the string + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_string_init (DBusString *str, + int max_length) +{ + DBusRealString *real; + + _dbus_assert (str != NULL); + _dbus_assert (max_length >= 0); + + _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString)); + + real = (DBusRealString*) str; + + /* It's very important not to touch anything + * other than real->str if we're going to fail, + * since we also use this function to reset + * an existing string, e.g. in _dbus_string_steal_data() + */ + +#define INITIAL_ALLOC 2 + + real->str = dbus_malloc (INITIAL_ALLOC); + if (real->str == NULL) + return FALSE; + + real->allocated = INITIAL_ALLOC; + real->len = 0; + real->str[real->len] = '\0'; + + real->max_length = max_length; + real->constant = FALSE; + real->locked = FALSE; + real->invalid = FALSE; + + return TRUE; +} + +/** + * Initializes a constant string. The value parameter is not copied + * (should be static), and the string may never be modified. + * It is safe but not necessary to call _dbus_string_free() + * on a const string. + * + * @param str memory to use for the string + * @param value a string to be stored in str (not copied!!!) + */ +void +_dbus_string_init_const (DBusString *str, + const char *value) +{ + DBusRealString *real; + + _dbus_assert (str != NULL); + _dbus_assert (value != NULL); + + real = (DBusRealString*) str; + + real->str = (char*) value; + real->len = strlen (real->str); + real->allocated = real->len; + real->max_length = real->len; + real->constant = TRUE; + real->invalid = FALSE; +} + +/** + * Frees a string created by _dbus_string_init(). + * + * @param str memory where the string is stored. + */ +void +_dbus_string_free (DBusString *str) +{ + DBUS_LOCKED_STRING_PREAMBLE (str); + + if (real->constant) + return; + + dbus_free (real->str); + + real->invalid = TRUE; +} + +/** + * Locks a string such that any attempts to change the string + * will result in aborting the program. Also, if the string + * is wasting a lot of memory (allocation is larger than what + * the string is really using), _dbus_string_lock() will realloc + * the string's data to "compact" it. + * + * @param str the string to lock. + */ +void +_dbus_string_lock (DBusString *str) +{ + DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */ + + real->locked = TRUE; + + /* Try to realloc to avoid excess memory usage, since + * we know we won't change the string further + */ +#define MAX_WASTE 24 + if (real->allocated > (real->len + MAX_WASTE)) + { + char *new_str; + int new_allocated; + + new_allocated = real->len + 1; + + new_str = dbus_realloc (real->str, new_allocated); + if (new_str != NULL) + { + real->str = new_str; + real->allocated = new_allocated; + } + } +} + +/** + * Gets the raw character buffer from the string. The returned buffer + * will be nul-terminated, but note that strings may contain binary + * data so there may be extra nul characters prior to the termination. + * This function should be little-used, extend DBusString or add + * stuff to dbus-sysdeps.c instead. It's an error to use this + * function on a const string. + * + * @param str the string + * @param data_return place to store the returned data + */ +void +_dbus_string_get_data (DBusString *str, + char **data_return) +{ + DBUS_STRING_PREAMBLE (str); + _dbus_assert (data_return != NULL); + + *data_return = real->str; +} + +/** + * Gets the raw character buffer from a const string. + * + * @param str the string + * @param data_return location to store returned data + */ +void +_dbus_string_get_const_data (const DBusString *str, + const char **data_return) +{ + DBUS_CONST_STRING_PREAMBLE (str); + _dbus_assert (data_return != NULL); + + *data_return = real->str; +} + +/** + * Gets a sub-portion of the raw character buffer from the + * string. The "len" field is required simply for error + * checking, to be sure you don't try to use more + * string than exists. The nul termination of the + * returned buffer remains at the end of the entire + * string, not at start + len. + * + * @param str the string + * @param data_return location to return the buffer + * @param start byte offset to return + * @param len length of segment to return + */ +void +_dbus_string_get_data_len (DBusString *str, + char **data_return, + int start, + int len) +{ + DBUS_STRING_PREAMBLE (str); + _dbus_assert (data_return != NULL); + _dbus_assert (start >= 0); + _dbus_assert (len >= 0); + _dbus_assert ((start + len) <= real->len); + + *data_return = real->str + start; +} + +/** + * const version of _dbus_string_get_data_len(). + * + * @param str the string + * @param data_return location to return the buffer + * @param start byte offset to return + * @param len length of segment to return + */ +void +_dbus_string_get_const_data_len (const DBusString *str, + const char **data_return, + int start, + int len) +{ + DBUS_CONST_STRING_PREAMBLE (str); + _dbus_assert (data_return != NULL); + _dbus_assert (start >= 0); + _dbus_assert (len >= 0); + _dbus_assert ((start + len) <= real->len); + + *data_return = real->str + start; +} + +/** + * Like _dbus_string_get_data(), but removes the + * gotten data from the original string. The caller + * must free the data returned. This function may + * fail due to lack of memory, and return #FALSE. + * + * @param str the string + * @param data_return location to return the buffer + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_string_steal_data (DBusString *str, + char **data_return) +{ + DBUS_STRING_PREAMBLE (str); + _dbus_assert (data_return != NULL); + + *data_return = real->str; + + /* reset the string */ + if (!_dbus_string_init (str, real->max_length)) + { + /* hrm, put it back then */ + real->str = *data_return; + *data_return = NULL; + return FALSE; + } + + return TRUE; +} + +/** + * Like _dbus_string_get_data_len(), but removes the gotten data from + * the original string. The caller must free the data returned. This + * function may fail due to lack of memory, and return #FALSE. + * The returned string is nul-terminated and has length len. + * + * @param str the string + * @param data_return location to return the buffer + * @param start the start of segment to steal + * @param len the length of segment to steal + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_string_steal_data_len (DBusString *str, + char **data_return, + int start, + int len) +{ + DBusString dest; + + DBUS_STRING_PREAMBLE (str); + _dbus_assert (data_return != NULL); + _dbus_assert (start >= 0); + _dbus_assert (len >= 0); + _dbus_assert ((start + len) <= real->len); + + if (!_dbus_string_init (&dest, real->max_length)) + return FALSE; + + if (!_dbus_string_move_len (str, start, len, &dest, 0)) + { + _dbus_string_free (&dest); + return FALSE; + } + + if (!_dbus_string_steal_data (&dest, data_return)) + { + _dbus_string_free (&dest); + return FALSE; + } + + _dbus_string_free (&dest); + return TRUE; +} + +/** + * Gets the length of a string (not including nul termination). + * + * @returns the length. + */ +int +_dbus_string_get_length (const DBusString *str) +{ + DBUS_CONST_STRING_PREAMBLE (str); + + return real->len; +} + +static dbus_bool_t +set_length (DBusRealString *real, + int new_length) +{ + /* Note, we are setting the length without nul termination */ + + /* exceeding max length is the same as failure to allocate memory */ + if (new_length > real->max_length) + return FALSE; + + while (new_length >= real->allocated) + { + int new_allocated; + char *new_str; + + new_allocated = 2 + real->allocated * 2; + if (new_allocated < real->allocated) + return FALSE; /* overflow */ + + new_str = dbus_realloc (real->str, new_allocated); + if (new_str == NULL) + return FALSE; + + real->str = new_str; + real->allocated = new_allocated; + } + + real->len = new_length; + real->str[real->len] = '\0'; + + return TRUE; +} + +/** + * Makes a string longer by the given number of bytes. Checks whether + * adding additional_length to the current length would overflow an + * integer, and checks for exceeding a string's max length. + * The new bytes are not initialized, other than nul-terminating + * the end of the string. The uninitialized bytes may contain + * unexpected nul bytes or other junk. + * + * @param str a string + * @param additional_length length to add to the string. + * @returns #TRUE on success. + */ +dbus_bool_t +_dbus_string_lengthen (DBusString *str, + int additional_length) +{ + DBUS_STRING_PREAMBLE (str); + _dbus_assert (additional_length >= 0); + + if ((real->len + additional_length) < real->len) + return FALSE; /* overflow */ + + return set_length (real, + real->len + additional_length); +} + +/** + * Makes a string shorter by the given number of bytes. + * + * @param str a string + * @param length_to_remove length to remove from the string. + */ +void +_dbus_string_shorten (DBusString *str, + int length_to_remove) +{ + DBUS_STRING_PREAMBLE (str); + _dbus_assert (length_to_remove >= 0); + _dbus_assert (length_to_remove <= real->len); + + set_length (real, + real->len - length_to_remove); +} + +/** + * Sets the length of a string. Can be used to truncate or lengthen + * the string. If the string is lengthened, the function may fail and + * return #FALSE. Newly-added bytes are not initialized, as with + * _dbus_string_lengthen(). + * + * @param str a string + * @param length new length of the string. + * @returns #FALSE on failure. + */ +dbus_bool_t +_dbus_string_set_length (DBusString *str, + int length) +{ + DBUS_STRING_PREAMBLE (str); + _dbus_assert (length >= 0); + + return set_length (real, length); +} + +static dbus_bool_t +append (DBusRealString *real, + const char *buffer, + int buffer_len) +{ + if (buffer_len == 0) + return TRUE; + + if (!_dbus_string_lengthen ((DBusString*)real, buffer_len)) + return FALSE; + + memcpy (real->str + (real->len - buffer_len), + buffer, + buffer_len); + + return TRUE; +} + +/** + * Appends a nul-terminated C-style string to a DBusString. + * + * @param str the DBusString + * @param buffer the nul-terminated characters to append + * @returns #FALSE if not enough memory. + */ +dbus_bool_t +_dbus_string_append (DBusString *str, + const char *buffer) +{ + int buffer_len; + + DBUS_STRING_PREAMBLE (str); + _dbus_assert (buffer != NULL); + + buffer_len = strlen (buffer); + + return append (real, buffer, buffer_len); +} + +/** + * Appends block of bytes with the given length to a DBusString. + * + * @param str the DBusString + * @param buffer the bytes to append + * @param len the number of bytes to append + * @returns #FALSE if not enough memory. + */ +dbus_bool_t +_dbus_string_append_len (DBusString *str, + const char *buffer, + int len) +{ + DBUS_STRING_PREAMBLE (str); + _dbus_assert (buffer != NULL); + _dbus_assert (len >= 0); + + return append (real, buffer, len); +} + +/** + * Appends a single byte to the string, returning #FALSE + * if not enough memory. + * + * @param str the string + * @param byte the byte to append + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_string_append_byte (DBusString *str, + unsigned char byte) +{ + DBUS_STRING_PREAMBLE (str); + + if (!set_length (real, real->len + 1)) + return FALSE; + + real->str[real->len-1] = byte; + + return TRUE; +} + +/** + * Appends a single Unicode character, encoding the character + * in UTF-8 format. + * + * @param str the string + * @param ch the Unicode character + */ +dbus_bool_t +_dbus_string_append_unichar (DBusString *str, + dbus_unichar_t ch) +{ + int len; + int first; + int i; + char *out; + + DBUS_STRING_PREAMBLE (str); + + /* this code is from GLib but is pretty standard I think */ + + len = 0; + + if (ch < 0x80) + { + first = 0; + len = 1; + } + else if (ch < 0x800) + { + first = 0xc0; + len = 2; + } + else if (ch < 0x10000) + { + first = 0xe0; + len = 3; + } + else if (ch < 0x200000) + { + first = 0xf0; + len = 4; + } + else if (ch < 0x4000000) + { + first = 0xf8; + len = 5; + } + else + { + first = 0xfc; + len = 6; + } + + if (!set_length (real, real->len + len)) + return FALSE; + + out = real->str + (real->len - len); + + for (i = len - 1; i > 0; --i) + { + out[i] = (ch & 0x3f) | 0x80; + ch >>= 6; + } + out[0] = ch | first; + + return TRUE; +} + +static void +delete (DBusRealString *real, + int start, + int len) +{ + if (len == 0) + return; + + memmove (real->str + start, real->str + start + len, real->len - (start + len)); + real->len -= len; + real->str[real->len] = '\0'; +} + +/** + * Deletes a segment of a DBusString with length len starting at + * start. (Hint: to clear an entire string, setting length to 0 + * with _dbus_string_set_length() is easier.) + * + * @param str the DBusString + * @param start where to start deleting + * @param len the number of bytes to delete + */ +void +_dbus_string_delete (DBusString *str, + int start, + int len) +{ + DBUS_STRING_PREAMBLE (str); + _dbus_assert (start >= 0); + _dbus_assert (len >= 0); + _dbus_assert ((start + len) <= real->len); + + delete (real, start, len); +} + +static dbus_bool_t +copy (DBusRealString *source, + int start, + int len, + DBusRealString *dest, + int insert_at) +{ + if (len == 0) + return TRUE; + + if (!set_length (dest, dest->len + len)) + return FALSE; + + memmove (dest->str + insert_at + len, + dest->str + insert_at, + dest->len - len); + + memcpy (dest->str + insert_at, + source->str + start, + len); + + return TRUE; +} + +/** + * Checks assertions for two strings we're copying a segment between, + * and declares real_source/real_dest variables. + * + * @param source the source string + * @param start the starting offset + * @param dest the dest string + * @param insert_at where the copied segment is inserted + */ +#define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \ + DBusRealString *real_source = (DBusRealString*) source; \ + DBusRealString *real_dest = (DBusRealString*) dest; \ + _dbus_assert ((source) != (dest)); \ + DBUS_GENERIC_STRING_PREAMBLE (real_source); \ + DBUS_GENERIC_STRING_PREAMBLE (real_dest); \ + _dbus_assert (!real_source->constant); \ + _dbus_assert (!real_source->locked); \ + _dbus_assert (!real_dest->constant); \ + _dbus_assert (!real_dest->locked); \ + _dbus_assert ((start) >= 0); \ + _dbus_assert ((start) <= real_source->len); \ + _dbus_assert ((insert_at) >= 0); \ + _dbus_assert ((insert_at) <= real_dest->len) + +/** + * Moves the end of one string into another string. Both strings + * must be initialized, valid strings. + * + * @param source the source string + * @param start where to chop off the source string + * @param dest the destination string + * @param insert_at where to move the chopped-off part of source string + * @returns #FALSE if not enough memory + */ +dbus_bool_t +_dbus_string_move (DBusString *source, + int start, + DBusString *dest, + int insert_at) +{ + DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); + + if (!copy (real_source, start, + real_source->len - start, + real_dest, + insert_at)) + return FALSE; + + delete (real_source, start, + real_source->len - start); + + return TRUE; +} + +/** + * Like _dbus_string_move(), but does not delete the section + * of the source string that's copied to the dest string. + * + * @param source the source string + * @param start where to start copying the source string + * @param dest the destination string + * @param insert_at where to place the copied part of source string + * @returns #FALSE if not enough memory + */ +dbus_bool_t +_dbus_string_copy (const DBusString *source, + int start, + DBusString *dest, + int insert_at) +{ + DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); + + return copy (real_source, start, + real_source->len - start, + real_dest, + insert_at); +} + +/** + * Like _dbus_string_move(), but can move a segment from + * the middle of the source string. + * + * @param source the source string + * @param start first byte of source string to move + * @param len length of segment to move + * @param dest the destination string + * @param insert_at where to move the bytes from the source string + * @returns #FALSE if not enough memory + */ +dbus_bool_t +_dbus_string_move_len (DBusString *source, + int start, + int len, + DBusString *dest, + int insert_at) + +{ + DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); + _dbus_assert (len >= 0); + _dbus_assert ((start + len) <= real_source->len); + + if (!copy (real_source, start, len, + real_dest, + insert_at)) + return FALSE; + + delete (real_source, start, + real_source->len - start); + + return TRUE; +} + +/** + * Like _dbus_string_copy(), but can copy a segment from the middle of + * the source string. + * + * @param source the source string + * @param start where to start copying the source string + * @param len length of segment to copy + * @param dest the destination string + * @param insert_at where to place the copied segment of source string + * @returns #FALSE if not enough memory + */ +dbus_bool_t +_dbus_string_copy_len (const DBusString *source, + int start, + int len, + DBusString *dest, + int insert_at) +{ + DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); + _dbus_assert (len >= 0); + _dbus_assert ((start + len) <= real_source->len); + + return copy (real_source, start, len, + real_dest, + insert_at); +} + +/* Unicode macros from GLib */ + +/** computes length and mask of a unicode character + * @param Char the char + * @param Mask the mask variable to assign to + * @param Len the length variable to assign to + */ +#define UTF8_COMPUTE(Char, Mask, Len) \ + if (Char < 128) \ + { \ + Len = 1; \ + Mask = 0x7f; \ + } \ + else if ((Char & 0xe0) == 0xc0) \ + { \ + Len = 2; \ + Mask = 0x1f; \ + } \ + else if ((Char & 0xf0) == 0xe0) \ + { \ + Len = 3; \ + Mask = 0x0f; \ + } \ + else if ((Char & 0xf8) == 0xf0) \ + { \ + Len = 4; \ + Mask = 0x07; \ + } \ + else if ((Char & 0xfc) == 0xf8) \ + { \ + Len = 5; \ + Mask = 0x03; \ + } \ + else if ((Char & 0xfe) == 0xfc) \ + { \ + Len = 6; \ + Mask = 0x01; \ + } \ + else \ + Len = -1; + +/** + * computes length of a unicode character in UTF-8 + * @param Char the char + */ +#define UTF8_LENGTH(Char) \ + ((Char) < 0x80 ? 1 : \ + ((Char) < 0x800 ? 2 : \ + ((Char) < 0x10000 ? 3 : \ + ((Char) < 0x200000 ? 4 : \ + ((Char) < 0x4000000 ? 5 : 6))))) + +/** + * Gets a UTF-8 value. + * + * @param Result variable for extracted unicode char. + * @param Chars the bytes to decode + * @param Count counter variable + * @param Mask mask for this char + * @param Len length for this char in bytes + */ +#define UTF8_GET(Result, Chars, Count, Mask, Len) \ + (Result) = (Chars)[0] & (Mask); \ + for ((Count) = 1; (Count) < (Len); ++(Count)) \ + { \ + if (((Chars)[(Count)] & 0xc0) != 0x80) \ + { \ + (Result) = -1; \ + break; \ + } \ + (Result) <<= 6; \ + (Result) |= ((Chars)[(Count)] & 0x3f); \ + } + +/** + * Check whether a unicode char is in a valid range. + * + * @param Char the character + */ +#define UNICODE_VALID(Char) \ + ((Char) < 0x110000 && \ + ((Char) < 0xD800 || (Char) >= 0xE000) && \ + (Char) != 0xFFFE && (Char) != 0xFFFF) + +/** + * Gets a unicode character from a UTF-8 string. Does no validation; + * you must verify that the string is valid UTF-8 in advance and must + * pass in the start of a character. + * + * @param str the string + * @param start the start of the UTF-8 character. + * @param ch_return location to return the character + * @param end_return location to return the byte index of next character + * @returns #TRUE on success, #FALSE otherwise. + */ +void +_dbus_string_get_unichar (const DBusString *str, + int start, + dbus_unichar_t *ch_return, + int *end_return) +{ + int i, mask, len; + dbus_unichar_t result; + unsigned char c; + unsigned char *p; + DBUS_CONST_STRING_PREAMBLE (str); + + if (ch_return) + *ch_return = 0; + if (end_return) + *end_return = real->len; + + mask = 0; + p = real->str + start; + c = *p; + + UTF8_COMPUTE (c, mask, len); + if (len == -1) + return; + UTF8_GET (result, p, i, mask, len); + + if (result == (dbus_unichar_t)-1) + return; + + if (ch_return) + *ch_return = result; + if (end_return) + *end_return = start + len; +} + +/** @} */ + +#ifdef DBUS_BUILD_TESTS +#include "dbus-test.h" +#include + +static void +test_max_len (DBusString *str, + int max_len) +{ + if (max_len > 0) + { + if (!_dbus_string_set_length (str, max_len - 1)) + _dbus_assert_not_reached ("setting len to one less than max should have worked"); + } + + if (!_dbus_string_set_length (str, max_len)) + _dbus_assert_not_reached ("setting len to max len should have worked"); + + if (_dbus_string_set_length (str, max_len + 1)) + _dbus_assert_not_reached ("setting len to one more than max len should not have worked"); + + if (!_dbus_string_set_length (str, 0)) + _dbus_assert_not_reached ("setting len to zero should have worked"); +} + +/** + * @ingroup DBusStringInternals + * Unit test for DBusString. + * + * @todo Need to write tests for _dbus_string_copy() and + * _dbus_string_move() moving to/from each of start/middle/end of a + * string. + * + * @returns #TRUE on success. + */ +dbus_bool_t +_dbus_string_test (void) +{ + DBusString str; + DBusString other; + int i, end; + long v; + double d; + int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 }; + char *s; + dbus_unichar_t ch; + + i = 0; + while (i < _DBUS_N_ELEMENTS (lens)) + { + if (!_dbus_string_init (&str, lens[i])) + _dbus_assert_not_reached ("failed to init string"); + + test_max_len (&str, lens[i]); + _dbus_string_free (&str); + + ++i; + } + + /* Test shortening and setting length */ + i = 0; + while (i < _DBUS_N_ELEMENTS (lens)) + { + int j; + + if (!_dbus_string_init (&str, lens[i])) + _dbus_assert_not_reached ("failed to init string"); + + if (!_dbus_string_set_length (&str, lens[i])) + _dbus_assert_not_reached ("failed to set string length"); + + j = lens[i]; + while (j > 0) + { + _dbus_assert (_dbus_string_get_length (&str) == j); + if (j > 0) + { + _dbus_string_shorten (&str, 1); + _dbus_assert (_dbus_string_get_length (&str) == (j - 1)); + } + --j; + } + + _dbus_string_free (&str); + + ++i; + } + + /* Test appending data */ + if (!_dbus_string_init (&str, _DBUS_INT_MAX)) + _dbus_assert_not_reached ("failed to init string"); + + i = 0; + while (i < 10) + { + if (!_dbus_string_append (&str, "a")) + _dbus_assert_not_reached ("failed to append string to string\n"); + + _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1); + + if (!_dbus_string_append_byte (&str, 'b')) + _dbus_assert_not_reached ("failed to append byte to string\n"); + + _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2); + + ++i; + } + + _dbus_string_free (&str); + + /* Check steal_data */ + + if (!_dbus_string_init (&str, _DBUS_INT_MAX)) + _dbus_assert_not_reached ("failed to init string"); + + if (!_dbus_string_append (&str, "Hello World")) + _dbus_assert_not_reached ("could not append to string"); + + i = _dbus_string_get_length (&str); + + if (!_dbus_string_steal_data (&str, &s)) + _dbus_assert_not_reached ("failed to steal data"); + + _dbus_assert (_dbus_string_get_length (&str) == 0); + _dbus_assert (((int)strlen (s)) == i); + + dbus_free (s); + + /* Check move */ + + if (!_dbus_string_append (&str, "Hello World")) + _dbus_assert_not_reached ("could not append to string"); + + i = _dbus_string_get_length (&str); + + if (!_dbus_string_init (&other, _DBUS_INT_MAX)) + _dbus_assert_not_reached ("could not init string"); + + if (!_dbus_string_move (&str, 0, &other, 0)) + _dbus_assert_not_reached ("could not move"); + + _dbus_assert (_dbus_string_get_length (&str) == 0); + _dbus_assert (_dbus_string_get_length (&other) == i); + + _dbus_string_free (&other); + + /* Check copy */ + + if (!_dbus_string_append (&str, "Hello World")) + _dbus_assert_not_reached ("could not append to string"); + + i = _dbus_string_get_length (&str); + + if (!_dbus_string_init (&other, _DBUS_INT_MAX)) + _dbus_assert_not_reached ("could not init string"); + + if (!_dbus_string_copy (&str, 0, &other, 0)) + _dbus_assert_not_reached ("could not copy"); + + _dbus_assert (_dbus_string_get_length (&str) == i); + _dbus_assert (_dbus_string_get_length (&other) == i); + + _dbus_string_free (&str); + _dbus_string_free (&other); + + /* Check append/get unichar */ + + if (!_dbus_string_init (&str, _DBUS_INT_MAX)) + _dbus_assert_not_reached ("failed to init string"); + + ch = 0; + if (!_dbus_string_append_unichar (&str, 0xfffc)) + _dbus_assert_not_reached ("failed to append unichar"); + + _dbus_string_get_unichar (&str, 0, &ch, &i); + + _dbus_assert (ch == 0xfffc); + _dbus_assert (i == _dbus_string_get_length (&str)); + + _dbus_string_free (&str); + + /* Check append/parse int/double */ + + if (!_dbus_string_init (&str, _DBUS_INT_MAX)) + _dbus_assert_not_reached ("failed to init string"); + + if (!_dbus_string_append_int (&str, 27)) + _dbus_assert_not_reached ("failed to append int"); + + i = _dbus_string_get_length (&str); + + if (!_dbus_string_parse_int (&str, 0, &v, &end)) + _dbus_assert_not_reached ("failed to parse int"); + + _dbus_assert (v == 27); + _dbus_assert (end == i); + + _dbus_string_set_length (&str, 0); + + if (!_dbus_string_init (&str, _DBUS_INT_MAX)) + _dbus_assert_not_reached ("failed to init string"); + + if (!_dbus_string_append_double (&str, 50.3)) + _dbus_assert_not_reached ("failed to append float"); + + i = _dbus_string_get_length (&str); + + if (!_dbus_string_parse_double (&str, 0, &d, &end)) + _dbus_assert_not_reached ("failed to parse float"); + + _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6)); + _dbus_assert (end == i); + + _dbus_string_free (&str); + + return TRUE; +} + +#endif /* DBUS_BUILD_TESTS */ diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h new file mode 100644 index 00000000..4eda5954 --- /dev/null +++ b/dbus/dbus-string.h @@ -0,0 +1,136 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-string.h String utility class (internal to D-BUS implementation) + * + * Copyright (C) 2002 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef DBUS_STRING_H +#define DBUS_STRING_H + +#include +#include +#include + +DBUS_BEGIN_DECLS; + +typedef struct DBusString DBusString; + +struct DBusString +{ + void *dummy1; /**< placeholder */ + int dummy2; /**< placeholder */ + int dummy3; /**< placeholder */ + int dummy4; /**< placeholder */ + unsigned int dummy5 : 1; /** placeholder */ + unsigned int dummy6 : 1; /** placeholder */ + unsigned int dummy7 : 1; /** placeholder */ +}; + +dbus_bool_t _dbus_string_init (DBusString *str, + int max_length); +void _dbus_string_init_const (DBusString *str, + const char *value); +void _dbus_string_free (DBusString *str); +void _dbus_string_lock (DBusString *str); + +void _dbus_string_get_data (DBusString *str, + char **data_return); +void _dbus_string_get_const_data (const DBusString *str, + const char **data_return); +void _dbus_string_get_data_len (DBusString *str, + char **data_return, + int start, + int len); +void _dbus_string_get_const_data_len (const DBusString *str, + const char **data_return, + int start, + int len); +dbus_bool_t _dbus_string_steal_data (DBusString *str, + char **data_return); +dbus_bool_t _dbus_string_steal_data_len (DBusString *str, + char **data_return, + int start, + int len); + +int _dbus_string_get_length (const DBusString *str); + +dbus_bool_t _dbus_string_lengthen (DBusString *str, + int additional_length); +void _dbus_string_shorten (DBusString *str, + int length_to_remove); +dbus_bool_t _dbus_string_set_length (DBusString *str, + int length); + +dbus_bool_t _dbus_string_append (DBusString *str, + const char *buffer); +dbus_bool_t _dbus_string_append_len (DBusString *str, + const char *buffer, + int len); +dbus_bool_t _dbus_string_append_int (DBusString *str, + long value); +dbus_bool_t _dbus_string_append_double (DBusString *str, + double value); +dbus_bool_t _dbus_string_append_byte (DBusString *str, + unsigned char byte); +dbus_bool_t _dbus_string_append_unichar (DBusString *str, + dbus_unichar_t ch); + + +void _dbus_string_delete (DBusString *str, + int start, + int len); +dbus_bool_t _dbus_string_move (DBusString *source, + int start, + DBusString *dest, + int insert_at); +dbus_bool_t _dbus_string_copy (const DBusString *source, + int start, + DBusString *dest, + int insert_at); +dbus_bool_t _dbus_string_move_len (DBusString *source, + int start, + int len, + DBusString *dest, + int insert_at); +dbus_bool_t _dbus_string_copy_len (const DBusString *source, + int start, + int len, + DBusString *dest, + int insert_at); + + +void _dbus_string_get_unichar (const DBusString *str, + int start, + dbus_unichar_t *ch_return, + int *end_return); + +dbus_bool_t _dbus_string_parse_int (const DBusString *str, + int start, + long *value_return, + int *end_return); +dbus_bool_t _dbus_string_parse_double (const DBusString *str, + int start, + double *value, + int *end_return); + + +DBUS_END_DECLS; + +#endif /* DBUS_STRING_H */ diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c new file mode 100644 index 00000000..4bc3db9d --- /dev/null +++ b/dbus/dbus-sysdeps.c @@ -0,0 +1,223 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation) + * + * Copyright (C) 2002 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "dbus-sysdeps.h" +#include +#include +#include +#include +#include + +/** + * @addtogroup DBusInternalsUtils + * @{ + */ +/** + * Aborts the program with SIGABRT (dumping core). + */ +void +_dbus_abort (void) +{ + abort (); + _exit (1); /* in case someone manages to ignore SIGABRT */ +} + +/** + * Wrapper for getenv(). + * + * @param varname name of environment variable + * @returns value of environment variable or #NULL if unset + */ +const char* +_dbus_getenv (const char *varname) +{ + return getenv (varname); +} + +/** @} */ + +/** + * @addtogroup DBusString + * + * @{ + */ +/** + * Appends an integer to a DBusString. + * + * @param str the string + * @param value the integer value + * @returns #FALSE if not enough memory or other failure. + */ +dbus_bool_t +_dbus_string_append_int (DBusString *str, + long value) +{ + /* this calculation is from comp.lang.c faq */ +#define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */ + int orig_len; + int i; + char *buf; + + orig_len = _dbus_string_get_length (str); + + if (!_dbus_string_lengthen (str, MAX_LONG_LEN)) + return FALSE; + + _dbus_string_get_data_len (str, &buf, orig_len, MAX_LONG_LEN); + + snprintf (buf, MAX_LONG_LEN, "%ld", value); + + i = 0; + while (*buf) + { + ++buf; + ++i; + } + + _dbus_string_shorten (str, MAX_LONG_LEN - i); + + return TRUE; +} + +/** + * Appends a double to a DBusString. + * + * @param str the string + * @param value the floating point value + * @returns #FALSE if not enough memory or other failure. + */ +dbus_bool_t +_dbus_string_append_double (DBusString *str, + double value) +{ +#define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */ + int orig_len; + char *buf; + int i; + + orig_len = _dbus_string_get_length (str); + + if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN)) + return FALSE; + + _dbus_string_get_data_len (str, &buf, orig_len, MAX_DOUBLE_LEN); + + snprintf (buf, MAX_LONG_LEN, "%g", value); + + i = 0; + while (*buf) + { + ++buf; + ++i; + } + + _dbus_string_shorten (str, MAX_DOUBLE_LEN - i); + + return TRUE; +} + +/** + * Parses an integer contained in a DBusString. Either return parameter + * may be #NULL if you aren't interested in it. The integer is parsed + * and stored in value_return. Return parameters are not initialized + * if the function returns #FALSE. + * + * @param str the string + * @param start the byte index of the start of the integer + * @param value_return return location of the integer value or #NULL + * @param end_return return location of the end of the integer, or #NULL + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_string_parse_int (const DBusString *str, + int start, + long *value_return, + int *end_return) +{ + long v; + const char *p; + char *end; + + _dbus_string_get_const_data_len (str, &p, start, + _dbus_string_get_length (str) - start); + + end = NULL; + errno = 0; + v = strtol (p, &end, 0); + if (end == NULL || end == p || errno != 0) + return FALSE; + + if (value_return) + *value_return = v; + if (end_return) + *end_return = (end - p); + + return TRUE; +} + +/** + * Parses a floating point number contained in a DBusString. Either + * return parameter may be #NULL if you aren't interested in it. The + * integer is parsed and stored in value_return. Return parameters are + * not initialized if the function returns #FALSE. + * + * @todo this function is currently locale-dependent. Should + * ask alexl to relicense g_ascii_strtod() code and put that in + * here instead, so it's locale-independent. + * + * @param str the string + * @param start the byte index of the start of the float + * @param value_return return location of the float value or #NULL + * @param end_return return location of the end of the float, or #NULL + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_string_parse_double (const DBusString *str, + int start, + double *value_return, + int *end_return) +{ + double v; + const char *p; + char *end; + + _dbus_warn ("_dbus_string_parse_double() needs to be made locale-independent\n"); + + _dbus_string_get_const_data_len (str, &p, start, + _dbus_string_get_length (str) - start); + + end = NULL; + errno = 0; + v = strtod (p, &end); + if (end == NULL || end == p || errno != 0) + return FALSE; + + if (value_return) + *value_return = v; + if (end_return) + *end_return = (end - p); + + return TRUE; +} + +/** @} end of DBusString */ diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h new file mode 100644 index 00000000..92b782a8 --- /dev/null +++ b/dbus/dbus-sysdeps.h @@ -0,0 +1,51 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-sysdeps.h Wrappers around system/libc features (internal to D-BUS implementation) + * + * Copyright (C) 2002 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef DBUS_SYSDEPS_H +#define DBUS_SYSDEPS_H + +#include + +/* this is perhaps bogus, but strcmp() etc. are faster if we use the + * stuff straight out of string.h, so have this here for now. + */ +#include + +DBUS_BEGIN_DECLS; + +/* The idea of this file is to encapsulate everywhere that we're + * relying on external libc features, for ease of security + * auditing. The idea is from vsftpd. This also gives us a chance to + * make things more convenient to use, e.g. by reading into a + * DBusString. Operating system headers aren't intended to be used + * outside of this file and a limited number of others (such as + * dbus-memory.c) + */ + +void _dbus_abort (void); + +const char* _dbus_getenv (const char *varname); + +DBUS_END_DECLS; + +#endif /* DBUS_SYSDEPS_H */ diff --git a/dbus/dbus-test.c b/dbus/dbus-test.c index ad01fe0c..c1514246 100644 --- a/dbus/dbus-test.c +++ b/dbus/dbus-test.c @@ -29,6 +29,11 @@ int main (int argc, char **argv) { + + printf ("%s: running string tests\n", argv[0]); + if (!_dbus_string_test ()) + return 1; + printf ("%s: running linked list tests\n", argv[0]); if (!_dbus_list_test ()) return 1; diff --git a/dbus/dbus-test.h b/dbus/dbus-test.h index 29381a5a..0df49738 100644 --- a/dbus/dbus-test.h +++ b/dbus/dbus-test.h @@ -26,7 +26,8 @@ #include -dbus_bool_t _dbus_hash_test (void); -dbus_bool_t _dbus_list_test (void); +dbus_bool_t _dbus_hash_test (void); +dbus_bool_t _dbus_list_test (void); +dbus_bool_t _dbus_string_test (void); #endif /* DBUS_TEST_H */ diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index 85498872..e212cf43 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -24,6 +24,7 @@ #include "dbus-transport-protected.h" #include "dbus-transport-unix.h" #include "dbus-connection-internal.h" +#include "dbus-watch.h" /** * @defgroup DBusTransport DBusTransport object diff --git a/dbus/dbus-types.h b/dbus/dbus-types.h index e55e0053..f46b2367 100644 --- a/dbus/dbus-types.h +++ b/dbus/dbus-types.h @@ -27,10 +27,10 @@ #ifndef DBUS_TYPES_H #define DBUS_TYPES_H -typedef unsigned int dbus_bool_t; -typedef unsigned int dbus_uint32_t; -typedef int dbus_int32_t; - +typedef unsigned int dbus_bool_t; +typedef unsigned int dbus_uint32_t; +typedef int dbus_int32_t; +typedef dbus_uint32_t dbus_unichar_t; /* Normally docs are in .c files, but there isn't a .c file for this. */ /** -- cgit