/* $Header$ * * This generates the /usr/lib/aliases file for the mailhub, and an additional * information file for helper programs that send back error messages. * * (c) Copyright 1988 by the Massachusetts Institute of Technology. * For copying and distribution information, please see the file * . */ #include #include #include #include #include #include #include #include #include extern int errno; char *whoami = "aliases.gen"; char *ingres_date_and_time(); char *divide = "################################################################\n"; main(argc, argv) int argc; char **argv; { long tm = time(NULL); FILE *out= stdout; char filename[64], *targetfile; struct stat sb; ## int flag; ## char *filetime; int ingerr(); IIseterr(ingerr); ## ingres sms ## set lockmode session where level = table if (argc == 2) { if (stat(argv[1], &sb) == 0) { filetime = ingres_date_and_time(sb.st_mtime); ## retrieve (flag = int4(interval("min",tblstats.modtime - filetime))) ## where tblstats.table = "users" if (flag < 0) { fprintf(stderr, "File %s does not need to be rebuilt.\n", argv[1]); exit(SMS_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); } } else if (argc != 1) { fprintf(stderr, "usage: %s [outfile]\n", argv[0]); exit(SMS_ARGS); } 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, "Sorting Info\n"); sort_info(); fprintf(stderr, "Dumping information\n"); do_people(out); fprintf(out, "\n%s\n# End of aliases file\n", divide); if (fclose(out)) { perror("close failed"); exit(SMS_CCONFIG); } if (argc == 2) fix_file(targetfile); exit(SMS_SUCCESS); } /* * 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 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); } struct hash *users, *machines, *strings, *names; struct user { char *login; unsigned short status; char *first; char *last; char mi; char *fullname; char *addr; char *pobox; int id; }; #define MAXIDS 10 struct names { char *name; struct names *next; int ids[MAXIDS]; short count; }; get_info() ##{ ## int id, pid, bid, stat, cnt; ## char name[129], type[9], fname[17], mname[17], lname[17], year[9]; ## char dept[13], oaddr[17], ophone[13], buf[257], haddr[17], hphone[13]; char *s, *depttmp, *savedat(), *office_addr, *office_phone; register struct user *u; /* get locks */ ## retrieve (buf = users.modtime) where users.users_id = 0 cnt = 0; 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)); cnt++; ## } fprintf(stderr, "Loaded %d machines\n", cnt); cnt = 0; strings = create_hash(2000); ## retrieve (id = strings.string_id, name = strings.string) { hash_store(strings, id, strsave(strtrim(name))); cnt++; ## } fprintf(stderr, "Loaded %d strings\n", cnt); cnt = 0; users = create_hash(15000); ## range of u is users ## retrieve (id = u.users_id, name = u.login, stat = u.status, ## fname = u.first, mname = u.middle, lname = u.last, ## year = u.mit_year, dept = u.mit_dept, ## oaddr = u.office_addr, ophone = u.office_phone, ## haddr = u.home_addr, hphone = u.home_phone, ## type = u.potype, pid = u.pop_id, bid = u.box_id) { u = (struct user *) malloc(sizeof(struct user)); u->status = stat; u->login = strsave(strtrim(name)); u->first = strsave(strtrim(fname)); u->last = strsave(strtrim(lname)); if (mname[0] != ' ') u->mi = mname[0]; else u->mi = 0; if (atoi(year) > 1900) depttmp = "Undergraduate"; else depttmp = strtrim(dept); sprintf(buf, "%s, %s %c; ID: %s; Dept: %s %s", u->last, u->first, u->mi ? u->mi : ' ', u->login, depttmp, strtrim(year)); u->fullname = strsave(buf); office_addr = strtrim(oaddr); if (*office_addr == 0) { office_addr = strtrim(haddr); } office_phone = strtrim(ophone); if (*office_phone == 0) { office_phone = strtrim(hphone); } if (*office_addr) { sprintf(buf, "%s; %s", office_addr, office_phone); u->addr = strsave(buf); } else u->addr = NULL; u->id = 0; u->pobox = (char *) NULL; if (stat != 3) { if (type[0] == 'P') { if (s = hash_lookup(machines, pid)) { sprintf(buf, "%s@%s", strtrim(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); cnt++; ## } fprintf(stderr, "Loaded %d users\n", cnt); ##} char *savedat(s) register char *s; { char buf[256]; register char *ss = &buf[0]; char *lastchar = NULL; while (isspace(*s)) s++; if (*s == 0) return(""); for (; *s; s++) { if (isspace(*s)) { *ss++ = '_'; } else if (islower(*s)) { *ss++ = toupper(*s); lastchar = ss; } else { *ss++ = *s; lastchar = ss; } } if (lastchar) *lastchar = 0; *ss = 0; if ((ss = (char *) malloc(strlen(buf)+1)) == NULL) { fprintf(stderr, "ran out of memory saving data\n"); exit(1); } strcpy(ss, buf); return(ss); } void insert_names(id, u, dummy) int id; struct user *u; int dummy; { char buffer[256]; if (u->status != 0 && u->status != 4) insert_name(u->login, id); insert_name(u->last, id); sprintf(buffer, "%s_%s", u->first, u->last); insert_name(buffer, id); if (u->mi) { sprintf(buffer, "%s_%c_%s", u->first, u->mi, u->last); insert_name(buffer, id); } } int incount = 0; insert_name(s, id) char *s; int id; { int code; register struct names *ns; register int count; register struct idblock *ra; incount++; code = hashstr(s); ns = (struct names *) hash_lookup(names, code); if (ns == NULL) { if ((ns = (struct names *) malloc(sizeof(struct names))) == NULL) { fprintf(stderr, "ran out of memory inserting name (sorting)\n"); exit(1); } ns->name = strsave(s); ns->count = 1; ns->ids[0] = id; hash_store(names, code, ns); return; } if (strcasecmp(ns->name, s)) { while (ns->next) { ns = ns->next; if (!strcasecmp(ns->name, s)) goto foundns; } if ((ns->next = (struct names *)malloc(sizeof(struct names))) == NULL) { fprintf(stderr, "ran out of memory insterting name (sorting)\n"); exit(1); } ns = ns->next; ns->name = strsave(s); ns->count = 1; ns->ids[0] = id; hash_store(names, code, ns); return; } foundns: if (ns->count < MAXIDS - 1) { ns->ids[ns->count++] = id; return; } ns->count++; } int hashstr(s) register char *s; { register int result; register int c; for (result = 0; *s; s++) { if (isupper(*s)) c = tolower(*s); else c = *s; /* result = result * 31 + *s; */ result = (result << 5) - result + c - 'a'; } return(result < 0 ? -result : result); } sort_info() { names = create_hash(10000); hash_step(users, insert_names, NULL); fprintf(stderr, "Inserted %d names\n", incount); } static long offset; static FILE *msgs; output_data(dummy, nms, out) int dummy; struct names *nms; FILE *out; { register struct names *ns; register struct user *u; int i; incount++; for (ns = nms; ns; ns = ns->next) { if (strlen(ns->name) < 2) continue; if (ns->count == 1) { u = (struct user *) hash_lookup(users, ns->ids[0]); if (u->pobox) { fprintf(out, "%s: %s\n", ns->name, u->pobox); continue; } if (u->id == 0) { u->id = offset; if (*u->addr) { fprintf(msgs, "%s\n %s\n\001", u->fullname, u->addr); offset += strlen(u->fullname) + strlen(u->addr) + 5; } else { fprintf(msgs, "%s\n\001", u->fullname); offset += strlen(u->fullname) + 2; } } fprintf(out, "%s: +%d+@no_po_box\n", ns->name, u->id); } else if (ns->count < 10) { fprintf(out, "%s: +%d+@ambiguous\n", ns->name, offset); for (i = 0; i < ns->count; i++) { u = (struct user *) hash_lookup(users, ns->ids[i]); fprintf(msgs, "%s\n", u->fullname); offset += strlen(u->fullname) + 1; } fputs("\001", msgs); offset++; } else { fprintf(out, "%s: +%d+@too_many\n", ns->name, ns->count); } } } do_people(out) FILE *out; { incount = 0; msgs = fopen("aliases.strings", "w"); fputs(msgs, "\001"); offset = 1; hash_step(names, output_data, out); fputs("\n", msgs); fclose(msgs); fprintf(stderr, "Output %d entries\n", incount); }