Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / ptserver / testpt.c
blobd0a1c9392459f0df91beab078dda87a0144113fa
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
10 #include <afsconfig.h>
11 #include <afs/param.h>
14 #include <ctype.h>
15 #include <errno.h>
16 #include <sys/types.h>
17 #ifdef AFS_NT40_ENV
18 #include <winsock2.h>
19 #include <WINNT/afsevent.h>
20 #else
21 #include <sys/socket.h>
22 #include <netdb.h>
23 #include <netinet/in.h>
24 #endif
25 #include <string.h>
26 #include <math.h>
27 #ifdef HAVE_FCNTL_H
28 #include <fcntl.h>
29 #endif
30 #ifdef HAVE_SYS_STAT_H
31 #include <sys/stat.h>
32 #endif
33 #ifdef HAVE_SYS_TYPES_H
34 #include <sys/types.h>
35 #endif
36 #include <rx/rx.h>
37 #include <rx/xdr.h>
38 #include <afs/rxgen_consts.h>
39 #include <afs/cmd.h>
40 #include <afs/auth.h>
41 #include <afs/cellconfig.h>
42 #include "ptclient.h"
43 #include "pterror.h"
44 #include "ptuser.h"
45 #include "ptprototypes.h"
46 #include <afs/afsutil.h>
47 #include <afs/com_err.h>
49 static char *whoami = "testpr";
50 static struct afsconf_dir *conf; /* cell info, set by MyBeforeProc */
51 static char conf_dir[100];
52 static char lcell[MAXCELLCHARS];
54 int
55 ListUsedIds(struct cmd_syndesc *as, void *arock)
57 afs_int32 code;
58 namelist lnames;
59 idlist lids;
60 int i, j;
61 int group = 0; /* check groups */
62 int unused = 0; /* print unused */
63 int number = 100; /* check 100 ids */
64 afs_int32 startId = 1;
65 afs_int32 maxId;
66 int range;
68 if (as->parms[0].items)
69 startId = atoi(as->parms[0].items->data);
70 if (as->parms[1].items)
71 number = atoi(as->parms[1].items->data);
72 if (as->parms[2].items)
73 unused = 1;
75 code = pr_Initialize(1, conf_dir, NULL);
76 if (code) {
77 afs_com_err(whoami, code, "initializing pruser");
78 exit(1);
80 if (startId < 0) {
81 group = 1;
82 code = pr_ListMaxGroupId(&maxId);
83 if (code) {
84 bad_max:
85 afs_com_err(whoami, code, "getting maximum id");
86 exit(2);
88 if (startId < maxId) {
89 fprintf(stderr, "Max group id is only %d.\n", maxId);
90 exit(3);
92 } else {
93 code = pr_ListMaxUserId(&maxId);
94 if (code)
95 goto bad_max;
96 if (startId > maxId) {
97 fprintf(stderr, "Max user id is only %d.\n", maxId);
98 exit(3);
101 range = abs(startId - maxId);
102 if (range < 0)
103 range = -range;
104 range++; /* number that can be printed */
105 if (range < number) {
106 fprintf(stderr, "Only %d ids to be checked.\n", range);
107 number = range;
110 printf("Checking for %d %sused ids starting at %d.\n", number,
111 (unused ? "un" : ""), startId);
112 #define NUM 100
113 lids.idlist_val = (afs_int32 *) malloc(sizeof(afs_int32) * NUM);
114 lnames.namelist_len = 0;
115 lnames.namelist_val = 0;
116 while (number) {
117 if (number < NUM)
118 i = number;
119 else
120 i = NUM;
121 for (j = 0; j < i; j++) {
122 lids.idlist_val[j] = startId;
123 if (group)
124 startId--;
125 else
126 startId++;
128 lids.idlist_len = i;
129 code = pr_IdToName(&lids, &lnames);
130 if (code) {
131 afs_com_err(whoami, code, "converting id to name");
132 exit(2);
134 for (j = 0; j < lnames.namelist_len; j++) {
135 if (lids.idlist_val[j] == atoi(lnames.namelist_val[j])) {
136 if (unused)
137 printf("%s is free\n", lnames.namelist_val[j]);
138 } else {
139 if (!unused)
140 printf("%s is id %d\n", lnames.namelist_val[j],
141 lids.idlist_val[j]);
144 number -= i;
146 if (lids.idlist_val)
147 free(lids.idlist_val);
148 if (lnames.namelist_val)
149 free(lnames.namelist_val);
150 return 0;
153 /* TestManyMembers - called with a number N. Try creating N users and N groups
154 * and put all the users on one of the groups and one of the users on all the
155 * groups. Also put many users on many groups.
157 * To keep track of this create an NxN matrix of membership and fill it in with
158 * a function that looks like a quarter of a circle. That makes the first
159 * group contain every user and the first user be a member of every group. */
161 int verbose;
162 char callerName[PR_MAXNAMELEN];
163 afs_int32 callerId;
164 afs_int32 lastGroup; /* id of last group created */
165 afs_int32 ownerUser; /* first created user */
166 char ownerUserName[PR_MAXNAMELEN]; /* " " " name */
167 int steepDropOff; /* precentage decreate in GroupLimit */
168 char *createPrefix; /* prefix for naming users&groups */
169 extern struct ubik_client *pruclient; /* initialized by pr_Initialize */
171 /* These variables form the state if this test */
172 int number; /* max number of members */
173 char *population; /* matrix of memberships */
174 afs_int32 *users; /* ids of users */
175 afs_int32 *groups; /* ids of groups */
176 afs_int32 *groupOwners; /* ids of owners of groups */
178 /* statistics */
179 int nUsers, nGroups, nAdds, nRems, nUDels, nGDels;
182 IdCmp(const void *a, const void *b)
184 if (*(afs_int32 *)a > *(afs_int32 *)b) {
185 return 1;
186 } else if (*(afs_int32 *)a == *(afs_int32 *)b) {
187 return 0;
188 } else /* (*a < *b) */ {
189 return -1;
193 static int
194 sqr(int n)
196 return n * n;
199 static int
200 GetGroupLimit(int N, int x)
202 int y;
204 if ((x >= N) || (x < 0)) {
205 printf("GetGroupLimit: input value out of range %d (%d)\n", x, N);
206 exit(10);
208 if (steepDropOff) { /* Use exponential decrease */
209 int i;
210 y = N;
211 for (i = 0; i < x; i++) {
212 y = (y * steepDropOff) / 100; /* parameter is a percentage */
213 if (y == 0) {
214 y = 1; /* with a floor of 1 */
215 break;
218 } else { /* Use a circle's third quadrant */
219 y = sqr(N - 1) - sqr(N - 1 - x);
220 y = (int)(sqrt((double)y) + 0.5); /* round off */
221 y = N - y;
223 if ((y > N) || (y < 1)) {
224 printf("filling value out of range: %d (%d) => %d\n", x, N, y);
225 exit(11);
227 return y;
230 void
231 CreateUser(int u)
233 afs_int32 code;
234 char name[16];
235 afs_int32 id;
237 sprintf(name, "%s%d", createPrefix, u);
238 id = 0;
239 code = pr_CreateUser(name, &id);
240 if (code) {
241 if (code == PREXIST) {
242 code = pr_Delete(name);
243 if (code == 0) {
244 nUDels++;
245 code = pr_CreateUser(name, &id);
246 if (code == 0) {
247 if (verbose)
248 printf("RE-");
249 goto done;
253 afs_com_err(whoami, code, "couldn't create %s", name);
254 exit(12);
256 done:
257 if (verbose)
258 printf("Creating user %s (%di)\n", name, id);
259 users[u] = id;
260 nUsers++;
262 if (ownerUser == 0) {
263 ownerUser = id;
264 strcpy(ownerUserName, name);
268 void
269 CreateGroup(int g)
271 afs_int32 code;
272 char name[16];
273 afs_int32 id = 0;
274 afs_int32 owner = 0;
275 char *ownerName = NULL;
276 int ownerType; /* type of ownership */
277 static char *lastGroupPrefix; /* prefix used for type==2 */
279 /* At least 50 groups should be owned by another group to test long owner
280 * chains during deletion. Also let's create some long owners of owners
281 * lists. */
282 ownerType = random() % 3;
284 if (!ownerUser)
285 ownerType = 0;
286 if (!lastGroup)
287 ownerType = 0;
288 switch (ownerType) {
289 case 0:
290 owner = callerId;
291 ownerName = callerName;
292 break;
293 case 1:
294 owner = ownerUser;
295 ownerName = ownerUserName;
296 break;
297 case 2:
298 owner = lastGroup;
299 ownerName = lastGroupPrefix;
300 break;
303 sprintf(name, "%s:%s%d", ownerName, createPrefix, g);
304 code = ubik_PR_NewEntry(pruclient, 0, name, PRGRP, owner, &id);
305 if (code) {
306 if (code == PREXIST) {
307 code = pr_Delete(name);
308 if (code == 0) {
309 nGDels++;
310 code =
311 ubik_PR_NewEntry(pruclient, 0, name, PRGRP, owner,
312 &id);
313 if (code == 0) {
314 if (verbose)
315 printf("RE-");
316 goto done;
320 afs_com_err(whoami, code, "couldn't create %s w/ owner=%d", name, owner);
321 exit(13);
323 done:
324 if (verbose)
325 printf("Creating group %s (%di)\n", name, id);
326 groups[g] = id;
327 groupOwners[g] = owner;
328 nGroups++;
329 if (!lastGroup || (ownerType == 2)) {
330 lastGroup = id;
331 lastGroupPrefix = ownerName;
336 DeleteRandomId(afs_int32 *list)
338 afs_int32 code;
339 afs_int32 id;
340 int j, k;
341 int m;
343 k = random(); /* random starting point */
344 for (j = 0; j < number; j++) { /* find an undeleted id */
345 m = (k + j) % number;
346 if ((id = list[m])) {
347 code = ubik_PR_Delete(pruclient, 0, id);
348 if (code) {
349 afs_com_err(whoami, code, "Couldn't delete %di", id);
350 exit(22);
352 list[m] = 0;
353 if (list == users)
354 nUDels++;
355 else
356 nGDels++;
357 return 0;
360 return -1; /* none left */
363 void
364 AddUser(int u, int g)
366 afs_int32 code;
367 afs_int32 ui, gi;
369 if (users[u] == 0) /* create if necessary */
370 CreateUser(u);
371 if (groups[g] == 0) /* create group if necessary */
372 CreateGroup(g);
373 ui = users[u];
374 gi = groups[g];
375 code = ubik_PR_AddToGroup(pruclient, 0, ui, gi);
376 if (code) {
377 afs_com_err(whoami, code, "couldn't add %d to %d", ui, gi);
378 exit(14);
380 if (verbose)
381 printf("Adding user (%di) to group (%di)\n", ui, gi);
382 population[u * number + g]++;
383 nAdds++;
386 void
387 RemUser(int u, int g)
389 afs_int32 code;
390 afs_int32 ui, gi;
392 ui = users[u];
393 gi = groups[g];
394 code = ubik_PR_RemoveFromGroup(pruclient, 0, ui, gi);
395 if (code) {
396 afs_com_err(whoami, code, "couldn't remove %d from %d", ui, gi);
397 exit(14);
399 if (verbose)
400 printf("Removing user (%di) from group (%di)\n", ui, gi);
401 population[u * number + g]--;
402 nRems++;
406 TestManyMembers(struct cmd_syndesc *as, void *arock)
408 char *filled; /* users filled up */
409 char *cleaned; /* users cleaned up */
411 int nFilled, nCleaned;
412 int u, g, i, j, n;
413 int seed; /* random number generator seed */
415 afs_int32 *glist; /* membership list */
417 afs_int32 code;
419 code = pr_Initialize(1, conf_dir, NULL);
420 if (code) {
421 afs_com_err(whoami, code, "initializing pruser");
422 exit(1);
424 /* get name of person running command */
426 struct ktc_principal afs, user;
427 struct ktc_token token;
429 strcpy(afs.name, "afs");
430 strcpy(afs.instance, "");
431 code = afsconf_GetLocalCell(conf, afs.cell, sizeof(afs.cell));
432 if (code)
433 exit(2);
434 code = ktc_GetToken(&afs, &token, sizeof(token), &user);
435 if (code) {
436 afs_com_err(whoami, code, "getting afs tokens");
437 exit(3);
439 if (strlen(user.instance) > 0) {
440 fprintf(stderr, "can't handle non-null instance %s.%s\n",
441 user.name, user.cell);
442 exit(4);
444 if (strncmp(user.name, "AFS ID ", 7) == 0) {
445 callerId = atoi(user.name + 7);
446 code = pr_SIdToName(callerId, callerName);
447 if (code) {
448 afs_com_err(whoami, code, "call get name for id %d", callerId);
449 exit(6);
451 } else {
452 strcpy(callerName, user.name);
453 code = pr_SNameToId(callerName, &callerId);
454 if ((code == 0) && (callerId == ANONYMOUSID))
455 code = PRNOENT;
457 #if 0 /* don't create user */
458 if (code == PRNOENT) {
459 callerId = 0;
460 code = pr_CreateUser(callerName, &callerId);
461 if (code) {
462 afs_com_err(whoami, code, "can't create caller %s", callerName);
463 exit(5);
465 printf("Creating caller %s (%di)\n", callerName, callerId);
467 /* else */
468 #endif
469 if (code) {
470 afs_com_err(whoami, code, "can't find caller %s", callerName);
471 exit(6);
472 } else
473 printf("Assuming caller is %s (%di)\n", callerName, callerId);
476 /* Parse arguments */
477 if (as->parms[0].items)
478 number = atoi(as->parms[0].items->data);
479 if (as->parms[1].items) {
480 steepDropOff = atoi(as->parms[1].items->data);
481 if ((steepDropOff < 0) || (steepDropOff > 100)) {
482 fprintf(stderr,
483 "Illegal value for dropoff: %d, must be between 0 and 100, inclusive.\n",
484 steepDropOff);
485 exit(7);
487 } else
488 steepDropOff = 0; /* use quadratic dropoff */
489 if (as->parms[2].items)
490 createPrefix = as->parms[2].items->data;
491 else
492 createPrefix = "u";
493 if (as->parms[3].items)
494 verbose = 1;
495 else
496 verbose = 0;
497 if (as->parms[4].items)
498 seed = atoi(as->parms[4].items->data);
499 else
500 seed = 1;
502 srandom(seed);
504 users = (afs_int32 *) malloc(number * sizeof(afs_int32));
505 groups = (afs_int32 *) malloc(number * sizeof(afs_int32));
506 filled = (char *)malloc(number * sizeof(char));
507 cleaned = (char *)malloc(number * sizeof(char));
508 population = (char *)malloc(sqr(number) * sizeof(char));
510 nFilled = 0;
511 memset(filled, 0, number);
512 nCleaned = 0;
513 memset(cleaned, 0, number);
514 memset(population, 0, sqr(number));
515 memset(users, 0, number * sizeof(afs_int32));
516 memset(groups, 0, number * sizeof(afs_int32));
518 ownerUser = lastGroup = 0;
519 groupOwners = (afs_int32 *) malloc(number * sizeof(afs_int32));
520 nUsers = nGroups = nAdds = nRems = nUDels = nGDels = 0;
522 while ((nFilled < number) || (nCleaned < number)) {
523 /* pick a user at random, using */
524 u = random() % number;
525 if (!filled[u]) {
526 n = GetGroupLimit(number, u); /* get group limit for that user */
527 g = random() % (n + 1); /* pick a random group */
528 if (g == n) { /* in a few cases create any user */
529 n = number; /* in the whole range */
530 g = random() % n;
532 for (i = 0; i < n; i++) { /* rotate until unused one found */
533 j = (g + i) % n;
534 if (!population[u * number + j]) {
535 /* add this user/group membership */
536 AddUser(u, j);
537 goto added;
540 filled[u]++;
541 nFilled++;
542 added:;
544 if (!cleaned[u]) {
545 int base;
546 if (filled[u]) { /* only clean above GroupLimit */
547 base = GetGroupLimit(number, u);
548 n = number - base;
549 if (n == 0)
550 goto iscleaned;
551 g = random() % n;
552 } else {
553 base = 0;
554 n = number; /* pick a group from the whole range */
555 g = random() % 2 * n; /* at random for removal */
556 if (g >= n)
557 goto remed; /* but half the time do nothing */
559 for (i = 0; i < n; i++) { /* rotate until used one found */
560 j = (g + i) % n + base;
561 if (population[u * number + j]) {
562 /* remove this user/group membership */
563 RemUser(u, j);
564 goto remed;
567 if (filled[u]) { /* track finished ones */
568 iscleaned:
569 cleaned[u]++;
570 nCleaned++;
572 remed:;
576 /* check the membership list of all users for correctness */
577 printf("Starting check of memberships\n");
578 glist = (afs_int32 *) malloc(number * sizeof(afs_int32));
579 for (u = 0; u < number; u++) {
580 afs_int32 ui = users[u];
581 if (ui) {
582 int i;
583 int ng; /* number groups */
584 int over;
585 int (*proc)(struct ubik_client *, afs_int32, afs_int32, prlist *,
586 afs_int32 *);
587 prlist alist;
589 alist.prlist_len = 0;
590 alist.prlist_val = 0;
591 if (random() & 4) {
592 proc = ubik_PR_ListElements;
593 } else {
594 proc = ubik_PR_GetCPS;
596 code = (*proc)(pruclient, 0, ui, &alist, &over);
597 if (code) {
598 afs_com_err(whoami, code,
599 "getting membership list of (%di) using %s", ui,
600 (proc == ubik_PR_ListElements?"ListElements":"GetCPS"));
601 exit(24);
603 if (over) {
604 fprintf(stderr, "membership list for id %di too long\n", ui);
606 ng = 0;
607 for (i = 0; i < number; i++)
608 if (population[u * number + i])
609 glist[ng++] = groups[i];
610 qsort(glist, ng, sizeof(afs_int32), IdCmp);
611 if (ng != (alist.prlist_len - ((proc == ubik_PR_GetCPS) ? 3 : 0))) {
612 fprintf(stderr,
613 "Membership list for %di of unexpected length: was %d but expected %d\n",
614 ui, alist.prlist_len, ng);
615 exit(20);
617 /* all the extra entries for the CPS should be at the end. */
618 code = 0;
619 for (i = 0; i < ng; i++)
620 if (alist.prlist_val[i] != glist[i]) {
621 fprintf(stderr,
622 "membership for %di not correct: was %di but expected %di\n",
623 ui, alist.prlist_val[i], glist[i]);
624 code++;
626 if (code)
627 exit(21);
628 if (proc == ubik_PR_GetCPS) {
629 if ((alist.prlist_val[i /* =ng */ ] != AUTHUSERID) ||
630 (alist.prlist_val[++i] != ANYUSERID)
631 || (alist.prlist_val[++i] != ui)) {
632 fprintf(stderr, "CPS doesn't have extra entries\n");
633 exit(27);
636 if (alist.prlist_val)
637 free(alist.prlist_val);
639 /* User 0 is a member of all groups all of which should also be on
640 * the owner list of the caller or the ownerUser, although there
641 * may also be others. Check this. */
642 if (u == 0) {
643 prlist callerList;
644 prlist ownerList;
645 prlist lastGroupList;
646 int i, j, k, l;
648 if (ng != number) {
649 fprintf(stderr, "User 0 not a member of all groups\n");
650 exit(26);
652 #define GETOWNED(xlist,xid) \
653 (xlist).prlist_val = 0; (xlist).prlist_len = 0; \
654 code = ubik_PR_ListOwned(pruclient, 0, (xid), &(xlist), &over); \
655 if (code) { \
656 afs_com_err (whoami, code, "getting owner list of (%di)", (xid)); \
657 exit (23); } \
658 if (over) \
659 { fprintf (stderr, "membership of id %di too long\n", (xid)); }
661 GETOWNED(callerList, callerId);
662 GETOWNED(ownerList, ownerUser);
664 /* look for every entry in glist, in all the owner lists */
665 for (i = j = k = l = 0; i < number; i++) {
666 while ((j < callerList.prlist_len)
667 && (callerList.prlist_val[j] < glist[i]))
668 j++;
669 while ((k < ownerList.prlist_len)
670 && (ownerList.prlist_val[k] < glist[i]))
671 k++;
672 #define PRLISTCMP(l,i) \
673 (((l).prlist_len == 0) || (glist[i] != (l).prlist_val[(i)]))
674 if (PRLISTCMP(callerList, j) && PRLISTCMP(ownerList, k)) {
675 for (l = 0; l < number; l++) {
676 if (groups[l] == glist[i]) {
677 if ((groupOwners[l] != callerId)
678 && (groupOwners[l] != ownerUser)) {
679 GETOWNED(lastGroupList, groupOwners[l]);
680 if ((lastGroupList.prlist_len != 1)
681 || (lastGroupList.prlist_val[0] !=
682 glist[i])) {
683 fprintf(stderr,
684 "Group (%di) not on any owner list\n",
685 glist[i]);
686 exit(25);
689 goto foundLast;
692 fprintf(stderr, "unexpected group %di\n", glist[i]);
693 foundLast:;
696 if (callerList.prlist_val)
697 free(callerList.prlist_val);
698 if (ownerList.prlist_val)
699 free(ownerList.prlist_val);
700 if (lastGroupList.prlist_val)
701 free(lastGroupList.prlist_val);
706 /* cleanup by deleting all the users and groups */
707 printf("Starting deletion of users and groups\n");
708 for (i = 0; i < number; i++) {
709 DeleteRandomId(users);
710 DeleteRandomId(groups);
713 printf
714 ("Created/deleted %d/%d users and %d/%d groups; added %d and removed %d.\n",
715 nUsers, nUDels, nGroups, nGDels, nAdds, nRems);
716 return 0;
719 /* from ka_ConvertBytes included here to avoid circularity */
720 /* Converts a byte string to ascii. Return the number of unconverted bytes. */
722 static int
723 ka_ConvertBytes(char *ascii, /* output buffer */
724 int alen, /* buffer length */
725 char bs[], /* byte string */
726 int bl) /* number of bytes */
728 int i;
729 unsigned char c;
731 alen--; /* make room for termination */
732 for (i = 0; i < bl; i++) {
733 c = bs[i];
734 if (alen <= 0)
735 return bl - i;
736 if (isalnum(c) || ispunct(c))
737 (*ascii++ = c), alen--;
738 else {
739 if (alen <= 3)
740 return bl - i;
741 *ascii++ = '\\';
742 *ascii++ = (c >> 6) + '0';
743 *ascii++ = (c >> 3 & 7) + '0';
744 *ascii++ = (c & 7) + '0';
745 alen -= 4;
748 *ascii = 0; /* terminate string */
749 return 0;
752 /* This runs various tests on the server. It creates, then deletes, a bunch of
753 * users and groups, so it would be safest to run it on a test database.
755 * These are the things I check for:
756 * User names longer than PR_MAXNAMELEN - strlen(cellname).
757 * Group names longer than PR_MAXNAMELEN.
758 * User names containing all legal 8-bit ascii characters. This excludes
759 * only ':', '@', and '\n'.
760 * Group names as above, but at least one colon is required, and the owner
761 * must be correct.
765 TestPrServ(struct cmd_syndesc *as, void *arock)
767 afs_int32 id;
768 char name[PR_MAXNAMELEN + 1];
769 char creator[PR_MAXNAMELEN]; /* our name */
770 struct prcheckentry ent;
771 afs_int32 code;
772 int i, j;
773 int maxLen = PR_MAXNAMELEN - 1 - strlen(lcell) - 1;
775 code = pr_Initialize(1, conf_dir, NULL);
776 if (code) {
777 afs_com_err(whoami, code, "initializing pruser");
778 exit(1);
781 for (i = 0; i < maxLen; i++)
782 name[i] = 'a';
783 name[i] = 'a'; /* too long a name... */
784 name[i + 1] = 0;
785 id = 0;
786 code = pr_CreateUser(name, &id);
787 if ((code != RXGEN_CC_MARSHAL) && (code != PRBADNAM)) {
788 afs_com_err(whoami, code, "succeeded creating %s", name);
789 exit(2);
791 name[i] = 0;
792 id = 0;
793 code = pr_CreateUser(name, &id);
794 if (code == PREXIST) {
795 fprintf(stderr, "group already exists, skipping\n");
796 pr_SNameToId(name, &id);
797 } else if (code) {
798 afs_com_err(whoami, code, "failed creating %s", name);
799 exit(3);
801 if ((code = pr_ListEntry(id, &ent))
802 || (code = pr_SIdToName(ent.creator, creator))) {
803 afs_com_err(whoami, code, "getting creator's name");
804 exit(5);
806 code = pr_DeleteByID(id);
807 if (code) {
808 afs_com_err(whoami, code, "deleting %s", name);
809 exit(6);
811 /* now make sure the illegal chars are detected */
813 char *illegalChars;
814 for (illegalChars = "@:\n"; *illegalChars; illegalChars++) {
815 name[10] = *illegalChars;
816 id = 0;
817 code = pr_CreateUser(name, &id);
818 if (code != PRBADNAM) {
819 afs_com_err(whoami, code, "succeeded creating %s", name);
820 exit(8);
825 for (i = 1; i <= 255;) { /* for all 8-bit ascii... */
826 j = 0; /* build a new name */
827 while ((j < maxLen) && (i <= 255)) {
828 if (!((i == ':') || (i == '@') || (i == '\n')))
829 name[j++] = i;
830 i++;
832 name[j] = 0; /* terminate string */
833 id = 0;
834 code = pr_CreateUser(name, &id);
835 if (code == PREXIST) {
836 fprintf(stderr, "user already exists, skipping\n");
837 pr_SNameToId(name, &id);
838 } else if (code) {
839 char ascii[BUFSIZ];
840 ka_ConvertBytes(ascii, sizeof(ascii), name, strlen(name));
841 afs_com_err(whoami, code, "failed creating %s", ascii);
842 exit(4);
844 code = pr_DeleteByID(id);
845 if (code) {
846 afs_com_err(whoami, code, "deleting %s", name);
847 exit(7);
851 /* now check group names */
852 strcpy(name, creator);
853 strcat(name, ":abcdefghijklmnopqrstuvwxyz");
854 name[0] = 1; /* bash the owner name */
855 id = 0;
856 code = pr_CreateGroup(name, creator, &id);
857 if (code != PRNOENT) { /* owner doesn't exist */
858 afs_com_err(whoami, code, "succeeded creating %s", name);
859 exit(9);
861 name[0] = creator[0]; /* fix owner */
862 /* Make sure the illegal chars are detected */
864 char *illegalChars;
865 for (illegalChars = ":@\n"; *illegalChars; illegalChars++) {
866 name[strlen(creator) + 10] = *illegalChars;
867 id = 0;
868 code = pr_CreateGroup(name, creator, &id);
869 if (code != PRBADNAM) {
870 afs_com_err(whoami, code, "succeeded creating %s", name);
871 exit(10);
875 for (i = 1; i <= 255;) { /* for all 8-bit ascii... */
876 j = strlen(creator) + 1; /* build a new name */
877 while ((j < PR_MAXNAMELEN - 1) && (i <= 255)) {
878 if (!((i == ':') || (i == '@') || (i == '\n')))
879 name[j++] = i;
880 i++;
882 name[j] = 0; /* terminate string */
883 id = 0;
884 code = pr_CreateGroup(name, creator, &id);
885 if (code == PREXIST) {
886 fprintf(stderr, "group already exists, skipping\n");
887 pr_SNameToId(name, &id);
888 } else if (code) {
889 char ascii[BUFSIZ];
890 ka_ConvertBytes(ascii, sizeof(ascii), name, strlen(name));
891 afs_com_err(whoami, code, "failed creating %s", ascii);
892 exit(4);
894 code = pr_DeleteByID(id);
895 if (code) {
896 afs_com_err(whoami, code, "deleting %s", name);
897 exit(7);
901 printf("All OK\n");
902 return 0;
905 static char tmp_conf_dir[128] = "";
906 static char tmp_conf_file[128] = "";
907 static char tmp_cell_file[128] = "";
908 static char tmp_noauth_file[128] = "";
910 static int
911 MyAfterProc(struct cmd_syndesc *as, void *arock)
913 if (strlen(tmp_conf_file))
914 unlink(tmp_conf_file);
915 if (strlen(tmp_cell_file))
916 unlink(tmp_cell_file);
917 if (strlen(tmp_noauth_file))
918 unlink(tmp_noauth_file);
919 if (strlen(tmp_conf_dir))
920 rmdir(tmp_conf_dir);
921 return 0;
924 static int
925 MyBeforeProc(struct cmd_syndesc *as, void *arock)
927 afs_int32 code;
928 int i;
929 char *cdir = 0;
930 int noAuth = 0;
931 struct cmd_item *serverList = 0;
932 struct afsconf_dir *local_conf = 0; /* so we can default stuff nicely */
933 struct afsconf_cell cellinfo;
935 if (as->parms[12].items) { /* if conf dir specified */
936 cdir = as->parms[12].items->data;
937 if (as->parms[13].items || as->parms[14].items || as->parms[15].items) {
938 printf("Can't specify conf dir and other cell parameters\n");
939 return AFSCONF_SYNTAX;
943 /* if we need to default cell name or cell servers, get local conf info */
945 if (!(local_conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))
946 && !(local_conf = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH))) {
947 printf("** Can't local configuration!\n");
948 return AFSCONF_NOCELL;
951 if (as->parms[13].items) { /* if cell name specified */
952 lcstring(lcell, as->parms[13].items->data, sizeof(lcell));
953 code = afsconf_GetCellInfo(local_conf, lcell, 0, &cellinfo);
954 if (code == 0)
955 strncpy(lcell, cellinfo.name, sizeof(lcell));
956 } else {
957 code = afsconf_GetLocalCell(local_conf, lcell, sizeof(lcell));
958 if (code)
959 return code;
962 if (as->parms[14].items) { /* noauth flag */
963 noAuth = 1;
966 if (as->parms[15].items) { /* servers list */
967 serverList = as->parms[15].items;
968 for (i = 0; serverList; i++, serverList = serverList->next) {
969 struct hostent *th;
970 if (i >= MAXHOSTSPERCELL)
971 return AFSCONF_FULL;
972 strncpy(cellinfo.hostName[i], serverList->data, MAXHOSTCHARS);
973 th = gethostbyname(cellinfo.hostName[i]);
974 if (!th)
975 return UBADHOST;
976 memcpy(&cellinfo.hostAddr[i].sin_addr, th->h_addr,
977 sizeof(afs_int32));
978 cellinfo.hostAddr[i].sin_family = AF_INET;
979 cellinfo.hostAddr[i].sin_port = 0;
980 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
981 cellinfo.hostAddr[i].sin_len = sizeof(struct sockaddr_in);
982 #endif
984 cellinfo.numServers = i;
985 strcpy(cellinfo.name, lcell);
986 } else {
987 code = afsconf_GetCellInfo(local_conf, lcell, 0, &cellinfo);
988 if (code)
989 return code;
992 if (local_conf)
993 afsconf_Close(local_conf);
995 if (cdir == 0) {
996 FILE *f;
998 sprintf(tmp_conf_dir, "%s/afsconf.%lu", gettmpdir(),
999 (unsigned long)getpid());
1000 code = mkdir(tmp_conf_dir, 0777);
1001 if ((code < 0) && (errno != EEXIST)) {
1002 afs_com_err(whoami, errno, "can't create temporary afsconf dir: %s",
1003 cdir);
1004 return errno;
1007 strcompose(tmp_conf_file, 128, tmp_conf_dir, "/",
1008 AFSDIR_CELLSERVDB_FILE, NULL);
1009 f = fopen(tmp_conf_file, "w");
1010 if (f == 0) {
1011 cantcreate:
1012 afs_com_err(whoami, errno, "can't create conf file %s",
1013 tmp_conf_file);
1014 return errno;
1016 fprintf(f, ">%s\n", lcell);
1017 for (i = 0; i < cellinfo.numServers; i++) {
1018 unsigned char *tp =
1019 (unsigned char *)&cellinfo.hostAddr[i].sin_addr;
1020 fprintf(f, "%d.%d.%d.%d\t#%s\n", tp[0], tp[1], tp[2], tp[3],
1021 cellinfo.hostName[i]);
1023 if (fclose(f) == EOF) {
1024 cantclose:
1025 afs_com_err(whoami, errno, "can't write to conf file %s",
1026 tmp_conf_file);
1027 return errno;
1030 strcompose(tmp_cell_file, 128, tmp_conf_dir, "/",
1031 AFSDIR_THISCELL_FILE, NULL);
1032 f = fopen(tmp_cell_file, "w");
1033 if (f == 0)
1034 goto cantcreate;
1035 fprintf(f, "%s", lcell);
1036 if (fclose(f) == EOF)
1037 goto cantclose;
1039 strcompose(tmp_noauth_file, 128, tmp_conf_dir, "/",
1040 AFSDIR_NOAUTH_FILE, NULL);
1041 if (noAuth) {
1042 code = creat(tmp_noauth_file, 0777);
1043 if (code && (errno != EEXIST))
1044 return errno;
1045 } else { /* make sure file doesn't exist */
1046 code = unlink(tmp_noauth_file);
1047 if (code && (errno != ENOENT))
1048 return errno;
1052 strncpy(conf_dir, tmp_conf_dir, sizeof(conf_dir));
1053 conf = afsconf_Open(conf_dir);
1054 if (conf == 0)
1055 return AFSCONF_NOTFOUND;
1056 return 0;
1059 static void
1060 add_std_args(struct cmd_syndesc *ts)
1062 cmd_Seek(ts, 12);
1063 cmd_AddParm(ts, "-confdir", CMD_SINGLE, CMD_OPTIONAL,
1064 "AFS Conf dir pathname");
1065 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "Cell name");
1066 cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL, "Don't authenticate");
1067 cmd_AddParm(ts, "-servers", CMD_LIST, CMD_OPTIONAL, "Server config");
1071 osi_audit(void)
1073 /* OK, this REALLY sucks bigtime, but I can't tell who is calling
1074 * afsconf_CheckAuth easily, and only *SERVERS* should be calling osi_audit
1075 * anyway. It's gonna give somebody fits to debug, I know, I know.
1077 return 0;
1080 #include "AFS_component_version_number.c"
1083 main(int argc, char *argv[])
1085 afs_int32 code;
1086 struct cmd_syndesc *ts; /* ptr to parsed command line syntax */
1088 whoami = argv[0];
1089 initialize_CMD_error_table();
1090 initialize_ACFG_error_table();
1091 initialize_KTC_error_table();
1092 initialize_U_error_table();
1093 initialize_PT_error_table();
1094 initialize_RXK_error_table();
1096 #ifdef AFS_NT40_ENV
1097 /* initialize winsock */
1098 if (afs_winsockInit() < 0) {
1099 fprintf(stderr, "%s: couldn't initialize winsock. \n", whoami);
1100 exit(1);
1102 #endif
1104 cmd_SetBeforeProc(MyBeforeProc, NULL);
1105 cmd_SetAfterProc(MyAfterProc, NULL);
1107 ts = cmd_CreateSyntax("usedIds", ListUsedIds, NULL,
1108 "Find used (or unused) user (or group) ids");
1109 cmd_AddParm(ts, "-startId", CMD_SINGLE, CMD_OPTIONAL,
1110 "id to start checking");
1111 cmd_AddParm(ts, "-number", CMD_SINGLE, CMD_OPTIONAL,
1112 "number of ids to check");
1113 cmd_AddParm(ts, "-unused", CMD_FLAG, CMD_OPTIONAL, "print unused ids");
1114 add_std_args(ts);
1116 ts = cmd_CreateSyntax("initcmd", TestPrServ, NULL, "test the prserver");
1117 add_std_args(ts);
1119 ts = cmd_CreateSyntax("testmanymembers", TestManyMembers, NULL,
1120 "test creating users and groups w/ many members");
1121 cmd_AddParm(ts, "-number", CMD_SINGLE, 0,
1122 "number of users/groups to create");
1123 cmd_AddParm(ts, "-dropoff", CMD_SINGLE, CMD_OPTIONAL,
1124 "precentage for exponential dropoff");
1125 cmd_AddParm(ts, "-prefix", CMD_SINGLE, CMD_OPTIONAL, "naming prefix");
1126 cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL, "show progress");
1127 cmd_AddParm(ts, "-seed", CMD_SINGLE, CMD_OPTIONAL, "random number seed");
1128 add_std_args(ts);
1129 cmd_CreateAlias(ts, "mm");
1132 code = cmd_Dispatch(argc, argv);
1133 if (code)
1134 afs_com_err(whoami, code, "calling cmd_Dispatch");
1135 exit(code);