/* * int readsleepycfg(char *cfgname, SleepyCfg* cfg) * * Common routines for SleepyCat DB interfacing in ZMailer * * by Matti Aarnio 2002 * */ #include "hostenv.h" #if defined(HAVE_DB_H) || defined(HAVE_DB1_DB_H) || \ defined(HAVE_DB2_DB_H) || defined(HAVE_DB3_DB_H) || \ defined(HAVE_DB4_DB_H) #include #if (defined(__svr4__) || defined(__SVR4)) && defined(__sun) # define BSD_COMP /* Damn Solaris, and its tricks... */ #endif #include #ifdef HAVE_STDLIB_H #include #endif #include #include #include #include "sleepycatdb.h" #include "zmalloc.h" #include "libz.h" ZSleepyEnvSet *ZSleepyEnvSetRoot = NULL; /* * readsleepycfg */ /* * * Config file syntax for SleepyCat DB 3.x/4.x: * * envhome = /path/to/envhome/directory * envflags = CDB, CREATE, RO * envmode = 0644 * tempdir = /path/to/tmp/dir * * */ static int readsleepycfg(prv) ZSleepyPrivate* prv; { FILE *cfgfp; char cfgline[250]; ZSleepyEnvSet ZSE; int zseset = 0; memset(&ZSE, 0, sizeof(ZSE)); if (!prv->cfgname) return -1; cfgfp = fopen(prv->cfgname,"r"); if (!cfgfp) return -1; while (cfgfp && !ferror(cfgfp) && !feof(cfgfp)) { char *cmd, *param, c; char *s = fgets(cfgline, sizeof(cfgline)-1, cfgfp); cfgline[sizeof(cfgline)-1] = 0; if (!s) break; /* Acceptable lines begin with letters */ c = *cfgline; if (!(('a' <= c && c <= 'z')||('A' <= c && c <= 'Z'))) continue; s = strchr(cfgline, '\n'); if (s) *s = 0; /* Zap ending LF */ cmd = cfgline; s = cfgline; while (*s && *s != ' ' && *s != '\t' && *s != ':' && *s != '=') ++s; if (*s) *s++ = 0; while (*s && (*s == ' ' || *s == '\t' || *s == ':' || *s == '='))++s; param = s; if (CISTREQ(cmd,"envflags")) { /* envflags = CDB, RO */ ZSE.envflags = 0; while (param && *param != 0) { char *p = param; while (*p && !strchr(" \t,",*p)) ++p; if (*p) *p++ = 0; while (*p && strchr(" \t,",*p)) ++p; #if defined(DB_INIT_CDB) && defined(DB_INIT_MPOOL) if (CISTREQ(param, "cdb")) { ZSE.envflags |= DB_INIT_CDB|DB_INIT_MPOOL; zseset = 1; param = p; continue; } #endif #ifdef DB_CREATE if (CISTREQ(param, "create")) { ZSE.envflags |= DB_CREATE; zseset = 1; param = p; continue; } #endif if (CISTREQ(param, "ro")) { prv->roflag = 1; param = p; continue; } fprintf(stderr, "In file '%s' envflags parameter '%s' is not supported in this system.\n",prv->cfgname, param); param = p; } continue; } #if defined(HAVE_DB3) || defined(HAVE_DB4) if (CISTREQ(cmd,"envhome")) { if (ZSE.envhome) free((void*)ZSE.envhome); ZSE.envhome = strdup(param); zseset = 1; continue; } if (CISTREQ(cmd,"envmode")) { ZSE.envmode = 0600; sscanf(param,"%o",&ZSE.envmode); zseset = 1; continue; } if (CISTREQ(cmd,"tmpdir")) { ZSE.tmpdir = strdup(param); if (ZSE.tmpdir) free((void*)ZSE.tmpdir); zseset = 1; continue; } #endif fprintf(stderr, "In file '%s' the keyword '%s' is not supported in this system\n", prv->cfgname, cmd); } fclose(cfgfp); if (zseset && ZSE.envhome) { /* Ok, something usefull set, lets see if there exists a ZSE set with alike values.. Well, alike ENVHOME value. */ ZSleepyEnvSet *zesp = ZSleepyEnvSetRoot; ZSleepyEnvSet *zesp0 = zesp; if (zesp) { do { if (strcmp(zesp->envhome,ZSE.envhome) == 0) { /* Alike value ! */ prv->ZSE = zesp; zesp->refcount += 1; if (ZSE.envhome) free((void*)ZSE.envhome); if (ZSE.tmpdir) free((void*)ZSE.tmpdir); return 0; } zesp = zesp->next; } while (zesp != zesp0); } /* No environment found .. */ /* .. so we add it into the chain. */ zesp = malloc(sizeof(*zesp)); if (!zesp) return -1; if (!ZSleepyEnvSetRoot) { /* We are the new root! */ ZSleepyEnvSetRoot = zesp; ZSE.next = zesp; ZSE.prev = zesp; } else { /* We join the chain */ ZSE.next = zesp0->next; ZSE.prev = zesp0; zesp0->next = zesp; ZSE.next->prev = zesp; } *zesp = ZSE; /* Store the ready bundle.. */ prv->ZSE = zesp; zesp->refcount = 1; } return 0; } ZSleepyPrivate *zsleepyprivateinit(filename, cfgname, dbtype) const char *filename; const char *cfgname; DBTYPE dbtype; { ZSleepyPrivate *prv = malloc(sizeof(*prv)); if (!prv) return NULL; /* GAWD!! */ memset(prv, 0, sizeof(*prv)); prv->dbtype = dbtype; prv->filename = filename; prv->cfgname = cfgname; readsleepycfg(prv); return prv; } void zsleepyprivatefree(prv) ZSleepyPrivate *prv; { ZSleepyEnvSet *ZSE = prv->ZSE; if (ZSE && ZSE->refcount == 1) { #if defined(HAVE_DB3) || defined(HAVE_DB4) ZSE->env->close(prv->ZSE->env, 0); #endif if (ZSE->envhome) free((void*)(ZSE->envhome)); if (ZSE->tmpdir) free((void*)(ZSE->tmpdir)); /* Unlink from the chains */ if (ZSE->next != ZSE->prev) { ZSE->next->prev = ZSE->next; ZSE->prev->next = ZSE->prev; /* Wether it was us, or not.. */ ZSleepyEnvSetRoot = ZSE->prev; } else { /* prev == next -- us alone.. */ ZSleepyEnvSetRoot = NULL; } free(ZSE); } else if (ZSE && ZSE->refcount > 1) ZSE->refcount -= 1; free(prv); } int zsleepyprivateopen(prv, roflag, mode, comment) ZSleepyPrivate *prv; int roflag; int mode; char **comment; { volatile int err = 0; DB *db = NULL; #if 0 /* Must always do environment init, even when doing R/O DB access */ if (prv->roflag && (roflag != O_RDONLY)) { return -1; } #endif #if defined(HAVE_DB3) || defined(HAVE_DB4) if (prv->ZSE && prv->ZSE->envhome && !prv->ZSE->env) { if (comment) *comment = " environment of"; err = db_env_create(& prv->ZSE->env, 0); if (err) return err; /* Uhh.. */ prv->ZSE->env->set_errpfx(prv->ZSE->env, "router"); prv->ZSE->env->set_errfile(prv->ZSE->env, stderr); if (prv->ZSE->tmpdir) err = prv->ZSE->env->set_tmp_dir(prv->ZSE->env, prv->ZSE->tmpdir); if (err) return err; /* Uhh.. */ err = prv->ZSE->env->open(prv->ZSE->env, prv->ZSE->envhome, prv->ZSE->envflags, prv->ZSE->envmode); if (err) prv->ZSE->env->err(prv->ZSE->env, err, "envhome <%s> open failed", prv->ZSE->envhome ? prv->ZSE->envhome : "NULL"); if (err) return err; /* Uhh.. */ } if (comment) *comment = " db_create()"; err = db_create(&db, prv->ZSE ? prv->ZSE->env : NULL, 0); if (err == 0 && db != NULL) { err = db->open( db, #if (DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR == 1) NULL, /* TXN id was added at SleepyDB 4.1 */ #endif prv->filename, NULL, prv->dbtype, ((roflag == O_RDONLY) ? DB_RDONLY:DB_CREATE), mode ); if (comment) *comment = " database"; } if (err != 0 && db != NULL) { db->close(db, 0); db = NULL; } #else #if defined(HAVE_DB2) err = db_open( prv->filename, prv->dbtype, ((roflag == O_RDONLY) ? DB_RDONLY:DB_CREATE), 0644, NULL, NULL, &db ); if (comment) *comment = " batabase"; #else db = dbopen( prv->filename, roflag, 0, prv->dbtype, NULL ); if (!db) err = errno; if (comment) *comment = " batabase"; #endif #endif prv->db = db; prv->roflag = roflag; return err; } #endif /* SleepyCat headers exist */