]> andersk Git - moira.git/blame - gen/aliases.qc
added copyright message
[moira.git] / gen / aliases.qc
CommitLineData
67796c83 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
0a5ff702 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>.
67796c83 12 */
13
14
0a5ff702 15#include <mit-copyright.h>
67796c83 16#include <stdio.h>
39b94410 17#include <string.h>
67796c83 18#include <sms.h>
19#include <sms_app.h>
5076cbb9 20#include <sys/types.h>
21#include <sys/stat.h>
22#include <sys/time.h>
23
67796c83 24
25#define ML_WID 72
26#define AL_MAX_WID 896
27
28char *divide = "########################################################################";
29extern int errno;
335b0c5e 30char *whoami = "aliases.gen";
5076cbb9 31char *ingres_date_and_time();
67796c83 32
33
34main(argc, argv)
35int argc;
36char **argv;
37{
38 long tm = time(NULL);
39 FILE *out= stdout;
39b94410 40 char filename[64], *targetfile;
5076cbb9 41 struct stat sb;
39b94410 42## int flag1, flag2, flag3;
5076cbb9 43## char *filetime;
335b0c5e 44 int ingerr();
5076cbb9 45
335b0c5e 46 IIseterr(ingerr);
5076cbb9 47## ingres sms
67796c83 48
49 if (argc == 2) {
5076cbb9 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]);
39b94410 61 exit(SMS_NO_CHANGE);
5076cbb9 62 }
63 }
39b94410 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);
67796c83 69 }
70 } else if (argc != 1) {
71 fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
39b94410 72 exit(SMS_ARGS);
67796c83 73 }
74
67796c83 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
39b94410 78## begin transaction
79 get_info();
80## end transaction
81## exit
82
83 fprintf(stderr, "Dumping information\n");
67796c83 84 do_mlists(out);
85 do_poboxes(out);
67796c83 86
87 fprintf(out, "\n%s\n# End of aliases file\n%s\n", divide, divide);
88
67796c83 89
90 if (fclose(out)) {
91 perror("close failed");
39b94410 92 exit(SMS_CCONFIG);
67796c83 93 }
39b94410 94
95 if (argc == 2)
96 fix_file(targetfile);
97 exit(SMS_SUCCESS);
67796c83 98}
99
100
335b0c5e 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
108static 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
39b94410 127struct hash *users, *machines, *strings, *lists;
128struct user {
129 char login[9];
130 char *pobox;
131};
132struct member {
133 struct member *next;
134 char *name;
135 int list_id;
136};
137struct 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
147get_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;
12116e76 155 register struct list *memberlist;
39b94410 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;
12116e76 224 if (memberlist = (struct list *) hash_lookup(lists, mid))
225 m->name = memberlist->name;
39b94410 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
240void save_mlist(id, l, sq)
241int id;
242struct list *l;
243struct save_queue *sq;
244{
245 if (l->maillist)
246 sq_save_unique_data(sq, id);
247}
248
249
39b94410 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...
67796c83 253 */
254
12116e76 255int lwid, bol, awid;
67796c83 256
257do_mlists(out)
258FILE *out;
39b94410 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;
67796c83 267
268 sq = sq_create();
269 fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
270
39b94410 271 hash_step(lists, save_mlist, sq);
67796c83 272
67796c83 273 while (sq_get_data(sq, &id)) {
39b94410 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);
12116e76 283 sq_save_unique_data(sq, l->acl_id);
39b94410 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);
67796c83 288 }
39b94410 289 fprintf(out, "%s: ", l->name);
290 lwid = strlen(l->name) + 2;
67796c83 291 bol = 1;
39b94410 292 for (m = l->m; m; m = m->next) {
12116e76 293 if (m->list_id != 0)
39b94410 294 sq_save_unique_data(sq, m->list_id);
295 do_member(out, m->name);
296 }
67796c83 297 fprintf(out, "\n\n");
298 }
299
12116e76 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); */
39b94410 303}
67796c83 304
305
306/* print out strings separated by commas, doing line breaks as appropriate */
307
308do_member(out, s)
309FILE *out;
310register char *s;
311{
312 register wwid;
67796c83 313 static int cont = 1;
314
39b94410 315 strtrim(s);
67796c83 316 wwid = strlen(s);
317
12116e76 318 if (!bol && awid + wwid + 2 > AL_MAX_WID) {
67796c83 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);
12116e76 333 awid += lwid + wwid + 2;
67796c83 334 lwid = wwid + 8;
335 return;
336 }
337 lwid += wwid + 2;
338 fprintf(out, ", %s", s);
339}
340
39b94410 341do_pobox(id, u, out)
342int id;
343register struct user *u;
344FILE *out;
345{
346 if (u->pobox)
347 fprintf(out, "%s: %s\n", u->login, u->pobox);
348}
349
67796c83 350
39b94410 351/* Do user poboxes. Just step through the users table, and print any
352 * we extracted earlier.
67796c83 353 */
354
355do_poboxes(out)
356FILE *out;
39b94410 357{
358 register char *p;
359 char *index();
67796c83 360
361 fprintf(out, "\n%s\n# User Poboxes\n%s\n", divide, divide);
362
39b94410 363 hash_step(users, do_pobox, out);
364}
67796c83 365
366
367put_fill(aliases, string)
368FILE *aliases;
369register 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.108222 seconds and 5 git commands to generate.