/*=====================================================================
  isqlcfg.h - edit one setting inside an ISQL configuration file.

  Shared by both servers. -dbhome and -port have to work this way rather
  than by passing values to the engine, because a value in the config
  BEATS one passed to StartInternetSql. Measured, with a config naming one
  home and the argument naming another:

      no config file, home passed     ->  the passed home is used
      config names a home             ->  the CONFIG wins, silently

  A server always has a [DatabaseHome], so a -dbhome that was merely handed
  to the engine would be ignored every single time. Writing it into the file
  the engine is about to read is the only thing that takes effect.

  Only lines inside the entry ... end block are considered. Everything
  outside is prose - the shipped KAMRANGA.CFG explains itself with a
  sentence containing "[DatabaseHome] MUST point at ...", which is a comment
  and must not be mistaken for a setting.

  The previous file is kept as <cfg>.bak, so the change is reversible.
 =====================================================================*/
#ifndef ISQL_CFG_H
#define ISQL_CFG_H

#include <stdio.h>
#include <string.h>

#define ISQL_CFG_MAXLINES 400

/* Returns 1 on success, 0 on failure (and explains itself through `report`,
   which may be NULL for a program with no console). */
static int IsqlSetConfigValue(const char *cfgname,
                              const char *key,
                              const char *value,
                              void (*report)(const char *))
{
    char  lines[ISQL_CFG_MAXLINES][512];
    char  msg[512];
    char  bak[512];
    int   n = 0, i, in_block = 0, replaced = 0;
    FILE *fp;

    fp = fopen(cfgname, "r");
    if (fp == NULL)
    {
        if (report) { sprintf(msg, "no %s here to apply -%s to", cfgname, key); report(msg); }
        return 0;
    }
    while (n < ISQL_CFG_MAXLINES && fgets(lines[n], sizeof(lines[0]), fp) != NULL) n++;
    fclose(fp);

    for (i = 0; i < n; i++)
    {
        char *p = lines[i];
        while (*p == ' ' || *p == '\t') p++;

        if (!in_block) { if (_strnicmp(p, "entry", 5) == 0) in_block = 1; continue; }
        if (_strnicmp(p, "end", 3) == 0) break;
        if (*p != '[') continue;

        if (_strnicmp(p + 1, key, strlen(key)) == 0 && p[1 + strlen(key)] == ']')
        {
            sprintf(lines[i], "[%s] %s\n", key, value);
            replaced = 1;
            break;
        }
    }
    if (!replaced)
    {
        if (report) { sprintf(msg, "%s has no [%s] inside its entry...end block", cfgname, key); report(msg); }
        return 0;
    }

    sprintf(bak, "%s.bak", cfgname);
    remove(bak);
    rename(cfgname, bak);

    fp = fopen(cfgname, "w");
    if (fp == NULL)
    {
        if (report) { sprintf(msg, "cannot rewrite %s", cfgname); report(msg); }
        return 0;
    }
    for (i = 0; i < n; i++) fputs(lines[i], fp);
    fclose(fp);

    if (report) { sprintf(msg, "[%s] set to %s (previous kept as %s)", key, value, bak); report(msg); }
    return 1;
}

#endif /* ISQL_CFG_H */
