0
|
1 /*
|
|
2 group.c
|
|
3
|
|
4 The group database resides in groupinfo.gdbm and stores all we know about
|
|
5 the groups we know of. One database record is cached in the global struct
|
|
6 grp. Group information is transfered between the grp and the database by
|
|
7 loadGrp() and saveGrp(). This is done transparently. Access to the groups
|
|
8 database is done by group name, by the functions defined in group.h.
|
|
9
|
|
10 $Id: group.c 3 2000-01-04 11:35:42Z enz $
|
|
11 */
|
|
12
|
|
13 #include "group.h"
|
|
14 #include <gdbm.h>
|
|
15 #include <errno.h>
|
|
16 #include <fcntl.h>
|
|
17 #include <sys/stat.h>
|
|
18 #include "config.h"
|
|
19 #include "log.h"
|
|
20 #include "util.h"
|
|
21
|
|
22 /* currently only used within grp */
|
|
23 typedef struct
|
|
24 {
|
|
25 int first; /* number of first article within group */
|
|
26 int last; /* number of last article within group */
|
|
27 int rmtNext;
|
|
28 time_t created;
|
|
29 time_t lastAccess;
|
|
30 } Entry;
|
|
31
|
|
32 struct
|
|
33 {
|
|
34 Str name; /* name of the group */
|
|
35 Entry entry; /* more information about this group */
|
|
36 Str serv; /* server the group resides on */
|
|
37 Str dsc; /* description of the group */
|
|
38 GDBM_FILE dbf;
|
|
39
|
|
40 } grp = { "(no grp)", { 0, 0, 0, 0, 0 }, "", "", NULL };
|
|
41
|
|
42 static const char *
|
|
43 errMsg( void )
|
|
44 {
|
|
45 if ( errno != 0 )
|
|
46 return strerror( errno );
|
|
47 return gdbm_strerror( gdbm_errno );
|
|
48 }
|
|
49
|
|
50 Bool
|
|
51 Grp_open( void )
|
|
52 {
|
|
53 Str name;
|
|
54 int flags;
|
|
55
|
|
56 ASSERT( grp.dbf == NULL );
|
|
57 snprintf( name, MAXCHAR, "%s/data/groupinfo.gdbm", Cfg_spoolDir() );
|
|
58 flags = GDBM_WRCREAT | GDBM_FAST;
|
|
59 if ( ! ( grp.dbf = gdbm_open( name, 512, flags, 0644, NULL ) ) )
|
|
60 {
|
|
61 Log_err( "Error opening %s for r/w (%s)", errMsg() );
|
|
62 return FALSE;
|
|
63 }
|
|
64 Log_dbg( "%s opened for r/w", name );
|
|
65 return TRUE;
|
|
66 }
|
|
67
|
|
68 void
|
|
69 Grp_close( void )
|
|
70 {
|
|
71 ASSERT( grp.dbf );
|
|
72 Log_dbg( "Closing groupinfo" );
|
|
73 gdbm_close( grp.dbf );
|
|
74 grp.dbf = NULL;
|
|
75 }
|
|
76
|
|
77 /* Load group info from gdbm-database into global struct grp */
|
|
78 static Bool
|
|
79 loadGrp( const char *name )
|
|
80 {
|
|
81 const char *p;
|
|
82 datum key, val;
|
|
83
|
|
84 ASSERT( grp.dbf );
|
|
85 if ( strcmp( grp.name, name ) == 0 )
|
|
86 return TRUE;
|
|
87 key.dptr = (void *)name;
|
|
88 key.dsize = strlen( name ) + 1;
|
|
89 val = gdbm_fetch( grp.dbf, key );
|
|
90 if ( val.dptr == NULL )
|
|
91 return FALSE;
|
|
92 grp.entry = *( (Entry *)val.dptr );
|
|
93 p = val.dptr + sizeof( grp.entry );
|
|
94 Utl_cpyStr( grp.serv, p );
|
|
95 p += strlen( p ) + 1;
|
|
96 Utl_cpyStr( grp.dsc, p );
|
|
97 Utl_cpyStr( grp.name, name );
|
|
98 free( val.dptr );
|
|
99 return TRUE;
|
|
100 }
|
|
101
|
|
102 /* Save group info from global struct grp into gdbm-database */
|
|
103 static void
|
|
104 saveGrp( void )
|
|
105 {
|
|
106 size_t lenServ, lenDsc, bufLen;
|
|
107 datum key, val;
|
|
108 void *buf;
|
|
109 char *p;
|
|
110
|
|
111 ASSERT( grp.dbf );
|
|
112 lenServ = strlen( grp.serv );
|
|
113 lenDsc = strlen( grp.dsc );
|
|
114 bufLen = sizeof( grp.entry ) + lenServ + lenDsc + 2;
|
|
115 buf = malloc( bufLen );
|
|
116 memcpy( buf, (void *)&grp.entry, sizeof( grp.entry ) );
|
|
117 p = (char *)buf + sizeof( grp.entry );
|
|
118 strcpy( p, grp.serv );
|
|
119 p += lenServ + 1;
|
|
120 strcpy( p, grp.dsc );
|
|
121 key.dptr = (void *)grp.name;
|
|
122 key.dsize = strlen( grp.name ) + 1;
|
|
123 val.dptr = buf;
|
|
124 val.dsize = bufLen;
|
|
125 if ( gdbm_store( grp.dbf, key, val, GDBM_REPLACE ) != 0 )
|
|
126 Log_err( "Could not save group %s: %s", errMsg() );
|
|
127 free( buf );
|
|
128 }
|
|
129
|
|
130 Bool
|
|
131 Grp_exists( const char *name )
|
|
132 {
|
|
133 datum key;
|
|
134
|
|
135 ASSERT( grp.dbf );
|
|
136 key.dptr = (void*)name;
|
|
137 key.dsize = strlen( name ) + 1;
|
|
138 return gdbm_exists( grp.dbf, key );
|
|
139 }
|
|
140
|
|
141 void
|
|
142 Grp_create( const char *name )
|
|
143 {
|
|
144 Utl_cpyStr( grp.name, name );
|
|
145 Utl_cpyStr( grp.serv, "(unknown)" );
|
|
146 grp.dsc[ 0 ] = '\0';
|
|
147 grp.entry.first = 0;
|
|
148 grp.entry.last = 0;
|
|
149 grp.entry.rmtNext = 0;
|
|
150 grp.entry.created = 0;
|
|
151 grp.entry.lastAccess = 0;
|
|
152 saveGrp();
|
|
153 }
|
|
154
|
|
155 const char *
|
|
156 Grp_dsc( const char *name )
|
|
157 {
|
|
158 if ( ! loadGrp( name ) )
|
|
159 return NULL;
|
|
160 return grp.dsc;
|
|
161 }
|
|
162
|
|
163 const char *
|
|
164 Grp_serv( const char *name )
|
|
165 {
|
|
166 static Str serv = "";
|
|
167
|
|
168 if ( ! loadGrp( name ) )
|
|
169 return "[unknown grp]";
|
|
170 if ( Cfg_servListContains( grp.serv ) )
|
|
171 Utl_cpyStr( serv, grp.serv );
|
|
172 else
|
|
173 snprintf( serv, MAXCHAR, "[%s]", grp.serv );
|
|
174 return serv;
|
|
175 }
|
|
176
|
|
177 int
|
|
178 Grp_first( const char *name )
|
|
179 {
|
|
180 if ( ! loadGrp( name ) )
|
|
181 return 0;
|
|
182 return grp.entry.first;
|
|
183 }
|
|
184
|
|
185 int
|
|
186 Grp_last( const char *name )
|
|
187 {
|
|
188 if ( ! loadGrp( name ) )
|
|
189 return 0;
|
|
190 return grp.entry.last;
|
|
191 }
|
|
192
|
|
193 int
|
|
194 Grp_lastAccess( const char *name )
|
|
195 {
|
|
196 if ( ! loadGrp( name ) )
|
|
197 return 0;
|
|
198 return grp.entry.lastAccess;
|
|
199 }
|
|
200
|
|
201 int
|
|
202 Grp_rmtNext( const char *name )
|
|
203 {
|
|
204 if ( ! loadGrp( name ) )
|
|
205 return 0;
|
|
206 return grp.entry.rmtNext;
|
|
207 }
|
|
208
|
|
209 time_t
|
|
210 Grp_created( const char *name )
|
|
211 {
|
|
212 if ( ! loadGrp( name ) )
|
|
213 return 0;
|
|
214 return grp.entry.created;
|
|
215 }
|
|
216
|
|
217 /* Replace group's description (only if value != ""). */
|
|
218 void
|
|
219 Grp_setDsc( const char *name, const char *value )
|
|
220 {
|
|
221 if ( loadGrp( name ) )
|
|
222 {
|
|
223 Utl_cpyStr( grp.dsc, value );
|
|
224 saveGrp();
|
|
225 }
|
|
226 }
|
|
227
|
|
228 void
|
|
229 Grp_setServ( const char *name, const char *value )
|
|
230 {
|
|
231 if ( loadGrp( name ) )
|
|
232 {
|
|
233 Utl_cpyStr( grp.serv, value );
|
|
234 saveGrp();
|
|
235 }
|
|
236 }
|
|
237
|
|
238 void
|
|
239 Grp_setCreated( const char *name, time_t value )
|
|
240 {
|
|
241 if ( loadGrp( name ) )
|
|
242 {
|
|
243 grp.entry.created = value;
|
|
244 saveGrp();
|
|
245 }
|
|
246 }
|
|
247
|
|
248 void
|
|
249 Grp_setRmtNext( const char *name, int value )
|
|
250 {
|
|
251 if ( loadGrp( name ) )
|
|
252 {
|
|
253 grp.entry.rmtNext = value;
|
|
254 saveGrp();
|
|
255 }
|
|
256 }
|
|
257
|
|
258 void
|
|
259 Grp_setLastAccess( const char *name, int value )
|
|
260 {
|
|
261 if ( loadGrp( name ) )
|
|
262 {
|
|
263 grp.entry.lastAccess = value;
|
|
264 saveGrp();
|
|
265 }
|
|
266 }
|
|
267
|
|
268 void
|
|
269 Grp_setFirstLast( const char *name, int first, int last )
|
|
270 {
|
|
271 if ( loadGrp( name ) )
|
|
272 {
|
|
273 grp.entry.first = first;
|
|
274 grp.entry.last = last;
|
|
275 saveGrp();
|
|
276 }
|
|
277 }
|
|
278
|
|
279 static datum cursor = { NULL, 0 };
|
|
280
|
|
281 Bool
|
|
282 Grp_firstGrp( const char **name )
|
|
283 {
|
|
284 ASSERT( grp.dbf );
|
|
285 if ( cursor.dptr != NULL )
|
|
286 {
|
|
287 free( cursor.dptr );
|
|
288 cursor.dptr = NULL;
|
|
289 }
|
|
290 cursor = gdbm_firstkey( grp.dbf );
|
|
291 *name = cursor.dptr;
|
|
292 return ( cursor.dptr != NULL );
|
|
293 }
|
|
294
|
|
295 Bool
|
|
296 Grp_nextGrp( const char **name )
|
|
297 {
|
|
298 void *oldDptr = cursor.dptr;
|
|
299
|
|
300 ASSERT( grp.dbf );
|
|
301 if ( cursor.dptr == NULL )
|
|
302 return FALSE;
|
|
303 cursor = gdbm_nextkey( grp.dbf, cursor );
|
|
304 free( oldDptr );
|
|
305 *name = cursor.dptr;
|
|
306 return ( cursor.dptr != NULL );
|
|
307 }
|