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();
46 EXEC SQL CONNECT moira;
49 EXEC SQL DATABASE moira;
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 /* The following WHENEVER is declarative, not executed,
139 * and applies for the remainder of this file only.
141 EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
144 EXEC SQL SELECT modtime INTO :buf FROM list WHERE list_id = 0;
145 EXEC SQL SELECT modtime INTO :buf FROM list WHERE users_id = 0;
147 fprintf(stderr, "Loading machines\n");
148 machines = create_hash(1000);
150 EXEC SQL DECLARE m_cursor CURSOR FOR
153 EXEC SQL OPEN m_cursor;
155 EXEC SQL FETCH m_cursor INTO :id, :name;
156 if (sqlca.sqlcode != 0) break;
157 if (s = index(name, '.'))
160 strcat(name, ".LOCAL");
162 hash_store(machines, id, strsave(name));
164 EXEC SQL CLOSE m_cursor;
167 fprintf(stderr, "Loading strings\n");
168 strings = create_hash(2000);
170 EXEC SQL DECLARE s_cursor CURSOR FOR
171 SELECT string_id, string
173 EXEC SQL OPEN s_cursor;
175 EXEC SQL FETCH s_cursor INTO :id, :name;
176 if (sqlca.sqlcode != 0) break;
177 hash_store(strings, id, strsave(strtrim(name)));
179 EXEC SQL CLOSE s_cursor;
181 fprintf(stderr, "Loading users\n");
182 users = create_hash(12001);
184 EXEC SQL DECLARE u_cursor CURSOR FOR
185 SELECT users_id, login, potype, pop_id, box_id
186 FROM users WHERE status = 1 OR status = 5 OR status = 6;
187 EXEC SQL OPEN u_cursor;
189 EXEC SQL FETCH u_cursor INTO :id, :name, :type, :pid, :bid;
190 if (sqlca.sqlcode != 0) break;
191 u = (struct user *) malloc(sizeof(struct user));
192 strcpy(u->login, strtrim(name));
193 if (type[0] == 'P') {
194 if (s = hash_lookup(machines, pid)) {
195 sprintf(buf, "%s@%s", name, s);
196 u->pobox = strsave(buf);
198 u->pobox = (char *) NULL;
199 fprintf(stderr, "User %s's pobox is on a missing machine!\n",
202 } else if (type[0] == 'S') {
203 if ((u->pobox = hash_lookup(strings, bid)) == NULL) {
204 u->pobox = (char *) NULL;
205 fprintf(stderr, "User %s's pobox string is missing!\n",
209 u->pobox = (char *) NULL;
210 hash_store(users, id, u);
212 EXEC SQL CLOSE u_cursor;
214 fprintf(stderr, "Loading lists\n");
215 lists = create_hash(15001);
217 EXEC SQL DECLARE l_cursor CURSOR FOR
218 SELECT list_id, name, maillist, description, acl_type, acl_id
219 FROM list WHERE active != 0;
220 EXEC SQL OPEN l_cursor;
222 EXEC SQL FETCH l_cursor INTO :id, :name, :maillistp,
224 if (sqlca.sqlcode != 0) break;
225 l = (struct list *) malloc(sizeof(struct list));
226 l->name = strsave(strtrim(name));
227 l->maillist = maillistp;
228 l->description = strsave(strtrim(buf));
231 l->m = (struct member *) NULL;
232 hash_store(lists, id, l);
234 EXEC SQL CLOSE l_cursor;
236 fprintf(stderr, "Loading members\n");
238 EXEC SQL DECLARE mem_cursor CURSOR FOR
239 SELECT list_id, member_type, member_id
240 FROM imembers WHERE direct = 1;
241 EXEC SQL OPEN mem_cursor;
243 EXEC SQL FETCH mem_cursor INTO :id, :type, :mid;
244 if (sqlca.sqlcode != 0) break;
245 if (l = (struct list *) hash_lookup(lists, id)) {
246 m = (struct member *) malloc(sizeof(struct member));
247 if (type[0] == 'U' &&
248 (u = (struct user *) hash_lookup(users, mid))) {
253 } else if (type[0] == 'L' &&
254 (memberlist = (struct list *) hash_lookup(lists, mid))) {
256 m->name = memberlist->name;
259 } else if (type[0] == 'S' &&
260 (s = hash_lookup(strings, mid))) {
268 EXEC SQL CLOSE mem_cursor;
271 com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
272 critical_alert("DCM", "Alias build encountered INGRES ERROR %d",
278 save_mlist(id, l, force)
280 register struct list *l;
283 register struct member *m;
286 if (l->maillist == 2 ||
287 (l->maillist == 0 && !force))
290 if (l->m && l->m->next == NULL &&
291 !strcasecmp(l->name, l->m->name)) {
298 if (l->acl_t == 'L' && (l1 = (struct list *)hash_lookup(lists, l->acl_id)))
299 save_mlist(0, l1, 1);
301 for (m = l->m; m; m = m->next) {
302 if (m->list_id && (l1 = (struct list *)hash_lookup(lists, m->list_id)))
303 save_mlist(0, l1, 1);
312 register struct list *l;
315 register struct member *m;
318 put_fill(out, l->description);
319 if (l->acl_t == 'L') {
320 if (l1 = (struct list *) hash_lookup(lists, l->acl_id))
321 fprintf(out, "owner-%s: %s\n", l->name, l1->name);
322 } else if (l->acl_t == 'U') {
323 if (u = (struct user *) hash_lookup(users, l->acl_id))
324 fprintf(out, "owner-%s: %s\n", l->name, u->login);
327 fprintf(out, "%s: ", l->name);
328 lwid = strlen(l->name) + 2;
330 for (m = l->m; m; m = m->next)
331 do_member(out, m->name);
332 if (l->m == (struct member *)NULL)
333 fprintf(out, "/dev/null");
334 fprintf(out, "\n\n");
338 /* Extract mailing lists. Make a list of all mailinglists, then
339 * process them, adding any sub-lists or acl lists to the list of lists
340 * to be processed. If further sublists are encountered, repeat...
346 fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
347 hash_step(lists, save_mlist, 0);
351 /* print out strings separated by commas, doing line breaks as appropriate */
362 if (!bol && awid + wwid + 2 > AL_MAX_WID) {
363 fprintf(out, ",\n\tcontinuation-%d\ncontinuation-%d: ", cont, cont);
365 awid = lwid = 17 + wwid;
377 if (lwid + wwid + 2 > ML_WID) {
378 fprintf(out, ",\n\t%s", s);
379 awid += lwid + wwid + 2;
384 fprintf(out, ", %s", s);
389 register struct user *u;
393 fprintf(out, "%s: %s\n", u->login, u->pobox);
397 /* Do user poboxes. Just step through the users table, and print any
398 * we extracted earlier.
404 fprintf(out, "\n%s\n# User Poboxes\n%s\n", divide, divide);
406 hash_step(users, do_pobox, out);
410 put_fill(aliases, string)
412 register char *string;
418 if (*string == 0) return;
419 fputs("# ", aliases);
423 while (*string && *string == ' ') string++;
424 c = (char *)index(string, ' ');
426 wwid = strlen(string);
432 if ((lwid + wwid) > ML_WID) {
433 fputs("\n# ", aliases);
435 fputs(string, aliases);
437 fputs(string, aliases);
440 if (c == (char *)0) break;
441 /* add a space after the word */
442 (void) fputc(' ', aliases);
446 /* add another if after a period */
448 (void) fputc(' ', aliases);
453 (void) fputc('\n', aliases);