#ifndef _DICT_H_INCLUDED_
#define _DICT_H_INCLUDED_
#include <fcntl.h>
#include <setjmp.h>
#ifdef NO_SIGSETJMP
#define DICT_JMP_BUF jmp_buf
#else
#define DICT_JMP_BUF sigjmp_buf
#endif
#include <vstream.h>
#include <argv.h>
#include <vstring.h>
#include <myflock.h>
typedef struct DICT_OWNER {
int status;
uid_t uid;
} DICT_OWNER;
#define DICT_OWNER_UNKNOWN (-1)
#define DICT_OWNER_TRUSTED (!1)
#define DICT_OWNER_UNTRUSTED (!0)
#define DICT_OWNER_AGGREGATE_INIT(dst) { \
(dst).status = DICT_OWNER_TRUSTED; \
(dst).uid = 0; \
} while (0)
#define DICT_OWNER_AGGREGATE_UPDATE(dst, src) do { \
if ((dst).status == DICT_OWNER_TRUSTED \
|| (src).status == DICT_OWNER_UNKNOWN) { \
(dst) = (src); \
} else if ((dst).status == (src).status \
&& (dst).uid != (src).uid) { \
(dst).status = DICT_OWNER_UNKNOWN; \
(dst).uid = ~0; \
} \
} while (0)
typedef struct DICT {
char *type;
char *name;
int flags;
const char *(*lookup) (struct DICT *, const char *);
int (*update) (struct DICT *, const char *, const char *);
int (*delete) (struct DICT *, const char *);
int (*sequence) (struct DICT *, int, const char **, const char **);
int (*lock) (struct DICT *, int);
void (*close) (struct DICT *);
int lock_type;
int lock_fd;
int stat_fd;
time_t mtime;
VSTRING *fold_buf;
DICT_OWNER owner;
int error;
DICT_JMP_BUF *jbuf;
struct DICT_UTF8_BACKUP *utf8_backup;
} DICT;
extern DICT *dict_alloc(const char *, const char *, ssize_t);
extern void dict_free(DICT *);
extern DICT *dict_debug(DICT *);
#define DICT_DEBUG(d) ((d)->flags & DICT_FLAG_DEBUG ? dict_debug(d) : (d))
#define DICT_FLAG_NONE (0)
#define DICT_FLAG_DUP_WARN (1<<0)
#define DICT_FLAG_DUP_IGNORE (1<<1)
#define DICT_FLAG_TRY0NULL (1<<2)
#define DICT_FLAG_TRY1NULL (1<<3)
#define DICT_FLAG_FIXED (1<<4)
#define DICT_FLAG_PATTERN (1<<5)
#define DICT_FLAG_LOCK (1<<6)
#define DICT_FLAG_DUP_REPLACE (1<<7)
#define DICT_FLAG_SYNC_UPDATE (1<<8)
#define DICT_FLAG_DEBUG (1<<9)
#define DICT_FLAG_NO_REGSUB (1<<11)
#define DICT_FLAG_NO_PROXY (1<<12)
#define DICT_FLAG_NO_UNAUTH (1<<13)
#define DICT_FLAG_FOLD_FIX (1<<14)
#define DICT_FLAG_FOLD_MUL (1<<15)
#define DICT_FLAG_FOLD_ANY (DICT_FLAG_FOLD_FIX | DICT_FLAG_FOLD_MUL)
#define DICT_FLAG_OPEN_LOCK (1<<16)
#define DICT_FLAG_BULK_UPDATE (1<<17)
#define DICT_FLAG_MULTI_WRITER (1<<18)
#define DICT_FLAG_UTF8_REQUEST (1<<19)
#define DICT_FLAG_UTF8_ACTIVE (1<<20)
#define DICT_FLAG_UTF8_MASK (DICT_FLAG_UTF8_REQUEST)
#define DICT_FLAG_PARANOID \
(DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY | DICT_FLAG_NO_UNAUTH)
#define DICT_FLAG_IMPL_MASK (DICT_FLAG_FIXED | DICT_FLAG_PATTERN | \
DICT_FLAG_MULTI_WRITER)
#define DICT_FLAG_RQST_MASK (DICT_FLAG_FOLD_ANY | DICT_FLAG_LOCK | \
DICT_FLAG_DUP_REPLACE | DICT_FLAG_DUP_WARN | \
DICT_FLAG_DUP_IGNORE | DICT_FLAG_SYNC_UPDATE | \
DICT_FLAG_PARANOID | DICT_FLAG_UTF8_MASK)
#define DICT_FLAG_INST_MASK ~(DICT_FLAG_IMPL_MASK | DICT_FLAG_RQST_MASK)
#define DICT_NEED_UTF8_ACTIVATION(enable, flags) \
((enable) && ((flags) & DICT_FLAG_UTF8_MASK))
#define DICT_ERR_NONE 0
#define DICT_ERR_RETRY (-1)
#define DICT_ERR_CONFIG (-2)
#define DICT_STAT_FAIL 1
#define DICT_STAT_SUCCESS 0
#define DICT_STAT_ERROR (-1)
#define DICT_ERR_VAL_RETURN(dict, err, val) do { \
(dict)->error = (err); \
return (val); \
} while (0)
#define DICT_SEQ_FUN_FIRST 0
#define DICT_SEQ_FUN_NEXT 1
extern ARGV *dict_mapnames(void);
typedef void (*DICT_MAPNAMES_EXTEND_FN) (ARGV *);
extern DICT_MAPNAMES_EXTEND_FN dict_mapnames_extend(DICT_MAPNAMES_EXTEND_FN);
extern void dict_register(const char *, DICT *);
extern DICT *dict_handle(const char *);
extern void dict_unregister(const char *);
extern int dict_update(const char *, const char *, const char *);
extern const char *dict_lookup(const char *, const char *);
extern int dict_delete(const char *, const char *);
extern int dict_sequence(const char *, const int, const char **, const char **);
extern int dict_load_file_xt(const char *, const char *);
extern void dict_load_fp(const char *, VSTREAM *);
extern const char *dict_eval(const char *, const char *, int);
extern int dict_error(const char *);
typedef DICT *(*DICT_OPEN_FN) (const char *, int, int);
typedef DICT_OPEN_FN (*DICT_OPEN_EXTEND_FN) (const char *);
extern DICT *dict_open(const char *, int, int);
extern DICT *dict_open3(const char *, const char *, int, int);
extern void dict_open_register(const char *, DICT_OPEN_FN);
extern DICT_OPEN_EXTEND_FN dict_open_extend(DICT_OPEN_EXTEND_FN);
#define dict_get(dp, key) ((const char *) (dp)->lookup((dp), (key)))
#define dict_put(dp, key, val) (dp)->update((dp), (key), (val))
#define dict_del(dp, key) (dp)->delete((dp), (key))
#define dict_seq(dp, f, key, val) (dp)->sequence((dp), (f), (key), (val))
#define dict_close(dp) (dp)->close(dp)
typedef void (*DICT_WALK_ACTION) (const char *, DICT *, void *);
extern void dict_walk(DICT_WALK_ACTION, void *);
extern int dict_changed(void);
extern const char *dict_changed_name(void);
extern const char *dict_flags_str(int);
extern int dict_flags_mask(const char *);
extern void dict_type_override(DICT *, const char *);
typedef struct DICT_UTF8_BACKUP {
const char *(*lookup) (struct DICT *, const char *);
int (*update) (struct DICT *, const char *, const char *);
int (*delete) (struct DICT *, const char *);
} DICT_UTF8_BACKUP;
extern DICT *dict_utf8_activate(DICT *);
void dict_test(int, char **);
extern int dict_allow_surrogate;
extern DICT *PRINTFLIKE(5, 6) dict_surrogate(const char *, const char *, int, int, const char *,...);
#define DICT_TYPE_NOFILE "non-existent"
#define DICT_TYPE_NOUTF8 "non-UTF-8"
#ifdef NO_SIGSETJMP
#define dict_setjmp(dict) setjmp((dict)->jbuf[0])
#define dict_longjmp(dict, val) longjmp((dict)->jbuf[0], (val))
#else
#define dict_setjmp(dict) sigsetjmp((dict)->jbuf[0], 1)
#define dict_longjmp(dict, val) siglongjmp((dict)->jbuf[0], (val))
#endif
#define dict_isjmp(dict) ((dict)->jbuf != 0)
extern void dict_jmp_alloc(DICT *);
#endif