/*
	WARNING: This file was generated by dkct.
	Changes you make here will be lost if dkct is run again!
	You should modify the original source and run dkct on it.
	Original source: itaconf.ctr
*/

/*
Copyright (C) 2012-2013, Dirk Krause

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
  this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above opyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.
* Neither the name of the author nor the names of contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**	@file itaconf.c The itaconf module.
*/


#line 10 "itaconf.ctr"

#include "dk3all.h"
#include "itadmin.h"





#line 17 "itaconf.ctr"



/**	Key names in configuration file.
*/
static dkChar const * const	itadmin_config_keys[] = {
/* 0 */
dkT("database-host"),

/* 1 */
dkT("database-name"),

/* 2 */
dkT("database-credentials-file"),

/* 3 */
dkT("dhcpd.conf-vlan"),

/* 4 */
dkT("organization"),

/* 5 */
dkT("organizational-unit"),

/* 6 */
dkT("administrator-name"),

/* 7 */
dkT("create-dhcpd.conf"),

/* 8 */
dkT("database-type"),

/* 9 */
dkT("ldap-base"),

/* 10 */
dkT("use-koma-script"),

NULL


#line 69 "itaconf.ctr"
};



/**	Names of SQL database types.
*/
static dkChar const * const	itadmin_config_database_types[] = {
/* 0 */
dkT("MySQL"),

NULL


#line 82 "itaconf.ctr"
};



/**	Keywords to watch out for when processing a credential file.
	Typically this is a .my.cnf file.
*/
static dkChar const * const itadmin_config_credential_keys[] = {
/* 0 */
dkT("client"),

/* 1 */
dkT("user"),

/* 2 */
dkT("password"),

NULL


#line 104 "itaconf.ctr"
};



/**	Set one string entry in job structure.
	@param	job	Job structure to modify.
	@param	resptr	Pointer to result pointer.
	@param	srcptr	Source string.
	@return	1 on success, 0 on error.
*/
static
int
itadmin_config_set_string(
  itadmin_job	 *job,
  dkChar const	**resptr,
  dkChar const	 *srcptr
)
{
  dkChar const	*np;		/* New string duplicate. */
  int		 back	= 0;
  

#line 125 "itaconf.ctr"
  np = dk3str_dup_app(srcptr,job->app);
  if(np) {
    dk3_release(*resptr)
    *resptr = np;
    back = 1;
  } else {
    /* ERROR: Memory allocation failed! */
  } 

#line 133 "itaconf.ctr"
  return back;
}



/**	Configure a boolean value setting.
	@param	job	Job structure.
	@param	bp	Pointer to result variable.
	@param	defv	Default value, used for empty or non-boolean strings.
	@param	txt	Configuration text.
	@return	1 on success, 0 on error.
*/
static
int
itadmin_config_set_bool(itadmin_job *job, int *bp, int defv, dkChar const *txt)
{
  dkChar	 lb[ITADMIN_CONFIG_LINE_SIZE];	/* Copy of value. */
  dkChar	*p1;				/* Start of text in copy. */
  int		 back	= 1;
  

#line 153 "itaconf.ctr"
  if(txt) {
    p1 = dk3str_start(txt, NULL);
    if(p1) {
      if(dk3str_len(p1) < DK3_SIZEOF(lb,dkChar)) {
        dk3str_cpy(lb, p1);
        dk3str_normalize(lb,NULL,dkT(' '));
	if(dk3str_is_bool(lb)) {
	  *bp = ((dk3str_is_on(lb)) ? 1 : 0);
	} else {					

#line 162 "itaconf.ctr"
	  back = 0;
	  *bp = defv;
	  /* ERROR: Not a boolean! */
	  dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 106, 107, lb);
	}
      } else {						

#line 168 "itaconf.ctr"
        back = 0;
	*bp = defv;
	/* ERROR: Text too long! */
	dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 108, 109, p1);
      }
    } else {						

#line 174 "itaconf.ctr"
      *bp = defv;
    }
  } else {						

#line 177 "itaconf.ctr"
    *bp = defv;
  } 

#line 179 "itaconf.ctr"
  return back;
}



/**	Set database type.
	@param	job	Job structure.
	@param	txt	Text for database type (at this time only "MySQL"
	can be used).
	@return	1 on success, 0 on error.
*/
static
int
itadmin_config_set_dbtype(itadmin_job *job, dkChar const *txt)
{
  int		back	= 0;
  int		i;		/* Index of type in array of known types. */
  if(txt) {
    i = dk3str_array_index(itadmin_config_database_types, txt, 0);
    if(i >= 0) {
      job->dbt = i;
      back = 1;
    } else {
      /* ERROR: No such database type! */
      dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 110, 111, txt);
    }
  } else {
    /* ERROR: Empty text. */
    dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 112);
  }
  return back;
}




/**	Handler function for one configuration file line.
	@param	obj	Reader object.
	@param	il	Input line to process (constant text).
	@return	1 for OK, 0 for recoverable error, -1 for abort.
*/
static
int
itadmin_config_const_line_handler(void *obj, dkChar const *il)
{
  dkChar	 line[ITADMIN_CONFIG_LINE_SIZE]; /* Private copy of line.*/
  itadmin_job	*job;
  dkChar	*p1;			/* Start of line. */
  dkChar	*p2;			/* Start of value in line. */
  int		 back = 0;
  

#line 230 "itaconf.ctr"
  if((obj) && (il)) {
    job = (itadmin_job *)obj;
    if(dk3str_len(il) < DK3_SIZEOF(line,dkChar)) {
      dk3str_cpy(line, il);
      dk3str_delnl(line);
      p1 = dk3str_start(line, NULL);
      if(p1) {
        if(*p1 == dkT('#')) {
	  back = 1;	/* Comment line. */
	} else {
	  p2 = dk3str_chr(p1, dkT('='));
	  if(p2) {
	    *(p2++) = dkT('\0');
	    p2 = dk3str_start(p2, NULL);
	    if(p2) {
	      dk3str_normalize(p1, NULL, dkT('-'));
	      switch(dk3str_array_index(itadmin_config_keys, p1, 0)) {
	        case 0: {	/* database host */
		  back = itadmin_config_set_string(job, &(job->dbhn), p2);
		} break;
		case 1: {	/* database name */
		  back = itadmin_config_set_string(job, &(job->dbn), p2);
		} break;
		case 2: {	/* credentials file */
		  back = itadmin_config_set_string(job, &(job->dbcf), p2);
		} break;
		case 3: {	/* VLAN name */
		  back = itadmin_config_set_string(job, &(job->vlan), p2);
		  if(back) {
		    job->f_dh = 1;
		  }
		} break;
		case 4: {	/* organization */
		  back = itadmin_config_set_string(job, &(job->org), p2);
		} break;
		case 5: {	/* organizational unit */
		  back = itadmin_config_set_string(job, &(job->ou), p2);
		} break;
		case 6: {	/* administrator name */
		  back = itadmin_config_set_string(job, &(job->admn), p2);
		} break;
		case 7: {
		  back = itadmin_config_set_bool(job, &(job->f_dh), 1, p2);
		} break;
		case 8: {
		  back = itadmin_config_set_dbtype(job, p2);
		} break;
		case 9: {
		  dk3str_normalize(p2, NULL, ' ');
		  back = itadmin_config_set_string(job, &(job->ldapb), p2);
		} break;
		case 10: {
		  if(dk3str_is_bool(p2)) {
		    back = 1;
		    job->ukoma = ((dk3str_is_on(p2)) ? 1 : 0);
		  } else {
		    /* ERROR: Boolean expected! */
		    dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,106,107,p2);
		  }
		} break;
		default: {
		  /* ERROR: Unknown option ... */
		  dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 113, 114, p1);
		} break;
	      }
	    } else {
	      /* ERROR: No value! */
	      dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 115);
	    }
	  } else {
	    /* ERROR: Missing '=' */
	    dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 115);
	  }
	}
      } else {
        back = 1;	/* Empty line. */
      }
    } else {
      /* ERROR: Input line too long! */
      dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 116);
    }
  } 

#line 312 "itaconf.ctr"
  return back;
}



/**	Handler function for one configuration file line.
	@param	obj	Reader object.
	@param	il	Input line to process.
	@return	1 for OK, 0 for recoverable error, -1 for abort.
*/
static
int
itadmin_cred_file_const_line_handler(void *obj, dkChar const *il)
{
  dkChar		 line[ITADMIN_CONFIG_LINE_SIZE]; /* Copy of line. */
  dkChar		*p1;		/* Start of key. */
  dkChar		*p2;		/* Start of value. */
  itadmin_cred_reader	*reader;	/* Help structure to read creds. */
  int			 back	= 0;
  

#line 332 "itaconf.ctr"
  if((obj) && (il)) {					

#line 333 "itaconf.ctr"
    reader = (itadmin_cred_reader *)obj;
    if(dk3str_len(il) < DK3_SIZEOF(line,dkChar)) {	

#line 335 "itaconf.ctr"
      dk3str_cpy(line, il);
      dk3str_delnl(line);
      p1 = dk3str_start(line, NULL);
      if(p1) {						

#line 339 "itaconf.ctr"
        if(*p1 == dkT('#')) {				

#line 340 "itaconf.ctr"
	  back = 1;		/* Ignore comment. */
	} else {					

#line 342 "itaconf.ctr"
	  if(*p1 == dkT('[')) {				

#line 343 "itaconf.ctr"
	    reader->f_clnt = 0;
	    p1++;
	    p2 = dk3str_chr(p1, dkT(']'));
	    if(p2) {					

#line 347 "itaconf.ctr"
	      back = 1;
	      *p2 = dkT('\0');
	      if(dk3str_cmp(p1, itadmin_config_credential_keys[0]) == 0) {
	        reader->f_clnt = 1;
	      }
	    } else {					

#line 353 "itaconf.ctr"
	      /* ERROR: Syntax! */
	      dk3app_log_1(
	        (reader->job)->app, DK3_LL_ERROR, (reader->job)->msg, 117
	      );
	    }
	  } else {					

#line 359 "itaconf.ctr"
	    back = 1;
	    p2 = dk3str_chr(p1, dkT('='));
	    if(p2) {					

#line 362 "itaconf.ctr"
	      *(p2++) = dkT('\0');
	      p2 = dk3str_start(p2, NULL);
	      if(p2) {					

#line 365 "itaconf.ctr"
	        dk3str_normalize(p1,NULL,dkT(' '));
		switch(dk3str_array_index(itadmin_config_credential_keys,p1,0))
		{
		  case 1: {	/* user */	

#line 369 "itaconf.ctr"
		    back = itadmin_config_set_string(
		      reader->job, &((reader->job)->dbus), p2
		    );
		  } break;
		  case 2: {	/* password */	

#line 374 "itaconf.ctr"
		    back = itadmin_config_set_string(
		      reader->job, &((reader->job)->dbpw), p2
		    );
		  } break;
		}
	      } else {					

#line 380 "itaconf.ctr"
	        /* Empty key. */
	      }
	    } else {					

#line 383 "itaconf.ctr"
	      /* Not a key=value line. */
	    }
	  }
	}
      } else {						

#line 388 "itaconf.ctr"
        back = 1;		/* Ignore empty line. */
      }
    } else {						

#line 391 "itaconf.ctr"
      /* ERROR: Line too long! */
      dk3app_log_1(
        (reader->job)->app, DK3_LL_ERROR, (reader->job)->msg, 116
      );
    }
  } else {						

#line 397 "itaconf.ctr"
  } 

#line 398 "itaconf.ctr"
  return back;
}



/**	Handler function for one configuration file line.
	@param	obj	Reader object.
	@param	il	Input line to process.
	@return	1 for OK, 0 for recoverable error, -1 for abort.
*/
static
int
itadmin_cred_file_line_handler(void *obj, dkChar *il)
{
  int back;
  back = itadmin_cred_file_const_line_handler(obj, il);
  return back;
}



/**	Handler function for one configuration file line.
	@param	obj	Reader object.
	@param	il	Input line to process.
	@return	1 for OK, 0 for recoverable error, -1 for abort.
*/
static
int
itadmin_config_line_handler(void *obj, dkChar *il)
{
  int		back;
  back = itadmin_config_const_line_handler(obj, il);
  return back;
}



/**	Process one configuration file.
	@param	job	Job structure.
	@param	fn	File name to process.
	@return	1 on success, 0 on error.
*/
static
int
itadmin_config_process_one_file(itadmin_job *job, dkChar const *fn)
{
  dkChar	line[ITADMIN_CONFIG_LINE_SIZE];	/* Copy of line. */
  int		back	= 0;
  

#line 447 "itaconf.ctr"
  back = dk3stream_process_filename_lines_app(
    (void *)job,
    itadmin_config_line_handler,
    fn,
    line,
    DK3_SIZEOF(line,dkChar),
    dk3app_get_encoding(job->app),
    dk3app_get_input_file_encoding(job->app),
    job->app
  );
  if(back < 1) {
    back = 0;
  } 

#line 460 "itaconf.ctr"
  return back;
}



/**	Read credentials file to obtain database user name and password.
	@param	job	Job structure.
	@return	1 on success, 0 on error.
*/
static
int
itadmin_config_read_credentials(itadmin_job *job)
{
  dkChar		fnb[DK3_MAX_PATH];		/* File name buffer. */
  dkChar		line[ITADMIN_CONFIG_LINE_SIZE];	/* Input line buffer. */
  itadmin_cred_reader	reader;		/* Helper structure to read creds. */
  int			back	= 0;
  

#line 478 "itaconf.ctr"
  if(dk3str_len(job->dbcf) < DK3_SIZEOF(fnb,dkChar)) {
    dk3str_cpy(fnb, job->dbcf);
    dk3str_correct_filename(fnb);
    if(dk3sf_must_expand(fnb)) {
      /* ERROR: File name must not contain wildcards! */
      dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 118, 119, fnb);
    } else {
      if(!dk3str_is_abs_path(fnb)) {
        /* WARNING: File name should be specified as absolute path! */
	dk3app_log_3(job->app, DK3_LL_WARNING, job->msg, 120, 121, fnb);
      }
      reader.job = job;
      reader.f_clnt = 1;	

#line 491 "itaconf.ctr"
      back = dk3stream_process_filename_lines_app(
        (void *)(&reader),
        itadmin_cred_file_line_handler,
        fnb,
        line,
        DK3_SIZEOF(line,dkChar),
        dk3app_get_encoding(job->app),
        dk3app_get_input_file_encoding(job->app),
        job->app
      );
    }
  } else {
    /* ERROR: File name too long! */
    dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, job->dbcf);
  }
  if(job->ec) {					

#line 507 "itaconf.ctr"
    back = 0;
  } 

#line 509 "itaconf.ctr"
  return back;
}



int
itadmin_config_read(itadmin_job *job)
{
  dkChar		 fnb[DK3_MAX_PATH];	/* Copy of file name. */
  dk3_search_t		*res;			/* Search result, config. */
  dk3_dir_t		*fne;			/* File name expander. */
  dk3_stat_t		*es;			/* Expandend file status. */
  dkChar const		*fn;			/* File name. */
  dkChar const		*en;			/* Expanded file name. */
  dkChar const		*fnorig;		/* Original file name. */
  int			 back	= 0;
  int			 have_file = 0;		/* Flag: File found. */
  int			 have_error = 0;	/* Flag: Error occured. */
  int			 argc;			/* Number of file names. */
  int			 i;			/* Current file name index. */
  

#line 530 "itaconf.ctr"
  /*
  	Process default configuration files.
  */
  res = dk3app_find_config_file(job->app, (job->noloc)[4], 0);
  if(res) {
    dk3search_reset(res);
    while((fn = dk3search_next(res)) != NULL) {
      have_file = 1;
      if(!itadmin_config_process_one_file(job, fn)) {
        have_error = 1;
      }
    }
    dk3search_close(res);
  }
  /*
  	Process configuration file(s) specified on command line.
  */
  argc = dk3opt_get_num_args(job->opt);
  for(i = 0; i < argc; i++) {
    fnorig = dk3opt_get_arg(job->opt, i);
    if(fnorig) {
      if(dk3str_len(fnorig) < DK3_SIZEOF(fnb,dkChar)) {
        dk3str_cpy(fnb, fnorig);
	dk3str_correct_filename(fnb);
	if(dk3sf_must_expand(fnb)) {
	  fne = dk3dir_fne_open_app(fnb, job->app);
	  if(fne) {
	    while(dk3dir_get_next_file(fne)) {
	      en = dk3dir_get_fullname(fne);
	      es = dk3dir_get_stat(fne);
	      if((en) && (es)) {
	        switch((es->ft) & (~(DK3_FT_SYMLINK))) {
		  case DK3_FT_REGULAR: {
	            have_file = 1;
	            if(!itadmin_config_process_one_file(job, fnb)) {
	              have_error = 1;
	            }
		  } break;
		  default: {
		    have_error = 1;
		    /* ERROR: Wrong file type! */
		    dk3app_log_i3(job->app, DK3_LL_ERROR, 255, 256, en);
		  } break;
		}
	      } else {
	        /* BUG: No complete information available! */
	      }
	    }
	    dk3dir_close(fne);
	  } else {
	    /* ERROR: Failed to expand file name! */
	  }
	} else {
	  have_file = 1;
	  if(!itadmin_config_process_one_file(job, fnb)) {
	    have_error = 1;
	  }
	}
      } else {
        /* ERROR: File name fnorig too long! */
	dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, fnorig);
      }
    } else {
      /* BUG: No pointer returned! */
    }
  }
  /*
  	Final tests and error messages.
  */
  if(have_file) {		

#line 600 "itaconf.ctr"
    if(!(have_error)) {		

#line 601 "itaconf.ctr"
      back = 1;
      if(!(job->dbhn)) {	

#line 603 "itaconf.ctr"
        /* ERROR: Missing database host name! */
	dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 122);
	back = 0;
      }
      if(!(job->dbn)) {		

#line 608 "itaconf.ctr"
        /* ERROR: Missing database name! */
	dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 123);
	back = 0;
      }
      if(!(job->vlan)) {	

#line 613 "itaconf.ctr"
        /* Warning: Missing VLAN name! */
	dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 124);
      }
      if(!(job->org)) {		

#line 617 "itaconf.ctr"
        /* ERROR: Missing organization name! */
	dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 125);
	back = 0;
      }
      if(!(job->ou)) {		

#line 622 "itaconf.ctr"
        /* ERROR: Missing organizational unit name! */
	dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 126);
	back = 0;
      }
      if(!(job->admn)) {	

#line 627 "itaconf.ctr"
        /* ERROR: Missing administrator name! */
	dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 127);
	back = 0;
      }
      if(!(job->dbcf)) {	

#line 632 "itaconf.ctr"
        /* ERROR: Missing database credentials file name! */
	dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 128);
	back = 0;
      } else {			

#line 636 "itaconf.ctr"
        if(back) {		

#line 637 "itaconf.ctr"
	  back = itadmin_config_read_credentials(job);
	  if(back) {
	    if(!(job->dbus)) {	

#line 640 "itaconf.ctr"
	      /* ERROR: Missing database user name! */
	      dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 129);
	      back = 0;
	    }
	    if(!(job->dbpw)) {	

#line 645 "itaconf.ctr"
	      /* ERROR: Missing database user password! */
	      dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 130);
	      back = 0;
	    }
	  }
	}
      }
      if(back) {
        if(!(job->ukoma)) {
	  if(dk3str_casecmp(dkT("de"), dk3app_get_language(job->app)) == 0) {
	    dk3app_log_1(job->app, DK3_LL_INFO, job->msg, 302);
	  }
	}
      }
      if(!(back)) {
        dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 132);
      }
    } else {			

#line 663 "itaconf.ctr"
    }
  } else {			

#line 665 "itaconf.ctr"
    /* ERROR: No configuration file found for processing! */
    dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 131);
  } 

#line 668 "itaconf.ctr"
  return back;
}

