]> andersk Git - moira.git/blame - gen/mailhub.qc
sms -> moira
[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();
8e7a00be 26char *divide = "##############################################################";
27
28#define ML_WID 72
29#define AL_MAX_WID 896
30
31#define FALSE 0
32#define TRUE (!FALSE)
63812b62 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]);
2ce085d2 59 exit(MR_NO_CHANGE);
63812b62 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);
2ce085d2 66 exit(MR_OCONFIG);
63812b62 67 }
68 } else if (argc != 1) {
69 fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
2ce085d2 70 exit(MR_ARGS);
63812b62 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");
8e7a00be 85 do_lists(out);
63812b62 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");
2ce085d2 92 exit(MR_CCONFIG);
63812b62 93 }
94
95 if (argc == 2)
96 fix_file(targetfile);
2ce085d2 97 exit(MR_SUCCESS);
63812b62 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:
2ce085d2 116 ingres_errno = MR_DEADLOCK;
63812b62 117 break;
118 default:
2ce085d2 119 ingres_errno = MR_INGRES_ERR;
63812b62 120 }
2ce085d2 121 com_err(whoami, MR_INGRES_ERR, " code %d\n", *num);
63812b62 122 critical_alert("DCM", "Alias build encountered INGRES ERROR %d", *num);
123 exit(ingres_errno);
124}
125
8e7a00be 126struct hash *users, *machines, *strings, *lists, *names;
63812b62 127struct user {
128 char *login;
63812b62 129 char *first;
130 char *last;
131 char mi;
63812b62 132 char *pobox;
63812b62 133};
8e7a00be 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};
63812b62 146struct names {
147 char *name;
148 struct names *next;
8e7a00be 149 int keep:1;
150 int id:31;
63812b62 151};
152
153
154get_info()
155##{
8e7a00be 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;
63812b62 159 register struct user *u;
8e7a00be 160 struct list *l, *memberlist;
161 register struct member *m;
63812b62 162
163 /* get locks */
164## retrieve (buf = users.modtime) where users.users_id = 0
8e7a00be 165## retrieve (buf = list.modtime) where list.list_id = 0
63812b62 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;
259dae79 172#ifdef ATHENA
63812b62 173 sprintf(buf, "%s.LOCAL", name);
8e7a00be 174 if (hash_store(machines, id, strsave(buf)) < 0) {
259dae79 175#else
176 if (hash_store(machines, id, strsave(name)) < 0) {
177#endif
8e7a00be 178 fprintf(stderr, "Out of memory!\n");
2ce085d2 179 exit(MR_NO_MEM);
8e7a00be 180 }
63812b62 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) {
8e7a00be 188 if (hash_store(strings, id, strsave(strtrim(name))) < 0) {
189 fprintf(stderr, "Out of memory!\n");
2ce085d2 190 exit(MR_NO_MEM);
8e7a00be 191 }
63812b62 192 cnt++;
193## }
194 fprintf(stderr, "Loaded %d strings\n", cnt);
195
196 cnt = 0;
8e7a00be 197 users = create_hash(12001);
63812b62 198## range of u is users
8e7a00be 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 {
259dae79 203 u = (struct user *) perm_malloc(sizeof(struct user));
63812b62 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;
63812b62 211
8e7a00be 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);
63812b62 217 } else
8e7a00be 218 u->pobox = (char *) NULL;
219 if (hash_store(users, id, u) < 0) {
220 fprintf(stderr, "Out of memory!\n");
2ce085d2 221 exit(MR_NO_MEM);
63812b62 222 }
63812b62 223 cnt++;
224## }
225 fprintf(stderr, "Loaded %d users\n", cnt);
8e7a00be 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 {
259dae79 233 l = (struct list *) perm_malloc(sizeof(struct list));
8e7a00be 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");
2ce085d2 241 exit(MR_NO_MEM);
8e7a00be 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)) {
259dae79 253 m = (struct member *) perm_malloc(sizeof(struct member));
8e7a00be 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);
63812b62 276##}
277
278
8e7a00be 279save_mlist(id, l, force)
280int id;
281struct list *l;
282int force;
63812b62 283{
8e7a00be 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;
63812b62 296 }
8e7a00be 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);
63812b62 306 }
63812b62 307}
308
309
8e7a00be 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
63812b62 319void insert_names(id, u, dummy)
320int id;
321struct user *u;
322int dummy;
323{
324 char buffer[256];
325
8e7a00be 326 insert_name(u->last, id, FALSE, FALSE);
63812b62 327 sprintf(buffer, "%s_%s", u->first, u->last);
8e7a00be 328 insert_name(buffer, id, FALSE, TRUE);
e1707f53 329/* sprintf(buffer, "%c_%s", u->first[0], u->last);
330 insert_name(buffer, id, FALSE, TRUE); */
63812b62 331 if (u->mi) {
332 sprintf(buffer, "%s_%c_%s", u->first, u->mi, u->last);
8e7a00be 333 insert_name(buffer, id, FALSE, TRUE);
63812b62 334 }
335}
336
337int incount = 0;
338
8e7a00be 339insert_name(s, id, nodups, copy)
63812b62 340char *s;
341int id;
8e7a00be 342int nodups;
343int copy;
63812b62 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) {
259dae79 354 if ((ns = (struct names *) perm_malloc(sizeof(struct names))) == NULL) {
63812b62 355 fprintf(stderr, "ran out of memory inserting name (sorting)\n");
2ce085d2 356 exit(MR_NO_MEM);
8e7a00be 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");
2ce085d2 366 exit(MR_NO_MEM);
63812b62 367 }
63812b62 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 }
259dae79 376 if ((ns->next = (struct names *) perm_malloc(sizeof(struct names)))
377 == NULL) {
63812b62 378 fprintf(stderr, "ran out of memory insterting name (sorting)\n");
2ce085d2 379 exit(MR_NO_MEM);
63812b62 380 }
381 ns = ns->next;
8e7a00be 382 if (copy)
383 ns->name = strsave(s);
384 else
385 ns->name = s;
386 ns->keep = nodups;
387 ns->id = id;
63812b62 388 return;
389 }
390 foundns:
8e7a00be 391 if (nodups || ns->keep)
392 return;
393 ns->id = 0;
63812b62 394}
395
396
259dae79 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
63812b62 421int hashstr(s)
422register char *s;
423{
424 register int result;
425 register int c;
426
8e7a00be 427 for (result = 0; c = *s; s++) {
259dae79 428 if (illegalchars[c]) {
429 register char *p;
430 for (p = s; *p; p++)
431 *p = p[1];
432 continue;
433 }
8e7a00be 434 if (isupper(c))
435 c = *s = tolower(c);
63812b62 436/* result = result * 31 + *s; */
8e7a00be 437 result = (result << 5) - result + c - '`';
63812b62 438 }
439 return(result < 0 ? -result : result);
440}
441
442
443sort_info()
444{
8e7a00be 445 names = create_hash(20001);
446 hash_step(users, insert_login, NULL);
447 hash_step(lists, save_mlist, FALSE);
63812b62 448 hash_step(users, insert_names, NULL);
449 fprintf(stderr, "Inserted %d names\n", incount);
450}
451
452
63812b62 453output_data(dummy, nms, out)
454int dummy;
455struct names *nms;
456FILE *out;
457{
458 register struct names *ns;
459 register struct user *u;
63812b62 460
461 incount++;
462 for (ns = nms; ns; ns = ns->next) {
8e7a00be 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);
63812b62 469 if (u->pobox) {
470 fprintf(out, "%s: %s\n", ns->name, u->pobox);
8e7a00be 471 } else {
472 fprintf(out, "%s: =%s=@nobox\n", ns->name, ns->name);
63812b62 473 }
8e7a00be 474 } else if (ns->id == 0) {
475 fprintf(out, "%s: =%s=@ambig\n", ns->name, ns->name);
63812b62 476 }
477 }
478}
479
480
8e7a00be 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)))
259dae79 496 fprintf(out, "owner-%s: %s\n%s: ", l->name, l1->name, l->name);
8e7a00be 497 else if (l->acl_t == 'U' &&
498 (u = (struct user *) hash_lookup(users, l->acl_id)))
259dae79 499 fprintf(out, "owner-%s: %s\n%s: ", l->name, u->login, l->name);
8e7a00be 500
8e7a00be 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)
63812b62 551FILE *out;
552{
553 incount = 0;
8e7a00be 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}
63812b62 558
8e7a00be 559do_people(out)
560FILE *out;
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
This page took 0.184759 seconds and 5 git commands to generate.