1/*++
2/* NAME
3/*	dict_alloc 3
4/* SUMMARY
5/*	dictionary memory manager
6/* SYNOPSIS
7/*	#include <dict.h>
8/*
9/*	DICT	*dict_alloc(dict_type, dict_name, size)
10/*	const char *dict_type;
11/*	const char *dict_name;
12/*	ssize_t	size;
13/*
14/*	void	dict_free(dict)
15/*	DICT	*ptr;
16/*
17/*	void	dict_jmp_alloc(dict)
18/*	DICT	*ptr;
19/* DESCRIPTION
20/*	dict_alloc() allocates memory for a dictionary structure of
21/*	\fIsize\fR bytes, initializes all generic dictionary
22/*	properties to default settings,
23/*	and installs default methods that do not support any operation.
24/*	The caller is supposed to override the default methods with
25/*	ones that it supports.
26/*	The purpose of the default methods is to trap an attempt to
27/*	invoke an unsupported method.
28/*
29/*	One exception is the default lock function.  When the
30/*	dictionary provides a file handle for locking, the default
31/*	lock function returns the result from myflock with the
32/*	locking method specified in the lock_type member, otherwise
33/*	it returns 0. Presently, the lock function is used only to
34/*	implement the DICT_FLAG_OPEN_LOCK feature (lock the database
35/*	exclusively after it is opened) for databases that are not
36/*	multi-writer safe.
37/*
38/*	dict_free() releases memory and cleans up after dict_alloc().
39/*	It is up to the caller to dispose of any memory that was allocated
40/*	by the caller.
41/*
42/*	dict_jmp_alloc() implements preliminary support for exception
43/*	handling. This will eventually be built into dict_alloc().
44/*
45/*	Arguments:
46/* .IP dict_type
47/*	The official name for this type of dictionary, as used by
48/*	dict_open(3) etc. This is stored under the \fBtype\fR
49/*	member.
50/* .IP dict_name
51/*	Dictionary name. This is stored as the \fBname\fR member.
52/* .IP size
53/*	The size in bytes of the dictionary subclass structure instance.
54/* SEE ALSO
55/*	dict(3)
56/* DIAGNOSTICS
57/*	Fatal errors: the process invokes a default method.
58/* LICENSE
59/* .ad
60/* .fi
61/*	The Secure Mailer license must be distributed with this software.
62/* AUTHOR(S)
63/*	Wietse Venema
64/*	IBM T.J. Watson Research
65/*	P.O. Box 704
66/*	Yorktown Heights, NY 10598, USA
67/*--*/
68
69/* System libraries. */
70
71#include "sys_defs.h"
72
73/* Utility library. */
74
75#include "msg.h"
76#include "mymalloc.h"
77#include "myflock.h"
78#include "dict.h"
79
80/* dict_default_lookup - trap unimplemented operation */
81
82static const char *dict_default_lookup(DICT *dict, const char *unused_key)
83{
84    msg_fatal("table %s:%s: lookup operation is not supported",
85	      dict->type, dict->name);
86}
87
88/* dict_default_update - trap unimplemented operation */
89
90static int dict_default_update(DICT *dict, const char *unused_key,
91			               const char *unused_value)
92{
93    msg_fatal("table %s:%s: update operation is not supported",
94	      dict->type, dict->name);
95}
96
97/* dict_default_delete - trap unimplemented operation */
98
99static int dict_default_delete(DICT *dict, const char *unused_key)
100{
101    msg_fatal("table %s:%s: delete operation is not supported",
102	      dict->type, dict->name);
103}
104
105/* dict_default_sequence - trap unimplemented operation */
106
107static int dict_default_sequence(DICT *dict, int unused_function,
108		         const char **unused_key, const char **unused_value)
109{
110    msg_fatal("table %s:%s: sequence operation is not supported",
111	      dict->type, dict->name);
112}
113
114/* dict_default_lock - default lock handler */
115
116static int dict_default_lock(DICT *dict, int operation)
117{
118    if (dict->lock_fd >= 0) {
119	return (myflock(dict->lock_fd, dict->lock_type, operation));
120    } else {
121	return (0);
122    }
123}
124
125/* dict_default_close - trap unimplemented operation */
126
127static void dict_default_close(DICT *dict)
128{
129    msg_fatal("table %s:%s: close operation is not supported",
130	      dict->type, dict->name);
131}
132
133/* dict_alloc - allocate dictionary object, initialize super-class */
134
135DICT   *dict_alloc(const char *dict_type, const char *dict_name, ssize_t size)
136{
137    DICT   *dict = (DICT *) mymalloc(size);
138
139    dict->type = mystrdup(dict_type);
140    dict->name = mystrdup(dict_name);
141    dict->flags = DICT_FLAG_FIXED;
142    dict->lookup = dict_default_lookup;
143    dict->update = dict_default_update;
144    dict->delete = dict_default_delete;
145    dict->sequence = dict_default_sequence;
146    dict->close = dict_default_close;
147    dict->lock = dict_default_lock;
148    dict->lock_type = INTERNAL_LOCK;
149    dict->lock_fd = -1;
150    dict->stat_fd = -1;
151    dict->mtime = 0;
152    dict->fold_buf = 0;
153    dict->owner.status = DICT_OWNER_UNKNOWN;
154    dict->owner.uid = ~0;
155    dict->error = DICT_ERR_NONE;
156    dict->jbuf = 0;
157    return dict;
158}
159
160/* dict_free - super-class destructor */
161
162void    dict_free(DICT *dict)
163{
164    myfree(dict->type);
165    myfree(dict->name);
166    if (dict->jbuf)
167	myfree((char *) dict->jbuf);
168    myfree((char *) dict);
169}
170
171 /*
172  * TODO: add a dict_flags() argument to dict_alloc() and handle jump buffer
173  * allocation there.
174  */
175
176/* dict_jmp_alloc - enable exception handling */
177
178void    dict_jmp_alloc(DICT *dict)
179{
180    if (dict->jbuf == 0)
181	dict->jbuf = (DICT_JMP_BUF *) mymalloc(sizeof(DICT_JMP_BUF));
182}
183