/*
 * nblib.h  -  Header file for netboot library
 *
 * Copyright (C) 1998-2007 Gero Kuhlmann <gero@gkminix.han.de>
 *
 *  This program 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 of the License, or
 *  any later version.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: nblib.h,v 1.37 2007/01/06 18:30:52 gkminix Exp $
 */

#ifndef NBLIB_H
#define NBLIB_H


/*
 * Include files required for definitions within this file
 */
#ifdef NETBOOT
# ifndef COMMON_H
#  include <common.h>
# endif
# ifndef NEED_NBLIBC
#  define NEED_NBLIBC
# endif
#else
# ifdef HAVE_CONFIG_H
#  include <config.h>
# endif
# include <stdlib.h>
# include <stdio.h>
# if defined(__STDC__) || defined(_AIX) || (defined(__mips) && defined(_SYSTYPE_SVR4)) || defined(_WIN32) || (defined(__alpha) && defined(__cplusplus))
#  ifndef HAVE_ANSI_CC
#   define HAVE_ANSI_CC 1
#  endif
# else
#  ifdef HAVE_ANSI_CC
#   undef HAVE_ANSI_CC
#  endif
# endif
# ifndef __P
#  if defined(PROTOTYPES) || defined(HAVE_ANSI_CC)
#   define __P(args)	args
#  else
#   define __P(args)
#  endif
# endif
# ifndef voidstar
#  ifdef HAVE_ANSI_CC
#   define voidstar void *
#  else
#   define voidstar char *
#  endif
# endif
# ifdef __STDC__
#  include <stdarg.h>
# else
#  include <varargs.h>
# endif
# if !defined(__GNUC__) || __GNUC__ < 3
#  define __attribute__(x)
# endif
typedef unsigned char __u8;
#endif



/*
 * Common size of I/O buffers
 */
#ifndef DEFBUFSIZE
# define DEFBUFSIZE	512
#endif



/*
 * Return values of filelock() and checklock()
 */
#define FILELOCK_ERROR	-1		/* error locking file */
#define FILELOCK_SET	0		/* a file lock is already set */
#define FILELOCK_OK	1		/* the file has been locked */



/*
 * File access time types used by filetime()
 */
#define FT_ATIME	0		/* last access time */
#define	FT_MTIME	1		/* last modification time */
#define FT_CTIME	2		/* last status change time */



/*
 * File access methods used by checkaccess()
 */
#define ACCESS_FILE_DEFAULT	-1
#define ACCESS_FILE_EXIST	 0		/* file exists */
#define ACCESS_FILE_READ	 1		/* file is readable */
#define ACCESS_FILE_RW		 2		/* file is writable */
#define ACCESS_FILE_EXEC	 3		/* file is executable */
#define ACCESS_DIR_EXIST	 4		/* directory exists */
#define ACCESS_DIR_READ		 5		/* directory is readable */
#define ACCESS_DIR_RW		 6		/* directory is writable */



/*
 * Logfile levels
 */
#define LOGLEVEL_NORMAL		0
#define LOGLEVEL_NOTICE		1
#define LOGLEVEL_INFO		2
#define LOGLEVEL_DEBUG		3



/*
 * Values used by boolean variables:
 */
#define BOOL_UNDEF	-1		/* value not assigned yet */
#define BOOL_FALSE	FALSE		/* FALSE value */
#define BOOL_TRUE	TRUE		/* TRUE value */



/*
 * Structure defining program options
 */
struct cmdopt {
	char		*longopt;	/* long option name */
	int		 shortopt;	/* short option character */
	enum {
		noval,			/* end of option list */
		boolval,		/* option has no argument */
		intval,			/* option has short integer argument */
		longval,		/* option has long integer argument */
		strval,			/* option has string argument */
		procval,		/* call procedure when option given */
		copyrightmsg,		/* dummy option with copyright msg */
		nonopt			/* argument without option name */
	}		 valtype;
	union {
		voidstar  dummyptr;	/* dummy pointer */
		char    **strptr;	/* pointer to string buffer */
		int      *intptr;	/* pointer to short integer buffer */
		long     *longptr;	/* pointer to long integer buffer */
		int      *boolptr;	/* pointer to boolean buffer */
		void    (*procptr) __P((struct cmdopt *, char *));
	}		 valptr;
	char		*helptext;	/* help text for option */
	char		*helparg;	/* help text for argument */
};



/*
 * Structures holding all the information required to parse config file
 */
struct enumdef {
	char     *enumstr;		/* enumeration string */
	int       val;			/* enumeration value */
};


struct paramdef {
	char		 *name;		/* name of parameter in config file */
	enum {
		par_null,		/* end of parameter list */
		par_string,		/* string value */
		par_file,		/* file name value */
		par_int,		/* short integer value */
		par_long,		/* long integer value */
		par_bool,		/* boolean value */
		par_enum,		/* enumeration value */
		par_proc		/* procedure to handle argument */
	}		  type;
	struct enumdef	 *enumlist;	/* list of enumeration values */
	union {
		voidstar   dummyptr;	/* dummy pointer */
		char     **strptr;	/* pointer to string buffer */
		char     **fnamptr;	/* pointer to file name buffer */
		int       *intptr;	/* pointer to short integer value */
		long      *longptr;	/* pointer to long integer value */
		int       *boolptr;	/* pointer to boolean value */
		int       *enumptr;	/* pointer to enumeration value */
		char    *(*procptr) __P((char *, char **, int));
	}		  valptr;
};

struct sectdef {
	char		 *name;		/* name of section */
	struct paramdef  *params;	/* pointer to parameter list */
	char		*(*startsect) __P((const char *, struct sectdef **));
	char		*(*endsect) __P((const char *, struct sectdef **));
};



/*
 * Database error routine pointer
 */
typedef enum {
	DBERR_CLASS_INFO,
	DBERR_CLASS_WARNING,
	DBERR_CLASS_ERROR,
	DBERR_CLASS_FATAL
} dberrclass;

typedef void (*dberr) __P((const char *dbname, const char *msg,
							dberrclass class));



/*
 * Database status values
 */
#define DBSTATUS_VALID		0x0001		/* cur database is valid */
#define DBSTATUS_RO		0x0002		/* cur database is readonly */
#define DBSTATUS_ADD		0x0004		/* cur database has add flag */
#define DBSTATUS_POS		0x0008		/* cur position is valid */
#define DBSTATUS_LAST		0x0010		/* cur database is last */



/*
 * Database handle type
 */
#define DBHDL		voidstar
#define DBHDL_NULL	NULL



/*
 * List handle type
 */
#define LISTHDL		voidstar
#define LISTHDL_NULL	NULL



/*
 * List callback function types
 */
typedef int (*listwalkcb)(LISTHDL handle, voidstar *data, const voidstar state);
typedef void (*listfreecb)(LISTHDL handle, voidstar data);



/*
 * Size of an MD5 checksum digest
 */
#define MD5_DIGEST_SIZE	16



/*
 * ELF file read modes
 */
#define ELF_MODE_NONE		0	/* not a valid read mode */
#define ELF_MODE_TEXT		1	/* read text segment */
#define ELF_MODE_DATA		2	/* read data segment */
#define ELF_MODE_SYMTAB		3	/* read symbol tables */
#define ELF_MODE_STRTAB		4	/* read string tables */
#define ELF_MODE_DYNAMIC	5	/* read dynamic data */



/*
 * Character set definitions
 */
#define CHARSET_UNKNOWN		0
#define CHARSET_EBCDIC		1
#define CHARSET_ASCII		2
#define CHARSET_UTF8		3
#define CHARSET_LATIN1		4
#define CHARSET_LATIN9		5



/*
 * Types used for host character strings when used with conversion
 * routines:
 *
 *  hchar_t  - One character in the host representation. If the host uses
 *             an 8-bit character set like Latin-1, only 8 bits are used
 *             with this data type. However, if the host uses a multibyte
 *             representation like UTF-8, all bits defining one character
 *             are used.
 *
 *  ucs_t    - One character in UCS-2 representation, independently of the
 *             character set used by the host.
 *
 *  pcchar_t - One character as represented on the target X86 system (which
 *             is the PC internal BIOS character set)
 */
typedef unsigned short hchar_t;		/* host character */
typedef unsigned int ucs_t;		/* UCS-2/4 character */
typedef __u8 pcchar_t;			/* target PC character */



/*
 * Variables exported by library
 */
extern char *progname;			/* name of current program */
extern char *nblibdir;			/* name of non-shared data directory */
extern char *nbdatadir;			/* name of shared data directory */
extern char *nbhomedir;			/* name of netboot home directory */
extern char *userhomedir;		/* name of user home directory */
extern char *curworkdir;		/* name of current working directory */
extern unsigned long write_chksum;	/* checksum when writing */
extern unsigned int dberrors;		/* number of errors in DB access */
extern unsigned int dbwarnings;		/* number of warnings in DB access */
extern int verbose;			/* verbosity flag */
extern int quiet;			/* quiet flag */
extern int debug;			/* debugging flag */



/*
 * Routines exported by library
 */

/* Error and log file printing */
extern FILE *logfd __P((int level));
extern void prnverr __P((const char *msg, va_list args));
extern void prnvlog __P((int level, const char *msg, va_list args));

extern void prnerr __P((const char *msg, ...))
				__attribute__ ((format (printf, 1, 2)));

extern void prnlog __P((int level, const char *msg, ...))
				__attribute__ ((format (printf, 2, 3)));


/* Memory allocation and management functions */
extern voidstar nbmalloc __P((size_t amount)) __attribute__ ((malloc));
extern voidstar nbcalloc __P((size_t nelem, size_t elsize)) __attribute__ ((malloc));
extern voidstar nbrealloc __P((voidstar oldmem, size_t amount)) __attribute__ ((malloc));
extern void copystr __P((char **dest, const char *src));


/* Character conversion routines */
extern int setcharset __P((int newcharset));
extern pcchar_t chartotarget __P((hchar_t c));
extern hchar_t chartohost __P((pcchar_t c));
extern hchar_t charcollect __P((char c));
extern hchar_t chartolower __P((hchar_t c));
extern hchar_t chartoupper __P((hchar_t c));
extern ucs_t chartoucs2 __P((hchar_t c));
extern hchar_t *strtohost __P((const char *s));
extern size_t savechar __P((hchar_t c, char *s, size_t n));
extern size_t charlen __P((hchar_t c));
extern char *bytestr __P((const __u8 *buf, size_t len));
extern int bytecmp __P((const char *str, const __u8 *buf, size_t len));
extern void bytecpy __P((const char *str, __u8 *buf, size_t len));
extern size_t bytelen __P((const char *str));


/* Signal handling */
void signal_stop __P((void));
void signal_resume __P((void));


/* File I/O functions */
extern int opentemp __P((int dounlink));
extern void closetemp __P((int fd));
extern void setpath __P((char **pathname, const char *maindir));
extern void checkaccess __P((char **filename, const char *maindir, int mode));
extern int checklock __P((const char *lockname));
extern int filelock __P((const char *lockname));
extern int fileunlock __P((const char *lockname));
extern long filesize __P((const char *filename));
extern time_t filetime __P((const char *filename, int timetype));
extern size_t nbread __P((__u8 *buf, size_t bufsize, int infile));
extern size_t nbwrite __P((__u8 *buf, size_t bufsize, int outfile));
extern int nbexec __P((char *progfile, char **args));


/* Configuration and setup function */
extern LISTHDL listsysdb __P((const char *filter));
extern int writesysdb __P((char *recname, struct paramdef *params));
extern int readsysdb __P((char *recname, struct paramdef *params));
extern int delsysdb __P((const char *recname));
extern int opensysdb __P((int readonly));
extern void closesysdb __P((void));
extern void nbsetup __P((int argc, char **argv,
				struct cmdopt *opts, struct sectdef *sects));


/* Database access routines */
extern DBHDL createdb __P((const char *name, dberr errorhandler));
extern int checkdb __P((DBHDL handle));
extern void freedb __P((DBHDL handle));
extern int opendb __P((DBHDL handle, int readonly));
extern void closedb __P((DBHDL handle));
extern void releasedb __P((DBHDL handle));
extern int getstatedb __P((DBHDL handle, char **recname));
extern int nextdb __P((DBHDL handle));
extern int prevdb __P((DBHDL handle));
extern int findfirst __P((DBHDL handle, const char *name));
extern int findnext __P((DBHDL handle));
extern int markrec __P((DBHDL handle, int jump));
extern int nextrec __P((DBHDL handle));
extern int prevrec __P((DBHDL handle));
extern int firstrec __P((DBHDL handle));
extern int lastrec __P((DBHDL handle));
extern int readrec __P((DBHDL handle, struct sectdef *sects));
extern void writerec __P((DBHDL handle, struct sectdef *sects));
extern void addrec __P((DBHDL handle, struct sectdef *sects, int sectindex));
extern void delrec __P((DBHDL handle));


/* Single-linked list handling routines */
extern LISTHDL createlist __P((listfreecb freecb));
extern void releaselist __P((LISTHDL handle));
extern voidstar *getatlist __P((LISTHDL handle, int index));
extern voidstar *findlist __P((LISTHDL handle, voidstar data));
extern int getcountlist __P((LISTHDL handle));
extern int appendlist __P((LISTHDL handle, voidstar data));
extern int removelist __P((LISTHDL handle, voidstar data));
extern int removeatlist __P((LISTHDL handle, int index));
extern int walklist __P((LISTHDL handle, listwalkcb callbackfunc,
							const voidstar state));


/* MD5 checksum routines */
extern void md5init __P((void));
extern void md5update __P((__u8 *buf, size_t len));
extern void md5final __P((__u8 *digest));


/* ELF file read routines */
extern char *elfgeterr __P((void));
extern void elfclose __P((void));
extern int elfopen __P((const char *fname,
				unsigned long textofs, unsigned long dataofs));
extern int elfset __P((unsigned int mode,
				unsigned long *addr, unsigned long *size));
extern int elfread __P((__u8 *buf, size_t *size));


/* Help file routines */
extern int helpinit __P((const char *fname));
extern int helptopic __P((int topic));
extern int helpget __P((char *buf, int bufsize));



/* General C library replacement function */
#ifdef NEED_NBLIBC
# if !defined(HAVE_MEMCPY) && !defined(HAVE_BCOPY)
extern void nbmemcpy __P((voidstar dest, const voidstar src, size_t len));
#  define memcpy(D, S, L)	nbmemcpy((D), (S), (L))
# endif

# if !defined(HAVE_MEMCMP)
extern int nbmemcmp __P((const voidstar m1, const voidstar m2, size_t len));
#  define memcmp(D, S, L)	nbmemcmp((D), (S), (L))
# endif

# if !defined(HAVE_MEMMOVE) && !defined(HAVE_BCOPY)
extern voidstar nbmemmove __P((voidstar dest, const voidstar src, size_t len));
#  define memmove(D, S, L)	nbmemmove((D), (S), (L))
# endif

# if !defined(HAVE_MEMSET)
extern void nbmemset __P((voidstar dest, int val, size_t len));
#  define memset(D, V, L)	nbmemset((D), (V), (L))
# endif

# if !defined(HAVE_STRNCMP)
extern int nbstrncmp __P((const char *s1, const char *s2, size_t n));
#  define strncmp(D, S, L)	nbstrncmp((D), (S), (L))
# endif

# if !defined(HAVE_STRSTR)
extern char *nbstrstr __P((const char *haystack, const char *needle));
#  define strstr(H, N)		nbstrstr((H), (N))
# endif

# if !defined(HAVE_STRSPN)
extern int nbstrspn __P((const char *str, const char *accept));
#  define strspn(S, A)		nbstrspn((S), (A))
# endif

# if !defined(HAVE_STRCSPN)
extern int nbstrcspn __P((const char *str, const char *reject));
#  define strcspn(S, R)		nbstrcspn((S), (R))
# endif

# if !defined(HAVE_STRCHR) && !defined(HAVE_INDEX)
extern char *nbstrchr __P((const char *s, char c));
#  define strchr(S, C)		nbstrchr((S), (C))
# endif

# if !defined(HAVE_STRRCHR) && !defined(HAVE_RINDEX)
extern char *nbstrrchr __P((const char *s, char c));
#  define strrchr(S, C)		nbstrrchr((S), (C))
# endif

# if !defined(HAVE_STRTOL)
extern long nbstrtol __P((const char *nptr, char **endptr, int base));
#  define strtol(N, E, B)	nbstrtol((N), (E), (B))
# endif

# if !defined(HAVE_VFPRINTF)
extern int nbvfprintf __P((FILE *stream, const char *format, va_list ap));
#  define vfprintf(S, F, A)	nbvfprintf((S), (F), (A))
# endif

# if !defined(HAVE_VSPRINTF)
extern int nbvsprintf __P((char *buf, const char *format, va_list ap));
#  define vsprintf(B, F, A)	nbvsprintf((B), (F), (A))
# endif

# if !defined(HAVE_VASPRINTF)
extern int nbvasprintf __P((char **buf, const char *format, va_list ap));
#  define vasprintf(B, F, A)	nbvasprintf((B), (F), (A))
# endif
#endif


/* Use BSD alternatives for non-existent SysV functions */
#if !defined(HAVE_MEMSET) && defined(HAVE_BZERO)
# define memzero(D, N) bzero((D), (N))
#else
# define memzero(D, N) memset((D), 0, (N))
#endif
#ifdef NEED_NBLIBC
# if !defined(HAVE_MEMCPY) && defined(HAVE_BCOPY)
#  define memcpy(D, S, N)	bcopy((S), (D), (N))
# endif
# if !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY)
#  define memmove(D, S, N)	bcopy((S), (D), (N))
# endif
# if !defined(HAVE_STRCHR) && defined(HAVE_INDEX)
#  define strchr(S, C)		index((S), (C))
# endif
# if !defined(HAVE_STRRCHR) && defined(HAVE_RINDEX)
#  define strrchr(S, C)		rindex((S), (C))
# endif
#endif



/*
 * Exit and error code handling
 */
extern int nbatexit __P((void (*func)(void)));
extern void nbexit __P((int code)) __attribute__ ((noreturn));
extern void nberror __P((int errnum, const char *errmsg, ...))
				__attribute__ ((format (printf, 2, 3)));



/*
 * Handle getopt library calls. Since the nblib library itself requires
 * getopt_long, we do not include the system-wide getopt.h if it does not
 * declare getopt_long. Actually, we are not going to use any system-wide
 * getopt-related stuff if getopt_long doesn't exist. In that case, we
 * rather use our own, GNU-derived getopt routines.
 * Note that the second include works everywhere because of the use of
 * $(MODNAME) when defining $(INCLUDE) in make.config.in!
 */
#if defined(NEED_GETOPT)
# if defined(HAVE_GETOPT_LONG) && defined(HAVE_GETOPT_H)
#  include <getopt.h>
# else
#  ifdef NETBOOT
#   include "../nblib/getopt.h"
#  endif
# endif
#endif


#endif

