]> andersk Git - moira.git/blob - gen/aliases.qc
New Imake stuff
[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 <sms.h>
19 #include <sms_app.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
33
34 main(argc, argv)
35 int argc;
36 char **argv;
37 {
38     long tm = time(NULL);
39     FILE *out= stdout;
40     char filename[64], *targetfile;
41     struct stat sb;
42 ##  int flag1, flag2, flag3;
43 ##  char *filetime;
44     int ingerr();
45
46     IIseterr(ingerr);
47 ##  ingres sms
48
49     if (argc == 2) {
50         if (stat(argv[1], &sb) == 0) {
51             filetime = ingres_date_and_time(sb.st_mtime);
52 ##          retrieve (flag1 = int4(interval("min",tblstats.modtime - filetime)))
53 ##              where tblstats.table = "list"
54 ##          retrieve (flag2 = int4(interval("min",tblstats.modtime - filetime)))
55 ##              where tblstats.table = "members"
56 ##          retrieve (flag3 = int4(interval("min",tblstats.modtime - filetime)))
57 ##              where tblstats.table = "users"
58             if (flag1 < 0 && flag2 < 0 && flag3 < 0) {
59                 fprintf(stderr, "File %s does not need to be rebuilt.\n",
60                         argv[1]);
61                 exit(SMS_NO_CHANGE);
62             }
63         }
64         targetfile = argv[1];
65         sprintf(filename, "%s~", targetfile);
66         if ((out = fopen(filename, "w")) == NULL) {
67             fprintf(stderr, "unable to open %s for output\n", filename);
68             exit(SMS_OCONFIG);
69         }
70     } else if (argc != 1) {
71         fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
72         exit(SMS_ARGS);
73     }
74
75     fprintf(out, "%s\n# Aliases File Extract of %s", divide, ctime(&tm));
76     fprintf(out, "# This file is automatically generated, do not edit it directly.\n%s\n\n", divide);
77
78 ##  begin transaction
79     get_info();
80 ##  end transaction
81 ##  exit
82
83     fprintf(stderr, "Dumping information\n");
84     do_mlists(out);
85     do_poboxes(out);
86
87     fprintf(out, "\n%s\n# End of aliases file\n%s\n", divide, divide);
88
89
90     if (fclose(out)) {
91         perror("close failed");
92         exit(SMS_CCONFIG);
93     }
94
95     if (argc == 2)
96       fix_file(targetfile);
97     exit(SMS_SUCCESS);
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
108 static int ingerr(num)
109     int *num;
110 {
111     char buf[256];
112     int ingres_errno;
113
114     switch (*num) {
115     case INGRES_DEADLOCK:
116         ingres_errno = SMS_DEADLOCK;
117         break;
118     default:
119         ingres_errno = SMS_INGRES_ERR;
120     }
121     com_err(whoami, SMS_INGRES_ERR, " code %d\n", *num);
122     critical_alert("DCM", "Alias build encountered INGRES ERROR %d", *num);
123     exit(ingres_errno);
124 }
125
126
127 struct hash *users, *machines, *strings, *lists;
128 struct user {
129     char login[9];
130     char *pobox;
131 };
132 struct member {
133     struct member *next;
134     char *name;
135     int list_id;
136 };
137 struct list {
138     char name[33];
139     char maillist;
140     char acl_t;
141     char description[256];
142     int acl_id;
143     struct member *m;
144 };
145
146
147 get_info()
148 ##{
149 ##  int id, maillistp, acl, pid, bid, mid;
150 ##  char name[129], type[9], buf[257];
151     char *s;
152     register struct user *u;
153     register struct list *l;
154     register struct member *m;
155     register struct list *memberlist;
156
157     fprintf(stderr, "Loading machines\n");
158     machines = create_hash(1000);
159 ##  retrieve (id = machine.mach_id, name = machine.#name) {
160       if (s = index(name, '.'))
161         *s = 0;
162       sprintf(buf, "%s.LOCAL", name);
163       hash_store(machines, id, strsave(buf));
164 ##  }
165
166     fprintf(stderr, "Loading strings\n");
167     strings = create_hash(2000);
168 ##  retrieve (id = strings.string_id, name = strings.string) {
169         hash_store(strings, id, strsave(strtrim(name)));
170 ##  }
171
172     fprintf(stderr, "Loading users\n");
173     users = create_hash(15000);
174 ##  range of u is users
175 ##  retrieve (id = u.users_id, name = u.login, type = u.potype,
176 ##            pid = u.pop_id, bid = u.box_id) where u.status = 1 {
177         u = (struct user *) malloc(sizeof(struct user));
178         strcpy(u->login, strtrim(name));
179         u->pobox = (char *) NULL;
180         if (type[0] == 'P') {
181             if (s = hash_lookup(machines, pid)) {
182                 sprintf(buf, "%s@%s", name, s);
183                 u->pobox = strsave(buf);
184             } else {
185                 fprintf(stderr, "User %s's pobox is on a missing machine!\n",
186                         u->login);
187             }
188         } else if (type[0] ==  'S') {
189             if ((u->pobox = hash_lookup(strings, bid)) == NULL)
190               fprintf(stderr, "User %s's pobox string is missing!\n", u->login);
191         }
192         hash_store(users, id, u);
193 ##  }
194
195     fprintf(stderr, "Loading lists\n");
196     lists = create_hash(15000);
197 ##  range of l is list
198 ##  retrieve (id = l.list_id, name = l.#name, maillistp = l.maillist,
199 ##            buf = l.desc, type = l.acl_type, acl = l.acl_id)
200 ##    where l.active != 0 {
201         l = (struct list *) malloc(sizeof(struct list));
202         strcpy(l->name, strtrim(name));
203         l->maillist = maillistp;
204         strcpy(l->description, strtrim(buf));
205         l->acl_t = type[0];
206         l->acl_id = acl;
207         l->m = (struct member *) NULL;
208         hash_store(lists, id, l);
209 ##  }
210
211
212     fprintf(stderr, "Loading members\n");
213 ##  range of m is members
214 ##  retrieve (id = m.list_id, type = m.member_type, mid = m.member_id) {
215         if (l = (struct list *) hash_lookup(lists, id)) {
216             m = (struct member *) malloc(sizeof(struct member));
217             m->name = (char *) NULL;
218             if (type[0] == 'U') {
219                 m->list_id = 0;
220                 if (u = (struct user *) hash_lookup(users, mid))
221                   m->name = u->login;
222             } else if (type[0] == 'L') {
223                 m->list_id = mid;
224                 if (memberlist = (struct list *) hash_lookup(lists, mid))
225                   m->name = memberlist->name;
226             } else if (type[0] == 'S') {
227                 m->list_id = 0;
228                 if (s = hash_lookup(strings, mid))
229                   m->name = s;
230             }
231             if (m->name != (char *) NULL) {
232                 m->next = l->m;
233                 l->m = m;
234             }
235         }
236 ##  }
237 ##}
238
239
240 void save_mlist(id, l, sq)
241 int id;
242 struct list *l;
243 struct save_queue *sq;
244 {
245     if (l->maillist)
246       sq_save_unique_data(sq, id);
247 }
248
249
250 /* Extract mailing lists.  Make a list of all mailinglists, then
251  * process them, adding any sub-lists or acl lists to the list of lists
252  * to be processed.  If further sublists are encountered, repeat...
253  */
254
255 int lwid, bol, awid;
256
257 do_mlists(out)
258 FILE *out;
259 {
260     register struct list *l;
261     struct list *l1;
262     register struct member *m;
263     struct user *u;
264     register struct save_queue *sq;
265     struct save_queue *sq_create();
266     int id;
267
268     sq = sq_create();
269     fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
270
271     hash_step(lists, save_mlist, sq);
272
273     while (sq_get_data(sq, &id)) {
274         l = (struct list *) hash_lookup(lists, id);
275         if (l->m &&                       /* there's at least one member */
276             l->m->next == NULL &&         /* there's only one member */
277             !strcmp(l->name, l->m->name)) /* the member is same as list */
278           continue;
279         put_fill(out, l->description);
280         if (l->acl_t ==  'L') {
281             if (l1 = (struct list *) hash_lookup(lists, l->acl_id)) {
282                 fprintf(out, "owner-%s: %s\n", l->name, l1->name);
283                 sq_save_unique_data(sq, l->acl_id);
284             }
285         } else if (l->acl_t ==  'U') {
286             if (u = (struct user *) hash_lookup(users, l->acl_id))
287               fprintf(out, "owner-%s: %s\n", l->name, u->login);
288         }
289         fprintf(out, "%s: ", l->name);
290         lwid = strlen(l->name) + 2;
291         bol = 1;
292         for (m = l->m; m; m = m->next) {
293             if (m->list_id != 0)
294               sq_save_unique_data(sq, m->list_id);
295             do_member(out, m->name);
296         }
297         fprintf(out, "\n\n");
298     }
299
300 /*  Removed for speed, since this take 10 minutes to free, and we don't
301  *  really need the memory reclaimed.
302  *  sq_destroy(sq); */
303 }
304
305
306 /* print out strings separated by commas, doing line breaks as appropriate */
307
308 do_member(out, s)
309 FILE *out;
310 register char *s;
311 {
312     register wwid;
313     static int cont = 1;
314
315     strtrim(s);
316     wwid = strlen(s);
317
318     if (!bol && awid + wwid + 2 > AL_MAX_WID) {
319         fprintf(out, ",\n\tcontinuation-%d\ncontinuation-%d: ", cont, cont);
320         cont++;
321         awid = lwid = bol = 17;
322     }
323
324     if (bol) {
325         lwid += wwid;
326         awid = lwid;
327         fprintf(out, "%s", s);
328         bol = 0;
329         return;
330     }
331     if (lwid + wwid + 2 > ML_WID) {
332         fprintf(out, ",\n\t%s", s);
333         awid += lwid + wwid + 2;
334         lwid = wwid + 8;
335         return;
336     }
337     lwid += wwid + 2;
338     fprintf(out, ", %s", s);
339 }
340
341 do_pobox(id, u, out)
342 int id;
343 register struct user *u;
344 FILE *out;
345 {
346     if (u->pobox)
347       fprintf(out, "%s: %s\n", u->login, u->pobox);
348 }
349
350
351 /* Do user poboxes.  Just step through the users table, and print any
352  * we extracted earlier.
353  */
354
355 do_poboxes(out)
356 FILE *out;
357 {
358     register char *p;
359     char *index();
360
361     fprintf(out, "\n%s\n# User Poboxes\n%s\n", divide, divide);
362
363     hash_step(users, do_pobox, out);
364 }
365
366
367 put_fill(aliases, string)
368 FILE *aliases;
369 register char *string;
370 {
371     register char *c;
372     register int lwid;
373     register int wwid;
374
375     if (*string == 0) return;
376     fputs("#  ", aliases);
377     lwid = 3;
378
379     while (1) {
380         while (*string && *string == ' ') string++;
381         c = (char *)index(string, ' ');
382         if (c == 0) {
383             wwid = strlen(string);
384         } else {
385             wwid = c - string;
386             *c = 0;
387         }
388
389         if ((lwid + wwid) > ML_WID) {
390             fputs("\n#  ", aliases);
391             lwid = 3;
392             fputs(string, aliases);
393         } else {
394             fputs(string, aliases);
395         }
396
397         if (c == (char *)0) break;
398         /* add a space after the word */
399         (void) fputc(' ', aliases);
400         wwid++;
401         lwid += wwid;
402         string += wwid;
403         /* add another if after a period */
404         if (*--c == '.') {
405             (void) fputc(' ', aliases);
406             lwid++;
407         }
408     }
409
410     (void) fputc('\n', aliases);
411 }
This page took 0.069006 seconds and 5 git commands to generate.