/* $Header$ * * * (c) Copyright 1989 by the Massachusetts Institute of Technology. * For copying and distribution information, please see the file * . */ #include #include #include #include #include #include "ptint.h" #include "ptserver.h" #include "pterror.h" #include #include #include EXEC SQL INCLUDE sqlca; EXEC SQL BEGIN DECLARE SECTION; char db[33] = "moira"; EXEC SQL END DECLARE SECTION; void do_passwd(void); void do_groups(void); void sqlerr(void); #ifndef min #define min(x,y) ((x) < (y) ? (x) : (y)) #endif char *whoami = "sync"; int dbase_fd; int ucount = 0; int gcount = 0; int kcount = 0; int mcount = 0; struct hash *users; struct hash *groups; struct member { struct entry *user; struct entry *group; struct member *unext; struct member *gnext; }; struct entry { long id; struct member *members; }; int main(int argc, char **argv) { int status; long t; setvbuf(stdout, NULL, _IOLBF, BUFSIZ); if (argc > 2 && !strcmp(argv[1], "-db")) { strncpy(db, argv[2], sizeof(db)-1); argc -= 2; argv += 2; } if (argc != 2) { fprintf(stderr, "usage: %s [-db moira] outfile\n", whoami); exit(MR_ARGS); } dbase_fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0660); if (dbase_fd < 0) { perror("opening data file"); exit(1); } initialize_sms_error_table(); initialize_pt_error_table(); Initdb(); /* Initialize prdb */ users = create_hash(10000); groups = create_hash(15000); EXEC SQL WHENEVER SQLERROR DO sqlerr(); EXEC SQL CONNECT :db IDENTIFIED BY :db; do_passwd(); do_groups(); t = time(0); fprintf(stderr, "Done (%d users, %d groups, %d kerberos, %d members): %s", ucount, gcount, kcount, mcount, ctime(&t)); EXEC SQL COMMIT; exit(MR_SUCCESS); } void do_passwd(void) { EXEC SQL BEGIN DECLARE SECTION; char login[9], name[33]; int uid, id, status; EXEC SQL END DECLARE SECTION; long t; struct prentry tentry; struct entry *u; t = time(0); fprintf(stderr, "Doing users: %s", ctime(&t)); EXEC SQL DECLARE u_cursor CURSOR FOR SELECT u.login, u.unix_uid, u.users_id FROM users u WHERE u.unix_uid > 0 AND (u.status = 1 OR u.status = 2) ORDER BY unix_uid; EXEC SQL OPEN u_cursor; while (1) { EXEC SQL FETCH u_cursor INTO :login, :uid, :id; if (sqlca.sqlcode != 0) break; lowercase(strtrim(login)); if (FindByID(0,uid)) status = PRIDEXIST; else status = CreateEntry(0,login,&uid,1 /*idflag*/,0/*gflag*/, SYSADMINID /*oid*/, SYSADMINID/*cid*/); if (status) fprintf(stderr, "Error adding user %s uid %d: %s\n", login, uid, error_message(status)); else { u = (struct entry *)malloc(sizeof(struct entry)); u->id = uid; u->members = 0; hash_store(users, id, u); ucount++; } } EXEC SQL CLOSE u_cursor; return; } void do_groups(void) { EXEC SQL BEGIN DECLARE SECTION; char name[33], string[129]; int gid, id, lid, hide, ustatus; EXEC SQL END DECLARE SECTION; long status, pos; struct prentry gentry, uentry; struct entry *u, *g; struct member *m; struct bucket **p, *b; char namebuf[40]; long aid, t; t = time(0); fprintf(stderr, "Doing groups: %s", ctime(&t)); EXEC SQL DECLARE l_cursor CURSOR FOR SELECT l.name, l.gid, l.list_id, l.hidden FROM list l WHERE l.gid > 0 AND l.active != 0 AND l.grouplist != 0 ORDER BY gid; EXEC SQL OPEN l_cursor; while (1) { EXEC SQL FETCH l_cursor INTO :name, :gid, :lid, :hide; if (sqlca.sqlcode != 0) break; lowercase(strtrim(name)); sprintf(namebuf, "system:%s", name); aid = -gid; if (FindByID(0, aid)) status = PRIDEXIST; else status = CreateEntry(0,namebuf,&aid,1 /*idflag*/,PRGRP/*gflag*/, SYSADMINID /*oid*/, SYSADMINID/*cid*/); if (status) fprintf(stderr, "Error adding group %s id %d: %s\n", namebuf, aid, error_message(status)); if ((status==0 || status==PRIDEXIST) && (aid!=ANYUSERID && aid!=AUTHUSERID)) { g = (struct entry *)malloc(sizeof(struct entry)); g->id = aid; g->members = 0; hash_store(groups, lid, g); gcount++; /* Set modes on hidden lists (S----) */ if (hide) { pos = FindByID(0, aid); status = pr_Read(0, 0, pos, &gentry, sizeof(gentry)); if (!status) { gentry.flags = htonl(PRGRP|PRACCESS|PRP_STATUS_ANY); status = pr_Write(0, 0, pos, &gentry, sizeof(gentry)); } if (status) fprintf(stderr, "Error setting flags on group %s: %s\n", namebuf, error_message(status)); } } } EXEC SQL CLOSE l_cursor; t = time(0); fprintf(stderr, "Reading/preparing members: %s", ctime(&t)); EXEC SQL DECLARE m_cursor CURSOR FOR SELECT m.list_id, m.member_id, m.member_type FROM imembers m ORDER BY member_id; EXEC SQL OPEN m_cursor; while (1) { EXEC SQL FETCH m_cursor INTO :lid, :id, :name; if (sqlca.sqlcode != 0) break; if (!(g = (struct entry *)hash_lookup(groups, lid))) continue; strtrim(name); if (!strcmp(name, "USER")) { if (u = (struct entry *)hash_lookup(users, id)) { m = (struct member *)malloc(sizeof(struct member)); m->user = u; m->group = g; m->unext = u->members; m->gnext = g->members; u->members = g->members = m; mcount++; } } } EXEC SQL CLOSE m_cursor; t = time(0); fprintf(stderr, "Doing members: %s", ctime(&t)); /* Do the bulk of the membership quickly. * Add PRSIZE members into the user/group record. After that, we * require the use of continuation records, but we assume this is * few enough that we do this the slow way (AddToEntry). */ for (p = &(users->data[users->size - 1]); p >= users->data; p--) { for (b = *p; b; b = b->next) { if ((u = (struct entry *)b->data)->members == 0) continue; pos = FindByID(0, u->id); pr_Read(0, 0, pos, &uentry, sizeof(uentry)); for (t=0, m=u->members; m && tunext, t++) uentry.entries[t] = htonl(m->group->id); uentry.count = htonl(t); pr_Write(0, 0, pos, &uentry, sizeof(uentry)); if (m) { pr_ReadEntry(0, 0, pos, &uentry); while (m) { AddToEntry(0, &uentry, pos, m->group->id); m = m->unext; } } } } for (p = &(groups->data[groups->size - 1]); p >= groups->data; p--) { for (b = *p; b; b = b->next) { if ((g = (struct entry *)b->data)->members == 0) continue; pos = FindByID(0, g->id); pr_Read(0, 0, pos, &gentry, sizeof(gentry)); for (t=0, m=g->members; m && tgnext, t++) gentry.entries[t] = htonl(m->user->id); gentry.count = htonl(t); pr_Write(0, 0, pos, &gentry, sizeof(gentry)); if (m) { pr_ReadEntry(0, 0, pos, &gentry); while (m) { AddToEntry(0, &gentry, pos, m->user->id); m = m->gnext; } } } } return; } void sqlerr(void) { char buf[256]; int size=256, len=0; sqlglm(buf, &size, &len); buf[len]='\0'; com_err(whoami, MR_DBMS_ERR, " code %d\n%s", sqlca.sqlcode, buf); exit(MR_DBMS_ERR); }