]> andersk Git - moira.git/blob - regtape/common.pc
Add expiration date column to users table and client support.
[moira.git] / regtape / common.pc
1 /* $Id$
2  *
3  * Staff/Student load common code
4  *
5  * Copyright (C) 1999 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 #include "common.h"
15
16 #include <ctype.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 EXEC SQL BEGIN DECLARE SECTION;
25 extern char *prog;
26 extern int who;
27 EXEC SQL END DECLARE SECTION;
28
29 extern char *whoami;
30
31 #define MIN_ID_VALUE 100
32 #define MAX_ID_VALUE 131072
33
34 /* Remove non-digits from a phone number. */
35 void fixphone(char *phone)
36 {
37   char *d = phone;
38
39   while (*phone)
40     {
41       if (isdigit(*phone))
42         *d++ = *phone;
43       phone++;
44     }
45   *d = '\0';
46 }
47
48 /* Remove characters from address that aren't safe for passwd files. */
49 void fixaddress(char *address)
50 {
51   char *p;
52
53   while ((p = strchr(address, ',')))
54     *p = ';';
55   while ((p = strchr(address, ':')))
56     *p = ';';
57 }  
58
59 void process_entry(struct entry *e, int secure)
60 {
61   int changed;
62   char buf[MAX_FIELD_WIDTH], *from, *to;
63   EXEC SQL BEGIN DECLARE SECTION;
64   char *first, *last, *middle, *sid;
65   char *name = e->name, *xtitle = e->xtitle, *xaddr = e->xaddress;
66   char *xphone1 = e->xphone1, *xphone2 = e->xphone2;
67   char type[USERS_TYPE_SIZE], oaddr[USERS_OFFICE_ADDR_SIZE];
68   char ophone[USERS_OFFICE_PHONE_SIZE], dept[USERS_DEPARTMENT_SIZE];
69   char haddr[USERS_HOME_ADDR_SIZE], hphone[USERS_HOME_PHONE_SIZE];
70   char dfirst[USERS_FIRST_SIZE], dlast[USERS_LAST_SIZE];
71   char dmiddle[USERS_MIDDLE_SIZE], fullname[USERS_FULLNAME_SIZE];
72   int id, status, fmodby, xnlen = USERS_XNAME_SIZE - 1;
73   EXEC SQL END DECLARE SECTION;
74
75   sid = e->id;
76   last = e->last;
77   if (strlen(last) > USERS_LAST_SIZE - 1)
78     last[USERS_LAST_SIZE - 1] = '\0';
79   first = e->first;
80   if (strlen(first) > USERS_FIRST_SIZE - 1)
81     first[USERS_FIRST_SIZE - 1] = '\0';
82   middle = e->middle;
83   if (strlen(middle) > USERS_MIDDLE_SIZE - 1)
84     middle[USERS_MIDDLE_SIZE - 1] = '\0';
85   id = 0;
86
87   /* Get user info */
88   EXEC SQL SELECT users_id, first, last, middle, type, office_addr,
89     office_phone, home_addr, home_phone, fullname, department, status, fmodby
90     INTO :id, :dfirst, :dlast, :dmiddle, :type, :oaddr,
91     :ophone, :haddr, :hphone, :fullname, :dept, :status, :fmodby
92     FROM users
93     WHERE clearid = :sid AND status != 3;
94   if (sqlfail())
95     {
96       if (sqlca.sqlcode == SQL_DUPLICATE)
97         {
98           com_err(whoami, 0, "duplicate ID number %s on user %s %s",
99                   sid, first, last);
100           return;
101         }
102       else
103         sqlexit();
104     }
105   if (id == 0)
106     {
107       newuser(e, secure);
108       return;
109     }
110   strtrim(dfirst);
111   strtrim(dlast);
112   strtrim(dmiddle);
113   strtrim(type);
114
115   /* Update type/state if necessary.  (Exclude several spacial cases.) */
116   if (strcmp(e->type, type) &&
117       strcmp(type, "STAFF") && strcmp(type, "SIPBMEM") &&
118       strcmp(type, "KNIGHT"))
119     {
120       com_err(whoami, 0, "updating type for %s %s from \"%s\" to \"%s\"",
121               first, last, type, e->type);
122       if (status == US_NOT_ALLOWED)
123         status = US_NO_LOGIN_YET;
124       else if (status == US_ENROLL_NOT_ALLOWED)
125         status = US_ENROLLED;
126       strcpy(type, e->type);
127       EXEC SQL UPDATE users
128         SET type = NVL(:type, CHR(0)), status = :status,
129         modtime = SYSDATE, modby = :who, modwith = :prog
130         WHERE users_id = :id;
131       if (sqlca.sqlcode)
132         {
133           dbmserr("updating user", sqlca.sqlcode);
134           exit(1);
135         }
136     }
137
138   /* Update name if necessary */
139   if (strcmp(first, dfirst) || strcmp(last, dlast) || strcmp(middle, dmiddle))
140     {
141       com_err(whoami, 0, "updating real name for %s%s%s %s (was %s%s%s %s)",
142               first, *middle ? " " : "", middle, last,
143               dfirst, *dmiddle ? " " : "", dmiddle, dlast);
144       EXEC SQL UPDATE users
145         SET first = NVL(:first, CHR(0)), last = NVL(:last, CHR(0)),
146         middle = NVL(:middle, CHR(0)), modby = :who, modwith = :prog,
147         modtime = SYSDATE
148         WHERE users_id = :id;
149       if (sqlca.sqlcode)
150         {
151           dbmserr("updating name", sqlca.sqlcode);
152           exit(1);
153         }
154     }
155
156   /* Update finger info fields if they have changed and the user
157    * didn't set them blank.
158    */
159   changed = 0;
160
161   if (strncmp(strtrim(oaddr), e->oaddr, USERS_OFFICE_ADDR_SIZE - 1) &&
162       (*oaddr || fmodby != id))
163     {
164       changed++;
165       com_err(whoami, 0, "office for %s %s changed from \"%s\" to \"%s\"",
166               first, last, oaddr, e->oaddr);
167       strlcpy(oaddr, e->oaddr, USERS_OFFICE_ADDR_SIZE);
168     }
169
170   if (strncmp(strtrim(ophone), e->ophone, USERS_OFFICE_PHONE_SIZE - 1) &&
171       (*ophone || fmodby != id))
172     {
173       changed++;
174       com_err(whoami, 0, "Phone for %s %s changed from \"%s\" to \"%s\"",
175               first, last, ophone, e->ophone);
176       strlcpy(ophone, e->ophone, USERS_OFFICE_PHONE_SIZE);
177     }
178
179   if (strncmp(strtrim(haddr), e->haddr, USERS_HOME_ADDR_SIZE - 1) &&
180       (*haddr || fmodby != id))
181     {
182       changed++;
183       com_err(whoami, 0, "home addr for %s %s changed from \"%s\" to \"%s\"",
184               first, last, haddr, e->haddr);
185       strlcpy(haddr, e->haddr, USERS_HOME_ADDR_SIZE);
186     }
187
188   if (strncmp(strtrim(hphone), e->hphone, USERS_HOME_PHONE_SIZE - 1) &&
189       (*hphone || fmodby != id))
190     {
191       changed++;
192       com_err(whoami, 0, "Phone for %s %s changed from \"%s\" to \"%s\"",
193               first, last, hphone, e->hphone);
194       strlcpy(hphone, e->hphone, USERS_HOME_PHONE_SIZE);
195     }
196
197   if (strncmp(strtrim(dept), e->dept, USERS_DEPARTMENT_SIZE - 1) &&
198       (*dept || fmodby != id))
199     {
200       changed++;
201       com_err(whoami, 0, "Department for %s %s changed from \"%s\" to \"%s\"",
202               first, last, dept, e->dept);
203       strlcpy(dept, e->dept, USERS_DEPARTMENT_SIZE);
204     }
205
206   if (strncmp(strtrim(fullname), e->name, USERS_FULLNAME_SIZE - 1) &&
207       (*fullname || fmodby != id))
208     {
209       changed++;
210       com_err(whoami, 0, "Fullname for %s %s changed from \"%s\" to \"%s\"",
211               first, last, fullname, e->name);
212       strlcpy(fullname, e->name, USERS_FULLNAME_SIZE);
213     }
214
215   if (changed)
216     {
217       com_err(whoami, 0, "updating finger for %s %s", first, last);
218       EXEC SQL UPDATE users
219         SET office_addr = NVL(:oaddr, CHR(0)),
220         office_phone = NVL(:ophone, CHR(0)), home_addr = NVL(:haddr, CHR(0)),
221         home_phone = NVL(:hphone, CHR(0)), department = NVL(:dept, CHR(0)),
222         fullname = NVL(:fullname, CHR(0)), fmodtime = SYSDATE, fmodby = :who,
223         fmodwith = :prog, xname = NVL(SUBSTR(:name, 0, :xnlen), CHR(0)),
224         xdept = NVL(:dept, CHR(0)), xtitle = NVL(:xtitle, CHR(0)),
225         xaddress = NVL(:xaddr, CHR(0)), xphone1 = NVL(:xphone1, CHR(0)),
226         xphone2 = NVL(:xphone2, CHR(0)), xmodtime = SYSDATE
227         WHERE users_id = :id;
228       if (sqlca.sqlcode)
229         {
230           dbmserr(NULL, sqlca.sqlcode);
231           exit(1);
232         }
233     }
234   else
235     {
236       EXEC SQL UPDATE users
237         SET xname = NVL(SUBSTR(:name, 0, :xnlen), CHR(0)), 
238         xdept = NVL(:dept, CHR(0)), xtitle = NVL(:xtitle, CHR(0)), 
239         xaddress = NVL(:xaddr, CHR(0)), xphone1 = NVL(:xphone1, CHR(0)), 
240         xphone2 = NVL(:xphone2, CHR(0)), xmodtime = SYSDATE
241         WHERE users_id = :id;
242       if (sqlca.sqlcode)
243         {
244           dbmserr(NULL, sqlca.sqlcode);
245           exit(1);
246         }
247     }
248 }
249
250 void newuser(struct entry *e, int secure)
251 {
252   EXEC SQL BEGIN DECLARE SECTION;
253   int issecure = secure, users_id, uid, st, xnlen = USERS_XNAME_SIZE - 1;
254   int oadlen = USERS_OFFICE_ADDR_SIZE - 1;
255   int ophlen = USERS_OFFICE_PHONE_SIZE - 1; 
256   char login[USERS_LOGIN_SIZE];
257   char *id, *last, *first, *middle, *type;
258   char *name, *dept, *haddr, *hphone, *oaddr, *ophone;
259   char *xtitle, *xaddress, *xphone1, *xphone2;
260   EXEC SQL END DECLARE SECTION;
261
262   users_id = set_next_users_id();
263   uid = set_next_uid();
264   sprintf(login, "#%d", uid);
265   if (!strcmp(e->type, "LINCOLN"))
266     st = US_NO_LOGIN_YET_KERBEROS_ONLY;
267   else
268     st = US_NO_LOGIN_YET;
269   last = e->last;
270   first = e->first;
271   middle = e->middle;
272   id = e->id;
273   type = e->type;
274   name = e->name;
275   dept = e->dept;
276   haddr = e->haddr;
277   hphone = e->hphone;
278   oaddr = e->oaddr;
279   ophone = e->ophone;
280   xtitle = e->xtitle;
281   xaddress = e->xaddress;
282   xphone1 = e->xphone1;
283   xphone2 = e->xphone2;
284
285   com_err(whoami, 0, "adding user %s %s", e->first, e->last);
286
287   EXEC SQL INSERT INTO users
288     (login, users_id, unix_uid, shell, winconsoleshell, last, first, 
289      middle, status, clearid, type, modtime, modby, modwith, fullname, 
290      department, home_addr, home_phone, office_addr, office_phone, fmodtime,
291      fmodby, fmodwith, potype, pmodtime, pmodby, pmodwith,
292      xname, xdept, xtitle, xaddress, xphone1, xphone2, xmodtime, secure,
293      created, creator, winhomedir, winprofiledir, sponsor_type, sponsor_id, expiration)
294     VALUES (:login, :users_id, :uid, '/bin/athena/tcsh', 'cmd',
295             NVL(:last, CHR(0)), NVL(:first, CHR(0)), NVL(:middle, CHR(0)),
296             :st, NVL(:id, CHR(0)), NVL(:type, CHR(0)), SYSDATE, :who, :prog,
297             NVL(:name, CHR(0)), NVL(:dept, CHR(0)), NVL(:haddr, CHR(0)),
298             NVL(:hphone, CHR(0)), NVL(SUBSTR(:oaddr, 0, :oadlen), CHR(0)), 
299             NVL(SUBSTR(:ophone, 0, :ophlen), CHR(0)), SYSDATE, :who, :prog, 
300             'NONE', SYSDATE, :who, :prog, 
301             NVL(SUBSTR(:name, 0, :xnlen), CHR(0)), NVL(:dept, CHR(0)),
302             NVL(:xtitle, CHR(0)), NVL(:xaddress, CHR(0)),
303             NVL(:xphone1, CHR(0)), NVL(:xphone2, CHR(0)), SYSDATE, :issecure,
304             SYSDATE, :who, '[DFS]', '[DFS]', 'NONE', 0, CHR(0));
305   if (sqlca.sqlcode)
306     {
307       dbmserr("adding user", sqlca.sqlcode);
308       exit(1);
309     }
310 }
311
312 int set_next_users_id(void)
313 {
314   EXEC SQL BEGIN DECLARE SECTION;
315   int flag, value, retval;
316   EXEC SQL END DECLARE SECTION;
317
318   EXEC SQL SELECT value INTO :value FROM numvalues
319     WHERE name = 'users_id';
320   if (sqlfail())
321     sqlexit();
322   if (sqlca.sqlerrd[2] != 1)
323     {
324       EXEC SQL ROLLBACK;
325       com_err(whoami, MR_INTERNAL, "values table inconsistancy");
326       exit(1);
327     }
328
329   flag = 0;
330   EXEC SQL SELECT users_id INTO :flag FROM users
331     WHERE users_id = :value;
332   if (sqlfail())
333     sqlexit();
334   if (sqlca.sqlerrd[2] == 0)
335     flag = 0;
336   while (flag)
337     {
338       value++;
339       flag = 0;
340       EXEC SQL SELECT users_id INTO :flag FROM users
341         WHERE users_id = :value;
342       if (sqlfail())
343         sqlexit();
344       if (sqlca.sqlerrd[2] == 0)
345         flag = 0;
346     }
347
348   retval = value++;
349   EXEC SQL UPDATE numvalues SET value = :value
350     WHERE name = 'users_id';
351   if (sqlca.sqlcode)
352     {
353       dbmserr("assigning ID", sqlca.sqlcode);
354       exit(1);
355     }
356   return retval;
357 }
358
359 int set_next_uid(void)
360 {
361   EXEC SQL BEGIN DECLARE SECTION;
362   int flag, initial, value, retval;
363   EXEC SQL END DECLARE SECTION;
364
365   EXEC SQL SELECT value INTO :initial FROM numvalues
366     WHERE name = 'unix_uid';
367   if (sqlfail())
368     sqlexit();
369   if (sqlca.sqlerrd[2] != 1)
370     {
371       EXEC SQL ROLLBACK;
372       com_err(whoami, MR_INTERNAL, "values table inconsistancy");
373       exit(1);
374     }
375
376   value = initial;
377   flag = 0;
378   EXEC SQL SELECT COUNT(unix_uid) INTO :flag
379     FROM users WHERE unix_uid = :value;
380   if (sqlfail())
381     sqlexit();
382   if (sqlca.sqlerrd[2] == 0)
383     flag = 0;
384   while (flag)
385     {
386       value++;
387 #ifdef ULTRIX_ID_HOLE
388       if (value > 31999 && value < 32768)
389         value = 32768;
390 #endif
391       if (value > MAX_ID_VALUE)
392         value = MIN_ID_VALUE;
393       if (value == initial)
394         {
395           com_err(whoami, 0, "Out of uids!");
396           EXEC SQL ROLLBACK WORK;
397           exit(1);
398         }
399       flag = 0;
400       EXEC SQL SELECT COUNT(unix_uid) INTO :flag
401         FROM users WHERE unix_uid = :value;
402       if (sqlfail())
403         sqlexit();
404     }
405
406   retval = value++;
407   if (value > MAX_ID_VALUE)
408     value = MIN_ID_VALUE;
409   EXEC SQL UPDATE numvalues SET value = :value WHERE name = 'unix_uid';
410   if (sqlca.sqlcode)
411     {
412       dbmserr("assigning ID", sqlca.sqlcode);
413       exit(1);
414     }
415   return retval;
416 }
417
418 void sqlexit(void)
419 {
420   dbmserr(NULL, sqlca.sqlcode);
421   EXEC SQL ROLLBACK WORK;
422   exit(1);
423 }
424
425 void dbmserr(char *where, int what)
426 {
427   char err_msg[256];
428   int bufsize = 256, msglength = 0;
429
430   sqlglm(err_msg, &bufsize, &msglength);
431   err_msg[msglength] = '\0';
432
433   if (where)
434     com_err(whoami, 0, "DBMS error %swhile %s", err_msg, where);
435   else
436     com_err(whoami, 0, "DBMS error %s", err_msg);
437 }
This page took 0.113778 seconds and 5 git commands to generate.