source: trunk/third/moira/regtape/common.pc @ 24319

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