]> andersk Git - moira.git/blob - regtape/employee.pc
second code style cleanup: void/void * usage, proper #includes. try to
[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
14 #include <ctype.h>
15 #include <stdio.h>
16 #include <string.h>
17
18 EXEC SQL INCLUDE sqlca;
19 extern void sqlglm(char *, unsigned int *, unsigned int *);
20
21 RCSID("$Header$");
22
23 #define WHO 11859               /* root */
24 #define PROG "emp-tape"
25
26 #define MAX_ID_VALUE    31999
27 #define MIN_ID_VALUE    101
28
29 /* File format is:
30
31 0-8     id number
32 9-38    name
33 39-62   office address
34 63-74   phone1
35 75-86   phone2
36 87-106  dept
37 107-156 title
38 157-186 username
39 187-241 host
40
41 */
42
43 #define LOC_ID 0
44 #define LOC_NAME 9
45 #define LOC_OFFICE 39
46 #define LOC_PHONE 63
47 #define LOC_PHONE2 75
48 #define LOC_DEPT 87
49 #define LOC_TITLE 107
50 #define LOC_USERNAME 157
51 #define LOC_HOST 187
52
53 #define LEN_ID 9
54 #define LEN_NAME 30
55 #define LEN_OFFICE 24
56 #define LEN_PHONE 12
57 #define LEN_PHONE2 12
58 #define LEN_DEPT 20
59 #define LEN_TITLE 50
60 #define LEN_USERNAME 30
61 #define LEN_HOST 55
62
63
64 struct entry {
65   char *name;
66   char *last;
67   char *first;
68   char *middle;
69   char *title;
70   char *class;
71   char *id;
72   char *eid;
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[BUFSIZ], *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           gets(buf);
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], eid[16];
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   e.eid = eid;
237   EncryptID(e.eid, e.id, e.first, e.last);
238
239   e.address = strtrim(office);
240   e.phone = strtrim(phone);
241   e.phone2 = strtrim(phone2);
242   e.dept = strtrim(dept);
243   e.title = strtrim(title);
244
245   e.class = "MITS";
246   e.highid = 0;
247   if (strstr(e.title, "PROF") || strstr(e.title, "LECTURE"))
248     e.class = "FACULTY";
249   if (!strcmp(e.dept, "LINCOLN LAB"))
250     {
251       e.class = "LINCOLN";
252       e.highid = 1;
253     }
254
255   return &e;
256 }
257
258 void process_entry(struct entry *e)
259 {
260   int changed, nochange, encrypted;
261   char buf[BUFSIZ], *from, *to;
262   EXEC SQL BEGIN DECLARE SECTION;
263   char *first, *last, *middle, *eid, *sid, *name, *rdept;
264   char *rtitle, *raddr, *rhphone, *rophone, *prog;
265   char class[9], oaddr[25], ophone[17], dept[128];
266   char dfirst[17], dlast[17], dmiddle[17];
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) > 16)
274     first[16] = '\0';
275   last = e->last;
276   if (strlen(last) > 16)
277     last[16] = '\0';
278   middle = e->middle;
279   eid = e->eid;
280   sid = e->id;
281   id = 0;
282   encrypted = 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       EXEC SQL SELECT users_id, first, last, middle, type, office_addr,
305         office_phone, department, status
306         INTO :id, :dfirst, :dlast, :dmiddle, :class, :oaddr,
307         :ophone, :dept, :status
308         FROM users
309         WHERE last = :last and first = :first and clearid = :eid;
310       if (sqlfail() && sqlca.sqlcode != SQL_DUPLICATE)
311         sqlexit();
312       encrypted++;
313       if (id == 0)
314         {
315           newuser(e);
316           return;
317         }
318     }
319
320   /* Update class/state if necessary.  (Exclude several spacial cases.) */
321   if (strcmp(e->class, strtrim(class)) &&
322       strcmp(class, "STAFF") && strcmp(class, "SIPBMEM") &&
323       strcmp(class, "KNIGHT"))
324     {
325       com_err(whoami, 0, "updating class for %s %s from %s to %s",
326               first, last, class, e->class);
327       if (status == US_NOT_ALLOWED)
328         status = US_NO_LOGIN_YET;
329       if (status == US_ENROLL_NOT_ALLOWED)
330         status = US_ENROLLED;
331       strcpy(class, e->class);
332       EXEC SQL UPDATE users
333         SET type = NVL(:class, CHR(0)), status = :status, modtime = SYSDATE,
334         modby = :who, modwith = :prog
335         WHERE users_id = :id;
336       if (sqlca.sqlcode)
337         {
338           dbmserr("updating user", sqlca.sqlcode);
339           exit(1);
340         }
341     }
342
343   /* Update name if necessary */
344   if (strcmp(first, strtrim(dfirst)) ||
345       strcmp(last, strtrim(dlast)) ||
346       strcmp(middle, strtrim(dmiddle)))
347     {
348       com_err(whoami, 0, "updating real name for %s %s", first, last);
349       EXEC SQL UPDATE users
350         SET first = NVL(:first, CHR(0)), last = NVL(:last, CHR(0)),
351         middle = NVL(:middle, CHR(0)), modby = :who, modwith = :prog,
352         modtime = SYSDATE
353         WHERE users_id = :id;
354       if (sqlca.sqlcode)
355         {
356           dbmserr("updating name", sqlca.sqlcode);
357           exit(1);
358         }
359     }
360
361   changed = nochange = 0;
362   if (encrypted)
363     changed++;
364   strcpy(buf, e->address);
365   while ((to = strchr(buf, ',')))
366     *to = ';';
367   while ((to = strchr(buf, ':')))
368     *to = ';';
369   if (newfinger)
370     {
371       if (oaddr[0] == ' ' && buf[0])
372         {
373           strncpy(oaddr, buf, 16);
374           oaddr[16] = '\0';
375           changed++;
376         }
377       else if (strncmp(strtrim(oaddr), buf, 15))
378         nochange++;
379     }
380   else
381     {
382       if (strncmp(strtrim(oaddr), buf, 15))
383         changed++;
384       strncpy(oaddr, buf, 16);
385       oaddr[16] = '\0';
386     }
387   from = e->phone;
388   to = buf;
389   while (*from)
390     {
391       if (isdigit(*from))
392         *to++ = *from;
393       from++;
394     }
395   *to = '\0';
396   if (newfinger)
397     {
398       if (ophone[0] == ' ')
399         {
400           strncpy(ophone, buf, 16);
401           ophone[16] = '\0';
402         }
403       else if (strncmp(strtrim(ophone), buf, 11))
404         nochange++;
405     }
406   else
407     {
408       if (strncmp(strtrim(ophone), buf, 11))
409         changed++;
410       strncpy(ophone, buf, 16);
411       ophone[16] = '\0';
412     }
413   FixCase(e->dept);
414   FixCase(e->title);
415   if (newfinger)
416     {
417       if (dept[0] == ' ')
418         {
419           strncpy(dept, e->dept, 12);
420           dept[12] = '\0';
421         }
422       else if (strncmp(strtrim(dept), e->dept, 11))
423         nochange++;
424     }
425   else
426     {
427       if (strncmp(strtrim(dept), e->dept, 11))
428         changed++;
429       strncpy(dept, e->dept, 12);
430       dept[12] = '\0';
431     }
432   sid = e->id;
433   name = e->name;
434   rdept = e->dept;
435   rtitle = e->title;
436   raddr = e->address;
437   rhphone = e->phone;
438   rophone = e->phone2;
439   if (changed)
440     {
441       com_err(whoami, 0, "updating finger for %s %s", first, last);
442       EXEC SQL UPDATE users
443         SET office_addr = NVL(:oaddr, CHR(0)),
444         office_phone = NVL(:ophone, CHR(0)), department = NVL(:dept, CHR(0)),
445         fmodtime = SYSDATE, fmodby = :who, fmodwith = :prog,
446         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   else
458     {
459       EXEC SQL UPDATE users
460         SET xname = NVL(:name, CHR(0)), xdept = NVL(:rdept, CHR(0)),
461         xtitle = NVL(:rtitle, CHR(0)), xaddress = NVL(:raddr, CHR(0)),
462         xphone1 = NVL(:rhphone, CHR(0)), xphone2 = NVL(:rophone, CHR(0)),
463         xmodtime = SYSDATE, clearid = NVL(:sid, CHR(0))
464         WHERE users_id = :id;
465       if (sqlca.sqlcode)
466         {
467           dbmserr(NULL, sqlca.sqlcode);
468           exit(1);
469         }
470     }
471 }
472
473
474 void newuser(struct entry *e)
475 {
476   char *from, *to;
477   EXEC SQL BEGIN DECLARE SECTION;
478   int id, uid, st, who;
479   char *last, *first, *class, *middle, login[9], *sid, fullname[65], *prog;
480   char oaddr[81], ophone[17], dept[128], *name, *title;
481   char *rdept, *rhphone, *rophone;
482   EXEC SQL END DECLARE SECTION;
483
484   who = WHO;
485   prog = PROG;
486   strncpy(oaddr, e->address, 16);
487   oaddr[16] = '\0';
488   while ((to = strchr(oaddr, ',')))
489     *to = ';';
490   while ((to = strchr(oaddr, ':')))
491     *to = ';';
492   from = e->phone;
493   to = ophone;
494   while (*from)
495     {
496       if (isdigit(*from))
497         *to++ = *from;
498       from++;
499     }
500   *to = '\0';
501   FixCase(e->dept);
502   strncpy(dept, e->dept, 12);
503   dept[12] = '\0';
504
505   id = set_next_users_id(0);
506   uid = set_next_uid(e->highid);
507   sprintf(login, "#%d", uid);
508   last = e->last;
509   first = e->first;
510   middle = e->middle;
511   class = e->class;
512   if (*middle)
513     sprintf(fullname, "%s %s %s", first, middle, last);
514   else
515     sprintf(fullname, "%s %s", first, last);
516   st = US_NO_LOGIN_YET;
517
518   sid = e->id;
519   name = e->name;
520   rdept = e->dept;
521   title = e->title;
522   rhphone = e->phone;
523   rophone = e->phone2;
524
525   EXEC SQL INSERT INTO users
526     (login, users_id, unix_uid, shell, last, first, middle, status,
527      clearid, type, modtime, modby, modwith, fullname, office_addr,
528      office_phone, department, fmodtime, fmodby, fmodwith,
529      potype, xname, xdept, xtitle, xaddress, xphone1, xphone2, xmodtime)
530     VALUES (:login, :id, :uid, '/bin/athena/tcsh',
531             NVL(:last, CHR(0)), NVL(:first, CHR(0)), NVL(:middle, CHR(0)),
532             :st, NVL(:sid, CHR(0)), NVL(:class, CHR(0)), SYSDATE, :who, :prog,
533             NVL(:fullname, CHR(0)), NVL(:oaddr, CHR(0)), NVL(:ophone, CHR(0)),
534             NVL(:dept, CHR(0)), SYSDATE, :who, :prog, 'NONE',
535             NVL(:name, CHR(0)), NVL(:rdept, CHR(0)), NVL(:title, CHR(0)),
536             NVL(:oaddr, CHR(0)), NVL(:rhphone, CHR(0)), NVL(:rophone, CHR(0)),
537             SYSDATE);
538   if (sqlca.sqlcode)
539     {
540       dbmserr("adding user", sqlca.sqlcode);
541       exit(1);
542     }
543   else
544     com_err(whoami, 0, "adding user %s %s", e->first, e->last);
545 }
546
547
548 int set_next_users_id(int limit)
549 {
550   EXEC SQL BEGIN DECLARE SECTION;
551   int flag, value, retval;
552   EXEC SQL END DECLARE SECTION;
553
554   EXEC SQL SELECT value INTO :value FROM numvalues
555     WHERE name = 'users_id';
556   if (sqlfail())
557     sqlexit();
558   if (sqlca.sqlerrd[2] != 1)
559     {
560       EXEC SQL ROLLBACK;
561       com_err(whoami, MR_INTERNAL, "values table inconsistancy");
562       exit(1);
563     }
564
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   while (flag)
573     {
574       value++;
575       if (limit && value > MAX_ID_VALUE)
576         value = MIN_ID_VALUE;
577       flag = 0;
578       EXEC SQL SELECT users_id INTO :flag FROM users
579         WHERE users_id = :value;
580       if (sqlfail())
581         sqlexit();
582       if (sqlca.sqlerrd[2] == 0)
583         flag = 0;
584     }
585
586   retval = value++;
587   if (limit && value > MAX_ID_VALUE)
588     value = MIN_ID_VALUE;
589   EXEC SQL UPDATE numvalues SET value = :value
590     WHERE name = 'users_id';
591   if (sqlca.sqlcode)
592     {
593       dbmserr("assigning ID", sqlca.sqlcode);
594       exit(1);
595     }
596   return retval;
597 }
598
599 int set_next_uid(int high)
600 {
601   EXEC SQL BEGIN DECLARE SECTION;
602   int flag, value, retval;
603   char *name;
604   EXEC SQL END DECLARE SECTION;
605
606   if (high)
607     name = "high_uid";
608   else
609     name = "unix_uid";
610
611   EXEC SQL SELECT value INTO :value FROM numvalues
612     WHERE name = :name;
613   if (sqlfail())
614     sqlexit();
615   if (sqlca.sqlerrd[2] != 1)
616     {
617       EXEC SQL ROLLBACK;
618       com_err(whoami, MR_INTERNAL, "values table inconsistancy");
619       exit(1);
620     }
621
622   flag = 0;
623   EXEC SQL SELECT unix_uid INTO :flag FROM users WHERE unix_uid = :value;
624   if (sqlfail())
625     sqlexit();
626   if (sqlca.sqlerrd[2] == 0)
627     flag = 0;
628   while (flag)
629     {
630       value++;
631       if (!high && value > MAX_ID_VALUE)
632         value = MIN_ID_VALUE;
633       flag = 0;
634       EXEC SQL SELECT unix_uid INTO :flag FROM users WHERE unix_uid = :value;
635       if (sqlfail())
636         sqlexit();
637       if (sqlca.sqlerrd[2] == 0)
638         flag = 0;
639     }
640
641   retval = value++;
642   if (!high && value > MAX_ID_VALUE)
643     value = MIN_ID_VALUE;
644   EXEC SQL UPDATE numvalues SET value = :value WHERE name = :name;
645   if (sqlca.sqlcode)
646     {
647       dbmserr("assigning ID", sqlca.sqlcode);
648       exit(1);
649     }
650   return retval;
651 }
652
653
654 void sqlexit(void)
655 {
656   dbmserr(NULL, sqlca.sqlcode);
657   EXEC SQL ROLLBACK WORK;
658   exit(1);
659 }
660
661 void dbmserr(char *where, int what)
662 {
663   char err_msg[256];
664   int bufsize = 256, msglength = 0;
665
666   sqlglm(err_msg, &bufsize, &msglength);
667   err_msg[msglength] = '\0';
668
669   if (where)
670     com_err(whoami, 0, "DBMS error %swhile %s", err_msg, where);
671   else
672     com_err(whoami, 0, "DBMS error %s", err_msg);
673 }
This page took 0.086483 seconds and 5 git commands to generate.