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