/* Configuration processing routines for GNATS -*- C -*-
   Copyright (C) 1993 Free Software Foundation, Inc.

This file is part of GNU GNATS.

GNU GNATS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU GNATS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU GNATS; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* The basic idea here is to be able to use the same configuration file for
   sh scripts and C programs; the sh script just uses `.', but the C program
   has to be a bit more trickier.  And a lot uglier.  */

/* FIXME, maybe: Use hash table for more option-ridden programs.  */

#include "config.h"

#include <stdio.h>
#include <string.h>
#include "globals.h"
#include "gnats.h"
#include "pathmax.h"

char *gnats_root = GNATS_ROOT;

static char _gnats_addr[STR_MAX] = GNATS_ADDR;
char *gnats_addr = _gnats_addr;
static char _gnats_admin[STR_MAX] = GNATS_ADMIN;
char *gnats_admin = _gnats_admin;
static char _def_subm[STR_MAX] = DEFAULT_SUBMITTER;
char *def_subm = _def_subm;
int flag_notify = NOTIFY;
int flag_ack = ACKNOWLEDGE;
int keep_rec = KEEP_RECEIVED_HEADERS;
int debug_mode = DEBUG_MODE;
int bday_start = BDAY_START;
int bday_end = BDAY_END;
int bweek_start = BWEEK_START;
int bweek_end = BWEEK_END;
static char _mail_agent[STR_MAX] = MAIL_AGENT;
char *mail_agent = _mail_agent;
static char _bindir[STR_MAX] = BINDIR;
char *bindir = _bindir;

struct conf
{
  char* key;
  char* val;
};

#ifdef __STDC__
#define STDCINIT
#endif
   
#ifdef STDCINIT
static struct conf confs[] = {
  { "GNATS_ADDR", _gnats_addr },
  { "GNATS_ADMIN", _gnats_admin },
  { "DEFAULT_SUBMITTER", _def_subm },
  { "NOTIFY", (char *) &flag_notify },
  { "ACKNOWLEDGE", (char *) &flag_ack },
  { "KEEP_RECEIVED_HEADERS", (char *) &keep_rec },
  { "DEBUG_MODE", (char *) &debug_mode },
  { "BDAY_START", (char *) &bday_start },
  { "BDAY_END", (char *) &bday_end },
  { "BWEEK_START", (char *) &bweek_start },
  { "BWEEK_END", (char *) &bweek_end },
  { "MAIL_AGENT", _mail_agent },
  { "BINDIR", _bindir },
};
#else
static struct conf confs[13];
#endif

static char *fname = NULL;
static char *string_extract_double_quoted ();
static char *safe_strtok ();

/* Read in and set the above configuration parameters */
void
configure()
{
  FILE *fp;
  char line[STR_MAX];

#ifndef STDCINIT
  confs[0].key = "GNATS_ADDR"; confs[0].val = gnats_addr;
  confs[1].key = "GNATS_ADMIN"; confs[1].val = gnats_admin;
  confs[2].key = "DEFAULT_SUBMITTER"; confs[2].val = def_subm;
  confs[3].key = "NOTIFY"; confs[3].val = (char *) &flag_notify;
  confs[4].key = "ACKNOWLEDGE"; confs[4].val = (char *) &flag_ack;
  confs[5].key = "KEEP_RECEIVED_HEADERS"; confs[5].val = (char *) &keep_rec;
  confs[6].key = "DEBUG_MODE"; confs[6].val = (char *) &debug_mode;
  confs[7].key = "BDAY_START"; confs[7].val = (char *) &bday_start;
  confs[8].key = "BDAY_END"; confs[8].val = (char *) &bday_end;
  confs[9].key = "BWEEK_START"; confs[9].val = (char *) &bweek_start;
  confs[10].key = "BWEEK_END"; confs[10].val = (char *) &bweek_end;
  confs[11].key = "MAIL_AGENT"; confs[11].val = mail_agent;
  confs[12].key = "BINDIR"; confs[12].val = bindir;
#endif
  
  if (fname) free (fname);
#define CONFSTR "%s/gnats-adm/config"
  fname = xmalloc (strlen (gnats_root) + sizeof (CONFSTR) - 1);
  sprintf (fname, CONFSTR, gnats_root);
  
  fp = fopen (fname, "r");
  
  if (fp == NULL)		/* no config file; no problem */
    return;
  
  while (fgets (line, STR_MAX, fp) != NULL)
    {
      int i;
      if (*line == '#') continue; /* comment */
      for (i=0; i < sizeof(confs)/sizeof(struct conf); i++) {
	int n = strlen(confs[i].key);
	if (! strncmp(confs[i].key, line, n) && line[n] == '=') {
	  char *p = line+n+1;
	  int d;
	  if (sscanf (p, "%d", &d) > 0)	/* NOTIFY=1 */
	    *((int *) confs[i].val) = d;
	  else			/* string parameter */
	    {
	      /* Mimic somewhat the sh interpretation of the line.  */
	      if (*p == '\'')
		strcpy (confs[i].val, safe_strtok(p+1, "'"));
	      else if (*p == '"')
		strcpy (confs[i].val, string_extract_double_quoted(p+1));
	      else strcpy (confs[i].val, safe_strtok(p, " \t\n"));
	    }
	  break;
	}
      }
    }
}

static char *
safe_strtok (s, d)
     char *s, *d;
{
  char *r = strtok (s, d);
  if (!r && *s != '\n')
    r = strtok (s, "\n");
  if (!r)
    r = "";
  return r;
}

/* Lifted largely from bash/subst.c */
static char *
string_extract_double_quoted (string)
     char *string;
{
  register int c, j, i;		/* character, temp pos, str pos */
  char *temp;			/* The new string we return. */
  int pass_next;		/* State variables for the machine. */

  pass_next = 0;
  temp = (char *)xmalloc (strlen (string) + 1);

  for (j = 0, i = 0; (c = string[i]) != '\0'; i++)
    {
      /* Process a character that was quoted by a backslash. */
      if (pass_next)
	{
	  /* Posix.2 sez:

	     ``The backslash shall retain its special meaning as an escape
	     character only when followed by one of the characters:
	     	$	`	"	\	<newline>''.  */
	  if (c != '$' && c != '`' && c != '"' && c != '\\' && c != '\n')
	    temp[j++] = '\\';
          temp[j++] = c;
          pass_next = 0;
          continue;
	}

      /* A backslash protects the next character.  The code just above
         handles preserving the backslash in front of any character but
         a double quote. */
      if (c == '\\')
	{
	  pass_next++;
	  continue;
	}

      /* An unescaped double quote serves to terminate the string. */
      if (c == '"')
        break;

      /* Add the character to the quoted string we're accumulating. */
      temp[j++] = c;
    }
  temp[j] = '\0';
  strcpy (string, temp);
  free (temp);
  return (string);
}
