/* elmo - ELectronic Mail Operator Copyright (C) 2003 rzyjontko 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; version 2. 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. ---------------------------------------------------------------------- this module defines operations on current configuration */ /**************************************************************************** * IMPLEMENTATION HEADERS ****************************************************************************/ #include #include #include #include "confhold.h" #include "confread.h" #include "hash.h" #include "rstring.h" #include "memblock.h" #include "xmalloc.h" #include "file.h" /**************************************************************************** * IMPLEMENTATION PRIVATE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS ****************************************************************************/ #define CONF_SIZE 3 /**************************************************************************** * IMPLEMENTATION PRIVATE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE STRUCTURES / UTILITY CLASSES ****************************************************************************/ /** * this is how I store information about available options * example: * name - pop_acc * fields - server, username, password, port * fields == NULL iff variable is simple (no fields) */ typedef struct citem { char *name; rstring_t *fields; } citem_t; /** * this is how I store values for options * the hashing table stores a list of values associated with an option * * m_value is not a usual rstring. It may have some NULLs inside. */ typedef struct vitem { char *s_value; rstring_t *m_value; struct vitem *next; } vitem_t; typedef struct conf { int unused; citem_t *citem; vitem_t *vitem; vitem_t *selected; } conf_t; /**************************************************************************** * IMPLEMENTATION REQUIRED EXTERNAL REFERENCES (AVOID) ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE DATA ****************************************************************************/ static conf_t conf_table[CONF_SIZE]; static htable_t *variable_table = NULL; static htable_t *values_table = NULL; static memblock_t *fields_block = NULL; static memblock_t *values_block = NULL; static citem_t *prepare_citem = NULL; static vitem_t *prepare_vitem = NULL; /**************************************************************************** * INTERFACE DATA ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTION PROTOTYPES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTIONS ****************************************************************************/ static int field_index (citem_t *item, const char *field) { int i; for (i = 0; i < item->fields->count; i++){ if (strcmp (field, item->fields->array[i]) == 0) break; } return i; } static void destroy_val (void *ptr) { vitem_t *item = (vitem_t *) ptr; for (item = (vitem_t *) ptr; item; item = item->next) if (item->m_value) rstring_delete (item->m_value); } static void destroy_def (void *ptr) { citem_t *item = (citem_t *) ptr; if (item->fields) rstring_delete (item->fields); } /**************************************************************************** * INTERFACE FUNCTIONS ****************************************************************************/ void confhold_init (void) { int i; if (variable_table){ htable_destroy (variable_table, NULL); } if (values_table){ htable_destroy (values_table, NULL); } if (fields_block){ memblock_destroy (fields_block); } if (values_block){ memblock_destroy (values_block); } variable_table = htable_create (5); values_table = htable_create (6); fields_block = memblock_create (100); values_block = memblock_create (200); for (i = 0; i < CONF_SIZE; i++){ conf_table[i].unused = 1; } } void confhold_free_resources (void) { if (variable_table){ htable_destroy (variable_table, destroy_def); variable_table = NULL; } if (values_table){ htable_destroy (values_table, destroy_val); values_table = NULL; } if (fields_block){ memblock_destroy (fields_block); fields_block = NULL; } if (values_block){ memblock_destroy (values_block); values_block = NULL; } } void confhold_register (const char *name, int fieldcount, ...) { citem_t *item; char *field; va_list ap; item = memblock_malloc (&fields_block, sizeof (citem_t)); item->name = memblock_strdup (&fields_block, name); if (fieldcount){ item->fields = rstring_create_size (fieldcount + 1); } else { item->fields = NULL; } va_start (ap, fieldcount); while (fieldcount--){ field = memblock_strdup (&fields_block, va_arg (ap, char *)); rstring_add (item->fields, field); } va_end (ap); htable_insert (variable_table, name, item); } int confhold_open (const char *name) { int i; entry_t *c_entry; entry_t *v_entry; for (i = 0; i < CONF_SIZE; i++){ if (conf_table[i].unused) break; } if (i == CONF_SIZE) return -1; c_entry = htable_lookup (variable_table, name); if (c_entry == NULL || c_entry->content == NULL) return -1; v_entry = htable_lookup (values_table, name); if (v_entry == NULL || v_entry->content == NULL) return -1; conf_table[i].citem = (citem_t *) c_entry->content; conf_table[i].vitem = (vitem_t *) v_entry->content; conf_table[i].unused = 0; return i; } void confhold_close (int cd) { conf_table[cd].unused = 1; } rstring_t * confhold_get_fields (int cd, const char *field) { int index; vitem_t *vitem; rstring_t *result; if (conf_table[cd].unused) return NULL; index = field_index (conf_table[cd].citem, field); result = rstring_create_size (2); for (vitem = conf_table[cd].vitem; vitem; vitem = vitem->next){ if (vitem->m_value && vitem->m_value->array[index]) rstring_add (result, vitem->m_value->array[index]); } return result; } void confhold_select (int cd, int index) { if (conf_table[cd].unused) return; for (conf_table[cd].selected = conf_table[cd].vitem; index && conf_table[cd].selected; index--){ conf_table[cd].selected = conf_table[cd].selected->next; } } void confhold_select_where (int cd, const char *field, const char *desired) { int index; vitem_t *old_selected; if (conf_table[cd].unused) return; old_selected = conf_table[cd].selected; index = field_index (conf_table[cd].citem, field); for (conf_table[cd].selected = conf_table[cd].vitem; conf_table[cd].selected; conf_table[cd].selected = conf_table[cd].selected->next){ if (! strcmp (conf_table[cd].selected->m_value->array[index], desired)) break; } if (conf_table[cd].selected == NULL) conf_table[cd].selected = old_selected; } char * confhold_field_from_selected (int cd, const char *field) { int index; if (conf_table[cd].unused) return NULL; if (conf_table[cd].vitem == NULL || conf_table[cd].citem == NULL) return NULL; if (conf_table[cd].selected == NULL) return NULL; index = field_index (conf_table[cd].citem, field); return conf_table[cd].selected->m_value->array[index]; } char * confhold_get_first (const char *name, const char *field) { int i; entry_t *d_entry = htable_lookup (variable_table, name); entry_t *v_entry; citem_t *def; vitem_t *val; if (d_entry == NULL && field) return NULL; v_entry = htable_lookup (values_table, name); if (v_entry == NULL) return NULL; def = (d_entry) ? (citem_t *) d_entry->content : NULL; val = (vitem_t *) v_entry->content; if (field == NULL) return val->s_value; if (def == NULL) return NULL; i = field_index (def, field); return val->m_value->array[i]; } rstring_t * confhold_get_all (const char *name) { entry_t *v_entry; vitem_t *vitem; rstring_t *result; v_entry = htable_lookup (values_table, name); if (v_entry == NULL || v_entry->content == NULL) return NULL; result = rstring_create_size (2); for (vitem = (vitem_t *) v_entry->content; vitem; vitem = vitem->next){ if (vitem->s_value) rstring_add (result, vitem->s_value); } return result; } int confhold_prepare_to_insert (const char *name) { entry_t *c_entry; entry_t *v_entry; c_entry = htable_lookup (variable_table, name); if (c_entry == NULL){ prepare_citem = NULL; return 1; } else prepare_citem = c_entry->content; v_entry = htable_insert (values_table, name, NULL); prepare_vitem = memblock_malloc (&values_block, sizeof (vitem_t)); prepare_vitem->next = (vitem_t *) v_entry->content; prepare_vitem->s_value = NULL; prepare_vitem->m_value = NULL; if (prepare_citem && prepare_citem->fields) prepare_vitem->m_value = rstring_create_size (prepare_citem->fields->count + 1); v_entry->content = prepare_vitem; return 0; } int confhold_insert_value (const char *field, const char *val) { int index; if (prepare_vitem == NULL) return 0; if (prepare_citem && prepare_citem->fields && field){ index = field_index (prepare_citem, field); if (index == prepare_citem->fields->count) return 1; prepare_vitem->m_value->array[index] = memblock_strdup (&values_block, val); } else if ((prepare_citem == NULL || prepare_citem->fields == NULL) && field == NULL){ prepare_vitem->s_value = memblock_strdup (&values_block, val); } return 0; } /**************************************************************************** * INTERFACE CLASS BODIES ****************************************************************************/ /**************************************************************************** * * END MODULE confhold.c * ****************************************************************************/