]>
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 | |
32 | #define MAX_ID_VALUE 65535 | |
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]; | |
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, department, status, fmodby | |
90 | INTO :id, :dfirst, :dlast, :dmiddle, :type, :oaddr, | |
91 | :ophone, :haddr, :hphone, :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 (changed) | |
207 | { | |
208 | com_err(whoami, 0, "updating finger for %s %s", first, last); | |
209 | EXEC SQL UPDATE users | |
210 | SET office_addr = NVL(:oaddr, CHR(0)), | |
211 | office_phone = NVL(:ophone, CHR(0)), home_addr = NVL(:haddr, CHR(0)), | |
212 | home_phone = NVL(:hphone, CHR(0)), department = NVL(:dept, CHR(0)), | |
213 | fmodtime = SYSDATE, fmodby = :who, fmodwith = :prog, | |
214 | xname = NVL(SUBSTR(:name, 0, :xnlen), CHR(0)), | |
215 | xdept = NVL(:dept, CHR(0)), xtitle = NVL(:xtitle, CHR(0)), | |
216 | xaddress = NVL(:xaddr, CHR(0)), xphone1 = NVL(:xphone1, CHR(0)), | |
217 | xphone2 = NVL(:xphone2, CHR(0)), xmodtime = SYSDATE | |
218 | WHERE users_id = :id; | |
219 | if (sqlca.sqlcode) | |
220 | { | |
221 | dbmserr(NULL, sqlca.sqlcode); | |
222 | exit(1); | |
223 | } | |
224 | } | |
225 | else | |
226 | { | |
227 | EXEC SQL UPDATE users | |
228 | SET xname = NVL(SUBSTR(:name, 0, :xnlen), CHR(0)), | |
229 | xdept = NVL(:dept, CHR(0)), xtitle = NVL(:xtitle, CHR(0)), | |
230 | xaddress = NVL(:xaddr, CHR(0)), xphone1 = NVL(:xphone1, CHR(0)), | |
231 | xphone2 = NVL(:xphone2, CHR(0)), xmodtime = SYSDATE | |
232 | WHERE users_id = :id; | |
233 | if (sqlca.sqlcode) | |
234 | { | |
235 | dbmserr(NULL, sqlca.sqlcode); | |
236 | exit(1); | |
237 | } | |
238 | } | |
239 | } | |
240 | ||
241 | void newuser(struct entry *e, int secure) | |
242 | { | |
243 | EXEC SQL BEGIN DECLARE SECTION; | |
244 | int issecure = secure, users_id, uid, st, xnlen = USERS_XNAME_SIZE - 1; | |
245 | int oadlen = USERS_OFFICE_ADDR_SIZE - 1; | |
246 | int ophlen = USERS_OFFICE_PHONE_SIZE - 1; | |
247 | char login[USERS_LOGIN_SIZE]; | |
248 | char *id, *last, *first, *middle, *type; | |
249 | char *name, *dept, *haddr, *hphone, *oaddr, *ophone; | |
250 | char *xtitle, *xaddress, *xphone1, *xphone2; | |
251 | EXEC SQL END DECLARE SECTION; | |
252 | ||
253 | users_id = set_next_users_id(); | |
254 | uid = set_next_uid(); | |
e9e7acde | 255 | if (!strcmp(e->type, "LINCOLN")) |
256 | { | |
257 | strncpy(login, e->first, 2); | |
258 | login[2] = '\0'; | |
259 | strncat(login, e->id+4, 5); | |
260 | lowercase(login); | |
261 | st = US_NO_LOGIN_YET_KERBEROS_ONLY; | |
262 | } | |
263 | else | |
264 | { | |
265 | sprintf(login, "#%d", uid); | |
266 | st = US_NO_LOGIN_YET; | |
267 | } | |
f0df8832 | 268 | last = e->last; |
269 | first = e->first; | |
270 | middle = e->middle; | |
271 | id = e->id; | |
272 | type = e->type; | |
273 | name = e->name; | |
274 | dept = e->dept; | |
275 | haddr = e->haddr; | |
276 | hphone = e->hphone; | |
277 | oaddr = e->oaddr; | |
278 | ophone = e->ophone; | |
279 | xtitle = e->xtitle; | |
280 | xaddress = e->xaddress; | |
281 | xphone1 = e->xphone1; | |
282 | xphone2 = e->xphone2; | |
283 | ||
284 | com_err(whoami, 0, "adding user %s %s", e->first, e->last); | |
285 | ||
286 | EXEC SQL INSERT INTO users | |
287 | (login, users_id, unix_uid, shell, winconsoleshell, last, first, | |
288 | middle, status, clearid, type, modtime, modby, modwith, fullname, | |
289 | department, home_addr, home_phone, office_addr, office_phone, fmodtime, | |
290 | fmodby, fmodwith, potype, pmodtime, pmodby, pmodwith, | |
7ba40987 | 291 | xname, xdept, xtitle, xaddress, xphone1, xphone2, xmodtime, secure, |
292 | created, creator) | |
f0df8832 | 293 | VALUES (:login, :users_id, :uid, '/bin/athena/tcsh', 'cmd', |
294 | NVL(:last, CHR(0)), NVL(:first, CHR(0)), NVL(:middle, CHR(0)), | |
295 | :st, NVL(:id, CHR(0)), NVL(:type, CHR(0)), SYSDATE, :who, :prog, | |
296 | NVL(:name, CHR(0)), NVL(:dept, CHR(0)), NVL(:haddr, CHR(0)), | |
297 | NVL(:hphone, CHR(0)), NVL(SUBSTR(:oaddr, 0, :oadlen), CHR(0)), | |
298 | NVL(SUBSTR(:ophone, 0, :ophlen), CHR(0)), SYSDATE, :who, :prog, | |
299 | 'NONE', SYSDATE, :who, :prog, | |
300 | NVL(SUBSTR(:name, 0, :xnlen), CHR(0)), NVL(:dept, CHR(0)), | |
301 | NVL(:xtitle, CHR(0)), NVL(:xaddress, CHR(0)), | |
7ba40987 | 302 | NVL(:xphone1, CHR(0)), NVL(:xphone2, CHR(0)), SYSDATE, :issecure, |
303 | SYSDATE, :who); | |
f0df8832 | 304 | if (sqlca.sqlcode) |
305 | { | |
306 | dbmserr("adding user", sqlca.sqlcode); | |
307 | exit(1); | |
308 | } | |
309 | } | |
310 | ||
311 | int set_next_users_id(void) | |
312 | { | |
313 | EXEC SQL BEGIN DECLARE SECTION; | |
314 | int flag, value, retval; | |
315 | EXEC SQL END DECLARE SECTION; | |
316 | ||
317 | EXEC SQL SELECT value INTO :value FROM numvalues | |
318 | WHERE name = 'users_id'; | |
319 | if (sqlfail()) | |
320 | sqlexit(); | |
321 | if (sqlca.sqlerrd[2] != 1) | |
322 | { | |
323 | EXEC SQL ROLLBACK; | |
324 | com_err(whoami, MR_INTERNAL, "values table inconsistancy"); | |
325 | exit(1); | |
326 | } | |
327 | ||
328 | flag = 0; | |
329 | EXEC SQL SELECT users_id INTO :flag FROM users | |
330 | WHERE users_id = :value; | |
331 | if (sqlfail()) | |
332 | sqlexit(); | |
333 | if (sqlca.sqlerrd[2] == 0) | |
334 | flag = 0; | |
335 | while (flag) | |
336 | { | |
337 | value++; | |
338 | flag = 0; | |
339 | EXEC SQL SELECT users_id INTO :flag FROM users | |
340 | WHERE users_id = :value; | |
341 | if (sqlfail()) | |
342 | sqlexit(); | |
343 | if (sqlca.sqlerrd[2] == 0) | |
344 | flag = 0; | |
345 | } | |
346 | ||
347 | retval = value++; | |
348 | EXEC SQL UPDATE numvalues SET value = :value | |
349 | WHERE name = 'users_id'; | |
350 | if (sqlca.sqlcode) | |
351 | { | |
352 | dbmserr("assigning ID", sqlca.sqlcode); | |
353 | exit(1); | |
354 | } | |
355 | return retval; | |
356 | } | |
357 | ||
358 | int set_next_uid(void) | |
359 | { | |
360 | EXEC SQL BEGIN DECLARE SECTION; | |
361 | int flag, initial, value, retval; | |
362 | EXEC SQL END DECLARE SECTION; | |
363 | ||
364 | EXEC SQL SELECT value INTO :initial FROM numvalues | |
365 | WHERE name = 'unix_uid'; | |
366 | if (sqlfail()) | |
367 | sqlexit(); | |
368 | if (sqlca.sqlerrd[2] != 1) | |
369 | { | |
370 | EXEC SQL ROLLBACK; | |
371 | com_err(whoami, MR_INTERNAL, "values table inconsistancy"); | |
372 | exit(1); | |
373 | } | |
374 | ||
375 | value = initial; | |
376 | flag = 0; | |
377 | EXEC SQL SELECT COUNT(unix_uid) INTO :flag | |
378 | FROM users WHERE unix_uid = :value; | |
379 | if (sqlfail()) | |
380 | sqlexit(); | |
381 | if (sqlca.sqlerrd[2] == 0) | |
382 | flag = 0; | |
383 | while (flag) | |
384 | { | |
385 | value++; | |
386 | #ifdef ULTRIX_ID_HOLE | |
387 | if (value > 31999 && value < 32768) | |
388 | value = 32768; | |
389 | #endif | |
390 | if (value > MAX_ID_VALUE) | |
391 | value = MIN_ID_VALUE; | |
392 | if (value == initial) | |
393 | { | |
394 | com_err(whoami, 0, "Out of uids!"); | |
395 | EXEC SQL ROLLBACK WORK; | |
396 | exit(1); | |
397 | } | |
398 | flag = 0; | |
399 | EXEC SQL SELECT COUNT(unix_uid) INTO :flag | |
400 | FROM users WHERE unix_uid = :value; | |
401 | if (sqlfail()) | |
402 | sqlexit(); | |
403 | } | |
404 | ||
405 | retval = value++; | |
406 | if (value > MAX_ID_VALUE) | |
407 | value = MIN_ID_VALUE; | |
408 | EXEC SQL UPDATE numvalues SET value = :value WHERE name = 'unix_uid'; | |
409 | if (sqlca.sqlcode) | |
410 | { | |
411 | dbmserr("assigning ID", sqlca.sqlcode); | |
412 | exit(1); | |
413 | } | |
414 | return retval; | |
415 | } | |
416 | ||
417 | void sqlexit(void) | |
418 | { | |
419 | dbmserr(NULL, sqlca.sqlcode); | |
420 | EXEC SQL ROLLBACK WORK; | |
421 | exit(1); | |
422 | } | |
423 | ||
424 | void dbmserr(char *where, int what) | |
425 | { | |
426 | char err_msg[256]; | |
427 | int bufsize = 256, msglength = 0; | |
428 | ||
429 | sqlglm(err_msg, &bufsize, &msglength); | |
430 | err_msg[msglength] = '\0'; | |
431 | ||
432 | if (where) | |
433 | com_err(whoami, 0, "DBMS error %swhile %s", err_msg, where); | |
434 | else | |
435 | com_err(whoami, 0, "DBMS error %s", err_msg); | |
436 | } |