]> andersk Git - moira.git/blob - afssync/sync.dc
Initial revision
[moira.git] / afssync / sync.dc
1 /* $Header$
2  *
3  *
4  *  (c) Copyright 1989 by the Massachusetts Institute of Technology.
5  *  For copying and distribution information, please see the file
6  *  <mit-copyright.h>.
7  */
8
9 #include <mit-copyright.h>
10 #include <stdio.h>
11 #include <sys/file.h>
12 #include <strings.h>
13
14 #include <rx/xdr.h>
15 #include "ptint.h"
16 #include "ptserver.h"
17 #include "pterror.h"
18
19 #include <moira.h>
20 #include <moira_site.h>
21 #include <ctype.h>
22
23 /* The following enables the processing of .root instances */
24 #define DO_KERBEROS
25
26 EXEC SQL INCLUDE sqlca;
27
28 EXEC SQL BEGIN DECLARE SECTION;
29 char db[33] = "moira";
30 EXEC SQL END DECLARE SECTION;
31
32 #define min(x,y)        ((x) < (y) ? (x) : (y))
33 char *whoami = "sync";
34
35 int dbase_fd;
36
37 int ucount = 0;
38 int gcount = 0;
39 int kcount = 0;
40 int mcount = 0;
41
42 struct hash *users;
43 struct hash *groups;
44 #ifdef DO_KERBEROS
45 struct hash *strings;
46 #endif
47
48 struct member {
49     struct entry *user;
50     struct entry *group;
51     struct member *unext;
52     struct member *gnext;
53 };
54 struct entry {
55     long id;
56     struct member *members;
57 };
58
59 main(argc, argv)
60 int argc;
61 char **argv;
62 {
63     int status;
64     long t;
65
66     if (argc > 2 && !strcmp(argv[1], "-db")) {
67         strncpy(db, argv[2], sizeof(db)-1);
68         argc -= 2;
69         argv += 2;
70     }
71     if (argc != 2) {
72         fprintf(stderr, "usage: %s [-db moira] outfile\n", whoami);
73         exit(MR_ARGS);
74     }
75
76     dbase_fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0660);
77     if (dbase_fd < 0) {
78         perror("opening file %s", argv[1]);
79         exit(1);
80     }
81
82     initialize_sms_error_table();
83     initialize_pt_error_table();
84     Initdb();                                   /* Initialize prdb */
85     setlinebuf(stdout);
86     
87     users = create_hash(10000);
88     groups = create_hash(15000);
89 #ifdef DO_KERBEROS
90     strings = create_hash(1000);
91 #endif
92
93     EXEC SQL WHENEVER SQLERROR CALL sqlerr;
94 #ifsql INGRES
95     EXEC SQL CONNECT :db;
96     EXEC SQL SET LOCKMODE SESSION WHERE LEVEL=TABLE, READLOCK=SHARED;
97 #endsql
98 #ifsql INFORMIX
99     EXEC SQL DATABASE :db;
100 #endsql
101
102     do_passwd();
103     do_groups();
104
105     t = time(0);
106     fprintf(stderr, "Done (%d users, %d groups, %d kerberos, %d members): %s",
107             ucount, gcount, kcount, mcount, ctime(&t));
108
109 #ifsql INGRES
110     EXEC SQL DISCONNECT;
111 #endsql
112 #ifsql INFORMIX
113     EXEC SQL CLOSE DATABASE;
114 #endsql
115
116     exit(MR_SUCCESS);
117 }
118
119
120 do_passwd()
121 {
122     EXEC SQL BEGIN DECLARE SECTION;
123     char login[9], name[33];
124     int uid, id, status;
125     EXEC SQL END DECLARE SECTION;
126
127     long t;
128     struct prentry tentry;
129     struct entry *u;
130
131     t = time(0);
132     fprintf(stderr, "Doing users: %s", ctime(&t));
133
134     /* get locks */
135     EXEC SQL SELECT modtime INTO :name FROM users WHERE users_id = 0;
136     
137     EXEC SQL DECLARE u_cursor CURSOR FOR
138         SELECT u.login, u.uid, u.users_id
139         FROM users u
140         WHERE u.uid > 0 AND (u.status = 1 OR u.status = 2)
141         ORDER BY uid;
142     EXEC SQL OPEN u_cursor;
143     while (1) {
144         EXEC SQL FETCH u_cursor INTO :login, :uid, :id;
145         if (sqlca.sqlcode != 0) break;
146         
147         lowercase(strtrim(login));
148
149         if (FindByID(0,uid))
150             status = PRIDEXIST;
151         else
152             status = CreateEntry(0,login,&uid,1 /*idflag*/,0/*gflag*/,
153                                  SYSADMINID     /*oid*/, SYSADMINID/*cid*/);
154         if (status)
155             fprintf(stderr, "Error adding user %s uid %d: %s\n",
156                     login, uid, error_message(status));
157         else {
158             u = (struct entry *)malloc(sizeof(struct entry));
159             u->id = uid;
160             u->members = 0;
161             hash_store(users, id, u);
162             ucount++;
163         }
164     }
165     EXEC SQL CLOSE u_cursor;
166     return;
167 }
168
169
170
171 do_groups()
172 {
173     EXEC SQL BEGIN DECLARE SECTION;
174     char name[33], string[129];
175     int gid, id, lid, hide, ustatus;
176     EXEC SQL END DECLARE SECTION;
177
178     long status, pos;
179     struct prentry gentry, uentry;
180     struct entry *u, *g;
181     struct member *m;
182     struct bucket **p, *b;
183     char namebuf[40];
184     long aid, t;
185
186     t = time(0);
187     fprintf(stderr, "Doing groups: %s", ctime(&t));
188
189     /* get locks */
190     EXEC SQL SELECT modtime INTO :name FROM list WHERE list_id = 0;
191
192     EXEC SQL DECLARE l_cursor CURSOR FOR
193         SELECT l.name, l.gid, l.list_id, l.hidden
194         FROM list l
195         WHERE l.gid > 0 AND l.active != 0 AND l.grouplist != 0
196         ORDER BY gid;
197     EXEC SQL OPEN l_cursor;
198     while (1) {
199         EXEC SQL FETCH l_cursor INTO :name, :gid, :lid, :hide;
200         if (sqlca.sqlcode != 0) break;
201         
202         lowercase(strtrim(name));
203         sprintf(namebuf, "system:%s", name);
204         aid = -gid;
205
206         if (FindByID(0, aid))
207             status = PRIDEXIST;
208         else
209             status = CreateEntry(0,namebuf,&aid,1 /*idflag*/,PRGRP/*gflag*/,
210                                  SYSADMINID     /*oid*/, SYSADMINID/*cid*/);
211         if (status)
212             fprintf(stderr, "Error adding group %s id %d: %s\n",
213                     namebuf, aid, error_message(status));
214
215         if ((status==0 || status==PRIDEXIST) &&
216             (aid!=ANYUSERID && aid!=AUTHUSERID)) {
217
218             g = (struct entry *)malloc(sizeof(struct entry));
219             g->id = aid;
220             g->members = 0;
221             hash_store(groups, lid, g);
222             gcount++;
223
224             /* Set modes on hidden lists (S----) */
225             if (hide) {
226                 pos = FindByID(0, aid);
227                 status = pr_Read(0, 0, pos, &gentry, sizeof(gentry));
228                 if (!status) {
229                     gentry.flags = htonl(PRGRP|PRACCESS|PRP_STATUS_ANY);
230                     status = pr_Write(0, 0, pos, &gentry, sizeof(gentry));
231                 }
232                 if (status)
233                     fprintf(stderr,
234                             "Error setting flags on group %s: %s\n",
235                             namebuf, error_message(status));
236             }
237         }
238     }
239     EXEC SQL CLOSE l_cursor;
240
241     t = time(0);
242     fprintf(stderr, "Reading/preparing members: %s", ctime(&t));
243
244     EXEC SQL DECLARE m_cursor CURSOR FOR
245         SELECT m.list_id, m.member_id, m.member_type
246         FROM imembers m
247         ORDER BY member_id;
248     EXEC SQL OPEN m_cursor;
249     while (1) {
250         EXEC SQL FETCH m_cursor INTO :lid, :id, :name;
251         if (sqlca.sqlcode != 0) break;
252
253         if (!(g = (struct entry *)hash_lookup(groups, lid)))
254             continue;
255
256         strtrim(name);
257         if (!strcmp(name, "USER")) {
258             if (u = (struct entry *)hash_lookup(users, id)) {
259                 m = (struct member *)malloc(sizeof(struct member));
260                 m->user = u;
261                 m->group = g;
262                 m->unext = u->members;
263                 m->gnext = g->members;
264                 u->members = g->members = m;
265                 mcount++;
266             }
267         }
268 #ifdef DO_KERBEROS
269         else if (!strcmp(name, "KERBEROS")) {
270             if (!(u = (struct entry *)hash_lookup(strings, id))) {
271                 char *p;
272                 
273                 EXEC SQL SELECT string INTO :string
274                     FROM strings WHERE string_id = :id;
275
276                 aid = 0;
277                 strtrim(string);
278
279                 if (p = (char *)index(string, '@')) {
280                     *p = 0;
281                     if (strcmp(p+1, "ATHENA.MIT.EDU")) aid = -1;
282                 } else aid = -1;
283
284                 if ((p = (char *)index(string, '.')) && (p-string) < 9 &&
285                     !strcmp(p+1, "root"))
286                 {
287                     strncpy(name, string, p-string);
288                     name[p-string] = 0;
289                 } else aid = -1;
290
291                 if (aid == 0) {
292                     EXEC SQL DECLARE k_cursor2 CURSOR FOR
293                         SELECT uid, status
294                         FROM users
295                         WHERE login = :name
296                         ORDER BY uid;
297                     EXEC SQL OPEN k_cursor2;
298                     while (1) {
299                         if (sqlca.sqlcode) break;
300                         EXEC SQL FETCH k_cursor2 INTO :lid, :ustatus;
301                         if (ustatus==1 || ustatus==2) aid = lid+65536;
302                     }
303                     EXEC SQL CLOSE k_cursor2;
304                 }
305
306                 if (aid > 0) {
307                     if (FindByID(0,aid))
308                         status = PRIDEXIST;
309                     else
310                         status = CreateEntry(0, string, &aid, 1 /*idflag*/,
311                                              0 /*gflag*/, SYSADMINID /*oid*/,
312                                              SYSADMINID /*cid */);
313                     if (status) {
314                         fprintf(stderr, "Error adding %s (id %d): %s\n",
315                                 string, aid, error_message(status));
316                         if (status != PRIDEXIST) aid = 0;
317                     }
318                 } else
319                     aid = 0;
320             
321                 u = (struct entry *)malloc(sizeof(struct entry));
322                 u->id = aid;
323                 u->members = 0;
324                 hash_store(strings, id, u);
325                 if (aid) kcount++;
326             }
327             if (u->id == 0) continue;
328
329             m = (struct member *)malloc(sizeof(struct member));
330             m->user = u;
331             m->group = g;
332             m->unext = u->members;
333             m->gnext = g->members;
334             u->members = g->members = m;
335             mcount++;
336         }
337 #endif
338     }
339     EXEC SQL CLOSE m_cursor;
340
341     t = time(0);
342     fprintf(stderr, "Doing members: %s", ctime(&t));
343
344     /* Do the bulk of the membership quickly.
345      * Add PRSIZE members into the user/group record.  After that, we
346      * require the use of continuation records, but we assume this is
347      * few enough that we do this the slow way (AddToEntry).
348      */
349     for (p = &(users->data[users->size - 1]); p >= users->data; p--) {
350         for (b = *p; b; b = b->next) {
351             if ((u = (struct entry *)b->data)->members == 0)
352                 continue;
353             pos = FindByID(0, u->id);
354             pr_Read(0, 0, pos, &uentry, sizeof(uentry));
355             for (t=0, m=u->members; m && t<PRSIZE; m=m->unext, t++)
356                 uentry.entries[t] = htonl(m->group->id);
357             uentry.count = htonl(t);
358             pr_Write(0, 0, pos, &uentry, sizeof(uentry));
359             if (m) {
360                 pr_ReadEntry(0, 0, pos, &uentry);
361                 while (m) {
362                     AddToEntry(0, &uentry, pos, m->group->id);
363                     m = m->unext;
364                 }
365             }
366         }
367     }
368 #ifdef DO_KERBEROS
369     for (p = &(strings->data[strings->size - 1]); p >= strings->data; p--) {
370         for (b = *p; b; b = b->next) {
371             if ((u = (struct entry *)b->data)->members == 0)
372                 continue;
373             pos = FindByID(0, u->id);
374             pr_Read(0, 0, pos, &uentry, sizeof(uentry));
375             for (t=0, m=u->members; m && t<PRSIZE; m=m->unext, t++)
376                 uentry.entries[t] = htonl(m->group->id);
377             uentry.count = htonl(t);
378             pr_Write(0, 0, pos, &uentry, sizeof(uentry));
379             if (m) {
380                 pr_ReadEntry(0, 0, pos, &uentry);
381                 while (m) {
382                     AddToEntry(0, &uentry, pos, m->group->id);
383                     m = m->unext;
384                 }
385             }
386         }
387     }
388 #endif
389     for (p = &(groups->data[groups->size - 1]); p >= groups->data; p--) {
390         for (b = *p; b; b = b->next) {
391             if ((g = (struct entry *)b->data)->members == 0)
392                 continue;
393             pos = FindByID(0, g->id);
394             pr_Read(0, 0, pos, &gentry, sizeof(gentry));
395             for (t=0, m=g->members; m && t<PRSIZE; m=m->gnext, t++)
396                 gentry.entries[t] = htonl(m->user->id);
397             gentry.count = htonl(t);
398             pr_Write(0, 0, pos, &gentry, sizeof(gentry));
399             if (m) {
400                 pr_ReadEntry(0, 0, pos, &gentry);
401                 while (m) {
402                     AddToEntry(0, &gentry, pos, m->user->id);
403                     m = m->gnext;
404                 }
405             }
406         }
407     }
408     return;
409 }
410
411     
412 sqlerr()
413 {
414     com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
415     exit(MR_INGRES_ERR);
416 }
This page took 0.061746 seconds and 5 git commands to generate.