]> andersk Git - moira.git/blame - gen/aliases.dc
fixup SQL
[moira.git] / gen / aliases.dc
CommitLineData
5d5f5413 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>
23EXEC SQL INCLUDE sqlca;
24
25
26#define ML_WID 72
f1567ffb 27#define AL_MAX_WID 592
5d5f5413 28
29char *divide = "########################################################################";
30extern int errno;
31char *whoami = "aliases.gen";
5d5f5413 32FILE *out;
33
34main(argc, argv)
35int argc;
36char **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
bcdea6a2 46 EXEC SQL CONNECT moira;
5d5f5413 47#endsql
48#ifsql INFORMIX
bcdea6a2 49 EXEC SQL DATABASE moira;
5d5f5413 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
106struct hash *users, *machines, *strings, *lists;
107struct user {
108 char login[9];
109 char *pobox;
110};
111struct member {
112 struct member *next;
113 char *name;
114 int list_id;
115};
116struct 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
126get_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 EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
139
140 /* get locks */
141 EXEC SQL SELECT modtime INTO :buf FROM list WHERE LIST_ID = 0;
bcdea6a2 142 EXEC SQL SELECT modtime INTO :buf FROM users WHERE USERS_ID = 0;
5d5f5413 143
144 fprintf(stderr, "Loading machines\n");
145 machines = create_hash(1000);
146
147 EXEC SQL DECLARE m_cursor CURSOR FOR
148 SELECT mach_id, name
149 FROM machine;
150 EXEC SQL OPEN m_cursor;
151 while (1) {
152 EXEC SQL FETCH m_cursor INTO :id, :name;
153 if (sqlca.sqlcode != 0) break;
154 if (s = index(name, '.'))
155 *s = 0;
156#ifdef ATHENA
157 strcat(name, ".LOCAL");
158#endif
159 hash_store(machines, id, strsave(name));
160 }
161 EXEC SQL CLOSE m_cursor;
162
163
164 fprintf(stderr, "Loading strings\n");
165 strings = create_hash(2000);
166
167 EXEC SQL DECLARE s_cursor CURSOR FOR
168 SELECT string_id, string
169 FROM strings;
170 EXEC SQL OPEN s_cursor;
171 while (1) {
172 EXEC SQL FETCH s_cursor INTO :id, :name;
173 if (sqlca.sqlcode != 0) break;
174 hash_store(strings, id, strsave(strtrim(name)));
175 }
176 EXEC SQL CLOSE s_cursor;
177
178 fprintf(stderr, "Loading users\n");
179 users = create_hash(12001);
180
181 EXEC SQL DECLARE u_cursor CURSOR FOR
182 SELECT users_id, login, potype, pop_id, box_id
183 FROM users WHERE status = 1 OR status = 5 OR status = 6;
184 EXEC SQL OPEN u_cursor;
185 while (1) {
186 EXEC SQL FETCH u_cursor INTO :id, :name, :type, :pid, :bid;
187 if (sqlca.sqlcode != 0) break;
188 u = (struct user *) malloc(sizeof(struct user));
189 strcpy(u->login, strtrim(name));
190 if (type[0] == 'P') {
191 if (s = hash_lookup(machines, pid)) {
192 sprintf(buf, "%s@%s", name, s);
193 u->pobox = strsave(buf);
194 } else {
195 u->pobox = (char *) NULL;
196 fprintf(stderr, "User %s's pobox is on a missing machine!\n",
197 u->login);
198 }
199 } else if (type[0] == 'S') {
200 if ((u->pobox = hash_lookup(strings, bid)) == NULL) {
201 u->pobox = (char *) NULL;
202 fprintf(stderr, "User %s's pobox string is missing!\n",
203 u->login);
204 }
205 } else
206 u->pobox = (char *) NULL;
207 hash_store(users, id, u);
208 }
209 EXEC SQL CLOSE u_cursor;
210
211 fprintf(stderr, "Loading lists\n");
212 lists = create_hash(15001);
213
214 EXEC SQL DECLARE l_cursor CURSOR FOR
bcdea6a2 215 SELECT list_id, name, maillist, description, acl_type, acl_id
5d5f5413 216 FROM list WHERE active != 0;
217 EXEC SQL OPEN l_cursor;
218 while (1) {
219 EXEC SQL FETCH l_cursor INTO :id, :name, :maillistp,
220 :buf, :type, :acl;
221 if (sqlca.sqlcode != 0) break;
222 l = (struct list *) malloc(sizeof(struct list));
223 l->name = strsave(strtrim(name));
224 l->maillist = maillistp;
225 l->description = strsave(strtrim(buf));
226 l->acl_t = type[0];
227 l->acl_id = acl;
228 l->m = (struct member *) NULL;
229 hash_store(lists, id, l);
230 }
231 EXEC SQL CLOSE l_cursor;
232
233 fprintf(stderr, "Loading members\n");
234
235 EXEC SQL DECLARE mem_cursor CURSOR FOR
236 SELECT list_id, member_type, member_id
237 FROM imembers WHERE direct = 1;
238 EXEC SQL OPEN mem_cursor;
239 while (1) {
240 EXEC SQL FETCH mem_cursor INTO :id, :type, :mid;
241 if (sqlca.sqlcode != 0) break;
242 if (l = (struct list *) hash_lookup(lists, id)) {
243 m = (struct member *) malloc(sizeof(struct member));
244 if (type[0] == 'U' &&
245 (u = (struct user *) hash_lookup(users, mid))) {
246 m->list_id = 0;
247 m->name = u->login;
248 m->next = l->m;
249 l->m = m;
250 } else if (type[0] == 'L' &&
251 (memberlist = (struct list *) hash_lookup(lists, mid))) {
252 m->list_id = mid;
253 m->name = memberlist->name;
254 m->next = l->m;
255 l->m = m;
256 } else if (type[0] == 'S' &&
257 (s = hash_lookup(strings, mid))) {
258 m->list_id = 0;
259 m->name = s;
260 m->next = l->m;
261 l->m = m;
262 }
263 }
264 }
265 EXEC SQL CLOSE mem_cursor;
266 return;
267 sqlerr:
268 com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
269 critical_alert("DCM", "Alias build encountered INGRES ERROR %d",
270 sqlca.sqlcode);
271 exit(MR_INGRES_ERR);
272}
273
274
275save_mlist(id, l, force)
276int id;
277register struct list *l;
278int force;
279{
280 register struct member *m;
281 struct list *l1;
282
283 if (l->maillist == 2 ||
284 (l->maillist == 0 && !force))
285 return;
286
287 if (l->m && l->m->next == NULL &&
288 !strcasecmp(l->name, l->m->name)) {
289 l->maillist = 0;
290 return;
291 }
292 l->maillist = 2;
293 output_mlist(id, l);
294
295 if (l->acl_t == 'L' && (l1 = (struct list *)hash_lookup(lists, l->acl_id)))
296 save_mlist(0, l1, 1);
297
298 for (m = l->m; m; m = m->next) {
299 if (m->list_id && (l1 = (struct list *)hash_lookup(lists, m->list_id)))
300 save_mlist(0, l1, 1);
301 }
302}
303
304
305int lwid, bol, awid;
306
307output_mlist(id, l)
308int id;
309register struct list *l;
310{
311 struct list *l1;
312 register struct member *m;
313 struct user *u;
314
315 put_fill(out, l->description);
316 if (l->acl_t == 'L') {
317 if (l1 = (struct list *) hash_lookup(lists, l->acl_id))
318 fprintf(out, "owner-%s: %s\n", l->name, l1->name);
319 } else if (l->acl_t == 'U') {
320 if (u = (struct user *) hash_lookup(users, l->acl_id))
321 fprintf(out, "owner-%s: %s\n", l->name, u->login);
322 }
323
324 fprintf(out, "%s: ", l->name);
325 lwid = strlen(l->name) + 2;
326 bol = 1;
327 for (m = l->m; m; m = m->next)
328 do_member(out, m->name);
329 if (l->m == (struct member *)NULL)
330 fprintf(out, "/dev/null");
331 fprintf(out, "\n\n");
332}
333
334
335/* Extract mailing lists. Make a list of all mailinglists, then
336 * process them, adding any sub-lists or acl lists to the list of lists
337 * to be processed. If further sublists are encountered, repeat...
338 */
339
340do_mlists(out)
341FILE *out;
342{
343 fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
344 hash_step(lists, save_mlist, 0);
345}
346
347
348/* print out strings separated by commas, doing line breaks as appropriate */
349
350do_member(out, s)
351FILE *out;
352register char *s;
353{
354 register wwid;
355 static int cont = 1;
356
357 wwid = strlen(s);
358
359 if (!bol && awid + wwid + 2 > AL_MAX_WID) {
360 fprintf(out, ",\n\tcontinuation-%d\ncontinuation-%d: ", cont, cont);
361 cont++;
362 awid = lwid = 17 + wwid;
363 fputs(s, out);
364 return;
365 }
366
367 if (bol) {
368 lwid += wwid;
369 awid = lwid;
370 fputs(s, out);
371 bol = 0;
372 return;
373 }
374 if (lwid + wwid + 2 > ML_WID) {
375 fprintf(out, ",\n\t%s", s);
376 awid += lwid + wwid + 2;
377 lwid = wwid + 8;
378 return;
379 }
380 lwid += wwid + 2;
381 fprintf(out, ", %s", s);
382}
383
384do_pobox(id, u, out)
385int id;
386register struct user *u;
387FILE *out;
388{
389 if (u->pobox)
390 fprintf(out, "%s: %s\n", u->login, u->pobox);
391}
392
393
394/* Do user poboxes. Just step through the users table, and print any
395 * we extracted earlier.
396 */
397
398do_poboxes(out)
399FILE *out;
400{
401 fprintf(out, "\n%s\n# User Poboxes\n%s\n", divide, divide);
402
403 hash_step(users, do_pobox, out);
404}
405
406
407put_fill(aliases, string)
408FILE *aliases;
409register char *string;
410{
411 register char *c;
412 register int lwid;
413 register int wwid;
414
415 if (*string == 0) return;
416 fputs("# ", aliases);
417 lwid = 3;
418
419 while (1) {
420 while (*string && *string == ' ') string++;
421 c = (char *)index(string, ' ');
422 if (c == 0) {
423 wwid = strlen(string);
424 } else {
425 wwid = c - string;
426 *c = 0;
427 }
428
429 if ((lwid + wwid) > ML_WID) {
430 fputs("\n# ", aliases);
431 lwid = 3;
432 fputs(string, aliases);
433 } else {
434 fputs(string, aliases);
435 }
436
437 if (c == (char *)0) break;
438 /* add a space after the word */
439 (void) fputc(' ', aliases);
440 wwid++;
441 lwid += wwid;
442 string += wwid;
443 /* add another if after a period */
444 if (*--c == '.') {
445 (void) fputc(' ', aliases);
446 lwid++;
447 }
448 }
449
450 (void) fputc('\n', aliases);
451}
This page took 0.138402 seconds and 5 git commands to generate.