3 * This generates the /usr/lib/aliases mail aliases file for the mailhub.
4 * The aliases file will contain:
7 * sublists of maillists
9 * (c) Copyright 1988, 1990 by the Massachusetts Institute of Technology.
10 * For copying and distribution information, please see the file
15 #include <mit-copyright.h>
19 #include <moira_site.h>
20 #include <sys/types.h>
23 EXEC SQL INCLUDE sqlca;
27 #define AL_MAX_WID 896
29 char *divide = "########################################################################";
31 char *whoami = "aliases.gen";
39 char filename[64], *targetfile;
41 int flag1, flag2, flag3;
44 initialize_sms_error_table();
49 EXEC SQL DATABASE sms;
54 if (stat(argv[1], &sb) == 0) {
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);
60 if (flag1 < 0 && flag2 < 0 && flag3 < 0) {
61 fprintf(stderr, "File %s does not need to be rebuilt.\n",
67 sprintf(filename, "%s~", targetfile);
68 if ((out = fopen(filename, "w")) == NULL) {
69 fprintf(stderr, "unable to open %s for output\n", filename);
72 } else if (argc != 1) {
73 fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
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);
88 fprintf(stderr, "Dumping information\n");
92 fprintf(out, "\n%s\n# End of aliases file\n%s\n", divide, divide);
96 perror("close failed");
101 fix_file(targetfile);
106 struct hash *users, *machines, *strings, *lists;
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;
133 register struct user *u;
134 register struct list *l;
135 register struct member *m;
136 register struct list *memberlist;
138 EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
141 EXEC SQL SELECT modtime INTO :buf FROM list WHERE LIST_ID = 0;
142 EXEC SQL SELECT modtime INTO :buf FROM list WHERE USERS_ID = 0;
144 fprintf(stderr, "Loading machines\n");
145 machines = create_hash(1000);
147 EXEC SQL DECLARE m_cursor CURSOR FOR
150 EXEC SQL OPEN m_cursor;
152 EXEC SQL FETCH m_cursor INTO :id, :name;
153 if (sqlca.sqlcode != 0) break;
154 if (s = index(name, '.'))
157 strcat(name, ".LOCAL");
159 hash_store(machines, id, strsave(name));
161 EXEC SQL CLOSE m_cursor;
164 fprintf(stderr, "Loading strings\n");
165 strings = create_hash(2000);
167 EXEC SQL DECLARE s_cursor CURSOR FOR
168 SELECT string_id, string
170 EXEC SQL OPEN s_cursor;
172 EXEC SQL FETCH s_cursor INTO :id, :name;
173 if (sqlca.sqlcode != 0) break;
174 hash_store(strings, id, strsave(strtrim(name)));
176 EXEC SQL CLOSE s_cursor;
178 fprintf(stderr, "Loading users\n");
179 users = create_hash(12001);
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;
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);
195 u->pobox = (char *) NULL;
196 fprintf(stderr, "User %s's pobox is on a missing machine!\n",
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",
206 u->pobox = (char *) NULL;
207 hash_store(users, id, u);
209 EXEC SQL CLOSE u_cursor;
211 fprintf(stderr, "Loading lists\n");
212 lists = create_hash(15001);
214 EXEC SQL DECLARE l_cursor CURSOR FOR
215 SELECT list_id, name, maillist, desc, acl_type, acl_id
216 FROM list WHERE active != 0;
217 EXEC SQL OPEN l_cursor;
219 EXEC SQL FETCH l_cursor INTO :id, :name, :maillistp,
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));
228 l->m = (struct member *) NULL;
229 hash_store(lists, id, l);
231 EXEC SQL CLOSE l_cursor;
233 fprintf(stderr, "Loading members\n");
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;
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))) {
250 } else if (type[0] == 'L' &&
251 (memberlist = (struct list *) hash_lookup(lists, mid))) {
253 m->name = memberlist->name;
256 } else if (type[0] == 'S' &&
257 (s = hash_lookup(strings, mid))) {
265 EXEC SQL CLOSE mem_cursor;
268 com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
269 critical_alert("DCM", "Alias build encountered INGRES ERROR %d",
275 save_mlist(id, l, force)
277 register struct list *l;
280 register struct member *m;
283 if (l->maillist == 2 ||
284 (l->maillist == 0 && !force))
287 if (l->m && l->m->next == NULL &&
288 !strcasecmp(l->name, l->m->name)) {
295 if (l->acl_t == 'L' && (l1 = (struct list *)hash_lookup(lists, l->acl_id)))
296 save_mlist(0, l1, 1);
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);
309 register struct list *l;
312 register struct member *m;
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);
324 fprintf(out, "%s: ", l->name);
325 lwid = strlen(l->name) + 2;
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");
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...
343 fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
344 hash_step(lists, save_mlist, 0);
348 /* print out strings separated by commas, doing line breaks as appropriate */
359 if (!bol && awid + wwid + 2 > AL_MAX_WID) {
360 fprintf(out, ",\n\tcontinuation-%d\ncontinuation-%d: ", cont, cont);
362 awid = lwid = 17 + wwid;
374 if (lwid + wwid + 2 > ML_WID) {
375 fprintf(out, ",\n\t%s", s);
376 awid += lwid + wwid + 2;
381 fprintf(out, ", %s", s);
386 register struct user *u;
390 fprintf(out, "%s: %s\n", u->login, u->pobox);
394 /* Do user poboxes. Just step through the users table, and print any
395 * we extracted earlier.
401 fprintf(out, "\n%s\n# User Poboxes\n%s\n", divide, divide);
403 hash_step(users, do_pobox, out);
407 put_fill(aliases, string)
409 register char *string;
415 if (*string == 0) return;
416 fputs("# ", aliases);
420 while (*string && *string == ' ') string++;
421 c = (char *)index(string, ' ');
423 wwid = strlen(string);
429 if ((lwid + wwid) > ML_WID) {
430 fputs("\n# ", aliases);
432 fputs(string, aliases);
434 fputs(string, aliases);
437 if (c == (char *)0) break;
438 /* add a space after the word */
439 (void) fputc(' ', aliases);
443 /* add another if after a period */
445 (void) fputc(' ', aliases);
450 (void) fputc('\n', aliases);