]> andersk Git - moira.git/blame - gen/mailhub.qc
use private version of strsave that calls perm_malloc();
[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
35
36main(argc, argv)
37int argc;
38char **argv;
39{
40 long tm = time(NULL);
41 FILE *out= stdout;
42 char filename[64], *targetfile;
43 struct stat sb;
44## int flag;
45## char *filetime;
46 int ingerr();
47
48 IIseterr(ingerr);
49## ingres sms
50## set lockmode session where level = table
51
52 if (argc == 2) {
53 if (stat(argv[1], &sb) == 0) {
54 filetime = ingres_date_and_time(sb.st_mtime);
55## retrieve (flag = int4(interval("min",tblstats.modtime - filetime)))
56## where tblstats.table = "users"
57 if (flag < 0) {
58 fprintf(stderr, "File %s does not need to be rebuilt.\n",
59 argv[1]);
2ce085d2 60 exit(MR_NO_CHANGE);
63812b62 61 }
62 }
63 targetfile = argv[1];
64 sprintf(filename, "%s~", targetfile);
65 if ((out = fopen(filename, "w")) == NULL) {
66 fprintf(stderr, "unable to open %s for output\n", filename);
2ce085d2 67 exit(MR_OCONFIG);
63812b62 68 }
69 } else if (argc != 1) {
70 fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
2ce085d2 71 exit(MR_ARGS);
63812b62 72 }
73
74 fprintf(out, "%s\n# Aliases File Extract of %s", divide, ctime(&tm));
75 fprintf(out, "# This file is automatically generated, do not edit it directly.\n%s\n\n", divide);
76
77## begin transaction
78 get_info();
79## end transaction
80## exit
81
82 fprintf(stderr, "Sorting Info\n");
83 sort_info();
84
85 fprintf(stderr, "Dumping information\n");
8e7a00be 86 do_lists(out);
63812b62 87 do_people(out);
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;
169 machines = create_hash(1000);
170## retrieve (id = machine.mach_id, name = machine.#name) {
171 if (s = index(name, '.'))
172 *s = 0;
259dae79 173#ifdef ATHENA
15437d42 174 strcat(name, ".LOCAL");
259dae79 175#endif
15437d42 176 if (hash_store(machines, id, pstrsave(name)) < 0) {
8e7a00be 177 fprintf(stderr, "Out of memory!\n");
2ce085d2 178 exit(MR_NO_MEM);
8e7a00be 179 }
63812b62 180 cnt++;
181## }
182 fprintf(stderr, "Loaded %d machines\n", cnt);
183
184 cnt = 0;
185 strings = create_hash(2000);
186## retrieve (id = strings.string_id, name = strings.string) {
15437d42 187 if (hash_store(strings, id, pstrsave(strtrim(name))) < 0) {
8e7a00be 188 fprintf(stderr, "Out of memory!\n");
2ce085d2 189 exit(MR_NO_MEM);
8e7a00be 190 }
63812b62 191 cnt++;
192## }
193 fprintf(stderr, "Loaded %d strings\n", cnt);
194
195 cnt = 0;
8e7a00be 196 users = create_hash(12001);
63812b62 197## range of u is users
8e7a00be 198## retrieve (id = u.users_id, name = u.login, fname = u.first,
199## mname = u.middle, lname = u.last,
200## type = u.potype, pid = u.pop_id, bid = u.box_id)
201## where u.status != 3 {
259dae79 202 u = (struct user *) perm_malloc(sizeof(struct user));
15437d42 203 u->login = pstrsave(strtrim(name));
204 u->first = pstrsave(strtrim(fname));
205 u->last = pstrsave(strtrim(lname));
63812b62 206 if (mname[0] != ' ')
207 u->mi = mname[0];
208 else
209 u->mi = 0;
63812b62 210
8e7a00be 211 if (type[0] == 'P' && (s = hash_lookup(machines, pid))) {
212 sprintf(buf, "%s@%s", strtrim(name), s);
15437d42 213 u->pobox = pstrsave(buf);
8e7a00be 214 } else if (type[0] == 'S') {
215 u->pobox = hash_lookup(strings, bid);
63812b62 216 } else
8e7a00be 217 u->pobox = (char *) NULL;
218 if (hash_store(users, id, u) < 0) {
219 fprintf(stderr, "Out of memory!\n");
2ce085d2 220 exit(MR_NO_MEM);
63812b62 221 }
63812b62 222 cnt++;
223## }
224 fprintf(stderr, "Loaded %d users\n", cnt);
8e7a00be 225
226 cnt = 0;
227 lists = create_hash(15000);
228## range of l is list
229## retrieve (id = l.list_id, name = l.#name, maillistp = l.maillist,
230## type = l.acl_type, acl = l.acl_id)
231## where l.active != 0 {
259dae79 232 l = (struct list *) perm_malloc(sizeof(struct list));
15437d42 233 l->name = pstrsave(strtrim(name));
8e7a00be 234 l->maillist = maillistp;
235 l->acl_t = type[0];
236 l->acl_id = acl;
237 l->m = (struct member *) NULL;
238 if (hash_store(lists, id, l) < 0) {
239 fprintf(stderr, "Out of memory!\n");
2ce085d2 240 exit(MR_NO_MEM);
8e7a00be 241 }
242 cnt++;
243## }
244 fprintf(stderr, "Loaded %d lists\n", cnt);
245
246 cnt = 0;
247## range of m is imembers
248## retrieve (id = m.list_id, type = m.member_type, mid = m.member_id)
249## where m.direct = 1 {
250 cnt++;
251 if (l = (struct list *) hash_lookup(lists, id)) {
259dae79 252 m = (struct member *) perm_malloc(sizeof(struct member));
8e7a00be 253 if (type[0] == 'U' &&
254 (u = (struct user *) hash_lookup(users, mid))) {
255 m->list_id = 0;
256 m->name = u->login;
257 m->next = l->m;
258 l->m = m;
259 } else if (type[0] == 'L' &&
260 (memberlist = (struct list *) hash_lookup(lists, mid))) {
261 m->list_id = mid;
262 m->name = memberlist->name;
263 m->next = l->m;
264 l->m = m;
265 } else if (type[0] == 'S' &&
266 (s = hash_lookup(strings, mid))) {
267 m->list_id = 0;
268 m->next = l->m;
269 l->m = m;
270 m->name = s;
271 }
272 }
273## }
274 fprintf(stderr, "Loaded %d members\n", cnt);
63812b62 275##}
276
277
8e7a00be 278save_mlist(id, l, force)
279int id;
280struct list *l;
281int force;
63812b62 282{
8e7a00be 283 register struct member *m;
284 register struct list *l1;
285
286 if (l->maillist == 2 ||
287 l->maillist == 3 ||
288 (l->maillist == 0 && !force))
289 return;
290
291 if (l->m && l->m->next == NULL &&
292 !strcasecmp(l->name, l->m->name)) {
293 l->maillist = 3;
294 return;
63812b62 295 }
8e7a00be 296 l->maillist = 2;
297 insert_name(l->name, -id, TRUE, FALSE);
298
299 if (l->acl_t == 'L' && (l1 = (struct list *)hash_lookup(lists, l->acl_id)))
300 save_mlist(0, l1, TRUE);
301
302 for (m = l->m; m; m = m->next) {
303 if (m->list_id && (l1 = (struct list *)hash_lookup(lists, m->list_id)))
304 save_mlist(0, l1, TRUE);
63812b62 305 }
63812b62 306}
307
308
8e7a00be 309insert_login(id, u, dummy)
310int id;
311struct user *u;
312int dummy;
313{
314 if (u->pobox && u->login[0] != '#')
315 insert_name(u->login, id, TRUE, FALSE);
316}
317
63812b62 318void insert_names(id, u, dummy)
319int id;
320struct user *u;
321int dummy;
322{
323 char buffer[256];
324
8e7a00be 325 insert_name(u->last, id, FALSE, FALSE);
63812b62 326 sprintf(buffer, "%s_%s", u->first, u->last);
8e7a00be 327 insert_name(buffer, id, FALSE, TRUE);
e1707f53 328/* sprintf(buffer, "%c_%s", u->first[0], u->last);
329 insert_name(buffer, id, FALSE, TRUE); */
63812b62 330 if (u->mi) {
331 sprintf(buffer, "%s_%c_%s", u->first, u->mi, u->last);
8e7a00be 332 insert_name(buffer, id, FALSE, TRUE);
63812b62 333 }
334}
335
336int incount = 0;
337
8e7a00be 338insert_name(s, id, nodups, copy)
63812b62 339char *s;
340int id;
8e7a00be 341int nodups;
342int copy;
63812b62 343{
344 int code;
345 register struct names *ns;
346 register int count;
347 register struct idblock *ra;
348
349 incount++;
350 code = hashstr(s);
351 ns = (struct names *) hash_lookup(names, code);
352 if (ns == NULL) {
259dae79 353 if ((ns = (struct names *) perm_malloc(sizeof(struct names))) == NULL) {
63812b62 354 fprintf(stderr, "ran out of memory inserting name (sorting)\n");
2ce085d2 355 exit(MR_NO_MEM);
8e7a00be 356 }
357 if (copy)
15437d42 358 ns->name = pstrsave(s);
8e7a00be 359 else
360 ns->name = s;
361 ns->keep = nodups;
362 ns->id = id;
363 if (hash_store(names, code, ns) < 0) {
364 fprintf(stderr, "Out of memory!\n");
2ce085d2 365 exit(MR_NO_MEM);
63812b62 366 }
63812b62 367 return;
368 }
369 if (strcasecmp(ns->name, s)) {
370 while (ns->next) {
371 ns = ns->next;
372 if (!strcasecmp(ns->name, s))
373 goto foundns;
374 }
259dae79 375 if ((ns->next = (struct names *) perm_malloc(sizeof(struct names)))
376 == NULL) {
63812b62 377 fprintf(stderr, "ran out of memory insterting name (sorting)\n");
2ce085d2 378 exit(MR_NO_MEM);
63812b62 379 }
380 ns = ns->next;
8e7a00be 381 if (copy)
15437d42 382 ns->name = pstrsave(s);
8e7a00be 383 else
384 ns->name = s;
385 ns->keep = nodups;
386 ns->id = id;
63812b62 387 return;
388 }
389 foundns:
8e7a00be 390 if (nodups || ns->keep)
391 return;
392 ns->id = 0;
63812b62 393}
394
395
259dae79 396/* Illegal chars: ! " % ( ) , . / : ; < = > @ [ \ ] ^ { | } */
397
398static int illegalchars[] = {
399 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
400 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
401 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, /* SPACE - / */
402 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, /* 0 - ? */
403 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
404 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* P - _ */
405 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
406 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
407 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
408 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
409 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
410 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
411 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
412 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
413 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
414 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
415};
416
417
418/* While hashing the string, punt any illegal characters */
419
63812b62 420int hashstr(s)
421register char *s;
422{
423 register int result;
424 register int c;
425
8e7a00be 426 for (result = 0; c = *s; s++) {
259dae79 427 if (illegalchars[c]) {
428 register char *p;
429 for (p = s; *p; p++)
430 *p = p[1];
431 continue;
432 }
8e7a00be 433 if (isupper(c))
434 c = *s = tolower(c);
63812b62 435/* result = result * 31 + *s; */
8e7a00be 436 result = (result << 5) - result + c - '`';
63812b62 437 }
438 return(result < 0 ? -result : result);
439}
440
441
442sort_info()
443{
8e7a00be 444 names = create_hash(20001);
445 hash_step(users, insert_login, NULL);
446 hash_step(lists, save_mlist, FALSE);
63812b62 447 hash_step(users, insert_names, NULL);
448 fprintf(stderr, "Inserted %d names\n", incount);
449}
450
451
63812b62 452output_data(dummy, nms, out)
453int dummy;
454struct names *nms;
455FILE *out;
456{
457 register struct names *ns;
458 register struct user *u;
63812b62 459
460 incount++;
461 for (ns = nms; ns; ns = ns->next) {
8e7a00be 462 if (ns->name[0] == 0 || ns->name[1] == 0) {
463 fprintf(stderr, "punting %s due to short name\n", ns->name);
464 continue;
465 }
466 if (ns->id > 0) {
467 u = (struct user *) hash_lookup(users, ns->id);
63812b62 468 if (u->pobox) {
469 fprintf(out, "%s: %s\n", ns->name, u->pobox);
8e7a00be 470 } else {
471 fprintf(out, "%s: =%s=@nobox\n", ns->name, ns->name);
63812b62 472 }
8e7a00be 473 } else if (ns->id == 0) {
474 fprintf(out, "%s: =%s=@ambig\n", ns->name, ns->name);
63812b62 475 }
476 }
477}
478
479
8e7a00be 480int lwid, bol, awid;
481
482output_mlist(id, l, out)
483int id;
484register struct list *l;
485FILE *out;
486{
487 struct list *l1;
488 register struct member *m;
489 register struct user *u;
490
491 if (l->maillist != 2)
492 return;
493 if (l->acl_t == 'L' &&
494 (l1 = (struct list *) hash_lookup(lists, l->acl_id)))
259dae79 495 fprintf(out, "owner-%s: %s\n%s: ", l->name, l1->name, l->name);
8e7a00be 496 else if (l->acl_t == 'U' &&
497 (u = (struct user *) hash_lookup(users, l->acl_id)))
259dae79 498 fprintf(out, "owner-%s: %s\n%s: ", l->name, u->login, l->name);
15437d42 499 else
500 fprintf(out, "%s: ", l->name);
501
8e7a00be 502
8e7a00be 503 lwid = strlen(l->name) + 2;
504 bol = 1;
505 for (m = l->m; m; m = m->next) {
506 do_member(out, m->name);
507 }
508 if (l->m == (struct member *)NULL)
509 fprintf(out, "/dev/null");
510 fprintf(out, "\n\n");
511 incount++;
512}
513
514
515/* print out strings separated by commas, doing line breaks as appropriate */
516
517do_member(out, s)
518FILE *out;
519register char *s;
520{
521 register wwid;
522 static int cont = 1;
523
524 wwid = strlen(s);
525
526 if (!bol && awid + wwid + 2 > AL_MAX_WID) {
527 fprintf(out, ",\n\tcontinuation-%d\ncontinuation-%d: ", cont, cont);
528 cont++;
529 awid = lwid = 17 + wwid;
530 fputs(s, out);
531 return;
532 }
533
534 if (bol) {
535 lwid += wwid;
536 awid = lwid;
537 fputs(s, out);
538 bol = 0;
539 return;
540 }
541 if (lwid + wwid + 2 > ML_WID) {
542 fprintf(out, ",\n\t%s", s);
543 awid += lwid + wwid + 2;
544 lwid = wwid + 8;
545 return;
546 }
547 lwid += wwid + 2;
548 fprintf(out, ", %s", s);
549}
550
551
552do_lists(out)
63812b62 553FILE *out;
554{
555 incount = 0;
8e7a00be 556 fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
557 hash_step(lists, output_mlist, out);
558 fprintf(stderr, "Output %d lists\n", incount);
559}
63812b62 560
8e7a00be 561do_people(out)
562FILE *out;
563{
564 incount = 0;
565 fprintf(out, "\n%s\n# People\n%s\n", divide, divide);
63812b62 566 hash_step(names, output_data, out);
63812b62 567 fprintf(stderr, "Output %d entries\n", incount);
568}
259dae79 569
570
571#define chunk_size 102400
572
573char *perm_malloc(size)
574unsigned size;
575{
576 static char *pool = NULL;
577 static unsigned pool_size = 0;
578 register char *ret;
579
580 if (size > pool_size) {
581 pool = (char *) malloc(chunk_size);
582 pool_size = chunk_size;
583 }
584 ret = pool;
585 pool += size;
586 pool = (char *)(((unsigned) (pool + 1)) & ~1);
587 pool_size -= (pool - ret);
588 return(ret);
589}
590
15437d42 591
592/*
593 * Make a (permenant) copy of a string.
594 */
595char *
596pstrsave(s)
597 char *s;
598{
599 register int len;
600 register char *p;
601 /* Kludge for sloppy string semantics */
602 if (!s) {
603 printf("NULL != \"\" !!!!\r\n");
604 p = perm_malloc(1);
605 *p = '\0';
606 return p;
607 }
608 len = strlen(s) + 1;
609 p = perm_malloc((u_int)len);
610 if (p) bcopy(s, p, len);
611 return p;
612}
This page took 0.139999 seconds and 5 git commands to generate.