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