* user pobox entries
* maillist expansions
* sublists of maillists
- * mail alias entries
+ *
+ * (c) Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
*/
+#include <mit-copyright.h>
#include <stdio.h>
+#include <string.h>
#include <sms.h>
#include <sms_app.h>
#include <sys/types.h>
char *divide = "########################################################################";
extern int errno;
+char *whoami = "aliases.gen";
char *ingres_date_and_time();
{
long tm = time(NULL);
FILE *out= stdout;
+ char filename[64], *targetfile;
struct stat sb;
-## int error, flag1, flag2, flag3;
+## int flag1, flag2, flag3;
## char *filetime;
+ int ingerr();
+ IIseterr(ingerr);
## ingres sms
if (argc == 2) {
if (flag1 < 0 && flag2 < 0 && flag3 < 0) {
fprintf(stderr, "File %s does not need to be rebuilt.\n",
argv[1]);
- exit(0);
+ exit(SMS_NO_CHANGE);
}
}
- if ((out = fopen(argv[1], "w")) == NULL) {
- fprintf(stderr, "unable to open %s for output\n", argv[1]);
- exit(errno);
+ targetfile = argv[1];
+ sprintf(filename, "%s~", targetfile);
+ if ((out = fopen(filename, "w")) == NULL) {
+ fprintf(stderr, "unable to open %s for output\n", filename);
+ exit(SMS_OCONFIG);
}
} else if (argc != 1) {
fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
- exit(-1);
+ exit(SMS_ARGS);
}
-## set lockmode session where readlock = nolock
-
-
fprintf(out, "%s\n# Aliases File Extract of %s", divide, ctime(&tm));
fprintf(out, "# This file is automatically generated, do not edit it directly.\n%s\n\n", divide);
+## begin transaction
+ get_info();
+## end transaction
+## exit
+
+ fprintf(stderr, "Dumping information\n");
do_mlists(out);
do_poboxes(out);
- do_aliases(out);
fprintf(out, "\n%s\n# End of aliases file\n%s\n", divide, divide);
-## inquire_equel(error = "errorno")
- if (error) {
- fprintf(out, "Ingres error %d\n", error);
- exit(error);
- }
-
-## exit
if (fclose(out)) {
perror("close failed");
- exit(errno);
+ exit(SMS_CCONFIG);
}
- exit(0);
+
+ if (argc == 2)
+ fix_file(targetfile);
+ exit(SMS_SUCCESS);
}
-/* Extract mailing lists. First dump all real mailing lists. While doing
- * this, make a list of all mailing list IDs and all sub-list IDs. Next,
- * as long as there are sub-lists that aren't mailing lists, extract them
- * and add them to the list of mailing lists. If further sublists are
- * encountered, repeat...
+/*
+ * ingerr: (supposedly) called when Ingres indicates an error.
+ * I have not yet been able to get this to work to intercept a
+ * database open error.
*/
+#define INGRES_DEADLOCK 4700
-int lwid, bol;
+static int ingerr(num)
+ int *num;
+{
+ char buf[256];
+ int ingres_errno;
+
+ switch (*num) {
+ case INGRES_DEADLOCK:
+ ingres_errno = SMS_DEADLOCK;
+ break;
+ default:
+ ingres_errno = SMS_INGRES_ERR;
+ }
+ com_err(whoami, SMS_INGRES_ERR, " code %d\n", *num);
+ critical_alert("DCM", "Alias build encountered INGRES ERROR %d", *num);
+ exit(ingres_errno);
+}
-do_mlists(out)
-FILE *out;
+
+struct hash *users, *machines, *strings, *lists;
+struct user {
+ char login[9];
+ char *pobox;
+};
+struct member {
+ struct member *next;
+ char *name;
+ int list_id;
+};
+struct list {
+ char name[33];
+ char maillist;
+ char acl_t;
+ char description[256];
+ int acl_id;
+ struct member *m;
+};
+
+
+get_info()
##{
-## char name[257], desc[257], own_type[9], owner_name[33];
-## int id, own_id, member_id;
- struct save_queue *sq, *sq_create();
+## int id, maillistp, acl, pid, bid, mid;
+## char name[129], type[9], buf[257];
+ char *s;
+ register struct user *u;
+ register struct list *l;
+ register struct member *m;
+ register struct list *memberlist;
+
+ fprintf(stderr, "Loading machines\n");
+ machines = create_hash(1000);
+## retrieve (id = machine.mach_id, name = machine.#name) {
+ if (s = index(name, '.'))
+ *s = 0;
+ sprintf(buf, "%s.LOCAL", name);
+ hash_store(machines, id, strsave(buf));
+## }
- sq = sq_create();
- fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
+ fprintf(stderr, "Loading strings\n");
+ strings = create_hash(2000);
+## retrieve (id = strings.string_id, name = strings.string) {
+ hash_store(strings, id, strsave(strtrim(name)));
+## }
+
+ fprintf(stderr, "Loading users\n");
+ users = create_hash(15000);
+## range of u is users
+## retrieve (id = u.users_id, name = u.login, type = u.potype,
+## pid = u.pop_id, bid = u.box_id) where u.status = 1 {
+ u = (struct user *) malloc(sizeof(struct user));
+ strcpy(u->login, strtrim(name));
+ u->pobox = (char *) NULL;
+ if (type[0] == 'P') {
+ if (s = hash_lookup(machines, pid)) {
+ sprintf(buf, "%s@%s", name, s);
+ u->pobox = strsave(buf);
+ } else {
+ fprintf(stderr, "User %s's pobox is on a missing machine!\n",
+ u->login);
+ }
+ } else if (type[0] == 'S') {
+ if ((u->pobox = hash_lookup(strings, bid)) == NULL)
+ fprintf(stderr, "User %s's pobox string is missing!\n", u->login);
+ }
+ hash_store(users, id, u);
+## }
+ fprintf(stderr, "Loading lists\n");
+ lists = create_hash(15000);
## range of l is list
-## retrieve (id = l.list_id) where l.maillist != 0 {
- sq_save_unique_data(sq, id);
+## retrieve (id = l.list_id, name = l.#name, maillistp = l.maillist,
+## buf = l.desc, type = l.acl_type, acl = l.acl_id)
+## where l.active != 0 {
+ l = (struct list *) malloc(sizeof(struct list));
+ strcpy(l->name, strtrim(name));
+ l->maillist = maillistp;
+ strcpy(l->description, strtrim(buf));
+ l->acl_t = type[0];
+ l->acl_id = acl;
+ l->m = (struct member *) NULL;
+ hash_store(lists, id, l);
## }
+
+ fprintf(stderr, "Loading members\n");
## range of m is members
-## range of u is users
-## range of s is strings
+## retrieve (id = m.list_id, type = m.member_type, mid = m.member_id) {
+ if (l = (struct list *) hash_lookup(lists, id)) {
+ m = (struct member *) malloc(sizeof(struct member));
+ m->name = (char *) NULL;
+ if (type[0] == 'U') {
+ m->list_id = 0;
+ if (u = (struct user *) hash_lookup(users, mid))
+ m->name = u->login;
+ } else if (type[0] == 'L') {
+ m->list_id = mid;
+ if (memberlist = (struct list *) hash_lookup(lists, mid))
+ m->name = memberlist->name;
+ } else if (type[0] == 'S') {
+ m->list_id = 0;
+ if (s = hash_lookup(strings, mid))
+ m->name = s;
+ }
+ if (m->name != (char *) NULL) {
+ m->next = l->m;
+ l->m = m;
+ }
+ }
+## }
+##}
+
+
+void save_mlist(id, l, sq)
+int id;
+struct list *l;
+struct save_queue *sq;
+{
+ if (l->maillist)
+ sq_save_unique_data(sq, id);
+}
+
+
+/* Extract mailing lists. Make a list of all mailinglists, then
+ * process them, adding any sub-lists or acl lists to the list of lists
+ * to be processed. If further sublists are encountered, repeat...
+ */
+
+int lwid, bol, awid;
+
+do_mlists(out)
+FILE *out;
+{
+ register struct list *l;
+ struct list *l1;
+ register struct member *m;
+ struct user *u;
+ register struct save_queue *sq;
+ struct save_queue *sq_create();
+ int id;
+
+ sq = sq_create();
+ fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
+
+ hash_step(lists, save_mlist, sq);
+
while (sq_get_data(sq, &id)) {
-## repeat retrieve (name= l.#name, desc = l.#desc,
-## own_type = l.acl_type, own_id = l.acl_id)
-## where l.list_id = @id
- trim(name);
- trim(desc);
- trim(own_type);
- put_fill(out, desc);
- if (!strcmp(own_type, "LIST")) {
-## repeat retrieve (owner_name = l.#name) where l.list_id = @own_id
- trim(owner_name);
- fprintf(out, "owner-%s: %s\n", name, owner_name);
- sq_save_unique_data(sq, own_id);
- } else if (!strcmp(own_type, "USER")) {
-## repeat retrieve (owner_name = u.#login) where u.users_id = @own_id
- trim(owner_name);
- fprintf(out, "owner-%s: %s\n", name, owner_name);
+ l = (struct list *) hash_lookup(lists, id);
+ if (l->m && /* there's at least one member */
+ l->m->next == NULL && /* there's only one member */
+ !strcmp(l->name, l->m->name)) /* the member is same as list */
+ continue;
+ put_fill(out, l->description);
+ if (l->acl_t == 'L') {
+ if (l1 = (struct list *) hash_lookup(lists, l->acl_id)) {
+ fprintf(out, "owner-%s: %s\n", l->name, l1->name);
+ sq_save_unique_data(sq, l->acl_id);
+ }
+ } else if (l->acl_t == 'U') {
+ if (u = (struct user *) hash_lookup(users, l->acl_id))
+ fprintf(out, "owner-%s: %s\n", l->name, u->login);
}
- fprintf(out, "%s: ", name);
- lwid = strlen(name) + 2;
+ fprintf(out, "%s: ", l->name);
+ lwid = strlen(l->name) + 2;
bol = 1;
-## repeat retrieve (name = u.#login) where u.users_id = m.#member_id and
-## m.list_id = @id and m.member_type = "USER" {
- do_member(out, name);
-## }
-## repeat retrieve (name = l.#name, member_id = m.#member_id)
-## where l.list_id = m.#member_id and
-## m.list_id = @id and m.member_type = "LIST" {
- do_member(out, name);
- sq_save_unique_data(sq, member_id);
-## }
-## repeat retrieve (name = s.#string) where s.string_id = m.#member_id and
-## m.list_id = @id and m.member_type = "STRING" {
- do_member(out, name);
-## }
+ for (m = l->m; m; m = m->next) {
+ if (m->list_id != 0)
+ sq_save_unique_data(sq, m->list_id);
+ do_member(out, m->name);
+ }
fprintf(out, "\n\n");
}
- sq_destroy(sq);
-##}
+/* Removed for speed, since this take 10 minutes to free, and we don't
+ * really need the memory reclaimed.
+ * sq_destroy(sq); */
+}
/* print out strings separated by commas, doing line breaks as appropriate */
register char *s;
{
register wwid;
- static int awid;
static int cont = 1;
- trim(s);
+ strtrim(s);
wwid = strlen(s);
- if (awid + wwid + 2 > AL_MAX_WID) {
+ if (!bol && awid + wwid + 2 > AL_MAX_WID) {
fprintf(out, ",\n\tcontinuation-%d\ncontinuation-%d: ", cont, cont);
cont++;
awid = lwid = bol = 17;
}
if (lwid + wwid + 2 > ML_WID) {
fprintf(out, ",\n\t%s", s);
- awid = lwid + wwid + 2;
+ awid += lwid + wwid + 2;
lwid = wwid + 8;
return;
}
fprintf(out, ", %s", s);
}
+do_pobox(id, u, out)
+int id;
+register struct user *u;
+FILE *out;
+{
+ if (u->pobox)
+ fprintf(out, "%s: %s\n", u->login, u->pobox);
+}
+
-/* Extract user poboxes. First do POP boxes, where the name matches the
- * login name and the machine name is in the pop_id. Then do SMTP boxes,
- * where the expansion is stored in the strings table. The remaining boxes
- * are of type NONE and should be skipped.
+/* Do user poboxes. Just step through the users table, and print any
+ * we extracted earlier.
*/
do_poboxes(out)
FILE *out;
-##{
-## char login[9], name[33], box[129];
+{
+ register char *p;
+ char *index();
fprintf(out, "\n%s\n# User Poboxes\n%s\n", divide, divide);
-## range of u is users
-## range of m is machine
-## retrieve (login = u.#login, name = m.#name)
-## where u.potype = "POP" and m.mach_id = u.pop_id {
- trim(login, name);
- fprintf(out, "%s: %s@%s\n", login, login, name);
-## }
-
- fprintf(out, "\n# User Forwarding\n");
-
-## range of s is strings
-## retrieve (login = u.#login, box = s.#string)
-## where u.potype = "SMTP" and u.box_id = s.string_id {
- trim(login);
- trim(box);
- fprintf(out, "%s: %s\n", login, box);
-## }
-
-##}
-
-
-do_aliases(out)
-FILE *out;
-##{
-## char name[33], trans[129];
-
- fprintf(out, "\n%s\n# Aliases\n%s\n", divide, divide);
-
-## range of a is alias
-## retrieve (name = a.#name, trans = a.#trans) where a.type = "MAIL" {
- trim(name);
- trim(trans);
- fprintf(out, "%s: %s\n", name, trans);
-## }
-##}
+ hash_step(users, do_pobox, out);
+}
put_fill(aliases, string)