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