source: trunk/third/moira/afssync/sync.pc @ 24319

Revision 24319, 7.3 KB checked in by broder, 14 years ago (diff)
New Moira snapshot from SVN.
Line 
1/* $Id: sync.pc 3956 2010-01-05 20:56:56Z zacheiss $
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/* PRO*C gets heartburn from variadic macro in rx/rx_prototypes.h, so hide it. */
16#ifndef _PROC_
17#include "ptint.h"
18#include "ptserver.h"
19#endif
20#include "pterror.h"
21
22#include <moira.h>
23#include <moira_site.h>
24#include <ctype.h>
25
26RCSID("$HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/afssync/sync.pc $ $Id: sync.pc 3956 2010-01-05 20:56:56Z zacheiss $");
27
28EXEC SQL INCLUDE sqlca;
29
30EXEC SQL BEGIN DECLARE SECTION;
31char db[33] = "moira";
32EXEC SQL END DECLARE SECTION;
33
34void do_passwd(void);
35void do_groups(void);
36void sqlerr(void);
37
38#ifndef min
39#define min(x,y)        ((x) < (y) ? (x) : (y))
40#endif
41char *whoami = "sync";
42
43int dbase_fd;
44
45int ucount = 0;
46int gcount = 0;
47int kcount = 0;
48int mcount = 0;
49
50struct hash *users;
51struct hash *groups;
52
53struct member {
54    struct entry *user;
55    struct entry *group;
56    struct member *unext;
57    struct member *gnext;
58};
59struct entry {
60    long id;
61    struct member *members;
62};
63
64int main(int argc, char **argv)
65{
66    int status;
67    long t;
68
69    setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
70
71    if (argc > 2 && !strcmp(argv[1], "-db")) {
72        strncpy(db, argv[2], sizeof(db)-1);
73        argc -= 2;
74        argv += 2;
75    }
76    if (argc != 2) {
77        fprintf(stderr, "usage: %s [-db moira] outfile\n", whoami);
78        exit(MR_ARGS);
79    }
80
81    dbase_fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0660);
82    if (dbase_fd < 0) {
83        perror("opening data file");
84        exit(1);
85    }
86
87    initialize_sms_error_table();
88    initialize_pt_error_table();
89    Initdb();                                   /* Initialize prdb */
90   
91    users = create_hash(10000);
92    groups = create_hash(15000);
93
94    EXEC SQL WHENEVER SQLERROR DO sqlerr();
95    EXEC SQL CONNECT :db IDENTIFIED BY :db;
96
97    do_passwd();
98    do_groups();
99
100    t = time(0);
101    fprintf(stderr, "Done (%d users, %d groups, %d kerberos, %d members): %s",
102            ucount, gcount, kcount, mcount, ctime(&t));
103
104    EXEC SQL COMMIT;
105
106    exit(MR_SUCCESS);
107}
108
109
110void do_passwd(void)
111{
112    EXEC SQL BEGIN DECLARE SECTION;
113    char login[9], name[33];
114    int uid, id, status;
115    EXEC SQL END DECLARE SECTION;
116
117    long t;
118    struct prentry tentry;
119    struct entry *u;
120
121    t = time(0);
122    fprintf(stderr, "Doing users: %s", ctime(&t));
123
124    EXEC SQL DECLARE u_cursor CURSOR FOR
125        SELECT u.login, u.unix_uid, u.users_id
126        FROM users u
127        WHERE u.unix_uid > 0 AND (u.status = 1 OR u.status = 2)
128        ORDER BY unix_uid;
129    EXEC SQL OPEN u_cursor;
130    while (1) {
131        EXEC SQL FETCH u_cursor INTO :login, :uid, :id;
132        if (sqlca.sqlcode != 0) break;
133       
134        lowercase(strtrim(login));
135
136        if (FindByID(0,uid))
137            status = PRIDEXIST;
138        else
139            status = CreateEntry(0,login,&uid,1 /*idflag*/,0/*gflag*/,
140                                 SYSADMINID     /*oid*/, SYSADMINID/*cid*/);
141        if (status)
142            fprintf(stderr, "Error adding user %s uid %d: %s\n",
143                    login, uid, error_message(status));
144        else {
145            u = (struct entry *)malloc(sizeof(struct entry));
146            u->id = uid;
147            u->members = 0;
148            hash_store(users, id, u);
149            ucount++;
150        }
151    }
152    EXEC SQL CLOSE u_cursor;
153    return;
154}
155
156
157
158void do_groups(void)
159{
160    EXEC SQL BEGIN DECLARE SECTION;
161    char name[33], string[129];
162    int gid, id, lid, hide, ustatus;
163    EXEC SQL END DECLARE SECTION;
164
165    long status, pos;
166    struct prentry gentry, uentry;
167    struct entry *u, *g;
168    struct member *m;
169    struct bucket **p, *b;
170    char namebuf[40];
171    long aid, t;
172
173    t = time(0);
174    fprintf(stderr, "Doing groups: %s", ctime(&t));
175
176    EXEC SQL DECLARE l_cursor CURSOR FOR
177        SELECT l.name, l.gid, l.list_id, l.hidden
178        FROM list l
179        WHERE l.gid > 0 AND l.active != 0 AND l.grouplist != 0
180        ORDER BY gid;
181    EXEC SQL OPEN l_cursor;
182    while (1) {
183        EXEC SQL FETCH l_cursor INTO :name, :gid, :lid, :hide;
184        if (sqlca.sqlcode != 0) break;
185       
186        lowercase(strtrim(name));
187        sprintf(namebuf, "system:%s", name);
188        aid = -gid;
189
190        if (FindByID(0, aid))
191            status = PRIDEXIST;
192        else
193            status = CreateEntry(0,namebuf,&aid,1 /*idflag*/,PRGRP/*gflag*/,
194                                 SYSADMINID     /*oid*/, SYSADMINID/*cid*/);
195        if (status)
196            fprintf(stderr, "Error adding group %s id %d: %s\n",
197                    namebuf, aid, error_message(status));
198
199        if ((status==0 || status==PRIDEXIST) &&
200            (aid!=ANYUSERID && aid!=AUTHUSERID)) {
201
202            g = (struct entry *)malloc(sizeof(struct entry));
203            g->id = aid;
204            g->members = 0;
205            hash_store(groups, lid, g);
206            gcount++;
207
208            /* Set modes on hidden lists (S----) */
209            if (hide) {
210                pos = FindByID(0, aid);
211                status = pr_Read(0, 0, pos, &gentry, sizeof(gentry));
212                if (!status) {
213                    gentry.flags = htonl(PRGRP|PRACCESS|PRP_STATUS_ANY);
214                    status = pr_Write(0, 0, pos, &gentry, sizeof(gentry));
215                }
216                if (status)
217                    fprintf(stderr,
218                            "Error setting flags on group %s: %s\n",
219                            namebuf, error_message(status));
220            }
221        }
222    }
223    EXEC SQL CLOSE l_cursor;
224
225    t = time(0);
226    fprintf(stderr, "Reading/preparing members: %s", ctime(&t));
227
228    EXEC SQL DECLARE m_cursor CURSOR FOR
229        SELECT m.list_id, m.member_id, m.member_type
230        FROM imembers m
231        ORDER BY member_id;
232    EXEC SQL OPEN m_cursor;
233    while (1) {
234        EXEC SQL FETCH m_cursor INTO :lid, :id, :name;
235        if (sqlca.sqlcode != 0) break;
236
237        if (!(g = (struct entry *)hash_lookup(groups, lid)))
238            continue;
239
240        strtrim(name);
241        if (!strcmp(name, "USER")) {
242            if (u = (struct entry *)hash_lookup(users, id)) {
243                m = (struct member *)malloc(sizeof(struct member));
244                m->user = u;
245                m->group = g;
246                m->unext = u->members;
247                m->gnext = g->members;
248                u->members = g->members = m;
249                mcount++;
250            }
251        }
252    }
253    EXEC SQL CLOSE m_cursor;
254
255    t = time(0);
256    fprintf(stderr, "Doing members: %s", ctime(&t));
257
258    /* Do the bulk of the membership quickly.
259     * Add PRSIZE members into the user/group record.  After that, we
260     * require the use of continuation records, but we assume this is
261     * few enough that we do this the slow way (AddToEntry).
262     */
263    for (p = &(users->data[users->size - 1]); p >= users->data; p--) {
264        for (b = *p; b; b = b->next) {
265            if ((u = (struct entry *)b->data)->members == 0)
266                continue;
267            pos = FindByID(0, u->id);
268            pr_Read(0, 0, pos, &uentry, sizeof(uentry));
269            for (t=0, m=u->members; m && t<PRSIZE; m=m->unext, t++)
270                uentry.entries[t] = htonl(m->group->id);
271            uentry.count = htonl(t);
272            pr_Write(0, 0, pos, &uentry, sizeof(uentry));
273            if (m) {
274                pr_ReadEntry(0, 0, pos, &uentry);
275                while (m) {
276                    AddToEntry(0, &uentry, pos, m->group->id);
277                    m = m->unext;
278                }
279            }
280        }
281    }
282    for (p = &(groups->data[groups->size - 1]); p >= groups->data; p--) {
283        for (b = *p; b; b = b->next) {
284            if ((g = (struct entry *)b->data)->members == 0)
285                continue;
286            pos = FindByID(0, g->id);
287            pr_Read(0, 0, pos, &gentry, sizeof(gentry));
288            for (t=0, m=g->members; m && t<PRSIZE; m=m->gnext, t++)
289                gentry.entries[t] = htonl(m->user->id);
290            gentry.count = htonl(t);
291            pr_Write(0, 0, pos, &gentry, sizeof(gentry));
292            if (m) {
293                pr_ReadEntry(0, 0, pos, &gentry);
294                while (m) {
295                    AddToEntry(0, &gentry, pos, m->user->id);
296                    m = m->gnext;
297                }
298            }
299        }
300    }
301    return;
302}
303
304   
305void sqlerr(void)
306{
307    char buf[256];
308    int size=256, len=0;
309
310    sqlglm(buf, &size, &len);
311    buf[len]='\0';
312    com_err(whoami, MR_DBMS_ERR, " code %d\n%s", sqlca.sqlcode, buf);
313    exit(MR_DBMS_ERR);
314}
Note: See TracBrowser for help on using the repository browser.