4 * This generates the /usr/lib/aliases file for the mailhub.
6 * (c) Copyright 1988 by the Massachusetts Institute of Technology.
7 * For copying and distribution information, please see the file
11 #include <mit-copyright.h>
16 #include <moira_site.h>
17 #include <sys/types.h>
23 char *whoami = "mailhub.gen";
24 char *ingres_date_and_time();
27 char *divide = "##############################################################";
30 #define AL_MAX_WID 896
42 char filename[64], *targetfile;
50 ## set lockmode session where level = table
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"
58 fprintf(stderr, "File %s does not need to be rebuilt.\n",
64 sprintf(filename, "%s~", targetfile);
65 if ((out = fopen(filename, "w")) == NULL) {
66 fprintf(stderr, "unable to open %s for output\n", filename);
69 } else if (argc != 1) {
70 fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
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);
82 fprintf(stderr, "Sorting Info\n");
85 fprintf(stderr, "Dumping information\n");
89 fprintf(out, "\n%s\n# End of aliases file\n", divide);
92 perror("close failed");
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.
107 #define INGRES_DEADLOCK 4700
109 static int ingerr(num)
116 case INGRES_DEADLOCK:
117 ingres_errno = MR_DEADLOCK;
120 ingres_errno = MR_INGRES_ERR;
122 com_err(whoami, MR_INGRES_ERR, " code %d\n", *num);
123 critical_alert("DCM", "Alias build encountered INGRES ERROR %d", *num);
127 struct hash *users, *machines, *strings, *lists, *names;
157 ## int id, pid, bid, stat, cnt, maillistp, acl, mid;
158 ## char name[129], type[9], fname[17], mname[17], lname[17], buf[257];
160 register struct user *u;
161 struct list *l, *memberlist;
162 register struct member *m;
165 ## retrieve (buf = users.modtime) where users.users_id = 0
166 ## retrieve (buf = list.modtime) where list.list_id = 0
169 machines = create_hash(1000);
170 ## retrieve (id = machine.mach_id, name = machine.#name) {
171 if (s = index(name, '.'))
174 strcat(name, ".LOCAL");
176 if (hash_store(machines, id, pstrsave(name)) < 0) {
177 fprintf(stderr, "Out of memory!\n");
182 fprintf(stderr, "Loaded %d machines\n", cnt);
185 strings = create_hash(2000);
186 ## retrieve (id = strings.string_id, name = strings.string) {
187 if (hash_store(strings, id, pstrsave(strtrim(name))) < 0) {
188 fprintf(stderr, "Out of memory!\n");
193 fprintf(stderr, "Loaded %d strings\n", cnt);
196 users = create_hash(12001);
197 ## range of u is users
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 {
202 u = (struct user *) perm_malloc(sizeof(struct user));
203 u->login = pstrsave(strtrim(name));
204 u->first = pstrsave(strtrim(fname));
205 u->last = pstrsave(strtrim(lname));
211 if (type[0] == 'P' && (s = hash_lookup(machines, pid))) {
212 sprintf(buf, "%s@%s", strtrim(name), s);
213 u->pobox = pstrsave(buf);
214 } else if (type[0] == 'S') {
215 u->pobox = hash_lookup(strings, bid);
217 u->pobox = (char *) NULL;
218 if (hash_store(users, id, u) < 0) {
219 fprintf(stderr, "Out of memory!\n");
224 fprintf(stderr, "Loaded %d users\n", cnt);
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 {
232 l = (struct list *) perm_malloc(sizeof(struct list));
233 l->name = pstrsave(strtrim(name));
234 l->maillist = maillistp;
237 l->m = (struct member *) NULL;
238 if (hash_store(lists, id, l) < 0) {
239 fprintf(stderr, "Out of memory!\n");
244 fprintf(stderr, "Loaded %d lists\n", cnt);
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 {
251 if (l = (struct list *) hash_lookup(lists, id)) {
252 m = (struct member *) perm_malloc(sizeof(struct member));
253 if (type[0] == 'U' &&
254 (u = (struct user *) hash_lookup(users, mid))) {
259 } else if (type[0] == 'L' &&
260 (memberlist = (struct list *) hash_lookup(lists, mid))) {
262 m->name = memberlist->name;
265 } else if (type[0] == 'S' &&
266 (s = hash_lookup(strings, mid))) {
274 fprintf(stderr, "Loaded %d members\n", cnt);
278 save_mlist(id, l, force)
283 register struct member *m;
284 register struct list *l1;
286 if (l->maillist == 2 ||
288 (l->maillist == 0 && !force))
291 if (l->m && l->m->next == NULL &&
292 !strcasecmp(l->name, l->m->name)) {
297 insert_name(l->name, -id, TRUE, FALSE);
299 if (l->acl_t == 'L' && (l1 = (struct list *)hash_lookup(lists, l->acl_id)))
300 save_mlist(0, l1, TRUE);
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);
309 insert_login(id, u, dummy)
314 if (u->pobox && u->login[0] != '#')
315 insert_name(u->login, id, TRUE, FALSE);
318 void insert_names(id, u, dummy)
325 insert_name(u->last, id, FALSE, FALSE);
326 sprintf(buffer, "%s_%s", u->first, u->last);
327 insert_name(buffer, id, FALSE, TRUE);
328 /* sprintf(buffer, "%c_%s", u->first[0], u->last);
329 insert_name(buffer, id, FALSE, TRUE); */
331 sprintf(buffer, "%s_%c_%s", u->first, u->mi, u->last);
332 insert_name(buffer, id, FALSE, TRUE);
338 insert_name(s, id, nodups, copy)
345 register struct names *ns;
347 register struct idblock *ra;
351 ns = (struct names *) hash_lookup(names, code);
353 if ((ns = (struct names *) perm_malloc(sizeof(struct names))) == NULL) {
354 fprintf(stderr, "ran out of memory inserting name (sorting)\n");
358 ns->name = pstrsave(s);
363 if (hash_store(names, code, ns) < 0) {
364 fprintf(stderr, "Out of memory!\n");
369 if (strcasecmp(ns->name, s)) {
372 if (!strcasecmp(ns->name, s))
375 if ((ns->next = (struct names *) perm_malloc(sizeof(struct names)))
377 fprintf(stderr, "ran out of memory insterting name (sorting)\n");
382 ns->name = pstrsave(s);
390 if (nodups || ns->keep)
396 /* Illegal chars: ! " % ( ) , . / : ; < = > @ [ \ ] ^ { | } */
398 static 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,
418 /* While hashing the string, punt any illegal characters */
426 for (result = 0; c = *s; s++) {
427 if (illegalchars[c]) {
435 /* result = result * 31 + *s; */
436 result = (result << 5) - result + c - '`';
438 return(result < 0 ? -result : result);
444 names = create_hash(20001);
445 hash_step(users, insert_login, NULL);
446 hash_step(lists, save_mlist, FALSE);
447 hash_step(users, insert_names, NULL);
448 fprintf(stderr, "Inserted %d names\n", incount);
452 output_data(dummy, nms, out)
457 register struct names *ns;
458 register struct user *u;
461 for (ns = nms; ns; ns = ns->next) {
462 if (ns->name[0] == 0 || ns->name[1] == 0) {
463 fprintf(stderr, "punting %s due to short name\n", ns->name);
467 u = (struct user *) hash_lookup(users, ns->id);
469 fprintf(out, "%s: %s\n", ns->name, u->pobox);
471 fprintf(out, "%s: =%s=@nobox\n", ns->name, ns->name);
473 } else if (ns->id == 0) {
474 fprintf(out, "%s: =%s=@ambig\n", ns->name, ns->name);
482 output_mlist(id, l, out)
484 register struct list *l;
488 register struct member *m;
489 register struct user *u;
491 if (l->maillist != 2)
493 if (l->acl_t == 'L' &&
494 (l1 = (struct list *) hash_lookup(lists, l->acl_id)))
495 fprintf(out, "owner-%s: %s\n%s: ", l->name, l1->name, l->name);
496 else if (l->acl_t == 'U' &&
497 (u = (struct user *) hash_lookup(users, l->acl_id)))
498 fprintf(out, "owner-%s: %s\n%s: ", l->name, u->login, l->name);
500 fprintf(out, "%s: ", l->name);
503 lwid = strlen(l->name) + 2;
505 for (m = l->m; m; m = m->next) {
506 do_member(out, m->name);
508 if (l->m == (struct member *)NULL)
509 fprintf(out, "/dev/null");
510 fprintf(out, "\n\n");
515 /* print out strings separated by commas, doing line breaks as appropriate */
526 if (!bol && awid + wwid + 2 > AL_MAX_WID) {
527 fprintf(out, ",\n\tcontinuation-%d\ncontinuation-%d: ", cont, cont);
529 awid = lwid = 17 + wwid;
541 if (lwid + wwid + 2 > ML_WID) {
542 fprintf(out, ",\n\t%s", s);
543 awid += lwid + wwid + 2;
548 fprintf(out, ", %s", s);
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);
565 fprintf(out, "\n%s\n# People\n%s\n", divide, divide);
566 hash_step(names, output_data, out);
567 fprintf(stderr, "Output %d entries\n", incount);
571 #define chunk_size 102400
573 char *perm_malloc(size)
576 static char *pool = NULL;
577 static unsigned pool_size = 0;
580 if (size > pool_size) {
581 pool = (char *) malloc(chunk_size);
582 pool_size = chunk_size;
586 pool = (char *)(((unsigned) (pool + 1)) & ~1);
587 pool_size -= (pool - ret);
593 * Make a (permenant) copy of a string.
601 /* Kludge for sloppy string semantics */
603 printf("NULL != \"\" !!!!\r\n");
609 p = perm_malloc((u_int)len);
610 if (p) bcopy(s, p, len);