summaryrefslogtreecommitdiff
path: root/cbtcommon
diff options
context:
space:
mode:
Diffstat (limited to 'cbtcommon')
-rw-r--r--cbtcommon/debug.c191
-rw-r--r--cbtcommon/debug.h75
-rw-r--r--cbtcommon/hash.c272
-rw-r--r--cbtcommon/hash.h52
-rw-r--r--cbtcommon/inline.h23
-rw-r--r--cbtcommon/list.h112
-rw-r--r--cbtcommon/rcsid.h21
-rw-r--r--cbtcommon/sio.c87
-rw-r--r--cbtcommon/sio.h29
-rw-r--r--cbtcommon/tcpsocket.c257
-rw-r--r--cbtcommon/tcpsocket.h33
-rw-r--r--cbtcommon/text_util.c317
-rw-r--r--cbtcommon/text_util.h43
13 files changed, 1512 insertions, 0 deletions
diff --git a/cbtcommon/debug.c b/cbtcommon/debug.c
new file mode 100644
index 0000000..3f5ac52
--- /dev/null
+++ b/cbtcommon/debug.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
+ * See COPYING file for license information
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "debug.h"
+#include "rcsid.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+RCSID("$Id: debug.c,v 1.14 2001/11/29 00:00:30 amb Exp $");
+
+unsigned int debuglvl = ~0;
+static FILE *debug_output_channel[DEBUG_NUM_FACILITIES];
+
+#ifdef MACINTOSH
+int ffs( int val )
+{
+ int i = 0;
+ for( i = 0; i < 32; i++ )
+ {
+ if( val & ( 1 << i ) )
+ return i+1;
+ }
+ return 0;
+}
+#endif
+
+void vdebug(int dtype, const char *fmt, va_list ap)
+{
+ int keep_errno;
+ char msgbuff[8192];
+
+ /* errno could be changed by vsprintf or perror */
+ keep_errno = errno;
+
+ if (debuglvl & dtype)
+ {
+ FILE * channel = debug_output_channel[ffs(dtype)];
+
+ if (!channel)
+ channel = stderr;
+
+#ifdef MACINTOSH
+ vsprintf(msgbuff, fmt, ap);
+#else
+ vsnprintf(msgbuff, sizeof(msgbuff), fmt, ap);
+#endif
+
+ /* DEBUG_ERROR (aka DEBUG_SYSERROR) */
+ if (dtype == DEBUG_ERROR)
+ {
+ const char * errmsg = "";
+
+#ifndef MACINTOSH
+ errmsg = strerror(errno);
+#endif
+
+ fprintf(channel, "%s: %s\n", msgbuff, errmsg);
+ }
+ else
+ fprintf(channel, "%s\n", msgbuff);
+
+ fflush(channel);
+#ifdef _WIN32
+ if (dtype == DEBUG_SYSERROR || dtype == DEBUG_APPERROR)
+ MessageBox(NULL, msgbuff, "Application Error", MB_OK);
+#endif
+ }
+
+ errno = keep_errno;
+}
+
+void vmdebug(int dtype, const char * fmt, va_list ap)
+{
+ FILE * chn[DEBUG_NUM_FACILITIES];
+ int i;
+
+ memcpy(chn, debug_output_channel, sizeof(FILE*) * DEBUG_NUM_FACILITIES);
+
+ for (i = 0; i < DEBUG_NUM_FACILITIES; i++)
+ if (chn[i] == NULL)
+ chn[i] = stderr;
+
+ for (i = 0; i < DEBUG_NUM_FACILITIES; i++)
+ {
+ if ((dtype & (1 << i)) && chn[i])
+ {
+
+ if (debuglvl & (1 << i))
+ {
+ int j;
+
+ vdebug(1 << i, fmt, ap);
+
+ for (j = i + 1; j < DEBUG_NUM_FACILITIES; j++)
+ if (chn[j] == chn[i])
+ chn[j] = NULL;
+ }
+ }
+ }
+}
+
+/* FIXME: use actual debug output core routine vdebug... */
+void hexdump(const char *ptr, int size, const char *fmt, ...)
+{
+ static char hexbuff[49];
+ static char printbuff[17];
+ int count = 0;
+ va_list ap;
+
+ if ( !debuglvl & DEBUG_STATUS )
+ return;
+
+ va_start(ap, fmt);
+
+ /* print the heading/banner */
+ vdebug(DEBUG_STATUS, fmt, ap);
+
+ memset(hexbuff, 0, 49);
+ memset(printbuff, 0, 17);
+
+ while (size--)
+ {
+ sprintf(hexbuff + (count*3), "%02x ", (int)*((unsigned char *)ptr));
+
+ if (isprint(*ptr))
+ printbuff[count] = *ptr;
+ else
+ printbuff[count] = '.';
+
+ ptr++;
+
+ if ( count++ == 15 )
+ {
+ count = 0;
+ debug(DEBUG_STATUS, "%s %s", hexbuff, printbuff);
+ memset(hexbuff, 0, 49);
+ memset(printbuff, 0, 17);
+ }
+ }
+
+ if ( count > 0 ) {
+ while ( count % 16 != 0 ) {
+ sprintf(hexbuff + (count * 3), "xx ");
+ printbuff[count++] = '.';
+ }
+ debug(DEBUG_STATUS, "%s %s", hexbuff, printbuff);
+ }
+
+ va_end(ap);
+}
+
+void
+to_hex( char* dest, const char* src, size_t n )
+{
+ while ( n-- )
+ {
+ sprintf( dest, "%02x ", (int)*((unsigned char *)src));
+ dest += 3;
+ src++;
+ }
+
+ *dest = 0;
+}
+
+void debug_set_error_file(FILE *f)
+{
+ int i;
+ for (i = 0; i < DEBUG_NUM_FACILITIES; i++)
+ debug_output_channel[i] = f;
+}
+
+void debug_set_error_facility(int fac, FILE * f)
+{
+ int i;
+
+ for (i = 0; i < DEBUG_NUM_FACILITIES; i++)
+ if (!debug_output_channel[i])
+ debug_output_channel[i] = stderr;
+
+ debug_output_channel[ffs(fac)] = f;
+}
diff --git a/cbtcommon/debug.h b/cbtcommon/debug.h
new file mode 100644
index 0000000..2ede381
--- /dev/null
+++ b/cbtcommon/debug.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
+ * See COPYING file for license information
+ */
+
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+#include <stdio.h>
+#include <stdarg.h>
+#ifndef MACINTOSH
+#include <sys/types.h>
+#endif
+
+#include "inline.h"
+
+#define DEBUG_NUM_FACILITIES 32 /* should be 64 on 64bit CPU... */
+#define DEBUG_SYSERROR 1 /* same as DEBUG_ERROR, but here for clarity */
+#define DEBUG_ERROR 1
+#define DEBUG_STATUS 2
+#define DEBUG_TCP 4
+#define DEBUG_SIGNALS 8
+#define DEBUG_APPERROR 16
+#define DEBUG_APPMSG1 32
+#define DEBUG_APPMSG2 64
+#define DEBUG_APPMSG3 128
+#define DEBUG_APPMSG4 256
+#define DEBUG_APPMSG5 512
+#define DEBUG_LIBERROR 1024
+#define DEBUG_LIBSTATUS 2048
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern unsigned int debuglvl;
+
+void hexdump( const char *ptr, int size, const char *fmt, ... );
+void vdebug(int dtype, const char *fmt, va_list);
+void vmdebug(int dtype, const char *fmt, va_list);
+void to_hex( char* dest, const char* src, size_t n );
+void debug_set_error_file(FILE *);
+void debug_set_error_facility(int mask, FILE *);
+
+static INLINE void debug(unsigned int dtype, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (!(debuglvl & dtype))
+ return;
+
+ va_start(ap, fmt);
+ vdebug(dtype, fmt, ap);
+ va_end(ap);
+}
+
+static INLINE void mdebug(unsigned int dtype, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (!(debuglvl & dtype))
+ return;
+
+ va_start(ap, fmt);
+ vmdebug(dtype, fmt, ap);
+ va_end(ap);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* DEBUG_H */
diff --git a/cbtcommon/hash.c b/cbtcommon/hash.c
new file mode 100644
index 0000000..ddc081b
--- /dev/null
+++ b/cbtcommon/hash.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
+ * See COPYING file for license information
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "debug.h"
+#include "hash.h"
+#include "rcsid.h"
+
+RCSID("$Id: hash.c,v 1.6 2003/05/07 15:42:38 david Exp $");
+
+#define HASH_CONST 37
+
+static unsigned int hash_string(const char *);
+static struct hash_entry *scan_list(struct list_head *, const char *);
+static struct hash_entry *get_hash_entry(struct hash_table *tbl, const char *key);
+
+struct hash_table *create_hash_table(unsigned int sz)
+{
+ struct hash_table *tbl;
+ unsigned int i;
+
+ tbl = (struct hash_table *)malloc(sizeof(*tbl) + sz*sizeof(struct list_head));
+
+ if (!tbl)
+ {
+ debug(DEBUG_APPERROR, "malloc for hash_table failed");
+ return NULL;
+ }
+
+ tbl->ht_size = sz;
+ tbl->ht_lists = (struct list_head *)(tbl + 1);
+ tbl->iterator = 0;
+
+ for (i = 0; i < sz; i++)
+ INIT_LIST_HEAD(&tbl->ht_lists[i]);
+
+ return tbl;
+}
+
+void destroy_hash_table(struct hash_table *tbl, void (*delete_obj)(void *))
+{
+ struct list_head *head, *next, *tmp;
+ struct hash_entry *entry;
+ int i;
+
+ for (i = 0; i < tbl->ht_size; i++)
+ {
+ head = &tbl->ht_lists[i];
+ next = head->next;
+
+ while (next != head)
+ {
+ tmp = next->next;
+ entry = list_entry(next, struct hash_entry, he_list);
+ if (delete_obj)
+ delete_obj(entry->he_obj);
+ free(entry);
+
+ next = tmp;
+ }
+ }
+
+ free(tbl);
+}
+
+/* FIXME: there is no way for the user of this to determine the difference
+ * between a put to a new key value and a malloc failure
+ */
+void *put_hash_object(struct hash_table *tbl, const char *key, void *obj)
+{
+ void * retval;
+ put_hash_object_ex(tbl, key, obj, HT_KEYCOPY, NULL, &retval);
+ return retval;
+}
+
+static struct hash_entry *get_hash_entry(struct hash_table *tbl, const char *key)
+{
+ struct list_head *head;
+ struct hash_entry *entry;
+ unsigned int hash;
+
+ hash = hash_string(key) % tbl->ht_size;
+ head = &tbl->ht_lists[hash];
+ entry = scan_list(head, key);
+
+ return entry;
+}
+
+void *get_hash_object(struct hash_table *tbl, const char *key)
+{
+ struct hash_entry *entry = get_hash_entry(tbl, key);
+ return (entry) ? entry->he_obj : NULL;
+}
+
+void *remove_hash_object(struct hash_table *tbl, const char *key)
+{
+ struct hash_entry *entry = get_hash_entry(tbl, key);
+ void *retval = NULL;
+
+ if (entry)
+ {
+ list_del(&entry->he_list);
+ retval = entry->he_obj;
+ free(entry);
+ }
+
+ return retval;
+}
+
+static unsigned int hash_string(register const char *key)
+{
+ register unsigned int hash = 0;
+
+ while(*key)
+ hash = hash * HASH_CONST + *key++;
+
+ return hash;
+}
+
+static struct hash_entry *scan_list(struct list_head *head, const char *key)
+{
+ struct list_head *next = head->next;
+ struct hash_entry *entry;
+
+ while (next != head)
+ {
+ entry = list_entry(next, struct hash_entry, he_list);
+ if (strcmp(entry->he_key, key) == 0)
+ return entry;
+
+ next = next->next;
+ }
+
+ return NULL;
+}
+
+void reset_hash_iterator(struct hash_table *tbl)
+{
+ tbl->iterator = 0;
+ tbl->iterator_ptr = NULL;
+}
+
+struct hash_entry *next_hash_entry(struct hash_table *tbl)
+{
+ while( tbl->iterator < tbl->ht_size )
+ {
+ struct list_head *head = &tbl->ht_lists[ tbl->iterator ];
+
+ if( tbl->iterator_ptr == NULL )
+ tbl->iterator_ptr = head->next;
+
+ if( tbl->iterator_ptr != head )
+ {
+ struct list_head *tmp = tbl->iterator_ptr;
+ tbl->iterator_ptr = tbl->iterator_ptr->next;
+ return( list_entry( tmp, struct hash_entry, he_list ) );
+ }
+
+ else
+ {
+ tbl->iterator++;
+ tbl->iterator_ptr = NULL;
+ }
+ }
+
+ return( NULL );
+}
+
+int put_hash_object_ex(struct hash_table *tbl, const char *key, void *obj, int copy,
+ char ** oldkey, void ** oldobj)
+{
+ struct list_head *head;
+ struct hash_entry *entry;
+ unsigned int hash;
+ int retval = 0;
+
+ /* FIXME: how can get_hash_entry be changed to be usable here?
+ * we need the value of head later if the entry is not found...
+ */
+ hash = hash_string(key) % tbl->ht_size;
+ head = &tbl->ht_lists[hash];
+ entry = scan_list(head, key);
+
+ if (entry)
+ {
+ if (oldkey)
+ *oldkey = entry->he_key;
+ if (oldobj)
+ *oldobj = entry->he_obj;
+
+ /* if 'copy' is set, then we already have an exact
+ * private copy of the key (by definition of having
+ * found the match in scan_list) so we do nothing.
+ * if !copy, then we can simply assign the new
+ * key
+ */
+ if (!copy)
+ entry->he_key = (char*)key; /* discard the const */
+ entry->he_obj = obj;
+ }
+ else
+ {
+ size_t s = sizeof(*entry);
+
+ if (oldkey)
+ *oldkey = NULL;
+ if (oldobj)
+ *oldobj = NULL;
+
+ if (copy)
+ s += strlen(key) + 1;
+
+ entry = (struct hash_entry *)malloc(s);
+
+ if (!entry)
+ {
+ debug(DEBUG_APPERROR,"malloc failed put_hash_object key='%s'",key);
+ retval = -1;
+ }
+ else
+ {
+ if (copy)
+ {
+ entry->he_key = (char *)(entry + 1);
+ strcpy(entry->he_key, key);
+ }
+ else
+ {
+ entry->he_key = (char*)key; /* discard the const */
+ }
+
+ entry->he_obj = obj;
+
+ list_add(&entry->he_list, head);
+ }
+ }
+
+ return retval;
+}
+
+void destroy_hash_table_ex(struct hash_table *tbl,
+ void (*delete_entry)(const void *, char *, void *),
+ const void * cookie)
+{
+ struct list_head *head, *next, *tmp;
+ struct hash_entry *entry;
+ int i;
+
+ for (i = 0; i < tbl->ht_size; i++)
+ {
+ head = &tbl->ht_lists[i];
+ next = head->next;
+
+ while (next != head)
+ {
+ tmp = next->next;
+ entry = list_entry(next, struct hash_entry, he_list);
+ if (delete_entry)
+ delete_entry(cookie, entry->he_key, entry->he_obj);
+ free(entry);
+
+ next = tmp;
+ }
+ }
+
+ free(tbl);
+}
diff --git a/cbtcommon/hash.h b/cbtcommon/hash.h
new file mode 100644
index 0000000..797e3b3
--- /dev/null
+++ b/cbtcommon/hash.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
+ * See COPYING file for license information
+ */
+
+#ifndef _COMMON_HASH_H
+#define _COMMON_HASH_H
+
+#include "list.h"
+
+struct hash_entry
+{
+ char *he_key;
+ void *he_obj;
+ struct list_head he_list;
+};
+
+struct hash_table
+{
+ int ht_size;
+ struct list_head *ht_lists;
+ int iterator;
+ struct list_head *iterator_ptr;
+};
+
+enum
+{
+ HT_NO_KEYCOPY,
+ HT_KEYCOPY
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct hash_table *create_hash_table(unsigned int sz);
+void destroy_hash_table(struct hash_table *tbl, void (*delete_obj)(void *));
+void *put_hash_object(struct hash_table *tbl, const char *key, void *obj);
+void *get_hash_object(struct hash_table *tbl, const char *key);
+void *remove_hash_object(struct hash_table *tbl, const char *key);
+
+int put_hash_object_ex(struct hash_table *tbl, const char *key, void *obj, int, char **, void **);
+void destroy_hash_table_ex(struct hash_table *tbl, void (*delete_entry)(const void *, char *, void *), const void *);
+
+void reset_hash_iterator(struct hash_table *tbl);
+struct hash_entry *next_hash_entry(struct hash_table *tbl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _COMMON_HASH_H */
diff --git a/cbtcommon/inline.h b/cbtcommon/inline.h
new file mode 100644
index 0000000..776ef26
--- /dev/null
+++ b/cbtcommon/inline.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
+ * See COPYING file for license information
+ */
+
+#ifndef UTIL_INLINE_H
+#define UTIL_INLINE_H
+
+#ifdef __GNUC__
+#define INLINE __inline__
+#endif
+
+#ifdef WIN32
+#define INLINE __inline
+#endif
+
+/* INLINE of last resort... heh */
+
+#ifndef INLINE
+#define INLINE /* void */
+#endif
+
+#endif
diff --git a/cbtcommon/list.h b/cbtcommon/list.h
new file mode 100644
index 0000000..4ee245d
--- /dev/null
+++ b/cbtcommon/list.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
+ * See COPYING file for license information
+ */
+
+#ifndef _COMMON_LIST_H
+#define _COMMON_LIST_H
+
+/*
+ * Stolen from linux-2.1.131
+ * All comments from the original source unless otherwise noted
+ * Added: the CLEAR_LIST_NODE macro
+ */
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+#include "inline.h"
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD(name) \
+ struct list_head name = { &name, &name }
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+#define CLEAR_LIST_NODE(ptr) do { \
+ (ptr)->next = NULL; (ptr)->prev = NULL; \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static INLINE void __list_add(struct list_head *li,
+ struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = li;
+ li->next = next;
+ li->prev = prev;
+ prev->next = li;
+}
+
+/*
+ * Insert a new entry after the specified head..
+ */
+static INLINE void list_add(struct list_head *li, struct list_head *head)
+{
+ __list_add(li, head, head->next);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static INLINE void __list_del(struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+static INLINE void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+static INLINE int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+/*
+ * Splice in "list" into "head"
+ */
+static INLINE void list_splice(struct list_head *list, struct list_head *head)
+{
+ struct list_head *first = list->next;
+
+ if (first != list) {
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+ }
+}
+
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+#endif /* _COMMON_LIST_H */
diff --git a/cbtcommon/rcsid.h b/cbtcommon/rcsid.h
new file mode 100644
index 0000000..b85b6fb
--- /dev/null
+++ b/cbtcommon/rcsid.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
+ * See COPYING file for license information
+ */
+
+#ifndef _COMMON_RCSID_H
+#define _COMMON_RCSID_H
+
+/* RCS Id macro (complements of bod@compusol.com.au (Brendan O'Dea)) */
+#ifdef lint
+# define RCSID(i)
+#else /* lint */
+# ifdef __GNUC__
+# define ATTRIB_UNUSED __attribute__ ((unused))
+# else /* __GNUC__ */
+# define ATTRIB_UNUSED
+# endif /* __GNUC__ */
+# define RCSID(i) static char const *rcsid ATTRIB_UNUSED = (i)
+#endif /* lint */
+
+#endif /* _COMMON_RCSID_H */
diff --git a/cbtcommon/sio.c b/cbtcommon/sio.c
new file mode 100644
index 0000000..a9faf81
--- /dev/null
+++ b/cbtcommon/sio.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
+ * See COPYING file for license information
+ */
+
+#include <stdio.h>
+
+#ifdef WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+
+#include "sio.h"
+#include "rcsid.h"
+
+RCSID("$Id: sio.c,v 1.5 2001/10/25 18:36:11 adam Exp $");
+
+ssize_t readn(int fd, void *buf, size_t len)
+{
+
+ int nleft,nread;
+
+ nleft = len;
+
+ while (nleft > 0)
+ {
+ nread = read(fd,buf,nleft);
+
+ /* there is an issue which EINTR which could leave us a bit haywire
+ * if we get a signal after having read some bytes. special handling
+ * N.B: we *do* return EINTR if no data has been read yet (thanks Karl)
+ */
+ if (nread < 0)
+ {
+ if (errno == EINTR && nleft != (int)len)
+ continue;
+ else
+ return (nread);
+ }
+ else if (nread == 0)
+ break;
+
+ nleft -= nread;
+
+ if (nleft)
+ buf = ((char *)buf) + nread;
+ }
+ return (len - nleft);
+}
+
+ssize_t writen(int fd, const void *buf, size_t len)
+{
+
+ int nleft, nwritten;
+
+ nleft = len;
+
+ while (nleft > 0)
+ {
+ nwritten = write(fd,buf,nleft);
+
+ /* there is an issue with EINTR if we have already written
+ a few bytes! return if we have not written any yet */
+ if (nwritten < 0 && errno == EINTR)
+ {
+ if (nleft == (int)len)
+ return nwritten;
+
+ continue;
+ }
+
+
+ if (nwritten <= 0)
+ return nwritten;
+
+ nleft -= nwritten;
+
+ if (nleft)
+ buf = ((char *)buf) + nwritten;
+ }
+
+ return (len - nleft);
+}
+
diff --git a/cbtcommon/sio.h b/cbtcommon/sio.h
new file mode 100644
index 0000000..f6f2978
--- /dev/null
+++ b/cbtcommon/sio.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
+ * See COPYING file for license information
+ */
+
+#ifndef _SIO_H
+#define _SIO_H
+
+/* include for typedefs */
+#ifdef WIN32
+#include <stdio.h>
+typedef int ssize_t;
+#else
+#include <unistd.h>
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* these are W.R.Stevens' famous io routines to read or write bytes to fd */
+ssize_t readn(int, void *, size_t);
+ssize_t writen(int, const void *, size_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SIO_H */
diff --git a/cbtcommon/tcpsocket.c b/cbtcommon/tcpsocket.c
new file mode 100644
index 0000000..27cc13a
--- /dev/null
+++ b/cbtcommon/tcpsocket.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
+ * See COPYING file for license information
+ */
+
+#ifdef SOLARIS
+#include <strings.h>
+#else
+#include <string.h>
+#endif
+
+#ifdef WIN32
+#include <winsock2.h>
+#else /* not windows */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <errno.h>
+
+#ifdef SOLARIS
+#include <netinet/tcp.h>
+#endif
+
+#endif /* if windows */
+
+#include "tcpsocket.h"
+#include "debug.h"
+#include "rcsid.h"
+#ifdef WIN32
+#include "win32fd.h"
+#endif
+
+RCSID("$Id: tcpsocket.c,v 1.6 1999/12/27 20:35:34 david Exp $");
+
+int
+tcp_create_socket(int reuse_addr)
+{
+ int retval;
+ int yes = 1;
+
+ if ((retval = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ debug(DEBUG_ERROR, "tcp: can't create socket");
+ }
+
+ if (reuse_addr)
+ {
+ setsockopt( retval, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(int));
+ }
+
+ debug(DEBUG_TCP, "tcp: socket created");
+#ifdef WIN32
+ return get_fd(retval, WIN32_SOCKET);
+#else
+ return retval;
+#endif
+}
+
+int
+tcp_bind_and_listen(int sockfd, unsigned short tcp_port)
+{
+ struct sockaddr_in addr;
+
+ memset((char *) &addr, 0, sizeof(struct sockaddr_in));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = htons(tcp_port);
+
+#ifdef WIN32
+ sockfd = win32_file_table[sockfd].win32id;
+#endif
+
+ if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+ {
+ debug(DEBUG_ERROR, "tcp: can't bind to socket");
+ return -1;
+ }
+
+
+ if (listen(sockfd, LISTEN_QUEUE_SIZE) < 0)
+ {
+ debug(DEBUG_ERROR, "tcp: can't listen on socket");
+ return -1;
+ }
+
+ debug(DEBUG_TCP, "tcp: socket bound and listening");
+
+ return 0;
+}
+
+int
+tcp_accept_connection(int sockfd)
+{
+ struct sockaddr_in remaddr;
+ int addrlen;
+ int retval;
+
+#ifdef WIN32
+ sockfd = win32_file_table[sockfd].win32id;
+#endif
+
+ addrlen = sizeof(struct sockaddr_in);
+
+#ifdef WIN32
+ if ((retval = accept(sockfd, (struct sockaddr *) &remaddr, &addrlen)) == INVALID_SOCKET)
+ {
+ debug(DEBUG_APPERROR, "tcp: error accepting connection");
+ return -1;
+ }
+#else
+ if ((retval = accept(sockfd, (struct sockaddr *) &remaddr, &addrlen)) < 0)
+ {
+ if (errno != EINTR )
+ debug(DEBUG_ERROR, "tcp: error accepting connection");
+
+ return -1;
+ }
+#endif
+
+ debug(DEBUG_TCP, "tcp: got connection (fd=%d)", retval);
+
+ return retval;
+}
+
+unsigned int
+tcp_get_client_ip(int fd)
+{
+ struct sockaddr_in remaddr;
+ int addrlen;
+ int retval;
+ unsigned int saddr;
+
+#ifdef WIN32
+ fd = win32_file_table[fd].win32id;
+#endif
+
+ addrlen = sizeof(struct sockaddr_in);
+
+ if ((retval = getpeername(fd, (struct sockaddr *) &remaddr, &addrlen)) < 0)
+ {
+ debug(DEBUG_ERROR, "tcp: error getting remote's ip address");
+ return 0;
+ }
+
+ saddr = ntohl(remaddr.sin_addr.s_addr);
+
+ return saddr;
+}
+
+int
+tcp_connect(int sockfd, const char *rem_addr, unsigned short port)
+{
+ struct sockaddr_in addr;
+ int addrlen;
+ long ipno;
+
+#ifdef WIN32
+ sockfd = win32_file_table[sockfd].win32id;
+#endif
+
+ if ( convert_address(&ipno , rem_addr) < 0 )
+ {
+ return -1;
+ }
+
+ addrlen = sizeof(struct sockaddr_in);
+
+ memset((char *) &addr, 0, sizeof(struct sockaddr_in));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = ipno;
+ addr.sin_port = htons(port);
+
+ if (connect(sockfd, (struct sockaddr *)&addr, addrlen) < 0)
+ {
+ debug(DEBUG_ERROR, "connect error");
+ return -1;
+ }
+
+ debug(DEBUG_STATUS, "tcp: connection established on port %d", port);
+ return 0;
+}
+
+int
+convert_address(long *dest, const char *addr_str)
+{
+#ifdef LINUX
+ struct in_addr ip;
+#endif
+ int retval = 0;
+ char errstr[256];
+
+ /* first try converting "numbers and dots" notation */
+#ifdef LINUX
+ if ( inet_aton(addr_str, &ip) )
+ {
+ memcpy(dest, &ip.s_addr, sizeof(ip.s_addr));
+ }
+#else
+ if ( (*dest = inet_addr(addr_str)) != -1)
+ {
+ /* nothing */
+ }
+#endif
+ else /* if it fails, do a gethostbyname() */
+ {
+ struct hostent *host;
+ if ((host = gethostbyname(addr_str)) == NULL)
+ {
+ switch(h_errno)
+ {
+ case HOST_NOT_FOUND:
+ strcpy(errstr, "HOST_NOT_FOUND");
+ break;
+
+ case NO_ADDRESS:
+ strcpy(errstr, "NO_ADDRESS");
+ break;
+
+ case NO_RECOVERY:
+ strcpy(errstr, "NO_RECOVERY");
+ break;
+
+ case TRY_AGAIN:
+ strcpy(errstr, "TRY_AGAIN");
+ break;
+ }
+
+ debug(DEBUG_ERROR, "gethostbyname failed for %s: ", addr_str, errstr);
+
+ retval = -1;
+ }
+
+ memcpy(dest, host->h_addr_list[0], sizeof(unsigned long));
+ }
+
+
+ return retval;
+}
+
+int tcp_get_local_address(int sockfd, unsigned int *ip, unsigned short *port)
+{
+ struct sockaddr_in addr;
+ int addrlen = sizeof(struct sockaddr_in);
+
+ if(getsockname(sockfd, (struct sockaddr *)&addr, &addrlen) < 0)
+ {
+ debug(DEBUG_SYSERROR, "getsockname failed" );
+ return -1;
+ }
+
+ *ip = ntohl( addr.sin_addr.s_addr );
+ *port = ntohs( addr.sin_port );
+
+ return 0;
+}
diff --git a/cbtcommon/tcpsocket.h b/cbtcommon/tcpsocket.h
new file mode 100644
index 0000000..ac606a5
--- /dev/null
+++ b/cbtcommon/tcpsocket.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
+ * See COPYING file for license information
+ */
+
+#ifndef _TCPSOCKET_H
+#define _TCPSOCKET_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifndef LISTEN_QUEUE_SIZE
+#define LISTEN_QUEUE_SIZE 5
+#endif
+
+#define REUSE_ADDR 1
+#define NO_REUSE_ADDR 0
+
+int tcp_create_socket(int reuse_addr);
+int tcp_bind_and_listen(int sockfd, unsigned short tcpport);
+int tcp_accept_connection(int sockfd);
+unsigned int tcp_get_client_ip(int fd);
+int tcp_connect(int sockfd, const char *rem_addr, unsigned short port);
+int convert_address(long *dest, const char *addr_str);
+int tcp_get_local_address(int sockfd, unsigned int *, unsigned short *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TCPSOCKET_H */
diff --git a/cbtcommon/text_util.c b/cbtcommon/text_util.c
new file mode 100644
index 0000000..052a94b
--- /dev/null
+++ b/cbtcommon/text_util.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
+ * See COPYING file for license information
+ */
+
+/**
+ * Copyright (c) 1998 Cobite, Inc. All Rights Reserved.
+ * @author Karl LaRocca
+ * @created Fri Nov 6 14:33:29 1998
+ * @version $Revision: 1.9 $$Date: 2001/10/25 18:36:11 $
+ */
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "text_util.h"
+#include "rcsid.h"
+
+RCSID("$Id: text_util.c,v 1.9 2001/10/25 18:36:11 adam Exp $");
+
+char*
+chop( char* src )
+{
+ char* p = src + strlen(src) - 1;
+
+ while( p >= src )
+ {
+ if ( *p == '\n' || *p == '\r' )
+ {
+ *p-- = 0;
+ }
+
+ else
+ {
+ break;
+ }
+ }
+
+ return( src );
+}
+
+char*
+digits( char* src )
+{
+ char* start = src;
+ char* check = src;
+
+ while( *check )
+ {
+ if ( isdigit( *check ) )
+ {
+ *start++ = *check;
+ }
+
+ check++;
+ }
+
+ *start = 0;
+
+ return( src );
+}
+
+char*
+lower_case( char* src )
+{
+ char* p = src;
+
+ while( *p )
+ {
+ *p = tolower( *p );
+ p++;
+ }
+
+ return( src );
+}
+
+char*
+reverse( char* src )
+{
+ int i;
+ int len = strlen( src );
+ char tmp;
+
+ for( i = len / 2; --i >= 0; )
+ {
+ tmp = src[ i ];
+ src[ i ] = src[ len - i - 1 ];
+ src[ len - i - 1 ] = tmp;
+ }
+
+ return( src );
+}
+
+char*
+trim( char* src )
+{
+ char *p = src + strlen(src) - 1;
+
+ while( p >= src && isspace(*p) )
+ *p-- = '\0';
+
+ return src;
+}
+
+char*
+upper_case( char* src )
+{
+ char* p = src;
+
+ while( *p )
+ {
+ *p = toupper(*p);
+ p++;
+ }
+
+ return( src );
+}
+
+int
+strrcmp( const char* haystack, const char* needle )
+{
+ int hlen = strlen( haystack );
+ int nlen = strlen( needle );
+ if( hlen < nlen )
+ return( -1 );
+ else
+ return( strcmp( haystack + hlen - nlen, needle ) );
+}
+
+/*
+ * Finding a - anywhere in the string makes it money negative.
+ * all characters other than digits, '-', and '.' are ignored, so:
+ * ab36-.g98 = -36.98
+ * This is fair, I think, if we don't want to reject anything as
+ * improperly formatted.
+ */
+long
+money2cents( const char* money )
+{
+ long retval = 0;
+ int decimal_places = -1;
+ int neg = 0;
+
+ while( *money && decimal_places < 2 )
+ {
+ if ( isdigit( *money ) )
+ {
+ if ( decimal_places >= 0 )
+ decimal_places++;
+
+ retval *= 10;
+ retval += (*money) - '0';
+ }
+
+ else if ( *money == '.' )
+ decimal_places = 0;
+
+ else if ( *money == '-' )
+ neg = 1;
+
+ money++;
+ }
+
+ if ( decimal_places == 1 )
+ retval *= 10;
+
+ else if ( decimal_places <= 0 )
+ retval *= 100;
+
+ return( neg ? -retval : retval );
+}
+
+const char*
+cents2money( long cents )
+{
+ static char buff[ 64 ];
+ int idx = 0;
+ char* d = buff;
+
+ if ( cents == 0 )
+ {
+ strcpy( buff, "0.00" );
+ }
+
+ else if ( cents < 100 )
+ {
+ sprintf( buff, "0.%2.2ld", cents );
+ }
+
+ else
+ {
+ while( cents > 0 )
+ {
+ *d++ = '0' + ( cents % 10 );
+ cents = cents / 10;
+
+ if ( idx == 1 )
+ {
+ *d++ = '.';
+ }
+
+ else if ( cents > 0 && ( idx - 1 ) % 3 == 0 )
+ {
+ *d++ = ',';
+ }
+
+ idx++;
+ }
+
+ *d++ = 0;
+
+ reverse( buff );
+ }
+
+ return( buff );
+}
+
+void trim_zeros_after_decimal( char* src )
+{
+ char * end = src + strlen( src ) - 1;
+
+ while( end != src )
+ {
+ if( *end == '0' )
+ *end = 0;
+ else if( *end == '.' )
+ {
+ *end = 0;
+ break;
+ }
+ else
+ break;
+
+ end--;
+ }
+}
+
+#ifdef linux
+extern void *memfrob(void *, size_t);
+#else
+static void * memfrob(void * mem, size_t len)
+{
+ size_t i;
+ char *c = (char *)mem;
+
+ for (i = 0; i < len; i++)
+ {
+ *c = *c ^ 42;
+ c++;
+ }
+
+ return mem;
+}
+#endif
+
+// simple functions to obfuscate strings in a binary
+char* frobstr( char* src )
+{
+ char* retval = (char*)malloc( strlen(src) * 2 + 1 );
+
+ memfrob( src, strlen( src ) );
+ str2hex( retval, src, 0 );
+ memfrob( src, strlen( src ) );
+
+ return( retval );
+}
+
+char* unfrobstr( char* src )
+{
+ int slen = strlen( src ) / 2;
+ char* retval = (char*)malloc( slen + 1 );
+
+ hex2str( retval, src, 0 );
+ memfrob( retval, slen );
+
+ return( retval );
+}
+
+void str2hex( char* dest, const char* src, int slen )
+{
+ int i;
+ char* p = dest;
+
+ if( slen == 0 )
+ slen = strlen( src );
+
+ for ( i = 0; i < slen; i++ )
+ {
+ sprintf( p, "%02x", src[i] );
+ p += 2;
+ }
+
+ *p = 0;
+}
+
+void hex2str( char* dest, const char* src, int slen )
+{
+ const char* p = src;
+ int i;
+ unsigned int v;
+
+ if( slen == 0 )
+ slen = strlen( src );
+
+ slen /= 2;
+
+ for( i = 0; i < slen; i++ )
+ {
+ sscanf( p, "%02x", &v );
+ dest[i] = (char)v;
+ p += 2;
+ }
+
+ dest[ slen ] = 0;
+}
+
diff --git a/cbtcommon/text_util.h b/cbtcommon/text_util.h
new file mode 100644
index 0000000..b22477b
--- /dev/null
+++ b/cbtcommon/text_util.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
+ * See COPYING file for license information
+ */
+
+/**
+ * Copyright (c) 1998 Cobite, Inc. All Rights Reserved.
+ * @author Karl LaRocca
+ * @created Fri Nov 6 14:48:04 1998
+ * @version $Revision: 1.4 $$Date: 2001/10/25 18:36:11 $
+ */
+#ifndef _TEXT_UTIL_H
+#define _TEXT_UTIL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+char* chop( char* src );
+char* digits( char* src );
+char* lower_case( char* src );
+char* reverse( char* src );
+char* trim( char* src );
+void trim_zeros_after_decimal( char* src );
+char* upper_case( char* src );
+int strrcmp( const char* haystack, const char* needle );
+
+const char* cents2money( long cents );
+long money2cents( const char* money );
+
+// these two allocate returned memory, so be sure to free it...
+char* frobstr( char* src );
+char* unfrobstr( char* src );
+
+void str2hex( char* dest, const char* src, int slen );
+void hex2str( char* dest, const char* src, int slen );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TEXT_UTIL_H */