]> andersk Git - moira.git/blob - gen/aliases.dc
Diane Delgado's changes for a fixed table-locking order
[moira.git] / gen / aliases.dc
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, 1990 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 EXEC SQL INCLUDE sqlca;
24
25
26 #define ML_WID  72
27 #define AL_MAX_WID 592
28
29 char *divide = "########################################################################";
30 extern int errno;
31 char *whoami = "aliases.gen";
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
43     out = stdout;
44     initialize_sms_error_table();
45 #ifsql INGRES
46     EXEC SQL CONNECT moira;
47     EXEC SQL SET LOCKMODE SESSION WHERE LEVEL=TABLE, READLOCK=SHARED;
48 #endsql
49 #ifsql INFORMIX
50     EXEC SQL DATABASE moira;
51 #endsql
52
53
54     if (argc == 2) {
55         if (stat(argv[1], &sb) == 0) {
56
57           if (ModDiff (&flag1, "list", sb.st_mtime) ||
58               ModDiff (&flag2, "imembers", sb.st_mtime) ||
59               ModDiff (&flag3, "users", sb.st_mtime)) exit (MR_DATE);
60
61           if (flag1 < 0 && flag2 < 0 && flag3 < 0) {
62             fprintf(stderr, "File %s does not need to be rebuilt.\n",
63                     argv[1]);
64             exit(MR_NO_CHANGE);
65           }
66         }
67         targetfile = argv[1];
68         sprintf(filename, "%s~", targetfile);
69         if ((out = fopen(filename, "w")) == NULL) {
70             fprintf(stderr, "unable to open %s for output\n", filename);
71             exit(MR_OCONFIG);
72         }
73     } else if (argc != 1) {
74         fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
75         exit(MR_ARGS);
76     }
77
78     fprintf(out, "%s\n# Aliases File Extract of %s", divide, ctime(&tm));
79     fprintf(out, "# This file is automatically generated, do not edit it directly.\n%s\n\n", divide);
80
81     get_info();
82 #ifsql INFORMIX
83     EXEC SQL COMMIT WORK;
84 #endif
85 #ifsql INGRES
86     EXEC SQL DISCONNECT;
87 #endsql
88
89     fprintf(stderr, "Dumping information\n");
90     do_mlists(out);
91     do_poboxes(out);
92
93     fprintf(out, "\n%s\n# End of aliases file\n%s\n", divide, divide);
94
95
96     if (fclose(out)) {
97         perror("close failed");
98         exit(MR_CCONFIG);
99     }
100
101     if (argc == 2)
102       fix_file(targetfile);
103     exit(MR_SUCCESS);
104 }
105
106
107 struct hash *users, *machines, *strings, *lists;
108 struct user {
109     char login[9];
110     char *pobox;
111 };
112 struct member {
113     struct member *next;
114     char *name;
115     int list_id;
116 };
117 struct list {
118     char *name;
119     char maillist;
120     char acl_t;
121     char *description;
122     int acl_id;
123     struct member *m;
124 };
125
126
127 get_info()
128 {
129     EXEC SQL BEGIN DECLARE SECTION;
130     int id, maillistp, acl, pid, bid, mid;
131     char name[129], type[9], buf[257];
132     EXEC SQL END DECLARE SECTION;
133     char *s;
134     register struct user *u;
135     register struct list *l;
136     register struct member *m;
137     register struct list *memberlist;
138
139     EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
140
141     /* get locks */
142     EXEC SQL SELECT modtime INTO :buf FROM imembers WHERE list_id = 0;
143     EXEC SQL SELECT modtime INTO :buf FROM users WHERE USERS_ID = 0;
144     EXEC SQL SELECT modtime INTO :buf FROM machine WHERE mach_id = 0;
145     EXEC SQL SELECT modtime INTO :buf FROM list WHERE LIST_ID = 0;
146
147     fprintf(stderr, "Loading machines\n");
148     machines = create_hash(1000);
149
150     EXEC SQL DECLARE m_cursor CURSOR FOR 
151       SELECT mach_id, name 
152       FROM machine WHERE mach_id != 0
153       ORDER BY mach_id;
154     EXEC SQL OPEN m_cursor;
155     while (1) {
156       EXEC SQL FETCH m_cursor INTO :id, :name;
157       if (sqlca.sqlcode != 0) break;
158       if (s = index(name, '.'))
159         *s = 0;
160 #ifdef ATHENA
161       strcat(name, ".LOCAL");
162 #endif
163       hash_store(machines, id, strsave(name));
164     }
165     EXEC SQL CLOSE m_cursor;
166
167
168     fprintf(stderr, "Loading strings\n");
169     strings = create_hash(11001);
170
171     EXEC SQL DECLARE s_cursor CURSOR FOR 
172       SELECT string_id, trim(string) 
173       FROM strings
174       ORDER BY string_id;
175     EXEC SQL OPEN s_cursor;
176     while (1) {
177       EXEC SQL FETCH s_cursor INTO :id, :name;
178       if (sqlca.sqlcode != 0) break;
179       hash_store(strings, id, strsave(name));
180     }
181     EXEC SQL CLOSE s_cursor;
182
183     fprintf(stderr, "Loading users\n");
184     users = create_hash(12001);
185
186     EXEC SQL DECLARE u_cursor CURSOR FOR
187       SELECT users_id, login, potype, pop_id, box_id
188       FROM users WHERE status = 1 OR status = 5 OR status = 6
189       ORDER BY users_id;
190     EXEC SQL OPEN u_cursor;
191     while (1) {
192         EXEC SQL FETCH u_cursor INTO :id, :name, :type, :pid, :bid;
193         if (sqlca.sqlcode != 0) break;
194         u = (struct user *) malloc(sizeof(struct user));
195         strcpy(u->login, strtrim(name));
196         if (type[0] == 'P') {
197             if (s = hash_lookup(machines, pid)) {
198                 sprintf(buf, "%s@%s", name, s);
199                 u->pobox = strsave(buf);
200             } else {
201                 u->pobox = (char *) NULL;
202                 fprintf(stderr, "User %s's pobox is on a missing machine!\n",
203                         u->login);
204             }
205         } else if (type[0] ==  'S') {
206             if ((u->pobox = hash_lookup(strings, bid)) == NULL) {
207                 u->pobox = (char *) NULL;
208                 fprintf(stderr, "User %s's pobox string is missing!\n",
209                         u->login);
210             }
211         } else
212           u->pobox = (char *) NULL;
213         hash_store(users, id, u);
214      }
215     EXEC SQL CLOSE u_cursor;
216     EXEC SQL COMMIT;
217
218     fprintf(stderr, "Loading lists\n");
219     lists = create_hash(15001);
220
221     EXEC SQL DECLARE l_cursor CURSOR FOR
222       SELECT list_id, name, maillist, description, acl_type, acl_id
223       FROM list WHERE active != 0 AND list_id != 0
224       ORDER BY list_id;
225     EXEC SQL OPEN l_cursor;
226     while (1) {
227         EXEC SQL FETCH l_cursor INTO :id, :name, :maillistp,
228                                      :buf, :type, :acl;
229         if (sqlca.sqlcode != 0) break;
230         l = (struct list *) malloc(sizeof(struct list));
231         l->name = strsave(strtrim(name));
232         l->maillist = maillistp;
233         l->description = strsave(strtrim(buf));
234         l->acl_t = type[0];
235         l->acl_id = acl;
236         l->m = (struct member *) NULL;
237         hash_store(lists, id, l);
238       }
239     EXEC SQL CLOSE l_cursor;
240     EXEC SQL COMMIT;
241
242     fprintf(stderr, "Loading members\n");
243
244     EXEC SQL DECLARE mem_cursor CURSOR FOR
245       SELECT list_id, member_type, member_id
246       FROM imembers WHERE direct = 1
247       ORDER BY list_id;
248     EXEC SQL OPEN mem_cursor;
249     while (1) {
250         EXEC SQL FETCH mem_cursor INTO :id, :type, :mid;
251         if (sqlca.sqlcode != 0) break;
252         if (id == 0)
253             continue;
254         if (l = (struct list *) hash_lookup(lists, id)) {
255             m = (struct member *) malloc(sizeof(struct member));
256             if (type[0] == 'U' &&
257                 (u = (struct user *) hash_lookup(users, mid))) {
258                 m->list_id = 0;
259                 m->name = u->login;
260                 m->next = l->m;
261                 l->m = m;
262             } else if (type[0] == 'L' &&
263                        (memberlist = (struct list *) hash_lookup(lists, mid))) {
264                 m->list_id = mid;
265                 m->name = memberlist->name;
266                 m->next = l->m;
267                 l->m = m;
268             } else if (type[0] == 'S' &&
269                        (s = hash_lookup(strings, mid))) {
270                 m->list_id = 0;
271                 m->name = s;
272                 m->next = l->m;
273                 l->m = m;
274             }
275         }
276     }
277     EXEC SQL CLOSE mem_cursor;
278     return;
279  sqlerr:
280     com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
281     critical_alert("DCM", "Alias build encountered INGRES ERROR %d",
282                    sqlca.sqlcode);
283     exit(MR_INGRES_ERR);
284 }
285
286
287 save_mlist(id, l, force)
288 int id;
289 register struct list *l;
290 int force;
291 {
292     register struct member *m;
293     struct list *l1;
294
295     if (l->maillist == 2 ||
296         (l->maillist == 0 && !force))
297       return;
298
299     if (l->m && l->m->next == NULL &&
300         !strcasecmp(l->name, l->m->name)) {
301         l->maillist = 0;
302         return;
303     }
304     l->maillist = 2;
305     output_mlist(id, l);
306
307     if (l->acl_t == 'L' && (l1 = (struct list *)hash_lookup(lists, l->acl_id)))
308       save_mlist(0, l1, 1);
309     
310     for (m = l->m; m; m = m->next) {
311         if (m->list_id && (l1 = (struct list *)hash_lookup(lists, m->list_id)))
312           save_mlist(0, l1, 1);
313     }
314 }
315
316
317 int lwid, bol, awid;
318
319 output_mlist(id, l)
320 int id;
321 register struct list *l;
322 {
323     struct list *l1;
324     register struct member *m;
325     struct user *u;
326
327     put_fill(out, l->description);
328     if (l->acl_t ==  'L') {
329         if (l1 = (struct list *) hash_lookup(lists, l->acl_id))
330           fprintf(out, "owner-%s: %s\n", l->name, l1->name);
331     } else if (l->acl_t ==  'U') {
332         if (u = (struct user *) hash_lookup(users, l->acl_id))
333           fprintf(out, "owner-%s: %s\n", l->name, u->login);
334     }
335
336     fprintf(out, "%s: ", l->name);
337     lwid = strlen(l->name) + 2;
338     bol = 1;
339     for (m = l->m; m; m = m->next)
340       do_member(out, m->name);
341     if (l->m == (struct member *)NULL)
342       fprintf(out, "/dev/null");
343     fprintf(out, "\n\n");
344 }
345
346
347 /* Extract mailing lists.  Make a list of all mailinglists, then
348  * process them, adding any sub-lists or acl lists to the list of lists
349  * to be processed.  If further sublists are encountered, repeat...
350  */
351
352 do_mlists(out)
353 FILE *out;
354 {
355     fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
356     hash_step(lists, save_mlist, 0);
357 }
358
359
360 /* print out strings separated by commas, doing line breaks as appropriate */
361
362 do_member(out, s)
363 FILE *out;
364 register char *s;
365 {
366     register wwid;
367     static int cont = 1;
368
369     wwid = strlen(s);
370
371     if (!bol && awid + wwid + 2 > AL_MAX_WID) {
372         fprintf(out, ",\n\tcontinuation-%d\ncontinuation-%d: ", cont, cont);
373         cont++;
374         awid = lwid = 17 + wwid;
375         fputs(s, out);
376         return;
377     }
378
379     if (bol) {
380         lwid += wwid;
381         awid = lwid;
382         fputs(s, out);
383         bol = 0;
384         return;
385     }
386     if (lwid + wwid + 2 > ML_WID) {
387         fprintf(out, ",\n\t%s", s);
388         awid += lwid + wwid + 2;
389         lwid = wwid + 8;
390         return;
391     }
392     lwid += wwid + 2;
393     fprintf(out, ", %s", s);
394 }
395
396 do_pobox(id, u, out)
397 int id;
398 register struct user *u;
399 FILE *out;
400 {
401     if (u->pobox)
402       fprintf(out, "%s: %s\n", u->login, u->pobox);
403 }
404
405
406 /* Do user poboxes.  Just step through the users table, and print any
407  * we extracted earlier.
408  */
409
410 do_poboxes(out)
411 FILE *out;
412 {
413     fprintf(out, "\n%s\n# User Poboxes\n%s\n", divide, divide);
414
415     hash_step(users, do_pobox, out);
416 }
417
418
419 put_fill(aliases, string)
420 FILE *aliases;
421 register char *string;
422 {
423     register char *c;
424     register int lwid;
425     register int wwid;
426
427     if (*string == 0) return;
428     fputs("#  ", aliases);
429     lwid = 3;
430
431     while (1) {
432         while (*string && *string == ' ') string++;
433         c = (char *)index(string, ' ');
434         if (c == 0) {
435             wwid = strlen(string);
436         } else {
437             wwid = c - string;
438             *c = 0;
439         }
440
441         if ((lwid + wwid) > ML_WID) {
442             fputs("\n#  ", aliases);
443             lwid = 3;
444             fputs(string, aliases);
445         } else {
446             fputs(string, aliases);
447         }
448
449         if (c == (char *)0) break;
450         /* add a space after the word */
451         (void) fputc(' ', aliases);
452         wwid++;
453         lwid += wwid;
454         string += wwid;
455         /* add another if after a period */
456         if (*--c == '.') {
457             (void) fputc(' ', aliases);
458             lwid++;
459         }
460     }
461
462     (void) fputc('\n', aliases);
463 }
464
465
466
This page took 0.06906 seconds and 5 git commands to generate.