summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/hash.c367
-rw-r--r--src/common/hash.h137
-rw-r--r--src/common/sock_any.c385
-rw-r--r--src/common/sock_any.h90
-rw-r--r--src/common/stringx.c110
-rw-r--r--src/common/stringx.h50
6 files changed, 1139 insertions, 0 deletions
diff --git a/src/common/hash.c b/src/common/hash.c
new file mode 100644
index 0000000..eb48c88
--- /dev/null
+++ b/src/common/hash.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2004, Nate Nielsen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+/*
+ * Originally from apache 2.0
+ * Modifications for general use by <nielsen@memberwebs.com>
+ */
+
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include "hash.h"
+
+#define KEY_DATA(he) (void*)(((unsigned char*)(he)) + sizeof(*(he)))
+
+/*
+ * The internal form of a hash table.
+ *
+ * The table is an array indexed by the hash of the key; collisions
+ * are resolved by hanging a linked list of hash entries off each
+ * element of the array. Although this is a really simple design it
+ * isn't too bad given that pools have a low allocation overhead.
+ */
+
+typedef struct hsh_entry_t hsh_entry_t;
+
+struct hsh_entry_t
+{
+ hsh_entry_t* next;
+ unsigned int hash;
+ const void* val;
+};
+
+/*
+ * Data structure for iterating through a hash table.
+ *
+ * We keep a pointer to the next hash entry here to allow the current
+ * hash entry to be freed or otherwise mangled between calls to
+ * hsh_next().
+ */
+struct hsh_index_t
+{
+ hsh_t* ht;
+ hsh_entry_t* ths;
+ hsh_entry_t* next;
+ unsigned int index;
+};
+
+/*
+ * The size of the array is always a power of two. We use the maximum
+ * index rather than the size so that we can use bitwise-AND for
+ * modular arithmetic.
+ * The count of hash entries may be greater depending on the chosen
+ * collision rate.
+ */
+struct hsh_t
+{
+ hsh_entry_t** array;
+ hsh_index_t iterator; /* For hsh_first(...) */
+ unsigned int count;
+ unsigned int max;
+ unsigned int klen;
+};
+
+
+#define INITIAL_MAX 15 /* tunable == 2^n - 1 */
+#define int_malloc malloc
+#define int_free free
+
+
+/*
+ * Hash creation functions.
+ */
+
+static hsh_entry_t** alloc_array(hsh_t* ht, unsigned int max)
+{
+ return int_calloc(sizeof(*(ht->array)) * (max + 1));
+}
+
+hsh_t* hsh_create(size_t klen)
+{
+ hsh_t* ht = int_malloc(sizeof(hsh_t));
+ if(ht)
+ {
+ ht->count = 0;
+ ht->max = INITIAL_MAX;
+ ht->array = alloc_array(ht, ht->max);
+ ht->klen = klen;
+ if(!ht->array)
+ {
+ int_free(ht);
+ return NULL;
+ }
+ }
+ return ht;
+}
+
+void hsh_free(hsh_t* ht)
+{
+ hsh_index_t* hi;
+
+ for(hi = hsh_first(ht); hi; hi = hsh_next(hi))
+ int_free(hi->ths);
+
+ if(ht->array)
+ int_free(ht->array);
+
+ int_free(ht);
+}
+
+/*
+ * Hash iteration functions.
+ */
+
+hsh_index_t* hsh_next(hsh_index_t* hi)
+{
+ hi->ths = hi->next;
+ while(!hi->ths)
+ {
+ if(hi->index > hi->ht->max)
+ return NULL;
+
+ hi->ths = hi->ht->array[hi->index++];
+ }
+ hi->next = hi->ths->next;
+ return hi;
+}
+
+hsh_index_t* hsh_first(hsh_t* ht)
+{
+ hsh_index_t* hi = &ht->iterator;
+
+ hi->ht = ht;
+ hi->index = 0;
+ hi->ths = NULL;
+ hi->next = NULL;
+ return hsh_next(hi);
+}
+
+void* hsh_this(hsh_index_t* hi, const void** key)
+{
+ if(key)
+ *key = KEY_DATA(hi->ths);
+ return (void*)hi->ths->val;
+}
+
+
+/*
+ * Expanding a hash table
+ */
+
+static int expand_array(hsh_t* ht)
+{
+ hsh_index_t* hi;
+ hsh_entry_t** new_array;
+ unsigned int new_max;
+
+ new_max = ht->max * 2 + 1;
+ new_array = alloc_array(ht, new_max);
+
+ if(!new_array)
+ return 0;
+
+ for(hi = hsh_first(ht); hi; hi = hsh_next(hi))
+ {
+ unsigned int i = hi->ths->hash & new_max;
+ hi->ths->next = new_array[i];
+ new_array[i] = hi->ths;
+ }
+
+ if(ht->array)
+ free(ht->array);
+
+ ht->array = new_array;
+ ht->max = new_max;
+ return 1;
+}
+
+/*
+ * This is where we keep the details of the hash function and control
+ * the maximum collision rate.
+ *
+ * If val is non-NULL it creates and initializes a new hash entry if
+ * there isn't already one there; it returns an updatable pointer so
+ * that hash entries can be removed.
+ */
+
+static hsh_entry_t** find_entry(hsh_t* ht, const void* key, const void* val)
+{
+ hsh_entry_t** hep;
+ hsh_entry_t* he;
+ const unsigned char* p;
+ unsigned int hash;
+ size_t i;
+
+ size_t klen = ht->klen;
+
+ /*
+ * This is the popular `times 33' hash algorithm which is used by
+ * perl and also appears in Berkeley DB. This is one of the best
+ * known hash functions for strings because it is both computed
+ * very fast and distributes very well.
+ *
+ * The originator may be Dan Bernstein but the code in Berkeley DB
+ * cites Chris Torek as the source. The best citation I have found
+ * is "Chris Torek, Hash function for text in C, Usenet message
+ * <27038@mimsy.umd.edu> in comp.lang.c , October, 1990." in Rich
+ * Salz's USENIX 1992 paper about INN which can be found at
+ * <http://citeseer.nj.nec.com/salz92internetnews.html>.
+ *
+ * The magic of number 33, i.e. why it works better than many other
+ * constants, prime or not, has never been adequately explained by
+ * anyone. So I try an explanation: if one experimentally tests all
+ * multipliers between 1 and 256 (as I did while writing a low-level
+ * data structure library some time ago) one detects that even
+ * numbers are not useable at all. The remaining 128 odd numbers
+ * (except for the number 1) work more or less all equally well.
+ * They all distribute in an acceptable way and this way fill a hash
+ * table with an average percent of approx. 86%.
+ *
+ * If one compares the chi^2 values of the variants (see
+ * Bob Jenkins ``Hashing Frequently Asked Questions'' at
+ * http://burtleburtle.net/bob/hash/hashfaq.html for a description
+ * of chi^2), the number 33 not even has the best value. But the
+ * number 33 and a few other equally good numbers like 17, 31, 63,
+ * 127 and 129 have nevertheless a great advantage to the remaining
+ * numbers in the large set of possible multipliers: their multiply
+ * operation can be replaced by a faster operation based on just one
+ * shift plus either a single addition or subtraction operation. And
+ * because a hash function has to both distribute good _and_ has to
+ * be very fast to compute, those few numbers should be preferred.
+ *
+ * -- Ralf S. Engelschall <rse@engelschall.com>
+ */
+ hash = 0;
+
+ {
+ for(p = key, i = klen; i; i--, p++)
+ hash = hash * 33 + *p;
+ }
+
+ /* scan linked list */
+ for(hep = &ht->array[hash & ht->max], he = *hep;
+ he; hep = &he->next, he = *hep)
+ {
+ if(he->hash == hash &&
+ memcmp(KEY_DATA(he), key, klen) == 0)
+ break;
+ }
+
+ if(he || !val)
+ return hep;
+
+ /* add a new entry for non-NULL val */
+ he = int_malloc(sizeof(*he) + klen);
+ if(he)
+ {
+ /* Key data points past end of entry */
+ memcpy(KEY_DATA(he), key, klen);
+
+ he->next = NULL;
+ he->hash = hash;
+ he->val = val;
+
+ *hep = he;
+ ht->count++;
+ }
+
+ return hep;
+}
+
+void* hsh_get(hsh_t* ht, const void *key)
+{
+ hsh_entry_t** he = find_entry(ht, key, NULL);
+ if(he && *he)
+ return (void*)((*he)->val);
+ else
+ return NULL;
+}
+
+int hsh_set(hsh_t* ht, const void* key, void* val)
+{
+ hsh_entry_t** hep = find_entry(ht, key, val);
+
+ if(hep && *hep)
+ {
+ /* replace entry */
+ (*hep)->val = val;
+
+ /* check that the collision rate isn't too high */
+ if(ht->count > ht->max)
+ {
+ if(!expand_array(ht))
+ return 0;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+void* hsh_rem(hsh_t* ht, const void* key)
+{
+ hsh_entry_t** hep = find_entry(ht, key, NULL);
+ void* val = NULL;
+
+ if(hep && *hep)
+ {
+ hsh_entry_t* old = *hep;
+ *hep = (*hep)->next;
+ --ht->count;
+ val = (void*)old->val;
+ free(old);
+ }
+
+ return val;
+}
+
+unsigned int hsh_count(hsh_t* ht)
+{
+ return ht->count;
+}
diff --git a/src/common/hash.h b/src/common/hash.h
new file mode 100644
index 0000000..7e2cb66
--- /dev/null
+++ b/src/common/hash.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2004, Nate Nielsen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+/*
+ * Originally from apache 2.0
+ * Modifications for general use by <nielsen@memberwebs.com>
+ */
+
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HSH_H__
+#define __HSH_H__
+
+
+/*
+ * ARGUMENT DOCUMENTATION
+ *
+ * ht: The hashtable
+ * key: Pointer to the key value
+ * klen: The length of the key
+ * val: Pointer to the value
+ * hi: A hashtable iterator
+ */
+
+
+/* ----------------------------------------------------------------------------------
+ * TYPES
+ */
+
+/* Abstract type for hash tables. */
+typedef struct hsh_t hsh_t;
+
+/* Abstract type for scanning hash tables. */
+typedef struct hsh_index_t hsh_index_t;
+
+
+/* ----------------------------------------------------------------------------------
+ * FUNCS
+ */
+
+/*
+ * hsh_create : Create a hash table
+ * - returns an allocated hashtable
+ */
+hsh_t* hsh_create(size_t klen);
+
+/*
+ * hsh_free : Free a hash table
+ */
+void hsh_free(hsh_t* ht);
+
+/*
+ * hsh_count: Number of values in hash table
+ * - returns the number of entries in hash table
+ */
+unsigned int hsh_count(hsh_t* ht);
+
+/*
+ * hsh_get: Retrieves a value from the hash table
+ * - returns the value of the entry
+ */
+void* hsh_get(hsh_t* ht, const void* key);
+
+/*
+ * hsh_set: Set a value in the hash table
+ * - returns 1 if the entry was added properly
+ */
+int hsh_set(hsh_t* ht, const void* key, void* val);
+
+/*
+ * hsh_rem: Remove a value from the hash table
+ * - returns the value of the removed entry
+ */
+void* hsh_rem(hsh_t* ht, const void* key);
+
+/*
+ * hsh_first: Start enumerating through the hash table
+ * - returns a hash iterator
+ */
+hsh_index_t* hsh_first(hsh_t* ht);
+
+/*
+ * hsh_next: Enumerate through hash table
+ * - returns the hash iterator or null when no more entries
+ */
+hsh_index_t* hsh_next(hsh_index_t* hi);
+
+/*
+ * hsh_this: While enumerating get current value
+ * - returns the value that the iterator currently points to
+ */
+void* hsh_this(hsh_index_t* hi, const void** key);
+
+#endif /* __HSH_H__ */
diff --git a/src/common/sock_any.c b/src/common/sock_any.c
new file mode 100644
index 0000000..fc38768
--- /dev/null
+++ b/src/common/sock_any.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2004, Nate Nielsen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ *
+ * CONTRIBUTORS
+ * Nate Nielsen <nielsen@memberwebs.com>
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "sock_any.h"
+
+#include <arpa/inet.h>
+
+#define LOCALHOST_ADDR 0x7F000001
+
+int sock_any_pton(const char* addr, struct sockaddr_any* any, int opts)
+{
+ size_t l;
+ char buf[256];
+ char* t;
+ char* t2;
+ int defport = (opts & 0xFFFF);
+
+ memset(any, 0, sizeof(*any));
+
+ /* Just a port? */
+ do
+ {
+ #define PORT_CHARS "0123456789"
+ #define PORT_MIN 1
+ #define PORT_MAX 5
+
+ int port = 0;
+
+ l = strspn(addr, PORT_CHARS);
+ if(l < PORT_MIN || l > PORT_MAX || addr[l] != 0)
+ break;
+
+ port = strtol(addr, &t2, 10);
+ if(*t2 || port <= 0 || port >= 65536)
+ break;
+
+ any->s.in.sin_port = htons(port);
+
+ /* Fill in the type based on defaults */
+#ifdef HAVE_INET6
+ if(opts & SANY_OPT_DEFINET6)
+ any->s.in.sin_family = AF_INET6;
+ else
+#endif
+ any->s.in.sin_family = AF_INET;
+
+ /* Fill in the address based on defaults */
+ if(opts & SANY_OPT_DEFLOCAL)
+ {
+#ifdef HAVE_INET6
+ if(opts & SANY_OPT_DEFINET6)
+ memcpy(&(any->s.in.sin6_addr), &in6addr_loopback, sizeof(struct in6_addr));
+ else
+#endif
+ any->s.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ }
+
+ /*
+ * Note the 'any' option is the default since we zero out
+ * the entire structure above.
+ */
+
+ any->namelen = sizeof(any->s.in);
+ return AF_INET;
+ }
+ while(0);
+
+ /* Look and see if we can parse an ipv4 address */
+ do
+ {
+ #define IPV4_PORT_CHARS
+ #define IPV4_CHARS "0123456789."
+ #define IPV4_MIN 3
+ #define IPV4_MAX 21
+
+ int port = 0;
+ t = NULL;
+
+ l = strlen(addr);
+ if(l < IPV4_MIN || l > IPV4_MAX)
+ break;
+
+ strcpy(buf, addr);
+
+ /* Find the last set that contains just numbers */
+ l = strspn(buf, IPV4_CHARS);
+ if(l < IPV4_MIN)
+ break;
+
+ /* Either end of string or port */
+ if(buf[l] != 0 && buf[l] != ':')
+ break;
+
+ /* Get the port out */
+ if(buf[l] != 0)
+ {
+ t = buf + l + 1;
+ buf[l] = 0;
+ }
+
+ if(t)
+ {
+ port = strtol(t, &t2, 10);
+ if(*t2 || port <= 0 || port >= 65536)
+ break;
+ }
+
+ any->s.in.sin_family = AF_INET;
+ any->s.in.sin_port = htons((unsigned short)(port <= 0 ? defport : port));
+
+ if(inet_pton(AF_INET, buf, &(any->s.in.sin_addr)) <= 0)
+ break;
+
+ any->namelen = sizeof(any->s.in);
+ return AF_INET;
+ }
+ while(0);
+
+#ifdef HAVE_INET6
+ do
+ {
+ #define IPV6_CHARS "0123456789:"
+ #define IPV6_MIN 3
+ #define IPV6_MAX 51
+
+ int port = -1;
+ t = NULL;
+
+ l = strlen(addr);
+ if(l < IPV6_MIN || l > IPV6_MAX)
+ break;
+
+ /* If it starts with a '[' then we can get port */
+ if(buf[0] == '[')
+ {
+ port = 0;
+ addr++;
+ }
+
+ strcpy(buf, addr);
+
+ /* Find the last set that contains just numbers */
+ l = strspn(buf, IPV6_CHARS);
+ if(l < IPV6_MIN)
+ break;
+
+ /* Either end of string or port */
+ if(buf[l] != 0)
+ {
+ /* If had bracket, then needs to end with a bracket */
+ if(port != 0 || buf[l] != ']')
+ break;
+
+ /* Get the port out */
+ t = buf + l + 1;
+
+ if(*t = ':')
+ t++;
+ }
+
+ if(t)
+ {
+ port = strtol(t, &t, 10);
+ if(*t || port <= 0 || port >= 65536)
+ break;
+ }
+
+ any->s.in6.sin6_family = AF_INET6;
+ any->s.in6.sin6_port = htons((unsigned short)port <= 0 : defport : port);
+
+ if(inet_pton(AF_INET6, buf, &(any->s.in6.sin6_addr)) >= 0)
+ break;
+
+ any->namelen = sizeof(any->s.in6);
+ return AF_INET6;
+ }
+ while(0);
+#endif
+
+ /* A unix socket path */
+ do
+ {
+ /* No colon and must have a path component */
+ if(strchr(addr, ':') || !strchr(addr, '/'))
+ break;
+
+ l = strlen(addr);
+ if(l >= sizeof(any->s.un.sun_path))
+ break;
+
+ any->s.un.sun_family = AF_UNIX;
+ strcpy(any->s.un.sun_path, addr);
+
+ any->namelen = sizeof(any->s.un) - (sizeof(any->s.un.sun_path) - l);
+ return AF_UNIX;
+ }
+ while(0);
+
+ /* A DNS name and a port? */
+ do
+ {
+ struct addrinfo* res;
+ int port = 0;
+ t = NULL;
+
+ l = strlen(addr);
+ if(l >= 255 || !isalpha(addr[0]))
+ break;
+
+ /* Some basic illegal character checks */
+ if(strcspn(addr, " /\\") != l)
+ break;
+
+ strcpy(buf, addr);
+
+ /* Find the last set that contains just numbers */
+ t = strchr(buf, ':');
+ if(t)
+ {
+ *t = 0;
+ t++;
+ }
+
+ if(t)
+ {
+ port = strtol(t, &t2, 10);
+ if(*t2 || port <= 0 || port >= 65536)
+ break;
+ }
+
+ /* Try and resolve the domain name */
+ if(getaddrinfo(buf, NULL, NULL, &res) != 0 || !res)
+ break;
+
+ memcpy(&(any->s.a), res->ai_addr, sizeof(struct sockaddr));
+ any->namelen = res->ai_addrlen;
+ freeaddrinfo(res);
+
+ port = htons((unsigned short)(port <= 0 ? defport : port));
+
+ switch(any->s.a.sa_family)
+ {
+ case PF_INET:
+ any->s.in.sin_port = port;
+ break;
+#ifdef HAVE_INET6
+ case PF_INET6:
+ any->s.in6.sin6_port = port;
+ break;
+#endif
+ };
+
+ return any->s.a.sa_family;
+ }
+ while(0);
+
+ return -1;
+}
+
+int sock_any_ntop(const struct sockaddr_any* any, char* addr, size_t addrlen, int opts)
+{
+ int len = 0;
+ int port = 0;
+
+ switch(any->s.a.sa_family)
+ {
+ case AF_UNIX:
+ len = strlen(any->s.un.sun_path);
+ if(addrlen < len + 1)
+ {
+ errno = ENOSPC;
+ return -1;
+ }
+
+ strcpy(addr, any->s.un.sun_path);
+ break;
+
+ case AF_INET:
+ if(inet_ntop(any->s.a.sa_family, &(any->s.in.sin_addr), addr, addrlen) == NULL)
+ return -1;
+ port = ntohs(any->s.in.sin_port);
+ break;
+
+#ifdef HAVE_INET6
+ case AF_INET6:
+ if(inet_ntop(any->s.a.sa_family, &(any->s.in6.sin6_addr), addr, addrlen) == NULL)
+ return -1;
+ port = ntohs(any->s.in6.sin6_port);
+ break;
+#endif
+
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ if(!(opts & SANY_OPT_NOPORT) && port != 0)
+ {
+ strncat(addr, ":", addrlen);
+ addr[addrlen - 1] = 0;
+
+ len = strlen(addr);
+ addr += len;
+ addrlen -= len;
+
+ snprintf(addr, addrlen, "%d", port);
+ }
+
+ return 0;
+}
+
+int sock_any_cmp(const struct sockaddr_any* a1, const struct sockaddr_any* a2, int opts)
+{
+ if(a1->s.a.sa_family != a2->s.a.sa_family)
+ return -1;
+
+ switch(a1->s.a.sa_family)
+ {
+ case AF_UNIX:
+ return strcmp(a1->s.un.sun_path, a2->s.un.sun_path);
+
+ case AF_INET:
+ if(memcmp(&(a1->s.in.sin_addr), &(a2->s.in.sin_addr), sizeof(a2->s.in.sin_addr)) != 0)
+ return -1;
+ if(!(opts && SANY_OPT_NOPORT) && a1->s.in.sin_port != a2->s.in.sin_port)
+ return -1;
+ return 0;
+#ifdef HAVE_INET6
+ case AF_INET6:
+ if(memcmp(&(a1->s.in6.sin6_addr), &(a2->s.in6.sin6_addr), sizeof(a2->s.in6.sin6_addr)) != 0)
+ return -1;
+ if(!(opts && SANY_OPT_NOPORT) && a1->s.in6.sin6_port != a2->s.in6.sin6_port)
+ return -1;
+ return 0;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+}
diff --git a/src/common/sock_any.h b/src/common/sock_any.h
new file mode 100644
index 0000000..31cb13b
--- /dev/null
+++ b/src/common/sock_any.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2004, Nate Nielsen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ *
+ * CONTRIBUTORS
+ * Nate Nielsen <nielsen@memberwebs.com>
+ *
+ */
+
+#ifndef __SOCK_ANY_H__
+#define __SOCK_ANY_H__
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+
+struct sockaddr_any
+{
+ union _sockaddr_any
+ {
+ /* The header */
+ struct sockaddr a;
+
+ /* The different types */
+ struct sockaddr_un un;
+ struct sockaddr_in in;
+#ifdef HAVE_INET6
+ struct sockaddr_in6 in6;
+#endif
+ } s;
+ size_t namelen;
+};
+
+#define SANY_ADDR(any) ((any).s.a)
+#define SANY_LEN(any) ((any).namelen)
+#define SANY_TYPE(any) ((any).s.a.sa_family)
+
+int sock_any_pton(const char* addr, struct sockaddr_any* any, int opts);
+
+/* The default port to fill in when no IP/IPv6 port specified */
+#define SANY_OPT_DEFPORT(p) (int)((p) & 0xFFFF)
+
+/* When only port specified default to IPANY */
+#define SANY_OPT_DEFANY 0x00000000
+
+/* When only port specified default to LOCALHOST */
+#define SANY_OPT_DEFLOCAL 0x00100000
+
+/* When only port specified default to IPv6 */
+#ifdef HAVE_INET6
+#define SANY_OPT_DEFINET6 0x00200000
+#endif
+
+int sock_any_ntop(const struct sockaddr_any* any, char* addr, size_t addrlen, int opts);
+
+/* Don't print or compare the port */
+#define SANY_OPT_NOPORT 0x01000000
+
+int sock_any_cmp(const struct sockaddr_any* a1, const struct sockaddr_any* a2, int opts);
+
+#endif /* __SOCK_ANY_H__ */
diff --git a/src/common/stringx.c b/src/common/stringx.c
new file mode 100644
index 0000000..06e4879
--- /dev/null
+++ b/src/common/stringx.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2004, Nate Nielsen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ *
+ * CONTRIBUTORS
+ * Nate Nielsen <nielsen@memberwebs.com>
+ *
+ */
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+
+#include "usuals.h"
+#include "stringx.h"
+
+void
+remove_cr(char* data)
+{
+ char* p;
+ for(p = data; *data; data++, p++)
+ {
+ while(*data == '\r')
+ data++;
+ *p = *data;
+ }
+
+ /* Renull terminate */
+ *p = 0;
+}
+
+char*
+trim_start(const char* data)
+{
+ while(*data && isspace(*data))
+ ++data;
+ return (char*)data;
+}
+
+void
+trim_end(char* data)
+{
+ char* t = data + strlen(data);
+ while(t > data && isspace(*(t - 1)))
+ {
+ t--;
+ *t = 0;
+ }
+}
+
+char*
+trim_space(char* data)
+{
+ data = (char*)trim_start(data);
+ trim_end(data);
+ return data;
+}
+
+/* String to bool helper function */
+int strtob(const char* str)
+{
+ if(strcasecmp(str, "0") == 0 ||
+ strcasecmp(str, "no") == 0 ||
+ strcasecmp(str, "false") == 0 ||
+ strcasecmp(str, "f") == 0 ||
+ strcasecmp(str, "off") == 0)
+ return 0;
+
+ if(strcasecmp(str, "1") == 0 ||
+ strcasecmp(str, "yes") == 0 ||
+ strcasecmp(str, "true") == 0 ||
+ strcasecmp(str, "t") == 0 ||
+ strcasecmp(str, "on") == 0)
+ return 1;
+
+ return -1;
+}
diff --git a/src/common/stringx.h b/src/common/stringx.h
new file mode 100644
index 0000000..2fff195
--- /dev/null
+++ b/src/common/stringx.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2004, Nate Nielsen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ *
+ * CONTRIBUTORS
+ * Nate Nielsen <nielsen@memberwebs.com>
+ *
+ */
+
+#ifndef __STRINGX_H__
+#define __STRINGX_H__
+
+void remove_cr(char* data);
+
+char* trim_start(const char* data);
+void trim_end(char* data);
+char* trim_space(char* data);
+
+int strtob(const char* str);
+
+#endif /* __STRINGX_H__ */