Changeset 783


Ignore:
Timestamp:
10/14/06 09:09:59 (6 years ago)
Author:
wd
Message:

Big commit:

  • Cleanup in main(), remove duped functions
  • Killed off msymbol support (bug #3) from hash tables
  • Added missing sconscript file for echo module
  • Tweak str_conv_bool to also handle true/false. :)
Location:
branches/ithildin-scons
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • branches/ithildin-scons/include/ithildin/hash.h

    r759 r783  
    1212 
    1313typedef struct hashtable hashtable_t; 
     14typedef int *(*hashcmp_function_t)(void *, void *, size_t); 
    1415 
    1516SLIST_HEAD(hashbucket, hashent); 
     
    5152     * int (*)(void *, void *, size_t).  If the value is NULL then the memcmp 
    5253     * function is used instead (with a little kludge-work ;) */ 
    53     struct msymbol *cmpsym; 
     54    hashcmp_function_t cmpfunc; 
    5455}; 
    5556 
    5657/* table management functions */ 
    57 hashtable_t *create_hash_table(uint32_t, size_t, size_t, int, const char *); 
     58hashtable_t *create_hash_table(uint32_t, size_t, size_t, int, 
     59        hashcmp_function_t); 
    5860void destroy_hash_table(hashtable_t *); 
    5961int hash_insert(hashtable_t *, void *); 
  • branches/ithildin-scons/include/ithildin/module.h

    r655 r783  
    2929SLIST_HEAD(module_savedata_list, module_savedata); 
    3030struct module_savedata { 
    31     char    *name;            /* the symbol name */ 
    32     size_t  size;            /* the size of the data */ 
    33     char    *data;            /* and the actual data */ 
     31    char    *name;                      /* the symbol name */ 
     32    size_t  size;                       /* the size of the data */ 
     33    char    *data;                      /* and the actual data */ 
    3434 
    3535    SLIST_ENTRY(module_savedata) lp; 
     
    4747    struct module_header *header; 
    4848 
    49     char    *fullpath;            /* full path to file's module */ 
    50     char    *depfile;            /* full path to the file's dependency file, or NULL 
    51                                if no file exists. */ 
    52     char    *name;            /* name of module */ 
    53     void    *handle;            /* dlopen() handle */ 
     49    char    *fullpath;                  /* full path to file's module */ 
     50    char    *name;                      /* name of module */ 
     51    void    *handle;                    /* dlopen() handle */ 
     52 
     53    char    *conffile;                  /* full path to the module's 
     54                                           configuration file, or NULL if it 
     55                                           does not exist */ 
    5456    conf_list_t *confdata; 
     57    event_t *conf_reload;               /* called when module configuration 
     58                                           is reloaded */ 
     59 
     60 
    5561    module_load_function load_function; 
    5662    module_unload_function unload_function; 
     
    115121        struct module_savedata_list *savelist __UNUSED) 
    116122 
    117 /* this macro should be used in the module loader function to export necessary 
    118  * symbols */ 
    119 #define EXPORT_SYM(sym) export_symbol(#sym, module) 
    120  
    121123/* and these two are wrappers on the 'savedata' functions below that take a 
    122124 * symbol and do all the necessary legwork to add/restore it */ 
     
    143145        void *); 
    144146 
    145 /* msymbol definitions */ 
    146 typedef struct msymbol msymbol_t; 
    147 struct msymbol { 
    148     char    name[32];        /* 31 characters worth of significant name info.  if 
    149                            this isn't enough it can be changed later.. */ 
    150     void    *val;        /* the value of the symbol */ 
    151     module_t *module;        /* the module which owns this symbol */ 
    152  
    153     LIST_ENTRY(msymbol) lp; 
    154 }; 
    155  
    156 msymbol_t *export_symbol(char *, module_t *); 
    157 msymbol_t *import_symbol(char *); 
    158 #ifdef DEBUG 
    159 # define getsym(sym)                                                          \ 
    160 ((sym->module != NULL && sym->module->handle == NULL) ?                       \ 
    161  (log_error("referenced unavailable symbol %s from module %s", sym->name,     \ 
    162             sym->module->name)), (void *)NULL : sym->val) 
    163 #else 
    164 # define getsym(sym) (sym->val) 
    165 #endif 
    166  
    167147/* mdext stuff */ 
    168148typedef char **(*mdext_iter_function)(char **); 
     
    186166     * convenience a void ** referring to the last item it worked on.  This 
    187167     * will be NULL at first. */ 
    188     msymbol_t *iter; 
     168    mdext_iter_function iter; 
    189169}; 
    190170 
    191171/* mdext management functions */ 
    192 struct mdext_header *create_mdext_header(const  char *); 
     172struct mdext_header *create_mdext_header(mdext_iter_function); 
    193173void destroy_mdext_header(struct mdext_header *); 
    194174struct mdext_item *create_mdext_item(struct mdext_header *, size_t); 
  • branches/ithildin-scons/lib/hash.c

    r761 r783  
    1616static void resize_hash_table(hashtable_t *table, uint32_t elems); 
    1717static unsigned int hash_get_key_hash(hashtable_t *, void *, size_t); 
     18 
     19/* Set a minimum size for hastables.  Tables smaller than this are not 
     20 * likely to be worth the overhead required to maintain them, in terms of 
     21 * saved CPU cycles vs. the size of the table.  If you're seeing messages 
     22 * about hashtable size adjustment because you're asking for a table that's 
     23 * too small.. this is why. :) */ 
     24#define MINIMUM_HASHTABLE_SIZE 64 /* must be a power of two! */ 
    1825 
    1926/* 
     
    3441 */ 
    3542hashtable_t *create_hash_table(uint32_t elems, size_t offset, size_t len, 
    36         int flags, const char *cmpname) { 
     43        int flags, hashcmp_function_t cmpfunc) { 
    3744    hashtable_t *htp = malloc(sizeof(hashtable_t)); 
    38     uint32_t real_elems = 0x80; 
     45    uint32_t real_elems = MINIMUM_HASHTABLE_SIZE; 
    3946     
    4047    /* Take elems and begin shifting real_elems to the left until it is 
     
    6774#endif 
    6875    htp->flags = flags; 
    69     if (cmpname != NULL) 
    70             htp->cmpsym = import_symbol((char *) cmpname); 
    71     else 
    72         htp->cmpsym = import_symbol("memcmp"); 
     76    if (cmpfunc != NULL) 
     77        htp->cmpfunc = cmpfunc; 
     78    else { 
     79        if (htp->flags & HASH_FL_STRING) { 
     80            if (htp->flags & HASH_FL_NOCASE) 
     81                htp->cmpfunc = (hashcmp_function_t)strncasecmp; 
     82            else 
     83                htp->cmpfunc = (hashcmp_function_t)strncmp; 
     84        } else 
     85            htp->cmpfunc = (hashcmp_function_t)memcmp; 
     86    } 
    7387 
    7488    htp->table = malloc(sizeof(struct hashbucket) * htp->size); 
     
    374388    struct hashbucket *bucket = &table->table[hash]; 
    375389    struct hashent *hep; 
    376     int (*cmpfunc)(void *, void *, size_t) = 
    377         (int (*)(void *, void *, size_t))getsym(table->cmpsym); 
    378390 
    379391    SLIST_FOREACH(hep, bucket, lp) { 
    380         if (hep->hv == hash && !cmpfunc(&((char *)hep->ent)[table->keyoffset], 
    381                     key, table->keylen)) 
     392        if (hep->hv == hash && 
     393                !table->cmpfunc(&((char *)hep->ent)[table->keyoffset], key, 
     394                    table->keylen)) 
    382395            return hep->ent; 
    383396    } 
     
    397410    struct hashbucket *bucket = &table->table[hash]; 
    398411    struct hashent *hep; 
    399     int (*cmpfunc)(void *, void *, size_t) = 
    400         (int (*)(void *, void *, size_t))getsym(table->cmpsym); 
    401412 
    402413    SLIST_FOREACH(hep, bucket, lp) { 
    403         if (hep->hv == hash && !cmpfunc(&((char *)hep->ent)[table->keyoffset], 
    404                     key, table->keylen)) 
     414        if (hep->hv == hash && 
     415                !table->cmpfunc(&((char *)hep->ent)[table->keyoffset], key, 
     416                    table->keylen)) 
    405417            return hep; 
    406418    } 
     
    413425        struct hashent *ent) { 
    414426    struct hashent *hep = ent; 
    415     int (*cmpfunc)(void *, void *, size_t) = 
    416         (int (*)(void *, void *, size_t))getsym(table->cmpsym); 
    417427 
    418428    /* we know where we are .. */ 
    419429    while ((hep = SLIST_NEXT(hep, lp)) != NULL) { 
    420         if (!cmpfunc(&((char *)hep->ent)[table->keyoffset], key, 
     430        if (!table->cmpfunc(&((char *)hep->ent)[table->keyoffset], key, 
    421431                    table->keylen)) 
    422432            return hep; 
  • branches/ithildin-scons/lib/module.c

    r761 r783  
    1818#endif 
    1919 
     20/* filename extension for modules, will become variable when multiple 
     21 * platforms become supported. */ 
     22#define MODULE_EXTENSION ".so" 
     23 
    2024/* create a module structure. */ 
    21 static module_t *create_module(char *name); 
     25static module_t *add_module_from_config(conf_entry_t *); 
     26static module_t *create_module(char *); 
    2227static void destroy_module(module_t *); 
    23  
    24 static LIST_HEAD(, msymbol) msym_list; 
    25 static msymbol_t *find_msymbol(char *); 
    2628 
    2729/* this is called both at start-up and at any time when the conf is reloaded 
     
    2931void build_module_list(void) { 
    3032    conf_list_t *list = conf_find_list("modules", me.confhead, 1); 
    31     conf_list_t *clp = NULL; 
    3233    conf_entry_t *cep = NULL, *oldcep; 
    3334    module_t *m = NULL; 
    34     module_t *last = NULL; /* track our last addition */ 
    35     char *s = NULL; 
     35    module_t *last = NULL; 
    3636 
    3737    if (list == NULL) { 
     
    4747    /* now pull in each load statement and parse it */ 
    4848    while (cep != NULL) { 
    49         do { /* use a do/while loop so we can 'break' from it without making 
    50                 life miserable or using silly gotos */ 
    51             int new = 0; 
    52             if (cep->type == CONF_TYPE_LIST) { 
    53                 /* check the 'string' value first, before checking the file 
    54                  * value. */ 
    55                 clp = cep->list; 
    56                 if (cep->string != NULL) 
    57                     s = cep->string; 
    58                 else { 
    59                     s = conf_find_entry("file", clp, 1); 
    60                     if (s == NULL) 
    61                         break; 
    62                 } 
    63             } else 
    64                 s = cep->string; 
    65  
    66             m = find_module(s); 
    67             if (m == NULL) { 
    68                 m = create_module(s); 
    69                 new++; 
    70             } 
    71             if (m == NULL) 
    72                 break; 
    73  
    74             if (cep->type == CONF_TYPE_LIST) { 
    75                 m->confdata = conf_find_list("data", clp, 1); 
    76                 if ((s = conf_find_entry("load", clp, 1)) != NULL && 
    77                         str_conv_bool(s, false)) 
    78                     m->flags |= MODULE_FL_AUTOLOAD; 
    79                 else 
    80                     m->flags |= MODULE_FL_AUTOLOAD; /* default is to load. */ 
    81                 if (str_conv_bool(conf_find_entry("export", clp, 1), 0)) 
    82                     m->flags |= MODULE_FL_DEPENDLOAD; 
    83                 if (cep->string != NULL) { 
    84                     free(m->name); 
    85                     m->name = strdup(cep->string); 
    86                 } 
    87             } else { 
    88                 /* We just got "module foo;"  I bet they want to autoload 
    89                  * it, so let's try that. */ 
    90                 m->confdata = NULL; 
    91                 m->flags |= MODULE_FL_AUTOLOAD; 
    92             } 
    93  
    94             if (new) { 
    95                 if (last == NULL) 
    96                     LIST_INSERT_HEAD(&me.modules, m, lp); 
    97                 else 
    98                     LIST_INSERT_AFTER(last, m, lp); 
    99  
    100                 last = m; 
    101             } 
    102         } while (0); /* just a once-through, heh */ 
     49        m = add_module_from_config(cep); 
    10350        oldcep = cep = conf_find_next("module", NULL, 0, oldcep, list, 1); 
     51 
     52        if (m == NULL) 
     53            continue; /* no need to add it to the list.. */ 
     54        if (last == NULL) 
     55            LIST_INSERT_HEAD(&me.modules, m, lp); 
     56        else 
     57            LIST_INSERT_AFTER(last, m, lp); 
     58        last = m; 
    10459    } 
    10560 
     
    11469} 
    11570 
     71static module_t *add_module_from_config(conf_entry_t *cep) { 
     72    conf_list_t *clp = NULL; 
     73    module_t *m; 
     74    bool new = false; 
     75    char *s = NULL; 
     76 
     77    if (cep->type == CONF_TYPE_LIST) { 
     78        /* check the 'string' value first, before checking the file 
     79         * value. */ 
     80        clp = cep->list; 
     81        if (cep->string != NULL) 
     82            s = cep->string; 
     83        else { 
     84            s = conf_find_entry("file", clp, 1); 
     85            if (s == NULL) { 
     86                log_warn("module with no name configured"); 
     87                return NULL; 
     88            } 
     89        } 
     90    } else 
     91        s = cep->string; 
     92 
     93    m = find_module(s); 
     94    if (m == NULL) { 
     95        m = create_module(s); 
     96        new = true; 
     97    } 
     98    if (m == NULL) 
     99        return NULL; 
     100 
     101    if (clp != NULL) { 
     102        if ((s = conf_find_entry("config", clp, 1)) != NULL) { 
     103            /* try to access their config file as specified, if it does not 
     104             * come with a path prefix, we try prepending the conf 
     105             * directory, then with the full pathname make sure we can load 
     106             * the conf.  if we can't we won't load the module */ 
     107            m->conffile = malloc(PATH_MAX); 
     108            if (*s != 's') /* XXX: this will suck come windows support time */ 
     109                snprintf(m->conffile, PATH_MAX, "%s/%s", me.conf_path, s); 
     110            else 
     111                strlcpy(m->conffile, s, PATH_MAX); 
     112 
     113        } 
     114 
     115        if ((s = conf_find_entry("load", clp, 1)) != NULL && 
     116                str_conv_bool(s, false)) 
     117            m->flags |= MODULE_FL_AUTOLOAD; 
     118        else 
     119            m->flags |= MODULE_FL_AUTOLOAD; /* default is to load. */ 
     120         
     121        /* allow module name to be overwritten (not sure why we'd want this, 
     122         * but let's see if it helps.. */ 
     123        if (cep->string != NULL) { 
     124            free(m->name); 
     125            m->name = strdup(cep->string); 
     126        } 
     127    } else { 
     128        /* We just got "module foo;"  I bet they want to autoload 
     129         * it, so let's try that. */ 
     130        m->flags |= MODULE_FL_AUTOLOAD; 
     131 
     132        /* let's also take a stab at guessing their module config file name. 
     133         * We try two things: $confdir/modulename.conf and 
     134         * $confdir/modulename/modulename.conf.  If neither works we do not 
     135         * make any further efforts.  We determine the usability of these 
     136         * files through the access() call. */ 
     137        s = malloc(PATH_MAX); 
     138        snprintf(s, PATH_MAX, "%s/%s.conf", me.conf_path, m->name); 
     139        if (access(s, R_OK) == 0) 
     140            m->conffile = s; 
     141        else { 
     142            /* don't try the directory method if the module name already 
     143             * contains slashes (indicating it is subdirectory-ized already) */ 
     144            if (!strchr(s, '/')) { 
     145                snprintf(s, PATH_MAX, "%s/%s/%s.conf", me.conf_path, m->name, 
     146                        m->name); 
     147                if (access(s, R_OK) == 0) 
     148                    m->conffile = s; 
     149            } 
     150        } 
     151    } 
     152 
     153    if (m->conffile != NULL) { 
     154        if ((m->confdata = read_conf(m->conffile)) == NULL) { 
     155            log_error("could not parse config for module %s, not loading it.", 
     156                    m->name); 
     157            destroy_module(m); 
     158            return NULL; 
     159        } 
     160    } 
     161 
     162    if (new) 
     163        return m; 
     164 
     165    return NULL; 
     166} 
     167 
    116168/* this function unloads all modules rather indiscriminately.  it just starts 
    117169 * at the top of the load and starts dropping them. */ 
     
    125177} 
    126178 
    127 /* this function handles all the necessary work to load a module.  it first 
    128  * checks for a .deps file in the same place as the module, and if one exists, 
    129  * opens it and loads all dependencies listed therein.  then it opens the dll, 
    130  * checks version headers, and calls the module's loader function. */ 
     179/* this function handles all the necessary work to load a module.  it opens the 
     180 * dll, checks version headers, loads dependencies, then calls the module's 
     181 * loader function (in that order). */ 
    131182int load_module(char *name, int flags) { 
    132183    module_t *m = NULL; 
    133     /* initially, we don't resolve symbols, we will run another dlopen call 
    134      * when our dependancies are loaded with RTLD_NOW to ensure that things 
    135      * work as they should */ 
     184    /* never ask for explicit symbol resolution.  every library a module 
     185     * depends on should be *already linked against* the module in question. 
     186     * we do not provide symbol help (because it is not reliably 
     187     * cross-platform) */ 
    136188    int rtld_flags = RTLD_NOW; 
    137189    char fn[33]; /* used for making function names */ 
    138190    char *sn; /* short name */ 
    139     FILE *fp; 
    140191    struct module_savedata *msdp; 
    141192    struct module_dependency *mdep; 
    142     msymbol_t *msym; 
     193    char **deplist = NULL; 
    143194 
    144195    if ((m = find_module(name)) == NULL) { 
     
    165216        log_notice("loading module %s...", m->name); 
    166217 
    167     /* load dependcies.  before we do, attest to the open-ness of this module. 
    168      * this isn't, technically, true, since we haven't initialized it. 
    169      * however, that can't be helped in the case of circular dependencies. 
    170      * this is simply a tough area... since we don't even do the dlopen() 
    171      * before we do the load_modules call, if you've got a circular dependency 
    172      * that won't survive on a lazy load, you're up the creek.  sorry. */ 
    173     if (m->depfile != NULL && !(m->flags & MODULE_FL_LOADED)) { 
    174         char sname[PATH_MAX]; 
    175  
    176         m->flags |= MODULE_FL_LOADED; 
    177         fp = fopen(m->depfile, "r"); 
    178         if (fp != NULL) { 
    179             while ((sn = sfgets(sname, PATH_MAX, fp)) != NULL) { 
    180                 module_t *m2 = find_module(sn); 
    181  
    182                 /* okay, depending on what's going on here, we do different 
    183                  * things.  if the module is reloading and a dependency isn't 
    184                  * loaded yet, we just return quietly because we assume we'll 
    185                  * get called later (see down towards the bottom of this 
    186                  * function), otherwise if we can't load that dependency, 
    187                  * return an error. */ 
    188                 if ((m2 == NULL || !(m2->flags & MODULE_FL_DEPENDLOAD))) { 
    189                     if (m2 == NULL) 
    190                         log_debug("loading dependant module %s for %s", 
    191                                 sn, name); 
    192 #if 0 
    193                     if (m->flags & MODULE_FL_RELOADING) { 
    194                         /* aaaaactually.  we only return if the module already 
    195                          * exists and is *also* reloading, this way a reload 
    196                          * with a module that has new dependencies will still 
    197                          * work! :) */ 
    198                         if (m2 != NULL && m2->flags & MODULE_FL_RELOADING) { 
    199                             m->flags &= ~MODULE_FL_LOADED; 
    200                             fclose(fp); 
    201                             return 0; /* waiting.. */ 
    202                         } 
    203                     } 
    204 #endif 
    205                     if (!load_module(sn, flags | MODULE_FL_DEPENDLOAD | 
    206                             MODULE_FL_CREATE | MODULE_FL_QUIET)) { 
    207                         log_error( 
    208                                 "loading dependant failed, giving up for %s!", 
    209                                 sn); 
    210                         fclose(fp); 
    211                         return 0; 
    212                     } 
    213                 } 
    214  
    215                 /* loaded?  add our current module to this new module's 
    216                  * dependency listing. */ 
    217                 m2 = find_module(sn); 
    218                 mdep = malloc(sizeof(struct module_dependency)); 
    219                 mdep->mod = m; 
    220                 LIST_INSERT_HEAD(&m2->deps, mdep, lp); 
    221  
    222             } 
    223             fclose(fp); 
    224         } 
    225         m->flags &= ~MODULE_FL_LOADED; /* undo this trickery. */ 
    226     } 
    227  
    228     /* check dependencies here */ 
     218    /* if we are being depend loaded make sure the module is set that way, 
     219     * if we've already been depend-loaded once we don't bother to go 
     220     * through the rest of the motions below. */ 
    229221    if (flags & MODULE_FL_DEPENDLOAD) { 
    230222        if (m->flags & MODULE_FL_DEPENDLOAD && m->flags & MODULE_FL_LOADED) 
    231223            return 1; /* already depend loaded */ 
    232         //rtld_flags |= RTLD_GLOBAL; 
    233224        m->flags |= MODULE_FL_DEPENDLOAD; 
    234225    } 
     
    244235        return 1; 
    245236         
     237    /* *********************************************************************** 
     238     * from this point on we are assured that m->opencalls is 1, that is, 
     239     * that this is our first try at loading the module, so any failures can 
     240     * safely be used to destroy the module/dlclose it/etc. 
     241     * ***********************************************************************/ 
     242 
    246243    m->header = (struct module_header *)dlsym(m->handle, "mheader"); 
    247244    if (m->header == NULL) { 
     
    252249    } 
    253250 
     251    deplist = (char **)dlsym(m->handle, "mdepends"); 
     252 
    254253    sn = strrchr(m->name, '/'); 
    255254    if (sn == NULL) 
     
    260259    snprintf(fn, 32, "%s_loader", sn); 
    261260    m->load_function = (module_load_function)dlsym(m->handle, fn); 
    262     snprintf(fn, 32, "%s_unloader", sn); 
    263     m->unload_function = (module_unload_function)dlsym(m->handle, fn); 
    264261 
    265262    /* Refuse to load modules compiled to use a module API version either 
     
    274271                m->header->baseversion.revision, 
    275272                MODULE_API_VERSION, MODULE_API_REVISION); 
    276         dlclose(m->handle); 
    277         m->opencalls = 0; 
     273        unload_module(m->name); 
    278274        return 0; 
    279275    } else if (m->header->baseversion.revision < MODULE_API_REVISION) { 
     
    285281    } /* ugh, okay, it's an alright version :) */ 
    286282 
    287     /* go ahead and say it's loaded now, so that if it tries to load other 
    288      * modules it will be okay. */ 
     283    /* load dependcies.  before we do, attest to the open-ness of this module. 
     284     * this isn't, technically, true, since we haven't initialized it. 
     285     * however, that can't be helped in the case of circular dependencies. 
     286     * this is simply a tough area because they will try to load this module 
     287     * and.. well.. we'll be right back here! :/ */ 
    289288    m->flags |= MODULE_FL_LOADED | flags; 
     289 
     290    while (deplist != NULL && *deplist != NULL) { 
     291        module_t *m2 = find_module(*deplist); 
     292        if (m2 == NULL || !(m2->flags & MODULE_FL_DEPENDLOAD)) { 
     293            if (m2 == NULL) 
     294                log_notice("loading dependant module %s for %s", *deplist, name); 
     295            if (!load_module(*deplist, flags | MODULE_FL_DEPENDLOAD | 
     296                    MODULE_FL_CREATE | MODULE_FL_QUIET)) { 
     297                log_error("loading dependant failed, giving up for %s!", name); 
     298                unload_module(m->name); 
     299                return 0; 
     300            } 
     301            m2 = find_module(*deplist); 
     302        } 
     303        /* m2 now definitely exists (yay) */ 
     304        mdep = malloc(sizeof(struct module_dependency)); 
     305        mdep->mod = m; 
     306        LIST_INSERT_HEAD(&m2->deps, mdep, lp); 
     307        deplist++; /* and onto the next one */ 
     308    } 
     309 
    290310 
    291311    /* okay, hopefully this will stay here.  I've decided to hook the 
    292312     * 'load_module' event prior to load function being called so that other 
    293313     * subsystems can do any data setup necessary that the load function might 
    294      * wish to rely on.  hope this works. ;) */ 
     314     * wish to rely on.  hope this works. ;)   this kind of sucks because it 
     315     * might be totally false if the loader errors out.  I'm not sure how to 
     316     * resolve this one, maybe we should hook the unload event right after? 
     317     * Hrmm... */ 
    295318    hook_event(me.events.load_module, m->name); 
    296319 
     
    298321        if (!m->load_function((m->flags & MODULE_FL_RELOADING ? 1 : 0), 
    299322                    &m->savedata, &m->confdata, m)) { 
    300             /* okay, it broke...clean up and go home */ 
    301             dlclose(m->handle); 
    302             m->opencalls = 0; 
    303             m->flags &= ~MODULE_FL_LOADED; 
     323            unload_module(m->name); 
    304324            log_error("failed to load module %s", m->name); 
    305325            return 0; 
    306326        } 
    307327    } 
     328 
     329    /* lookup and set the unload function late so that it cannot be used by 
     330     * unload_module() when we call it above in failure cases. */ 
     331    snprintf(fn, 32, "%s_unloader", sn); 
     332    m->unload_function = (module_unload_function)dlsym(m->handle, fn); 
    308333 
    309334    /* go ahead and take care of destroying the saved data for them */ 
     
    314339        free(msdp->name); 
    315340        free(msdp); 
    316     } 
    317  
    318     /* fix symbol exports */ 
    319     LIST_FOREACH(msym, &msym_list, lp) { 
    320         if (msym->module == m) { 
    321             msym->val = dlsym(m->handle, msym->name); 
    322             if (msym->val == NULL) 
    323                 log_error("yipes!  invalidated module symbol %s(%s)", 
    324                         msym->name, m->name); 
    325         } 
    326341    } 
    327342 
     
    372387    module_t *m2; 
    373388    struct module_dependency *mdep, *mdep2; 
    374     msymbol_t *msym; 
    375389 
    376390    if (m == NULL) { 
     
    440454    } 
    441455 
    442     /* nullify symbols */ 
    443     LIST_FOREACH(msym, &msym_list, lp) { 
    444         if (msym->module == m) 
    445             msym->val = NULL; 
    446     } 
    447  
    448456    /* now for each of our modules, if they have a dependency for this module, 
    449457     * remove it from their listing. */ 
     
    540548    m->name = strdup(name); 
    541549    /* strip off the extension */ 
    542     s = strrchr(m->name, '.'); 
    543     if (s != NULL) { 
    544         if (!strcmp(s, ".so")) 
    545             *s = '\0'; 
    546     } 
    547     /* check to see if there's a dependncies file */ 
    548     sprintf(m->fullpath, "%s/%s.deps", me.lib_path, m->name); 
    549     if (access(m->fullpath, R_OK) != -1) 
    550         m->depfile = strdup(m->fullpath); 
    551     else 
    552         m->depfile = NULL; 
    553     sprintf(m->fullpath, "%s/%s.so", me.lib_path, m->name); 
    554     if (access(m->fullpath, R_OK) == -1) { 
     550    if (MODULE_EXTENSION[0]) { 
     551        s = strrchr(m->name, MODULE_EXTENSION[0]); 
     552        if (s != NULL) { 
     553            if (!strcmp(s, MODULE_EXTENSION)) 
     554                *s = '\0'; 
     555        } 
     556    } 
     557 
     558    sprintf(m->fullpath, "%s/%s" MODULE_EXTENSION, me.lib_path, m->name); 
     559    if (access(m->fullpath, R_OK | X_OK) == -1) { 
    555560        log_error("unable to open module %s from %s: %s", m->name, 
    556561                m->fullpath, strerror(errno)); 
    557         if (m->depfile != NULL) 
    558             free(m->depfile); 
    559         free(m->name); 
    560         free(m); 
     562        destroy_module(m); 
    561563        return NULL; 
    562564    } 
     
    566568static void destroy_module(module_t *mod) { 
    567569 
    568     LIST_REMOVE(mod, lp); 
     570    /* only remove it if it's in the list */ 
     571    if (find_module(mod->name) != NULL) 
     572        LIST_REMOVE(mod, lp); 
    569573    free(mod->name); 
    570574    free(mod->fullpath); 
    571     if (mod->depfile != NULL) 
    572         free(mod->depfile); 
     575    if (mod->conffile != NULL) 
     576        free(mod->conffile); 
     577    if (mod->confdata != NULL) 
     578        destroy_conf_branch(mod->confdata); 
    573579    free(mod); 
    574 } 
    575  
    576 /* module symbol stuffs. */ 
    577 static msymbol_t *find_msymbol(char *name) { 
    578     msymbol_t *msp; 
    579  
    580     LIST_FOREACH(msp, &msym_list, lp) { 
    581         if (!strcmp(msp->name, name)) 
    582             return msp; 
    583     } 
    584  
    585     return NULL; 
    586 } 
    587  
    588 /* this function 'exports' a symbol (basically, creates an msymbol structure 
    589  * for it, and finds it, etc.  it can be called by import_msymbol, and is 
    590  * basically useful as a 'pre-declare' call. */ 
    591 msymbol_t *export_symbol(char *name, module_t *mod) { 
    592     msymbol_t *msp; 
    593     void *obj = NULL; 
    594  
    595     if (mod != NULL && !(mod->flags & MODULE_FL_LOADED)) { 
    596         log_error("export_symbol(%s, %s) called with unloaded module.", 
    597                 name, mod->name); 
    598         return NULL; /* blech. */ 
    599     } 
    600      
    601     msp = find_msymbol(name); 
    602     if (msp != NULL && msp->module != mod) { 
    603         log_warn("attempt to overwrite msymbol %s(%s)", msp->name, 
    604                 msp->module->name); 
    605         return msp; /* hm..? */ 
    606     } 
    607      
    608     if (msp == NULL) { 
    609         msp = malloc(sizeof(msymbol_t)); 
    610         LIST_INSERT_HEAD(&msym_list, msp, lp); 
    611     } 
    612  
    613     strlcpy(msp->name, name, sizeof(msp->name)); 
    614     if (mod != NULL) { 
    615         /* they told us where to get it from.. */ 
    616         if ((obj = dlsym(mod->handle, msp->name)) == NULL) { 
    617             log_warn("export_symbol(%s, %s): could not find symbol", msp->name, 
    618                     mod->name); 
    619             LIST_REMOVE(msp, lp); 
    620             free(msp); 
    621             return NULL; 
    622         } 
    623         msp->module = mod; 
    624         msp->val = obj; 
    625         return msp; 
    626     } else { 
    627         /* try the modules we know of first */ 
    628         mod = LIST_FIRST(&me.modules); 
    629         while (obj == NULL && mod != NULL) { 
    630             if (mod->flags & MODULE_FL_LOADED) { 
    631                 if ((obj = dlsym(mod->handle, msp->name)) != NULL) 
    632                     break; 
    633             } 
    634             mod = LIST_NEXT(mod, lp); 
    635         } 
    636         if (obj == NULL) { 
    637             /* no luck?  try RTLD_DEFAULT..  Actually, try NULL (the executable 
    638              * itself), then RTLD_NEXT (all the shared modules loaded by the 
    639              * executable .. which is actually more than we want, but will get 
    640              * us to compile-time linked libraries when nothing else will) */ 
    641             mod = NULL; 
    642             if ((obj = dlsym(NULL, msp->name)) == NULL) 
    643                 obj = dlsym(RTLD_NEXT, msp->name); 
    644         } 
    645     } 
    646     if (obj == NULL) { 
    647         log_warn("export_symbol(%s): could not find symbol", msp->name); 
    648         LIST_REMOVE(msp, lp); 
    649         free(msp); 
    650         return NULL; 
    651     } 
    652     msp->module = mod; 
    653     msp->val = obj; 
    654  
    655     return msp; 
    656 } 
    657  
    658 /* this function is considerably simpler.  do a symbol lookup to see if we 
    659  * already know of this symbol, if we do then pass it back to the caller, 
    660  * otherwise try to get it from an export, then return the final value. */ 
    661 msymbol_t *import_symbol(char *name) { 
    662     msymbol_t *msp; 
    663  
    664     msp = find_msymbol(name); 
    665     if (msp == NULL) 
    666         msp = export_symbol(name, NULL); 
    667  
    668     return msp; 
    669580} 
    670581 
     
    678589 * mdext data. */ 
    679590 
    680 #define mdext_realloc(header, data) do {                                \ 
    681     if (header->size != 0)                                                \ 
    682         data = realloc(data, header->size);                                \ 
    683     else {                                                                \ 
    684         if (data != NULL)                                                \ 
    685             free(data);                                                        \ 
    686         data = NULL;                                                        \ 
    687     }                                                                        \ 
     591#define mdext_realloc(header, data) do {                                      \ 
     592    if (header->size != 0)                                                    \ 
     593        data = realloc(data, header->size);                                   \ 
     594    else {                                                                    \ 
     595        if (data != NULL)                                                     \ 
     596            free(data);                                                       \ 
     597        data = NULL;                                                          \ 
     598    }                                                                         \ 
    688599} while (0) 
    689600 
     
    691602 * type, not per structure.  this is used as the head of the tracking data for 
    692603 * that structure. */ 
    693 struct mdext_header *create_mdext_header(const char *iter) { 
     604struct mdext_header *create_mdext_header(mdext_iter_function iter) { 
    694605    struct mdext_header *mdhp = NULL; 
    695606 
     
    697608    mdhp->create = create_event(EVENT_FL_NORETURN); 
    698609    mdhp->destroy = create_event(EVENT_FL_NORETURN); 
    699     mdhp->iter = import_symbol((char *) iter); 
     610    mdhp->iter = iter; 
    700611 
    701612    return mdhp; 
     
    725636    char **data; 
    726637    char *rhold = NULL; /* data held for iter */ 
    727     mdext_iter_function iter = (mdext_iter_function)getsym(header->iter); 
    728638 
    729639    mip = calloc(1, sizeof(struct mdext_item)); 
     
    734644 
    735645    /* go through and resize everything.  also, zero-fill our new section. */ 
    736     while ((data = iter(&rhold)) != NULL) { 
     646    while ((data = header->iter(&rhold)) != NULL) { 
    737647        mdext_realloc(header, *data); 
    738648        memset(*data + mip->offset, 0, mip->size); 
     
    750660    char **data; 
    751661    char *rhold = NULL; /* data held for iter */ 
    752     mdext_iter_function iter = (mdext_iter_function)getsym(header->iter); 
    753662 
    754663    SLIST_FOREACH(mip, &header->items, lp) { 
     
    772681     * total size (making this the last item)) then do so. */ 
    773682    if (mip->offset + mip->size != header->size) { 
    774         while ((data = iter(&rhold)) != NULL)  
     683        while ((data = header->iter(&rhold)) != NULL)  
    775684            memmove(*data + mip->offset, *data + (mip->offset + mip->size), 
    776685                    (header->size - mip->offset - mip->size)); 
     
    778687    header->size -= mip->size; 
    779688    rhold = NULL; 
    780     while ((data = iter(&rhold)) != NULL) 
     689    while ((data = header->iter(&rhold)) != NULL) 
    781690        mdext_realloc(header, *data); 
    782691 
  • branches/ithildin-scons/lib/string.c

    r761 r783  
    387387        return def; 
    388388 
    389     if (!strcasecmp(str, "yes") || !strcasecmp(str, "on") || atoi(str)) 
     389    if (!strcasecmp(str, "yes") || !strcasecmp(str, "on") || 
     390            !strcasecmp(str, "true") || atoi(str) == 1) 
    390391        return 1; 
    391     else if (!strcasecmp(str, "no") || !strcasecmp(str, "off") || !atoi(str)) 
     392    else if (!strcasecmp(str, "no") || !strcasecmp(str, "off") || 
     393            !strcasecmp(str, "false") || atoi(str) == 0) 
    392394        return 0; 
    393395 
  • branches/ithildin-scons/source/main.c

    r764 r783  
    339339} 
    340340 
    341 HOOK_FUNCTION(reload_conf) { 
    342     char currdir[PATH_MAX]; 
    343     conf_list_t *newconf = NULL; 
    344     conf_list_t *oldconf = NULL; 
    345  
    346     getcwd(currdir, PATH_MAX); 
    347     if (chdir(me.conf_path)) { 
    348         log_error("couldn't chdir to conf directory %s while reloading conf ", 
    349                 me.conf_path); 
    350         return NULL; 
    351     } 
    352     newconf = read_conf(me.conf_file); 
    353     if (newconf == NULL) { 
    354         log_error("couldn't read configuration file %s while reloading conf!", 
    355                 me.conf_file); 
    356         return NULL; 
    357     } 
    358     chdir(currdir); 
    359  
    360     oldconf = me.confhead; 
    361     me.confhead = newconf; 
    362     build_module_list(); /* rebuild the module list */ 
    363     hook_event(me.events.read_conf, (void *)me.confhead); 
    364     destroy_conf_branch(oldconf); 
    365     log_notice("reloaded configuration file %s/%s", me.conf_path, 
    366             me.conf_file); 
    367  
    368     return NULL; 
    369 } 
    370  
    371 /* eventually aborting existence should consist of more cleanup, right now 
    372  * all we do is destroy all our sockets.  probably what I should do is write 
    373  * a *_shutdown function for each subsystem.  later.  */ 
    374 HOOK_FUNCTION(exit_process) { 
    375     struct isocket *sp; 
    376  
    377     /* if this function is called pre-shutdown, simply set the shutdown flag, 
    378      * we will get called again later to do cleanup. */ 
    379     if (me.shutdown == 0) { 
    380         me.shutdown = -1; 
    381         return NULL; 
    382     } 
    383  
    384     /* unload all our modules */ 
    385     unload_all_modules(); 
    386  
    387     /* free our conf stuff */ 
    388     destroy_conf_branch(me.confhead); 
    389  
    390     /* thrash all our sockets */ 
    391     reap_dead_sockets(); 
    392     LIST_FOREACH(sp, &allsockets, intlp) { 
    393         destroy_socket(sp); 
    394     } 
    395     reap_dead_sockets(); 
    396  
    397 #ifdef HAVE_OPENSSL 
    398     if (me.ssl.enabled) 
    399         ERR_free_strings(); 
    400 #endif 
    401  
    402     exit(0); 
    403     return NULL; /* NOTREACHED */ 
    404 } 
    405  
    406341void sighandler_generic(int sig) { 
    407342    switch (sig) { 
Note: See TracChangeset for help on using the changeset viewer.