]> andersk Git - moira.git/blob - regtape/employee.pc
updates for server-side VPATH compiling
[moira.git] / regtape / employee.pc
1 /* $Id$
2  *
3  * Load data into Moira from Personnel Office data file
4  *
5  * Copyright (C) 1990-1998 by the Massachusetts Institute of Technology
6  * For copying and distribution information, please see the file
7  * <mit-copyright.h>.
8  */
9
10 #include <mit-copyright.h>
11 #include <moira.h>
12 #include <moira_site.h>
13 #include <moira_schema.h>
14
15 #include <ctype.h>
16 #include <stdio.h>
17 #include <string.h>
18
19 EXEC SQL INCLUDE sqlca;
20 extern void sqlglm(char *, unsigned int *, unsigned int *);
21
22 RCSID("$Header$");
23
24 #define WHO 11859               /* root */
25 #define PROG "emp-tape"
26
27 #define MAX_ID_VALUE    31999
28 #define MIN_ID_VALUE    101
29
30 /* File format is:
31
32 0-8     id number
33 9-38    name
34 39-62   office address
35 63-74   phone1
36 75-86   phone2
37 87-106  dept
38 107-156 title
39 157-186 username
40 187-241 host
41
42 */
43
44 #define LOC_ID 0
45 #define LOC_NAME 9
46 #define LOC_OFFICE 39
47 #define LOC_PHONE 63
48 #define LOC_PHONE2 75
49 #define LOC_DEPT 87
50 #define LOC_TITLE 107
51 #define LOC_USERNAME 157
52 #define LOC_HOST 187
53
54 #define LEN_ID 9
55 #define LEN_NAME 30
56 #define LEN_OFFICE 24
57 #define LEN_PHONE 12
58 #define LEN_PHONE2 12
59 #define LEN_DEPT 20
60 #define LEN_TITLE 50
61 #define LEN_USERNAME 30
62 #define LEN_HOST 55
63
64
65 struct entry {
66   char *name;
67   char *last;
68   char *first;
69   char *middle;
70   char *title;
71   char *class;
72   char *id;
73   char *eid;
74   char *dept;
75   char *address;
76   char *phone;
77   char *phone2;
78   int highid;
79 };
80
81 struct entry *get_next_entry(FILE *in);
82 void process_entry(struct entry *e);
83 void newuser(struct entry *e);
84 int set_next_users_id(int limit);
85 int set_next_uid(int high);
86 void sqlexit(void);
87 void dbmserr(char *where, int what);
88
89 char *whoami;
90 int newfinger = 0;
91
92 #define sqlfail() (sqlca.sqlcode && sqlca.sqlcode != 1403)
93 #define SQL_DUPLICATE -2112
94
95
96 int main(int argc, char **argv)
97 {
98   FILE *in;
99   struct entry *e;
100   int i, wait = 0;
101   char buf[80], *file = NULL;
102   EXEC SQL BEGIN DECLARE SECTION;
103   char *db = "moira";
104   EXEC SQL END DECLARE SECTION;
105
106   whoami = strrchr(argv[0], '/');
107   if (whoami)
108     whoami++;
109   else
110     whoami = argv[0];
111
112   setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
113   setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
114
115   for (i = 1; i < argc; i++)
116     {
117       if (!strcmp(argv[i], "-w"))
118         wait++;
119       else if (!strcmp(argv[i], "-n"))
120         newfinger++;
121       else if (file)
122         fprintf(stderr, "Usage: %s [-w] [-D] [-n] inputfile\n", whoami);
123       else
124         file = argv[i];
125     }
126
127   in = fopen(file, "r");
128   if (!in)
129     {
130       fprintf(stderr, "Unable to open %s for input\n", file);
131       exit(1);
132     }
133
134   initialize_sms_error_table();
135
136   EXEC SQL CONNECT :db IDENTIFIED BY :db;
137   if (sqlca.sqlcode)
138     {
139       dbmserr("opening database", sqlca.sqlcode);
140       exit(1);
141     }
142
143   while ((e = get_next_entry(in)))
144     {
145       process_entry(e);
146       EXEC SQL COMMIT WORK;
147       if (sqlca.sqlcode)
148         {
149           dbmserr("committing work", sqlca.sqlcode);
150           exit(1);
151         }
152       if (wait)
153         {
154           printf("Next");
155           fflush(stdout);
156           fgets(buf, sizeof(buf), stdin);
157         }
158     }
159
160   exit(0);
161 }
162
163 struct entry *get_next_entry(FILE *in)
164 {
165   static struct entry e;
166   static char buf[BUFSIZ], eid[16];
167   static char name[LEN_NAME + 1], sname[LEN_NAME + 1], id[LEN_ID + 1];
168   static char office[LEN_OFFICE + 1], phone[LEN_PHONE + 1];
169   static char phone2[LEN_PHONE2 + 1], dept[LEN_DEPT + 1], title[LEN_TITLE + 1];
170   static char username[LEN_USERNAME + 1], host[LEN_HOST + 1];
171   int ends_sr, ends_jr, ends_iii, ends_iv, ends_ii, ends_v;
172   char *p;
173
174   if (!fgets(buf, sizeof(buf), in))
175     return NULL;
176
177   strncpy(id, &buf[LOC_ID], LEN_ID);
178   id[LEN_ID] = '\0';
179   strncpy(name, &buf[LOC_NAME], LEN_NAME);
180   name[LEN_NAME] = '\0';
181   strncpy(office, &buf[LOC_OFFICE], LEN_OFFICE);
182   office[LEN_OFFICE] = '\0';
183   strncpy(phone, &buf[LOC_PHONE], LEN_PHONE);
184   phone[LEN_PHONE] = '\0';
185   strncpy(phone2, &buf[LOC_PHONE2], LEN_PHONE2);
186   phone2[LEN_PHONE2] = '\0';
187   strncpy(dept, &buf[LOC_DEPT], LEN_DEPT);
188   dept[LEN_DEPT] = '\0';
189   strncpy(title, &buf[LOC_TITLE], LEN_TITLE);
190   title[LEN_TITLE] = '\0';
191   strncpy(username, &buf[LOC_USERNAME], LEN_USERNAME);
192   username[LEN_USERNAME] = '\0';
193   strncpy(host, &buf[LOC_HOST], LEN_HOST);
194   host[LEN_HOST] = '\0';
195
196   strcpy(sname, name);
197   e.name = strtrim(sname);
198   p = strchr(name, ',');
199   if (p)
200     *p = '\0';
201   e.last = strtrim(name);
202   if (p)
203     {
204       p++;
205       while (isspace(*p))
206         p++;
207       e.first = p;
208       if ((p = strchr(e.first, ' ')))
209         {
210           *p = '\0';
211           e.first = strtrim(e.first);
212           e.middle = strtrim(p + 1);
213         }
214       else
215         {
216           e.first = strtrim(e.first);
217           e.middle = "";
218         }
219     }
220   else
221     {
222       e.first = "";
223       e.middle = "";
224     }
225   ends_sr = ends_jr = ends_iii = ends_iv = ends_ii = ends_v = 0;
226   LookForSt(e.last);
227   LookForO(e.last);
228   LookForJrAndIII(e.last, &ends_jr, &ends_sr, &ends_ii, &ends_iii,
229                   &ends_iv, &ends_v);
230   LookForJrAndIII(e.first, &ends_jr, &ends_sr, &ends_ii, &ends_iii,
231                   &ends_iv, &ends_v);
232   FixCase(e.last);
233   FixCase(e.first);
234   FixCase(e.middle);
235
236   e.id = id;
237   e.eid = eid;
238   EncryptID(e.eid, e.id, e.first, e.last);
239
240   e.address = strtrim(office);
241   e.phone = strtrim(phone);
242   e.phone2 = strtrim(phone2);
243   e.dept = strtrim(dept);
244   e.title = strtrim(title);
245
246   e.class = "MITS";
247   e.highid = 0;
248   if (strstr(e.title, "PROF") || strstr(e.title, "LECTURE"))
249     e.class = "FACULTY";
250   if (!strcmp(e.dept, "LINCOLN LAB"))
251     {
252       e.class = "LINCOLN";
253       e.highid = 1;
254     }
255
256   return &e;
257 }
258
259 void process_entry(struct entry *e)
260 {
261   int changed, nochange, encrypted;
262   char buf[MAX_FIELD_WIDTH], *from, *to;
263   EXEC SQL BEGIN DECLARE SECTION;
264   char *first, *last, *middle, *eid, *sid, *name, *rdept;
265   char *rtitle, *raddr, *rhphone, *rophone, *prog;
266   char class[USERS_TYPE_SIZE], oaddr[USERS_OFFICE_ADDR_SIZE];
267   char ophone[USERS_OFFICE_PHONE_SIZE], dept[USERS_DEPARTMENT_SIZE];
268   char dfirst[USERS_FIRST_SIZE], dlast[USERS_LAST_SIZE];
269   char dmiddle[USERS_MIDDLE_SIZE];
270   int id, status, who;
271   EXEC SQL END DECLARE SECTION;
272
273   who = WHO;
274   prog = PROG;
275   first = e->first;
276   if (strlen(first) > USERS_FIRST_SIZE - 1)
277     first[USERS_FIRST_SIZE - 1] = '\0';
278   last = e->last;
279   if (strlen(last) > USERS_LAST_SIZE - 1)
280     last[USERS_LAST_SIZE - 1] = '\0';
281   middle = e->middle;
282   if (strlen(middle) > USERS_MIDDLE_SIZE - 1)
283     middle[USERS_MIDDLE_SIZE - 1] = '\0';
284   eid = e->eid;
285   sid = e->id;
286   id = 0;
287   encrypted = 0;
288
289   /* Get user info */
290   EXEC SQL SELECT users_id, first, last, middle, type, office_addr,
291     office_phone, department, status
292     INTO :id, :dfirst, :dlast, :dmiddle, :class, :oaddr,
293     :ophone, :dept, :status
294     FROM users
295     WHERE clearid = :sid;
296   if (sqlfail())
297     {
298       if (sqlca.sqlcode == SQL_DUPLICATE)
299         {
300           com_err(whoami, 0, "duplicate ID number %s on user %s %s",
301                   sid, first, last);
302           return;
303         }
304       else
305         sqlexit();
306     }
307   if (id == 0)
308     {
309       EXEC SQL SELECT users_id, first, last, middle, type, office_addr,
310         office_phone, department, status
311         INTO :id, :dfirst, :dlast, :dmiddle, :class, :oaddr,
312         :ophone, :dept, :status
313         FROM users
314         WHERE last = :last and first = :first and clearid = :eid;
315       if (sqlfail() && sqlca.sqlcode != SQL_DUPLICATE)
316         sqlexit();
317       encrypted++;
318       if (id == 0)
319         {
320           newuser(e);
321           return;
322         }
323     }
324
325   /* Update class/state if necessary.  (Exclude several spacial cases.) */
326   if (strcmp(e->class, strtrim(class)) &&
327       strcmp(class, "STAFF") && strcmp(class, "SIPBMEM") &&
328       strcmp(class, "KNIGHT"))
329     {
330       com_err(whoami, 0, "updating class for %s %s from %s to %s",
331               first, last, class, e->class);
332       if (status == US_NOT_ALLOWED)
333         status = US_NO_LOGIN_YET;
334       if (status == US_ENROLL_NOT_ALLOWED)
335         status = US_ENROLLED;
336       strcpy(class, e->class);
337       EXEC SQL UPDATE users
338         SET type = NVL(:class, CHR(0)), status = :status, modtime = SYSDATE,
339         modby = :who, modwith = :prog
340         WHERE users_id = :id;
341       if (sqlca.sqlcode)
342         {
343           dbmserr("updating user", sqlca.sqlcode);
344           exit(1);
345         }
346     }
347
348   /* Update name if necessary */
349   if (strcmp(first, strtrim(dfirst)) ||
350       strcmp(last, strtrim(dlast)) ||
351       strcmp(middle, strtrim(dmiddle)))
352     {
353       com_err(whoami, 0, "updating real name for %s %s", first, last);
354       EXEC SQL UPDATE users
355         SET first = NVL(:first, CHR(0)), last = NVL(:last, CHR(0)),
356         middle = NVL(:middle, CHR(0)), modby = :who, modwith = :prog,
357         modtime = SYSDATE
358         WHERE users_id = :id;
359       if (sqlca.sqlcode)
360         {
361           dbmserr("updating name", sqlca.sqlcode);
362           exit(1);
363         }
364     }
365
366   changed = nochange = 0;
367   if (encrypted)
368     changed++;
369   strcpy(buf, e->address);
370   while ((to = strchr(buf, ',')))
371     *to = ';';
372   while ((to = strchr(buf, ':')))
373     *to = ';';
374   if (newfinger)
375     {
376       if (oaddr[0] == ' ' && buf[0])
377         {
378           strncpy(oaddr, buf, USERS_OFFICE_ADDR_SIZE - 1);
379           oaddr[USERS_OFFICE_ADDR_SIZE - 1] = '\0';
380           changed++;
381         }
382       else if (strncmp(strtrim(oaddr), buf, USERS_OFFICE_ADDR_SIZE - 1))
383         nochange++;
384     }
385   else
386     {
387       if (strncmp(strtrim(oaddr), buf, USERS_OFFICE_ADDR_SIZE - 1))
388         changed++;
389       strncpy(oaddr, buf, USERS_OFFICE_ADDR_SIZE - 1);
390       oaddr[USERS_OFFICE_ADDR_SIZE - 1] = '\0';
391     }
392   from = e->phone;
393   to = buf;
394   while (*from)
395     {
396       if (isdigit(*from))
397         *to++ = *from;
398       from++;
399     }
400   *to = '\0';
401   if (newfinger)
402     {
403       if (ophone[0] == ' ')
404         {
405           strncpy(ophone, buf, USERS_OFFICE_PHONE_SIZE - 1);
406           ophone[USERS_OFFICE_PHONE_SIZE - 1] = '\0';
407         }
408       else if (strncmp(strtrim(ophone), buf, USERS_OFFICE_PHONE_SIZE - 1))
409         nochange++;
410     }
411   else
412     {
413       if (strncmp(strtrim(ophone), buf, USERS_OFFICE_PHONE_SIZE - 1))
414         changed++;
415       strncpy(ophone, buf, USERS_OFFICE_PHONE_SIZE - 1);
416       ophone[USERS_OFFICE_PHONE_SIZE - 1] = '\0';
417     }
418   FixCase(e->dept);
419   FixCase(e->title);
420   if (newfinger)
421     {
422       if (dept[0] == ' ')
423         {
424           strncpy(dept, e->dept, USERS_DEPARTMENT_SIZE - 1);
425           dept[USERS_DEPARTMENT_SIZE - 1] = '\0';
426         }
427       else if (strncmp(strtrim(dept), e->dept, USERS_DEPARTMENT_SIZE - 1))
428         nochange++;
429     }
430   else
431     {
432       if (strncmp(strtrim(dept), e->dept, USERS_DEPARTMENT_SIZE - 1))
433         changed++;
434       strncpy(dept, e->dept, USERS_DEPARTMENT_SIZE - 1);
435       dept[USERS_DEPARTMENT_SIZE - 1] = '\0';
436     }
437   sid = e->id;
438   name = e->name;
439   rdept = e->dept;
440   rtitle = e->title;
441   raddr = e->address;
442   rhphone = e->phone;
443   rophone = e->phone2;
444   if (changed)
445     {
446       com_err(whoami, 0, "updating finger for %s %s", first, last);
447       EXEC SQL UPDATE users
448         SET office_addr = NVL(:oaddr, CHR(0)),
449         office_phone = NVL(:ophone, CHR(0)), department = NVL(:dept, CHR(0)),
450         fmodtime = SYSDATE, fmodby = :who, fmodwith = :prog,
451         xname = NVL(:name, CHR(0)), xdept = NVL(:rdept, CHR(0)),
452         xtitle = NVL(:rtitle, CHR(0)), xaddress = NVL(:raddr, CHR(0)),
453         xphone1 = NVL(:rhphone, CHR(0)), xphone2 = NVL(:rophone, CHR(0)),
454         xmodtime = SYSDATE, clearid = NVL(:sid, CHR(0))
455         WHERE users_id = :id;
456       if (sqlca.sqlcode)
457         {
458           dbmserr(NULL, sqlca.sqlcode);
459           exit(1);
460         }
461     }
462   else
463     {
464       EXEC SQL UPDATE users
465         SET xname = NVL(:name, CHR(0)), xdept = NVL(:rdept, CHR(0)),
466         xtitle = NVL(:rtitle, CHR(0)), xaddress = NVL(:raddr, CHR(0)),
467         xphone1 = NVL(:rhphone, CHR(0)), xphone2 = NVL(:rophone, CHR(0)),
468         xmodtime = SYSDATE, clearid = NVL(:sid, CHR(0))
469         WHERE users_id = :id;
470       if (sqlca.sqlcode)
471         {
472           dbmserr(NULL, sqlca.sqlcode);
473           exit(1);
474         }
475     }
476 }
477
478
479 void newuser(struct entry *e)
480 {
481   char *from, *to;
482   EXEC SQL BEGIN DECLARE SECTION;
483   int id, uid, st, who;
484   char *last, *first, *class, *middle, login[USERS_LOGIN_SIZE], *sid;
485   char fullname[USERS_FULLNAME_SIZE], *prog;
486   char oaddr[USERS_OFFICE_ADDR_SIZE], ophone[USERS_OFFICE_PHONE_SIZE];
487   char dept[USERS_DEPARTMENT_SIZE], *name, *title;
488   char *rdept, *rhphone, *rophone;
489   EXEC SQL END DECLARE SECTION;
490
491   who = WHO;
492   prog = PROG;
493   strncpy(oaddr, e->address, USERS_OFFICE_ADDR_SIZE - 1);
494   oaddr[USERS_OFFICE_ADDR_SIZE - 1] = '\0';
495   while ((to = strchr(oaddr, ',')))
496     *to = ';';
497   while ((to = strchr(oaddr, ':')))
498     *to = ';';
499   from = e->phone;
500   to = ophone;
501   while (*from)
502     {
503       if (isdigit(*from))
504         *to++ = *from;
505       from++;
506     }
507   *to = '\0';
508   FixCase(e->dept);
509   strncpy(dept, e->dept, USERS_DEPARTMENT_SIZE - 1);
510   dept[USERS_DEPARTMENT_SIZE] = '\0';
511
512   id = set_next_users_id(0);
513   uid = set_next_uid(e->highid);
514   sprintf(login, "#%d", uid);
515   last = e->last;
516   first = e->first;
517   middle = e->middle;
518   class = e->class;
519   if (*middle)
520     sprintf(fullname, "%s %s %s", first, middle, last);
521   else
522     sprintf(fullname, "%s %s", first, last);
523   st = US_NO_LOGIN_YET;
524
525   sid = e->id;
526   name = e->name;
527   rdept = e->dept;
528   title = e->title;
529   rhphone = e->phone;
530   rophone = e->phone2;
531
532   EXEC SQL INSERT INTO users
533     (login, users_id, unix_uid, shell, last, first, middle, status,
534      clearid, type, modtime, modby, modwith, fullname, office_addr,
535      office_phone, department, fmodtime, fmodby, fmodwith,
536      potype, xname, xdept, xtitle, xaddress, xphone1, xphone2, xmodtime)
537     VALUES (:login, :id, :uid, '/bin/athena/tcsh',
538             NVL(:last, CHR(0)), NVL(:first, CHR(0)), NVL(:middle, CHR(0)),
539             :st, NVL(:sid, CHR(0)), NVL(:class, CHR(0)), SYSDATE, :who, :prog,
540             NVL(:fullname, CHR(0)), NVL(:oaddr, CHR(0)), NVL(:ophone, CHR(0)),
541             NVL(:dept, CHR(0)), SYSDATE, :who, :prog, 'NONE',
542             NVL(:name, CHR(0)), NVL(:rdept, CHR(0)), NVL(:title, CHR(0)),
543             NVL(:oaddr, CHR(0)), NVL(:rhphone, CHR(0)), NVL(:rophone, CHR(0)),
544             SYSDATE);
545   if (sqlca.sqlcode)
546     {
547       dbmserr("adding user", sqlca.sqlcode);
548       exit(1);
549     }
550   else
551     com_err(whoami, 0, "adding user %s %s", e->first, e->last);
552 }
553
554
555 int set_next_users_id(int limit)
556 {
557   EXEC SQL BEGIN DECLARE SECTION;
558   int flag, value, retval;
559   EXEC SQL END DECLARE SECTION;
560
561   EXEC SQL SELECT value INTO :value FROM numvalues
562     WHERE name = 'users_id';
563   if (sqlfail())
564     sqlexit();
565   if (sqlca.sqlerrd[2] != 1)
566     {
567       EXEC SQL ROLLBACK;
568       com_err(whoami, MR_INTERNAL, "values table inconsistancy");
569       exit(1);
570     }
571
572   flag = 0;
573   EXEC SQL SELECT users_id INTO :flag FROM users
574     WHERE users_id = :value;
575   if (sqlfail())
576     sqlexit();
577   if (sqlca.sqlerrd[2] == 0)
578     flag = 0;
579   while (flag)
580     {
581       value++;
582       if (limit && value > MAX_ID_VALUE)
583         value = MIN_ID_VALUE;
584       flag = 0;
585       EXEC SQL SELECT users_id INTO :flag FROM users
586         WHERE users_id = :value;
587       if (sqlfail())
588         sqlexit();
589       if (sqlca.sqlerrd[2] == 0)
590         flag = 0;
591     }
592
593   retval = value++;
594   if (limit && value > MAX_ID_VALUE)
595     value = MIN_ID_VALUE;
596   EXEC SQL UPDATE numvalues SET value = :value
597     WHERE name = 'users_id';
598   if (sqlca.sqlcode)
599     {
600       dbmserr("assigning ID", sqlca.sqlcode);
601       exit(1);
602     }
603   return retval;
604 }
605
606 int set_next_uid(int high)
607 {
608   EXEC SQL BEGIN DECLARE SECTION;
609   int flag, value, retval;
610   char *name;
611   EXEC SQL END DECLARE SECTION;
612
613   if (high)
614     name = "high_uid";
615   else
616     name = "unix_uid";
617
618   EXEC SQL SELECT value INTO :value FROM numvalues
619     WHERE name = :name;
620   if (sqlfail())
621     sqlexit();
622   if (sqlca.sqlerrd[2] != 1)
623     {
624       EXEC SQL ROLLBACK;
625       com_err(whoami, MR_INTERNAL, "values table inconsistancy");
626       exit(1);
627     }
628
629   flag = 0;
630   EXEC SQL SELECT unix_uid INTO :flag FROM users WHERE unix_uid = :value;
631   if (sqlfail())
632     sqlexit();
633   if (sqlca.sqlerrd[2] == 0)
634     flag = 0;
635   while (flag)
636     {
637       value++;
638       if (!high && value > MAX_ID_VALUE)
639         value = MIN_ID_VALUE;
640       flag = 0;
641       EXEC SQL SELECT unix_uid INTO :flag FROM users WHERE unix_uid = :value;
642       if (sqlfail())
643         sqlexit();
644       if (sqlca.sqlerrd[2] == 0)
645         flag = 0;
646     }
647
648   retval = value++;
649   if (!high && value > MAX_ID_VALUE)
650     value = MIN_ID_VALUE;
651   EXEC SQL UPDATE numvalues SET value = :value WHERE name = :name;
652   if (sqlca.sqlcode)
653     {
654       dbmserr("assigning ID", sqlca.sqlcode);
655       exit(1);
656     }
657   return retval;
658 }
659
660
661 void sqlexit(void)
662 {
663   dbmserr(NULL, sqlca.sqlcode);
664   EXEC SQL ROLLBACK WORK;
665   exit(1);
666 }
667
668 void dbmserr(char *where, int what)
669 {
670   char err_msg[256];
671   int bufsize = 256, msglength = 0;
672
673   sqlglm(err_msg, &bufsize, &msglength);
674   err_msg[msglength] = '\0';
675
676   if (where)
677     com_err(whoami, 0, "DBMS error %swhile %s", err_msg, where);
678   else
679     com_err(whoami, 0, "DBMS error %s", err_msg);
680 }
This page took 0.084775 seconds and 5 git commands to generate.