]> andersk Git - moira.git/blame - gen/mailhub.qc
Used /bin/sh format instead of /bin/csh format, by accident.
[moira.git] / gen / mailhub.qc
CommitLineData
8e7a00be 1
63812b62 2/* $Header$
3 *
8e7a00be 4 * This generates the /usr/lib/aliases file for the mailhub.
63812b62 5 *
6 * (c) Copyright 1988 by the Massachusetts Institute of Technology.
7 * For copying and distribution information, please see the file
8 * <mit-copyright.h>.
9 */
10
11#include <mit-copyright.h>
12#include <stdio.h>
13#include <string.h>
14#include <ctype.h>
2ce085d2 15#include <moira.h>
16#include <moira_site.h>
63812b62 17#include <sys/types.h>
18#include <sys/stat.h>
19#include <sys/time.h>
20
8e7a00be 21
63812b62 22extern int errno;
8e7a00be 23char *whoami = "mailhub.gen";
63812b62 24char *ingres_date_and_time();
259dae79 25char *perm_malloc();
15437d42 26char *pstrsave();
8e7a00be 27char *divide = "##############################################################";
28
29#define ML_WID 72
30#define AL_MAX_WID 896
31
32#define FALSE 0
33#define TRUE (!FALSE)
63812b62 34
ed742a8a 35FILE *out= stdout;
36
63812b62 37
38main(argc, argv)
39int argc;
40char **argv;
41{
42 long tm = time(NULL);
63812b62 43 char filename[64], *targetfile;
44 struct stat sb;
45## int flag;
46## char *filetime;
47 int ingerr();
48
49 IIseterr(ingerr);
50## ingres sms
51## set lockmode session where level = table
52
53 if (argc == 2) {
54 if (stat(argv[1], &sb) == 0) {
55 filetime = ingres_date_and_time(sb.st_mtime);
56## retrieve (flag = int4(interval("min",tblstats.modtime - filetime)))
57## where tblstats.table = "users"
58 if (flag < 0) {
59 fprintf(stderr, "File %s does not need to be rebuilt.\n",
60 argv[1]);
2ce085d2 61 exit(MR_NO_CHANGE);
63812b62 62 }
63 }
64 targetfile = argv[1];
65 sprintf(filename, "%s~", targetfile);
66 if ((out = fopen(filename, "w")) == NULL) {
67 fprintf(stderr, "unable to open %s for output\n", filename);
2ce085d2 68 exit(MR_OCONFIG);
63812b62 69 }
70 } else if (argc != 1) {
71 fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
2ce085d2 72 exit(MR_ARGS);
63812b62 73 }
74
75 fprintf(out, "%s\n# Aliases File Extract of %s", divide, ctime(&tm));
76 fprintf(out, "# This file is automatically generated, do not edit it directly.\n%s\n\n", divide);
77
78## begin transaction
79 get_info();
80## end transaction
81## exit
82
83 fprintf(stderr, "Sorting Info\n");
84 sort_info();
85
86 fprintf(stderr, "Dumping information\n");
ed742a8a 87 do_people();
63812b62 88
89 fprintf(out, "\n%s\n# End of aliases file\n", divide);
90
91 if (fclose(out)) {
92 perror("close failed");
2ce085d2 93 exit(MR_CCONFIG);
63812b62 94 }
95
96 if (argc == 2)
97 fix_file(targetfile);
2ce085d2 98 exit(MR_SUCCESS);
63812b62 99}
100
101
102/*
103 * ingerr: (supposedly) called when Ingres indicates an error.
104 * I have not yet been able to get this to work to intercept a
105 * database open error.
106 */
107#define INGRES_DEADLOCK 4700
108
109static int ingerr(num)
110 int *num;
111{
112 char buf[256];
113 int ingres_errno;
114
115 switch (*num) {
116 case INGRES_DEADLOCK:
2ce085d2 117 ingres_errno = MR_DEADLOCK;
63812b62 118 break;
119 default:
2ce085d2 120 ingres_errno = MR_INGRES_ERR;
63812b62 121 }
2ce085d2 122 com_err(whoami, MR_INGRES_ERR, " code %d\n", *num);
63812b62 123 critical_alert("DCM", "Alias build encountered INGRES ERROR %d", *num);
124 exit(ingres_errno);
125}
126
8e7a00be 127struct hash *users, *machines, *strings, *lists, *names;
63812b62 128struct user {
129 char *login;
63812b62 130 char *first;
131 char *last;
132 char mi;
63812b62 133 char *pobox;
63812b62 134};
8e7a00be 135struct member {
136 struct member *next;
137 char *name;
138 int list_id;
139};
140struct list {
141 char *name;
142 char maillist;
143 char acl_t;
144 int acl_id;
145 struct member *m;
146};
63812b62 147struct names {
148 char *name;
149 struct names *next;
8e7a00be 150 int keep:1;
151 int id:31;
63812b62 152};
153
154
155get_info()
156##{
8e7a00be 157## int id, pid, bid, stat, cnt, maillistp, acl, mid;
158## char name[129], type[9], fname[17], mname[17], lname[17], buf[257];
159 char *s;
63812b62 160 register struct user *u;
8e7a00be 161 struct list *l, *memberlist;
162 register struct member *m;
63812b62 163
164 /* get locks */
165## retrieve (buf = users.modtime) where users.users_id = 0
8e7a00be 166## retrieve (buf = list.modtime) where list.list_id = 0
63812b62 167
168 cnt = 0;
ed742a8a 169 machines = create_hash(10);
170## retrieve (id = machine.mach_id, name = machine.#name)
171## where machine.mach_id = users.pop_id {
63812b62 172 if (s = index(name, '.'))
173 *s = 0;
ed742a8a 174 else
175 strtrim(name);
259dae79 176#ifdef ATHENA
15437d42 177 strcat(name, ".LOCAL");
259dae79 178#endif
15437d42 179 if (hash_store(machines, id, pstrsave(name)) < 0) {
8e7a00be 180 fprintf(stderr, "Out of memory!\n");
2ce085d2 181 exit(MR_NO_MEM);
8e7a00be 182 }
63812b62 183 cnt++;
184## }
185 fprintf(stderr, "Loaded %d machines\n", cnt);
186
187 cnt = 0;
ed742a8a 188 strings = create_hash(4000);
63812b62 189## retrieve (id = strings.string_id, name = strings.string) {
15437d42 190 if (hash_store(strings, id, pstrsave(strtrim(name))) < 0) {
8e7a00be 191 fprintf(stderr, "Out of memory!\n");
2ce085d2 192 exit(MR_NO_MEM);
8e7a00be 193 }
63812b62 194 cnt++;
195## }
196 fprintf(stderr, "Loaded %d strings\n", cnt);
197
198 cnt = 0;
8e7a00be 199 users = create_hash(12001);
63812b62 200## range of u is users
8e7a00be 201## retrieve (id = u.users_id, name = u.login, fname = u.first,
202## mname = u.middle, lname = u.last,
203## type = u.potype, pid = u.pop_id, bid = u.box_id)
204## where u.status != 3 {
259dae79 205 u = (struct user *) perm_malloc(sizeof(struct user));
15437d42 206 u->login = pstrsave(strtrim(name));
207 u->first = pstrsave(strtrim(fname));
208 u->last = pstrsave(strtrim(lname));
63812b62 209 if (mname[0] != ' ')
210 u->mi = mname[0];
211 else
212 u->mi = 0;
63812b62 213
8e7a00be 214 if (type[0] == 'P' && (s = hash_lookup(machines, pid))) {
ed742a8a 215 sprintf(buf, "%s@%s", u->login, s);
15437d42 216 u->pobox = pstrsave(buf);
8e7a00be 217 } else if (type[0] == 'S') {
218 u->pobox = hash_lookup(strings, bid);
63812b62 219 } else
8e7a00be 220 u->pobox = (char *) NULL;
221 if (hash_store(users, id, u) < 0) {
222 fprintf(stderr, "Out of memory!\n");
2ce085d2 223 exit(MR_NO_MEM);
63812b62 224 }
63812b62 225 cnt++;
226## }
227 fprintf(stderr, "Loaded %d users\n", cnt);
8e7a00be 228
229 cnt = 0;
230 lists = create_hash(15000);
231## range of l is list
232## retrieve (id = l.list_id, name = l.#name, maillistp = l.maillist,
233## type = l.acl_type, acl = l.acl_id)
234## where l.active != 0 {
259dae79 235 l = (struct list *) perm_malloc(sizeof(struct list));
15437d42 236 l->name = pstrsave(strtrim(name));
8e7a00be 237 l->maillist = maillistp;
238 l->acl_t = type[0];
239 l->acl_id = acl;
240 l->m = (struct member *) NULL;
241 if (hash_store(lists, id, l) < 0) {
242 fprintf(stderr, "Out of memory!\n");
2ce085d2 243 exit(MR_NO_MEM);
8e7a00be 244 }
245 cnt++;
246## }
247 fprintf(stderr, "Loaded %d lists\n", cnt);
248
249 cnt = 0;
250## range of m is imembers
251## retrieve (id = m.list_id, type = m.member_type, mid = m.member_id)
252## where m.direct = 1 {
253 cnt++;
254 if (l = (struct list *) hash_lookup(lists, id)) {
259dae79 255 m = (struct member *) perm_malloc(sizeof(struct member));
8e7a00be 256 if (type[0] == 'U' &&
257 (u = (struct user *) hash_lookup(users, mid))) {
258 m->list_id = 0;
259 m->name = u->login;
260 m->next = l->m;
261 l->m = m;
262 } else if (type[0] == 'L' &&
263 (memberlist = (struct list *) hash_lookup(lists, mid))) {
264 m->list_id = mid;
265 m->name = memberlist->name;
266 m->next = l->m;
267 l->m = m;
268 } else if (type[0] == 'S' &&
269 (s = hash_lookup(strings, mid))) {
270 m->list_id = 0;
271 m->next = l->m;
272 l->m = m;
273 m->name = s;
274 }
275 }
276## }
277 fprintf(stderr, "Loaded %d members\n", cnt);
63812b62 278##}
279
280
8e7a00be 281save_mlist(id, l, force)
282int id;
283struct list *l;
284int force;
63812b62 285{
8e7a00be 286 register struct member *m;
287 register struct list *l1;
288
ed742a8a 289 if (l->maillist > 1 ||
8e7a00be 290 (l->maillist == 0 && !force))
291 return;
292
293 if (l->m && l->m->next == NULL &&
294 !strcasecmp(l->name, l->m->name)) {
295 l->maillist = 3;
296 return;
63812b62 297 }
8e7a00be 298 l->maillist = 2;
ed742a8a 299 insert_name(l->name, -1, TRUE, FALSE);
300 output_mlist(id, l);
8e7a00be 301
302 if (l->acl_t == 'L' && (l1 = (struct list *)hash_lookup(lists, l->acl_id)))
303 save_mlist(0, l1, TRUE);
304
305 for (m = l->m; m; m = m->next) {
306 if (m->list_id && (l1 = (struct list *)hash_lookup(lists, m->list_id)))
307 save_mlist(0, l1, TRUE);
63812b62 308 }
63812b62 309}
310
311
8e7a00be 312insert_login(id, u, dummy)
313int id;
314struct user *u;
315int dummy;
316{
317 if (u->pobox && u->login[0] != '#')
318 insert_name(u->login, id, TRUE, FALSE);
319}
320
63812b62 321void insert_names(id, u, dummy)
322int id;
323struct user *u;
324int dummy;
325{
326 char buffer[256];
327
8e7a00be 328 insert_name(u->last, id, FALSE, FALSE);
63812b62 329 sprintf(buffer, "%s_%s", u->first, u->last);
8e7a00be 330 insert_name(buffer, id, FALSE, TRUE);
e1707f53 331/* sprintf(buffer, "%c_%s", u->first[0], u->last);
332 insert_name(buffer, id, FALSE, TRUE); */
63812b62 333 if (u->mi) {
334 sprintf(buffer, "%s_%c_%s", u->first, u->mi, u->last);
8e7a00be 335 insert_name(buffer, id, FALSE, TRUE);
63812b62 336 }
337}
338
339int incount = 0;
340
8e7a00be 341insert_name(s, id, nodups, copy)
63812b62 342char *s;
343int id;
8e7a00be 344int nodups;
345int copy;
63812b62 346{
347 int code;
348 register struct names *ns;
349 register int count;
350 register struct idblock *ra;
351
352 incount++;
353 code = hashstr(s);
354 ns = (struct names *) hash_lookup(names, code);
355 if (ns == NULL) {
259dae79 356 if ((ns = (struct names *) perm_malloc(sizeof(struct names))) == NULL) {
63812b62 357 fprintf(stderr, "ran out of memory inserting name (sorting)\n");
2ce085d2 358 exit(MR_NO_MEM);
8e7a00be 359 }
360 if (copy)
15437d42 361 ns->name = pstrsave(s);
8e7a00be 362 else
363 ns->name = s;
364 ns->keep = nodups;
365 ns->id = id;
ed742a8a 366 ns->next = NULL;
8e7a00be 367 if (hash_store(names, code, ns) < 0) {
368 fprintf(stderr, "Out of memory!\n");
2ce085d2 369 exit(MR_NO_MEM);
63812b62 370 }
63812b62 371 return;
372 }
373 if (strcasecmp(ns->name, s)) {
374 while (ns->next) {
375 ns = ns->next;
376 if (!strcasecmp(ns->name, s))
377 goto foundns;
378 }
259dae79 379 if ((ns->next = (struct names *) perm_malloc(sizeof(struct names)))
380 == NULL) {
63812b62 381 fprintf(stderr, "ran out of memory insterting name (sorting)\n");
2ce085d2 382 exit(MR_NO_MEM);
63812b62 383 }
384 ns = ns->next;
8e7a00be 385 if (copy)
15437d42 386 ns->name = pstrsave(s);
8e7a00be 387 else
388 ns->name = s;
389 ns->keep = nodups;
390 ns->id = id;
ed742a8a 391 ns->next = NULL;
63812b62 392 return;
393 }
394 foundns:
ed742a8a 395 if (nodups || ns->keep) {
396 if (nodups && ns->keep)
397 fprintf(stderr, "duplicated named: %s\n", s);
398 return;
399 }
8e7a00be 400 ns->id = 0;
63812b62 401}
402
403
259dae79 404/* Illegal chars: ! " % ( ) , . / : ; < = > @ [ \ ] ^ { | } */
405
406static int illegalchars[] = {
407 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
408 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
409 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, /* SPACE - / */
410 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, /* 0 - ? */
411 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
412 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* P - _ */
413 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
414 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
415 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
416 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
417 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
418 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
419 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
420 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
421 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
422 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
423};
424
425
426/* While hashing the string, punt any illegal characters */
427
63812b62 428int hashstr(s)
429register char *s;
430{
431 register int result;
432 register int c;
433
8e7a00be 434 for (result = 0; c = *s; s++) {
259dae79 435 if (illegalchars[c]) {
436 register char *p;
437 for (p = s; *p; p++)
438 *p = p[1];
439 continue;
440 }
8e7a00be 441 if (isupper(c))
442 c = *s = tolower(c);
63812b62 443/* result = result * 31 + *s; */
8e7a00be 444 result = (result << 5) - result + c - '`';
63812b62 445 }
446 return(result < 0 ? -result : result);
447}
448
449
450sort_info()
451{
8e7a00be 452 names = create_hash(20001);
453 hash_step(users, insert_login, NULL);
ed742a8a 454 incount = 0;
455 fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
8e7a00be 456 hash_step(lists, save_mlist, FALSE);
ed742a8a 457 fprintf(stderr, "Output %d lists\n", incount);
63812b62 458 hash_step(users, insert_names, NULL);
459 fprintf(stderr, "Inserted %d names\n", incount);
460}
461
462
63812b62 463output_data(dummy, nms, out)
464int dummy;
465struct names *nms;
466FILE *out;
467{
468 register struct names *ns;
469 register struct user *u;
63812b62 470
471 incount++;
472 for (ns = nms; ns; ns = ns->next) {
8e7a00be 473 if (ns->name[0] == 0 || ns->name[1] == 0) {
474 fprintf(stderr, "punting %s due to short name\n", ns->name);
475 continue;
476 }
477 if (ns->id > 0) {
478 u = (struct user *) hash_lookup(users, ns->id);
63812b62 479 if (u->pobox) {
480 fprintf(out, "%s: %s\n", ns->name, u->pobox);
8e7a00be 481 } else {
482 fprintf(out, "%s: =%s=@nobox\n", ns->name, ns->name);
63812b62 483 }
8e7a00be 484 } else if (ns->id == 0) {
485 fprintf(out, "%s: =%s=@ambig\n", ns->name, ns->name);
63812b62 486 }
487 }
488}
489
490
8e7a00be 491int lwid, bol, awid;
492
ed742a8a 493output_mlist(id, l)
8e7a00be 494int id;
495register struct list *l;
8e7a00be 496{
497 struct list *l1;
498 register struct member *m;
499 register struct user *u;
500
8e7a00be 501 if (l->acl_t == 'L' &&
502 (l1 = (struct list *) hash_lookup(lists, l->acl_id)))
259dae79 503 fprintf(out, "owner-%s: %s\n%s: ", l->name, l1->name, l->name);
8e7a00be 504 else if (l->acl_t == 'U' &&
505 (u = (struct user *) hash_lookup(users, l->acl_id)))
259dae79 506 fprintf(out, "owner-%s: %s\n%s: ", l->name, u->login, l->name);
15437d42 507 else
508 fprintf(out, "%s: ", l->name);
509
8e7a00be 510
8e7a00be 511 lwid = strlen(l->name) + 2;
512 bol = 1;
513 for (m = l->m; m; m = m->next) {
514 do_member(out, m->name);
515 }
516 if (l->m == (struct member *)NULL)
517 fprintf(out, "/dev/null");
518 fprintf(out, "\n\n");
519 incount++;
520}
521
522
523/* print out strings separated by commas, doing line breaks as appropriate */
524
525do_member(out, s)
526FILE *out;
527register char *s;
528{
529 register wwid;
530 static int cont = 1;
531
532 wwid = strlen(s);
533
534 if (!bol && awid + wwid + 2 > AL_MAX_WID) {
535 fprintf(out, ",\n\tcontinuation-%d\ncontinuation-%d: ", cont, cont);
536 cont++;
537 awid = lwid = 17 + wwid;
538 fputs(s, out);
539 return;
540 }
541
542 if (bol) {
543 lwid += wwid;
544 awid = lwid;
545 fputs(s, out);
546 bol = 0;
547 return;
548 }
549 if (lwid + wwid + 2 > ML_WID) {
550 fprintf(out, ",\n\t%s", s);
551 awid += lwid + wwid + 2;
552 lwid = wwid + 8;
553 return;
554 }
555 lwid += wwid + 2;
556 fprintf(out, ", %s", s);
557}
558
559
ed742a8a 560do_people()
8e7a00be 561{
562 incount = 0;
563 fprintf(out, "\n%s\n# People\n%s\n", divide, divide);
63812b62 564 hash_step(names, output_data, out);
63812b62 565 fprintf(stderr, "Output %d entries\n", incount);
566}
259dae79 567
568
569#define chunk_size 102400
570
571char *perm_malloc(size)
572unsigned size;
573{
574 static char *pool = NULL;
575 static unsigned pool_size = 0;
576 register char *ret;
577
578 if (size > pool_size) {
579 pool = (char *) malloc(chunk_size);
580 pool_size = chunk_size;
581 }
582 ret = pool;
583 pool += size;
584 pool = (char *)(((unsigned) (pool + 1)) & ~1);
585 pool_size -= (pool - ret);
586 return(ret);
587}
588
15437d42 589
590/*
591 * Make a (permenant) copy of a string.
592 */
593char *
594pstrsave(s)
595 char *s;
596{
597 register int len;
598 register char *p;
599 /* Kludge for sloppy string semantics */
600 if (!s) {
601 printf("NULL != \"\" !!!!\r\n");
602 p = perm_malloc(1);
603 *p = '\0';
604 return p;
605 }
606 len = strlen(s) + 1;
607 p = perm_malloc((u_int)len);
608 if (p) bcopy(s, p, len);
609 return p;
610}
ed742a8a 611
612#define hash_func(h, key) (key >= 0 ? (key % h->size) : (-key % h->size))
613
614/* Create a hash table. The size is just a hint, not a maximum. */
615
616struct hash *create_hash(size)
617int size;
618{
619 struct hash *h;
620
621 h = (struct hash *) perm_malloc(sizeof(struct hash));
622 if (h == (struct hash *) NULL)
623 return((struct hash *) NULL);
624 h->size = size;
625 h->data = (struct bucket **) perm_malloc(size * sizeof(char *));
626 if (h->data == (struct bucket **) NULL) {
627 free(h);
628 return((struct hash *) NULL);
629 }
630 bzero(h->data, size * sizeof(char *));
631 return(h);
632}
633
634/* Lookup an object in the hash table. Returns the value associated with
635 * the key, or NULL (thus NULL is not a very good value to store...)
636 */
637
638char *hash_lookup(h, key)
639struct hash *h;
640register int key;
641{
642 register struct bucket *b;
643
644 b = h->data[hash_func(h, key)];
645 while (b && b->key != key)
646 b = b->next;
647 if (b && b->key == key)
648 return(b->data);
649 else
650 return(NULL);
651}
652
653
654/* Update an existing object in the hash table. Returns 1 if the object
655 * existed, or 0 if not.
656 */
657
658int hash_update(h, key, value)
659struct hash *h;
660register int key;
661char *value;
662{
663 register struct bucket *b;
664
665 b = h->data[hash_func(h, key)];
666 while (b && b->key != key)
667 b = b->next;
668 if (b && b->key == key) {
669 b->data = value;
670 return(1);
671 } else
672 return(0);
673}
674
675
676/* Store an item in the hash table. Returns 0 if the key was not previously
677 * there, 1 if it was, or -1 if we ran out of memory.
678 */
679
680int hash_store(h, key, value)
681struct hash *h;
682register int key;
683char *value;
684{
685 register struct bucket *b, **p;
686
687 p = &(h->data[hash_func(h, key)]);
688 if (*p == NULL) {
689 b = *p = (struct bucket *) perm_malloc(sizeof(struct bucket));
690 if (b == (struct bucket *) NULL)
691 return(-1);
692 b->next = NULL;
693 b->key = key;
694 b->data = value;
695 return(0);
696 }
697
698 for (b = *p; b && b->key != key; b = *p)
699 p = (struct bucket **) *p;
700 if (b && b->key == key) {
701 b->data = value;
702 return(1);
703 }
704 b = *p = (struct bucket *) perm_malloc(sizeof(struct bucket));
705 if (b == (struct bucket *) NULL)
706 return(-1);
707 b->next = NULL;
708 b->key = key;
709 b->data = value;
710 return(0);
711}
712
713
714/* Search through the hash table for a given value. For each piece of
715 * data with that value, call the callback proc with the corresponding key.
716 */
717
718hash_search(h, value, callback)
719struct hash *h;
720register char *value;
721void (*callback)();
722{
723 register struct bucket *b, **p;
724
725 for (p = &(h->data[h->size - 1]); p >= h->data; p--) {
726 for (b = *p; b; b = b->next) {
727 if (b->data == value)
728 (*callback)(b->key);
729 }
730 }
731}
732
733
734/* Step through the hash table, calling the callback proc with each key.
735 */
736
737hash_step(h, callback, hint)
738struct hash *h;
739void (*callback)();
740char *hint;
741{
742 register struct bucket *b, **p;
743
744 for (p = &(h->data[h->size - 1]); p >= h->data; p--) {
745 for (b = *p; b; b = b->next) {
746 (*callback)(b->key, b->data, hint);
747 }
748 }
749}
750
751
752/* Deallocate all of the memory associated with a table */
753
754hash_destroy(h)
755struct hash *h;
756{
757 register struct bucket *b, **p, *b1;
758
759 for (p = &(h->data[h->size - 1]); p >= h->data; p--) {
760 for (b = *p; b; b = b1) {
761 b1 = b->next;
762 free(b);
763 }
764 }
765}
This page took 0.352888 seconds and 5 git commands to generate.