Browse Source

Add a part of lub library

Serj Kalichev 9 years ago
parent
commit
f1ce5d7fbd

+ 8 - 4
Makefile.am

@@ -13,16 +13,20 @@ AM_CFLAGS = -Wall $(DEBUG_CFLAGS)
 #AM_CFLAGS = -ansi -pedantic -Werror -Wall -D_POSIX_C_SOURCE=199309 -DVERSION=$(VERSION) $(DEBUG_CFLAGS)
 
 sbin_PROGRAMS = birq
-
 lib_LTLIBRARIES =
+noinst_LTLIBRARIES =
 lib_LIBRARIES =
 nobase_include_HEADERS =
 
 birq_SOURCES = \
-	birq.c \
-	log.h \
-	log.c
+	birq.c
+
+birq_LDADD = liblub.la
+birq_DEPENDENCIES = liblub.la
 
 EXTRA_DIST = \
+	lub/module.am \
 	LICENCE \
 	README
+
+include $(top_srcdir)/lub/module.am

+ 2 - 2
birq.c

@@ -28,7 +28,7 @@
 #include <linux/types.h>
 #include <linux/netlink.h>
 
-#include "log.h"
+#include "lub/log.h"
 
 #ifndef VERSION
 #define VERSION 1.0.0
@@ -351,7 +351,7 @@ static int opts_parse(int argc, char *argv[], struct options *opts)
 			opts->debug = 1;
 			break;
 		case 'O':
-			if (parse_log_facility(optarg, &(opts->log_facility))) {
+			if (lub_log_facility(optarg, &(opts->log_facility))) {
 				fprintf(stderr, "Error: Illegal syslog facility %s.\n", optarg);
 				help(-1, argv[0]);
 				exit(-1);

+ 0 - 51
log.c

@@ -1,51 +0,0 @@
-#include "log.h"
-#include <syslog.h>
-#include <strings.h>
-
-int parse_log_facility(const char *str, int *facility)
-{
-	if (!strcasecmp(str, "local0"))
-		*facility = LOG_LOCAL0;
-	else if (!strcasecmp(str, "local1"))
-		*facility = LOG_LOCAL1;
-	else if (!strcasecmp(str, "local2"))
-		*facility = LOG_LOCAL2;
-	else if (!strcasecmp(str, "local3"))
-		*facility = LOG_LOCAL3;
-	else if (!strcasecmp(str, "local4"))
-		*facility = LOG_LOCAL4;
-	else if (!strcasecmp(str, "local5"))
-		*facility = LOG_LOCAL5;
-	else if (!strcasecmp(str, "local6"))
-		*facility = LOG_LOCAL6;
-	else if (!strcasecmp(str, "local7"))
-		*facility = LOG_LOCAL7;
-	else if (!strcasecmp(str, "auth"))
-		*facility = LOG_AUTH;
-	else if (!strcasecmp(str, "authpriv"))
-		*facility = LOG_AUTHPRIV;
-	else if (!strcasecmp(str, "cron"))
-		*facility = LOG_CRON;
-	else if (!strcasecmp(str, "daemon"))
-		*facility = LOG_DAEMON;
-	else if (!strcasecmp(str, "ftp"))
-		*facility = LOG_FTP;
-	else if (!strcasecmp(str, "kern"))
-		*facility = LOG_KERN;
-	else if (!strcasecmp(str, "lpr"))
-		*facility = LOG_LPR;
-	else if (!strcasecmp(str, "mail"))
-		*facility = LOG_MAIL;
-	else if (!strcasecmp(str, "news"))
-		*facility = LOG_NEWS;
-	else if (!strcasecmp(str, "syslog"))
-		*facility = LOG_SYSLOG;
-	else if (!strcasecmp(str, "user"))
-		*facility = LOG_USER;
-	else if (!strcasecmp(str, "uucp"))
-		*facility = LOG_UUCP;
-	else
-		return -1;
-
-	return 0;
-}

+ 3 - 0
lub/README

@@ -0,0 +1,3 @@
+lub "Little Useful Bits" Library
+This is a general purpose library of small utilities.
+The lub source is clish and klish projects.

+ 47 - 0
lub/c_decl.h

@@ -0,0 +1,47 @@
+/* 
+ * c_decl.h 
+ * 
+ * a simple set of macros to ease declaration of C interfaces.
+ */
+ /**
+\ingroup lub
+\defgroup lub_c_decl C linkage macros
+@{
+These two macros are used to simplify the declaration of C-linkage code.
+Rather than worry about preprocessor directives similar to
+\code
+#ifdef __cplusplus
+extern "C" {
+#endif 
+
+int foobar(void);
+
+#ifdef __cplusplus
+}
+#endif
+\endcode
+you simply need to use the _BEGIN_C_DECL and _END_C_DECL macros instead.
+
+\code
+#include "lub/c_decl.h"
+_BEGIN_C_DECL
+
+int foobar(void);
+
+_END_C_DECL
+\endcode
+*/
+
+#ifndef _lub_c_decl_h
+#define _lub_c_decl_h
+
+#ifdef __cplusplus
+#define _BEGIN_C_DECL extern "C" {
+#define _END_C_DECL   }
+#else				/* not __cplusplus */
+#define _BEGIN_C_DECL
+#define _END_C_DECL
+#endif				/* not __cplusplus */
+
+/** @} */
+#endif				/* _lub_c_decl_h */

+ 126 - 0
lub/ctype.h

@@ -0,0 +1,126 @@
+/*
+ * ctype.h
+ */
+/**
+\ingroup lub
+\defgroup lub_ctype ctype
+@{
+
+\brief The ANSI-C standard <ctype.h> interface works fine for strings 
+containing characters encoded with the ASCII 7-bit coding. However 
+when you use characters outside this range things start to get ambiguous. 
+
+The default manner in which to represent a string in C is to use a 
+"char *". (NB. this is a signed type) The interfaces presented 
+in <ctype.h> take signed integers. When a character greater than 128 is
+passed as a "char" to isspace() (e.g. the british pound sign "£") then 
+a negative value is passed into the function/macro. A typical
+implementation (e.g. VxWorks) may use the passed argument as an offset
+into a lookup table, negative values in this case cause problems...
+
+This utility provides an interface which avoids this ambiguity by passing 
+"char" characters directly rather than converting to "int".
+
+This component currently only contains those operations which are required
+by the current CLISH/LUB implementations. It can be extended on an as needed 
+basis.
+
+*/
+/*---------------------------------------------------------------
+ * HISTORY
+ * 4-Sep-2006		Graeme McKerrell	
+ *    Initial Version
+ *---------------------------------------------------------------
+ * Copyright (C) 2006 Newport Networks. All Rights Reserved.
+ *--------------------------------------------------------------- */
+#ifndef _lub_ctype_h
+#define _lub_ctype_h
+
+#include "lub/types.h"
+
+#include "lub/c_decl.h"
+_BEGIN_C_DECL
+/**
+ * This operation identifies whether a character is a decimal digit
+ * or not.
+ *
+ * \pre 
+ * - none
+ * 
+ * \return 
+ * BOOL_TRUE  - if the character is a decimal digit
+ * BOOL_FALSE - if the character is not a decimal digit
+ *
+ * \post 
+ * - none
+ */
+bool_t lub_ctype_isdigit(
+	/** 
+         * The character to check
+         */
+				char c);
+/**
+ * This operation identifies whether a character is a standard white space
+ * character. (space, tab, carriage-return, vertical tab, form-feed)
+ *
+ * \pre 
+ * - none
+ * 
+ * \return 
+ * BOOL_TRUE  - if the character is white space
+ * BOOL_FALSE - if the character is not white space
+ *
+ * \post 
+ * - none
+ */
+bool_t lub_ctype_isspace(
+	/** 
+         * The character to check
+         */
+				char c);
+/**
+ * This operation converts an uppercase letter to the corresponding 
+ * lowercase letter.
+ *
+ * \pre 
+ * - none
+ * 
+ * \return 
+ * If the parameter is a character for which lub_ctype_isupper() is true 
+ * and there is a corresponding character for which lub_ctype_islower() is true
+ * then the corresponding character is returned. Otherwise the parameter is 
+ * returned unchanged.
+ *
+ * \post 
+ * - none
+ */
+char lub_ctype_tolower(
+	/** 
+         * The character to convert
+         */
+			      char c);
+/**
+ * This operation converts a lowercase letter to the corresponding 
+ * uppercase letter.
+ *
+ * \pre 
+ * - none
+ * 
+ * \return 
+ * If the parameter is a character for which lub_ctype_islower() is true 
+ * and there is a corresponding character for which lub_ctype_isupper() is true
+ * then the corresponding character is returned. Otherwise the parameter is 
+ * returned unchanged.
+ *
+ * \post 
+ * - none
+ */
+char lub_ctype_toupper(
+	/** 
+         * The character to convert
+         */
+			      char c);
+
+_END_C_DECL
+#endif				/* _lub_ctype_h */
+/** @} */

+ 14 - 0
lub/ctype/ctype_isdigit.c

@@ -0,0 +1,14 @@
+/*
+ * ctype_isdigit.c
+ */
+#include "lub/ctype.h"
+#include <ctype.h>
+
+/*--------------------------------------------------------- */
+bool_t lub_ctype_isdigit(char c)
+{
+	unsigned char tmp = (unsigned char)c;
+	return isdigit(tmp) ? BOOL_TRUE : BOOL_FALSE;
+}
+
+/*--------------------------------------------------------- */

+ 14 - 0
lub/ctype/ctype_isspace.c

@@ -0,0 +1,14 @@
+/*
+ * ctype_isspace.c
+ */
+#include "lub/ctype.h"
+#include <ctype.h>
+
+/*--------------------------------------------------------- */
+bool_t lub_ctype_isspace(char c)
+{
+	unsigned char tmp = (unsigned char)c;
+	return isspace(tmp) ? BOOL_TRUE : BOOL_FALSE;
+}
+
+/*--------------------------------------------------------- */

+ 14 - 0
lub/ctype/ctype_tolower.c

@@ -0,0 +1,14 @@
+/*
+ * ctype_tolower.c
+ */
+#include "lub/ctype.h"
+#include <ctype.h>
+
+/*--------------------------------------------------------- */
+char lub_ctype_tolower(char c)
+{
+	unsigned char tmp = (unsigned char)c;
+	return tolower(tmp);
+}
+
+/*--------------------------------------------------------- */

+ 14 - 0
lub/ctype/ctype_toupper.c

@@ -0,0 +1,14 @@
+/*
+ * ctype_toupper.c
+ */
+#include "lub/ctype.h"
+#include <ctype.h>
+
+/*--------------------------------------------------------- */
+char lub_ctype_toupper(char c)
+{
+	unsigned char tmp = (unsigned char)c;
+	return toupper(tmp);
+}
+
+/*--------------------------------------------------------- */

+ 5 - 0
lub/ctype/module.am

@@ -0,0 +1,5 @@
+liblub_la_SOURCES +=	lub/ctype/ctype_isspace.c	\
+			lub/ctype/ctype_isdigit.c	\
+			lub/ctype/ctype_toupper.c	\
+			lub/ctype/ctype_tolower.c
+

+ 62 - 0
lub/list.h

@@ -0,0 +1,62 @@
+#ifndef _lub_list_h
+#define _lub_list_h
+
+#include <stddef.h>
+#include "lub/c_decl.h"
+
+/****************************************************************
+ * TYPE DEFINITIONS
+ **************************************************************** */
+
+typedef struct lub_list_node_s lub_list_node_t;
+
+/**
+ * This type defines a callback function which will compare two nodes
+ * with each other
+ *
+ * \param clientnode 	the client node to compare
+ * \param clientkey 	the key to compare with a node
+ *
+ * \return
+ *     <0 if clientnode  < clientkey;
+ *      0 if clientnode == clientkey;
+ *     >0 if clientnode  > clientkey
+ */
+typedef int lub_list_compare_fn(const void *first, const void *second);
+
+/**
+ * This type represents a list instance
+ */
+typedef struct lub_list_s lub_list_t;
+
+/**
+ * This is used to perform iterations of a list
+ */
+typedef struct lub_list_node_s lub_list_iterator_t;
+
+_BEGIN_C_DECL
+/****************************************************************
+ * LIST OPERATIONS
+ **************************************************************** */
+/**
+ * This operation initialises an instance of a list.
+ */
+lub_list_t *lub_list_new(lub_list_compare_fn compareFn);
+lub_list_node_t *lub_list_node_new(void *data);
+void lub_list_free(lub_list_t *list);
+void lub_list_node_free(lub_list_node_t *node);
+lub_list_node_t *lub_list__get_head(lub_list_t *list);
+lub_list_node_t *lub_list__get_tail(lub_list_t *list);
+lub_list_node_t *lub_list_node__get_prev(lub_list_node_t *node);
+lub_list_node_t *lub_list_node__get_next(lub_list_node_t *node);
+void *lub_list_node__get_data(lub_list_node_t *node);
+lub_list_node_t *lub_list_iterator_init(lub_list_t *list);
+lub_list_node_t *lub_list_iterator_next(lub_list_node_t *node);
+lub_list_node_t *lub_list_iterator_prev(lub_list_node_t *node);
+lub_list_node_t *lub_list_add(lub_list_t *list, void *data);
+void lub_list_del(lub_list_t *list, lub_list_node_t *node);
+void lub_list_node_copy(lub_list_node_t *dst, lub_list_node_t *src);
+
+_END_C_DECL
+#endif				/* _lub_list_h */
+

+ 172 - 0
lub/list/list.c

@@ -0,0 +1,172 @@
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "private.h"
+
+/*--------------------------------------------------------- */
+static inline void lub_list_init(lub_list_t * this,
+	lub_list_compare_fn compareFn)
+{
+	this->head = NULL;
+	this->compareFn = compareFn;
+}
+
+/*--------------------------------------------------------- */
+lub_list_t *lub_list_new(lub_list_compare_fn compareFn)
+{
+	lub_list_t *this;
+
+	this = malloc(sizeof(*this));
+	assert(this);
+	lub_list_init(this, compareFn);
+
+	return this;
+}
+
+/*--------------------------------------------------------- */
+void inline lub_list_free(lub_list_t *this)
+{
+	free(this);
+}
+
+/*--------------------------------------------------------- */
+inline lub_list_node_t *lub_list__get_head(lub_list_t *this)
+{
+	return this->head;
+}
+
+/*--------------------------------------------------------- */
+inline lub_list_node_t *lub_list__get_tail(lub_list_t *this)
+{
+	return this->tail;
+}
+
+/*--------------------------------------------------------- */
+static inline void lub_list_node_init(lub_list_node_t *this,
+	void *data)
+{
+	this->prev = this->next = NULL;
+	this->data = data;
+}
+
+/*--------------------------------------------------------- */
+lub_list_node_t *lub_list_node_new(void *data)
+{
+	lub_list_node_t *this;
+
+	this = malloc(sizeof(*this));
+	assert(this);
+	lub_list_node_init(this, data);
+
+	return this;
+}
+
+/*--------------------------------------------------------- */
+inline lub_list_node_t *lub_list_iterator_init(lub_list_t *this)
+{
+	return this->head;
+}
+
+/*--------------------------------------------------------- */
+inline lub_list_node_t *lub_list_node__get_prev(lub_list_node_t *this)
+{
+	return this->prev;
+}
+
+/*--------------------------------------------------------- */
+inline lub_list_node_t *lub_list_node__get_next(lub_list_node_t *this)
+{
+	return this->next;
+}
+
+/*--------------------------------------------------------- */
+inline lub_list_node_t *lub_list_iterator_next(lub_list_node_t *this)
+{
+	return lub_list_node__get_next(this);
+}
+
+/*--------------------------------------------------------- */
+inline lub_list_node_t *lub_list_iterator_prev(lub_list_node_t *this)
+{
+	return lub_list_node__get_prev(this);
+}
+
+/*--------------------------------------------------------- */
+void inline lub_list_node_free(lub_list_node_t *this)
+{
+	free(this);
+}
+
+/*--------------------------------------------------------- */
+inline void *lub_list_node__get_data(lub_list_node_t *this)
+{
+	return this->data;
+}
+
+/*--------------------------------------------------------- */
+lub_list_node_t *lub_list_add(lub_list_t *this, void *data)
+{
+	lub_list_node_t *node = lub_list_node_new(data);
+	lub_list_node_t *iter;
+
+	/* Empty list */
+	if (!this->head) {
+		this->head = node;
+		this->tail = node;
+		return node;
+	}
+
+	/* Not sorted list. Add to the tail. */
+	if (!this->compareFn) {
+		node->prev = this->tail;
+		node->next = NULL;
+		this->tail->next = node;
+		this->tail = node;
+		return node;
+	}
+
+	/* Sorted list */
+	iter = this->tail;
+	while (iter) {
+		if (this->compareFn(node->data, iter->data) >= 0) {
+			node->next = iter->next;
+			node->prev = iter;
+			iter->next = node;
+			if (node->next)
+				node->next->prev = node;
+			break;
+		}
+		iter = iter->prev;
+	}
+	/* Insert node into the list head */
+	if (!iter) {
+		node->next = this->head;
+		node->prev = NULL;
+		this->head->prev = node;
+		this->head = node;
+	}
+	if (!node->next)
+		this->tail = node;
+
+	return node;
+}
+
+/*--------------------------------------------------------- */
+void lub_list_del(lub_list_t *this, lub_list_node_t *node)
+{
+	if (node->prev)
+		node->prev->next = node->next;
+	else
+		this->head = node->next;
+	if (node->next)
+		node->next->prev = node->prev;
+	else
+		this->tail = node->prev;
+}
+
+inline void lub_list_node_copy(lub_list_node_t *dst, lub_list_node_t *src)
+{
+	memcpy(dst, src, sizeof(lub_list_node_t));
+}
+/*--------------------------------------------------------- */

+ 5 - 0
lub/list/module.am

@@ -0,0 +1,5 @@
+## Process this file with automake to produce Makefile.in
+liblub_la_SOURCES += \
+	lub/list/list.c \
+	lub/list/private.h
+

+ 13 - 0
lub/list/private.h

@@ -0,0 +1,13 @@
+#include "lub/list.h"
+
+struct lub_list_node_s {
+	lub_list_node_t *prev;
+	lub_list_node_t *next;
+	void *data;
+};
+
+struct lub_list_s {
+	lub_list_node_t *head;
+	lub_list_node_t *tail;
+	lub_list_compare_fn *compareFn;
+};

+ 3 - 3
log.h → lub/log.h

@@ -1,5 +1,5 @@
-#ifndef _log_h
-#define _log_h
+#ifndef _lub_log_h
+#define _lub_log_h
 
 #include <syslog.h>
 
@@ -7,7 +7,7 @@
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-int parse_log_facility(const char *str, int *facility);
+int lub_log_facility(const char *str, int *facility);
 
 #endif
 

+ 51 - 0
lub/log/log.c

@@ -0,0 +1,51 @@
+#include "lub/log.h"
+#include <syslog.h>
+#include "lub/string.h"
+
+int lub_log_facility(const char *str, int *facility)
+{
+	if (!lub_string_nocasecmp(str, "local0"))
+		*facility = LOG_LOCAL0;
+	else if (!lub_string_nocasecmp(str, "local1"))
+		*facility = LOG_LOCAL1;
+	else if (!lub_string_nocasecmp(str, "local2"))
+		*facility = LOG_LOCAL2;
+	else if (!lub_string_nocasecmp(str, "local3"))
+		*facility = LOG_LOCAL3;
+	else if (!lub_string_nocasecmp(str, "local4"))
+		*facility = LOG_LOCAL4;
+	else if (!lub_string_nocasecmp(str, "local5"))
+		*facility = LOG_LOCAL5;
+	else if (!lub_string_nocasecmp(str, "local6"))
+		*facility = LOG_LOCAL6;
+	else if (!lub_string_nocasecmp(str, "local7"))
+		*facility = LOG_LOCAL7;
+	else if (!lub_string_nocasecmp(str, "auth"))
+		*facility = LOG_AUTH;
+	else if (!lub_string_nocasecmp(str, "authpriv"))
+		*facility = LOG_AUTHPRIV;
+	else if (!lub_string_nocasecmp(str, "cron"))
+		*facility = LOG_CRON;
+	else if (!lub_string_nocasecmp(str, "daemon"))
+		*facility = LOG_DAEMON;
+	else if (!lub_string_nocasecmp(str, "ftp"))
+		*facility = LOG_FTP;
+	else if (!lub_string_nocasecmp(str, "kern"))
+		*facility = LOG_KERN;
+	else if (!lub_string_nocasecmp(str, "lpr"))
+		*facility = LOG_LPR;
+	else if (!lub_string_nocasecmp(str, "mail"))
+		*facility = LOG_MAIL;
+	else if (!lub_string_nocasecmp(str, "news"))
+		*facility = LOG_NEWS;
+	else if (!lub_string_nocasecmp(str, "syslog"))
+		*facility = LOG_SYSLOG;
+	else if (!lub_string_nocasecmp(str, "user"))
+		*facility = LOG_USER;
+	else if (!lub_string_nocasecmp(str, "uucp"))
+		*facility = LOG_UUCP;
+	else
+		return -1;
+
+	return 0;
+}

+ 2 - 0
lub/log/module.am

@@ -0,0 +1,2 @@
+liblub_la_SOURCES += lub/log/log.c
+

+ 24 - 0
lub/module.am

@@ -0,0 +1,24 @@
+## Process this file with automake to generate Makefile.in
+noinst_LTLIBRARIES += liblub.la
+liblub_la_SOURCES =
+liblub_la_LIBADD =
+
+nobase_include_HEADERS += \
+    lub/list.h \
+    lub/c_decl.h \
+    lub/string.h \
+    lub/types.h \
+    lub/ctype.h \
+    lub/log.h
+
+EXTRA_DIST +=   \
+    lub/list/module.am \
+    lub/string/module.am \
+    lub/log/module.am \
+    lub/ctype/module.am \
+    lub/README
+
+include $(top_srcdir)/lub/list/module.am
+include $(top_srcdir)/lub/string/module.am
+include $(top_srcdir)/lub/log/module.am
+include $(top_srcdir)/lub/ctype/module.am

+ 278 - 0
lub/string.h

@@ -0,0 +1,278 @@
+/*
+ * string.h
+ */
+/**
+\ingroup lub
+\defgroup lub_string string
+@{
+
+\brief This utility provides some simple string manipulation functions which
+augment those found in the standard ANSI-C library.
+
+As a rule of thumb if a function returns "char *" then the calling client becomes responsible for invoking 
+lub_string_free() to release the dynamically allocated memory.
+
+If a "const char *" is returned then the client has no responsiblity for releasing memory.
+*/
+/*---------------------------------------------------------------
+ * HISTORY
+ * 7-Dec-2004		Graeme McKerrell	
+ *    Updated to use the "lub" prefix
+ * 6-Feb-2004		Graeme McKerrell	
+ *    removed init_fn type definition and parameter, the client had
+ *    more flexiblity in defining their own initialisation operation with
+ *    arguments rather than use a "one-size-fits-all" approach.
+ *    Modified blockpool structure to support FIFO block allocation.
+ * 23-Jan-2004		Graeme McKerrell	
+ *    Initial version
+ *---------------------------------------------------------------
+ * Copyright (C) 2004 3Com Corporation. All Rights Reserved.
+ *--------------------------------------------------------------- */
+#ifndef _lub_string_h
+#define _lub_string_h
+
+#include <stddef.h>
+
+#include "lub/c_decl.h"
+#include "lub/types.h"
+
+#define UTF8_MASK 0xC0
+#define UTF8_11   0xC0 /* First UTF8 byte */
+#define UTF8_10   0x80 /* Next UTF8 bytes */
+
+_BEGIN_C_DECL
+/**
+ * This operation duplicates the specified string.
+ *
+ * \pre 
+ * - none
+ * 
+ * \return 
+ * A dynamically allocated string containing the same content as that specified.
+ *
+ * \post 
+ * - The client is responsible for calling lub_string_free() with the
+ *   returned string when they are finished using it.
+ */
+char *lub_string_dup(
+	/** 
+         * The string to duplicate
+         */
+			    const char *string);
+/**
+ * This operation concatinates the specified text onto an existing string.
+ *
+ * \pre 
+ * - 'string_ptr' must contain reference to NULL or to a dynamically 
+ *   allocated string.
+ * 
+ * \post 
+ * - The old string referenced by 'string_ptr' will be automatically released
+ * - 'string_ptr' will be updated to point to a dynamically allocated string 
+ *   containing the concatinated text.
+ * - If there is insufficient resource to extend the string then it will not
+ *   be extended.
+ * - The client maintains responsibility for releasing the string reference
+ *   by string_ptr when they are finished using it.
+ */
+void lub_string_cat(
+	/** 
+         * A pointer to the string to concatinate
+         */
+			   char **string_ptr,
+	/** 
+         * The text to be appended
+         */
+			   const char *text);
+/**
+ * This operation concatinates a specified length of some text onto an
+ * existing string.
+ *
+ * \pre 
+ * - 'string_ptr' must contain reference to NULL or to a dynamically allocated
+ *   string.
+ * 
+ * \post 
+ * - The old string referenced by 'string_ptr' will be automatically
+ *   released.
+ * - 'string_ptr' will be updated to point to a dynamically allocated
+ *   string containing the concatinated text.
+ * - If there is insufficient resource to extend the string then it will not
+ *   be extended.
+ * - If there length passed in is greater than that of the specified 'text'
+ *   then the length of the 'text' will be assumed.
+ * - The client maintains responsibility for releasing the string reference
+ *   by string_ptr when they are finished using it.
+ */
+void lub_string_catn(
+	/** 
+         * A pointer to the string to concatinate
+         */
+			    char **string_ptr,
+	/** 
+         * The text to be appended
+         */
+			    const char *text,
+	/** 
+         * The length of text to be appended
+         */
+			    size_t length);
+/**
+ * This operation dupicates a specified length of some text into a
+ * new string.
+ *
+ * \pre 
+ * - none
+ * 
+ * \return 
+ * A dynamically allocated string containing the same content as that specified.
+ *
+ * \post 
+ * - The client is responsible for calling lub_string_free() with the
+ *   returned string when they are finished using it.
+ */
+char *lub_string_dupn(
+	/** 
+         * The string containing the text to duplicate
+         */
+			     const char *string,
+	/** 
+         * The length of text to be duplicated
+         */
+			     unsigned length);
+/**
+ * This operation returns a pointer to the last (space separated) word in the
+ * specified string.
+ *
+ * \pre 
+ * - none
+ * 
+ * \return 
+ * A pointer to the last word in the string.
+ *
+ * \post 
+ * - none
+ */
+const char *lub_string_suffix(
+	/**
+         * The string from which to extract a suffix 
+         */
+				     const char *string);
+
+/**
+ * This operation compares string cs to string ct in a case insensitive manner.
+ *
+ * \pre 
+ * - none
+ * 
+ * \return 
+ * - < 0 if cs < ct
+ * -   0 if cs == ct
+ * - > 0 if cs > ct
+ *
+ * \post 
+ * - none
+ */
+int lub_string_nocasecmp(
+	/**
+         * The first string for the comparison
+         */
+				const char *cs,
+	/**
+         * The second string for the comparison 
+         */
+				const char *ct);
+/**
+ * This operation performs a case insensitive search for a substring within
+ * another string.
+ *
+ * \pre 
+ * - none
+ * 
+ * \return
+ * pointer to first occurance of a case insensitive version of the string ct, 
+ * or NULL if not present.
+ *
+ * \post 
+ * - none
+ */
+const char *lub_string_nocasestr(
+	/**
+         * The string within which to find a substring
+         */
+					const char *cs,
+	/**
+         * The substring for which to search
+         */
+					const char *ct);
+
+/**
+ * This operation releases the resources associated with a dynamically allocated
+ * string.
+ *
+ * \pre 
+ * - The calling client must have responsibility for the passed string.
+ * 
+ * \return
+ * none
+ *
+ * \post 
+ * - The string is no longer usable, any references to it must be discarded.
+ */
+void lub_string_free(
+	/**
+         * The string to be released
+         */
+			    char *string);
+
+/*
+ * These are the escape characters which are used by default when 
+ * expanding variables. These characters will be backslash escaped
+ * to prevent them from being interpreted in a script.
+ *
+ * This is a security feature to prevent users from arbitarily setting
+ * parameters to contain special sequences.
+ */
+extern const char *lub_string_esc_default;
+extern const char *lub_string_esc_regex;
+extern const char *lub_string_esc_quoted;
+
+/**
+ * This operation decode the escaped string.
+ *
+ * \pre
+ * - none
+ *
+ * \return
+ * - The allocated string without escapes.
+ *
+ * \post
+ * - The result string must be freed after using.
+ */
+char *lub_string_decode(const char *string);
+char *lub_string_ndecode(const char *string, unsigned int len);
+
+/**
+ * This operation encode the string using escape.
+ *
+ * \pre
+ * - none
+ *
+ * \return
+ * - The allocated string with escapes.
+ *
+ * \post
+ * - The result string must be freed after using.
+ */
+char *lub_string_encode(const char *string, const char *escape_chars);
+
+char *lub_string_tolower(const char *str);
+unsigned int lub_string_equal_part(const char *str1, const char *str2,
+	bool_t utf8);
+const char *lub_string_nextword(const char *string,
+	size_t *len, size_t *offset, size_t *quoted);
+unsigned int lub_string_wordcount(const char *line);
+
+_END_C_DECL
+#endif				/* _lub_string_h */
+/** @} */

+ 12 - 0
lub/string/module.am

@@ -0,0 +1,12 @@
+liblub_la_SOURCES += \
+	lub/string/string_cat.c\
+	lub/string/string_catn.c \
+	lub/string/string_dup.c \
+	lub/string/string_free.c \
+	lub/string/string_nocasecmp.c \
+	lub/string/string_nocasestr.c \
+	lub/string/string_suffix.c \
+	lub/string/string_escape.c \
+	lub/string/string_word.c \
+	lub/string/private.h
+

+ 4 - 0
lub/string/private.h

@@ -0,0 +1,4 @@
+/*
+ * private.h
+ */
+#include "lub/string.h"

+ 14 - 0
lub/string/string_cat.c

@@ -0,0 +1,14 @@
+/*
+ * string_cat.c
+ */
+#include "private.h"
+
+#include <string.h>
+/*--------------------------------------------------------- */
+void lub_string_cat(char **string, const char *text)
+{
+	size_t len = text ? strlen(text) : 0;
+	lub_string_catn(string, text, len);
+}
+
+/*--------------------------------------------------------- */

+ 39 - 0
lub/string/string_catn.c

@@ -0,0 +1,39 @@
+/*
+ * string_cat.c
+ */
+#include "private.h"
+
+#include <string.h>
+#include <stdlib.h>
+/*--------------------------------------------------------- */
+void lub_string_catn(char **string, const char *text, size_t len)
+{
+	if (text) {
+		char *q;
+		size_t length, initlen, textlen = strlen(text);
+
+		/* make sure the client cannot give us duff details */
+		len = (len < textlen) ? len : textlen;
+
+		/* remember the size of the original string */
+		initlen = *string ? strlen(*string) : 0;
+
+		/* account for '\0' */
+		length = initlen + len + 1;
+
+		/* allocate the memory for the result */
+		q = realloc(*string, length);
+		if (NULL != q) {
+			*string = q;
+			/* move to the end of the initial string */
+			q += initlen;
+
+			while (len--) {
+				*q++ = *text++;
+			}
+			*q = '\0';
+		}
+	}
+}
+
+/*--------------------------------------------------------- */

+ 32 - 0
lub/string/string_dup.c

@@ -0,0 +1,32 @@
+/*
+ * string_dup.c
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#include "private.h"
+
+/*--------------------------------------------------------- */
+char *lub_string_dup(const char *string)
+{
+	if (!string)
+		return NULL;
+	return strdup(string);
+}
+
+/*--------------------------------------------------------- */
+char *lub_string_dupn(const char *string, unsigned int len)
+{
+	char *res = NULL;
+
+	if (!string)
+		return res;
+	res = malloc(len + 1);
+	strncpy(res, string, len);
+	res[len] = '\0';
+
+	return res;
+}
+
+
+/*--------------------------------------------------------- */

+ 93 - 0
lub/string/string_escape.c

@@ -0,0 +1,93 @@
+/*
+ * string_escape.c
+ */
+#include "private.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+const char *lub_string_esc_default = "`|$<>&()#;\\\"!";
+const char *lub_string_esc_regex = "^$.*+[](){}";
+const char *lub_string_esc_quoted = "\\\"";
+
+/*--------------------------------------------------------- */
+char *lub_string_ndecode(const char *string, unsigned int len)
+{
+	const char *s = string;
+	char *res, *p;
+	int esc = 0;
+
+	if (!string)
+		return NULL;
+
+	/* Allocate enough memory for result */
+	p = res = malloc(len + 1);
+
+	while (*s && (s < (string +len))) {
+		if (!esc) {
+			if ('\\' == *s)
+				esc = 1;
+			else
+				*p = *s;
+		} else {
+/*			switch (*s) {
+			case 'r':
+			case 'n':
+				*p = '\n';
+				break;
+			case 't':
+				*p = '\t';
+				break;
+			default:
+				*p = *s;
+				break;
+			}
+*/			*p = *s;
+			esc = 0;
+		}
+		if (!esc)
+			p++;
+		s++;
+	}
+	*p = '\0';
+
+	return res;
+}
+
+/*--------------------------------------------------------- */
+inline char *lub_string_decode(const char *string)
+{
+	return lub_string_ndecode(string, strlen(string));
+}
+
+/*----------------------------------------------------------- */
+/*
+ * This needs to escape any dangerous characters within the command line
+ * to prevent gaining access to the underlying system shell.
+ */
+char *lub_string_encode(const char *string, const char *escape_chars)
+{
+	char *result = NULL;
+	const char *p;
+
+	if (!escape_chars)
+		return lub_string_dup(string);
+	if (string && !(*string)) /* Empty string */
+		return lub_string_dup(string);
+
+	for (p = string; p && *p; p++) {
+		/* find any special characters and prefix them with '\' */
+		size_t len = strcspn(p, escape_chars);
+		lub_string_catn(&result, p, len);
+		p += len;
+		if (*p) {
+			lub_string_catn(&result, "\\", 1);
+			lub_string_catn(&result, p, 1);
+		} else {
+			break;
+		}
+	}
+	return result;
+}
+
+/*--------------------------------------------------------- */

+ 14 - 0
lub/string/string_free.c

@@ -0,0 +1,14 @@
+/*
+ * string_free.c
+ */
+#include "private.h"
+
+#include <stdlib.h>
+
+/*--------------------------------------------------------- */
+void lub_string_free(char *ptr)
+{
+	free(ptr);
+}
+
+/*--------------------------------------------------------- */

+ 51 - 0
lub/string/string_nocasecmp.c

@@ -0,0 +1,51 @@
+/*
+ * string_nocasecmp.c
+ */
+#include <string.h>
+#include <ctype.h>
+
+#include "private.h"
+#include "lub/ctype.h"
+
+
+/*--------------------------------------------------------- */
+int lub_string_nocasecmp(const char *cs, const char *ct)
+{
+	int result = 0;
+	while ((0 == result) && *cs && *ct) {
+		/*lint -e155 Ignoring { }'ed sequence within an expression, 0 assumed 
+		 * MACRO implementation uses braces to prevent multiple increments
+		 * when called.
+		 */
+		int s = lub_ctype_tolower(*cs++);
+		int t = lub_ctype_tolower(*ct++);
+
+		result = s - t;
+	}
+	/*lint -e774 Boolean within 'if' always evealuates to True 
+	 * not the case because of tolower() evaluating to 0 under lint
+	 * (see above)
+	 */
+	if (0 == result) {
+		/* account for different string lengths */
+		result = *cs - *ct;
+	}
+	return result;
+}
+
+/*--------------------------------------------------------- */
+char *lub_string_tolower(const char *str)
+{
+	char *tmp = strdup(str);
+	char *p = tmp;
+
+	while (*p) {
+		*p = tolower(*p);
+		p++;
+	}
+
+	return tmp;
+}
+
+
+/*--------------------------------------------------------- */

+ 69 - 0
lub/string/string_nocasestr.c

@@ -0,0 +1,69 @@
+/*
+ * string_nocasestr.c
+ *
+ * Find a string within another string in a case insensitive manner
+ */
+#include "private.h"
+
+#include "lub/ctype.h"
+
+/*--------------------------------------------------------- */
+const char *lub_string_nocasestr(const char *cs, const char *ct)
+{
+	const char *p = NULL;
+	const char *result = NULL;
+
+	while (*cs) {
+		const char *q = cs;
+
+		p = ct;
+		/*lint -e155 Ignoring { }'ed sequence within an expression, 0 assumed 
+		 * MACRO implementation uses braces to prevent multiple increments
+		 * when called.
+		 */
+		/*lint -e506 Constant value Boolean
+		 * not the case because of tolower() evaluating to 0 under lint
+		 * (see above)
+		 */
+		while (*p && *q
+		       && (lub_ctype_tolower(*p) == lub_ctype_tolower(*q))) {
+			p++, q++;
+		}
+		if (0 == *p) {
+			break;
+		}
+		cs++;
+	}
+	if (p && !*p) {
+		/* we've found the first match of ct within cs */
+		result = cs;
+	}
+	return result;
+}
+
+/*--------------------------------------------------------- */
+unsigned int lub_string_equal_part(const char *str1, const char *str2,
+	bool_t utf8)
+{
+	unsigned int cnt = 0;
+
+	if (!str1 || !str2)
+		return cnt;
+	while (*str1 && *str2) {
+		if (*str1 != *str2)
+			break;
+		cnt++;
+		str1++;
+		str2++;
+	}
+	if (!utf8)
+		return cnt;
+
+	/* UTF8 features */
+	if (cnt && (UTF8_11 == (*(str1 - 1) & UTF8_MASK)))
+		cnt--;
+
+	return cnt;
+}
+
+/*--------------------------------------------------------- */

+ 22 - 0
lub/string/string_suffix.c

@@ -0,0 +1,22 @@
+/*
+ * string_suffix.c
+ */
+#include "private.h"
+
+#include "lub/ctype.h"
+/*--------------------------------------------------------- */
+const char *lub_string_suffix(const char *string)
+{
+	const char *p1, *p2;
+	p1 = p2 = string;
+	while (*p1) {
+		if (lub_ctype_isspace(*p1)) {
+			p2 = p1;
+			p2++;
+		}
+		p1++;
+	}
+	return p2;
+}
+
+/*--------------------------------------------------------- */

+ 81 - 0
lub/string/string_word.c

@@ -0,0 +1,81 @@
+/*
+ * /lub/string/string_word.c
+ */
+#include <stddef.h>
+#include <ctype.h>
+
+#include "private.h"
+#include "lub/types.h"
+
+/*--------------------------------------------------------- */
+const char *lub_string_nextword(const char *string,
+	size_t *len, size_t *offset, size_t *quoted)
+{
+	const char *word;
+
+	*quoted = 0;
+
+	/* find the start of a word (not including an opening quote) */
+	while (*string && isspace(*string)) {
+		string++;
+		(*offset)++;
+	}
+	if (*string == '\\') {
+		string++;
+		if (*string)
+			string++;
+	}
+	/* is this the start of a quoted string ? */
+	if (*string == '"') {
+		*quoted = 1;
+		string++;
+	}
+	word = string;
+	*len = 0;
+
+	/* find the end of the word */
+	while (*string) {
+		if (*string == '\\') {
+			string++;
+			(*len)++;
+			if (*string) {
+				(*len)++;
+				string++;
+			}
+			continue;
+		}
+		/* end of word */
+		if (!*quoted && isspace(*string))
+			break;
+		if (*string == '"') {
+			/* end of a quoted string */
+			*quoted = 2;
+			break;
+		}
+		(*len)++;
+		string++;
+	}
+
+	return word;
+}
+
+/*--------------------------------------------------------- */
+unsigned int lub_string_wordcount(const char *line)
+{
+	const char *word;
+	unsigned int result = 0;
+	size_t len = 0, offset = 0;
+	size_t quoted;
+
+	for (word = lub_string_nextword(line, &len, &offset, &quoted);
+		*word || quoted;
+		word = lub_string_nextword(word + len, &len, &offset, &quoted)) {
+		/* account for the terminating quotation mark */
+		len += quoted ? quoted - 1 : 0;
+		result++;
+	}
+
+	return result;
+}
+
+/*--------------------------------------------------------- */

+ 24 - 0
lub/types.h

@@ -0,0 +1,24 @@
+/*
+ * types.h
+ */
+/**
+\ingroup  lub
+\defgroup lub_types types
+
+\brief This provides some primative types not found in ANSI-C.
+@{
+*/
+
+#ifndef _lub_types_h
+#define _lub_types_h
+
+/**
+ * A boolean type for ANSI-C
+ */
+typedef enum {
+	BOOL_FALSE,
+	BOOL_TRUE
+} bool_t;
+
+/** @} */
+#endif				/* _lub_types_h */