]> andersk Git - moira.git/blob - gen/aliases.qc
moved PCAP field defines to sms_app.h where they belong;
[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     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(SMS_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(SMS_OCONFIG);
71         }
72     } else if (argc != 1) {
73         fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
74         exit(SMS_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(SMS_CCONFIG);
95     }
96
97     if (argc == 2)
98       fix_file(targetfile);
99     exit(SMS_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     char buf[256];
114     int ingres_errno;
115
116     switch (*num) {
117     case INGRES_DEADLOCK:
118         ingres_errno = SMS_DEADLOCK;
119         break;
120     default:
121         ingres_errno = SMS_INGRES_ERR;
122     }
123     com_err(whoami, SMS_INGRES_ERR, " code %d\n", *num);
124     critical_alert("DCM", "Alias build encountered INGRES ERROR %d", *num);
125     exit(ingres_errno);
126 }
127
128
129 struct hash *users, *machines, *strings, *lists;
130 struct user {
131     char login[9];
132     char *pobox;
133 };
134 struct member {
135     struct member *next;
136     char *name;
137     int list_id;
138 };
139 struct list {
140     char name[33];
141     char maillist;
142     char acl_t;
143     char description[256];
144     int acl_id;
145     struct member *m;
146 };
147
148
149 get_info()
150 ##{
151 ##  int id, maillistp, acl, pid, bid, mid;
152 ##  char name[129], type[9], buf[257];
153     char *s;
154     register struct user *u;
155     register struct list *l;
156     register struct member *m;
157     register struct list *memberlist;
158
159     /* get locks */
160 ##  retrieve (buf = list.modtime) where list.list_id = 0
161 ##  retrieve (buf = users.modtime) where users.users_id = 0
162
163     fprintf(stderr, "Loading machines\n");
164     machines = create_hash(1000);
165 ##  retrieve (id = machine.mach_id, name = machine.#name) {
166       if (s = index(name, '.'))
167         *s = 0;
168       sprintf(buf, "%s.LOCAL", name);
169       hash_store(machines, id, strsave(buf));
170 ##  }
171
172     fprintf(stderr, "Loading strings\n");
173     strings = create_hash(2000);
174 ##  retrieve (id = strings.string_id, name = strings.string) {
175         hash_store(strings, id, strsave(strtrim(name)));
176 ##  }
177
178     fprintf(stderr, "Loading users\n");
179     users = create_hash(15000);
180 ##  range of u is users
181 ##  retrieve (id = u.users_id, name = u.login, type = u.potype,
182 ##            pid = u.pop_id, bid = u.box_id) 
183 ##      where u.status = 1 or u.status = 5 or u.status = 6 {
184         u = (struct user *) malloc(sizeof(struct user));
185         strcpy(u->login, strtrim(name));
186         u->pobox = (char *) NULL;
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                 fprintf(stderr, "User %s's pobox is on a missing machine!\n",
193                         u->login);
194             }
195         } else if (type[0] ==  'S') {
196             if ((u->pobox = hash_lookup(strings, bid)) == NULL)
197               fprintf(stderr, "User %s's pobox string is missing!\n", u->login);
198         }
199         hash_store(users, id, u);
200 ##  }
201
202     fprintf(stderr, "Loading lists\n");
203     lists = create_hash(15000);
204 ##  range of l is list
205 ##  retrieve (id = l.list_id, name = l.#name, maillistp = l.maillist,
206 ##            buf = l.desc, type = l.acl_type, acl = l.acl_id)
207 ##    where l.active != 0 {
208         l = (struct list *) malloc(sizeof(struct list));
209         strcpy(l->name, strtrim(name));
210         l->maillist = maillistp;
211         strcpy(l->description, strtrim(buf));
212         l->acl_t = type[0];
213         l->acl_id = acl;
214         l->m = (struct member *) NULL;
215         hash_store(lists, id, l);
216 ##  }
217
218
219     fprintf(stderr, "Loading members\n");
220 ##  range of m is imembers
221 ##  retrieve (id = m.list_id, type = m.member_type, mid = m.member_id)
222 ##      where m.direct = 1  {
223         if (l = (struct list *) hash_lookup(lists, id)) {
224             m = (struct member *) malloc(sizeof(struct member));
225             m->name = (char *) NULL;
226             if (type[0] == 'U') {
227                 m->list_id = 0;
228                 if (u = (struct user *) hash_lookup(users, mid))
229                   m->name = u->login;
230             } else if (type[0] == 'L') {
231                 m->list_id = mid;
232                 if (memberlist = (struct list *) hash_lookup(lists, mid))
233                   m->name = memberlist->name;
234             } else if (type[0] == 'S') {
235                 m->list_id = 0;
236                 if (s = hash_lookup(strings, mid))
237                   m->name = s;
238             }
239             if (m->name != (char *) NULL) {
240                 m->next = l->m;
241                 l->m = m;
242             }
243         }
244 ##  }
245 ##}
246
247
248 void save_mlist(id, l, sq)
249 int id;
250 struct list *l;
251 struct save_queue *sq;
252 {
253     if (l->maillist)
254       sq_save_unique_data(sq, id);
255 }
256
257
258 /* Extract mailing lists.  Make a list of all mailinglists, then
259  * process them, adding any sub-lists or acl lists to the list of lists
260  * to be processed.  If further sublists are encountered, repeat...
261  */
262
263 int lwid, bol, awid;
264
265 do_mlists(out)
266 FILE *out;
267 {
268     register struct list *l;
269     struct list *l1;
270     register struct member *m;
271     struct user *u;
272     register struct save_queue *sq;
273     struct save_queue *sq_create();
274     int id;
275
276     sq = sq_create();
277     fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
278
279     hash_step(lists, save_mlist, sq);
280
281     while (sq_get_data(sq, &id)) {
282         l = (struct list *) hash_lookup(lists, id);
283         if (l->m &&                       /* there's at least one member */
284             l->m->next == NULL &&         /* there's only one member */
285             !strcmp(l->name, l->m->name)) /* the member is same as list */
286           continue;
287         put_fill(out, l->description);
288         if (l->acl_t ==  'L') {
289             if (l1 = (struct list *) hash_lookup(lists, l->acl_id)) {
290                 fprintf(out, "owner-%s: %s\n", l->name, l1->name);
291                 sq_save_unique_data(sq, l->acl_id);
292             }
293         } else if (l->acl_t ==  'U') {
294             if (u = (struct user *) hash_lookup(users, l->acl_id))
295               fprintf(out, "owner-%s: %s\n", l->name, u->login);
296         }
297         fprintf(out, "%s: ", l->name);
298         lwid = strlen(l->name) + 2;
299         bol = 1;
300         for (m = l->m; m; m = m->next) {
301             if (m->list_id != 0)
302               sq_save_unique_data(sq, m->list_id);
303             do_member(out, m->name);
304         }
305         fprintf(out, "\n\n");
306     }
307
308 /*  Removed for speed, since this take 10 minutes to free, and we don't
309  *  really need the memory reclaimed.
310  *  sq_destroy(sq); */
311 }
312
313
314 /* print out strings separated by commas, doing line breaks as appropriate */
315
316 do_member(out, s)
317 FILE *out;
318 register char *s;
319 {
320     register wwid;
321     static int cont = 1;
322
323     strtrim(s);
324     wwid = strlen(s);
325
326     if (!bol && awid + wwid + 2 > AL_MAX_WID) {
327         fprintf(out, ",\n\tcontinuation-%d\ncontinuation-%d: ", cont, cont);
328         cont++;
329         awid = lwid = bol = 17;
330     }
331
332     if (bol) {
333         lwid += wwid;
334         awid = lwid;
335         fprintf(out, "%s", s);
336         bol = 0;
337         return;
338     }
339     if (lwid + wwid + 2 > ML_WID) {
340         fprintf(out, ",\n\t%s", s);
341         awid += lwid + wwid + 2;
342         lwid = wwid + 8;
343         return;
344     }
345     lwid += wwid + 2;
346     fprintf(out, ", %s", s);
347 }
348
349 do_pobox(id, u, out)
350 int id;
351 register struct user *u;
352 FILE *out;
353 {
354     if (u->pobox)
355       fprintf(out, "%s: %s\n", u->login, u->pobox);
356 }
357
358
359 /* Do user poboxes.  Just step through the users table, and print any
360  * we extracted earlier.
361  */
362
363 do_poboxes(out)
364 FILE *out;
365 {
366     register char *p;
367     char *index();
368
369     fprintf(out, "\n%s\n# User Poboxes\n%s\n", divide, divide);
370
371     hash_step(users, do_pobox, out);
372 }
373
374
375 put_fill(aliases, string)
376 FILE *aliases;
377 register char *string;
378 {
379     register char *c;
380     register int lwid;
381     register int wwid;
382
383     if (*string == 0) return;
384     fputs("#  ", aliases);
385     lwid = 3;
386
387     while (1) {
388         while (*string && *string == ' ') string++;
389         c = (char *)index(string, ' ');
390         if (c == 0) {
391             wwid = strlen(string);
392         } else {
393             wwid = c - string;
394             *c = 0;
395         }
396
397         if ((lwid + wwid) > ML_WID) {
398             fputs("\n#  ", aliases);
399             lwid = 3;
400             fputs(string, aliases);
401         } else {
402             fputs(string, aliases);
403         }
404
405         if (c == (char *)0) break;
406         /* add a space after the word */
407         (void) fputc(' ', aliases);
408         wwid++;
409         lwid += wwid;
410         string += wwid;
411         /* add another if after a period */
412         if (*--c == '.') {
413             (void) fputc(' ', aliases);
414             lwid++;
415         }
416     }
417
418     (void) fputc('\n', aliases);
419 }
This page took 0.109145 seconds and 5 git commands to generate.