5 #include <mit-copyright.h>
13 #include <moira_site.h>
17 #define min(x,y) ((x) < (y) ? (x) : (y))
18 #define abs(x) (((x) > 0) ? (x) : -(x))
19 struct hash *users, *groups, *usersid, *groupsid;
20 char *whoami = "sync";
22 char *malloc(), *strsave(), *perm_malloc();
36 for (i = 1; i < argc; i++) {
37 if (argv[i][0] == '-') {
56 dbase_fd = open(file, i, 0660);
58 perror("opening file %s", file);
62 initialize_sms_error_table ();
65 ## set lockmode session where level = table
75 pr_Read(NULL, 0, 0, &prh, sizeof(prh));
76 check_users_and_groups();
84 fprintf(stderr, "usage: %s [-r] dbfile\n", name);
90 * ingerr: (supposedly) called when Ingres indicates an error.
91 * I have not yet been able to get this to work to intercept a
92 * database open error.
94 #define INGRES_DEADLOCK 4700
96 static int ingerr(num)
103 case INGRES_DEADLOCK:
104 ingres_errno = MR_DEADLOCK;
107 ingres_errno = MR_INGRES_ERR;
109 com_err(whoami, MR_INGRES_ERR, " code %d\n", *num);
114 prserror(status, msg, arg1, arg2)
117 unsigned long arg1, arg2;
121 sprintf(buf, msg, arg1, arg2);
124 msg = "name already exists";
127 msg = "ID already exists";
130 msg = "no IDs available";
133 msg = "database failed";
136 msg = "no space left in database";
139 msg = "permission denied";
154 msg = "unknown code";
157 fprintf(stderr, "%s (%d): %s\n", msg, status, buf);
164 fprintf(stderr, "Out of memory: %s\n", msg);
182 fprintf(stderr, "Loading users from Moira\n");
183 users = create_hash(10000);
184 usersid = create_hash(10000);
185 ## range of u is users
186 ## retrieve (login = u.#login, uid = u.#uid, id = u.users_id)
187 ## where u.#status = 1 {
189 u = (struct user *)perm_malloc(sizeof(struct user));
191 nomem("loading users");
192 strncpy(u->login, login, 9);
195 hash_store(users, uid, u);
196 hash_store(usersid, id, u);
203 short member[CHUNKSIZE];
222 fprintf(stderr, "Loading groups from Moira\n");
223 groups = create_hash(10000);
224 groupsid = create_hash(10000);
225 ## range of l is list
226 ## retrieve (name = l.#name, gid = l.#gid, id = l.list_id)
227 ## where l.#active = 1 and l.#group = 1 {
229 g = (struct group *)perm_malloc(sizeof(struct group));
231 nomem("loading groups");
232 bzero(g, sizeof(struct group));
233 strncpy(g->name, name, 33);
235 hash_store(groups, gid, g);
236 hash_store(groupsid, id, g);
247 fprintf(stderr, "Fetching members from Moira\n");
249 ## range of m is imembers
251 ## retrieve (lid = m.list_id, id = m.member_id)
252 ## where m.member_type = "USER" {
253 if ((u = (struct user *) hash_lookup(usersid, id)) &&
254 (g = (struct group *) hash_lookup(groupsid, lid))) {
255 if (g->members < CHUNKSIZE) {
256 g->ch.member[g->members] = u->uid;
258 int i = g->members - CHUNKSIZE;
261 if ((c = g->ch.xmem) == NULL) {
262 c = (struct chunk *) perm_malloc(sizeof(struct chunk));
264 nomem("loading members");
267 while (i >= CHUNKSIZE) {
269 if (c->xmem == NULL) {
270 c->xmem = (struct chunk *) perm_malloc(sizeof(struct chunk));
272 nomem("loading members");
276 c->member[i] = u->uid;
293 printf("< User %s id %d is in Moira but not in prs\n",
296 status = PR_INewEntry(NULL, u->login, u->uid, 0);
298 prserror(status, "adding user %s uid %d to prs database",
309 register int i, j, status;
313 printf("< Group %s id %d is in Moira but not in prs\n",
317 sprintf(namebuf, "system:%s", g->name);
318 status = PR_INewEntry(NULL, namebuf, -g->gid, SYSADMINID);
320 prserror(status, "adding list %s gid %d to prs database",
324 c = (struct chunk *)&(g->ch);
325 for (i = 0; i < g->members; i++) {
327 printf("< Group %s contains user %d in Moira but not in prs\n",
328 g->name, c->member[j]);
330 status = PR_AddToGroup(NULL, c->member[j], -g->gid);
332 prserror(status, "adding %d to group %d in prs",
333 c->member[j], -g->gid);
335 if (j == CHUNKSIZE - 1)
340 check_users_and_groups()
345 fprintf(stderr, "Scanning PRS database\n");
347 for (i = 0; i < HASHSIZE; i++) {
348 offset = ntohl(prh.idHash[i]);
350 offset = check_entry(offset);
352 hash_step(users, checkuser, NULL);
353 hash_step(groups, checkgroup, NULL);
359 struct prentry entry;
360 int flags, id, status;
364 status = pr_Read(NULL, 0, offset, &entry, sizeof(entry));
366 prserror(status, "reading prentry at %d", offset, 0);
367 flags = ntohl(entry.flags);
368 id = ntohl(entry.id);
369 if ((flags & PRFREE) == 0) {
371 g = (struct group *) hash_lookup(groups, abs(id));
373 if (!strncmp(entry.name, "system:", 7)) {
374 printf("> Group %s, id %d is in prs but not moira\n",
377 status = PR_Delete(NULL, id);
379 prserror(status, "deleting group %d from prs", id);
382 } else if (strcasecmp(g->name, index(entry.name, ':')+1)) {
383 printf("> GID %d in prs is %s, but GID %d in moira is %s\n",
384 id, entry.name, -id, g->name);
386 printf("*** Dont' know how to fix this!!!!!\n");
390 if (entry.entries[0])
391 do_members(&entry, g);
394 u = (struct user *) hash_lookup(users, abs(id));
396 printf("> User %s, id %d is in prs but not moira\n",
399 status = PR_Delete(NULL, id);
401 prserror(status, "while deleting user %d from prs", id);
403 } else if (strcasecmp(u->login, entry.name)) {
404 printf("> User id %d in prs is %s, but UID %d in moira is %s\n",
405 id, entry.name, id, u->login);
407 printf("*** don't know how to fix this!!!!!\n");
413 return(ntohl(entry.nextID));
423 struct contentry prco;
425 for (i = 0; i < PRSIZE; i++) {
426 if (e->entries[i] == 0)
428 mark_member(g, ntohl(e->entries[i]));
430 offset = ntohl(e->next);
432 pr_Read(NULL, 0, offset, &prco, sizeof(struct contentry));
433 for (i = 0; i < COSIZE; i++) {
434 if (prco.entries[i] == 0)
436 mark_member(g, ntohl(prco.entries[i]));
438 offset = ntohl(prco.next);
447 register int i, j, status;
451 if (g->members >= CHUNKSIZE) {
453 struct chunk *c = (struct chunk *)&(g->ch);
455 for (i = 0; i < g->members; i++) {
457 if (c->member[j] == uid) {
460 if (j == CHUNKSIZE - 1) {
461 s1 = c->member[CHUNKSIZE - 1];
465 if (j != CHUNKSIZE - 1)
472 printf("> Group %s contains user %d in prs but not in Moira\n", g->name,
475 status = PR_RemoveFromGroup(NULL, uid, -g->gid);
477 prserror(status, "While removing user %d from group %d in prs",
482 for (i = 0; i < g->members; i++) {
483 if (g->ch.member[i] == uid) {
484 if (g->members == i + 1)
487 g->ch.member[i] = g->ch.member[g->members];
488 g->ch.member[g->members] = 0;
494 printf("> Group %s contains user %d in prs but not in Moira\n", g->name,
497 status = PR_RemoveFromGroup(NULL, uid, -g->gid);
499 prserror(status, "While removing user %d from group %d in prs",
505 #define MALLOC_BLOCK 102400
507 char *perm_malloc(size)
510 static char *pool = NULL;
511 static unsigned pool_size = 0;
514 if (size > pool_size) {
515 pool = (char *) malloc(MALLOC_BLOCK);
516 pool_size = MALLOC_BLOCK;
520 pool = (char *)(((unsigned) (pool + 1)) & ~1);
521 pool_size -= (pool - ret);