/* * Parse the in-memory copy of the configuration data */ static int __iodbcdm_cfg_parse (PCONFIG pconfig) { int isContinue, inString; char *imgPtr; char *endPtr; char *lp; char *section; char *id; char *value; char *comment; if (_iodbcdm_cfg_valid (pconfig)) return 0; endPtr = pconfig->image + pconfig->size; for (imgPtr = pconfig->image; imgPtr < endPtr;) { if (!__iodbcdm_cfg_getline (&imgPtr, &lp)) continue; section = id = value = comment = NULL; /* * Skip leading spaces */ if (iswhite (*lp)) { lp = __iodbcdm_cfg_skipwhite (lp); isContinue = 1; } else isContinue = 0; /* * Parse Section */ if (*lp == '[') { section = __iodbcdm_cfg_skipwhite (lp + 1); if ((lp = strchr (section, ']')) == NULL) continue; *lp++ = 0; if (rtrim (section) == NULL) { section = NULL; continue; } lp = __iodbcdm_cfg_skipwhite (lp); } else if (*lp != ';' && *lp != '#') { /* Try to parse * 1. Key = Value * 2. Value (iff isContinue) */ if (!isContinue) { /* Parse `<Key> = ..' */ id = lp; if ((lp = strchr (id, '=')) == NULL) continue; *lp++ = 0; rtrim (id); lp = __iodbcdm_cfg_skipwhite (lp); } /* Parse value */ inString = 0; value = lp; while (*lp) { if (inString) { if (*lp == inString) inString = 0; } else if (*lp == '"' || *lp == '\'') inString = *lp; else if ((*lp == ';' || *lp == '#') && iswhite (lp[-1])) { *lp = 0; comment = lp + 1; rtrim (value); break; } lp++; } } /* * Parse Comment */ if (*lp == ';' || *lp == '#') comment = lp + 1; if (_iodbcdm_cfg_storeentry (pconfig, section, id, value, comment, 0) == -1) { pconfig->dirty = 1; return -1; } } pconfig->flags |= CFG_VALID; return 0; }
/* * Change the configuration * * section id value action * -------------------------------------------------------------------------- * value value value update '<entry>=<string>' in section <section> * value value NULL delete '<entry>' from section <section> * value NULL NULL delete section <section> */ int _iodbcdm_cfg_write ( PCONFIG pconfig, char *section, char *id, char *value) { PCFGENTRY e, e2, eSect; int idx; int i; if (!_iodbcdm_cfg_valid (pconfig) || section == NULL) return -1; /* find the section */ e = pconfig->entries; i = pconfig->numEntries; eSect = 0; while (i--) { if (e->section && !strcasecmp (e->section, section)) { eSect = e; break; } e++; } /* did we find the section? */ if (!eSect) { /* check for delete operation on a nonexisting section */ if (!id || !value) return 0; /* add section first */ if (_iodbcdm_cfg_storeentry (pconfig, section, NULL, NULL, NULL, 1) == -1 || _iodbcdm_cfg_storeentry (pconfig, NULL, id, value, NULL, 1) == -1) return -1; pconfig->dirty = 1; return 0; } /* ok - we have found the section - let's see what we need to do */ if (id) { if (value) { /* add / update a key */ while (i--) { e++; /* break on next section */ if (e->section) { /* insert new entry before e */ idx = e - pconfig->entries; if (__iodbcdm_cfg_poolalloc (pconfig, 1) == NULL) return -1; memmove (e + 1, e, (pconfig->numEntries - idx) * sizeof (TCFGENTRY)); e->section = NULL; e->id = strdup (id); e->value = strdup (value); e->comment = NULL; if (e->id == NULL || e->value == NULL) return -1; e->flags |= CFE_MUST_FREE_ID | CFE_MUST_FREE_VALUE; pconfig->dirty = 1; return 0; } if (e->id && !strcasecmp (e->id, id)) { /* found key - do update */ if (e->value && (e->flags & CFE_MUST_FREE_VALUE)) { e->flags &= ~CFE_MUST_FREE_VALUE; free (e->value); } pconfig->dirty = 1; if ((e->value = strdup (value)) == NULL) return -1; e->flags |= CFE_MUST_FREE_VALUE; return 0; } } /* last section in file - add new entry */ if (_iodbcdm_cfg_storeentry (pconfig, NULL, id, value, NULL, 1) == -1) return -1; pconfig->dirty = 1; return 0; } else { /* delete a key */ while (i--) { e++; /* break on next section */ if (e->section) return 0; /* not found */ if (e->id && !strcasecmp (e->id, id)) { /* found key - do delete */ eSect = e; e++; goto doDelete; } } /* key not found - that' ok */ return 0; } } else { /* delete entire section */ /* find e : next section */ while (i--) { e++; /* break on next section */ if (e->section) break; } if (i < 0) e++; /* move up e while comment */ e2 = e - 1; while (e2->comment && !e2->section && !e2->id && !e2->value && (iswhite (e2->comment[0]) || e2->comment[0] == ';')) e2--; e = e2 + 1; doDelete: /* move up eSect while comment */ e2 = eSect - 1; while (e2->comment && !e2->section && !e2->id && !e2->value && (iswhite (e2->comment[0]) || e2->comment[0] == ';')) e2--; eSect = e2 + 1; /* delete everything between eSect .. e */ for (e2 = eSect; e2 < e; e2++) { if (e2->flags & CFE_MUST_FREE_SECTION) free (e2->section); if (e2->flags & CFE_MUST_FREE_ID) free (e2->id); if (e2->flags & CFE_MUST_FREE_VALUE) free (e2->value); if (e2->flags & CFE_MUST_FREE_COMMENT) free (e2->comment); } idx = e - pconfig->entries; memmove (eSect, e, (pconfig->numEntries - idx) * sizeof (TCFGENTRY)); pconfig->numEntries -= e - eSect; pconfig->dirty = 1; } return 0; }
/* * Parse a configuration from string (internal) */ int _iodbcdm_cfg_parse_str_Internal (PCONFIG pconfig, char *str) { char *s; int count; /* init image */ _iodbcdm_cfg_freeimage (pconfig); if (str == NULL) { /* NULL string is ok */ return 0; } s = pconfig->image = strdup (str); /* Add [ODBC] section */ if (_iodbcdm_cfg_storeentry (pconfig, "ODBC", NULL, NULL, NULL, 0) == -1) return -1; for (count = 0; *s; count++) { char *keywd = NULL, *value; char *cp, *n; /* * Extract KEY=VALUE upto first ';' */ for (cp = s; *cp && *cp != ';'; cp++) { if (*cp == '{') { for (cp++; *cp && *cp != '}'; cp++) ; } } /* * Store start of next token if available in n and terminate string */ if (*cp) { *cp = 0; n = cp + 1; } else n = cp; /* * Find '=' in string */ for (cp = s; *cp && *cp != '='; cp++) ; if (*cp) { *cp++ = 0; keywd = s; value = cp; } else if (count == 0) { /* * Handle missing DSN=... from the beginning of the string, e.g.: * 'dsn_ora7;UID=scott;PWD=tiger' */ keywd = "DSN"; value = s; } if (keywd != NULL) { /* store entry */ if (_iodbcdm_cfg_storeentry (pconfig, NULL, keywd, value, NULL, 0) == -1) return -1; } /* * Continue with next token */ s = n; } /* we're done */ pconfig->flags |= CFG_VALID; pconfig->dirty = 1; return 0; }