/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ #include #include #include #include #include #include #ifdef AFS_NT40_ENV #include #endif #include #include #include #include #include #include #include #include #include "ptclient.h" #include "pterror.h" #include "ptuser.h" #include "ptprototypes.h" static char *whoami = "testpr"; static struct afsconf_dir *conf; /* cell info, set by MyBeforeProc */ static char conf_dir[100]; static char lcell[MAXCELLCHARS]; int ListUsedIds(struct cmd_syndesc *as, void *arock) { afs_int32 code; namelist lnames; idlist lids; int i, j; int group = 0; /* check groups */ int unused = 0; /* print unused */ int number = 100; /* check 100 ids */ afs_int32 startId = 1; afs_int32 maxId; int range; if (as->parms[0].items) startId = atoi(as->parms[0].items->data); if (as->parms[1].items) number = atoi(as->parms[1].items->data); if (as->parms[2].items) unused = 1; code = pr_Initialize(1, conf_dir, NULL); if (code) { afs_com_err(whoami, code, "initializing pruser"); exit(1); } if (startId < 0) { group = 1; code = pr_ListMaxGroupId(&maxId); if (code) { bad_max: afs_com_err(whoami, code, "getting maximum id"); exit(2); } if (startId < maxId) { fprintf(stderr, "Max group id is only %d.\n", maxId); exit(3); } } else { code = pr_ListMaxUserId(&maxId); if (code) goto bad_max; if (startId > maxId) { fprintf(stderr, "Max user id is only %d.\n", maxId); exit(3); } } range = abs(startId - maxId); range++; /* number that can be printed */ if (range < number) { fprintf(stderr, "Only %d ids to be checked.\n", range); number = range; } printf("Checking for %d %sused ids starting at %d.\n", number, (unused ? "un" : ""), startId); #define NUM 100 lids.idlist_val = malloc(sizeof(afs_int32) * NUM); lnames.namelist_len = 0; lnames.namelist_val = 0; while (number) { if (number < NUM) i = number; else i = NUM; for (j = 0; j < i; j++) { lids.idlist_val[j] = startId; if (group) startId--; else startId++; } lids.idlist_len = i; code = pr_IdToName(&lids, &lnames); if (code) { afs_com_err(whoami, code, "converting id to name"); exit(2); } for (j = 0; j < lnames.namelist_len; j++) { if (lids.idlist_val[j] == atoi(lnames.namelist_val[j])) { if (unused) printf("%s is free\n", lnames.namelist_val[j]); } else { if (!unused) printf("%s is id %d\n", lnames.namelist_val[j], lids.idlist_val[j]); } } number -= i; } if (lids.idlist_val) free(lids.idlist_val); if (lnames.namelist_val) free(lnames.namelist_val); return 0; } /* TestManyMembers - called with a number N. Try creating N users and N groups * and put all the users on one of the groups and one of the users on all the * groups. Also put many users on many groups. * * To keep track of this create an NxN matrix of membership and fill it in with * a function that looks like a quarter of a circle. That makes the first * group contain every user and the first user be a member of every group. */ int verbose; char callerName[PR_MAXNAMELEN]; afs_int32 callerId; afs_int32 lastGroup; /* id of last group created */ afs_int32 ownerUser; /* first created user */ char ownerUserName[PR_MAXNAMELEN]; /* " " " name */ int steepDropOff; /* precentage decreate in GroupLimit */ char *createPrefix; /* prefix for naming users&groups */ extern struct ubik_client *pruclient; /* initialized by pr_Initialize */ /* These variables form the state if this test */ int number; /* max number of members */ char *population; /* matrix of memberships */ afs_int32 *users; /* ids of users */ afs_int32 *groups; /* ids of groups */ afs_int32 *groupOwners; /* ids of owners of groups */ /* statistics */ int nUsers, nGroups, nAdds, nRems, nUDels, nGDels; int IdCmp(const void *a, const void *b) { if (*(afs_int32 *)a > *(afs_int32 *)b) { return 1; } else if (*(afs_int32 *)a == *(afs_int32 *)b) { return 0; } else /* (*a < *b) */ { return -1; } } static int sqr(int n) { return n * n; } static int GetGroupLimit(int N, int x) { int y; if ((x >= N) || (x < 0)) { printf("GetGroupLimit: input value out of range %d (%d)\n", x, N); exit(10); } if (steepDropOff) { /* Use exponential decrease */ int i; y = N; for (i = 0; i < x; i++) { y = (y * steepDropOff) / 100; /* parameter is a percentage */ if (y == 0) { y = 1; /* with a floor of 1 */ break; } } } else { /* Use a circle's third quadrant */ y = sqr(N - 1) - sqr(N - 1 - x); y = (int)(sqrt((double)y) + 0.5); /* round off */ y = N - y; } if ((y > N) || (y < 1)) { printf("filling value out of range: %d (%d) => %d\n", x, N, y); exit(11); } return y; } void CreateUser(int u) { afs_int32 code; prname name; afs_int32 id; sprintf(name, "%s%d", createPrefix, u); id = 0; code = pr_CreateUser(name, &id); if (code) { if (code == PREXIST) { code = pr_Delete(name); if (code == 0) { nUDels++; code = pr_CreateUser(name, &id); if (code == 0) { if (verbose) printf("RE-"); goto done; } } } afs_com_err(whoami, code, "couldn't create %s", name); exit(12); } done: if (verbose) printf("Creating user %s (%di)\n", name, id); users[u] = id; nUsers++; if (ownerUser == 0) { ownerUser = id; strcpy(ownerUserName, name); } } void CreateGroup(int g) { afs_int32 code; char name[PR_MAXNAMELEN + 1]; afs_int32 id = 0; afs_int32 owner = 0; char *ownerName = NULL; int ownerType; /* type of ownership */ static char *lastGroupPrefix; /* prefix used for type==2 */ /* At least 50 groups should be owned by another group to test long owner * chains during deletion. Also let's create some long owners of owners * lists. */ ownerType = random() % 3; if (!ownerUser) ownerType = 0; if (!lastGroup) ownerType = 0; switch (ownerType) { case 0: owner = callerId; ownerName = callerName; break; case 1: owner = ownerUser; ownerName = ownerUserName; break; case 2: owner = lastGroup; ownerName = lastGroupPrefix; break; } code = snprintf(name, sizeof(name), "%s:%s%d", ownerName, createPrefix, g); if (code >= sizeof(name)) { fprintf(stderr, "%s: generated group name is too long: %s:%s%d\n", whoami, ownerName, createPrefix, g); exit(13); } code = ubik_PR_NewEntry(pruclient, 0, name, PRGRP, owner, &id); if (code) { if (code == PREXIST) { code = pr_Delete(name); if (code == 0) { nGDels++; code = ubik_PR_NewEntry(pruclient, 0, name, PRGRP, owner, &id); if (code == 0) { if (verbose) printf("RE-"); goto done; } } } afs_com_err(whoami, code, "couldn't create %s w/ owner=%d", name, owner); exit(13); } done: if (verbose) printf("Creating group %s (%di)\n", name, id); groups[g] = id; groupOwners[g] = owner; nGroups++; if (!lastGroup || (ownerType == 2)) { lastGroup = id; lastGroupPrefix = ownerName; } } int DeleteRandomId(afs_int32 *list) { afs_int32 code; afs_int32 id; int j, k; int m; k = random(); /* random starting point */ for (j = 0; j < number; j++) { /* find an undeleted id */ m = (k + j) % number; if ((id = list[m])) { code = ubik_PR_Delete(pruclient, 0, id); if (code) { afs_com_err(whoami, code, "Couldn't delete %di", id); exit(22); } list[m] = 0; if (list == users) nUDels++; else nGDels++; return 0; } } return -1; /* none left */ } void AddUser(int u, int g) { afs_int32 code; afs_int32 ui, gi; if (users[u] == 0) /* create if necessary */ CreateUser(u); if (groups[g] == 0) /* create group if necessary */ CreateGroup(g); ui = users[u]; gi = groups[g]; code = ubik_PR_AddToGroup(pruclient, 0, ui, gi); if (code) { afs_com_err(whoami, code, "couldn't add %d to %d", ui, gi); exit(14); } if (verbose) printf("Adding user (%di) to group (%di)\n", ui, gi); population[u * number + g]++; nAdds++; } void RemUser(int u, int g) { afs_int32 code; afs_int32 ui, gi; ui = users[u]; gi = groups[g]; code = ubik_PR_RemoveFromGroup(pruclient, 0, ui, gi); if (code) { afs_com_err(whoami, code, "couldn't remove %d from %d", ui, gi); exit(14); } if (verbose) printf("Removing user (%di) from group (%di)\n", ui, gi); population[u * number + g]--; nRems++; } int TestManyMembers(struct cmd_syndesc *as, void *arock) { char *filled; /* users filled up */ char *cleaned; /* users cleaned up */ int nFilled, nCleaned; int u, g, i, j, n; int seed; /* random number generator seed */ afs_int32 *glist; /* membership list */ afs_int32 code; code = pr_Initialize(1, conf_dir, NULL); if (code) { afs_com_err(whoami, code, "initializing pruser"); exit(1); } /* get name of person running command */ { struct ktc_principal afs, user; struct ktc_token token; strcpy(afs.name, "afs"); strcpy(afs.instance, ""); code = afsconf_GetLocalCell(conf, afs.cell, sizeof(afs.cell)); if (code) exit(2); code = ktc_GetToken(&afs, &token, sizeof(token), &user); if (code) { afs_com_err(whoami, code, "getting afs tokens"); exit(3); } if (strlen(user.instance) > 0) { fprintf(stderr, "can't handle non-null instance %s.%s\n", user.name, user.cell); exit(4); } if (strncmp(user.name, "AFS ID ", 7) == 0) { callerId = atoi(user.name + 7); code = pr_SIdToName(callerId, callerName); if (code) { afs_com_err(whoami, code, "call get name for id %d", callerId); exit(6); } } else { strcpy(callerName, user.name); code = pr_SNameToId(callerName, &callerId); if ((code == 0) && (callerId == ANONYMOUSID)) code = PRNOENT; } if (code) { afs_com_err(whoami, code, "can't find caller %s", callerName); exit(6); } else printf("Assuming caller is %s (%di)\n", callerName, callerId); } /* Parse arguments */ if (as->parms[0].items) number = atoi(as->parms[0].items->data); if (as->parms[1].items) { steepDropOff = atoi(as->parms[1].items->data); if ((steepDropOff < 0) || (steepDropOff > 100)) { fprintf(stderr, "Illegal value for dropoff: %d, must be between 0 and 100, inclusive.\n", steepDropOff); exit(7); } } else steepDropOff = 0; /* use quadratic dropoff */ if (as->parms[2].items) createPrefix = as->parms[2].items->data; else createPrefix = "u"; if (as->parms[3].items) verbose = 1; else verbose = 0; if (as->parms[4].items) seed = atoi(as->parms[4].items->data); else seed = 1; srandom(seed); users = calloc(number, sizeof(afs_int32)); groups = calloc(number, sizeof(afs_int32)); filled = calloc(number, sizeof(char)); cleaned = calloc(number, sizeof(char)); population = calloc(sqr(number), sizeof(char)); nFilled = 0; nCleaned = 0; ownerUser = lastGroup = 0; groupOwners = malloc(number * sizeof(afs_int32)); nUsers = nGroups = nAdds = nRems = nUDels = nGDels = 0; while ((nFilled < number) || (nCleaned < number)) { /* pick a user at random, using */ u = random() % number; if (!filled[u]) { n = GetGroupLimit(number, u); /* get group limit for that user */ g = random() % (n + 1); /* pick a random group */ if (g == n) { /* in a few cases create any user */ n = number; /* in the whole range */ g = random() % n; } for (i = 0; i < n; i++) { /* rotate until unused one found */ j = (g + i) % n; if (!population[u * number + j]) { /* add this user/group membership */ AddUser(u, j); goto added; } } filled[u]++; nFilled++; added:; } if (!cleaned[u]) { int base; if (filled[u]) { /* only clean above GroupLimit */ base = GetGroupLimit(number, u); n = number - base; if (n == 0) goto iscleaned; g = random() % n; } else { base = 0; n = number; /* pick a group from the whole range */ g = random() % 2 * n; /* at random for removal */ if (g >= n) goto remed; /* but half the time do nothing */ } for (i = 0; i < n; i++) { /* rotate until used one found */ j = (g + i) % n + base; if (population[u * number + j]) { /* remove this user/group membership */ RemUser(u, j); goto remed; } } if (filled[u]) { /* track finished ones */ iscleaned: cleaned[u]++; nCleaned++; } remed:; } } /* check the membership list of all users for correctness */ printf("Starting check of memberships\n"); glist = malloc(number * sizeof(afs_int32)); for (u = 0; u < number; u++) { afs_int32 ui = users[u]; if (ui) { int i; int ng; /* number groups */ int over; int (*proc)(struct ubik_client *, afs_int32, afs_int32, prlist *, afs_int32 *); prlist alist; alist.prlist_len = 0; alist.prlist_val = 0; if (random() & 4) { proc = ubik_PR_ListElements; } else { proc = ubik_PR_GetCPS; } code = (*proc)(pruclient, 0, ui, &alist, &over); if (code) { afs_com_err(whoami, code, "getting membership list of (%di) using %s", ui, (proc == ubik_PR_ListElements?"ListElements":"GetCPS")); exit(24); } if (over) { fprintf(stderr, "membership list for id %di too long\n", ui); } ng = 0; for (i = 0; i < number; i++) if (population[u * number + i]) glist[ng++] = groups[i]; qsort(glist, ng, sizeof(afs_int32), IdCmp); if (ng != (alist.prlist_len - ((proc == ubik_PR_GetCPS) ? 3 : 0))) { fprintf(stderr, "Membership list for %di of unexpected length: was %d but expected %d\n", ui, alist.prlist_len, ng); exit(20); } /* all the extra entries for the CPS should be at the end. */ code = 0; for (i = 0; i < ng; i++) if (alist.prlist_val[i] != glist[i]) { fprintf(stderr, "membership for %di not correct: was %di but expected %di\n", ui, alist.prlist_val[i], glist[i]); code++; } if (code) exit(21); if (proc == ubik_PR_GetCPS) { if ((alist.prlist_val[i /* =ng */ ] != AUTHUSERID) || (alist.prlist_val[++i] != ANYUSERID) || (alist.prlist_val[++i] != ui)) { fprintf(stderr, "CPS doesn't have extra entries\n"); exit(27); } } if (alist.prlist_val) free(alist.prlist_val); /* User 0 is a member of all groups all of which should also be on * the owner list of the caller or the ownerUser, although there * may also be others. Check this. */ if (u == 0) { prlist callerList; prlist ownerList; prlist lastGroupList; int i, j, k, l; if (ng != number) { fprintf(stderr, "User 0 not a member of all groups\n"); exit(26); } #define GETOWNED(xlist,xid) \ (xlist).prlist_val = 0; (xlist).prlist_len = 0; \ code = ubik_PR_ListOwned(pruclient, 0, (xid), &(xlist), &over); \ if (code) { \ afs_com_err (whoami, code, "getting owner list of (%di)", (xid)); \ exit (23); } \ if (over) \ { fprintf (stderr, "membership of id %di too long\n", (xid)); } GETOWNED(callerList, callerId); GETOWNED(ownerList, ownerUser); /* look for every entry in glist, in all the owner lists */ for (i = j = k = l = 0; i < number; i++) { while ((j < callerList.prlist_len) && (callerList.prlist_val[j] < glist[i])) j++; while ((k < ownerList.prlist_len) && (ownerList.prlist_val[k] < glist[i])) k++; #define PRLISTCMP(l,i) \ (((l).prlist_len == 0) || (glist[i] != (l).prlist_val[(i)])) if (PRLISTCMP(callerList, j) && PRLISTCMP(ownerList, k)) { for (l = 0; l < number; l++) { if (groups[l] == glist[i]) { if ((groupOwners[l] != callerId) && (groupOwners[l] != ownerUser)) { GETOWNED(lastGroupList, groupOwners[l]); if ((lastGroupList.prlist_len != 1) || (lastGroupList.prlist_val[0] != glist[i])) { fprintf(stderr, "Group (%di) not on any owner list\n", glist[i]); exit(25); } } goto foundLast; } } fprintf(stderr, "unexpected group %di\n", glist[i]); foundLast:; } } if (callerList.prlist_val) free(callerList.prlist_val); if (ownerList.prlist_val) free(ownerList.prlist_val); if (lastGroupList.prlist_val) free(lastGroupList.prlist_val); } } } /* cleanup by deleting all the users and groups */ printf("Starting deletion of users and groups\n"); for (i = 0; i < number; i++) { DeleteRandomId(users); DeleteRandomId(groups); } printf ("Created/deleted %d/%d users and %d/%d groups; added %d and removed %d.\n", nUsers, nUDels, nGroups, nGDels, nAdds, nRems); return 0; } /* from ka_ConvertBytes included here to avoid circularity */ /* Converts a byte string to ascii. Return the number of unconverted bytes. */ static int ka_ConvertBytes(char *ascii, /* output buffer */ int alen, /* buffer length */ char bs[], /* byte string */ int bl) /* number of bytes */ { int i; unsigned char c; alen--; /* make room for termination */ for (i = 0; i < bl; i++) { c = bs[i]; if (alen <= 0) return bl - i; if (isalnum(c) || ispunct(c)) (*ascii++ = c), alen--; else { if (alen <= 3) return bl - i; *ascii++ = '\\'; *ascii++ = (c >> 6) + '0'; *ascii++ = (c >> 3 & 7) + '0'; *ascii++ = (c & 7) + '0'; alen -= 4; } } *ascii = 0; /* terminate string */ return 0; } /* This runs various tests on the server. It creates, then deletes, a bunch of * users and groups, so it would be safest to run it on a test database. * * These are the things I check for: * User names longer than PR_MAXNAMELEN - strlen(cellname). * Group names longer than PR_MAXNAMELEN. * User names containing all legal 8-bit ascii characters. This excludes * only ':', '@', and '\n'. * Group names as above, but at least one colon is required, and the owner * must be correct. */ int TestPrServ(struct cmd_syndesc *as, void *arock) { afs_int32 id; char name[PR_MAXNAMELEN + 1]; char creator[PR_MAXNAMELEN]; /* our name */ struct prcheckentry ent; afs_int32 code; int i, j; int maxLen = PR_MAXNAMELEN - 1 - strlen(lcell) - 1; code = pr_Initialize(1, conf_dir, NULL); if (code) { afs_com_err(whoami, code, "initializing pruser"); exit(1); } for (i = 0; i < maxLen; i++) name[i] = 'a'; name[i] = 'a'; /* too long a name... */ name[i + 1] = 0; id = 0; code = pr_CreateUser(name, &id); if ((code != RXGEN_CC_MARSHAL) && (code != PRBADNAM)) { afs_com_err(whoami, code, "succeeded creating %s", name); exit(2); } name[i] = 0; id = 0; code = pr_CreateUser(name, &id); if (code == PREXIST) { fprintf(stderr, "group already exists, skipping\n"); pr_SNameToId(name, &id); } else if (code) { afs_com_err(whoami, code, "failed creating %s", name); exit(3); } if ((code = pr_ListEntry(id, &ent)) || (code = pr_SIdToName(ent.creator, creator))) { afs_com_err(whoami, code, "getting creator's name"); exit(5); } code = pr_DeleteByID(id); if (code) { afs_com_err(whoami, code, "deleting %s", name); exit(6); } /* now make sure the illegal chars are detected */ { char *illegalChars; for (illegalChars = "@:\n"; *illegalChars; illegalChars++) { name[10] = *illegalChars; id = 0; code = pr_CreateUser(name, &id); if (code != PRBADNAM) { afs_com_err(whoami, code, "succeeded creating %s", name); exit(8); } } } for (i = 1; i <= 255;) { /* for all 8-bit ascii... */ j = 0; /* build a new name */ while ((j < maxLen) && (i <= 255)) { if (!((i == ':') || (i == '@') || (i == '\n'))) name[j++] = i; i++; } name[j] = 0; /* terminate string */ id = 0; code = pr_CreateUser(name, &id); if (code == PREXIST) { fprintf(stderr, "user already exists, skipping\n"); pr_SNameToId(name, &id); } else if (code) { char ascii[BUFSIZ]; ka_ConvertBytes(ascii, sizeof(ascii), name, strlen(name)); afs_com_err(whoami, code, "failed creating %s", ascii); exit(4); } code = pr_DeleteByID(id); if (code) { afs_com_err(whoami, code, "deleting %s", name); exit(7); } } /* now check group names */ strcpy(name, creator); strcat(name, ":abcdefghijklmnopqrstuvwxyz"); name[0] = 1; /* bash the owner name */ id = 0; code = pr_CreateGroup(name, creator, &id); if (code != PRNOENT) { /* owner doesn't exist */ afs_com_err(whoami, code, "succeeded creating %s", name); exit(9); } name[0] = creator[0]; /* fix owner */ /* Make sure the illegal chars are detected */ { char *illegalChars; for (illegalChars = ":@\n"; *illegalChars; illegalChars++) { name[strlen(creator) + 10] = *illegalChars; id = 0; code = pr_CreateGroup(name, creator, &id); if (code != PRBADNAM) { afs_com_err(whoami, code, "succeeded creating %s", name); exit(10); } } } for (i = 1; i <= 255;) { /* for all 8-bit ascii... */ j = strlen(creator) + 1; /* build a new name */ while ((j < PR_MAXNAMELEN - 1) && (i <= 255)) { if (!((i == ':') || (i == '@') || (i == '\n'))) name[j++] = i; i++; } name[j] = 0; /* terminate string */ id = 0; code = pr_CreateGroup(name, creator, &id); if (code == PREXIST) { fprintf(stderr, "group already exists, skipping\n"); pr_SNameToId(name, &id); } else if (code) { char ascii[BUFSIZ]; ka_ConvertBytes(ascii, sizeof(ascii), name, strlen(name)); afs_com_err(whoami, code, "failed creating %s", ascii); exit(4); } code = pr_DeleteByID(id); if (code) { afs_com_err(whoami, code, "deleting %s", name); exit(7); } } printf("All OK\n"); return 0; } static char tmp_conf_dir[128] = ""; static char tmp_conf_file[128] = ""; static char tmp_cell_file[128] = ""; static char tmp_noauth_file[128] = ""; static int MyAfterProc(struct cmd_syndesc *as, void *arock) { if (strlen(tmp_conf_file)) unlink(tmp_conf_file); if (strlen(tmp_cell_file)) unlink(tmp_cell_file); if (strlen(tmp_noauth_file)) unlink(tmp_noauth_file); if (strlen(tmp_conf_dir)) rmdir(tmp_conf_dir); return 0; } static int MyBeforeProc(struct cmd_syndesc *as, void *arock) { afs_int32 code; int i; char *cdir = 0; int noAuth = 0; struct cmd_item *serverList = 0; struct afsconf_dir *local_conf = 0; /* so we can default stuff nicely */ struct afsconf_cell cellinfo; if (as->parms[12].items) { /* if conf dir specified */ cdir = as->parms[12].items->data; if (as->parms[13].items || as->parms[14].items || as->parms[15].items) { printf("Can't specify conf dir and other cell parameters\n"); return AFSCONF_SYNTAX; } } /* if we need to default cell name or cell servers, get local conf info */ if (!(local_conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH)) && !(local_conf = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH))) { printf("** Can't local configuration!\n"); return AFSCONF_NOCELL; } if (as->parms[13].items) { /* if cell name specified */ lcstring(lcell, as->parms[13].items->data, sizeof(lcell)); code = afsconf_GetCellInfo(local_conf, lcell, 0, &cellinfo); if (code == 0) strncpy(lcell, cellinfo.name, sizeof(lcell)); } else { code = afsconf_GetLocalCell(local_conf, lcell, sizeof(lcell)); if (code) return code; } if (as->parms[14].items) { /* noauth flag */ noAuth = 1; } if (as->parms[15].items) { /* servers list */ serverList = as->parms[15].items; for (i = 0; serverList; i++, serverList = serverList->next) { struct hostent *th; if (i >= MAXHOSTSPERCELL) return AFSCONF_FULL; strncpy(cellinfo.hostName[i], serverList->data, MAXHOSTCHARS); th = gethostbyname(cellinfo.hostName[i]); if (!th) return UBADHOST; memcpy(&cellinfo.hostAddr[i].sin_addr, th->h_addr, sizeof(afs_int32)); cellinfo.hostAddr[i].sin_family = AF_INET; cellinfo.hostAddr[i].sin_port = 0; #ifdef STRUCT_SOCKADDR_HAS_SA_LEN cellinfo.hostAddr[i].sin_len = sizeof(struct sockaddr_in); #endif } cellinfo.numServers = i; strcpy(cellinfo.name, lcell); } else { code = afsconf_GetCellInfo(local_conf, lcell, 0, &cellinfo); if (code) return code; } if (local_conf) afsconf_Close(local_conf); if (cdir == 0) { FILE *f; sprintf(tmp_conf_dir, "%s/afsconf.%lu", gettmpdir(), (unsigned long)getpid()); code = mkdir(tmp_conf_dir, 0777); if ((code < 0) && (errno != EEXIST)) { afs_com_err(whoami, errno, "can't create temporary afsconf dir: %s", tmp_conf_dir); return errno; } strcompose(tmp_conf_file, 128, tmp_conf_dir, "/", AFSDIR_CELLSERVDB_FILE, (char *)NULL); f = fopen(tmp_conf_file, "w"); if (f == 0) { cantcreate: afs_com_err(whoami, errno, "can't create conf file %s", tmp_conf_file); return errno; } fprintf(f, ">%s\n", lcell); for (i = 0; i < cellinfo.numServers; i++) { unsigned char *tp = (unsigned char *)&cellinfo.hostAddr[i].sin_addr; fprintf(f, "%d.%d.%d.%d\t#%s\n", tp[0], tp[1], tp[2], tp[3], cellinfo.hostName[i]); } if (fclose(f) == EOF) { cantclose: afs_com_err(whoami, errno, "can't write to conf file %s", tmp_conf_file); return errno; } strcompose(tmp_cell_file, 128, tmp_conf_dir, "/", AFSDIR_THISCELL_FILE, (char *)NULL); f = fopen(tmp_cell_file, "w"); if (f == 0) goto cantcreate; fprintf(f, "%s", lcell); if (fclose(f) == EOF) goto cantclose; strcompose(tmp_noauth_file, 128, tmp_conf_dir, "/", AFSDIR_NOAUTH_FILE, (char *)NULL); if (noAuth) { code = creat(tmp_noauth_file, 0777); if (code && (errno != EEXIST)) return errno; } else { /* make sure file doesn't exist */ code = unlink(tmp_noauth_file); if (code && (errno != ENOENT)) return errno; } } strncpy(conf_dir, tmp_conf_dir, sizeof(conf_dir)); conf = afsconf_Open(conf_dir); if (conf == 0) return AFSCONF_NOTFOUND; return 0; } static void add_std_args(struct cmd_syndesc *ts) { cmd_Seek(ts, 12); cmd_AddParm(ts, "-confdir", CMD_SINGLE, CMD_OPTIONAL, "AFS Conf dir pathname"); cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "Cell name"); cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL, "Don't authenticate"); cmd_AddParm(ts, "-servers", CMD_LIST, CMD_OPTIONAL, "Server config"); } int osi_audit(void) { /* OK, this REALLY sucks bigtime, but I can't tell who is calling * afsconf_CheckAuth easily, and only *SERVERS* should be calling osi_audit * anyway. It's gonna give somebody fits to debug, I know, I know. */ return 0; } #include "AFS_component_version_number.c" int main(int argc, char *argv[]) { afs_int32 code; struct cmd_syndesc *ts; /* ptr to parsed command line syntax */ whoami = argv[0]; initialize_CMD_error_table(); initialize_ACFG_error_table(); initialize_KTC_error_table(); initialize_U_error_table(); initialize_PT_error_table(); initialize_RXK_error_table(); #ifdef AFS_NT40_ENV /* initialize winsock */ if (afs_winsockInit() < 0) { fprintf(stderr, "%s: couldn't initialize winsock. \n", whoami); exit(1); } #endif cmd_SetBeforeProc(MyBeforeProc, NULL); cmd_SetAfterProc(MyAfterProc, NULL); ts = cmd_CreateSyntax("usedIds", ListUsedIds, NULL, 0, "Find used (or unused) user (or group) ids"); cmd_AddParm(ts, "-startId", CMD_SINGLE, CMD_OPTIONAL, "id to start checking"); cmd_AddParm(ts, "-number", CMD_SINGLE, CMD_OPTIONAL, "number of ids to check"); cmd_AddParm(ts, "-unused", CMD_FLAG, CMD_OPTIONAL, "print unused ids"); add_std_args(ts); ts = cmd_CreateSyntax("initcmd", TestPrServ, NULL, 0, "test the prserver"); add_std_args(ts); ts = cmd_CreateSyntax("testmanymembers", TestManyMembers, NULL, 0, "test creating users and groups w/ many members"); cmd_AddParm(ts, "-number", CMD_SINGLE, 0, "number of users/groups to create"); cmd_AddParm(ts, "-dropoff", CMD_SINGLE, CMD_OPTIONAL, "precentage for exponential dropoff"); cmd_AddParm(ts, "-prefix", CMD_SINGLE, CMD_OPTIONAL, "naming prefix"); cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL, "show progress"); cmd_AddParm(ts, "-seed", CMD_SINGLE, CMD_OPTIONAL, "random number seed"); add_std_args(ts); cmd_CreateAlias(ts, "mm"); code = cmd_Dispatch(argc, argv); if (code) afs_com_err(whoami, code, "calling cmd_Dispatch"); exit(code); }