--- /dev/null
+/* $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
+ * <mit-copyright.h>.
+ */
+
+#include <mit-copyright.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <sms.h>
+#include <sms_app.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+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);
+}