diff options
Diffstat (limited to 'cbtcommon')
-rw-r--r-- | cbtcommon/debug.c | 191 | ||||
-rw-r--r-- | cbtcommon/debug.h | 75 | ||||
-rw-r--r-- | cbtcommon/hash.c | 272 | ||||
-rw-r--r-- | cbtcommon/hash.h | 52 | ||||
-rw-r--r-- | cbtcommon/inline.h | 23 | ||||
-rw-r--r-- | cbtcommon/list.h | 112 | ||||
-rw-r--r-- | cbtcommon/rcsid.h | 21 | ||||
-rw-r--r-- | cbtcommon/sio.c | 87 | ||||
-rw-r--r-- | cbtcommon/sio.h | 29 | ||||
-rw-r--r-- | cbtcommon/tcpsocket.c | 257 | ||||
-rw-r--r-- | cbtcommon/tcpsocket.h | 33 | ||||
-rw-r--r-- | cbtcommon/text_util.c | 317 | ||||
-rw-r--r-- | cbtcommon/text_util.h | 43 |
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 */ |