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 592
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;
47 EXEC SQL SET LOCKMODE SESSION WHERE LEVEL=TABLE, READLOCK=SHARED;
50 EXEC SQL DATABASE moira;
55 if (stat(argv[1], &sb) == 0) {
57 if (ModDiff (&flag1, "list", sb.st_mtime) ||
58 ModDiff (&flag2, "imembers", sb.st_mtime) ||
59 ModDiff (&flag3, "users", sb.st_mtime)) exit (MR_DATE);
61 if (flag1 < 0 && flag2 < 0 && flag3 < 0) {
62 fprintf(stderr, "File %s does not need to be rebuilt.\n",
68 sprintf(filename, "%s~", targetfile);
69 if ((out = fopen(filename, "w")) == NULL) {
70 fprintf(stderr, "unable to open %s for output\n", filename);
73 } else if (argc != 1) {
74 fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
78 fprintf(out, "%s\n# Aliases File Extract of %s", divide, ctime(&tm));
79 fprintf(out, "# This file is automatically generated, do not edit it directly.\n%s\n\n", divide);
89 fprintf(stderr, "Dumping information\n");
93 fprintf(out, "\n%s\n# End of aliases file\n%s\n", divide, divide);
97 perror("close failed");
102 fix_file(targetfile);
107 struct hash *users, *machines, *strings, *lists;
129 EXEC SQL BEGIN DECLARE SECTION;
130 int id, maillistp, acl, pid, bid, mid;
131 char name[129], type[9], buf[257];
132 EXEC SQL END DECLARE SECTION;
134 register struct user *u;
135 register struct list *l;
136 register struct member *m;
137 register struct list *memberlist;
139 EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
142 EXEC SQL SELECT modtime INTO :buf FROM imembers WHERE list_id = 0;
143 EXEC SQL SELECT modtime INTO :buf FROM users WHERE USERS_ID = 0;
144 EXEC SQL SELECT modtime INTO :buf FROM machine WHERE mach_id = 0;
145 EXEC SQL SELECT modtime INTO :buf FROM list WHERE LIST_ID = 0;
147 fprintf(stderr, "Loading machines\n");
148 machines = create_hash(1000);
150 EXEC SQL DECLARE m_cursor CURSOR FOR
152 FROM machine WHERE mach_id != 0
154 EXEC SQL OPEN m_cursor;
156 EXEC SQL FETCH m_cursor INTO :id, :name;
157 if (sqlca.sqlcode != 0) break;
158 if (s = index(name, '.'))
161 strcat(name, ".LOCAL");
163 hash_store(machines, id, strsave(name));
165 EXEC SQL CLOSE m_cursor;
168 fprintf(stderr, "Loading strings\n");
169 strings = create_hash(11001);
171 EXEC SQL DECLARE s_cursor CURSOR FOR
172 SELECT string_id, trim(string)
175 EXEC SQL OPEN s_cursor;
177 EXEC SQL FETCH s_cursor INTO :id, :name;
178 if (sqlca.sqlcode != 0) break;
179 hash_store(strings, id, strsave(name));
181 EXEC SQL CLOSE s_cursor;
183 fprintf(stderr, "Loading users\n");
184 users = create_hash(12001);
186 EXEC SQL DECLARE u_cursor CURSOR FOR
187 SELECT users_id, login, potype, pop_id, box_id
188 FROM users WHERE status = 1 OR status = 5 OR status = 6
190 EXEC SQL OPEN u_cursor;
192 EXEC SQL FETCH u_cursor INTO :id, :name, :type, :pid, :bid;
193 if (sqlca.sqlcode != 0) break;
194 u = (struct user *) malloc(sizeof(struct user));
195 strcpy(u->login, strtrim(name));
196 if (type[0] == 'P') {
197 if (s = hash_lookup(machines, pid)) {
198 sprintf(buf, "%s@%s", name, s);
199 u->pobox = strsave(buf);
201 u->pobox = (char *) NULL;
202 fprintf(stderr, "User %s's pobox is on a missing machine!\n",
205 } else if (type[0] == 'S') {
206 if ((u->pobox = hash_lookup(strings, bid)) == NULL) {
207 u->pobox = (char *) NULL;
208 fprintf(stderr, "User %s's pobox string is missing!\n",
212 u->pobox = (char *) NULL;
213 hash_store(users, id, u);
215 EXEC SQL CLOSE u_cursor;
218 fprintf(stderr, "Loading lists\n");
219 lists = create_hash(15001);
221 EXEC SQL DECLARE l_cursor CURSOR FOR
222 SELECT list_id, name, maillist, description, acl_type, acl_id
223 FROM list WHERE active != 0 AND list_id != 0
225 EXEC SQL OPEN l_cursor;
227 EXEC SQL FETCH l_cursor INTO :id, :name, :maillistp,
229 if (sqlca.sqlcode != 0) break;
230 l = (struct list *) malloc(sizeof(struct list));
231 l->name = strsave(strtrim(name));
232 l->maillist = maillistp;
233 l->description = strsave(strtrim(buf));
236 l->m = (struct member *) NULL;
237 hash_store(lists, id, l);
239 EXEC SQL CLOSE l_cursor;
242 fprintf(stderr, "Loading members\n");
244 EXEC SQL DECLARE mem_cursor CURSOR FOR
245 SELECT list_id, member_type, member_id
246 FROM imembers WHERE direct = 1
248 EXEC SQL OPEN mem_cursor;
250 EXEC SQL FETCH mem_cursor INTO :id, :type, :mid;
251 if (sqlca.sqlcode != 0) break;
254 if (l = (struct list *) hash_lookup(lists, id)) {
255 m = (struct member *) malloc(sizeof(struct member));
256 if (type[0] == 'U' &&
257 (u = (struct user *) hash_lookup(users, mid))) {
262 } else if (type[0] == 'L' &&
263 (memberlist = (struct list *) hash_lookup(lists, mid))) {
265 m->name = memberlist->name;
268 } else if (type[0] == 'S' &&
269 (s = hash_lookup(strings, mid))) {
277 EXEC SQL CLOSE mem_cursor;
280 com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
281 critical_alert("DCM", "Alias build encountered INGRES ERROR %d",
287 save_mlist(id, l, force)
289 register struct list *l;
292 register struct member *m;
295 if (l->maillist == 2 ||
296 (l->maillist == 0 && !force))
299 if (l->m && l->m->next == NULL &&
300 !strcasecmp(l->name, l->m->name)) {
307 if (l->acl_t == 'L' && (l1 = (struct list *)hash_lookup(lists, l->acl_id)))
308 save_mlist(0, l1, 1);
310 for (m = l->m; m; m = m->next) {
311 if (m->list_id && (l1 = (struct list *)hash_lookup(lists, m->list_id)))
312 save_mlist(0, l1, 1);
321 register struct list *l;
324 register struct member *m;
327 put_fill(out, l->description);
328 if (l->acl_t == 'L') {
329 if (l1 = (struct list *) hash_lookup(lists, l->acl_id))
330 fprintf(out, "owner-%s: %s\n", l->name, l1->name);
331 } else if (l->acl_t == 'U') {
332 if (u = (struct user *) hash_lookup(users, l->acl_id))
333 fprintf(out, "owner-%s: %s\n", l->name, u->login);
336 fprintf(out, "%s: ", l->name);
337 lwid = strlen(l->name) + 2;
339 for (m = l->m; m; m = m->next)
340 do_member(out, m->name);
341 if (l->m == (struct member *)NULL)
342 fprintf(out, "/dev/null");
343 fprintf(out, "\n\n");
347 /* Extract mailing lists. Make a list of all mailinglists, then
348 * process them, adding any sub-lists or acl lists to the list of lists
349 * to be processed. If further sublists are encountered, repeat...
355 fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
356 hash_step(lists, save_mlist, 0);
360 /* print out strings separated by commas, doing line breaks as appropriate */
371 if (!bol && awid + wwid + 2 > AL_MAX_WID) {
372 fprintf(out, ",\n\tcontinuation-%d\ncontinuation-%d: ", cont, cont);
374 awid = lwid = 17 + wwid;
386 if (lwid + wwid + 2 > ML_WID) {
387 fprintf(out, ",\n\t%s", s);
388 awid += lwid + wwid + 2;
393 fprintf(out, ", %s", s);
398 register struct user *u;
402 fprintf(out, "%s: %s\n", u->login, u->pobox);
406 /* Do user poboxes. Just step through the users table, and print any
407 * we extracted earlier.
413 fprintf(out, "\n%s\n# User Poboxes\n%s\n", divide, divide);
415 hash_step(users, do_pobox, out);
419 put_fill(aliases, string)
421 register char *string;
427 if (*string == 0) return;
428 fputs("# ", aliases);
432 while (*string && *string == ' ') string++;
433 c = (char *)index(string, ' ');
435 wwid = strlen(string);
441 if ((lwid + wwid) > ML_WID) {
442 fputs("\n# ", aliases);
444 fputs(string, aliases);
446 fputs(string, aliases);
449 if (c == (char *)0) break;
450 /* add a space after the word */
451 (void) fputc(' ', aliases);
455 /* add another if after a period */
457 (void) fputc(' ', aliases);
462 (void) fputc('\n', aliases);