diff --git a/src/bag.c b/src/bag.c deleted file mode 100644 index c9d07a86..00000000 --- a/src/bag.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * $Id$ - * Simple collection as linked lists - * - * Copyright (C) 2006 Ron Pedde (rpedde@users.sourceforge.net) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include - -#include "bag.h" -#include "err.h" - -typedef struct _BAGITEM { - int type; - char *name; - union { - int as_int; - char *as_string; - struct _BAG *as_bag; - } value; - struct _BAGITEM *next; -} BAG_ITEM; - -struct _BAG { - unsigned int flags; - struct _BAGITEM *tailptr; - struct _BAGITEM itemlist; -}; - -/** Globals */ -pthread_mutex_t bag_mutex=PTHREAD_MUTEX_INITIALIZER; - -/** Internal functions */ -void _bag_lock(void); -void _bag_unlock(void); -int _bag_delete(BAG_HANDLE pb); -BAG_ITEM *_bag_fetch_item(BAG_HANDLE pb, char *key); -int _bag_add_item(BAG_HANDLE pb, void* vpval, int ival, int type); - -/** - * lock the mutex. This could be done on a bag-by-bag basis, - * and it could further be done as a reader-writer lock, but - * I don't think performance is going to be an issue, so I'll just - * use a global lock. - */ -void _bag_lock(void) { - int err; - - if((err=pthread_mutex_lock(&bag_mutex))) { - DPRINTF(E_FATAL,L_MISC,"Could not lock mutex: %s\n",strerror(err)); - } -} - -/** - * unlock the mutex - */ -void _bag_unlock(void) { - int err; - - if((err = pthread_mutex_unlock(&bag_mutex))) { - DPRINTF(E_FATAL,L_MISC,"Could not unlock mutex: %s\n",strerror(err)); - } -} - -/** - * create a bag - * - * @param pbp pointer to a BAG_HANDLE. Returns valid handle on BAG_E_SUCCESS - * @returns BAG_E_SUCCESS on success, error code otherwise - */ -int bag_create(BAG_HANDLE *ppb) { - *ppb = (BAG_HANDLE)malloc(sizeof(struct _BAG)); - if(!*ppb) - return BAG_E_MALLOC; - - memset(*ppb,0x0,sizeof(struct _BAG)); - return BAG_E_SUCCESS; -} - -/** - * destroy a bag, recusively, if neccesary - * - * @param pb bag to destroy - * @returns BAG_E_SUCCESS - */ -int bag_destroy(BAG_HANDLE pb) { - _bag_lock(); - _bag_delete(pb); - _bag_unlock(); - return BAG_E_SUCCESS; -} - -/** - * internal function to implement the actual delete. - * assumes that the semaphore is held - * - * @param pb bag to delete - * @returns BAG_E_SUCCESS - */ -int _bag_delete(BAG_HANDLE pb) { - BAG_ITEM *current,*last; - - last = &(pb->itemlist); - current = pb->itemlist.next; - - while(current) { - switch(current->type) { - case BAG_TYPE_BAG: - bag_delete(current->value.as_bag); - break; - case BAG_TYPE_STRING: - free(current->value.as_string); - break; - default: - break; - } - - last = current; - current = current->next; - free(last); - } - - free(pb); - - return BAG_E_SUCCESS; -} - -/** - * thin wrapper for _bag_add_item - */ -int bag_add_string(BAG_HANDLE pb, char *cval) { - return _bag_add_item(pb,cval,0,BAG_TYPE_STRING); -} - -/** - * thin wrapper for _bag_add_item - */ -int bag_add_int(BAG_HANDLE pb, int ival) { - return _bag_add_item(pb,NULL,ival,BAG_TYPE_INT); -} - -/** - * thin wrapper for _bag_add_item - */ -int bag_add_bag(BAG_HANDLE pb, BAG_HANDLE pnew) { - return _bag_add_item(pb,(void*)pnew,0,BAG_TYPE_BAG); -} - -/** - * add an item to a bag - */ -int _bag_add_item(BAG_HANDLE pb, void* vpval, int ival, int type) { - BAG_ITEM *pbi; - - pbi=(BAG_ITEM *)malloc(sizeof(BAG_ITEM)); - if(!pbi) { - return BAG_E_MALLOC; - } - - pbi->type = type; - switch(type) { - case BAG_TYPE_INT: - pbi->value.as_int = ival; - break; - case BAG_TYPE_BAG: - pbi->value.as_bag = (BAG_HANDLE)vpval; - break; - case BAG_TYPE_STRING: - pbi->value.as_string = strdup((char*)vpval); - break; - default: - break; - } - - _bag_lock(); - - if(pb->flags & BAG_FLAG_HEADINSERT) { - pbi->next = pb->itemlist.next; - pb->itemlist.next = pbi; - } else { - pbi->next = NULL; - pb->tailptr->next = pbi; - pb->tailptr = pbi; - } - - _bag_unlock(); - return BAG_E_SUCCESS; -} - -/** - * internal function to get the bag item associated with - * a specific key, using the case sensitivity specified - * by the bag flags. This assumes that the lock is held! - * - * @param pb bag to fetch item from - * @param key key name to fetch - * @returns pointer to bagitem, or null if not found - */ -BAG_ITEM *_bag_fetch_item(BAG_HANDLE pb, char *key) { - BAG_ITEM *current; - - current = pb->itemlist.next; - while(current) { - if(pb->flags & BAG_FLAG_HONORCASE) { - if(!strcasecmp(current->name,key)) - break; - if(!strcmp(current->name,key)) - break; - } - current = current->next; - } - - return current; -} - -/** - * set flags - * - * @param pb bag to set flags for - * @returns BAG_E_SUCCESS - */ -int bag_set_flags(BAG_HANDLE pb, unsigned int flags) { - pb->flags = flags; - return BAG_E_SUCCESS; -} - -/** - * get flags - * - * @param pb bag to get flags from - * @returns BAG_E_SUCCESS - */ -int bag_get_flags(BAG_HANDLE pb, unsigned int *flags) { - *flags = pb->flags; - return BAG_E_SUCCESS; -} - - -/** - * get the type for a particular key in a bag. - * - * @param pb bag to search in - * @param key key to search for - * @param type return value for type of bag (BAG_TYPE_*) - * @returns BAG_E_SUCCESS or BAG_E_NOKEY on failure - */ -int bag_get_type(BAG_HANDLE pb, char *key, int *type) { - BAG_ITEM *pitem; - - _bag_lock(); - - pitem = _bag_fetch_item(pb, key); - if(!pitem) { - _bag_unlock(); - return BAG_E_NOKEY; - } - - *type = pitem->type; - _bag_unlock; - - return BAG_E_SUCCESS; -} - diff --git a/src/bag.h b/src/bag.h deleted file mode 100644 index 829d9307..00000000 --- a/src/bag.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * $Id$ - * Simple collection as linked lists - * - * Copyright (C) 2006 Ron Pedde (rpedde@users.sourceforge.net) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _BAG_H_ -#define _BAG_H_ - -#define BAG_TYPE_INT 0 -#define BAG_TYPE_STRING 1 -#define BAG_TYPE_BAG 2 - - -#define BAG_E_SUCCESS 0 -#define BAG_E_MALLOC 1 -#define BAG_E_NOKEY 2 - -#define BAG_FLAG_HONORCASE 1 /** Make keys case sensitive */ -#define BAG_FLAG_HEADINSERT 2 /** Insert at head, rather than tail */ - - -typedef struct _BAG *BAG_HANDLE; - -extern int bag_create(BAG_HANDLE *ppb); -extern int bag_destroy(BAG_HANDLE pb); - -extern int bag_add_string(BAG_HANDLE pb, char *cval); -extern int bag_add_int(BAG_HANDLE pb, int ival); -extern int bag_add_bag(BAG_HANDLE pb, BAG_HANDLE pnew); - -extern int bag_set_flags(BAG_HANDLE pb, unsigned int flags); -extern int bag_get_flags(BAG_HANDLE pb, unsigned int *flags); - -extern int bag_get_type(BAG_HANDLE pb, char *key, int *type); - -#endif /* _BAG_H_ */ - diff --git a/src/config-driver.c b/src/config-driver.c new file mode 100644 index 00000000..95e1ba87 --- /dev/null +++ b/src/config-driver.c @@ -0,0 +1,16 @@ +/* + * $Id$ + */ + +#include + +#include "config.h" + +int main(int argc, char *argv[]) { + if(config_read(argv[1]) != CONFIG_E_SUCCESS) { + printf("Read config!\n"); + } else { + printf("Error reading config\n"); + } + config_close(); +} diff --git a/src/config.c b/src/config.c index 48a24a62..845ae3e1 100644 --- a/src/config.c +++ b/src/config.c @@ -32,13 +32,15 @@ #include - -#include "bag.h" -#include "daap.h" +#include "err.h" +#include "ll.h" +#include "daapd.h" /** Globals */ int ecode; -BAG_HANDLE config_main; +LL_HANDLE config_main=NULL; + +#define CONFIG_LINEBUFFER 128 /** * read a configfile into a bag @@ -49,25 +51,94 @@ BAG_HANDLE config_main; int config_read(char *file) { FILE *fin; int err; + LL_HANDLE pllnew, plltemp; + char linebuffer[CONFIG_LINEBUFFER+1]; + char *comment, *term, *value, *delim; + int compat_mode=1; fin=fopen(file,"r"); if(!fin) { - ecode = errno; return CONFIG_E_FOPEN; } - if((err=bag_create(&config_main)) != BAG_E_SUCCESS) { - DPRINTF(E_LOG,L_CONF,"Error creating bag: %d\n",err); + if((err=ll_create(&pllnew)) != LL_E_SUCCESS) { + DPRINTF(E_LOG,L_CONF,"Error creating linked list: %d\n",err); + fclose(fin); return CONFIG_E_UNKNOWN; } + /* got what will be the root of the config tree, now start walking through + * the input file, populating the tree + */ + while(fgets(linebuffer,CONFIG_LINEBUFFER,fin)) { + linebuffer[CONFIG_LINEBUFFER] = '\0'; + comment=strchr(linebuffer,'#'); + if(comment) { + /* we should really preserve these in another tree*/ + *comment = '\0'; + } + + while(strlen(linebuffer) && (strchr("\n\r ",linebuffer[strlen(linebuffer)-1]))) + linebuffer[strlen(linebuffer)-1] = '\0'; + + if(linebuffer[0] == '[') { + /* section header */ + compat_mode=0; + term=&linebuffer[1]; + value = strchr(term,']'); + if(!value) { + ll_destroy(pllnew); + fclose(fin); + return CONFIG_E_BADHEADER; + } + *value = '\0'; + + if((err = ll_create(&plltemp)) != LL_E_SUCCESS) { + ll_destroy(pllnew); + fclose(fin); + return CONFIG_E_UNKNOWN; + } + + ll_add_ll(pllnew,term,plltemp); + } else { + /* k/v pair */ + term=&linebuffer[0]; + + while((*term=='\t') || (*term==' ')) + term++; + + value=term; + + if(compat_mode) { + delim="\t "; + } else { + delim="="; + } + + strsep(&value,delim); + if((value) && (term) && (strlen(term))) { + while(strlen(value) && (strchr("\t ",*value))) + value++; + + ll_add_string(pllnew,term,value); + } + } + } fclose(fin); + + /* Sanity check */ + ll_dump(pllnew); + ll_destroy(pllnew); + return CONFIG_E_SUCCESS; } int config_close(void) { + if(config_main) + ll_destroy(config_main); + return CONFIG_E_SUCCESS; } diff --git a/src/config.h b/src/config.h index a154f105..455f8a57 100644 --- a/src/config.h +++ b/src/config.h @@ -25,9 +25,10 @@ #define CONFIG_E_SUCCESS 0 #define CONFIG_E_FOPEN 1 #define CONFIG_E_UNKNOWN 2 +#define CONFIG_E_BADHEADER 3 + extern int config_read(char *file); -extern int config_write(WS_CONNINFO *pwsc); extern int config_close(void); #endif /* _CONFIG_H_ */ diff --git a/src/config.mk b/src/config.mk new file mode 100644 index 00000000..b8b48699 --- /dev/null +++ b/src/config.mk @@ -0,0 +1,12 @@ +# $Id$ +CC=gcc +CFLAGS := $(CFLAGS) -g -DHAVE_CONFIG_H -I. -I.. +LDFLAGS := $(LDFLAGS) +TARGET = config +OBJECTS=config-driver.o config.o ll.o + +$(TARGET): $(OBJECTS) + $(CC) -o $(TARGET) $(LDFLAGS) $(OBJECTS) + +clean: + rm -f $(OBJECTS) $(TARGET) diff --git a/src/daapd.h b/src/daapd.h index 90f54696..738cad85 100644 --- a/src/daapd.h +++ b/src/daapd.h @@ -31,6 +31,7 @@ #ifndef _DAAPD_H_ #define _DAAPD_H_ +#include #include "webserver.h" /** Simple struct for holding stat info. diff --git a/src/ll.c b/src/ll.c new file mode 100644 index 00000000..945e6cd3 --- /dev/null +++ b/src/ll.c @@ -0,0 +1,204 @@ +/* + * $Id$ + * Rock stupid char* indexed linked lists + * + * Copyright (C) 2006 Ron Pedde (rpedde@users.sourceforge.net) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "ll.h" +#include "err.h" + + +/** Internal functions */ + +int _ll_add_item(LL *pl, char *key, void *vpval, int ival, int type); + +/** + * create a ll + * + * @param ppl pointer to a LL *. Returns valid handle on LL_E_SUCCESS + * @returns LL_E_SUCCESS on success, error code otherwise + */ +int ll_create(LL **ppl) { + *ppl = (LL *)malloc(sizeof(struct _LL)); + if(!*ppl) + return LL_E_MALLOC; + + memset(*ppl,0x0,sizeof(struct _LL)); + return LL_E_SUCCESS; +} + +/** + * destroy a ll, recusively, if neccesary + * + * @param pl ll to destroy + * @returns LL_E_SUCCESS + */ +int ll_destroy(LL *pl) { + LL_ITEM *current,*last; + + last = &(pl->itemlist); + current = pl->itemlist.next; + + while(current) { + switch(current->type) { + case LL_TYPE_LL: + ll_destroy(current->value.as_ll); + break; + case LL_TYPE_STRING: + free(current->value.as_string); + break; + default: + break; + } + free(current->key); + last = current; + current = current->next; + free(last); + } + + free(pl); + + return LL_E_SUCCESS; +} + +/** + * thin wrapper for _ll_add_item + */ +int ll_add_string(LL *pl, char *key, char *cval) { + return _ll_add_item(pl,cval,key,0,LL_TYPE_STRING); +} + +/** + * thin wrapper for _ll_add_item + */ +int ll_add_int(LL *pl, char *key, int ival) { + return _ll_add_item(pl,key,NULL,ival,LL_TYPE_INT); +} + +/** + * thin wrapper for _ll_add_item + */ +int ll_add_ll(LL *pl, char *key, LL *pnew) { + return _ll_add_item(pl,key,(void*)pnew,0,LL_TYPE_LL); +} + +/** + * add an item to a ll + */ +int _ll_add_item(LL *pl, char *key, void* vpval, int ival, int type) { + LL_ITEM *pli; + + pli=(LL_ITEM *)malloc(sizeof(LL_ITEM)); + if(!pli) { + return LL_E_MALLOC; + } + + pli->type = type; + pli->key = strdup(key); + + switch(type) { + case LL_TYPE_INT: + pli->value.as_int = ival; + break; + case LL_TYPE_LL: + pli->value.as_ll = (LL *)vpval; + break; + case LL_TYPE_STRING: + pli->value.as_string = strdup((char*)vpval); + break; + default: + break; + } + + if(pl->flags & LL_FLAG_HEADINSERT) { + pli->next = pl->itemlist.next; + pl->itemlist.next = pli; + } else { + pli->next = NULL; + pl->tailptr->next = pli; + pl->tailptr = pli; + } + + return LL_E_SUCCESS; +} + +/** + * internal function to get the ll item associated with + * a specific key, using the case sensitivity specified + * by the ll flags. This assumes that the lock is held! + * + * @param pl ll to fetch item from + * @param key key name to fetch + * @returns pointer to llitem, or null if not found + */ +LL_ITEM *ll_fetch_item(LL *pl, char *key) { + LL_ITEM *current; + + current = pl->itemlist.next; + while(current) { + if(pl->flags & LL_FLAG_HONORCASE) { + if(!strcasecmp(current->key,key)) + break; + if(!strcmp(current->key,key)) + break; + } + current = current->next; + } + + return current; +} + +/** + * set flags + * + * @param pl ll to set flags for + * @returns LL_E_SUCCESS + */ +int ll_set_flags(LL *pl, unsigned int flags) { + pl->flags = flags; + return LL_E_SUCCESS; +} + +/** + * get flags + * + * @param pl ll to get flags from + * @returns LL_E_SUCCESS + */ +int ll_get_flags(LL *pl, unsigned int *flags) { + *flags = pl->flags; + return LL_E_SUCCESS; +} + +/** + * Dump a linked list + * + * @parm pl linked list to dump + */ +extern void ll_dump(LL *pl) { + +} + diff --git a/src/ll.h b/src/ll.h new file mode 100644 index 00000000..319303cb --- /dev/null +++ b/src/ll.h @@ -0,0 +1,72 @@ +/* + * $Id$ + * Rock stupid char* indexed linked lists + * + * Copyright (C) 2006 Ron Pedde (rpedde@users.sourceforge.net) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _LL_H_ +#define _LL_H_ + +#define LL_TYPE_INT 0 +#define LL_TYPE_STRING 1 +#define LL_TYPE_LL 2 + + +#define LL_E_SUCCESS 0 +#define LL_E_MALLOC 1 +#define LL_E_NOKEY 2 + +#define LL_FLAG_HONORCASE 1 /** Make keys case sensitive */ +#define LL_FLAG_HEADINSERT 2 /** Insert at head, rather than tail */ + + +typedef struct _LLITEM { + int type; + char *key; + union { + int as_int; + char *as_string; + struct _LL *as_ll; + } value; + struct _LLITEM *next; +} LL_ITEM, *LL_ITEMHANDLE; + +typedef struct _LL { + unsigned int flags; + struct _LLITEM *tailptr; + struct _LLITEM itemlist; +} LL, *LL_HANDLE; + + + +extern int ll_create(LL **ppl); +extern int ll_destroy(LL *pl); + +extern int ll_add_string(LL *pl, char *key, char *cval); +extern int ll_add_int(LL *pl, char *key, int ival); +extern int ll_add_ll(LL *pl, char *key, LL *pnew); + +extern int ll_set_flags(LL *pl, unsigned int flags); +extern int ll_get_flags(LL *pl, unsigned int *flags); + +extern LL_ITEM *ll_fetch_item(LL *pl, char *key); + +extern void ll_dump(LL *pl); + +#endif /* _LL_H_ */ +