]> andersk Git - moira.git/blob - gen/mailhub.qc
Initial revision
[moira.git] / gen / mailhub.qc
1 /* $Header$
2  *
3  * This generates the /usr/lib/aliases file for the mailhub, and an additional
4  * information file for helper programs that send back error messages.
5  *
6  *  (c) Copyright 1988 by the Massachusetts Institute of Technology.
7  *  For copying and distribution information, please see the file
8  *  <mit-copyright.h>.
9  */
10
11 #include <mit-copyright.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <sms.h>
16 #include <sms_app.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/time.h>
20
21 extern int errno;
22 char *whoami = "aliases.gen";
23 char *ingres_date_and_time();
24 char *divide = "################################################################\n";
25
26
27 main(argc, argv)
28 int argc;
29 char **argv;
30 {
31     long tm = time(NULL);
32     FILE *out= stdout;
33     char filename[64], *targetfile;
34     struct stat sb;
35 ##  int flag;
36 ##  char *filetime;
37     int ingerr();
38
39     IIseterr(ingerr);
40 ##  ingres sms
41 ##  set lockmode session where level = table
42
43     if (argc == 2) {
44         if (stat(argv[1], &sb) == 0) {
45             filetime = ingres_date_and_time(sb.st_mtime);
46 ##          retrieve (flag = int4(interval("min",tblstats.modtime - filetime)))
47 ##              where tblstats.table = "users"
48             if (flag < 0) {
49                 fprintf(stderr, "File %s does not need to be rebuilt.\n",
50                         argv[1]);
51                 exit(SMS_NO_CHANGE);
52             }
53         }
54         targetfile = argv[1];
55         sprintf(filename, "%s~", targetfile);
56         if ((out = fopen(filename, "w")) == NULL) {
57             fprintf(stderr, "unable to open %s for output\n", filename);
58             exit(SMS_OCONFIG);
59         }
60     } else if (argc != 1) {
61         fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
62         exit(SMS_ARGS);
63     }
64
65     fprintf(out, "%s\n# Aliases File Extract of %s", divide, ctime(&tm));
66     fprintf(out, "# This file is automatically generated, do not edit it directly.\n%s\n\n", divide);
67
68 ##  begin transaction
69     get_info();
70 ##  end transaction
71 ##  exit
72
73     fprintf(stderr, "Sorting Info\n");
74     sort_info();
75
76     fprintf(stderr, "Dumping information\n");
77     do_people(out);
78
79     fprintf(out, "\n%s\n# End of aliases file\n", divide);
80
81     if (fclose(out)) {
82         perror("close failed");
83         exit(SMS_CCONFIG);
84     }
85
86     if (argc == 2)
87       fix_file(targetfile);
88     exit(SMS_SUCCESS);
89 }
90
91
92 /*
93  * ingerr: (supposedly) called when Ingres indicates an error.
94  * I have not yet been able to get this to work to intercept a
95  * database open error.
96  */
97 #define INGRES_DEADLOCK 4700
98
99 static int ingerr(num)
100     int *num;
101 {
102     char buf[256];
103     int ingres_errno;
104
105     switch (*num) {
106     case INGRES_DEADLOCK:
107         ingres_errno = SMS_DEADLOCK;
108         break;
109     default:
110         ingres_errno = SMS_INGRES_ERR;
111     }
112     com_err(whoami, SMS_INGRES_ERR, " code %d\n", *num);
113     critical_alert("DCM", "Alias build encountered INGRES ERROR %d", *num);
114     exit(ingres_errno);
115 }
116
117 struct hash *users, *machines, *strings, *names;
118 struct user {
119     char *login;
120     unsigned short status;
121     char *first;
122     char *last;
123     char mi;
124     char *fullname;
125     char *addr;
126     char *pobox;
127     int id;
128 };
129 #define MAXIDS 10
130 struct names {
131     char *name;
132     struct names *next;
133     int ids[MAXIDS];
134     short count;
135 };
136
137
138 get_info()
139 ##{
140 ##  int id, pid, bid, stat, cnt;
141 ##  char name[129], type[9], fname[17], mname[17], lname[17], year[9];
142 ##  char dept[13], oaddr[17], ophone[13], buf[257], haddr[17], hphone[13];
143     char *s, *depttmp, *savedat(), *office_addr, *office_phone;
144     register struct user *u;
145
146     /* get locks */
147 ##  retrieve (buf = users.modtime) where users.users_id = 0
148
149     cnt = 0;
150     machines = create_hash(1000);
151 ##  retrieve (id = machine.mach_id, name = machine.#name) {
152       if (s = index(name, '.'))
153         *s = 0;
154       sprintf(buf, "%s.LOCAL", name);
155       hash_store(machines, id, strsave(buf));
156       cnt++;
157 ##  }
158     fprintf(stderr, "Loaded %d machines\n", cnt);
159
160     cnt = 0;
161     strings = create_hash(2000);
162 ##  retrieve (id = strings.string_id, name = strings.string) {
163         hash_store(strings, id, strsave(strtrim(name)));
164         cnt++;
165 ##  }
166     fprintf(stderr, "Loaded %d strings\n", cnt);
167
168     cnt = 0;
169     users = create_hash(15000);
170 ##  range of u is users
171 ##  retrieve (id = u.users_id, name = u.login, stat = u.status,
172 ##            fname = u.first, mname = u.middle, lname = u.last,
173 ##            year = u.mit_year, dept = u.mit_dept,
174 ##            oaddr = u.office_addr, ophone = u.office_phone,
175 ##            haddr = u.home_addr, hphone = u.home_phone,
176 ##            type = u.potype, pid = u.pop_id, bid = u.box_id) {
177         u = (struct user *) malloc(sizeof(struct user));
178         u->status = stat;
179         u->login = strsave(strtrim(name));
180         u->first = strsave(strtrim(fname));
181         u->last  = strsave(strtrim(lname));
182         if (mname[0] != ' ')
183           u->mi = mname[0];
184         else
185           u->mi = 0;
186         if (atoi(year) > 1900)
187           depttmp = "Undergraduate";
188         else
189           depttmp = strtrim(dept);
190         sprintf(buf, "%s, %s %c; ID: %s; Dept: %s %s",
191                 u->last, u->first, u->mi ? u->mi : ' ',
192                 u->login, depttmp, strtrim(year));
193         u->fullname = strsave(buf);
194
195         office_addr = strtrim(oaddr);
196         if (*office_addr == 0) {
197             office_addr = strtrim(haddr);
198         }
199         office_phone = strtrim(ophone);
200         if (*office_phone == 0) {
201             office_phone = strtrim(hphone);
202         }
203
204         if (*office_addr) {
205             sprintf(buf, "%s; %s",
206                     office_addr, office_phone);
207             u->addr = strsave(buf);
208         } else
209           u->addr = NULL;
210
211         u->id = 0;
212         u->pobox = (char *) NULL;
213         if (stat != 3) {
214             if (type[0] == 'P') {
215                 if (s = hash_lookup(machines, pid)) {
216                     sprintf(buf, "%s@%s", strtrim(name), s);
217                     u->pobox = strsave(buf);
218                 } else {
219                     fprintf(stderr,
220                             "User %s's pobox is on a missing machine!\n",
221                             u->login);
222                 }
223             } else if (type[0] ==  'S') {
224                 if ((u->pobox = hash_lookup(strings, bid)) == NULL)
225                   fprintf(stderr,
226                           "User %s's pobox string is missing!\n",
227                           u->login);
228             }
229         }
230         hash_store(users, id, u);
231         cnt++;
232 ##  }
233     fprintf(stderr, "Loaded %d users\n", cnt);
234 ##}
235
236
237 char *savedat(s)
238 register char *s;
239 {
240     char buf[256];
241     register char *ss = &buf[0];
242     char *lastchar = NULL;
243
244     while (isspace(*s))
245       s++;
246     if (*s == 0)
247       return("");
248
249     for (; *s; s++) {
250         if (isspace(*s)) {
251             *ss++ = '_';
252         } else if (islower(*s)) {
253             *ss++ = toupper(*s);
254             lastchar = ss;
255         } else {
256             *ss++ = *s;
257             lastchar = ss;
258         }
259     }
260     if (lastchar)
261       *lastchar = 0;
262     *ss = 0;
263     if ((ss = (char *) malloc(strlen(buf)+1)) == NULL) {
264         fprintf(stderr, "ran out of memory saving data\n");
265         exit(1);
266     }
267     strcpy(ss, buf);
268     return(ss);
269 }
270
271
272 void insert_names(id, u, dummy)
273 int id;
274 struct user *u;
275 int dummy;
276 {
277     char buffer[256];
278
279     if (u->status != 0 && u->status != 4)
280       insert_name(u->login, id);
281     insert_name(u->last, id);
282     sprintf(buffer, "%s_%s", u->first, u->last);
283     insert_name(buffer, id);
284     if (u->mi) {
285         sprintf(buffer, "%s_%c_%s", u->first, u->mi, u->last);
286         insert_name(buffer, id);
287     }
288 }
289
290 int incount = 0;
291
292 insert_name(s, id)
293 char *s;
294 int id;
295 {
296     int code;
297     register struct names *ns;
298     register int count;
299     register struct idblock *ra;
300
301     incount++;
302     code = hashstr(s);
303     ns = (struct names *) hash_lookup(names, code);
304     if (ns == NULL) {
305         if ((ns = (struct names *) malloc(sizeof(struct names))) == NULL) {
306             fprintf(stderr, "ran out of memory inserting name (sorting)\n");
307             exit(1);
308         }
309         ns->name = strsave(s);
310         ns->count = 1;
311         ns->ids[0] = id;
312         hash_store(names, code, ns);
313         return;
314     }
315     if (strcasecmp(ns->name, s)) {
316         while (ns->next) {
317             ns = ns->next;
318             if (!strcasecmp(ns->name, s))
319               goto foundns;
320         }
321         if ((ns->next = (struct names *)malloc(sizeof(struct names))) == NULL) {
322             fprintf(stderr, "ran out of memory insterting name (sorting)\n");
323             exit(1);
324         }
325         ns = ns->next;
326         ns->name = strsave(s);
327         ns->count = 1;
328         ns->ids[0] = id;
329         hash_store(names, code, ns);
330         return;
331     }
332  foundns:
333     if (ns->count < MAXIDS - 1) {
334         ns->ids[ns->count++] = id;
335         return;
336     }
337     ns->count++;
338 }
339
340
341 int hashstr(s)
342 register char *s;
343 {
344     register int result;
345     register int c;
346
347     for (result = 0; *s; s++) {
348         if (isupper(*s))
349           c = tolower(*s);
350         else
351           c = *s;
352 /*      result = result * 31 + *s; */
353         result = (result << 5) - result + c - 'a';
354     }
355     return(result < 0 ? -result : result);
356 }
357
358
359 sort_info()
360 {
361     names = create_hash(10000);
362     hash_step(users, insert_names, NULL);
363     fprintf(stderr, "Inserted %d names\n", incount);
364 }
365
366
367 static long offset;
368 static FILE *msgs;
369
370 output_data(dummy, nms, out)
371 int dummy;
372 struct names *nms;
373 FILE *out;
374 {
375     register struct names *ns;
376     register struct user *u;
377     int i;
378
379     incount++;
380     for (ns = nms; ns; ns = ns->next) {
381         if (strlen(ns->name) < 2)
382           continue;
383         if (ns->count == 1) {
384             u = (struct user *) hash_lookup(users, ns->ids[0]);
385             if (u->pobox) {
386                 fprintf(out, "%s: %s\n", ns->name, u->pobox);
387                 continue;
388             }
389             if (u->id == 0) {
390                 u->id = offset;
391                 if (*u->addr) {
392                     fprintf(msgs, "%s\n  %s\n\001", u->fullname, u->addr);
393                     offset += strlen(u->fullname) + strlen(u->addr) + 5;
394                 } else {
395                     fprintf(msgs, "%s\n\001", u->fullname);
396                     offset += strlen(u->fullname) + 2;
397                 }
398             }
399             fprintf(out, "%s: +%d+@no_po_box\n", ns->name, u->id);
400         } else  if (ns->count < 10) {
401             fprintf(out, "%s: +%d+@ambiguous\n", ns->name, offset);
402             for (i = 0; i < ns->count; i++) {
403                 u = (struct user *) hash_lookup(users, ns->ids[i]);
404                 fprintf(msgs, "%s\n", u->fullname);
405                 offset += strlen(u->fullname) + 1;
406             }
407             fputs("\001", msgs);
408             offset++;
409         } else {
410             fprintf(out, "%s: +%d+@too_many\n", ns->name, ns->count);
411         }
412     }
413 }
414
415
416 do_people(out)
417 FILE *out;
418 {
419     incount = 0;
420     msgs = fopen("aliases.strings", "w");
421     fputs(msgs, "\001");
422     offset = 1;
423
424     hash_step(names, output_data, out);
425     fputs("\n", msgs);
426     fclose(msgs);
427     fprintf(stderr, "Output %d entries\n", incount);
428 }
This page took 0.0724 seconds and 5 git commands to generate.