]>
Commit | Line | Data |
---|---|---|
63812b62 | 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 | } |