3 * Staff/Student load common code
5 * Copyright (C) 1999 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
10 #include <mit-copyright.h>
12 #include <moira_site.h>
13 #include <moira_schema.h>
19 EXEC SQL INCLUDE sqlca;
20 extern void sqlglm(char *, unsigned int *, unsigned int *);
24 EXEC SQL BEGIN DECLARE SECTION;
27 EXEC SQL END DECLARE SECTION;
31 #define MIN_ID_VALUE 100
32 #define MAX_ID_VALUE 131072
34 /* Remove non-digits from a phone number. */
35 void fixphone(char *phone)
48 /* Remove characters from address that aren't safe for passwd files. */
49 void fixaddress(char *address)
53 while ((p = strchr(address, ',')))
55 while ((p = strchr(address, ':')))
59 void process_entry(struct entry *e, int secure)
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;
77 if (strlen(last) > USERS_LAST_SIZE - 1)
78 last[USERS_LAST_SIZE - 1] = '\0';
80 if (strlen(first) > USERS_FIRST_SIZE - 1)
81 first[USERS_FIRST_SIZE - 1] = '\0';
83 if (strlen(middle) > USERS_MIDDLE_SIZE - 1)
84 middle[USERS_MIDDLE_SIZE - 1] = '\0';
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
93 WHERE clearid = :sid AND status != 3;
96 if (sqlca.sqlcode == SQL_DUPLICATE)
98 com_err(whoami, 0, "duplicate ID number %s on user %s %s",
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"))
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;
133 dbmserr("updating user", sqlca.sqlcode);
138 /* Update name if necessary */
139 if (strcmp(first, dfirst) || strcmp(last, dlast) || strcmp(middle, dmiddle))
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,
148 WHERE users_id = :id;
151 dbmserr("updating name", sqlca.sqlcode);
156 /* Update finger info fields if they have changed and the user
157 * didn't set them blank.
161 if (strncmp(strtrim(oaddr), e->oaddr, USERS_OFFICE_ADDR_SIZE - 1) &&
162 (*oaddr || fmodby != id))
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);
170 if (strncmp(strtrim(ophone), e->ophone, USERS_OFFICE_PHONE_SIZE - 1) &&
171 (*ophone || fmodby != id))
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);
179 if (strncmp(strtrim(haddr), e->haddr, USERS_HOME_ADDR_SIZE - 1) &&
180 (*haddr || fmodby != id))
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);
188 if (strncmp(strtrim(hphone), e->hphone, USERS_HOME_PHONE_SIZE - 1) &&
189 (*hphone || fmodby != id))
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);
197 if (strncmp(strtrim(dept), e->dept, USERS_DEPARTMENT_SIZE - 1) &&
198 (*dept || fmodby != id))
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);
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;
221 dbmserr(NULL, sqlca.sqlcode);
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;
235 dbmserr(NULL, sqlca.sqlcode);
241 void newuser(struct entry *e, int secure)
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;
253 users_id = set_next_users_id();
254 uid = set_next_uid();
255 sprintf(login, "#%d", uid);
256 if (!strcmp(e->type, "LINCOLN"))
257 st = US_NO_LOGIN_YET_KERBEROS_ONLY;
259 st = US_NO_LOGIN_YET;
272 xaddress = e->xaddress;
273 xphone1 = e->xphone1;
274 xphone2 = e->xphone2;
276 com_err(whoami, 0, "adding user %s %s", e->first, e->last);
278 EXEC SQL INSERT INTO users
279 (login, users_id, unix_uid, shell, winconsoleshell, last, first,
280 middle, status, clearid, type, modtime, modby, modwith, fullname,
281 department, home_addr, home_phone, office_addr, office_phone, fmodtime,
282 fmodby, fmodwith, potype, pmodtime, pmodby, pmodwith,
283 xname, xdept, xtitle, xaddress, xphone1, xphone2, xmodtime, secure,
284 created, creator, winhomedir, winprofiledir, sponsor_type, sponsor_id, expiration)
285 VALUES (:login, :users_id, :uid, '/bin/athena/tcsh', 'cmd',
286 NVL(:last, CHR(0)), NVL(:first, CHR(0)), NVL(:middle, CHR(0)),
287 :st, NVL(:id, CHR(0)), NVL(:type, CHR(0)), SYSDATE, :who, :prog,
288 NVL(:name, CHR(0)), NVL(:dept, CHR(0)), NVL(:haddr, CHR(0)),
289 NVL(:hphone, CHR(0)), NVL(SUBSTR(:oaddr, 0, :oadlen), CHR(0)),
290 NVL(SUBSTR(:ophone, 0, :ophlen), CHR(0)), SYSDATE, :who, :prog,
291 'NONE', SYSDATE, :who, :prog,
292 NVL(SUBSTR(:name, 0, :xnlen), CHR(0)), NVL(:dept, CHR(0)),
293 NVL(:xtitle, CHR(0)), NVL(:xaddress, CHR(0)),
294 NVL(:xphone1, CHR(0)), NVL(:xphone2, CHR(0)), SYSDATE, :issecure,
295 SYSDATE, :who, '[DFS]', '[DFS]', 'NONE', 0, CHR(0));
298 dbmserr("adding user", sqlca.sqlcode);
303 int set_next_users_id(void)
305 EXEC SQL BEGIN DECLARE SECTION;
306 int flag, value, retval;
307 EXEC SQL END DECLARE SECTION;
309 EXEC SQL SELECT value INTO :value FROM numvalues
310 WHERE name = 'users_id';
313 if (sqlca.sqlerrd[2] != 1)
316 com_err(whoami, MR_INTERNAL, "values table inconsistancy");
321 EXEC SQL SELECT users_id INTO :flag FROM users
322 WHERE users_id = :value;
325 if (sqlca.sqlerrd[2] == 0)
331 EXEC SQL SELECT users_id INTO :flag FROM users
332 WHERE users_id = :value;
335 if (sqlca.sqlerrd[2] == 0)
340 EXEC SQL UPDATE numvalues SET value = :value
341 WHERE name = 'users_id';
344 dbmserr("assigning ID", sqlca.sqlcode);
350 int set_next_uid(void)
352 EXEC SQL BEGIN DECLARE SECTION;
353 int flag, initial, value, retval;
354 EXEC SQL END DECLARE SECTION;
356 EXEC SQL SELECT value INTO :initial FROM numvalues
357 WHERE name = 'unix_uid';
360 if (sqlca.sqlerrd[2] != 1)
363 com_err(whoami, MR_INTERNAL, "values table inconsistancy");
369 EXEC SQL SELECT COUNT(unix_uid) INTO :flag
370 FROM users WHERE unix_uid = :value;
373 if (sqlca.sqlerrd[2] == 0)
378 #ifdef ULTRIX_ID_HOLE
379 if (value > 31999 && value < 32768)
382 if (value > MAX_ID_VALUE)
383 value = MIN_ID_VALUE;
384 if (value == initial)
386 com_err(whoami, 0, "Out of uids!");
387 EXEC SQL ROLLBACK WORK;
391 EXEC SQL SELECT COUNT(unix_uid) INTO :flag
392 FROM users WHERE unix_uid = :value;
398 if (value > MAX_ID_VALUE)
399 value = MIN_ID_VALUE;
400 EXEC SQL UPDATE numvalues SET value = :value WHERE name = 'unix_uid';
403 dbmserr("assigning ID", sqlca.sqlcode);
411 dbmserr(NULL, sqlca.sqlcode);
412 EXEC SQL ROLLBACK WORK;
416 void dbmserr(char *where, int what)
419 int bufsize = 256, msglength = 0;
421 sqlglm(err_msg, &bufsize, &msglength);
422 err_msg[msglength] = '\0';
425 com_err(whoami, 0, "DBMS error %swhile %s", err_msg, where);
427 com_err(whoami, 0, "DBMS error %s", err_msg);