]> andersk Git - moira.git/blame_incremental - gen/mailhub.qc
clean up lint; make sure we output list dependancies
[moira.git] / gen / mailhub.qc
... / ...
CommitLineData
1
2/* $Header$
3 *
4 * This generates the /usr/lib/aliases file for the mailhub.
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>
15#include <moira.h>
16#include <moira_site.h>
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <sys/time.h>
20
21
22extern int errno;
23char *whoami = "mailhub.gen";
24char *ingres_date_and_time();
25char *perm_malloc();
26char *divide = "##############################################################";
27
28#define ML_WID 72
29#define AL_MAX_WID 896
30
31#define FALSE 0
32#define TRUE (!FALSE)
33
34
35main(argc, argv)
36int argc;
37char **argv;
38{
39 long tm = time(NULL);
40 FILE *out= stdout;
41 char filename[64], *targetfile;
42 struct stat sb;
43## int flag;
44## char *filetime;
45 int ingerr();
46
47 IIseterr(ingerr);
48## ingres sms
49## set lockmode session where level = table
50
51 if (argc == 2) {
52 if (stat(argv[1], &sb) == 0) {
53 filetime = ingres_date_and_time(sb.st_mtime);
54## retrieve (flag = int4(interval("min",tblstats.modtime - filetime)))
55## where tblstats.table = "users"
56 if (flag < 0) {
57 fprintf(stderr, "File %s does not need to be rebuilt.\n",
58 argv[1]);
59 exit(MR_NO_CHANGE);
60 }
61 }
62 targetfile = argv[1];
63 sprintf(filename, "%s~", targetfile);
64 if ((out = fopen(filename, "w")) == NULL) {
65 fprintf(stderr, "unable to open %s for output\n", filename);
66 exit(MR_OCONFIG);
67 }
68 } else if (argc != 1) {
69 fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
70 exit(MR_ARGS);
71 }
72
73 fprintf(out, "%s\n# Aliases File Extract of %s", divide, ctime(&tm));
74 fprintf(out, "# This file is automatically generated, do not edit it directly.\n%s\n\n", divide);
75
76## begin transaction
77 get_info();
78## end transaction
79## exit
80
81 fprintf(stderr, "Sorting Info\n");
82 sort_info();
83
84 fprintf(stderr, "Dumping information\n");
85 do_lists(out);
86 do_people(out);
87
88 fprintf(out, "\n%s\n# End of aliases file\n", divide);
89
90 if (fclose(out)) {
91 perror("close failed");
92 exit(MR_CCONFIG);
93 }
94
95 if (argc == 2)
96 fix_file(targetfile);
97 exit(MR_SUCCESS);
98}
99
100
101/*
102 * ingerr: (supposedly) called when Ingres indicates an error.
103 * I have not yet been able to get this to work to intercept a
104 * database open error.
105 */
106#define INGRES_DEADLOCK 4700
107
108static int ingerr(num)
109 int *num;
110{
111 char buf[256];
112 int ingres_errno;
113
114 switch (*num) {
115 case INGRES_DEADLOCK:
116 ingres_errno = MR_DEADLOCK;
117 break;
118 default:
119 ingres_errno = MR_INGRES_ERR;
120 }
121 com_err(whoami, MR_INGRES_ERR, " code %d\n", *num);
122 critical_alert("DCM", "Alias build encountered INGRES ERROR %d", *num);
123 exit(ingres_errno);
124}
125
126struct hash *users, *machines, *strings, *lists, *names;
127struct user {
128 char *login;
129 char *first;
130 char *last;
131 char mi;
132 char *pobox;
133};
134struct member {
135 struct member *next;
136 char *name;
137 int list_id;
138};
139struct list {
140 char *name;
141 char maillist;
142 char acl_t;
143 int acl_id;
144 struct member *m;
145};
146struct names {
147 char *name;
148 struct names *next;
149 int keep:1;
150 int id:31;
151};
152
153
154get_info()
155##{
156## int id, pid, bid, stat, cnt, maillistp, acl, mid;
157## char name[129], type[9], fname[17], mname[17], lname[17], buf[257];
158 char *s;
159 register struct user *u;
160 struct list *l, *memberlist;
161 register struct member *m;
162
163 /* get locks */
164## retrieve (buf = users.modtime) where users.users_id = 0
165## retrieve (buf = list.modtime) where list.list_id = 0
166
167 cnt = 0;
168 machines = create_hash(1000);
169## retrieve (id = machine.mach_id, name = machine.#name) {
170 if (s = index(name, '.'))
171 *s = 0;
172#ifdef ATHENA
173 sprintf(buf, "%s.LOCAL", name);
174 if (hash_store(machines, id, strsave(buf)) < 0) {
175#else
176 if (hash_store(machines, id, strsave(name)) < 0) {
177#endif
178 fprintf(stderr, "Out of memory!\n");
179 exit(MR_NO_MEM);
180 }
181 cnt++;
182## }
183 fprintf(stderr, "Loaded %d machines\n", cnt);
184
185 cnt = 0;
186 strings = create_hash(2000);
187## retrieve (id = strings.string_id, name = strings.string) {
188 if (hash_store(strings, id, strsave(strtrim(name))) < 0) {
189 fprintf(stderr, "Out of memory!\n");
190 exit(MR_NO_MEM);
191 }
192 cnt++;
193## }
194 fprintf(stderr, "Loaded %d strings\n", cnt);
195
196 cnt = 0;
197 users = create_hash(12001);
198## range of u is users
199## retrieve (id = u.users_id, name = u.login, fname = u.first,
200## mname = u.middle, lname = u.last,
201## type = u.potype, pid = u.pop_id, bid = u.box_id)
202## where u.status != 3 {
203 u = (struct user *) perm_malloc(sizeof(struct user));
204 u->login = strsave(strtrim(name));
205 u->first = strsave(strtrim(fname));
206 u->last = strsave(strtrim(lname));
207 if (mname[0] != ' ')
208 u->mi = mname[0];
209 else
210 u->mi = 0;
211
212 if (type[0] == 'P' && (s = hash_lookup(machines, pid))) {
213 sprintf(buf, "%s@%s", strtrim(name), s);
214 u->pobox = strsave(buf);
215 } else if (type[0] == 'S') {
216 u->pobox = hash_lookup(strings, bid);
217 } else
218 u->pobox = (char *) NULL;
219 if (hash_store(users, id, u) < 0) {
220 fprintf(stderr, "Out of memory!\n");
221 exit(MR_NO_MEM);
222 }
223 cnt++;
224## }
225 fprintf(stderr, "Loaded %d users\n", cnt);
226
227 cnt = 0;
228 lists = create_hash(15000);
229## range of l is list
230## retrieve (id = l.list_id, name = l.#name, maillistp = l.maillist,
231## type = l.acl_type, acl = l.acl_id)
232## where l.active != 0 {
233 l = (struct list *) perm_malloc(sizeof(struct list));
234 l->name = strsave(strtrim(name));
235 l->maillist = maillistp;
236 l->acl_t = type[0];
237 l->acl_id = acl;
238 l->m = (struct member *) NULL;
239 if (hash_store(lists, id, l) < 0) {
240 fprintf(stderr, "Out of memory!\n");
241 exit(MR_NO_MEM);
242 }
243 cnt++;
244## }
245 fprintf(stderr, "Loaded %d lists\n", cnt);
246
247 cnt = 0;
248## range of m is imembers
249## retrieve (id = m.list_id, type = m.member_type, mid = m.member_id)
250## where m.direct = 1 {
251 cnt++;
252 if (l = (struct list *) hash_lookup(lists, id)) {
253 m = (struct member *) perm_malloc(sizeof(struct member));
254 if (type[0] == 'U' &&
255 (u = (struct user *) hash_lookup(users, mid))) {
256 m->list_id = 0;
257 m->name = u->login;
258 m->next = l->m;
259 l->m = m;
260 } else if (type[0] == 'L' &&
261 (memberlist = (struct list *) hash_lookup(lists, mid))) {
262 m->list_id = mid;
263 m->name = memberlist->name;
264 m->next = l->m;
265 l->m = m;
266 } else if (type[0] == 'S' &&
267 (s = hash_lookup(strings, mid))) {
268 m->list_id = 0;
269 m->next = l->m;
270 l->m = m;
271 m->name = s;
272 }
273 }
274## }
275 fprintf(stderr, "Loaded %d members\n", cnt);
276##}
277
278
279save_mlist(id, l, force)
280int id;
281struct list *l;
282int force;
283{
284 register struct member *m;
285 register struct list *l1;
286
287 if (l->maillist == 2 ||
288 l->maillist == 3 ||
289 (l->maillist == 0 && !force))
290 return;
291
292 if (l->m && l->m->next == NULL &&
293 !strcasecmp(l->name, l->m->name)) {
294 l->maillist = 3;
295 return;
296 }
297 l->maillist = 2;
298 insert_name(l->name, -id, TRUE, FALSE);
299
300 if (l->acl_t == 'L' && (l1 = (struct list *)hash_lookup(lists, l->acl_id)))
301 save_mlist(0, l1, TRUE);
302
303 for (m = l->m; m; m = m->next) {
304 if (m->list_id && (l1 = (struct list *)hash_lookup(lists, m->list_id)))
305 save_mlist(0, l1, TRUE);
306 }
307}
308
309
310insert_login(id, u, dummy)
311int id;
312struct user *u;
313int dummy;
314{
315 if (u->pobox && u->login[0] != '#')
316 insert_name(u->login, id, TRUE, FALSE);
317}
318
319void insert_names(id, u, dummy)
320int id;
321struct user *u;
322int dummy;
323{
324 char buffer[256];
325
326 insert_name(u->last, id, FALSE, FALSE);
327 sprintf(buffer, "%s_%s", u->first, u->last);
328 insert_name(buffer, id, FALSE, TRUE);
329/* sprintf(buffer, "%c_%s", u->first[0], u->last);
330 insert_name(buffer, id, FALSE, TRUE); */
331 if (u->mi) {
332 sprintf(buffer, "%s_%c_%s", u->first, u->mi, u->last);
333 insert_name(buffer, id, FALSE, TRUE);
334 }
335}
336
337int incount = 0;
338
339insert_name(s, id, nodups, copy)
340char *s;
341int id;
342int nodups;
343int copy;
344{
345 int code;
346 register struct names *ns;
347 register int count;
348 register struct idblock *ra;
349
350 incount++;
351 code = hashstr(s);
352 ns = (struct names *) hash_lookup(names, code);
353 if (ns == NULL) {
354 if ((ns = (struct names *) perm_malloc(sizeof(struct names))) == NULL) {
355 fprintf(stderr, "ran out of memory inserting name (sorting)\n");
356 exit(MR_NO_MEM);
357 }
358 if (copy)
359 ns->name = strsave(s);
360 else
361 ns->name = s;
362 ns->keep = nodups;
363 ns->id = id;
364 if (hash_store(names, code, ns) < 0) {
365 fprintf(stderr, "Out of memory!\n");
366 exit(MR_NO_MEM);
367 }
368 return;
369 }
370 if (strcasecmp(ns->name, s)) {
371 while (ns->next) {
372 ns = ns->next;
373 if (!strcasecmp(ns->name, s))
374 goto foundns;
375 }
376 if ((ns->next = (struct names *) perm_malloc(sizeof(struct names)))
377 == NULL) {
378 fprintf(stderr, "ran out of memory insterting name (sorting)\n");
379 exit(MR_NO_MEM);
380 }
381 ns = ns->next;
382 if (copy)
383 ns->name = strsave(s);
384 else
385 ns->name = s;
386 ns->keep = nodups;
387 ns->id = id;
388 return;
389 }
390 foundns:
391 if (nodups || ns->keep)
392 return;
393 ns->id = 0;
394}
395
396
397/* Illegal chars: ! " % ( ) , . / : ; < = > @ [ \ ] ^ { | } */
398
399static int illegalchars[] = {
400 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
401 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
402 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, /* SPACE - / */
403 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, /* 0 - ? */
404 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
405 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* P - _ */
406 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
407 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
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 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
416};
417
418
419/* While hashing the string, punt any illegal characters */
420
421int hashstr(s)
422register char *s;
423{
424 register int result;
425 register int c;
426
427 for (result = 0; c = *s; s++) {
428 if (illegalchars[c]) {
429 register char *p;
430 for (p = s; *p; p++)
431 *p = p[1];
432 continue;
433 }
434 if (isupper(c))
435 c = *s = tolower(c);
436/* result = result * 31 + *s; */
437 result = (result << 5) - result + c - '`';
438 }
439 return(result < 0 ? -result : result);
440}
441
442
443sort_info()
444{
445 names = create_hash(20001);
446 hash_step(users, insert_login, NULL);
447 hash_step(lists, save_mlist, FALSE);
448 hash_step(users, insert_names, NULL);
449 fprintf(stderr, "Inserted %d names\n", incount);
450}
451
452
453output_data(dummy, nms, out)
454int dummy;
455struct names *nms;
456FILE *out;
457{
458 register struct names *ns;
459 register struct user *u;
460
461 incount++;
462 for (ns = nms; ns; ns = ns->next) {
463 if (ns->name[0] == 0 || ns->name[1] == 0) {
464 fprintf(stderr, "punting %s due to short name\n", ns->name);
465 continue;
466 }
467 if (ns->id > 0) {
468 u = (struct user *) hash_lookup(users, ns->id);
469 if (u->pobox) {
470 fprintf(out, "%s: %s\n", ns->name, u->pobox);
471 } else {
472 fprintf(out, "%s: =%s=@nobox\n", ns->name, ns->name);
473 }
474 } else if (ns->id == 0) {
475 fprintf(out, "%s: =%s=@ambig\n", ns->name, ns->name);
476 }
477 }
478}
479
480
481int lwid, bol, awid;
482
483output_mlist(id, l, out)
484int id;
485register struct list *l;
486FILE *out;
487{
488 struct list *l1;
489 register struct member *m;
490 register struct user *u;
491
492 if (l->maillist != 2)
493 return;
494 if (l->acl_t == 'L' &&
495 (l1 = (struct list *) hash_lookup(lists, l->acl_id)))
496 fprintf(out, "owner-%s: %s\n%s: ", l->name, l1->name, l->name);
497 else if (l->acl_t == 'U' &&
498 (u = (struct user *) hash_lookup(users, l->acl_id)))
499 fprintf(out, "owner-%s: %s\n%s: ", l->name, u->login, l->name);
500
501 lwid = strlen(l->name) + 2;
502 bol = 1;
503 for (m = l->m; m; m = m->next) {
504 do_member(out, m->name);
505 }
506 if (l->m == (struct member *)NULL)
507 fprintf(out, "/dev/null");
508 fprintf(out, "\n\n");
509 incount++;
510}
511
512
513/* print out strings separated by commas, doing line breaks as appropriate */
514
515do_member(out, s)
516FILE *out;
517register char *s;
518{
519 register wwid;
520 static int cont = 1;
521
522 wwid = strlen(s);
523
524 if (!bol && awid + wwid + 2 > AL_MAX_WID) {
525 fprintf(out, ",\n\tcontinuation-%d\ncontinuation-%d: ", cont, cont);
526 cont++;
527 awid = lwid = 17 + wwid;
528 fputs(s, out);
529 return;
530 }
531
532 if (bol) {
533 lwid += wwid;
534 awid = lwid;
535 fputs(s, out);
536 bol = 0;
537 return;
538 }
539 if (lwid + wwid + 2 > ML_WID) {
540 fprintf(out, ",\n\t%s", s);
541 awid += lwid + wwid + 2;
542 lwid = wwid + 8;
543 return;
544 }
545 lwid += wwid + 2;
546 fprintf(out, ", %s", s);
547}
548
549
550do_lists(out)
551FILE *out;
552{
553 incount = 0;
554 fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
555 hash_step(lists, output_mlist, out);
556 fprintf(stderr, "Output %d lists\n", incount);
557}
558
559do_people(out)
560FILE *out;
561{
562 incount = 0;
563 fprintf(out, "\n%s\n# People\n%s\n", divide, divide);
564 hash_step(names, output_data, out);
565 fprintf(stderr, "Output %d entries\n", incount);
566}
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
This page took 0.032418 seconds and 5 git commands to generate.