#include #include #include #include #include #include #include "list.h" #include "mapcalc.h" typedef char *(*func_t)(void); static int register_function (char *fname, void *func, char *proto); void init_plug (void); static int register_function (char *fname, void *func, char *proto) { STYP type; SYMBOL *sym; sym = getsym (fname); if (sym) symtab = (SYMBOL *)listdel ((LIST *)symtab, (LIST *)sym, freesym); /* * This is quite incomplete */ switch (proto[0]) { case 'd': type = st_nfunc; break; case 'm': type = st_mfunc; break; case 'p': type = st_pfunc; break; default: return 0; } sym = putsym (fname); sym->v.p = func; sym->type = sym->itype = sym->rettype = type; sym->proto = strdup (proto + 2); /* skip "m=" */ return 1; } void init_plug (void) { SYMBOL *sym; char path[4096], pathname[4096], *ptr, *fname, *proto; struct dirent *ent; void *handle, *func; func_t fh, ph; DIR *dir; /* * Search algorithm: * 1. Find "pluginpath" in symbol table. If not found... * 2. Find "$GISBASE/plugins". If not defined * 3. Use "./plugins" */ sym = getsym ("pluginpath"); if (sym && sym->v.p) strcpy (path, sym->v.p); else { ptr = getenv ("GISBASE"); if (ptr) strcpy (path, ptr); else strcpy (path, getcwd (path, 4096)); if (path[strlen (path) - 1] != '/') strcat (path, "/"); strcat (path, "plugins"); } dir = opendir (path); if (!dir) return; while ((ent = readdir (dir)) != NULL) { if (!strcmp (ent->d_name, ".") || !strcmp (ent->d_name, "..")) continue; strcpy (pathname, path); strcat (pathname, "/"); strcat (pathname, ent->d_name); if (access (pathname, R_OK | X_OK)) continue; handle = dlopen (pathname, RTLD_LAZY); if (!handle) continue; fh = dlsym (handle, "fname"); if (dlerror ()) { dlclose (handle); continue; } fname = (*fh)(); if (!fname) { dlclose (handle); continue; } ph = dlsym (handle, "proto"); if (dlerror ()) { dlclose (handle); continue; } proto = (*ph)(); if (!proto) { dlclose (handle); continue; } func = dlsym (handle, fname); if (!func) { dlclose (handle); continue; } if (!register_function (fname, func, proto)) dlclose (handle); } closedir (dir); }