]> andersk Git - moira.git/blame - gen/mailhub.pc
deal with mc in printcaps
[moira.git] / gen / mailhub.pc
CommitLineData
7ac48069 1/* $Id$
bac4ceaa 2 *
3 * This generates the /usr/lib/aliases file for the mailhub.
4 *
7ac48069 5 * (c) Copyright 1988-1998 by the Massachusetts Institute of Technology.
6 * For copying and distribution information, please see the file
7 * <mit-copyright.h>.
bac4ceaa 8 */
9
10#include <mit-copyright.h>
bac4ceaa 11#include <moira.h>
12#include <moira_site.h>
7ac48069 13
bac4ceaa 14#include <sys/stat.h>
7ac48069 15
16#include <ctype.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include "util.h"
22
bac4ceaa 23EXEC SQL INCLUDE sqlca;
24
7ac48069 25RCSID("$Header$");
26
bac4ceaa 27char *whoami = "mailhub.gen";
9c04b191 28char *db = "moira/moira";
bac4ceaa 29char *divide = "##############################################################";
30
b033c6ed 31#define MAX_LINE_WIDTH 72
32#define MAX_ALIAS_WIDTH 592
bac4ceaa 33
34#define FALSE 0
35#define TRUE (!FALSE)
36
5eaef520 37FILE *out = stdout;
bac4ceaa 38
1c9c2ec8 39struct hash *users, *machines, *strings, *lists;
7ac48069 40struct user {
41 char *login;
7ac48069 42 char *pobox;
43};
44struct member {
45 struct member *next;
46 char *name;
47 int list_id;
48};
49struct list {
50 char *name;
51 char maillist;
52 char *description;
53 char acl_t;
54 int acl_id;
55 struct member *m;
56};
7ac48069 57
58void get_info(void);
59void save_mlist(int id, void *list, void *force);
1c9c2ec8 60int check_string(char *s);
61void output_login(int dummy, void *names, void *out);
7ac48069 62void output_mlist(int id, struct list *l);
7ac48069 63void put_fill(FILE *aliases, char *string);
64void do_people(void);
65
b033c6ed 66int incount = 0;
67
5eaef520 68int main(int argc, char **argv)
bac4ceaa 69{
b033c6ed 70 time_t tm = time(NULL);
dfaf9b68 71 char filename[MAXPATHLEN], *targetfile;
5eaef520 72 struct stat sb;
b033c6ed 73 int flag1, flag2;
5eaef520 74
75 EXEC SQL CONNECT :db;
76
77 if (argc == 2)
78 {
79 if (stat(argv[1], &sb) == 0)
80 {
b033c6ed 81 if (ModDiff(&flag1, "users", sb.st_mtime) ||
82 ModDiff(&flag2, "list", sb.st_mtime))
5eaef520 83 exit(MR_DATE);
b033c6ed 84 if (flag1 < 0 && flag2 < 0)
5eaef520 85 {
86 fprintf(stderr, "File %s does not need to be rebuilt.\n",
87 argv[1]);
88 exit(MR_NO_CHANGE);
bac4ceaa 89 }
90 }
5eaef520 91 targetfile = argv[1];
92 sprintf(filename, "%s~", targetfile);
93 if (!(out = fopen(filename, "w")))
94 {
95 fprintf(stderr, "unable to open %s for output\n", filename);
96 exit(MR_OCONFIG);
bac4ceaa 97 }
5eaef520 98 }
99 else if (argc != 1)
100 {
101 fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
102 exit(MR_ARGS);
bac4ceaa 103 }
104
5eaef520 105 fprintf(out, "%s\n# Aliases File Extract of %s", divide, ctime(&tm));
106 fprintf(out, "# This file is automatically generated, "
107 "do not edit it directly.\n%s\n\n", divide);
bac4ceaa 108
5eaef520 109 get_info();
bac4ceaa 110
5eaef520 111 EXEC SQL COMMIT;
bac4ceaa 112
1c9c2ec8 113 incount = 0;
114 fprintf(out, "\n%s\n# Mailing lists\n%s\n\n", divide, divide);
115 hash_step(lists, save_mlist, FALSE);
116 fprintf(stderr, "Output %d lists\n", incount);
bac4ceaa 117
1c9c2ec8 118 incount = 0;
119 fprintf(out, "\n%s\n# People\n%s\n\n", divide, divide);
120 hash_step(users, output_login, out);
121 fprintf(stderr, "Output %d users\n", incount);
bac4ceaa 122
5eaef520 123 fprintf(out, "\n%s\n# End of aliases file\n", divide);
bac4ceaa 124
5eaef520 125 if (fclose(out))
126 {
127 perror("close failed");
128 exit(MR_CCONFIG);
bac4ceaa 129 }
130
5eaef520 131 if (argc == 2)
132 fix_file(targetfile);
133 exit(MR_SUCCESS);
bac4ceaa 134}
135
7ac48069 136void get_info(void)
bac4ceaa 137{
5eaef520 138 EXEC SQL BEGIN DECLARE SECTION;
139 int id, pid, bid, cnt, maillistp, acl, mid;
dfaf9b68 140 char mname[MACHINE_NAME_SIZE], str[STRINGS_STRING_SIZE];
141 char login[USERS_LOGIN_SIZE], potype[USERS_POTYPE_SIZE];
142 char lname[LIST_NAME_SIZE], desc[LIST_DESCRIPTION_SIZE];
143 char type[LIST_ACL_TYPE_SIZE];
5eaef520 144 EXEC SQL END DECLARE SECTION;
145 char *s;
44d12d58 146 struct user *u;
5eaef520 147 struct list *l, *memberlist;
44d12d58 148 struct member *m;
5eaef520 149
150 /* The following is declarative, not executed,
151 * and so is dependent on where it is in the file,
152 * not in the order of execution of statements.
153 */
154 EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
155
156 cnt = 0;
b033c6ed 157 machines = create_hash(100);
5eaef520 158
159 EXEC SQL DECLARE m_cursor CURSOR FOR
160 SELECT mach_id, name
161 FROM machine
162 WHERE status = 1
b033c6ed 163 AND mach_id IN ( SELECT UNIQUE pop_id FROM users )
5eaef520 164 ORDER BY mach_id;
165 EXEC SQL OPEN m_cursor;
166 while (1)
167 {
dfaf9b68 168 EXEC SQL FETCH m_cursor INTO :id, :mname;
5eaef520 169 if (sqlca.sqlcode)
170 break;
dfaf9b68 171 if ((s = strchr(mname, '.')))
5eaef520 172 *s = '\0';
173 else
dfaf9b68 174 strtrim(mname);
bac4ceaa 175#ifdef ATHENA
dfaf9b68 176 strcat(mname, ".LOCAL");
bac4ceaa 177#endif
dfaf9b68 178 if (hash_store(machines, id, strdup(mname)) < 0)
5eaef520 179 {
180 fprintf(stderr, "Out of memory!\n");
181 exit(MR_NO_MEM);
bac4ceaa 182 }
5eaef520 183 cnt++;
bac4ceaa 184 }
5eaef520 185 EXEC SQL CLOSE m_cursor;
186
187 fprintf(stderr, "Loaded %d machines\n", cnt);
188
189 cnt = 0;
190 strings = create_hash(11001);
191
192 EXEC SQL DECLARE s_cursor CURSOR FOR
193 SELECT string_id, string
194 FROM strings
195 ORDER BY string_id;
196 EXEC SQL OPEN s_cursor;
197 while (1)
198 {
dfaf9b68 199 EXEC SQL FETCH s_cursor INTO :id, :str;
5eaef520 200 if (sqlca.sqlcode)
201 break;
dfaf9b68 202 if (hash_store(strings, id, strdup(strtrim(str))) < 0)
5eaef520 203 {
204 fprintf(stderr, "Out of memory!\n");
205 exit(MR_NO_MEM);
bac4ceaa 206 }
5eaef520 207 cnt++;
bac4ceaa 208 }
5eaef520 209 EXEC SQL CLOSE s_cursor;
210
211 fprintf(stderr, "Loaded %d strings\n", cnt);
212
213 cnt = 0;
214 users = create_hash(13001);
215
216 EXEC SQL DECLARE u_cursor CURSOR FOR
dfaf9b68 217 SELECT users_id, login, potype, pop_id, box_id
5eaef520 218 FROM users
219 WHERE status != 3
220 ORDER BY users_id;
221 EXEC SQL OPEN u_cursor;
222 while (1)
223 {
dfaf9b68 224 EXEC SQL FETCH u_cursor INTO :id, :login, :potype, :pid, :bid;
5eaef520 225 if (sqlca.sqlcode)
226 break;
7ac48069 227 u = malloc(sizeof(struct user));
dfaf9b68 228 u->login = strdup(strtrim(login));
5eaef520 229
dfaf9b68 230 if (potype[0] == 'P' && (s = hash_lookup(machines, pid)))
5eaef520 231 {
dfaf9b68 232 char *buf = malloc(strlen(u->login) + strlen(s) + 2);
5eaef520 233 sprintf(buf, "%s@%s", u->login, s);
dfaf9b68 234 u->pobox = buf;
5eaef520 235 }
dfaf9b68 236 else if (potype[0] == 'S')
5eaef520 237 u->pobox = hash_lookup(strings, bid);
238 else
239 u->pobox = NULL;
1c9c2ec8 240
241 check_string(u->login);
5eaef520 242 if (hash_store(users, id, u) < 0)
243 {
244 fprintf(stderr, "Out of memory!\n");
245 exit(MR_NO_MEM);
bac4ceaa 246 }
5eaef520 247 cnt++;
bac4ceaa 248 }
5eaef520 249 EXEC SQL CLOSE u_cursor;
250 fprintf(stderr, "Loaded %d users\n", cnt);
251
252 cnt = 0;
253 lists = create_hash(15000);
254
255 EXEC SQL DECLARE l_cursor CURSOR FOR
256 SELECT list_id, name, maillist, description, acl_type, acl_id
257 FROM list
258 WHERE active != 0
259 ORDER BY list_id;
260 EXEC SQL OPEN l_cursor;
261 while (1)
262 {
dfaf9b68 263 EXEC SQL FETCH l_cursor INTO :id, :lname, :maillistp, :desc, :type, :acl;
5eaef520 264 if (sqlca.sqlcode)
265 break;
7ac48069 266 l = malloc(sizeof(struct list));
dfaf9b68 267 l->name = strdup(strtrim(lname));
5eaef520 268 l->maillist = maillistp;
dfaf9b68 269 l->description = strdup(strtrim(desc));
5eaef520 270 l->acl_t = type[0];
271 l->acl_id = acl;
272 l->m = NULL;
273 if (hash_store(lists, id, l) < 0)
274 {
275 fprintf(stderr, "Out of memory!\n");
276 exit(MR_NO_MEM);
bac4ceaa 277 }
5eaef520 278 cnt++;
bac4ceaa 279 }
5eaef520 280 EXEC SQL CLOSE l_cursor;
281 fprintf(stderr, "Loaded %d lists\n", cnt);
282
283 cnt = 0;
284
285 EXEC SQL DECLARE m_cursor2 CURSOR FOR
286 SELECT list_id, member_type, member_id
287 FROM imembers
288 WHERE direct = 1
289 ORDER BY list_id;
290 EXEC SQL OPEN m_cursor2;
291 while (1)
292 {
293 EXEC SQL FETCH m_cursor2 INTO :id, :type, :mid;
294 if (sqlca.sqlcode)
295 break;
296 cnt++;
7ac48069 297 if ((l = hash_lookup(lists, id)))
5eaef520 298 {
7ac48069 299 m = malloc(sizeof(struct member));
300 if (type[0] == 'U' && (u = hash_lookup(users, mid)))
5eaef520 301 {
302 m->list_id = 0;
303 m->name = u->login;
304 m->next = l->m;
305 l->m = m;
306 }
7ac48069 307 else if (type[0] == 'L' && (memberlist = hash_lookup(lists, mid)))
5eaef520 308 {
309 m->list_id = mid;
310 m->name = memberlist->name;
311 m->next = l->m;
312 l->m = m;
313 }
314 else if (type[0] == 'S' && (s = hash_lookup(strings, mid)))
315 {
316 m->list_id = 0;
317 m->next = l->m;
318 l->m = m;
319 m->name = s;
bac4ceaa 320 }
321 }
322 }
5eaef520 323 EXEC SQL CLOSE m_cursor2;
324 fprintf(stderr, "Loaded %d members\n", cnt);
325
326 EXEC SQL COMMIT;
327 return;
328sqlerr:
329 db_error(sqlca.sqlcode);
330 exit(MR_DBMS_ERR);
bac4ceaa 331}
332
333
7ac48069 334void save_mlist(int id, void *list, void *force)
bac4ceaa 335{
44d12d58 336 struct member *m;
7ac48069 337 struct list *l = list, *l1;
bac4ceaa 338
1c9c2ec8 339 if (l->maillist > 1 || (l->maillist == 0 && !force) ||
340 !check_string(l->name))
5eaef520 341 return;
bac4ceaa 342
1c9c2ec8 343 /* If user group appears on list, replace with user. */
5eaef520 344 if (l->m && l->m->next == NULL && !strcasecmp(l->name, l->m->name))
345 {
346 l->maillist = 3;
347 return;
bac4ceaa 348 }
5eaef520 349 l->maillist = 2;
5eaef520 350 output_mlist(id, l);
351
7ac48069 352 if (l->acl_t == 'L' && (l1 = hash_lookup(lists, l->acl_id)))
353 save_mlist(0, l1, (void *)TRUE);
5eaef520 354
355 for (m = l->m; m; m = m->next)
356 {
7ac48069 357 if (m->list_id && (l1 = hash_lookup(lists, m->list_id)))
358 save_mlist(0, l1, (void *)TRUE);
bac4ceaa 359 }
360}
361
1c9c2ec8 362void output_login(int dummy, void *user, void *out)
bac4ceaa 363{
7ac48069 364 struct user *u = user;
5eaef520 365
366 incount++;
1c9c2ec8 367 if (u->pobox && check_string(u->login) && u->login[0] != '#')
368 fprintf(out, "%s: %s\n", u->login, u->pobox);
bac4ceaa 369}
370
7ac48069 371void output_mlist(int id, struct list *l)
bac4ceaa 372{
5eaef520 373 struct list *l1;
44d12d58 374 struct member *m;
375 struct user *u;
b033c6ed 376 int line_width, alias_width, word_width, beginning;
377 static int cont = 1;
378 char str[8];
5eaef520 379
380 put_fill(out, l->description);
7ac48069 381 if (l->acl_t == 'L' && (l1 = hash_lookup(lists, l->acl_id)))
5eaef520 382 fprintf(out, "owner-%s: %s\n%s: ", l->name, l1->name, l->name);
7ac48069 383 else if (l->acl_t == 'U' && (u = hash_lookup(users, l->acl_id)))
5eaef520 384 fprintf(out, "owner-%s: %s\n%s: ", l->name, u->login, l->name);
385 else
386 fprintf(out, "%s: ", l->name);
387
b033c6ed 388 alias_width = line_width = strlen(l->name) + 2;
389 beginning = 1;
5eaef520 390 for (m = l->m; m; m = m->next)
b033c6ed 391 {
392 word_width = strlen(m->name);
393
394 if (!beginning && alias_width + word_width + 2 > MAX_ALIAS_WIDTH)
395 {
396 /* Make a continuation. */
397 sprintf(str, "%c%c%c%c%c%c", rand() % 26 + 97, rand() % 26 + 97,
398 rand() % 26 + 97, rand() % 26 + 97,
399 rand() % 26 + 97, rand() % 26 + 97);
400 fprintf(out, ",\n\tcont%d-%s\ncont%d-%s: ", cont, str, cont, str);
401 cont++;
402 alias_width = line_width = 17 + word_width;
403 fputs(m->name, out);
404 }
405 else if (beginning)
406 {
407 /* Beginning of alias, so don't wrap. */
408 line_width += word_width;
409 alias_width = line_width;
410 fputs(m->name, out);
411 beginning = 0;
412 }
413 else if (line_width + word_width + 2 > MAX_LINE_WIDTH)
414 {
415 /* Wrap. */
416 fprintf(out, ",\n\t%s", m->name);
417 alias_width += line_width + word_width + 2;
418 line_width = word_width + 8;
419 }
420 else
421 {
422 /* Continue line. */
423 line_width += word_width + 2;
424 fprintf(out, ", %s", m->name);
425 }
426 }
5eaef520 427 if (!l->m)
428 fprintf(out, "/dev/null");
429 fprintf(out, "\n\n");
430 incount++;
bac4ceaa 431}
432
b033c6ed 433/* Write a word-wrapped list description to the aliases file as a
434 * comment. */
7ac48069 435void put_fill(FILE *aliases, char *string)
492f333e 436{
44d12d58 437 char *c;
b033c6ed 438 int line_width;
439 int word_width;
492f333e 440
5eaef520 441 if (!string || !*string)
442 return;
443 fputs("# ", aliases);
b033c6ed 444 line_width = 3;
5eaef520 445
446 while (1)
447 {
448 while (*string == ' ')
449 string++;
450 c = strchr(string, ' ');
451 if (!c)
b033c6ed 452 word_width = strlen(string);
5eaef520 453 else
454 {
b033c6ed 455 word_width = c - string;
5eaef520 456 *c = '\0';
492f333e 457 }
458
b033c6ed 459 if (line_width + word_width > MAX_LINE_WIDTH)
5eaef520 460 {
461 fputs("\n# ", aliases);
b033c6ed 462 line_width = 3;
5eaef520 463 fputs(string, aliases);
464 }
465 else
466 fputs(string, aliases);
467
468 if (!c)
469 break;
470 /* add a space after the word */
471 fputc(' ', aliases);
b033c6ed 472 word_width++;
473 line_width += word_width;
474 string += word_width;
5eaef520 475 /* add another if after a period */
476 if (*--c == '.')
477 {
478 fputc(' ', aliases);
b033c6ed 479 line_width++;
492f333e 480 }
481 }
482
5eaef520 483 fputc('\n', aliases);
492f333e 484}
485
486
1c9c2ec8 487/* Illegal chars: this should correspond to the array used by
488 * setup_alis. */
489
490static int illegalchars[] = {
491 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
492 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
493 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, /* SPACE - / */
494 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
495 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
496 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
497 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
498 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
499 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
500 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
501 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
502 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
503 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
504 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
505 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
506 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
507};
508
509int check_string(char *s)
bac4ceaa 510{
1c9c2ec8 511 for (; *s; s++)
512 {
513 if (isupper(*s))
514 *s = tolower(*s);
515
516 if (illegalchars[(unsigned) *s])
517 return 0;
518 }
519 return 1;
bac4ceaa 520}
This page took 0.158294 seconds and 5 git commands to generate.