]>
Commit | Line | Data |
---|---|---|
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 | } |