]>
Commit | Line | Data |
---|---|---|
f0df8832 | 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 | |
4f15c8b6 | 32 | #define MAX_ID_VALUE 131072 |
f0df8832 | 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]; | |
7902e669 | 71 | char dmiddle[USERS_MIDDLE_SIZE], fullname[USERS_FULLNAME_SIZE]; |
f0df8832 | 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, | |
7902e669 | 89 | office_phone, home_addr, home_phone, fullname, department, status, fmodby |
f0df8832 | 90 | INTO :id, :dfirst, :dlast, :dmiddle, :type, :oaddr, |
7902e669 | 91 | :ophone, :haddr, :hphone, :fullname, :dept, :status, :fmodby |
f0df8832 | 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 | ||
7902e669 | 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 | ||
f0df8832 | 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)), | |
7902e669 | 222 | fullname = NVL(:fullname, CHR(0)), fmodtime = SYSDATE, fmodby = :who, |
223 | fmodwith = :prog, xname = NVL(SUBSTR(:name, 0, :xnlen), CHR(0)), | |
f0df8832 | 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(); | |
44a2baf1 | 264 | sprintf(login, "#%d", uid); |
e9e7acde | 265 | if (!strcmp(e->type, "LINCOLN")) |
44a2baf1 | 266 | st = US_NO_LOGIN_YET_KERBEROS_ONLY; |
e9e7acde | 267 | else |
44a2baf1 | 268 | st = US_NO_LOGIN_YET; |
f0df8832 | 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, | |
7ba40987 | 292 | xname, xdept, xtitle, xaddress, xphone1, xphone2, xmodtime, secure, |
00fef14d | 293 | created, creator, winhomedir, winprofiledir, sponsor_type, sponsor_id, expiration) |
f0df8832 | 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)), | |
7ba40987 | 303 | NVL(:xphone1, CHR(0)), NVL(:xphone2, CHR(0)), SYSDATE, :issecure, |
00fef14d | 304 | SYSDATE, :who, '[DFS]', '[DFS]', 'NONE', 0, CHR(0)); |
f0df8832 | 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 | } |