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