]> andersk Git - moira.git/blob - gen/aliases.qc
Used /bin/sh format instead of /bin/csh format, by accident.
[moira.git] / gen / aliases.qc
1 /* $Header$
2  *
3  * This generates the /usr/lib/aliases mail aliases file for the mailhub.
4  * The aliases file will contain:
5  *      user pobox entries
6  *      maillist expansions
7  *      sublists of maillists
8  *
9  *  (c) Copyright 1988 by the Massachusetts Institute of Technology.
10  *  For copying and distribution information, please see the file
11  *  <mit-copyright.h>.
12  */
13
14
15 #include <mit-copyright.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <moira.h>
19 #include <moira_site.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/time.h>
23
24
25 #define ML_WID  72
26 #define AL_MAX_WID 896
27
28 char *divide = "########################################################################";
29 extern int errno;
30 char *whoami = "aliases.gen";
31 char *ingres_date_and_time();
32 FILE *out;
33
34 main(argc, argv)
35 int argc;
36 char **argv;
37 {
38     long tm = time(NULL);
39     char filename[64], *targetfile;
40     struct stat sb;
41 ##  int flag1, flag2, flag3;
42 ##  char *filetime;
43     int ingerr();
44
45     out= stdout;
46     IIseterr(ingerr);
47     initialize_sms_error_table();
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 (flag1 = int4(interval("min",tblstats.modtime - filetime)))
55 ##              where tblstats.table = "list"
56 ##          retrieve (flag2 = int4(interval("min",tblstats.modtime - filetime)))
57 ##              where tblstats.table = "imembers"
58 ##          retrieve (flag3 = int4(interval("min",tblstats.modtime - filetime)))
59 ##              where tblstats.table = "users"
60             if (flag1 < 0 && flag2 < 0 && flag3 < 0) {
61                 fprintf(stderr, "File %s does not need to be rebuilt.\n",
62                         argv[1]);
63                 exit(MR_NO_CHANGE);
64             }
65         }
66         targetfile = argv[1];
67         sprintf(filename, "%s~", targetfile);
68         if ((out = fopen(filename, "w")) == NULL) {
69             fprintf(stderr, "unable to open %s for output\n", filename);
70             exit(MR_OCONFIG);
71         }
72     } else if (argc != 1) {
73         fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
74         exit(MR_ARGS);
75     }
76
77     fprintf(out, "%s\n# Aliases File Extract of %s", divide, ctime(&tm));
78     fprintf(out, "# This file is automatically generated, do not edit it directly.\n%s\n\n", divide);
79
80 ##  begin transaction
81     get_info();
82 ##  end transaction
83 ##  exit
84
85     fprintf(stderr, "Dumping information\n");
86     do_mlists(out);
87     do_poboxes(out);
88
89     fprintf(out, "\n%s\n# End of aliases file\n%s\n", divide, divide);
90
91
92     if (fclose(out)) {
93         perror("close failed");
94         exit(MR_CCONFIG);
95     }
96
97     if (argc == 2)
98       fix_file(targetfile);
99     exit(MR_SUCCESS);
100 }
101
102
103 /*
104  * ingerr: (supposedly) called when Ingres indicates an error.
105  * I have not yet been able to get this to work to intercept a
106  * database open error.
107  */
108 #define INGRES_DEADLOCK 4700
109
110 static int ingerr(num)
111     int *num;
112 {
113     int ingres_errno;
114
115     switch (*num) {
116     case INGRES_DEADLOCK:
117         ingres_errno = MR_DEADLOCK;
118         break;
119     default:
120         ingres_errno = MR_INGRES_ERR;
121     }
122     com_err(whoami, MR_INGRES_ERR, " code %d\n", *num);
123     critical_alert("DCM", "Alias build encountered INGRES ERROR %d", *num);
124     exit(ingres_errno);
125 }
126
127
128 struct hash *users, *machines, *strings, *lists;
129 struct user {
130     char login[9];
131     char *pobox;
132 };
133 struct member {
134     struct member *next;
135     char *name;
136     int list_id;
137 };
138 struct list {
139     char *name;
140     char maillist;
141     char acl_t;
142     char *description;
143     int acl_id;
144     struct member *m;
145 };
146
147
148 get_info()
149 ##{
150 ##  int id, maillistp, acl, pid, bid, mid;
151 ##  char name[129], type[9], buf[257];
152     char *s;
153     register struct user *u;
154     register struct list *l;
155     register struct member *m;
156     register struct list *memberlist;
157
158     /* get locks */
159 ##  retrieve (buf = list.modtime) where list.list_id = 0
160 ##  retrieve (buf = users.modtime) where users.users_id = 0
161
162     fprintf(stderr, "Loading machines\n");
163     machines = create_hash(1000);
164 ##  retrieve (id = machine.mach_id, name = machine.#name) {
165       if (s = index(name, '.'))
166         *s = 0;
167 #ifdef ATHENA
168       strcat(name, ".LOCAL");
169 #endif
170       hash_store(machines, id, strsave(name));
171 ##  }
172
173     fprintf(stderr, "Loading strings\n");
174     strings = create_hash(2000);
175 ##  retrieve (id = strings.string_id, name = strings.string) {
176         hash_store(strings, id, strsave(strtrim(name)));
177 ##  }
178
179     fprintf(stderr, "Loading users\n");
180     users = create_hash(12001);
181 ##  range of u is users
182 ##  retrieve (id = u.users_id, name = u.login, type = u.potype,
183 ##            pid = u.pop_id, bid = u.box_id) 
184 ##      where u.status = 1 or u.status = 5 or u.status = 6 {
185         u = (struct user *) malloc(sizeof(struct user));
186         strcpy(u->login, strtrim(name));
187         if (type[0] == 'P') {
188             if (s = hash_lookup(machines, pid)) {
189                 sprintf(buf, "%s@%s", name, s);
190                 u->pobox = strsave(buf);
191             } else {
192                 u->pobox = (char *) NULL;
193                 fprintf(stderr, "User %s's pobox is on a missing machine!\n",
194                         u->login);
195             }
196         } else if (type[0] ==  'S') {
197             if ((u->pobox = hash_lookup(strings, bid)) == NULL) {
198                 u->pobox = (char *) NULL;
199                 fprintf(stderr, "User %s's pobox string is missing!\n",
200                         u->login);
201             }
202         } else
203           u->pobox = (char *) NULL;
204         hash_store(users, id, u);
205 ##  }
206
207     fprintf(stderr, "Loading lists\n");
208     lists = create_hash(15001);
209 ##  range of l is list
210 ##  retrieve (id = l.list_id, name = l.#name, maillistp = l.maillist,
211 ##            buf = l.desc, type = l.acl_type, acl = l.acl_id)
212 ##    where l.active != 0 {
213         l = (struct list *) malloc(sizeof(struct list));
214         l->name = strsave(strtrim(name));
215         l->maillist = maillistp;
216         l->description = strsave(strtrim(buf));
217         l->acl_t = type[0];
218         l->acl_id = acl;
219         l->m = (struct member *) NULL;
220         hash_store(lists, id, l);
221 ##  }
222
223
224     fprintf(stderr, "Loading members\n");
225 ##  range of m is imembers
226 ##  retrieve (id = m.list_id, type = m.member_type, mid = m.member_id)
227 ##      where m.direct = 1  {
228         if (l = (struct list *) hash_lookup(lists, id)) {
229             m = (struct member *) malloc(sizeof(struct member));
230             if (type[0] == 'U' &&
231                 (u = (struct user *) hash_lookup(users, mid))) {
232                 m->list_id = 0;
233                 m->name = u->login;
234                 m->next = l->m;
235                 l->m = m;
236             } else if (type[0] == 'L' &&
237                        (memberlist = (struct list *) hash_lookup(lists, mid))) {
238                 m->list_id = mid;
239                 m->name = memberlist->name;
240                 m->next = l->m;
241                 l->m = m;
242             } else if (type[0] == 'S' &&
243                        (s = hash_lookup(strings, mid))) {
244                 m->list_id = 0;
245                 m->name = s;
246                 m->next = l->m;
247                 l->m = m;
248             }
249         }
250 ##  }
251 ##}
252
253
254 save_mlist(id, l, force)
255 int id;
256 register struct list *l;
257 int force;
258 {
259     register struct member *m;
260     struct list *l1;
261
262     if (l->maillist == 2 ||
263         (l->maillist == 0 && !force))
264       return;
265
266     if (l->m && l->m->next == NULL &&
267         !strcasecmp(l->name, l->m->name)) {
268         l->maillist = 0;
269         return;
270     }
271     l->maillist = 2;
272     output_mlist(id, l);
273
274     if (l->acl_t == 'L' && (l1 = (struct list *)hash_lookup(lists, l->acl_id)))
275       save_mlist(0, l1, 1);
276     
277     for (m = l->m; m; m = m->next) {
278         if (m->list_id && (l1 = (struct list *)hash_lookup(lists, m->list_id)))
279           save_mlist(0, l1, 1);
280     }
281 }
282
283
284 int lwid, bol, awid;
285
286 output_mlist(id, l)
287 int id;
288 register struct list *l;
289 {
290     struct list *l1;
291     register struct member *m;
292     struct user *u;
293
294     put_fill(out, l->description);
295     if (l->acl_t ==  'L') {
296         if (l1 = (struct list *) hash_lookup(lists, l->acl_id))
297           fprintf(out, "owner-%s: %s\n", l->name, l1->name);
298     } else if (l->acl_t ==  'U') {
299         if (u = (struct user *) hash_lookup(users, l->acl_id))
300           fprintf(out, "owner-%s: %s\n", l->name, u->login);
301     }
302
303     fprintf(out, "%s: ", l->name);
304     lwid = strlen(l->name) + 2;
305     bol = 1;
306     for (m = l->m; m; m = m->next)
307       do_member(out, m->name);
308     if (l->m == (struct member *)NULL)
309       fprintf(out, "/dev/null");
310     fprintf(out, "\n\n");
311 }
312
313
314 /* Extract mailing lists.  Make a list of all mailinglists, then
315  * process them, adding any sub-lists or acl lists to the list of lists
316  * to be processed.  If further sublists are encountered, repeat...
317  */
318
319 do_mlists(out)
320 FILE *out;
321 {
322     fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
323     hash_step(lists, save_mlist, 0);
324 }
325
326
327 /* print out strings separated by commas, doing line breaks as appropriate */
328
329 do_member(out, s)
330 FILE *out;
331 register char *s;
332 {
333     register wwid;
334     static int cont = 1;
335
336     wwid = strlen(s);
337
338     if (!bol && awid + wwid + 2 > AL_MAX_WID) {
339         fprintf(out, ",\n\tcontinuation-%d\ncontinuation-%d: ", cont, cont);
340         cont++;
341         awid = lwid = 17 + wwid;
342         fputs(s, out);
343         return;
344     }
345
346     if (bol) {
347         lwid += wwid;
348         awid = lwid;
349         fputs(s, out);
350         bol = 0;
351         return;
352     }
353     if (lwid + wwid + 2 > ML_WID) {
354         fprintf(out, ",\n\t%s", s);
355         awid += lwid + wwid + 2;
356         lwid = wwid + 8;
357         return;
358     }
359     lwid += wwid + 2;
360     fprintf(out, ", %s", s);
361 }
362
363 do_pobox(id, u, out)
364 int id;
365 register struct user *u;
366 FILE *out;
367 {
368     if (u->pobox)
369       fprintf(out, "%s: %s\n", u->login, u->pobox);
370 }
371
372
373 /* Do user poboxes.  Just step through the users table, and print any
374  * we extracted earlier.
375  */
376
377 do_poboxes(out)
378 FILE *out;
379 {
380     fprintf(out, "\n%s\n# User Poboxes\n%s\n", divide, divide);
381
382     hash_step(users, do_pobox, out);
383 }
384
385
386 put_fill(aliases, string)
387 FILE *aliases;
388 register char *string;
389 {
390     register char *c;
391     register int lwid;
392     register int wwid;
393
394     if (*string == 0) return;
395     fputs("#  ", aliases);
396     lwid = 3;
397
398     while (1) {
399         while (*string && *string == ' ') string++;
400         c = (char *)index(string, ' ');
401         if (c == 0) {
402             wwid = strlen(string);
403         } else {
404             wwid = c - string;
405             *c = 0;
406         }
407
408         if ((lwid + wwid) > ML_WID) {
409             fputs("\n#  ", aliases);
410             lwid = 3;
411             fputs(string, aliases);
412         } else {
413             fputs(string, aliases);
414         }
415
416         if (c == (char *)0) break;
417         /* add a space after the word */
418         (void) fputc(' ', aliases);
419         wwid++;
420         lwid += wwid;
421         string += wwid;
422         /* add another if after a period */
423         if (*--c == '.') {
424             (void) fputc(' ', aliases);
425             lwid++;
426         }
427     }
428
429     (void) fputc('\n', aliases);
430 }
This page took 0.151165 seconds and 5 git commands to generate.