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

Revision 23740, 11.5 KB checked in by broder, 16 years ago (diff)
In moira: * New CVS snapshot (Trac: #195) * Drop patches that have been incorporated upstream. * Update to build without krb4 on systems that no longer have it. This doesn't build yet on squeeze, which lacks a krb4 library, but I'm committing now before I start hacking away at a patch to fix that.
Line 
1/* $Id: common.pc,v 1.12 2009-03-31 19:13:20 zacheiss Exp $
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
19EXEC SQL INCLUDE sqlca;
20extern void sqlglm(char *, unsigned int *, unsigned int *);
21
22RCSID("$Header: /afs/athena.mit.edu/astaff/project/moiradev/repository/moira/regtape/common.pc,v 1.12 2009-03-31 19:13:20 zacheiss Exp $");
23
24EXEC SQL BEGIN DECLARE SECTION;
25extern char *prog;
26extern int who;
27EXEC SQL END DECLARE SECTION;
28
29extern char *whoami;
30
31#define MIN_ID_VALUE 100
32#define MAX_ID_VALUE 131072
33
34/* Remove non-digits from a phone number. */
35void 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. */
49void fixaddress(char *address)
50{
51  char *p;
52
53  while ((p = strchr(address, ',')))
54    *p = ';';
55  while ((p = strchr(address, ':')))
56    *p = ';';
57
58
59void 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
241void 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();
255  sprintf(login, "#%d", uid);
256  if (!strcmp(e->type, "LINCOLN"))
257    st = US_NO_LOGIN_YET_KERBEROS_ONLY;
258  else
259    st = US_NO_LOGIN_YET;
260  last = e->last;
261  first = e->first;
262  middle = e->middle;
263  id = e->id;
264  type = e->type;
265  name = e->name;
266  dept = e->dept;
267  haddr = e->haddr;
268  hphone = e->hphone;
269  oaddr = e->oaddr;
270  ophone = e->ophone;
271  xtitle = e->xtitle;
272  xaddress = e->xaddress;
273  xphone1 = e->xphone1;
274  xphone2 = e->xphone2;
275
276  com_err(whoami, 0, "adding user %s %s", e->first, e->last);
277
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/bash', '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));
296  if (sqlca.sqlcode)
297    {
298      dbmserr("adding user", sqlca.sqlcode);
299      exit(1);
300    }
301}
302
303int set_next_users_id(void)
304{
305  EXEC SQL BEGIN DECLARE SECTION;
306  int flag, value, retval;
307  EXEC SQL END DECLARE SECTION;
308
309  EXEC SQL SELECT value INTO :value FROM numvalues
310    WHERE name = 'users_id';
311  if (sqlfail())
312    sqlexit();
313  if (sqlca.sqlerrd[2] != 1)
314    {
315      EXEC SQL ROLLBACK;
316      com_err(whoami, MR_INTERNAL, "values table inconsistancy");
317      exit(1);
318    }
319
320  flag = 0;
321  EXEC SQL SELECT users_id INTO :flag FROM users
322    WHERE users_id = :value;
323  if (sqlfail())
324    sqlexit();
325  if (sqlca.sqlerrd[2] == 0)
326    flag = 0;
327  while (flag)
328    {
329      value++;
330      flag = 0;
331      EXEC SQL SELECT users_id INTO :flag FROM users
332        WHERE users_id = :value;
333      if (sqlfail())
334        sqlexit();
335      if (sqlca.sqlerrd[2] == 0)
336        flag = 0;
337    }
338
339  retval = value++;
340  EXEC SQL UPDATE numvalues SET value = :value
341    WHERE name = 'users_id';
342  if (sqlca.sqlcode)
343    {
344      dbmserr("assigning ID", sqlca.sqlcode);
345      exit(1);
346    }
347  return retval;
348}
349
350int set_next_uid(void)
351{
352  EXEC SQL BEGIN DECLARE SECTION;
353  int flag, initial, value, retval;
354  EXEC SQL END DECLARE SECTION;
355
356  EXEC SQL SELECT value INTO :initial FROM numvalues
357    WHERE name = 'unix_uid';
358  if (sqlfail())
359    sqlexit();
360  if (sqlca.sqlerrd[2] != 1)
361    {
362      EXEC SQL ROLLBACK;
363      com_err(whoami, MR_INTERNAL, "values table inconsistancy");
364      exit(1);
365    }
366
367  value = initial;
368  flag = 0;
369  EXEC SQL SELECT COUNT(unix_uid) INTO :flag
370    FROM users WHERE unix_uid = :value;
371  if (sqlfail())
372    sqlexit();
373  if (sqlca.sqlerrd[2] == 0)
374    flag = 0;
375  while (flag)
376    {
377      value++;
378#ifdef ULTRIX_ID_HOLE
379      if (value > 31999 && value < 32768)
380        value = 32768;
381#endif
382      if (value > MAX_ID_VALUE)
383        value = MIN_ID_VALUE;
384      if (value == initial)
385        {
386          com_err(whoami, 0, "Out of uids!");
387          EXEC SQL ROLLBACK WORK;
388          exit(1);
389        }
390      flag = 0;
391      EXEC SQL SELECT COUNT(unix_uid) INTO :flag
392        FROM users WHERE unix_uid = :value;
393      if (sqlfail())
394        sqlexit();
395    }
396
397  retval = value++;
398  if (value > MAX_ID_VALUE)
399    value = MIN_ID_VALUE;
400  EXEC SQL UPDATE numvalues SET value = :value WHERE name = 'unix_uid';
401  if (sqlca.sqlcode)
402    {
403      dbmserr("assigning ID", sqlca.sqlcode);
404      exit(1);
405    }
406  return retval;
407}
408
409void sqlexit(void)
410{
411  dbmserr(NULL, sqlca.sqlcode);
412  EXEC SQL ROLLBACK WORK;
413  exit(1);
414}
415
416void dbmserr(char *where, int what)
417{
418  char err_msg[256];
419  int bufsize = 256, msglength = 0;
420
421  sqlglm(err_msg, &bufsize, &msglength);
422  err_msg[msglength] = '\0';
423
424  if (where)
425    com_err(whoami, 0, "DBMS error %swhile %s", err_msg, where);
426  else
427    com_err(whoami, 0, "DBMS error %s", err_msg);
428}
Note: See TracBrowser for help on using the repository browser.