/*
	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: pqdconf.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 pqdconf.c The pqdconf module.
*/


#line 10 "pqdconf.ctr"

#include "printqd.h"





#line 16 "pqdconf.ctr"


#if DK3_CHAR_SIZE == 1
#if DK3_HAVE_STRUCT_SOCKADDR_UN
#if DK3_HAVE_SIGSET
#if DK3_HAVE_GETPWNAM && DK3_HAVE_GETGRNAM

/**	Message texts for diagnostics.
*/
static dkChar const * const	pqdconf_messages[] = {
/* 0 */
"printqdc.str",

/* 1 */
"Not a limit value: \"",

/* 2 */
"\"!",

/* 3 */
"Alias already defined: \"",

/* 4 */
"\"!",

/* 5 */
"Printer already defined: \"",

/* 6 */
"\"!",

/* 7 */
"Class already defined: \"",

/* 8 */
"\"!",

/* 9 */
"Missing class name!",

/* 10 */
"No argument allowed after section title!",

/* 11 */
"Illegal configuration section title: \"",

/* 12 */
"\"!",

/* 13 */
"Closing bracket is missing!",

/* 14 */
"Printer already assigned to a class!",

/* 15 */
"No such class: \"",

/* 16 */
"\"!",

/* 17 */
"Illegal configuration key: \"",

/* 18 */
"\"!",

/* 19 */
"Limit for group \"",

/* 20 */
"\" already defined!",

/* 21 */
"Limit must be specified as name:limit!",

/* 22 */
"Limit for user \"",

/* 23 */
"\" already defined!",

/* 24 */
"Illegal deny action: \"",

/* 25 */
"\"! Must be \"hold\" or \"remove\"!",

/* 26 */
"Database file name already defined!",

/* 27 */
"Socket file name already defined!",

/* 28 */
"Info port already defined!",

/* 29 */
"Range overflow in port number: \"",

/* 30 */
"\"! Must be 65535 or less!",

/* 31 */
"Not a number: \"",

/* 32 */
"\"!",

/* 33 */
"User account to run daemon is already defined!",

/* 34 */
"Group to run daemon is already defined!",

/* 35 */
"No such user: \"",

/* 36 */
"\"!",

/* 37 */
"No such group: \"",

/* 38 */
"\"!",

/* 39 */
"Missing value!",

/* 40 */
"Local state directory name too long: \"",

/* 41 */
"\"!",

/* 42 */
"Failed to find local state directory name!",

/* 43 */
"UNIX domain socket name too long: \"",

/* 44 */
"\"!",

NULL


#line 160 "pqdconf.ctr"
};




/**	Keywords used by the module.
*/
static char const * const	pqdconf_c8_kw[] = {
/* 0 */
"r",

/* 1 */
"unlimited",

/* 2 */
"deny",

/* 3 */
"/run/printqd/printqd.sock",

/* 4 */
"mem::",

/* 5 */
"ndbm::",

/* 6 */
"bdb::",

/* 7 */
"/printqd/printqd-db",

NULL


#line 202 "pqdconf.ctr"
};



/**	Keywords for deny actions.
*/
static char const * const	pqdconf_deny_actions[] = {
/* 0 */
"remove",

/* 1 */
"hold",

NULL


#line 215 "pqdconf.ctr"
};



/**	Secion type names.
*/
static char const * const	pqdconf_section_types[] = {
/* 0 */
"options",

/* 1 */
"class",

/* 2 */
"printer",

NULL


#line 227 "pqdconf.ctr"
};



/**	Keys in the options section.
*/
static char const * const	pqdconf_section_options[] = {
/* 0 */
"database",

/* 1 */
"socket",

/* 2 */
"info port",

/* 3 */
"info allow",

/* 4 */
"run as user",

/* 5 */
"run as group",

/* 6 */
"backlog",

/* 7 */
"info backlog",

NULL


#line 268 "pqdconf.ctr"
};



/**	Keys in a class section.
*/
static char const * const	pqdconf_section_class[] = {
/* 0 */
"default limit",

/* 1 */
"group limit",

/* 2 */
"user limit",

/* 3 */
"deny action",

NULL


#line 285 "pqdconf.ctr"
};



/**	Keys in a printer section.
*/
static char const * const	pqdconf_section_printer[] = {
/* 0 */
"class",

/* 1 */
"alias",

NULL


#line 298 "pqdconf.ctr"
};



dkChar const * const *
pqdconf_get_messages(dk3_app_t *app)
{
  dkChar const * const *back = NULL;
  if(app) {
    dk3app_messages(app, pqdconf_messages[0], pqdconf_messages);
  }
  return back;
}



/**	Destroy limit structure.
	@param	lp	Limit structure to destroy.
*/
static
void
pqdconf_limit_delete(pqd_limit_t *lp)
{
  

#line 322 "pqdconf.ctr"
  if(lp) {
    lp->limit = 0UL;	

#line 324 "pqdconf.ctr"
    dk3_release(lp->name)
    dk3_delete(lp);
  } 

#line 327 "pqdconf.ctr"
}



/**	Create a new limit structure.
	@param	name	User or group name.
	@param	val	Limit value.
	@param	app	Application structure for diagnostics.
	@return	Pointer to new limit structure on success, NULL on error.
*/
static
pqd_limit_t	*
pqdconf_limit_new(char const *name, unsigned long val, dk3_app_t *app)
{
  pqd_limit_t		*back = NULL;
  

#line 343 "pqdconf.ctr"
  if(name) {
    back = dk3_new_app(pqd_limit_t,1,app);
    if(back) {
      back->limit = val;
      back->name = dk3str_c8_dup_app(name, app);
      if(!(back->name)) {
        pqdconf_limit_delete(back);
	back = NULL;
      }
    }
  } 

#line 354 "pqdconf.ctr"
  return back;
}



/**	Compare two limit entries.
	@param	l	Left limit object.
	@param	r	Right limit object or user name.
	@param	cr	Comparison criteria (0=limit/limit by name,
	1=limit/name, 2=limit/limit by value largest first).
	@return	Comparison result.
*/
static
int
pqdconf_limit_compare(void *l, void *r, int cr)
{
  int		 back = 0;
  pqd_limit_t	*pl;
  pqd_limit_t	*pr;
  if(l) {
    if(r) {
      pl = (pqd_limit_t *)l;
      switch(cr) {
        case 2: {
	  pr = (pqd_limit_t *)r;
	  if(pl->limit > pr->limit) {
	    back = -1;
	  } else {
	    if(pl->limit < pr->limit) {
	      back = 1;
	    }
	  }
	} break;
	case 1: {
	  if(pl->name) {
	    back = strcmp(pl->name, (char *)r);
	    if(back < -1) back = -1;
	    if(back >  1) back =  1;
	  } else back = -1;
	} break;
	default: {
	  pr = (pqd_limit_t *)r;
	  if(pl->name) {
	    if(pr->name) {
	      back = strcmp(pl->name, pr->name);
	      if(back < -1) back = -1;
	      if(back >  1) back =  1;
	    } else back = 1;
	  } else {
	    if(pr->name) back = -1;
	  }
	} break;
      }
    } else back = 1;
  } else {
    if(r) back = -1;
  }
  return back;
}


/**	Delete class entry.
	@param	cp	Class entry to delete.
*/
static
void
pqdconf_class_delete(pqd_class_t *cp)
{
  pqd_limit_t	*lp;
  

#line 424 "pqdconf.ctr"
  if(cp) {	

#line 425 "pqdconf.ctr"
    dk3_release(cp->name)
    if(cp->s_u) {
      if(cp->i_u) {
        dk3sto_it_reset(cp->i_u);
	while(NULL != (lp = (pqd_limit_t *)dk3sto_it_next(cp->i_u))) {
	  pqdconf_limit_delete(lp);
	}
	dk3sto_it_close(cp->i_u);
      }
      dk3sto_close(cp->s_u);
    } cp->s_u = NULL; cp->i_u = NULL;
    if(cp->s_g) {
      if(cp->i_g) {
        dk3sto_it_reset(cp->i_g);
	while(NULL != (lp = (pqd_limit_t *)dk3sto_it_next(cp->i_g))) {
	  pqdconf_limit_delete(lp);
	}
	dk3sto_it_close(cp->i_g);
      }
      dk3sto_close(cp->s_g);
    } cp->s_g = NULL; cp->i_g = NULL;
    cp->dl = 0UL;
    cp->da = 0;
    dk3_delete(cp)
  } 

#line 450 "pqdconf.ctr"
}



/**	Create new printer class.
	@param	name	Class name.
	@param	app	Application structure for diagnostics.
	@return	Pointer to new class on success, NULL on error.
*/
static
pqd_class_t *
pqdconf_class_new(char const *name, dk3_app_t *app)
{
  pqd_class_t		*back	= NULL;
  int			 ok	= 0;
  

#line 466 "pqdconf.ctr"
  if(name) {
    back = dk3_new_app(pqd_class_t,1,app);
    if(back) {
      back->s_u = NULL;
      back->i_u = NULL;
      back->s_g = NULL;
      back->i_g = NULL;
      back->dl  = DK3_UL_MAX; /* Default is unlimited printing + accounting. */
      back->da  = 0;
      back->name = dk3str_c8_dup_app(name, app);
      if(back->name) {
        back->s_u = dk3sto_open_app(app);
	if(back->s_u) {
	  dk3sto_set_comp(back->s_u, pqdconf_limit_compare, 0);
	  back->i_u = dk3sto_it_open(back->s_u);
	  if(back->i_u) {
	    back->s_g = dk3sto_open_app(app);
	    if(back->s_g) {
	      dk3sto_set_comp(back->s_g, pqdconf_limit_compare, 2);
	      back->i_g = dk3sto_it_open(back->s_g);
	      if(back->i_g) {
	        ok = 1;
	      }
	    }
	  }
	}
      }
      if(!(ok)) {
        pqdconf_class_delete(back);
	back = NULL;
      }
    }
  } 

#line 499 "pqdconf.ctr"
  return back;
}



/**	Compare two class entries.
	@param	l	Left class object.
	@param	r	Right class object.
	@param	cr	Comparison criteria (0=class/class, 1=class/name).
	@return	Comparison result.
*/
static
int
pqdconf_class_compare(void *l, void *r, int cr)
{
  int		 back	= 0;
  pqd_class_t	*pl;
  pqd_class_t	*pr;
  if(l) {
    if(r) {
      pl = (pqd_class_t *)l;
      switch(cr) {
        case 1: {
	  if(pl->name) {
	    back = dk3str_c8_cmp(pl->name, (char *)r);
	    if(back < -1) back = -1;
	    if(back >  1) back =  1;
	  } else back = -1;
	} break;
	default: {
	  pr = (pqd_class_t *)r;
	  if(pl->name) {
	    if(pr->name) {
	      back = dk3str_c8_cmp(pl->name, pr->name);
	      if(back < -1) back = -1;
	      if(back >  1) back =  1;
	    } else back = 1;
	  } else {
	    if(pr->name) back = -1;
	  }
	} break;
      }
    } else back = 1;
  } else {
    if(r) back = -1;
  }
  return back;
}



/**	Delete printer entry.
	@param	pp	Printer to delete.
*/
static
void
pqdconf_printer_delete(pqd_printer_t *pp)
{
  

#line 558 "pqdconf.ctr"
  if(pp) {
    pp->cl = NULL; 

#line 560 "pqdconf.ctr"
    dk3_release(pp->name)
    dk3_delete(pp)
  } 

#line 563 "pqdconf.ctr"
}



/**	Create new printer entry.
	@param	name	Printer name.
	@param	app	Application structure for diagnostics.
	@return	Pointer to new printer entry on success, NULL on error.
*/
static
pqd_printer_t	*
pqdconf_printer_new(char const *name, dk3_app_t *app)
{
  pqd_printer_t		*back	= NULL;
  

#line 578 "pqdconf.ctr"
  if(name) {
    back = dk3_new_app(pqd_printer_t,1,app);
    if(back) {
      back->cl = NULL;
      back->name = dk3str_c8_dup_app(name, app);
      if(!(back->name)) {
        pqdconf_printer_delete(back);
	back = NULL;
      }
    }
  } 

#line 589 "pqdconf.ctr"
  return  back;
}



/**	Compare two printer entries.
	@param	l	Left printer entry.
	@param	r	Printer entry or name.
	@param	cr	Comparison criteria (0=printer/printer, 1=printer/name).
	@return	Comparison result.
*/
static
int
pqdconf_printer_compare(void *l, void *r, int cr)
{
  int		 back	= 0;
  pqd_printer_t	*pl;
  pqd_printer_t	*pr;
  if(l) {
    if(r) {
      pl = (pqd_printer_t *)l;
      switch(cr) {
        case 1: {
	  if(pl->name) {
	    back = dk3str_c8_cmp(pl->name, (char *)r);
	    if(back < -1) back = -1;
	    if(back >  1) back =  1;
	  } else back = -1;
	} break;
	default: {
	  pr = (pqd_printer_t *)r;
	  if(pl->name) {
	    if(pr->name) {
	      back = dk3str_c8_cmp(pl->name, pr->name);
	      if(back < -1) back = -1;
	      if(back >  1) back =  1;
	    } else back = 1;
	  } else {
	    if(pr->name) back = -1;
	  }
	} break;
      }
    } else back = 1;
  } else {
    if(r) back = -1;
  }
  return back;
}



/**	Delete alias entry.
	@param	ap	Alias to delete.
*/
static
void
pqdconf_alias_delete(pqd_alias_t *ap)
{
  

#line 648 "pqdconf.ctr"
  if(ap) {
    ap->pr = NULL;	

#line 650 "pqdconf.ctr"
    dk3_release(ap->name)
    dk3_delete(ap)
  } 

#line 653 "pqdconf.ctr"
}



/**	Create alias entry.
	@param	name	Alias name for printer.
	@param	pr	Printer entry.
	@param	app	Application structure for diagnostics.
	@return	Pointer no new alias entry on success, NULL on error.
*/
static
pqd_alias_t	*
pqdconf_alias_new(char const *name, pqd_printer_t *pr, dk3_app_t *app)
{
  pqd_alias_t		*back	= NULL;
  

#line 669 "pqdconf.ctr"
  if((name) && (pr)) {
    back = dk3_new_app(pqd_alias_t,1,app);
    if(back) {
      back->pr = pr;
      back->name = dk3str_c8_dup_app(name, app);
      if(!(back->name)) {
        pqdconf_alias_delete(back);
	back = NULL;
      }
    }
  } 

#line 680 "pqdconf.ctr"
  return back;
}



/**	Compare two alias entries.
	@param	l	Left alias object.
	@param	r	Right alias object or name.
	@param	cr	Comparison criteria (0=alias/alias, 1=alias/name).
	@return	Comparison result.
*/
static
int
pqdconf_alias_compare(void *l, void *r, int cr)
{
  int			 back	= 0;
  pqd_alias_t	*pl;
  pqd_alias_t	*pr;
  if(l) {
    if(r) {
      pl = (pqd_alias_t*)l;
      switch(cr) {
        case 1: {
	  if(pl->name) {
	    back = dk3str_c8_cmp(pl->name, (char *)r);
	    if(back < -1) back = -1;
	    if(back >  1) back =  1;
	  } else back = -1;
	} break;
	default: {
	  pr = (pqd_alias_t *)r;
	  if(pl->name) {
	    if(pr->name) {
	      back = dk3str_c8_cmp(pl->name, pr->name);
	      if(back < -1) back = -1;
	      if(back >  1) back =  1;
	    } else back = 1;
	  } else {
	    if(pr->name) back = -1;
	  }
	} break;
      }
    } else back = 1;
  } else {
    if(r) back = -1;
  }
  return back;
}



/**	Delete data for allowed peer.
	@param	pp	Peer to delete.
*/
static
void
pqdconf_peer_delete(dk3_peer_allowed_t *pp)
{
  

#line 739 "pqdconf.ctr"
  dk3_release(pp)
  

#line 741 "pqdconf.ctr"
}



/**	Create data for allowed peer.
	@param	src	Allowed peer (data source).
	@param	app	Application structure for diagnostics.
	@return	Pointer to new structure on success, NULL on error.
*/
static
dk3_peer_allowed_t *
pqdconf_peer_new(dk3_peer_allowed_t *src, dk3_app_t *app)
{
  dk3_peer_allowed_t	*back;
  

#line 756 "pqdconf.ctr"
  if(src) {
    back = dk3_new_app(dk3_peer_allowed_t,1,app);
    if(back) {
      dk3mem_cpy((void *)back, (void *)src, sizeof(dk3_peer_allowed_t));
    }
  } 

#line 762 "pqdconf.ctr"
  return back;
}



/**	Initialize configuration before reading configuration file.
	@param	cfg	Configuration to initialize.
*/
static
void
pqdconf_init(pqd_conf_t *cfg)
{
  

#line 775 "pqdconf.ctr"
  dk3mem_res((void *)cfg, sizeof(pqd_conf_t));
  cfg->usn = NULL; cfg->dbn = NULL;
  cfg->s_c = NULL; cfg->i_c = NULL;
  cfg->s_p = NULL; cfg->i_p = NULL;
  cfg->s_a = NULL; cfg->i_a = NULL;
  cfg->s_i = NULL; cfg->i_i = NULL;
  cfg->uid = (uid_t)0; cfg->gid = (gid_t)0;
  cfg->port = 0; 
  cfg->ubl = 5; cfg->ibl = 5;
  

#line 785 "pqdconf.ctr"
}



/**	Prepare a configuration structure to read a configuration file.
	@param	cfg	Configuration to prepare.
	@param	type	Type of caller program.
	@param	app	Application structure for diagnostics.
	@param	cmsg	Localized messages related to configuration.
	@return	1 on success, 0 on error.
*/
static
int
pqdconf_prepare(
  pqd_conf_t 		*cfg,
  int			 type,
  dk3_app_t 		*app,
  dkChar const * const	*cmsg
)
{
  int		 back = 1;
  

#line 807 "pqdconf.ctr"
  switch(type) {
    case PQD_PROGRAM_TYPE_DAEMON: {
      back = 0;
      cfg->s_c = dk3sto_open_app(app);
      if(cfg->s_c) {
	dk3sto_set_comp(cfg->s_c, pqdconf_class_compare, 0);
        cfg->i_c = dk3sto_it_open(cfg->s_c);
	if(cfg->i_c) {
	  cfg->s_p = dk3sto_open_app(app);
	  if(cfg->s_p) {
	    dk3sto_set_comp(cfg->s_p, pqdconf_printer_compare, 0);
	    cfg->i_p = dk3sto_it_open(cfg->s_p);
	    if(cfg->i_p) {
	      cfg->s_a = dk3sto_open_app(app);
	      if(cfg->s_a) {
		dk3sto_set_comp(cfg->s_a, pqdconf_alias_compare, 0);
	        cfg->i_a = dk3sto_it_open(cfg->s_a);
		if(cfg->i_a) {
		  back = 1;
		}
	      }
	    }
	  }
	}
      }
      if(!(back)) {
        /* ERROR: MEMORY */
      }
    } break;
    case PQD_PROGRAM_TYPE_INFO: {
      back = 0;
      cfg->s_i = dk3sto_open_app(app);
      if(cfg->s_i) {
        dk3sto_set_comp(cfg->s_i, dk3socket_compare_peer, 0);
        cfg->i_i = dk3sto_it_open(cfg->s_i);
        if(cfg->i_i) {
          back = 1;
        }
      }
      if(!(back)) {
        /* ERROR: Memory */
      }
    } break;
  } 

#line 851 "pqdconf.ctr"
  return back;
}



/**	Check whether or not an alias already exists.
	@param	cfg	Configuration structure.
	@param	aln	Alias name to test.
	@param	app	Application structure for diagnostics.
	@return	1 if alias already exists, 0 if it does not yet exist.
*/
static
int
pqdconf_check_alias_name(
  pqd_conf_t		*cfg,
  char const		*aln,
  dk3_app_t		*app
)
{
  int			 back = 0;
  

#line 872 "pqdconf.ctr"
  if(dk3sto_it_find_like(cfg->i_a, (void *)aln, 1)) {
    back = 1;
  } 

#line 875 "pqdconf.ctr"
  return back;
}



/**	Check whether or not a printer already exists.
	@param	cfg	Configuration structure.
	@param	prn	Printer name to test.
	@param	app	Application structure for diagnostics.
	@return	1 if printer already exists, 0 if it does not yet exist.
*/
static
int
pqdconf_check_printer_name(
  pqd_conf_t		*cfg,
  char const		*prn,
  dk3_app_t		*app
)
{
  pqd_printer_t *lp;
  int			 back = 0;
  

#line 897 "pqdconf.ctr"
  lp = (pqd_printer_t *)dk3sto_it_find_like(cfg->i_p, (void *)prn, 1);
  if(lp) {		

#line 899 "pqdconf.ctr"
    back = 1;
  } 

#line 901 "pqdconf.ctr"
  return back;
}



/**	Check whether a limit for the specified group was already found.
	@param	i_glim	Iterator through group limits storage.
	@param	name	Group name to check.
	@return	1 for found, 0 for not found.
*/
static
int
pqdconf_check_group_limit(
  dk3_sto_it_t		*i_glim,
  char const		*name
)
{
  pqd_limit_t		*pl;
  int			 back = 0;
  

#line 921 "pqdconf.ctr"
  dk3sto_it_reset(i_glim);
  while((NULL != (pl = (pqd_limit_t *)dk3sto_it_next(i_glim))) && (0 == back)) {
    if(strcmp(pl->name, name) == 0) {
      back = 1;
    }
  } 

#line 927 "pqdconf.ctr"
  return back;
}



/**	Find limit value.
	@param	ulp	Pointer to destination variable.
	@param	str	Source text.
	@param	app	Application structure for diagnostics.
	@param	cmsg	Localized messages related to configuration.
	@return	1 on success, 0 on error.
*/
static
int
pqdconf_get_limit_value(
  unsigned long		*ulp,
  char const		*str,
  dk3_app_t		*app,
  char const * const	*cmsg
)
{
  unsigned long		 ul;
  int			 back = 0;
  

#line 951 "pqdconf.ctr"
  if(strcmp(pqdconf_c8_kw[1], str) == 0) {
    *ulp = ul = DK3_UL_MAX;
    back = 1;
  } else {
    if(strcmp(pqdconf_c8_kw[2], str) == 0) {
      *ulp = ul = 0UL;
      back = 1;
    } else {
      if(1 == sscanf(str, "%lu", &ul)) {
        *ulp = ul;
	back = 1;
      } else {
        ul = 0UL;
        /* ERROR: Not a limit value! */
	dk3app_log_3(app, DK3_LL_ERROR, cmsg, 1, 2, str);
      }
    }
  } 

#line 969 "pqdconf.ctr"
  return back;
}



int
pqdconf_read(
  pqd_conf_t 		*cfg, 
  char const		*fn,
  int			 type,
  dk3_app_t		*app,
  dkChar const * const	*cmsg
)
{
  char		 bu[PQD_CONFIG_BUFFER_SIZE];	/* Line buffer to read file. */
  dk3_peer_allowed_t	peer;			/* Allowed peer. */
  dk3_peer_allowed_t	*np;			/* New peer. */
  FILE		*fipo;				/* Input file. */
  char		*p1;				/* Start of line. */
  char		*p2;				/* Start of value. */
  char		*p3;				/* Second part of value. */
  pqd_class_t	*pc;				/* Current class. */
  struct passwd	*pw;				/* Run as user. */
  struct group	*gr;				/* Run as group. */
  pqd_printer_t	*pp;				/* Current printer. */
  pqd_alias_t	*pa;				/* Current alias. */
  pqd_limit_t	*pl;				/* New limit. */
  char const	*oldsrcfile;			/* Old source file name. */
  unsigned long	 ul;				/* Result from sscanf. */
  unsigned long	 oldsrcline;			/* Old source file line. */
  unsigned long	 lineno = 0UL;			/* Current line number. */
  int		 cc;				/* Flag: Can continue. */
  int		 st;				/* Section type. */
  int		 act;				/* Action to take. */
  int		 back = 0;
  

#line 1005 "pqdconf.ctr"
  oldsrcfile = dk3app_get_source_file(app);
  oldsrcline = dk3app_get_source_line(app);
  dk3app_set_source_file(app, fn);
  dk3app_set_source_line(app, 0UL);
  pqdconf_init(cfg);
  if(pqdconf_prepare(cfg, type, app, cmsg)) {		

#line 1011 "pqdconf.ctr"
    fipo = dk3sf_fopen_app(fn, pqdconf_c8_kw[0], app);
    if(fipo) {						

#line 1013 "pqdconf.ctr"
      back = 1;
      st = 0;
      pp = NULL; pc = NULL;
      do {
        cc = 0;
	if(fgets(bu, sizeof(bu), fipo)) {
	  lineno++;
	  dk3app_set_source_line(app, lineno);
	  cc = 1;
	  dk3str_c8_delnl(bu);				

#line 1023 "pqdconf.ctr"
	  p1 = dk3str_c8_start(bu, NULL);
	  if(p1) {
	    switch(*p1) {
	      case '#': {				

#line 1027 "pqdconf.ctr"
	        /* Comments are always ok. */
	      } break;
	      case '[': {				

#line 1030 "pqdconf.ctr"
	        pp = NULL;
		pc = NULL;
		st = -1;
	        p2 = dk3str_c8_chr(p1, ']');
		if(p2) {
		  p1++;
		  *p2 = '\0';
		  p2 = dk3str_c8_next(p1, NULL);	

#line 1038 "pqdconf.ctr"
		  st = dk3str_c8_array_index(
		    pqdconf_section_types, p1, 0
		  );
		  switch(st) {
		    case 2: {
		      switch(type) {
		        case PQD_PROGRAM_TYPE_DAEMON: {
		          if(p2) {
			    if(pqdconf_check_alias_name(cfg, p2, app)) {
			      back = 0;		

#line 1048 "pqdconf.ctr"
			      /* ERROR: Alias already exists! */
			      dk3app_log_3(app, DK3_LL_ERROR, cmsg, 3, 4, p2);
			    } else {
			      pp = (pqd_printer_t *)dk3sto_it_find_like(
			        cfg->i_p, p2, 1
			      );
			      if(pp) {
			        back = 0;	

#line 1056 "pqdconf.ctr"
			        /* ERROR: Printer already defined! */
				dk3app_log_3(app, DK3_LL_ERROR, cmsg, 5, 6, p2);
				pp = NULL;
			      } else {
			        pp = pqdconf_printer_new(p2, app);
			        if(pp) {
			          if(!dk3sto_add(cfg->s_p, (void *)pp)) {
				    back = 0;	

#line 1064 "pqdconf.ctr"
				    pqdconf_printer_delete(pp);
				    pp = NULL;
				  }
			        } else {	

#line 1068 "pqdconf.ctr"
			          back = 0;	/* ERROR: Memory */
			        }
			      }
			      if(!(pp)) {	

#line 1072 "pqdconf.ctr"
			        back = 0;
			      }
			    }
			  } else {
		            back = 0;		

#line 1077 "pqdconf.ctr"
		            /* ERROR: Syntax, argument required! */
			    dk3app_log_1(app, DK3_LL_ERROR, cmsg, 38);
		          }
		        } break;
		      }
		    } break;
		    case 1: {
		      switch(type) {
		        case PQD_PROGRAM_TYPE_DAEMON: {
		          if(p2) {
			    pc = (pqd_class_t *)dk3sto_it_find_like(
			      cfg->i_c, p2, 1
			    );
			    if(pc) {
			      back = 0;		

#line 1092 "pqdconf.ctr"
			      /* ERROR: Class already defined! */
			      dk3app_log_3(app, DK3_LL_ERROR, cmsg, 7, 8, p2);
			      pc = NULL;
			    } else {
			      pc = pqdconf_class_new(p2, app);
			      if(pc) {
			        if(!dk3sto_add(cfg->s_c, (void *)pc)) {
				  back = 0;	

#line 1100 "pqdconf.ctr"
				  pqdconf_class_delete(pc);
				  pc = NULL;
				}
			      } else {		

#line 1104 "pqdconf.ctr"
			        back = 0;	/* ERROR: Memory */
			      }
			    }
			    if(!(pc)) {		

#line 1108 "pqdconf.ctr"
			      back = 0;
			    }
		          } else {
		            back = 0;		

#line 1112 "pqdconf.ctr"
			    /* ERROR: Syntax, argument required! */
			    dk3app_log_1(app, DK3_LL_ERROR, cmsg, 9);
		          }
		        } break;
		      }
		    } break;
		    case 0: {
		      if(p2) {
		        back = 0;		

#line 1121 "pqdconf.ctr"
			/* ERROR: Syntax, no argument allowed! */
			dk3app_log_1(app, DK3_LL_ERROR, cmsg, 10);
		      }
		    } break;
		    default: {			

#line 1126 "pqdconf.ctr"
		      back = 0;
		      /* ERROR: Illegal configuration section name! */
		      dk3app_log_3(app, DK3_LL_ERROR, cmsg, 11, 12, p1);
		    } break;
		  }
		} else {		

#line 1132 "pqdconf.ctr"
		  /* ERROR: Closing bracket is missing */
		  dk3app_log_1(app, DK3_LL_ERROR, cmsg, 13);
		}
	      } break;
	      default: {				

#line 1137 "pqdconf.ctr"
	        p2 = dk3str_c8_chr(p1, '=');
		if(p2) {
		  *(p2++) = '\0';
		  p2 = dk3str_c8_start(p2, NULL);
		  if(p2) {
		    dk3str_c8_normalize(p1, NULL, ' ');
		    switch(st) {
		      case 2: {		/* Configure current printer. */
		        if(PQD_PROGRAM_TYPE_DAEMON == type) {
			  if(pp) {		

#line 1147 "pqdconf.ctr"
			    act = dk3str_c8_array_index(
			      pqdconf_section_printer, p1, 0
			    );
			    switch(act) {
			      case 0: {		

#line 1152 "pqdconf.ctr"
			        if(pp->cl) {	

#line 1153 "pqdconf.ctr"
				  back = 0;
				  /* ERROR: Already configured! */
				  dk3app_log_1(app, DK3_LL_ERROR, cmsg, 14);
				} else {
			          pc = (pqd_class_t *)dk3sto_it_find_like(
				    cfg->i_c, p2, 1
			          );
				  if(pc) {	

#line 1161 "pqdconf.ctr"
				    pp->cl = pc;
				    pc = NULL;
				  } else {	

#line 1164 "pqdconf.ctr"
				   back = 0;
				   /* ERROR: No such class! */
				   dk3app_log_3(app,DK3_LL_ERROR,cmsg,15,16,p2);
				  }
				}
			      } break;
			      case 1: {		

#line 1171 "pqdconf.ctr"
			        if(pqdconf_check_printer_name(cfg,p2,app)) {
				  back = 0;	

#line 1173 "pqdconf.ctr"
				  /* ERROR: Printer already exists! */
				  dk3app_log_3(app,DK3_LL_ERROR,cmsg,5,6,p2);
				} else {
				  if(pqdconf_check_alias_name(cfg,p2,app)) {
				    back = 0;	

#line 1178 "pqdconf.ctr"
				    /* ERROR: Alias already exists! */
				    dk3app_log_3(app,DK3_LL_ERROR,cmsg,3,4,p2);
				  } else {
			            pa = pqdconf_alias_new(p2, pp, app);
				    if(pa) {
				      if(!dk3sto_add(cfg->s_a, (void *)pa)) {
				        back = 0;	

#line 1185 "pqdconf.ctr"
				        pqdconf_alias_delete(pa);
				      }
				    } else {	

#line 1188 "pqdconf.ctr"
				      back = 0;	/* ERROR: Memory */
				    }
				    pa = NULL;
				  }
				}
			      } break;
			      default: {	

#line 1195 "pqdconf.ctr"
			        back = 0;
				/* ERROR: Unknown key! */
				dk3app_log_3(app,DK3_LL_ERROR,cmsg,17,18,p1);
			      } break;
			    }
			  }
			}
		      } break;
		      case 1: {		/* Configure current class. */
		        if(PQD_PROGRAM_TYPE_DAEMON == type) {
			  if(pc) {		

#line 1206 "pqdconf.ctr"
			    act = dk3str_c8_array_index(
			      pqdconf_section_class, p1, 0
			    );
			    switch(act) {
			      case 0: {	

#line 1211 "pqdconf.ctr"
				if(pqdconf_get_limit_value(&ul,p2,app,cmsg)) {
				  pc->dl = ul;	

#line 1213 "pqdconf.ctr"
				} else {
				  back = 0;	

#line 1215 "pqdconf.ctr"
				}
			      } break;
			      case 1: {	

#line 1218 "pqdconf.ctr"
			        p3 = dk3str_c8_chr(p2, ':');
				if(p3) {
				  *(p3++) = '\0';
			          if(pqdconf_check_group_limit(pc->i_g,p2)) {
				   back = 0;	

#line 1223 "pqdconf.ctr"
				   /* ERROR: Limit group already defined. */
				   dk3app_log_3(app,DK3_LL_ERROR,cmsg,19,20,p2);
				  } else {
				    if(pqdconf_get_limit_value(&ul,p3,app,cmsg))
				    {
				      pl = pqdconf_limit_new(p2, ul, app);
				      if(pl) {		

#line 1230 "pqdconf.ctr"
				        if(!dk3sto_add(pc->s_g, (void *)pl))
					{		

#line 1232 "pqdconf.ctr"
					  back = 0;	/* ERROR: Memory. */
					  pqdconf_limit_delete(pl);
					}
				      } else {		

#line 1236 "pqdconf.ctr"
				        back = 0;	/* ERROR: Memory. */
				      }
				    } else {		

#line 1239 "pqdconf.ctr"
				      back = 0;
				    }
				  }
				} else {		

#line 1243 "pqdconf.ctr"
				  back = 0;
				  /* ERROR: Syntax */
				  dk3app_log_1(app, DK3_LL_ERROR, cmsg, 21);
				}
			      } break;
			      case 2: {	

#line 1249 "pqdconf.ctr"
			        p3 = dk3str_c8_chr(p2, ':');
				if(p3) {
				  *(p3++) = '\0';
			          if(dk3sto_it_find_like(pc->i_u,p2,1)) {
				   back = 0;		

#line 1254 "pqdconf.ctr"
				   /* ERROR: Limit for user already defined. */
				   dk3app_log_3(app,DK3_LL_ERROR,cmsg,22,23,p2);
				  } else {
				    if(pqdconf_get_limit_value(&ul,p3,app,cmsg))
				    {
				      pl = pqdconf_limit_new(p2, ul, app);
				      if(pl) {		

#line 1261 "pqdconf.ctr"
				        if(!dk3sto_add(pc->s_u, (void *)pl))
					{		

#line 1263 "pqdconf.ctr"
					  back = 0;	/* ERROR: Memory! */
					  pqdconf_limit_delete(pl);
					}
				      } else {		

#line 1267 "pqdconf.ctr"
				        back = 0;	/* ERROR: Memory! */
				      }
				    } else {		

#line 1270 "pqdconf.ctr"
				      back = 0;	/* ERROR: Syntax! */
				    }
				  }
				} else {
				  back = 0;		

#line 1275 "pqdconf.ctr"
				  /* ERROR: Syntax! */
				  dk3app_log_1(app, DK3_LL_ERROR, cmsg, 21);
				}
			      } break;
			      case 3: {	

#line 1280 "pqdconf.ctr"
			        pc->da = dk3str_array_index(
				  pqdconf_deny_actions,
				  p2,
				  0
				);
				if(pc->da < 0) {	

#line 1286 "pqdconf.ctr"
				  back = 0;
				  /* ERROR: Syntax! */
				  dk3app_log_3(app,DK3_LL_ERROR,cmsg,24,25,p2);
				}
			      } break;
			      default: {		

#line 1292 "pqdconf.ctr"
			        back = 0;
			        /* ERROR: Unknown key */
				dk3app_log_3(app,DK3_LL_ERROR,cmsg,17,18,p1);
			      } break;
			    }
			  }
			}
		      } break;
		      case 0: {		/* Configure options. */
		        act = dk3str_c8_array_index(
			  pqdconf_section_options, p1, 0
			);
			switch(act) {
			  case 0: {	/* database */
			    switch(type) {
			      case PQD_PROGRAM_TYPE_DAEMON: {	

#line 1308 "pqdconf.ctr"
			        if(cfg->dbn) {
				  back = 0;		

#line 1310 "pqdconf.ctr"
				  /* ERROR: Database already defined! */
				  dk3app_log_1(app, DK3_LL_ERROR, cmsg, 26);
				} else {
				  dk3str_c8_normalize(p2, NULL, ' ');
				  cfg->dbn = dk3str_c8_dup_app(p2, app);
				  if(!(cfg->dbn)) {		

#line 1316 "pqdconf.ctr"
				    back = 0;	/* ERROR: Memory */
				  }
				}
			      } break;
			    }
			  } break;
			  case 1: {	/* socket */
			    switch(type) {
			      case PQD_PROGRAM_TYPE_DAEMON:
			      case PQD_PROGRAM_TYPE_MULTIPLEXOR:
			      case PQD_PROGRAM_TYPE_ADMIN:
			      case PQD_PROGRAM_TYPE_INFO: {	

#line 1328 "pqdconf.ctr"
				if(cfg->usn) {
				  back = 0;		

#line 1330 "pqdconf.ctr"
				  /* ERROR: Socket already defined! */
				  dk3app_log_1(app, DK3_LL_ERROR, cmsg, 27);
				} else {
				  dk3str_c8_normalize(p2, NULL, ' ');
				  cfg->usn = dk3str_c8_dup_app(p2, app);
				  if(!(cfg->usn)) {	

#line 1336 "pqdconf.ctr"
				    back = 0;	/* ERROR: MEMORY */
				  }
				}
			      } break;
			    }
			  } break;
			  case 2: {	/* info port */
			    switch(type) {
			      case PQD_PROGRAM_TYPE_INFO: {	

#line 1345 "pqdconf.ctr"
			        if(cfg->port) {
				  back = 0;		

#line 1347 "pqdconf.ctr"
				  /* ERROR: Port already defined! */
				  dk3app_log_1(app, DK3_LL_ERROR, cmsg, 28);
				} else {
				  unsigned u;
				  if(1 == sscanf(p2, "%u", &u)) {
				    cfg->port = (unsigned short)u;
				    if(u != (unsigned)(cfg->port)) {
				      back = 0;			

#line 1355 "pqdconf.ctr"
				      /* ERROR: Range overflow! */
				      dk3app_log_3(
				        app,DK3_LL_ERROR,cmsg,29,30,p2
				      );
				    }
				  } else {			

#line 1361 "pqdconf.ctr"
				   back = 0;
				   /* ERROR: Not a number! */
				   dk3app_log_3(app,DK3_LL_ERROR,cmsg,30,31,p2);
				  }
				}
			      } break;
			    }
			  } break;
			  case 3: {	/* info allow */
			    switch(type) {
			      case PQD_PROGRAM_TYPE_INFO: {	

#line 1372 "pqdconf.ctr"
				if(dk3socket_set_peer(&peer, p2, NULL, app)) {
				  np = pqdconf_peer_new(&peer, app);
				  if(np) {
				    if(!dk3sto_add(cfg->s_i, (void *)np)) {
				      back = 0;	

#line 1377 "pqdconf.ctr"
				      dk3_delete(np)
				    }
				  } else {	

#line 1380 "pqdconf.ctr"
				    back = 0;	/* ERROR: Memory */
				  }
				} else {	

#line 1383 "pqdconf.ctr"
				  back = 0;	/* ERROR: Not a valid peer! */
				}
			      } break;
			    }
			  } break;
			  case 4: {	/* run as user */
			    switch(type) {
			      case PQD_PROGRAM_TYPE_DAEMON: {	

#line 1391 "pqdconf.ctr"
			        if(cfg->uid) {
				  back = 0;		

#line 1393 "pqdconf.ctr"
				  /* ERROR: Already defined! */
				  dk3app_log_1(app, DK3_LL_ERROR, cmsg, 32);
				} else {
				  pw = getpwnam(p2);
				  if(pw) {
				    cfg->uid = pw->pw_uid;
				  } else {		

#line 1400 "pqdconf.ctr"
				   back = 0;
				   /* ERROR: No such user! */
				   dk3app_log_3(app,DK3_LL_ERROR,cmsg,34,35,p2);
				  }
				}
			      } break;
			    }
			  } break;
			  case 5: {	/* run as group */
			    switch(type) {
			      case PQD_PROGRAM_TYPE_DAEMON: {	

#line 1411 "pqdconf.ctr"
			        if(cfg->gid) {
				  back = 0;		

#line 1413 "pqdconf.ctr"
				  dk3app_log_1(app, DK3_LL_ERROR, cmsg, 33);
				} else {
				  gr = getgrnam(p2);
				  if(gr) {
				    cfg->gid = gr->gr_gid;
				  } else {		

#line 1419 "pqdconf.ctr"
				   back = 0;
				   /* ERROR: No such group! */
				   dk3app_log_3(app,DK3_LL_ERROR,cmsg,36,37,p2);
				  }
				}
			      } break;
			    }
			  } break;
			  case 6: case 7: {	

#line 1428 "pqdconf.ctr"
			    int i;
			    if(p2) {
			      if(1 == sscanf(p2, "%d", &i)) {
			        if(i > 0) {
				  if(7 == act) {
				    cfg->ibl = i;
				  } else {
				    cfg->ubl = i;
				  }
				}
			      }
			    }
			  } break;
			  default: {			

#line 1442 "pqdconf.ctr"
			    back = 0;
			    /* ERROR: Unknown key! */
			    dk3app_log_3(app, DK3_LL_ERROR, cmsg, 17, 18, p1);
			  } break;
			}
		      } break;
		    }
		  } else {				

#line 1450 "pqdconf.ctr"
		    back = 0;
		    /* ERROR: Missing value! */
		    dk3app_log_1(app, DK3_LL_ERROR, cmsg, 38);
		  }
		} else {				

#line 1455 "pqdconf.ctr"
		  back = 0;
		  /* ERROR: Missing value! */
		  dk3app_log_1(app, DK3_LL_ERROR, cmsg, 38);
		}
	      } break;
	    }
	  } else {					

#line 1462 "pqdconf.ctr"
	  }						

#line 1463 "pqdconf.ctr"
	}
      } while((back == 1) && (cc == 1));
      fclose(fipo);
    } else {						

#line 1467 "pqdconf.ctr"
    }
  } else {						

#line 1469 "pqdconf.ctr"
  }
  dk3app_set_source_file(app, oldsrcfile);
  dk3app_set_source_line(app, oldsrcline);
  

#line 1473 "pqdconf.ctr"
  return back;
}



void
pqdconf_cleanup(pqd_conf_t *cfg)
{
  pqd_class_t		*pcl;
  pqd_printer_t		*ppr;
  pqd_alias_t		*pal;
  dk3_peer_allowed_t	*ppeer;
  

#line 1486 "pqdconf.ctr"
  

#line 1487 "pqdconf.ctr"
  if(cfg->s_c) {
    if(cfg->i_c) {
      dk3sto_it_reset(cfg->i_c);
      while(NULL != (pcl = (pqd_class_t *)dk3sto_it_next(cfg->i_c))) {
        pqdconf_class_delete(pcl);
      }
      dk3sto_it_close(cfg->i_c);
    }
    dk3sto_close(cfg->s_c);
  } cfg->s_c = NULL; cfg->i_c = NULL;
  

#line 1498 "pqdconf.ctr"
  if(cfg->s_p) {
    if(cfg->i_p) {
      dk3sto_it_reset(cfg->i_p);
      while(NULL != (ppr = (pqd_printer_t *)dk3sto_it_next(cfg->i_p))) {
        pqdconf_printer_delete(ppr);
      }
      dk3sto_it_close(cfg->i_p);
    }
    dk3sto_close(cfg->s_p);
  } cfg->s_p = NULL; cfg->i_p = NULL;
  

#line 1509 "pqdconf.ctr"
  if(cfg->s_a) {
    if(cfg->i_a) {
      dk3sto_it_reset(cfg->i_a);
      while(NULL != (pal = (pqd_alias_t *)dk3sto_it_next(cfg->i_a))) {
        pqdconf_alias_delete(pal);
      }
      dk3sto_it_close(cfg->i_a);
    }
    dk3sto_close(cfg->s_a);
  } cfg->s_a = NULL; cfg->i_a = NULL;
  

#line 1520 "pqdconf.ctr"
  if(cfg->s_i) {
    if(cfg->i_i) {
      dk3sto_it_reset(cfg->i_i);
      while(NULL != (ppeer=(dk3_peer_allowed_t *)dk3sto_it_next(cfg->i_i))) {
        pqdconf_peer_delete(ppeer);
      }
      dk3sto_it_close(cfg->i_i);
    }
    dk3sto_close(cfg->s_i);
  } cfg->s_i = NULL; cfg->i_i = NULL;
  

#line 1531 "pqdconf.ctr"
  if(cfg->usn) {		

#line 1532 "pqdconf.ctr"
    dk3_release(cfg->usn)
  }
  cfg->usn = NULL;
  

#line 1536 "pqdconf.ctr"
  if(cfg->dbn) {		

#line 1537 "pqdconf.ctr"
    dk3_release(cfg->dbn)
  } cfg->dbn = NULL;
  cfg->port = 0;		

#line 1540 "pqdconf.ctr"
}



int
pqdconf_check(
  pqd_conf_t		*cfg,
  int			 type,
  dk3_app_t		*app,
  dkChar const * const	*cmsg
)
{
  char		 bu[DK3_MAX_PATH];
  char const	*p1;
  int		 back = 0;
  

#line 1556 "pqdconf.ctr"
  if(cfg->ubl < 5) { cfg->ubl = 5; }
  if(cfg->ibl < 5) { cfg->ibl = 5; }
  if(!(cfg->usn)) {
    p1 = dk3inst_get_directory(3);
    if(p1) {
      if(strlen(p1) < sizeof(bu)) {
        strcpy(bu, p1);
	p1 = pqdconf_c8_kw[3];
	if((strlen(bu) + strlen(p1)) < sizeof(bu)) {
	  strcat(bu, p1);
	  cfg->usn = dk3str_c8_dup_app(bu, app);
	} else {
	  /* ERROR: Local state directory too long! */
	  dk3app_log_3(app, DK3_LL_ERROR, cmsg, 39, 40, p1);
	}
      } else {
        /* ERROR: Local state directory too long! */
	dk3app_log_3(app, DK3_LL_ERROR, cmsg, 39, 40, p1);
      }
    } else {
      /* ERROR: Failed to find local state directory */
      dk3app_log_1(app, DK3_LL_ERROR, cmsg, 41);
    }
  }
  if(PQD_PROGRAM_TYPE_DAEMON == type) {
    if(!(cfg->dbn)) {
      p1 = pqdconf_c8_kw[4];
      if(dk3dbi_type_supported(DK3_DB_TYPE_NDBM)) {
        p1 = pqdconf_c8_kw[5];
      }
      if(dk3dbi_type_supported(DK3_DB_TYPE_BDB)) {
        p1 = pqdconf_c8_kw[6];
      }
      strcpy(bu, p1);
      p1 = dk3inst_get_directory(3);
      if(p1) {
        if((strlen(bu) + strlen(p1)) < sizeof(bu)) {
	  strcat(bu, p1);
	  p1 = pqdconf_c8_kw[7];
	  if((strlen(bu) + strlen(p1)) < sizeof(bu)) {
	    strcat(bu, p1);
	    cfg->dbn = dk3str_c8_dup_app(bu, app);
	  } else {
	    /* ERROR: Local state directory too long! */
	    dk3app_log_3(app, DK3_LL_ERROR, cmsg, 39, 40, p1);
	  }
	} else {
	  /* ERROR: Local state directory too long! */
	  dk3app_log_3(app, DK3_LL_ERROR, cmsg, 39, 40, p1);
	}
      } else {
        /* ERROR: Failed to find local state directory */
	dk3app_log_1(app, DK3_LL_ERROR, cmsg, 41);
      }
    }
  }
  if(cfg->usn) {
    if(strlen(cfg->usn) < 108) {
      back = 1;
      switch(type) {
        case PQD_PROGRAM_TYPE_DAEMON: {
          back = 0;
	  if(cfg->dbn) {
	    back = 1;
	  }
        } break;
        case PQD_PROGRAM_TYPE_INFO: {
          if(!(cfg->port)) {
	    cfg->port = PRINTQD_DEFAULT_PORT;
	  }
        } break;
      }
    } else {
      /* ERROR: Socket name too long! */
      dk3app_log_3(app, DK3_LL_ERROR, cmsg, 42, 43, cfg->usn);
    }
  }
  

#line 1634 "pqdconf.ctr"
  return back;
}

#endif
#endif
#endif
#endif

