]> andersk Git - moira.git/blame - gen/mailhub.dc
Changed "sms" to "Moira". Added time estimates. Filled in missing info.
[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
b188943c 156 /* Get Locks */
157
bac4ceaa 158 EXEC SQL SELECT modtime INTO :buf FROM users WHERE users_id = 0;
159 EXEC SQL SELECT modtime INTO :buf FROM list WHERE list_id = 0;
160
161 cnt = 0;
4534b281 162 machines = create_hash(1000);
bac4ceaa 163
164 EXEC SQL DECLARE m_cursor CURSOR FOR
9e1513ae 165 SELECT mach_id, name
166 FROM machine
4534b281 167 WHERE status=1
9e1513ae 168 ORDER BY mach_id;
bac4ceaa 169 EXEC SQL OPEN m_cursor;
170 while (1) {
171 EXEC SQL FETCH m_cursor INTO :id, :name;
172 if (sqlca.sqlcode != 0) break;
173 if (s = index(name, '.'))
174 *s = 0;
175 else
176 strtrim(name);
177#ifdef ATHENA
178 strcat(name, ".LOCAL");
179#endif
180 if (hash_store(machines, id, pstrsave(name)) < 0) {
181 fprintf(stderr, "Out of memory!\n");
182 exit(MR_NO_MEM);
183 }
184 cnt++;
185 }
186 EXEC SQL CLOSE m_cursor;
187
188 fprintf(stderr, "Loaded %d machines\n", cnt);
189
190 cnt = 0;
9e1513ae 191 strings = create_hash(11001);
bac4ceaa 192
193 EXEC SQL DECLARE s_cursor CURSOR FOR
9e1513ae 194 SELECT string_id, trim(string)
195 FROM strings
196 ORDER BY string_id;
bac4ceaa 197 EXEC SQL OPEN s_cursor;
198 while (1) {
199 EXEC SQL FETCH s_cursor INTO :id, :name;
200 if (sqlca.sqlcode != 0) break;
9e1513ae 201 if (hash_store(strings, id, pstrsave(name)) < 0) {
bac4ceaa 202 fprintf(stderr, "Out of memory!\n");
203 exit(MR_NO_MEM);
204 }
205 cnt++;
206 }
207 EXEC SQL CLOSE s_cursor;
208
209 fprintf(stderr, "Loaded %d strings\n", cnt);
210
211 cnt = 0;
9e1513ae 212 users = create_hash(13001);
bac4ceaa 213
214 EXEC SQL DECLARE u_cursor CURSOR FOR
215 SELECT users_id, login, first, middle, last, potype, pop_id, box_id
216 FROM users
9e1513ae 217 WHERE status != 3
218 ORDER BY users_id;
bac4ceaa 219 EXEC SQL OPEN u_cursor;
220 while (1) {
221 EXEC SQL FETCH u_cursor INTO :id, :name, :fname, :mname, :lname,
222 :type, :pid, :bid;
223 if (sqlca.sqlcode != 0) break;
224 u = (struct user *) perm_malloc(sizeof(struct user));
225 u->login = pstrsave(strtrim(name));
226 u->first = pstrsave(strtrim(fname));
227 u->last = pstrsave(strtrim(lname));
228 if (mname[0] != ' ')
229 u->mi = mname[0];
230 else
231 u->mi = 0;
232
233 if (type[0] == 'P' && (s = hash_lookup(machines, pid))) {
234 sprintf(buf, "%s@%s", u->login, s);
235 u->pobox = pstrsave(buf);
236 } else if (type[0] == 'S') {
237 u->pobox = hash_lookup(strings, bid);
238 } else
239 u->pobox = (char *) NULL;
240 if (hash_store(users, id, u) < 0) {
241 fprintf(stderr, "Out of memory!\n");
242 exit(MR_NO_MEM);
243 }
244 cnt++;
245 }
246 EXEC SQL CLOSE u_cursor;
9e1513ae 247 EXEC SQL COMMIT;
bac4ceaa 248 fprintf(stderr, "Loaded %d users\n", cnt);
249
250 cnt = 0;
251 lists = create_hash(15000);
252
253 EXEC SQL DECLARE l_cursor CURSOR FOR
492f333e 254 SELECT list_id, name, maillist, description, acl_type, acl_id
bac4ceaa 255 FROM list
9e1513ae 256 WHERE active != 0
257 ORDER BY list_id;
bac4ceaa 258 EXEC SQL OPEN l_cursor;
259 while (1) {
492f333e 260 EXEC SQL FETCH l_cursor INTO :id, :name, :maillistp, :buf, :type, :acl;
bac4ceaa 261 if (sqlca.sqlcode != 0) break;
262 l = (struct list *) perm_malloc(sizeof(struct list));
263 l->name = pstrsave(strtrim(name));
264 l->maillist = maillistp;
492f333e 265 l->description = pstrsave(strtrim(buf));
bac4ceaa 266 l->acl_t = type[0];
267 l->acl_id = acl;
268 l->m = (struct member *) NULL;
269 if (hash_store(lists, id, l) < 0) {
270 fprintf(stderr, "Out of memory!\n");
271 exit(MR_NO_MEM);
272 }
273 cnt++;
274 }
275 EXEC SQL CLOSE l_cursor;
9e1513ae 276 EXEC SQL COMMIT;
bac4ceaa 277 fprintf(stderr, "Loaded %d lists\n", cnt);
278
279 cnt = 0;
280
281 EXEC SQL DECLARE m_cursor2 CURSOR FOR
282 SELECT list_id, member_type, member_id
283 FROM imembers
9e1513ae 284 WHERE direct = 1
285 ORDER BY list_id;
bac4ceaa 286 EXEC SQL OPEN m_cursor2;
287 while (1) {
288 EXEC SQL FETCH m_cursor2 INTO :id, :type, :mid;
289 if (sqlca.sqlcode != 0) break;
290 cnt++;
291 if (l = (struct list *) hash_lookup(lists, id)) {
292 m = (struct member *) perm_malloc(sizeof(struct member));
293 if (type[0] == 'U' &&
294 (u = (struct user *) hash_lookup(users, mid))) {
295 m->list_id = 0;
296 m->name = u->login;
297 m->next = l->m;
298 l->m = m;
299 } else if (type[0] == 'L' &&
300 (memberlist = (struct list *) hash_lookup(lists, mid))) {
301 m->list_id = mid;
302 m->name = memberlist->name;
303 m->next = l->m;
304 l->m = m;
305 } else if (type[0] == 'S' &&
306 (s = hash_lookup(strings, mid))) {
307 m->list_id = 0;
308 m->next = l->m;
309 l->m = m;
310 m->name = s;
311 }
312 }
313 }
314 EXEC SQL CLOSE m_cursor2;
315 fprintf(stderr, "Loaded %d members\n", cnt);
316 return;
317 sqlerr:
318 com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
2796e83d 319 critical_alert("DCM", "Mailhub build encountered DATABASE ERROR %d",
bac4ceaa 320 sqlca.sqlcode);
321 exit(MR_INGRES_ERR);
322}
323
324
325save_mlist(id, l, force)
326int id;
327struct list *l;
328int force;
329{
330 register struct member *m;
331 register struct list *l1;
332
333 if (l->maillist > 1 ||
334 (l->maillist == 0 && !force))
335 return;
336
337 if (l->m && l->m->next == NULL &&
338 !strcasecmp(l->name, l->m->name)) {
339 l->maillist = 3;
340 return;
341 }
342 l->maillist = 2;
566f0499 343 insert_name(l->name, -1, TRUE, FALSE);
9e1513ae 344 output_mlist(id, l);
bac4ceaa 345
346 if (l->acl_t == 'L' && (l1 = (struct list *)hash_lookup(lists, l->acl_id)))
347 save_mlist(0, l1, TRUE);
348
349 for (m = l->m; m; m = m->next) {
350 if (m->list_id && (l1 = (struct list *)hash_lookup(lists, m->list_id)))
351 save_mlist(0, l1, TRUE);
352 }
353}
354
355
356insert_login(id, u, dummy)
357int id;
358struct user *u;
359int dummy;
360{
361 if (u->pobox && u->login[0] != '#')
362 insert_name(u->login, id, TRUE, FALSE);
363}
364
365void insert_names(id, u, dummy)
366int id;
367struct user *u;
368int dummy;
369{
370 char buffer[256];
371
372 insert_name(u->last, id, FALSE, FALSE);
373 sprintf(buffer, "%s_%s", u->first, u->last);
374 insert_name(buffer, id, FALSE, TRUE);
375/* sprintf(buffer, "%c_%s", u->first[0], u->last);
376 insert_name(buffer, id, FALSE, TRUE); */
377 if (u->mi) {
378 sprintf(buffer, "%s_%c_%s", u->first, u->mi, u->last);
379 insert_name(buffer, id, FALSE, TRUE);
380 }
381}
382
383int incount = 0;
384
385insert_name(s, id, nodups, copy)
386char *s;
387int id;
388int nodups;
389int copy;
390{
391 int code;
392 register struct names *ns;
393
394 incount++;
395 code = hashstr(s);
396 ns = (struct names *) hash_lookup(names, code);
397 if (ns == NULL) {
398 if ((ns = (struct names *) perm_malloc(sizeof(struct names))) == NULL) {
399 fprintf(stderr, "ran out of memory inserting name (sorting)\n");
400 exit(MR_NO_MEM);
401 }
402 if (copy)
403 ns->name = pstrsave(s);
404 else
405 ns->name = s;
406 ns->keep = nodups;
407 ns->id = id;
408 ns->next = NULL;
409 if (hash_store(names, code, ns) < 0) {
410 fprintf(stderr, "Out of memory!\n");
411 exit(MR_NO_MEM);
412 }
413 return;
414 }
415 if (strcasecmp(ns->name, s)) {
416 while (ns->next) {
417 ns = ns->next;
418 if (!strcasecmp(ns->name, s))
419 goto foundns;
420 }
421 if ((ns->next = (struct names *) perm_malloc(sizeof(struct names)))
422 == NULL) {
423 fprintf(stderr, "ran out of memory insterting name (sorting)\n");
424 exit(MR_NO_MEM);
425 }
426 ns = ns->next;
427 if (copy)
428 ns->name = pstrsave(s);
429 else
430 ns->name = s;
431 ns->keep = nodups;
432 ns->id = id;
433 ns->next = NULL;
434 return;
435 }
436 foundns:
437 if (nodups || ns->keep) {
438 if (nodups && ns->keep)
439 fprintf(stderr, "duplicated name: %s\n", s);
440 return;
441 }
442 ns->id = 0;
443}
444
445
3ce369ab 446/* Illegal chars: ! " % ( ) , / : ; < = > @ [ \ ] ^ { | } */
bac4ceaa 447
448static int illegalchars[] = {
449 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
450 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3ce369ab 451 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, /* SPACE - / */
bac4ceaa 452 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, /* 0 - ? */
453 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
454 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* P - _ */
455 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
456 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
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 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
463 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
464 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
465};
466
467
468/* While hashing the string, punt any illegal characters */
469
470int hashstr(s)
471register char *s;
472{
473 register int result;
474 register int c;
475
476 for (result = 0; c = *s; s++) {
477 if (illegalchars[c]) {
478 register char *p;
479 for (p = s; *p; p++)
480 *p = p[1];
481 continue;
482 }
483 if (isupper(c))
484 c = *s = tolower(c);
485/* result = result * 31 + *s; */
486 result = (result << 5) - result + c - '`';
487 }
488 return(result < 0 ? -result : result);
489}
490
491
492sort_info()
493{
494 names = create_hash(20001);
495 hash_step(users, insert_login, NULL);
496 incount = 0;
497 fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
498 hash_step(lists, save_mlist, FALSE);
499 fprintf(stderr, "Output %d lists\n", incount);
500 hash_step(users, insert_names, NULL);
501 fprintf(stderr, "Inserted %d names\n", incount);
502}
503
504
505output_data(dummy, nms, out)
506int dummy;
507struct names *nms;
508FILE *out;
509{
510 register struct names *ns;
511 register struct user *u;
512
513 incount++;
514 for (ns = nms; ns; ns = ns->next) {
515 if (ns->name[0] == 0 || ns->name[1] == 0) {
516 fprintf(stderr, "punting %s due to short name\n", ns->name);
517 continue;
518 }
519 if (ns->id > 0) {
520 u = (struct user *) hash_lookup(users, ns->id);
521 if (u->pobox) {
522 fprintf(out, "%s: %s\n", ns->name, u->pobox);
523 } else {
524 fprintf(out, "%s: =%s=@nobox\n", ns->name, ns->name);
525 }
526 } else if (ns->id == 0) {
527 fprintf(out, "%s: =%s=@ambig\n", ns->name, ns->name);
528 }
529 }
530}
531
532
533int lwid, bol, awid;
534
535output_mlist(id, l)
536int id;
537register struct list *l;
538{
539 struct list *l1;
540 register struct member *m;
541 register struct user *u;
542
492f333e 543 put_fill(out, l->description);
bac4ceaa 544 if (l->acl_t == 'L' &&
545 (l1 = (struct list *) hash_lookup(lists, l->acl_id)))
546 fprintf(out, "owner-%s: %s\n%s: ", l->name, l1->name, l->name);
547 else if (l->acl_t == 'U' &&
548 (u = (struct user *) hash_lookup(users, l->acl_id)))
549 fprintf(out, "owner-%s: %s\n%s: ", l->name, u->login, l->name);
550 else
551 fprintf(out, "%s: ", l->name);
552
553
554 lwid = strlen(l->name) + 2;
555 bol = 1;
556 for (m = l->m; m; m = m->next) {
557 do_member(out, m->name);
558 }
559 if (l->m == (struct member *)NULL)
560 fprintf(out, "/dev/null");
561 fprintf(out, "\n\n");
562 incount++;
563}
564
565
566/* print out strings separated by commas, doing line breaks as appropriate */
567
568do_member(out, s)
569FILE *out;
570register char *s;
571{
572 register wwid;
573 static int cont = 1;
2796e83d 574 char str[8];
bac4ceaa 575
576 wwid = strlen(s);
577
578 if (!bol && awid + wwid + 2 > AL_MAX_WID) {
2796e83d 579 sprintf(str, "%c%c%c%c%c%c", random() % 26 + 97, random() % 26 + 97,
580 random() % 26 + 97, random() % 26 + 97,
581 random() % 26 + 97, random() % 26 + 97);
582 str[6] = '\0';
583 fprintf(out, ",\n\tcont%d-%s\ncont%d-%s: ", cont, str, cont, str);
bac4ceaa 584 cont++;
585 awid = lwid = 17 + wwid;
586 fputs(s, out);
587 return;
588 }
589
590 if (bol) {
591 lwid += wwid;
592 awid = lwid;
593 fputs(s, out);
594 bol = 0;
595 return;
596 }
597 if (lwid + wwid + 2 > ML_WID) {
598 fprintf(out, ",\n\t%s", s);
599 awid += lwid + wwid + 2;
600 lwid = wwid + 8;
601 return;
602 }
603 lwid += wwid + 2;
604 fprintf(out, ", %s", s);
605}
606
607
492f333e 608put_fill(aliases, string)
609FILE *aliases;
610register char *string;
611{
612 register char *c;
613 register int lwid;
614 register int wwid;
615
616 if (string == 0 || *string == 0) return;
617 fputs("# ", aliases);
618 lwid = 3;
619
620 while (1) {
621 while (*string && *string == ' ') string++;
622 c = (char *)index(string, ' ');
623 if (c == 0) {
624 wwid = strlen(string);
625 } else {
626 wwid = c - string;
627 *c = 0;
628 }
629
630 if ((lwid + wwid) > ML_WID) {
631 fputs("\n# ", aliases);
632 lwid = 3;
633 fputs(string, aliases);
634 } else {
635 fputs(string, aliases);
636 }
637
638 if (c == (char *)0) break;
639 /* add a space after the word */
640 (void) fputc(' ', aliases);
641 wwid++;
642 lwid += wwid;
643 string += wwid;
644 /* add another if after a period */
645 if (*--c == '.') {
646 (void) fputc(' ', aliases);
647 lwid++;
648 }
649 }
650
651 (void) fputc('\n', aliases);
652}
653
654
bac4ceaa 655do_people()
656{
657 incount = 0;
658 fprintf(out, "\n%s\n# People\n%s\n", divide, divide);
659 hash_step(names, output_data, out);
660 fprintf(stderr, "Output %d entries\n", incount);
661}
662
663
664#define chunk_size 102400
665
666char *perm_malloc(size)
667unsigned size;
668{
669 static char *pool = NULL;
670 static unsigned pool_size = 0;
671 register char *ret;
672
673 if (size > pool_size) {
674 pool = (char *) malloc(chunk_size);
675 pool_size = chunk_size;
676 }
677 ret = pool;
678 pool += size;
cf813189 679 pool = (char *)(((unsigned) (pool + 3)) & ~3);
bac4ceaa 680 pool_size -= (pool - ret);
681 return(ret);
682}
683
684
685/*
686 * Make a (permenant) copy of a string.
687 */
688char *
689pstrsave(s)
690 char *s;
691{
692 register int len;
693 register char *p;
694 /* Kludge for sloppy string semantics */
695 if (!s) {
696 printf("NULL != \"\" !!!!\r\n");
697 p = perm_malloc(1);
698 *p = '\0';
699 return p;
700 }
701 len = strlen(s) + 1;
702 p = perm_malloc((u_int)len);
703 if (p) bcopy(s, p, len);
704 return p;
705}
706
707#define hash_func(h, key) (key >= 0 ? (key % h->size) : (-key % h->size))
708
709/* Create a hash table. The size is just a hint, not a maximum. */
710
711struct hash *create_hash(size)
712int size;
713{
714 struct hash *h;
715
716 h = (struct hash *) perm_malloc(sizeof(struct hash));
717 if (h == (struct hash *) NULL)
718 return((struct hash *) NULL);
719 h->size = size;
720 h->data = (struct bucket **) perm_malloc(size * sizeof(char *));
721 if (h->data == (struct bucket **) NULL) {
722 free(h);
723 return((struct hash *) NULL);
724 }
725 bzero(h->data, size * sizeof(char *));
726 return(h);
727}
728
729/* Lookup an object in the hash table. Returns the value associated with
730 * the key, or NULL (thus NULL is not a very good value to store...)
731 */
732
733char *hash_lookup(h, key)
734struct hash *h;
735register int key;
736{
737 register struct bucket *b;
738
739 b = h->data[hash_func(h, key)];
740 while (b && b->key != key)
741 b = b->next;
742 if (b && b->key == key)
743 return(b->data);
744 else
745 return(NULL);
746}
747
748
749/* Update an existing object in the hash table. Returns 1 if the object
750 * existed, or 0 if not.
751 */
752
753int hash_update(h, key, value)
754struct hash *h;
755register int key;
756char *value;
757{
758 register struct bucket *b;
759
760 b = h->data[hash_func(h, key)];
761 while (b && b->key != key)
762 b = b->next;
763 if (b && b->key == key) {
764 b->data = value;
765 return(1);
766 } else
767 return(0);
768}
769
770
771/* Store an item in the hash table. Returns 0 if the key was not previously
772 * there, 1 if it was, or -1 if we ran out of memory.
773 */
774
775int hash_store(h, key, value)
776struct hash *h;
777register int key;
778char *value;
779{
780 register struct bucket *b, **p;
781
782 p = &(h->data[hash_func(h, key)]);
783 if (*p == NULL) {
784 b = *p = (struct bucket *) perm_malloc(sizeof(struct bucket));
785 if (b == (struct bucket *) NULL)
786 return(-1);
787 b->next = NULL;
788 b->key = key;
789 b->data = value;
790 return(0);
791 }
792
793 for (b = *p; b && b->key != key; b = *p)
794 p = (struct bucket **) *p;
795 if (b && b->key == key) {
796 b->data = value;
797 return(1);
798 }
799 b = *p = (struct bucket *) perm_malloc(sizeof(struct bucket));
800 if (b == (struct bucket *) NULL)
801 return(-1);
802 b->next = NULL;
803 b->key = key;
804 b->data = value;
805 return(0);
806}
807
808
809/* Search through the hash table for a given value. For each piece of
810 * data with that value, call the callback proc with the corresponding key.
811 */
812
813hash_search(h, value, callback)
814struct hash *h;
815register char *value;
816void (*callback)();
817{
818 register struct bucket *b, **p;
819
820 for (p = &(h->data[h->size - 1]); p >= h->data; p--) {
821 for (b = *p; b; b = b->next) {
822 if (b->data == value)
823 (*callback)(b->key);
824 }
825 }
826}
827
828
829/* Step through the hash table, calling the callback proc with each key.
830 */
831
832hash_step(h, callback, hint)
833struct hash *h;
834void (*callback)();
835char *hint;
836{
837 register struct bucket *b, **p;
838
839 for (p = &(h->data[h->size - 1]); p >= h->data; p--) {
840 for (b = *p; b; b = b->next) {
841 (*callback)(b->key, b->data, hint);
842 }
843 }
844}
845
846
847/* Deallocate all of the memory associated with a table */
848
849hash_destroy(h)
850struct hash *h;
851{
852 register struct bucket *b, **p, *b1;
853
854 for (p = &(h->data[h->size - 1]); p >= h->data; p--) {
855 for (b = *p; b; b = b1) {
856 b1 = b->next;
857 free(b);
858 }
859 }
860}
This page took 0.183097 seconds and 5 git commands to generate.