/* Nessuslib -- the Nessus Library
 * Copyright (C) 1998 Renaud Deraison
 *
 * $Id: harglists.h,v 1.13 2000/12/14 13:27:53 jordan Exp $
 *
 * Author: Jordan Hrycaj <jordan@mjh.teddy-net.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Jordan re-wrote Renauds idea of an arglists management on top
 * of the hash list manager
 *
 * --------------------------------------------------------------------
 *
 * There is a generic interface to symbolic run time variable managemet.
 * Althoug opaque variable types are supported, the idea is to let the
 * C language to type defs checking as far a possible.
 *
 *
 * Vitual data types supported:
 * ----------------------------
 *
 * HARG_NONE:    may be casted to (int)0, means no data type at all
 *		 and is used in special cases, only.
 *
 * HARG_STRING:  is stored as a '\0' terminated character string, the
 *               corresponding type group is BLOB
 *
 * HARG_BLOB:    is considered similar as HARG_STRING but without the
 *               terminating '\0', is stored as Binary Large OBject,
 *               the corresponding type group is BLOB
 *
 * HARG_PTR      is stored as a (var*)pointer, the corresponding type
 *               group is SCALAR
 *
 * HARG_INT      is stored as a HARG_PTR and interpreted as integer, the
 *               corresponding type group is SCALAR
 *
 * HARG_HARGLST  is stored and treated as a HARG_PTR with the only
 *               exception, that harg_dup() and harg_close_all() will
 *               recurse to that sublist implied and process it, too;
 *               the corresponding type group is SCALAR
 *
 *
 * List construction/destruction:
 * ------------------------------
 *
 * harglst*   harg_create              (unsigned estimated_size);
 * harglst*   harg_dup       (harglst*, unsigned estimated_size);
 * void       harg_close     (harglst*);
 * void       harg_close_all (harglst*);
 *
 * Both, harg_create() and harg_dup() create new variable lists,
 * the latter copies the access tree forthat list, recursively (see 
 * HARG_HARGLST, above.)
 *
 *
 * Adding symbolically accessed data:
 * ----------------------------------
 *
 * hargkey_t *harg_add_string         (harglst*, hargkey_t*, char*);
 * hargkey_t *harg_add_blob           (harglst*, hargkey_t*, unsigned, void*);
 * hargkey_t *harg_add_ptr            (harglst*, hargkey_t*, void*);
 * hargkey_t *harg_add_harg           (harglst*, hargkey_t*  harglst*)
 * hargkey_t *harg_add_int            (harglst*, hargkey_t*  int);
 *
 * hargkey_t *harg_add_default_string (harglst*, hargkey_t*, char*);
 * hargkey_t *harg_add_default_blob   (harglst*, hargkey_t*, unsigned, void*);
 * hargkey_t *harg_add_default_ptr    (harglst*, hargkey_t*, void*);
 * hargkey_t *harg_add_default_harg   (harglst*, hargkey_t*  harglst*)
 * hargkey_t *harg_add_default_int    (harglst*, hargkey_t*  int);
 *
 * Add some typed entry to the list.  If an entry with the given key exists,
 * already, the harg_add_default_*() directive will have no effect, whreas
 * the others always overwrite an exixting entry.
 *
 * The return value is always a pointer to a copy of the second argument,
 * the access key which exists on the same memory location as long as the
 * table entry exists without being overwitten.
 *
 * Only upon error or when the list pointer (the first argument) is NULL,
 * the return value is also NULL.
 *
 *
 * Deleting symbolically accessed data:
 * ------------------------------------
 *
 * int harg_remove (harglst*, hargkey_t*);
 *
 *
 * Modifying symbolically accessed data:
 * --------------------------------------
 *
 * int harg_set_string (harglst*, hargkey_t*, char*);
 * int harg_set_blob   (harglst*, hargkey_t*, unsigned, void*);
 * int harg_set_ptr    (harglst*, hargkey_t*, void*);
 * int harg_set_harg   (harglst*, hargkey_t*, harglst*);
 * int harg_set_int    (harglst*, hargkey_t*, int);
 * int harg_set_value  (harglst*, hargkey_t*, void*);
 *
 * An existing table entry is assigned a new value.  The directive
 * harg_set_value() will not do any type checking and assume the new
 * value given as third argument matches the internal data type. All
 * other function will do a type checking and detect an error if the
 * types don't match. Upon error, -1 is returned and 0,  otherwise.
 *
 * int harg_type_set_string (harglst*, hargkey_t*);
 * int harg_type_set_blob   (harglst*, hargkey_t*);
 * int harg_type_set_ptr    (harglst*, hargkey_t*);
 * int harg_type_set_harg   (harglst*, hargkey_t*);
 * int harg_type_set_int    (harglst*, hargkey_t*);
 *
 * These functions redefine an existing type of a table entry to a new
 * type. This only works among the same type groups scalar (ptr, harg, 
 * and int) or object (blob and string.) Upon error, -1 is returned and 0,
 * otherwise.
 *
 * int harg_set_id (harglst*, hargkey_t*, int);
 *
 * This functions overwites the internal id any element get by default. The
 * default id of an element is non-zero and sort of unique over all elements
 * in the list in that sense, that any newly created element gets a new
 * positive value  from the incremented list counter (which may overflow and
 * start anew at 1.)   The internal id will not change when list entries are
 * assigned new values, or types.  Upon error, -1 is returned  and 0, 
 * otherwise.
 *
 *
 * Retrieving symbolically accessed data:
 * --------------------------------------
 *
 * char      *harg_get_string  (harglst*, hargkey_t*);
 * void      *harg_get_ptr     (harglst*, hargkey_t*);
 * harglst   *harg_get_harg    (harglst*, hargkey_t*);
 * void      *harg_get_blob    (harglst*, hargkey_t*);
 * int        harg_get_int     (harglst*, hargkey_t*);
 * void      *harg_get_value   (harglst*, hargkey_t*);
 *
 *
 * hargkey_t *harg_inx_key     (harglst*,unsigned);
 *
 * Get the key of the n-th element as given as second argument, and the NULL 
 * pointer if there was none. Note that the list needs sorting before the key 
 * is retrieved if the structure has changed since the last time, this
 * directive was used.
 *
 *
 * unsigned   harg_get_size    (harglst*,hargkey_t*);
 *
 * hargkey_t *harg_inx_key     (harglst*,unsigned);
 *
 * Get the key of the n-th element as given as second argument, and the NULL 
 * pointer if there was none. Note that the list needs sorting before the key 
 * is retrieved if the structure has changed since the last time, this
 * directive was used.
 *
 *
 * hargtype_t harg_get_type    (harglst*,hargkey_t*);
 * int        harg_get_id      (harglst*,hargkey_t*);
 *
 *
 * Operations on all entries of a list:
 * ------------------------------------
 *
 * void      harg_dump        (harglst*);
 * hargwalk *harg_walk_init   (harglst*);
 * char*     harg_walk_next  (hargwalk*);
 * void      harg_walk_stop  (hargwalk*);
 * int       harg_do         (harglst*, int(*call_back)(), void *);
 *
 *
 * Operations on a remote archive
 * ------------------------------
 *
 * int harg_attach 
 * (int fd, harglst* localserver,  harglst* lst, const char *name, int flags);
 *
 * int harg_detach
 * (harglst*, int flags);
 *
 *
 *
 * int harg_commit
 * (harglst*); 
 *
 * int harg_rstrategy 
 * (harglst*, int flags);
 *
 *
 *
 * int harg_get_origin
 * (harglst*,hargkey_t*);
 *
 * int harg_ptr_get_origin 
 * (harglst *,void*);
 *
 *
 *
 * const char *harg_datadir
 * (const char *); 
 *
 * harg_ddump  (list, filename) harg_rdump (d,f,O_CREAT|O_TRUNC,0600)
 * harg_store  (list, filename) harg_rdump (d,f,O_CREAT,        0600)
 * harg_undump (list, filename) harg_rload (d,f,1,1)
 * harg_load   (list, filename) harg_rload (d,f,0,1)
 * harg_merge  (list, filename) harg_rload (d,f,0,0)
 *
 * int harg_rdump
 * (harglst*, const char *fname, int open_flags, int open_mode);
 *
 * int harg_rload 
 * (harglst*, const char *fname,  int flush_server, int overwrite_data);
 *
 */

#ifndef __HARGLIST_H__
#define __HARGLIST_H__

typedef
enum _hargtype_t {
  HARG_NONE = 0,

  HARG_STRING,
  HARG_PTR,
  HARG_INT,
  HARG_ARGLIST,
  HARG_BLOB,
  HARG_HARGLST,

  /* remote data types -- not directly accessible */
  RHARG_HARGLST
} hargtype_t ;

typedef const char hargkey_t ;

#ifdef __HARG_INTERNAL__
typedef 
struct _harglst {
  hlst              *x ;
  unsigned      autoid ;
  char destroy_sublist ;
  short         rflags ;  /* open/mode flags */
} harglst;
#else

typedef struct _harglst  {char opaq;} harglst;
#endif /* __HARG_INTERNAL__ */

typedef struct _hargwalk {char opaq;} hargwalk;

/* stategy flags for remote lists */
#define H_sNDELAY   0x0001 /* io process immediately */
#define H_sWRTHRU   0x0002 /* write through (and cache locally) */
#define H_sTAINTED  0x0004 /* filter out tainted records */
#define H_sLOCKED   0x0008 /* filter out tainted records */
#define H_sRDTHRU   0x0010 /* always fetch from server */
#define H_sOWRITE   0x0020 /* overwrite by default */
#define H_sLOCAL    0x0040 /* no update on the server (yet) */
#define H_sREMOTE   0x0080 /* NOOP, indicates remote processing or origin */

/* remote open mode/initialization flags */
#define H_oCREATE   0x0100 /* create new data base (must not exist) */
#define H_oOPEN     0x0200 /* data base need not exist when creating */
#define H_oTRUNC    0x0400 /* empty data base */
#define H_oCOPY     0x0800 /* copy data to/from the server */
#define H_oMOVE     0x1000 /* move data to/from the server */
#define H_oOWRITE   0x2000 /* overwrite data on the server */

/* local queue descriptor for a pseudo remote list */
#define H_fLOCALQ   0x08000 /* local queue instead of io stream */


/* functional interface */
extern harglst*    harg_create     (unsigned estimated_size);
extern harglst*    harg_dup        (harglst*, unsigned estimated_size);
extern void        harg_close      (harglst*);
extern void        harg_close_all  (harglst*);

extern hargkey_t  *harg_add        (harglst*,hargkey_t*,
				    hargtype_t,unsigned,void*);
extern hargkey_t  *harg_add_default(harglst*,hargkey_t*,
				    hargtype_t,unsigned,void*);
extern hargkey_t  *harg_ptr_add_ptr(harglst*, void*);

extern int         harg_remove     (harglst*,hargkey_t*);
extern int         harg_ptr_remove_ptr(harglst*, void*);

extern int         harg_set_tvalue (harglst*,hargkey_t*,
				    hargtype_t,unsigned,void*);
extern int         harg_set_type   (harglst*,hargkey_t*,hargtype_t);
extern int         harg_set_id     (harglst*,hargkey_t*,int);

extern void       *harg_get_tvalue (harglst*,hargkey_t*,hargtype_t);
extern hargtype_t  harg_get_type   (harglst*,hargkey_t*);
extern int         harg_get_id     (harglst*,hargkey_t*);
extern unsigned    harg_get_size   (harglst*,hargkey_t*);
extern void       *harg_ptr_get_ptr(harglst *,void*);

extern hargkey_t  *harg_inx_key    (harglst*,unsigned);

extern void        harg_dump       (harglst*);
extern hargwalk   *harg_walk_init  (harglst*);
extern hargkey_t  *harg_walk_next  (hargwalk*);
extern void        harg_walk_stop  (hargwalk*);

extern int         harg_do         (harglst*, 
   int(*)(void*state,void*data,hargtype_t,unsigned size,int id,hargkey_t*),
   void *state) ;

/* remote extensions for the functional interface */
extern int         harg_attach     (int fd, harglst* localserver, 
				    harglst* lst, const char *name, int flags);
extern int         harg_detach     (harglst*, int flags);
extern int         harg_commit     (harglst*); /* flush pending to server */
extern int         harg_rstrategy  (harglst*, int flags);
extern int         harg_get_origin (harglst*,hargkey_t*);

extern int         harg_ptr_get_origin (harglst *,void*);
extern const char *harg_datadir    (const char *); /* see hlstio_datadir () */
extern int         harg_rdump      (harglst*, const char *fname, 
				    int open_flags, int open_mode);
extern int         harg_rload      (harglst*, const char *fname, 
				    int flush_server, int overwrite_data);

/* convenience macros */
#define harg_ddump( d,f) harg_rdump (d,f,O_CREAT|O_TRUNC,0600)
#define harg_store( d,f) harg_rdump (d,f,O_CREAT,        0600)
#define harg_undump(d,f) harg_rload (d,f,1,1)    /* flush list */
#define harg_load(  d,f) harg_rload (d,f,0,1)    /* overwrite */
#define harg_merge( d,f) harg_rload (d,f,0,0)

#define harg_add_string( d,key,  str) harg_add ((d),(key),HARG_STRING, 0,(void*)(str))
#define harg_add_nstring(d,key,n,str) harg_add ((d),(key),HARG_STRING, n,(void*)(str))
#define harg_add_ptr(    d,key,  ptr) harg_add ((d),(key),HARG_PTR,    0,(ptr))
#define harg_add_harg(   d,key,  lst) harg_add ((d),(key),HARG_HARGLST,0,(lst))
#define harg_add_blob(   d,key,l,ptr) harg_add ((d),(key),HARG_BLOB,   l,(ptr))
#define harg_add_int(     d,key,   n) harg_add ((d),(key), HARG_INT,   0,(void*)(n))

#define harg_add_default_string(d,key,  str) harg_add_default ((d),(key),HARG_STRING, 0,(void*)(str))
#define harg_add_default_ptr(   d,key,  ptr) harg_add_default ((d),(key),HARG_PTR,    0,(ptr))
#define harg_add_default_harg(  d,key,  lst) harg_add_default ((d),(key),HARG_HARGLST,0,(lst))
#define harg_add_default_blob(  d,key,l,ptr) harg_add_default ((d),(key),HARG_BLOB,   l,(ptr))
#define harg_add_default_int(   d,key,  num) harg_add_default ((d),(key),HARG_INT,    0,(void*)(num))

#define harg_get_string(d,key)    ((char*)harg_get_tvalue ((d),(key),HARG_STRING))
#define harg_get_ptr(   d,key)    ((void*)harg_get_tvalue ((d),(key),HARG_PTR))
#define harg_get_harg(  d,key) ((harglst*)harg_get_tvalue ((d),(key),HARG_HARGLST))
#define harg_get_blob(  d,key)    ((void*)harg_get_tvalue ((d),(key),HARG_BLOB))
#define harg_get_int(   d,key)      ((int)harg_get_tvalue ((d),(key),HARG_INT))
#define harg_get_value( d,key)            harg_get_tvalue ((d),(key),HARG_NONE)

#define harg_set_string( d,key,  str) harg_set_tvalue ((d),(key),HARG_STRING, 0,(str))
#define harg_set_nstring(d,key,n,str) harg_set_tvalue ((d),(key),HARG_STRING, n,(str))
#define harg_set_ptr(    d,key,  ptr) harg_set_tvalue ((d),(key),HARG_PTR,    0,(ptr))
#define harg_set_harg(   d,key,  lst) harg_set_tvalue ((d),(key),HARG_HARGLST,0,(lst))
#define harg_set_blob(   d,key,l,ptr) harg_set_tvalue ((d),(key),HARG_BLOB,   l,(ptr))
#define harg_set_int(    d,key,  num) harg_set_tvalue ((d),(key),HARG_INT,    0,(void*)(num))
#define harg_set_value(  d,key,  val) harg_set_tvalue ((d),(key),HARG_NONE,   0,(val))

#define harg_type_set_string(d,key)   harg_set_type   ((d),(key),HARG_STRING)
#define harg_type_set_ptr(   d,key)   harg_set_type   ((d),(key),HARG_PTR)
#define harg_type_set_harg(  d,key)   harg_set_type   ((d),(key),HARG_HARGLST) 
#define harg_type_set_blob(  d,key)   harg_set_type   ((d),(key),HARG_BLOB)
#define harg_type_set_int(   d,key)   harg_set_type   ((d),(key),HARG_INT)
#endif /* __HARGLIST_H__ */
