248 #include <sys/stat.h>
271 static HTABLE *dict_table;
284 #define dict_node(dict) \
285 (dict_table ? (DICT_NODE *) htable_find(dict_table, dict) : 0)
289 #define DICT_FIND_FOR_LOOKUP(dict, dict_name) do { \
291 if ((node = dict_node(dict_name)) != 0) \
299 #define DICT_FIND_FOR_UPDATE(dict, dict_name) do { \
301 if ((node = dict_node(dict_name)) == 0) { \
302 dict = dict_ht_open(dict_name, O_CREAT | O_RDWR, 0); \
303 dict_register(dict_name, dict); \
308 #define STR(x) vstring_str(x)
314 const char *myname =
"dict_register";
319 if ((node =
dict_node(dict_name)) == 0) {
321 node->
dict = dict_info;
324 }
else if (dict_info != node->
dict)
325 msg_fatal(
"%s: dictionary name exists: %s", myname, dict_name);
337 return ((node =
dict_node(dict_name)) != 0 ? node->
dict : 0);
342 static void dict_node_free(
void *ptr)
356 const char *myname =
"dict_unregister";
360 msg_panic(
"non-existing dictionary: %s", dict_name);
369 int dict_update(
const char *dict_name,
const char *member,
const char *value)
371 const char *myname =
"dict_update";
376 msg_info(
"%s: %s = %s", myname, member, value);
377 return (dict->
update(dict, member, value));
382 const char *
dict_lookup(
const char *dict_name,
const char *member)
384 const char *myname =
"dict_lookup";
390 ret = dict->
lookup(dict, member);
392 msg_info(
"%s: %s = %s", myname, member, ret ? ret :
393 dict->
error ?
"(error)" :
"(notfound)");
397 msg_info(
"%s: %s = %s", myname, member,
"(notfound)");
406 const char *myname =
"dict_delete";
411 msg_info(
"%s: delete %s", myname, member);
418 const char **member,
const char **value)
420 const char *myname =
"dict_sequence";
425 msg_info(
"%s: sequence func %d", myname, func);
452 for (before = time((time_t *) 0); ; before = after) {
460 after = time((time_t *) 0);
461 if (st.st_mtime < before - 1 || st.st_mtime > after)
464 msg_info(
"pausing to let %s cool down", path);
474 const char *myname =
"dict_load_fp";
494 while (
readllines(buf, fp, &last_line, &lineno)) {
501 msg_info(
"%s: %s = %s", myname, member, val);
502 if ((old = dict->lookup(dict, member)) != 0
503 && strcmp(old, val) != 0)
504 msg_warn(
"%s, line %d: overriding earlier entry: %s=%s",
506 if (dict->update(dict, member, val) != 0)
507 msg_fatal(
"%s, line %d: unable to update %s:%s",
511 dict->owner.uid = st.st_uid;
512 dict->owner.status = (st.st_uid != 0);
517 static const char *dict_eval_lookup(
const char *key,
int unused_type,
520 char *dict_name = (
char *) context;
529 && (pp = dict->
lookup(dict, key)) == 0 && dict->
error != 0)
530 msg_fatal(
"dictionary %s: lookup %s: operation failed", dict_name, key);
536 const char *
dict_eval(
const char *dict_name,
const char *value,
int recursive)
538 const char *myname =
"dict_eval";
551 #define DONT_FILTER (char *) 0
555 DONT_FILTER, dict_eval_lookup, (
void *) dict_name);
557 msg_fatal(
"dictionary %s: macro processing error", dict_name);
559 if (strcmp(value,
STR(buf)) != 0)
560 msg_info(
"%s: expand %s -> %s", myname, value,
STR(buf));
562 msg_info(
"%s: const %s", myname, value);
576 for (ht = ht_info_list; (h = *ht) != 0; ht++)
578 myfree((
void *) ht_info_list);
585 const char *myname =
"dict_changed_name";
594 for (status = 0, ht = ht_info_list; status == 0 && (h = *ht) != 0; ht++) {
598 if (dict->
mtime == 0)
599 msg_warn(
"%s: table %s: null time stamp", myname, h->
key);
603 && st.st_mtime != dict->
mtime)
607 myfree((
void *) ht_info_list);
662 return (
name_mask(
"dictionary flags", dict_mask, names));
#define DICT_FLAG_DUP_IGNORE
int dict_error(const char *dict_name)
int mac_expand(VSTRING *result, const char *pattern, int flags, const char *filter, MAC_EXP_LOOKUP_FN lookup, void *context)
void dict_register(const char *dict_name, DICT *dict_info)
#define DICT_FLAG_NO_UNAUTH
int dict_load_file_xt(const char *dict_name, const char *path)
void(* close)(struct DICT *)
NORETURN msg_panic(const char *fmt,...)
int(* delete)(struct DICT *, const char *)
#define MAC_EXP_FLAG_RECURSE
#define DICT_FLAG_UTF8_REQUEST
#define DICT_FLAG_MULTI_WRITER
const char * split_nameval(char *buf, char **name, char **value)
#define DICT_FLAG_FOLD_FIX
void dict_unregister(const char *dict_name)
VSTREAM * vstream_fopen(const char *path, int flags, mode_t mode)
int dict_flags_mask(const char *names)
HTABLE * htable_create(ssize_t size)
const char * dict_lookup(const char *dict_name, const char *member)
int(* update)(struct DICT *, const char *, const char *)
HTABLE_INFO ** htable_list(HTABLE *table)
const char * str_name_mask_opt(VSTRING *buf, const char *context, const NAME_MASK *table, int mask, int flags)
int dict_sequence(const char *dict_name, const int func, const char **member, const char **value)
#define MAC_EXP_FLAG_NONE
#define DICT_FLAG_DUP_REPLACE
const char * dict_changed_name(void)
int vstream_fclose(VSTREAM *stream)
#define DICT_FLAG_TRY1NULL
DICT * dict_handle(const char *dict_name)
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
#define name_mask(tag, table, str)
const char * dict_flags_str(int dict_flags)
void doze(unsigned delay)
const char *(* lookup)(struct DICT *, const char *)
void dict_load_fp(const char *dict_name, VSTREAM *fp)
#define DICT_FLAG_DUP_WARN
void(* DICT_WALK_ACTION)(const char *, DICT *, void *)
NORETURN msg_fatal(const char *fmt,...)
int dict_update(const char *dict_name, const char *member, const char *value)
VSTRING * readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line)
#define DICT_FLAG_PATTERN
#define DICT_FIND_FOR_UPDATE(dict, dict_name)
const char * dict_eval(const char *dict_name, const char *value, int recursive)
VSTRING * vstring_free(VSTRING *vp)
#define DICT_FLAG_NO_REGSUB
#define DICT_FLAG_FOLD_MUL
#define vstream_fileno(vp)
void dict_walk(DICT_WALK_ACTION action, void *ptr)
#define DICT_FLAG_SYNC_UPDATE
int(* sequence)(struct DICT *, int, const char **, const char **)
#define DICT_FIND_FOR_LOOKUP(dict, dict_name)
void htable_delete(HTABLE *table, const char *key, void(*free_fn)(void *))
#define vstream_ferror(vp)
#define DICT_FLAG_BULK_UPDATE
#define DICT_FLAG_TRY0NULL
#define DICT_FLAG_NO_PROXY
int dict_delete(const char *dict_name, const char *member)
#define DICT_FLAG_OPEN_LOCK
#define DICT_FLAG_UTF8_ACTIVE
void * mymalloc(ssize_t len)
HTABLE_INFO * htable_enter(HTABLE *table, const char *key, void *value)
void msg_info(const char *fmt,...)