/* libemfw.h */

/* Copyright 1997-2000 by Eberhard Mattes <em-gw@windhager.de>
   Donated to the public domain.  No warranty.

   1997-01-04 Initial version
   1997-04-05 Reorganize library
   1997-07-22 Add config_int()
   1997-07-24 Include "libemcommon.h", protect against multiple inclusion
   1997-07-27 Add ASSERT, add Cfg hack
   1997-07-31 ASSERT->DEBUG_ASSERT, add ALWAYS_ASSERT, add do_fastdaemon()
   1997-09-06 Lower-case stuff moved from squid-gw to libem
   1997-09-09 lower_cmpz(); upper; hash stuff moved from squid-gw to libem
   1997-09-12 libemfw_version(), libemfw_version_check()
   1997-10-21 ipaddr_parse(), ipaddr_compare()
   1998-09-03 check_snprintf()
   1999-03-17 copy_bidir()
   2000-04-14 create_pid_file(), write_pid_file()
   2000-04-15 Make NAME_data const
   2000-04-29 set_userid_groupid()
   2000-05-27 parse_fastdaemon(), xstrdup(), config_arg_count() */

#ifndef LIBEMFW_INCLUDED
#define LIBEMFW_INCLUDED

#include "libemcommon.h"

typedef unsigned char octet;

struct emi_file;		/* See emio.h */

/* Dirty hack to be able to include this fire without "firewall.h" and
   without having to use "struct cfgrec" instead of Cfg in the
   prototypes. */

struct cfgrec;			/* See firewall.h */
#define Cfg struct cfgrec

typedef	struct libemfw_Cmd
{
  char *cnam;
  int  flg;
  char *help;
  int  (*cfun)();
} Cmd;

struct hash_entry
{
  const char *name;
  int len;
  const struct hash_entry *next;
  int (*handler)();
  unsigned flags;
};

struct hash_descr
{
  const struct hash_entry *data;
  const struct hash_entry * const *hash;
  const struct hash_entry * const *by_code;
  unsigned hash_size;
};

struct fastdaemon_args
{
  char *hostname;
  char *ipaddr;
  int port;
};

extern const unsigned char lower_table[];
extern const unsigned char upper_table[];

void em_assert (const char *, const char *, unsigned) ATTR_NORETURN;

#define CB_SHUTDOWN1	0x0001	/* Use shutdown() on 1st channel */
#define CB_EOF1		0x0002	/* Terminate on EOF of 1st channel */
#define CB_SHUTDOWN2	0x0100	/* Use shutdown() on 1st channel */
#define CB_EOF2		0x0200	/* Terminate on EOF of 2nd channel */

/* If neither CB_EOF1 nor CB_EOF2 is used, copying terminates after
   both channels have hit EOF (and all data has been written). */

int copy_bidir (int, int, int, unsigned);
int copy_bidir_emi (struct emi_file *, int, struct emi_file *, int, int,
		    unsigned);

#ifdef NDEBUG
#define DEBUG_ASSERT(exp) ((void)0)
#else
#define DEBUG_ASSERT(exp) ((exp) ? (void)0 : \
			   em_assert (#exp, __FILE__, __LINE__))
#endif

#define ALWAYS_ASSERT(exp) ((exp) ? (void)0 : \
			    em_assert (#exp, __FILE__, __LINE__))

Cfg *config_hosts (Cfg *, char *, char *);
int config_groupid (Cfg *, int);
int config_userid (Cfg *, int);
int config_int (Cfg *, const char *, int, int, int);
char *config_string (Cfg *, const char *);
void config_arg_count (Cfg *, int);

void set_userid_groupid (void);

Cmd *find_command (Cmd *, char *);

void check_snprintf (int);

void *xmalloc (size_t);
char *xstrdup (const char *);
char *xstrndup (const char *, size_t);

void parse_fastdaemon (struct fastdaemon_args *, int *, char ***);
int do_fastdaemon (struct fastdaemon_args *);
void create_pid_file (const char *);
void write_pid_file (void);
void keep_pid_file ();

int fastpeername (int, char *, int);

#define HASH_IDX(name,ptr) HASH_IDX1 (name##_data, ptr)
#define HASH_IDX1(data,ptr) ((ptr) - &(data)[0])
#define HASH_IDX2(descr,ptr) HASH_IDX1 ((descr).data, ptr)

unsigned hash (const char *, size_t, unsigned);
const struct hash_entry *find_hash_entry (const struct hash_entry * const *,
					  unsigned, const char *, size_t);
const struct hash_entry *find_hash_entry2 (const struct hash_descr *,
					   const char *, size_t);

int lower_cmpn (const char *, const char *, size_t);
int lower_cmpz (const char *, const char *);
void lower_copy (char *, const char *, size_t);
int lower_match (const char *, size_t, const char *, size_t);

void upper_copy (char *, const char *, size_t);

#define IAP_WILDCARD	0x01

int ipaddr_parsez (const octet *, octet *, octet *, unsigned);
int ipaddr_parsen (const octet *, size_t, octet *, octet *, unsigned);
int ipaddr_compare (const octet *, const octet *, const octet *);

unsigned libemfw_version (void);
void libemfw_version_check (unsigned, unsigned);

/* Internal */

struct sockaddr_in;
void fastdaemon_sockaddr (struct sockaddr_in *, struct fastdaemon_args *);
void fastdaemon_ready (const struct fastdaemon_args *);

#undef Cfg

#endif
