X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/259dae79477f3f38ce3d14af52805c8048e5d824..67805159a972397342c342ee735c8acd640e1399:/gen/mailhub.qc diff --git a/gen/mailhub.qc b/gen/mailhub.qc index 294dfacf..070fdba3 100644 --- a/gen/mailhub.qc +++ b/gen/mailhub.qc @@ -12,8 +12,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -23,6 +23,7 @@ extern int errno; char *whoami = "mailhub.gen"; char *ingres_date_and_time(); char *perm_malloc(); +char *pstrsave(); char *divide = "##############################################################"; #define ML_WID 72 @@ -31,13 +32,14 @@ char *divide = "##############################################################"; #define FALSE 0 #define TRUE (!FALSE) +FILE *out= stdout; + main(argc, argv) int argc; char **argv; { long tm = time(NULL); - FILE *out= stdout; char filename[64], *targetfile; struct stat sb; ## int flag; @@ -56,18 +58,18 @@ char **argv; if (flag < 0) { fprintf(stderr, "File %s does not need to be rebuilt.\n", argv[1]); - exit(SMS_NO_CHANGE); + exit(MR_NO_CHANGE); } } 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); + exit(MR_OCONFIG); } } else if (argc != 1) { fprintf(stderr, "usage: %s [outfile]\n", argv[0]); - exit(SMS_ARGS); + exit(MR_ARGS); } fprintf(out, "%s\n# Aliases File Extract of %s", divide, ctime(&tm)); @@ -82,19 +84,18 @@ char **argv; sort_info(); fprintf(stderr, "Dumping information\n"); - do_lists(out); - do_people(out); + do_people(); fprintf(out, "\n%s\n# End of aliases file\n", divide); if (fclose(out)) { perror("close failed"); - exit(SMS_CCONFIG); + exit(MR_CCONFIG); } if (argc == 2) fix_file(targetfile); - exit(SMS_SUCCESS); + exit(MR_SUCCESS); } @@ -113,12 +114,12 @@ static int ingerr(num) switch (*num) { case INGRES_DEADLOCK: - ingres_errno = SMS_DEADLOCK; + ingres_errno = MR_DEADLOCK; break; default: - ingres_errno = SMS_INGRES_ERR; + ingres_errno = MR_INGRES_ERR; } - com_err(whoami, SMS_INGRES_ERR, " code %d\n", *num); + com_err(whoami, MR_INGRES_ERR, " code %d\n", *num); critical_alert("DCM", "Alias build encountered INGRES ERROR %d", *num); exit(ingres_errno); } @@ -165,29 +166,30 @@ get_info() ## retrieve (buf = list.modtime) where list.list_id = 0 cnt = 0; - machines = create_hash(1000); -## retrieve (id = machine.mach_id, name = machine.#name) { + machines = create_hash(10); +## retrieve (id = machine.mach_id, name = machine.#name) +## where machine.mach_id = users.pop_id { if (s = index(name, '.')) *s = 0; + else + strtrim(name); #ifdef ATHENA - sprintf(buf, "%s.LOCAL", name); - if (hash_store(machines, id, strsave(buf)) < 0) { -#else - if (hash_store(machines, id, strsave(name)) < 0) { + strcat(name, ".LOCAL"); #endif + if (hash_store(machines, id, pstrsave(name)) < 0) { fprintf(stderr, "Out of memory!\n"); - exit(SMS_NO_MEM); + exit(MR_NO_MEM); } cnt++; ## } fprintf(stderr, "Loaded %d machines\n", cnt); cnt = 0; - strings = create_hash(2000); + strings = create_hash(4000); ## retrieve (id = strings.string_id, name = strings.string) { - if (hash_store(strings, id, strsave(strtrim(name))) < 0) { + if (hash_store(strings, id, pstrsave(strtrim(name))) < 0) { fprintf(stderr, "Out of memory!\n"); - exit(SMS_NO_MEM); + exit(MR_NO_MEM); } cnt++; ## } @@ -201,24 +203,24 @@ get_info() ## type = u.potype, pid = u.pop_id, bid = u.box_id) ## where u.status != 3 { u = (struct user *) perm_malloc(sizeof(struct user)); - u->login = strsave(strtrim(name)); - u->first = strsave(strtrim(fname)); - u->last = strsave(strtrim(lname)); + u->login = pstrsave(strtrim(name)); + u->first = pstrsave(strtrim(fname)); + u->last = pstrsave(strtrim(lname)); if (mname[0] != ' ') u->mi = mname[0]; else u->mi = 0; if (type[0] == 'P' && (s = hash_lookup(machines, pid))) { - sprintf(buf, "%s@%s", strtrim(name), s); - u->pobox = strsave(buf); + sprintf(buf, "%s@%s", u->login, s); + u->pobox = pstrsave(buf); } else if (type[0] == 'S') { u->pobox = hash_lookup(strings, bid); } else u->pobox = (char *) NULL; if (hash_store(users, id, u) < 0) { fprintf(stderr, "Out of memory!\n"); - exit(SMS_NO_MEM); + exit(MR_NO_MEM); } cnt++; ## } @@ -231,14 +233,14 @@ get_info() ## type = l.acl_type, acl = l.acl_id) ## where l.active != 0 { l = (struct list *) perm_malloc(sizeof(struct list)); - l->name = strsave(strtrim(name)); + l->name = pstrsave(strtrim(name)); l->maillist = maillistp; l->acl_t = type[0]; l->acl_id = acl; l->m = (struct member *) NULL; if (hash_store(lists, id, l) < 0) { fprintf(stderr, "Out of memory!\n"); - exit(SMS_NO_MEM); + exit(MR_NO_MEM); } cnt++; ## } @@ -284,8 +286,7 @@ int force; register struct member *m; register struct list *l1; - if (l->maillist == 2 || - l->maillist == 3 || + if (l->maillist > 1 || (l->maillist == 0 && !force)) return; @@ -295,7 +296,8 @@ int force; return; } l->maillist = 2; - insert_name(l->name, -id, TRUE, FALSE); + insert_name(l->name, -1, TRUE, FALSE); + output_mlist(id, l); if (l->acl_t == 'L' && (l1 = (struct list *)hash_lookup(lists, l->acl_id))) save_mlist(0, l1, TRUE); @@ -353,17 +355,18 @@ int copy; if (ns == NULL) { if ((ns = (struct names *) perm_malloc(sizeof(struct names))) == NULL) { fprintf(stderr, "ran out of memory inserting name (sorting)\n"); - exit(SMS_NO_MEM); + exit(MR_NO_MEM); } if (copy) - ns->name = strsave(s); + ns->name = pstrsave(s); else ns->name = s; ns->keep = nodups; ns->id = id; + ns->next = NULL; if (hash_store(names, code, ns) < 0) { fprintf(stderr, "Out of memory!\n"); - exit(SMS_NO_MEM); + exit(MR_NO_MEM); } return; } @@ -376,20 +379,24 @@ int copy; if ((ns->next = (struct names *) perm_malloc(sizeof(struct names))) == NULL) { fprintf(stderr, "ran out of memory insterting name (sorting)\n"); - exit(SMS_NO_MEM); + exit(MR_NO_MEM); } ns = ns->next; if (copy) - ns->name = strsave(s); + ns->name = pstrsave(s); else ns->name = s; ns->keep = nodups; ns->id = id; + ns->next = NULL; return; } foundns: - if (nodups || ns->keep) - return; + if (nodups || ns->keep) { + if (nodups && ns->keep) + fprintf(stderr, "duplicated named: %s\n", s); + return; + } ns->id = 0; } @@ -444,7 +451,10 @@ sort_info() { names = create_hash(20001); hash_step(users, insert_login, NULL); + incount = 0; + fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide); hash_step(lists, save_mlist, FALSE); + fprintf(stderr, "Output %d lists\n", incount); hash_step(users, insert_names, NULL); fprintf(stderr, "Inserted %d names\n", incount); } @@ -480,23 +490,23 @@ FILE *out; int lwid, bol, awid; -output_mlist(id, l, out) +output_mlist(id, l) int id; register struct list *l; -FILE *out; { struct list *l1; register struct member *m; register struct user *u; - if (l->maillist != 2) - return; if (l->acl_t == 'L' && (l1 = (struct list *) hash_lookup(lists, l->acl_id))) fprintf(out, "owner-%s: %s\n%s: ", l->name, l1->name, l->name); else if (l->acl_t == 'U' && (u = (struct user *) hash_lookup(users, l->acl_id))) fprintf(out, "owner-%s: %s\n%s: ", l->name, u->login, l->name); + else + fprintf(out, "%s: ", l->name); + lwid = strlen(l->name) + 2; bol = 1; @@ -547,17 +557,7 @@ register char *s; } -do_lists(out) -FILE *out; -{ - incount = 0; - fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide); - hash_step(lists, output_mlist, out); - fprintf(stderr, "Output %d lists\n", incount); -} - -do_people(out) -FILE *out; +do_people() { incount = 0; fprintf(out, "\n%s\n# People\n%s\n", divide, divide); @@ -586,3 +586,180 @@ unsigned size; return(ret); } + +/* + * Make a (permenant) copy of a string. + */ +char * +pstrsave(s) + char *s; +{ + register int len; + register char *p; + /* Kludge for sloppy string semantics */ + if (!s) { + printf("NULL != \"\" !!!!\r\n"); + p = perm_malloc(1); + *p = '\0'; + return p; + } + len = strlen(s) + 1; + p = perm_malloc((u_int)len); + if (p) bcopy(s, p, len); + return p; +} + +#define hash_func(h, key) (key >= 0 ? (key % h->size) : (-key % h->size)) + +/* Create a hash table. The size is just a hint, not a maximum. */ + +struct hash *create_hash(size) +int size; +{ + struct hash *h; + + h = (struct hash *) perm_malloc(sizeof(struct hash)); + if (h == (struct hash *) NULL) + return((struct hash *) NULL); + h->size = size; + h->data = (struct bucket **) perm_malloc(size * sizeof(char *)); + if (h->data == (struct bucket **) NULL) { + free(h); + return((struct hash *) NULL); + } + bzero(h->data, size * sizeof(char *)); + return(h); +} + +/* Lookup an object in the hash table. Returns the value associated with + * the key, or NULL (thus NULL is not a very good value to store...) + */ + +char *hash_lookup(h, key) +struct hash *h; +register int key; +{ + register struct bucket *b; + + b = h->data[hash_func(h, key)]; + while (b && b->key != key) + b = b->next; + if (b && b->key == key) + return(b->data); + else + return(NULL); +} + + +/* Update an existing object in the hash table. Returns 1 if the object + * existed, or 0 if not. + */ + +int hash_update(h, key, value) +struct hash *h; +register int key; +char *value; +{ + register struct bucket *b; + + b = h->data[hash_func(h, key)]; + while (b && b->key != key) + b = b->next; + if (b && b->key == key) { + b->data = value; + return(1); + } else + return(0); +} + + +/* Store an item in the hash table. Returns 0 if the key was not previously + * there, 1 if it was, or -1 if we ran out of memory. + */ + +int hash_store(h, key, value) +struct hash *h; +register int key; +char *value; +{ + register struct bucket *b, **p; + + p = &(h->data[hash_func(h, key)]); + if (*p == NULL) { + b = *p = (struct bucket *) perm_malloc(sizeof(struct bucket)); + if (b == (struct bucket *) NULL) + return(-1); + b->next = NULL; + b->key = key; + b->data = value; + return(0); + } + + for (b = *p; b && b->key != key; b = *p) + p = (struct bucket **) *p; + if (b && b->key == key) { + b->data = value; + return(1); + } + b = *p = (struct bucket *) perm_malloc(sizeof(struct bucket)); + if (b == (struct bucket *) NULL) + return(-1); + b->next = NULL; + b->key = key; + b->data = value; + return(0); +} + + +/* Search through the hash table for a given value. For each piece of + * data with that value, call the callback proc with the corresponding key. + */ + +hash_search(h, value, callback) +struct hash *h; +register char *value; +void (*callback)(); +{ + register struct bucket *b, **p; + + for (p = &(h->data[h->size - 1]); p >= h->data; p--) { + for (b = *p; b; b = b->next) { + if (b->data == value) + (*callback)(b->key); + } + } +} + + +/* Step through the hash table, calling the callback proc with each key. + */ + +hash_step(h, callback, hint) +struct hash *h; +void (*callback)(); +char *hint; +{ + register struct bucket *b, **p; + + for (p = &(h->data[h->size - 1]); p >= h->data; p--) { + for (b = *p; b; b = b->next) { + (*callback)(b->key, b->data, hint); + } + } +} + + +/* Deallocate all of the memory associated with a table */ + +hash_destroy(h) +struct hash *h; +{ + register struct bucket *b, **p, *b1; + + for (p = &(h->data[h->size - 1]); p >= h->data; p--) { + for (b = *p; b; b = b1) { + b1 = b->next; + free(b); + } + } +}