/* $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 /* The following enables the processing of .root instances */ #define DO_KERBEROS EXEC SQL INCLUDE sqlca; EXEC SQL BEGIN DECLARE SECTION; char db[33] = "moira"; EXEC SQL END DECLARE SECTION; #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; #ifdef DO_KERBEROS struct hash *strings; #endif struct member { struct entry *user; struct entry *group; struct member *unext; struct member *gnext; }; struct entry { long id; struct member *members; }; main(argc, argv) 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); #ifdef DO_KERBEROS strings = create_hash(1000); #endif 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); } do_passwd() { 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; } do_groups() { 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++; } } #ifdef DO_KERBEROS else if (!strcmp(name, "KERBEROS")) { if (!(u = (struct entry *)hash_lookup(strings, id))) { char *p; EXEC SQL SELECT string INTO :string FROM strings WHERE string_id = :id; aid = 0; strtrim(string); if (p = (char *)index(string, '@')) { *p = 0; if (strcmp(p+1, "ATHENA.MIT.EDU")) aid = -1; } else aid = -1; if ((p = (char *)index(string, '.')) && (p-string) < 9 && !strcmp(p+1, "root")) { strncpy(name, string, p-string); name[p-string] = 0; } else aid = -1; if (aid == 0) { EXEC SQL DECLARE k_cursor2 CURSOR FOR SELECT unix_uid, status FROM users WHERE login = :name ORDER BY unix_uid; EXEC SQL OPEN k_cursor2; while (1) { if (sqlca.sqlcode) break; EXEC SQL FETCH k_cursor2 INTO :lid, :ustatus; if (ustatus==1 || ustatus==2) aid = lid+65536; } EXEC SQL CLOSE k_cursor2; } if (aid > 0) { if (FindByID(0,aid)) status = PRIDEXIST; else status = CreateEntry(0, string, &aid, 1 /*idflag*/, 0 /*gflag*/, SYSADMINID /*oid*/, SYSADMINID /*cid */); if (status) { fprintf(stderr, "Error adding %s (id %d): %s\n", string, aid, error_message(status)); if (status != PRIDEXIST) aid = 0; } } else aid = 0; u = (struct entry *)malloc(sizeof(struct entry)); u->id = aid; u->members = 0; hash_store(strings, id, u); if (aid) kcount++; } if (u->id == 0) continue; 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++; } #endif } 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; } } } } #ifdef DO_KERBEROS for (p = &(strings->data[strings->size - 1]); p >= strings->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; } } } } #endif 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; } sqlerr() { 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); }