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