X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/5eaef52092da48d922a6b37cf48bb7c5104d0841..e35622fc2ccc96373a383fe1550e1e5b17202d28:/gen/mailhub.pc diff --git a/gen/mailhub.pc b/gen/mailhub.pc index ff9aa63e..6e531aa5 100644 --- a/gen/mailhub.pc +++ b/gen/mailhub.pc @@ -1,64 +1,81 @@ - -/* $Header$ +/* $Id$ * * This generates the /usr/lib/aliases file for the mailhub. * - * (c) Copyright 1988, 1990 by the Massachusetts Institute of Technology. - * For copying and distribution information, please see the file - * . + * (c) Copyright 1988-1998 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * . */ #include -#include -#include -#include -#include -#include #include #include -#include + #include -#include + +#include +#include +#include +#include + +#include "util.h" + EXEC SQL INCLUDE sqlca; +RCSID("$Header$"); + char *whoami = "mailhub.gen"; char *db = "moira/moira"; -char *perm_malloc(); -char *pstrsave(); char *divide = "##############################################################"; -#define ML_WID 72 -#define AL_MAX_WID 592 +#define MAX_LINE_WIDTH 72 +#define MAX_ALIAS_WIDTH 592 #define FALSE 0 #define TRUE (!FALSE) -FILE *out = stdout; +struct hash *users, *machines, *strings, *lists; +struct user { + char *login; + char *pobox; +}; +struct member { + struct member *next; + char *name; + int list_id; +}; +struct list { + char *name; + char maillist; + char *description; + char acl_t; + int acl_id; + char mailman; + char *mailman_server; + struct member *m; +}; + +void get_info(void); +int check_string(char *s); +void output_login(int dummy, void *names, void *out); +void output_mlist(int id, void *list, void *out); +void output_membership(struct list *l, FILE *out); +void put_fill(FILE *aliases, char *string); +void do_people(void); + +int incount = 0; int main(int argc, char **argv) { - long tm = time(NULL); - char filename[64], *targetfile; - struct stat sb; - EXEC SQL BEGIN DECLARE SECTION; - int flag; - EXEC SQL END DECLARE SECTION; + time_t tm = time(NULL); + char filename[MAXPATHLEN], *targetfile; + FILE *out = stdout; + srand(tm); EXEC SQL CONNECT :db; if (argc == 2) { - if (stat(argv[1], &sb) == 0) - { - if (ModDiff (&flag, "users", sb.st_mtime)) - exit(MR_DATE); - if (flag < 0) - { - fprintf(stderr, "File %s does not need to be rebuilt.\n", - argv[1]); - exit(MR_NO_CHANGE); - } - } targetfile = argv[1]; sprintf(filename, "%s~", targetfile); if (!(out = fopen(filename, "w"))) @@ -81,11 +98,15 @@ int main(int argc, char **argv) EXEC SQL COMMIT; - fprintf(stderr, "Sorting Info\n"); - sort_info(); + incount = 0; + fprintf(out, "\n%s\n# Mailing lists\n%s\n\n", divide, divide); + hash_step(lists, output_mlist, out); + fprintf(stderr, "Output %d lists\n", incount); - fprintf(stderr, "Dumping information\n"); - do_people(); + incount = 0; + fprintf(out, "\n%s\n# People\n%s\n\n", divide, divide); + hash_step(users, output_login, out); + fprintf(stderr, "Output %d users\n", incount); fprintf(out, "\n%s\n# End of aliases file\n", divide); @@ -100,47 +121,19 @@ int main(int argc, char **argv) exit(MR_SUCCESS); } - - -struct hash *users, *machines, *strings, *lists, *names; -struct user { - char *login; - char *first; - char *last; - char mi; - char *pobox; -}; -struct member { - struct member *next; - char *name; - int list_id; -}; -struct list { - char *name; - char maillist; - char *description; - char acl_t; - int acl_id; - struct member *m; -}; -struct names { - char *name; - struct names *next; - int keep; - int id; -}; - - -get_info(void) +void get_info(void) { EXEC SQL BEGIN DECLARE SECTION; - int id, pid, bid, cnt, maillistp, acl, mid; - char name[129], type[9], fname[17], mname[17], lname[17], buf[257]; + int id, pid, iid, bid, cnt, maillistp, acl, mid, mailman; + char mname[MACHINE_NAME_SIZE], str[STRINGS_STRING_SIZE]; + char login[USERS_LOGIN_SIZE], potype[USERS_POTYPE_SIZE]; + char lname[LIST_NAME_SIZE], desc[LIST_DESCRIPTION_SIZE]; + char type[LIST_ACL_TYPE_SIZE], mailman_server[MACHINE_NAME_SIZE]; EXEC SQL END DECLARE SECTION; char *s; - register struct user *u; + struct user *u; struct list *l, *memberlist; - register struct member *m; + struct member *m; /* The following is declarative, not executed, * and so is dependent on where it is in the file, @@ -149,27 +142,30 @@ get_info(void) EXEC SQL WHENEVER SQLERROR GOTO sqlerr; cnt = 0; - machines = create_hash(1000); + machines = create_hash(100); EXEC SQL DECLARE m_cursor CURSOR FOR SELECT mach_id, name FROM machine WHERE status = 1 + AND ( mach_id IN ( SELECT UNIQUE pop_id FROM users ) OR + mach_id IN ( SELECT UNIQUE mach_id FROM filesys + WHERE type = 'IMAP' ) ) ORDER BY mach_id; EXEC SQL OPEN m_cursor; while (1) { - EXEC SQL FETCH m_cursor INTO :id, :name; + EXEC SQL FETCH m_cursor INTO :id, :mname; if (sqlca.sqlcode) break; - if (s = strchr(name, '.')) + if ((s = strchr(mname, '.'))) *s = '\0'; else - strtrim(name); + strtrim(mname); #ifdef ATHENA - strcat(name, ".LOCAL"); + strcat(mname, ".LOCAL"); #endif - if (hash_store(machines, id, pstrsave(name)) < 0) + if (hash_store(machines, id, strdup(mname)) < 0) { fprintf(stderr, "Out of memory!\n"); exit(MR_NO_MEM); @@ -190,10 +186,10 @@ get_info(void) EXEC SQL OPEN s_cursor; while (1) { - EXEC SQL FETCH s_cursor INTO :id, :name; + EXEC SQL FETCH s_cursor INTO :id, :str; if (sqlca.sqlcode) break; - if (hash_store(strings, id, pstrsave(strtrim(name))) < 0) + if (hash_store(strings, id, strdup(strtrim(str))) < 0) { fprintf(stderr, "Out of memory!\n"); exit(MR_NO_MEM); @@ -208,35 +204,61 @@ get_info(void) users = create_hash(13001); EXEC SQL DECLARE u_cursor CURSOR FOR - SELECT users_id, login, first, middle, last, potype, pop_id, box_id + SELECT users_id, login, potype, pop_id, imap_id, box_id FROM users WHERE status != 3 ORDER BY users_id; EXEC SQL OPEN u_cursor; while (1) { - EXEC SQL FETCH u_cursor INTO :id, :name, :fname, :mname, :lname, - :type, :pid, :bid; + char *saddr = NULL, *paddr = NULL; + + EXEC SQL FETCH u_cursor INTO :id, :login, :potype, :pid, :iid, :bid; if (sqlca.sqlcode) break; - u = (struct user *) perm_malloc(sizeof(struct user)); - 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; + u = malloc(sizeof(struct user)); + u->login = strdup(strtrim(login)); - if (type[0] == 'P' && (s = hash_lookup(machines, pid))) + if (!strcmp(strtrim(potype), "NONE")) + u->pobox = NULL; + else { - sprintf(buf, "%s@%s", u->login, s); - u->pobox = pstrsave(buf); + /* If SMTP or SPLIT, get SMTP address. */ + if (potype[0] == 'S') + { + saddr = hash_lookup(strings, bid); + + /* If SMTP, clear pid and iid. */ + if (potype[1] == 'M') + pid = iid = 0; + } + + /* If IMAP, or SPLIT with IMAP, set pid to mach_id. */ + if (potype[0] == 'I' || (potype[0] == 'S' && iid)) + { + EXEC SQL SELECT mach_id INTO :pid FROM filesys + WHERE filsys_id = :iid; + } + + if (pid && (s = hash_lookup(machines, pid))) + { + paddr = malloc(strlen(u->login) + strlen(s) + 2); + sprintf(paddr, "%s@%s", u->login, s); + } + + if (paddr && saddr) + { + u->pobox = malloc(strlen(paddr) + strlen(saddr) + 3); + sprintf(u->pobox, "%s, %s", paddr, saddr); + free(paddr); + } + else if (paddr) + u->pobox = paddr; + else + u->pobox = saddr; } - else if (type[0] == 'S') - u->pobox = hash_lookup(strings, bid); - else - u->pobox = NULL; + + check_string(u->login); if (hash_store(users, id, u) < 0) { fprintf(stderr, "Out of memory!\n"); @@ -251,22 +273,26 @@ get_info(void) lists = create_hash(15000); EXEC SQL DECLARE l_cursor CURSOR FOR - SELECT list_id, name, maillist, description, acl_type, acl_id - FROM list - WHERE active != 0 + SELECT l.list_id, l.name, l.maillist, l.description, l.acl_type, l.acl_id, + l.mailman, m.name + FROM list l, machine m + WHERE active != 0 AND l.mailman_id = m.mach_id ORDER BY list_id; EXEC SQL OPEN l_cursor; while (1) { - EXEC SQL FETCH l_cursor INTO :id, :name, :maillistp, :buf, :type, :acl; + EXEC SQL FETCH l_cursor INTO :id, :lname, :maillistp, :desc, :type, :acl, + :mailman, :mailman_server; if (sqlca.sqlcode) break; - l = (struct list *) perm_malloc(sizeof(struct list)); - l->name = pstrsave(strtrim(name)); + l = malloc(sizeof(struct list)); + l->name = strdup(strtrim(lname)); l->maillist = maillistp; - l->description = pstrsave(strtrim(buf)); + l->description = strdup(strtrim(desc)); l->acl_t = type[0]; l->acl_id = acl; + l->mailman = mailman; + l->mailman_server = strdup(strtrim(mailman_server)); l->m = NULL; if (hash_store(lists, id, l) < 0) { @@ -292,18 +318,17 @@ get_info(void) if (sqlca.sqlcode) break; cnt++; - if ((l = (struct list *) hash_lookup(lists, id))) + if ((l = hash_lookup(lists, id))) { - m = (struct member *) perm_malloc(sizeof(struct member)); - if (type[0] == 'U' && (u = (struct user *) hash_lookup(users, mid))) + m = malloc(sizeof(struct member)); + if (type[0] == 'U' && (u = hash_lookup(users, mid))) { m->list_id = 0; m->name = u->login; m->next = l->m; l->m = m; } - else if (type[0] == 'L' && - (memberlist = (struct list *) hash_lookup(lists, mid))) + else if (type[0] == 'L' && (memberlist = hash_lookup(lists, mid))) { m->list_id = mid; m->name = memberlist->name; @@ -330,290 +355,130 @@ sqlerr: } -save_mlist(int id, struct list *l, int force) +void output_login(int dummy, void *user, void *out) { - register struct member *m; - register struct list *l1; + struct user *u = user; - if (l->maillist > 1 || (l->maillist == 0 && !force)) - return; - - if (l->m && l->m->next == NULL && !strcasecmp(l->name, l->m->name)) - { - l->maillist = 3; - return; - } - l->maillist = 2; - 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); - - for (m = l->m; m; m = m->next) - { - if (m->list_id && (l1 = (struct list *)hash_lookup(lists, m->list_id))) - save_mlist(0, l1, TRUE); - } + incount++; + if (u->pobox && check_string(u->login) && u->login[0] != '#') + fprintf(out, "%s: %s\n", u->login, u->pobox); } +int line_width, alias_width; +static const char *mailman_suffixes[] = { "-admin", "-owner", "-request", + "-bounces", "-confirm", "-join", + "-leave", "-subscribe", + "-unsubscribe", NULL }; -insert_login(int id, struct user *u, int dummy) +void output_mlist(int id, void *list, void *out) { - if (u->pobox && u->login[0] != '#') - insert_name(u->login, id, TRUE, FALSE); -} + struct list *l = list, *l1; + struct user *u; + int len = strlen(l->name), i; -void insert_names(int id, struct user *u, int dummy) -{ - char buffer[256]; - - insert_name(u->last, id, FALSE, FALSE); - sprintf(buffer, "%s_%s", u->first, u->last); - insert_name(buffer, id, FALSE, TRUE); -#if 0 - sprintf(buffer, "%c_%s", u->first[0], u->last); - insert_name(buffer, id, FALSE, TRUE); -#endif - if (u->mi) - { - sprintf(buffer, "%s_%c_%s", u->first, u->mi, u->last); - insert_name(buffer, id, FALSE, TRUE); - } -} + if (!l->maillist || !check_string(l->name)) + return; -int incount = 0; + /* If standard user group appears on a list, substitute in the user. */ + if (l->m && l->m->next == NULL && !strcasecmp(l->name, l->m->name)) + return; -insert_name(char *s, int id, int nodups, int copy) -{ - int code; - register struct names *ns; + put_fill(out, l->description); - incount++; - code = hashstr(s); - ns = (struct names *) hash_lookup(names, code); - if (!ns) + if (l->mailman && strcmp(l->mailman_server, "[NONE]")) { - if (!(ns = (struct names *) perm_malloc(sizeof(struct names)))) - { - fprintf(stderr, "ran out of memory inserting name (sorting)\n"); - exit(MR_NO_MEM); - } - if (copy) - 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(MR_NO_MEM); - } - return; + for (i = 0; mailman_suffixes[i]; i++) + fprintf(out, "%s%s: %s%s@%s\n", l->name, mailman_suffixes[i], l->name, + mailman_suffixes[i], l->mailman_server); + fprintf(out, "owner-%s: %s-owner@%s\n", l->name, l->name, + l->mailman_server); } - if (strcasecmp(ns->name, s)) + else if (l->acl_t == 'L' && (l1 = hash_lookup(lists, l->acl_id))) { - while (ns->next) - { - ns = ns->next; - if (!strcasecmp(ns->name, s)) - goto foundns; - } - if (!(ns->next = (struct names *) perm_malloc(sizeof(struct names)))) - { - fprintf(stderr, "ran out of memory insterting name (sorting)\n"); - exit(MR_NO_MEM); - } - ns = ns->next; - if (copy) - ns->name = pstrsave(s); + fprintf(out, "owner-%s: ", l->name); + if ((l1->maillist) && (strcmp(l->name, l1->name))) + fprintf(out, "%s\n", l1->name); else - ns->name = s; - ns->keep = nodups; - ns->id = id; - ns->next = NULL; - return; - } -foundns: - if (nodups || ns->keep) - { - if (nodups && ns->keep) - fprintf(stderr, "duplicated name: %s\n", s); - return; - } - ns->id = 0; -} - - -/* Illegal chars: ! " % ( ) , / : ; < = > @ [ \ ] ^ { | } */ - -static int illegalchars[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */ - 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, /* SPACE - / */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, /* 0 - ? */ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* P - _ */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -}; - - -/* While hashing the string, punt any illegal characters */ - -int hashstr(register char *s) -{ - register int result; - register int c; - - for (result = 0; c = *s; s++) - { - if (illegalchars[c]) { - register char *p; - for (p = s; *p; p++) - *p = p[1]; - continue; + alias_width = line_width = len + 8; + output_membership(l1, out); + fprintf(out, "\n"); } - if (isupper(c)) - c = *s = tolower(c); - result = (result << 5) - result + c - '`'; } - return result < 0 ? -result : result; -} - + else if (l->acl_t == 'U' && (u = hash_lookup(users, l->acl_id))) + fprintf(out, "owner-%s: %s\n", l->name, u->login); -sort_info(void) -{ - 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); + fprintf(out, "%s: ", l->name); + alias_width = line_width = len + 2; + output_membership(l, out); + fprintf(out, "\n\n"); + incount++; } - -output_data(int dummy, struct names *nms, FILE *out) +void output_membership(struct list *l, FILE *out) { - register struct names *ns; - register struct user *u; + struct member *m; + struct list *l1; + int word_width, linestart = 1; + static int cont = 1; + char str[8]; - incount++; - for (ns = nms; ns; ns = ns->next) + for (m = l->m; m; m = m->next) { - if (!ns->name[0] || !ns->name[1]) + word_width = strlen(m->name); + + if (!linestart && alias_width + word_width + 2 > MAX_ALIAS_WIDTH) { - fprintf(stderr, "punting %s due to short name\n", ns->name); - continue; + /* Make a continuation. */ + sprintf(str, "%c%c%c%c%c%c", rand() % 26 + 97, rand() % 26 + 97, + rand() % 26 + 97, rand() % 26 + 97, + rand() % 26 + 97, rand() % 26 + 97); + fprintf(out, ",\n\tcont%d-%s\ncont%d-%s: ", cont, str, cont, str); + cont++; + alias_width = line_width = 17 + word_width; } - if (ns->id > 0) + else if (linestart) { - u = (struct user *) hash_lookup(users, ns->id); - if (u->pobox) - fprintf(out, "%s: %s\n", ns->name, u->pobox); - else - fprintf(out, "%s: =%s=@nobox\n", ns->name, ns->name); + /* First word on line, so we can't wrap. */ + line_width += word_width; + alias_width = line_width; + linestart = 0; + } + else if (line_width + word_width + 2 > MAX_LINE_WIDTH) + { + /* Wrap. */ + fputs(",\n\t", out); + alias_width += line_width + word_width + 2; + line_width = word_width + 8; + } + else + { + /* Continue line. */ + line_width += word_width + 2; + fputs(", ", out); } - else if (ns->id == 0) - fprintf(out, "%s: =%s=@ambig\n", ns->name, ns->name); - } -} - - -int lwid, bol, awid; - -output_mlist(int id, register struct list *l) -{ - struct list *l1; - register struct member *m; - register struct user *u; - put_fill(out, l->description); - 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; - for (m = l->m; m; m = m->next) - do_member(out, m->name); + if (m->list_id && (l1 = hash_lookup(lists, m->list_id)) && !l1->maillist) + output_membership(l1, out); + else + fputs(m->name, out); + } if (!l->m) fprintf(out, "/dev/null"); - fprintf(out, "\n\n"); - incount++; -} - - -/* print out strings separated by commas, doing line breaks as appropriate */ - -do_member(FILE *out, register char *s) -{ - register wwid; - static int cont = 1; - char str[8]; - - wwid = strlen(s); - - if (!bol && awid + wwid + 2 > AL_MAX_WID) - { - sprintf(str, "%c%c%c%c%c%c", rand() % 26 + 97, rand() % 26 + 97, - rand() % 26 + 97, rand() % 26 + 97, - rand() % 26 + 97, rand() % 26 + 97); - str[6] = '\0'; - fprintf(out, ",\n\tcont%d-%s\ncont%d-%s: ", cont, str, cont, str); - cont++; - awid = lwid = 17 + wwid; - fputs(s, out); - return; - } - - if (bol) - { - lwid += wwid; - awid = lwid; - fputs(s, out); - bol = 0; - return; - } - if (lwid + wwid + 2 > ML_WID) - { - fprintf(out, ",\n\t%s", s); - awid += lwid + wwid + 2; - lwid = wwid + 8; - return; - } - lwid += wwid + 2; - fprintf(out, ", %s", s); } - -put_fill(FILE *aliases, register char *string) +/* Write a word-wrapped list description to the aliases file as a + * comment. */ +void put_fill(FILE *aliases, char *string) { - register char *c; - register int lwid; - register int wwid; + char *c; + int line_width; + int word_width; if (!string || !*string) return; fputs("# ", aliases); - lwid = 3; + line_width = 3; while (1) { @@ -621,17 +486,17 @@ put_fill(FILE *aliases, register char *string) string++; c = strchr(string, ' '); if (!c) - wwid = strlen(string); + word_width = strlen(string); else { - wwid = c - string; + word_width = c - string; *c = '\0'; } - if ((lwid + wwid) > ML_WID) + if (line_width + word_width > MAX_LINE_WIDTH) { fputs("\n# ", aliases); - lwid = 3; + line_width = 3; fputs(string, aliases); } else @@ -641,14 +506,14 @@ put_fill(FILE *aliases, register char *string) break; /* add a space after the word */ fputc(' ', aliases); - wwid++; - lwid += wwid; - string += wwid; + word_width++; + line_width += word_width; + string += word_width; /* add another if after a period */ if (*--c == '.') { fputc(' ', aliases); - lwid++; + line_width++; } } @@ -656,182 +521,39 @@ put_fill(FILE *aliases, register char *string) } -do_people(void) -{ - incount = 0; - fprintf(out, "\n%s\n# People\n%s\n", divide, divide); - hash_step(names, output_data, out); - fprintf(stderr, "Output %d entries\n", incount); -} - - -#define chunk_size 102400 - -char *perm_malloc(unsigned size) -{ - static char *pool = NULL; - static unsigned pool_size = 0; - register char *ret; - - if (size > pool_size) - { - pool = malloc(chunk_size); - pool_size = chunk_size; - } - ret = pool; - pool += size; - pool = (char *)(((unsigned) (pool + 3)) & ~3); - pool_size -= (pool - ret); - return ret; -} - - -/* - * Make a (permenant) copy of a string. - */ -char *pstrsave(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) - memcpy(p, s, 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(int size) -{ - struct hash *h; - - h = (struct hash *) perm_malloc(sizeof(struct hash)); - if (!h) - return NULL; - h->size = size; - h->data = (struct bucket **) perm_malloc(size * sizeof(char *)); - if (!h->data) - return NULL; - memset(h->data, 0, 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...) +/* Illegal chars: this no longer corresponds to the array + * in setup_alis. '+' is a valid character in a string on + * a list, but is not a valid character in a listname. */ -char *hash_lookup(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(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(struct hash *h, register int key, char *value) -{ - register struct bucket *b, **p; - - p = &(h->data[hash_func(h, key)]); - if (!*p) - { - b = *p = (struct bucket *) perm_malloc(sizeof(struct bucket)); - if (!b) - 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) - 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. - */ +static int illegalchars[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */ + 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, /* SPACE - / */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; -hash_search(struct hash *h, register char *value, void (*callback)()) +int check_string(char *s) { - register struct bucket *b, **p; - - for (p = &(h->data[h->size - 1]); p >= h->data; p--) + for (; *s; s++) { - 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(struct hash *h, void (*callback)(), char *hint) -{ - register struct bucket *b, **p; + if (isupper(*s)) + *s = tolower(*s); - for (p = &(h->data[h->size - 1]); p >= h->data; p--) - { - for (b = *p; b; b = b->next) - (*callback)(b->key, b->data, hint); + if (illegalchars[(unsigned) *s]) + return 0; } + return 1; }