deal-with-printf-as-macros-20010623
[openafs.git] / src / ptserver / testpt.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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  */
9
10 #ifndef lint
11 #endif
12 #include <afs/param.h>
13 #include <ctype.h>
14 #include <errno.h>
15 #include <sys/types.h>
16 #ifdef AFS_NT40_ENV
17 #include <winsock2.h>
18 #include <WINNT/afsevent.h>
19 #else
20 #include <sys/socket.h>
21 #include <netdb.h>
22 #include <netinet/in.h>
23 #endif
24 #include <rx/rx.h>
25 #include <rx/xdr.h>
26 #include <afs/rxgen_consts.h>
27 #include <afs/cmd.h>
28 #include <afs/auth.h>
29 #include <afs/cellconfig.h>
30 #include "ptclient.h"
31 #include "pterror.h"
32 #include <afs/afsutil.h>
33
34 extern char *ucstring();
35 extern char *lcstring();
36
37 static char *whoami = "testpr";
38 static struct afsconf_dir *conf;        /* cell info, set by MyBeforeProc */
39 static char  conf_dir[100];
40 static char  lcell[MAXCELLCHARS];
41
42 ListUsedIds (as, arock)
43   struct cmd_syndesc *as;
44   char *arock;
45 {   afs_int32  code;
46     namelist lnames;
47     idlist lids;
48     int i,j;
49     int group = 0;                      /* check groups */
50     int unused = 0;                     /* print unused */
51     int number = 100;                   /* check 100 ids */
52     afs_int32 startId = 1;
53     afs_int32 maxId;
54     int range;
55
56     if (as->parms[0].items) startId = atoi (as->parms[0].items->data);
57     if (as->parms[1].items) number = atoi (as->parms[1].items->data);
58     if (as->parms[2].items) unused = 1;
59
60     code = pr_Initialize(1, conf_dir,(char *)0);
61     if (code) {
62         com_err (whoami, code, "initializing pruser");
63         exit (1);
64     }
65     if (startId < 0) {
66         group = 1;
67         code = pr_ListMaxGroupId (&maxId);
68         if (code) {
69 bad_max:
70             com_err (whoami, code, "getting maximum id");
71             exit (2);
72         }
73         if (startId < maxId) {
74             fprintf (stderr, "Max group id is only %d.\n", maxId);
75             exit (3);
76         }
77     } else {
78         code = pr_ListMaxUserId (&maxId);
79         if (code) goto bad_max;
80         if (startId > maxId) {
81             fprintf (stderr, "Max user id is only %d.\n", maxId);
82             exit (3);
83         }
84     }
85     range = abs(startId - maxId);
86     if (range < 0) range = -range;
87     range++;                            /* number that can be printed */
88     if (range < number) {
89         fprintf (stderr, "Only %d ids to be checked.\n", range);
90         number = range;
91     }
92
93     printf ("Checking for %d %sused ids starting at %d.\n",
94             number, (unused ? "un" : ""), startId);
95 #define NUM 100
96     lids.idlist_val = (afs_int32 *)malloc(sizeof(afs_int32)*NUM);
97     lnames.namelist_len = 0;
98     lnames.namelist_val = 0;
99     while (number) {
100         if (number < NUM) i = number; else i = NUM;
101         for (j=0; j<i; j++) {
102             lids.idlist_val[j] = startId;
103             if (group) startId--; else startId++;
104         }
105         lids.idlist_len = i;
106         code = pr_IdToName (&lids, &lnames);
107         if (code) {
108             com_err (whoami, code, "converting id to name");
109             exit (2);
110         }
111         for (j=0;j<lnames.namelist_len;j++) {
112             if (lids.idlist_val[j] == atoi(lnames.namelist_val[j])) {
113                 if (unused) printf ("%s is free\n", lnames.namelist_val[j]);
114             } else {
115                 if (!unused) printf ("%s is id %d\n", lnames.namelist_val[j],
116                                      lids.idlist_val[j]);
117             }
118         }
119         number -= i;
120     }
121     if (lids.idlist_val) free (lids.idlist_val);
122     if (lnames.namelist_val) free (lnames.namelist_val);
123     return 0;
124 }
125
126 /* TestManyMembers - called with a number N.  Try creating N users and N groups
127  * and put all the users on one of the groups and one of the users on all the
128  * groups.  Also put many users on many groups.
129  *
130  * To keep track of this create an NxN matrix of membership and fill it in with
131  * a function that looks like a quarter of a circle.  That makes the first
132  * group contain every user and the first user be a member of every group. */
133
134 int   verbose;
135 char  callerName[PR_MAXNAMELEN];
136 afs_int32  callerId;
137 afs_int32  lastGroup;                   /* id of last group created */
138 afs_int32  ownerUser;                   /* first created user */
139 char  ownerUserName[PR_MAXNAMELEN];     /*  " " " name */
140 int   steepDropOff;                     /* precentage decreate in GroupLimit */
141 char *createPrefix;                     /* prefix for naming users&groups */
142 extern struct ubik_client *pruclient;   /* initialized by pr_Initialize */
143
144 /* These variables form the state if this test */
145 int number;                             /* max number of members */
146 char *population;                       /* matrix of memberships */
147 afs_int32 *users;                               /* ids of users */
148 afs_int32 *groups;                              /* ids of groups */
149 afs_int32 *groupOwners;                 /* ids of owners of groups */
150
151 /* statistics */
152 int nUsers, nGroups, nAdds, nRems, nUDels, nGDels;
153
154 int IdCmp(a,b)
155   afs_int32 *a;
156   afs_int32 *b;
157 {
158     if (*a > *b) return 1;
159     if (*a == *b) return 0;
160     if (*a < *b) return -1;
161 }
162
163 static int sqr (n)
164   int n;
165 {
166     return n*n;
167 }
168
169 static int GetGroupLimit (N, x)
170   int N;
171   int x;
172 {
173     int y;
174     double sqrt();
175
176     if ((x >= N) || (x < 0)) {
177         printf ("GetGroupLimit: input value out of range %d (%d)\n", x, N);
178         exit (10);
179     }
180     if (steepDropOff) {                 /* Use exponential decrease */
181         int i;
182         y = N;
183         for (i=0; i<x; i++) {
184             y = (y*steepDropOff)/100;   /* parameter is a percentage */
185             if (y == 0) {
186                 y = 1;                  /* with a floor of 1 */
187                 break;
188             }
189         }
190     }
191     else {                              /* Use a circle's third quadrant */
192         y = sqr(N-1) - sqr(N-1-x);
193         y = (int) (sqrt ((double)y) + 0.5); /* round off */
194         y = N - y;
195     }
196     if ((y > N) || (y < 1)) {
197         printf ("filling value out of range: %d (%d) => %d\n", x, N, y);
198         exit (11);
199     }
200     return y;
201 }
202
203 CreateUser (u)
204   int u;
205 {
206     afs_int32 code;
207     char name[16];
208     afs_int32 id;
209
210     sprintf (name, "%s%d", createPrefix, u);
211     id = 0;
212     code = pr_CreateUser (name, &id);
213     if (code) {
214         if (code == PREXIST) {
215             code = pr_Delete (name);
216             if (code == 0) {
217                 nUDels++;
218                 code = pr_CreateUser (name, &id);
219                 if (code == 0) {
220                     if (verbose) printf ("RE-");
221                     goto done;
222                 }
223             }
224         }
225         com_err (whoami, code, "couldn't create %s", name);
226         exit (12);
227     }
228   done:
229     if (verbose) printf ("Creating user %s (%di)\n", name, id);
230     users[u] = id;
231     nUsers++;
232
233     if (ownerUser == 0) {
234         ownerUser = id;
235         strcpy (ownerUserName, name);
236     }
237     return;
238 }
239
240 CreateGroup (g)
241   int g;
242 {
243     afs_int32 code;
244     char name[16];
245     afs_int32 id = 0;
246     afs_int32 flags = PRGRP;
247     afs_int32 owner;
248     char *ownerName;
249     int ownerType;                      /* type of ownership */
250     static char *lastGroupPrefix;       /* prefix used for type==2 */
251
252     /* At least 50 groups should be owned by another group to test long owner
253      * chains during deletion.  Also let's create some long owners of owners
254      * lists.  */
255     ownerType = random() % 3;
256
257     if (!ownerUser) ownerType = 0;
258     if (!lastGroup) ownerType = 0;
259     switch (ownerType) {
260       case 0:
261         owner = callerId;
262         ownerName = callerName;
263         break;
264       case 1:
265         owner = ownerUser;
266         ownerName = ownerUserName;
267         break;
268       case 2:
269         owner = lastGroup;
270         ownerName = lastGroupPrefix;
271         break;
272     }
273
274     sprintf (name, "%s:%s%d", ownerName, createPrefix, g);
275     code = ubik_Call (PR_NewEntry, pruclient, 0, name, PRGRP, owner, &id);
276     if (code) {
277         if (code == PREXIST) {
278             code = pr_Delete (name);
279             if (code == 0) {
280                 nGDels++;
281                 code = ubik_Call
282                     (PR_NewEntry, pruclient, 0, name, PRGRP, owner, &id);
283                 if (code == 0) {
284                     if (verbose) printf ("RE-");
285                     goto done;
286                 }
287             }
288         }
289         com_err (whoami, code, "couldn't create %s w/ owner=%d", name, owner);
290         exit (13);
291     }
292   done:
293     if (verbose) printf ("Creating group %s (%di)\n", name, id);
294     groups[g] = id;
295     groupOwners[g] = owner;
296     nGroups++;
297     if (!lastGroup || (ownerType == 2)) {
298         lastGroup = id;
299         lastGroupPrefix = ownerName;
300     }   
301     return;
302 }
303
304 int DeleteRandomId (list)
305   afs_int32 *list;
306 {
307     afs_int32 code;
308     afs_int32 id;
309     int j,k;
310     int m;
311
312     k = random();                       /* random starting point */
313     for (j=0; j<number; j++) {          /* find an undeleted id */
314         m = (k+j) % number;
315         if (id = list[m]) {
316             code = ubik_Call (PR_Delete, pruclient, 0, id);
317             if (code) {
318                 com_err (whoami, code, "Couldn't delete %di", id);
319                 exit (22);
320             }
321             list[m] = 0;
322             if (list == users) nUDels++;
323             else nGDels++;
324             return 0;
325         }
326     }
327     return -1;                          /* none left */
328 }
329
330 AddUser (u, g)
331   int u,g;
332 {
333     afs_int32 code;
334     afs_int32 ui, gi;
335
336     if (users[u] == 0)                  /* create if necessary */
337         CreateUser (u);
338     if (groups[g] == 0)                 /* create group if necessary */
339         CreateGroup (g);
340     ui = users[u];
341     gi = groups[g];
342     code = ubik_Call(PR_AddToGroup, pruclient, 0, ui, gi);
343     if (code) {
344         com_err (whoami, code, "couldn't add %d to %d", ui, gi);
345         exit (14);
346     }
347     if (verbose) printf ("Adding user (%di) to group (%di)\n", ui, gi);
348     population[u*number+g]++;
349     nAdds++;
350     return;
351 }
352
353 RemUser (u, g)
354   int u,g;
355 {
356     afs_int32 code;
357     afs_int32 ui, gi;
358
359     ui = users[u];
360     gi = groups[g];
361     code = ubik_Call(PR_RemoveFromGroup, pruclient, 0, ui, gi);
362     if (code) {
363         com_err (whoami, code, "couldn't remove %d from %d", ui, gi);
364         exit (14);
365     }
366     if (verbose) printf ("Removing user (%di) from group (%di)\n", ui, gi);
367     population[u*number+g]--;
368     nRems++;
369     return;
370 }
371
372 TestManyMembers (as, arock)
373   struct cmd_syndesc *as;
374   char *arock;
375 {
376     char *filled;                       /* users filled up */
377     char *cleaned;                      /* users cleaned up */
378
379     int nFilled, nCleaned;
380     int u,g, i,j, n;
381     int seed;                           /* random number generator seed */
382
383     afs_int32 *glist;                   /* membership list */
384
385     afs_int32 code;
386
387     code = pr_Initialize(1, conf_dir,(char *)0);
388     if (code) {
389         com_err (whoami, code, "initializing pruser");
390         exit (1);
391     }
392     /* get name of person running command */
393     {   struct ktc_principal afs, user;
394         struct ktc_token token;
395
396         strcpy (afs.name, "afs");
397         strcpy (afs.instance, "");
398         code = afsconf_GetLocalCell (conf, afs.cell, sizeof(afs.cell));
399         if (code) exit (2);
400         code = ktc_GetToken (&afs, &token, sizeof(token), &user);
401         if (code) {
402             com_err (whoami, code, "getting afs tokens");
403             exit (3);
404         }
405         if (strlen(user.instance) > 0) {
406             fprintf (stderr, "can't handle non-null instance %s.%s\n", user.name, user.cell);
407             exit (4);
408         }
409         if (strncmp (user.name, "AFS ID ", 7) == 0) {
410             callerId = atoi (user.name+7);
411             code = pr_SIdToName (callerId, callerName);
412             if (code) {
413                 com_err (whoami, code, "call get name for id %d", callerId);
414                 exit (6);
415             }
416         } else {
417             strcpy (callerName, user.name);
418             code = pr_SNameToId (callerName, &callerId);
419             if ((code == 0) && (callerId == ANONYMOUSID)) code = PRNOENT;
420         }
421 #if 0 /* don't create user */
422         if (code == PRNOENT) {
423             callerId = 0;
424             code = pr_CreateUser (callerName, &callerId);
425             if (code) {
426                 com_err (whoami, code, "can't create caller %s", callerName);
427                 exit (5);
428             }
429             printf ("Creating caller %s (%di)\n", callerName, callerId);
430         }
431         /* else */
432 #endif
433         if (code) {
434             com_err (whoami, code, "can't find caller %s", callerName);
435             exit (6);
436         }
437         else printf ("Assuming caller is %s (%di)\n", callerName, callerId);
438     }
439
440     /* Parse arguments */
441     if (as->parms[0].items) number = atoi (as->parms[0].items->data);
442     if (as->parms[1].items) {
443         steepDropOff = atoi (as->parms[1].items->data);
444         if ((steepDropOff < 0) || (steepDropOff > 100)) {
445             fprintf (stderr, "Illegal value for dropoff: %d, must be between 0 and 100, inclusive.\n", steepDropOff);
446             exit (7);
447         }
448     } else steepDropOff = 0;            /* use quadratic dropoff */
449     if (as->parms[2].items) createPrefix = as->parms[2].items->data;
450     else createPrefix = "u";
451     if (as->parms[3].items) verbose = 1;
452     else verbose = 0;
453     if (as->parms[4].items) seed = atoi(as->parms[4].items->data);
454     else seed = 1;
455
456     srandom(seed);
457
458     users = (afs_int32 *) malloc (number*sizeof(afs_int32));
459     groups = (afs_int32 *) malloc (number*sizeof(afs_int32));
460     filled = (char *) malloc (number*sizeof(char));
461     cleaned = (char *) malloc (number*sizeof(char));
462     population = (char *)malloc (sqr(number)*sizeof(char));
463
464     nFilled = 0;
465     bzero (filled, number);
466     nCleaned = 0;
467     bzero (cleaned, number);
468     bzero (population, sqr(number));
469     bzero (users, number*sizeof(afs_int32));
470     bzero (groups, number*sizeof(afs_int32));
471
472     ownerUser = lastGroup = 0;
473     groupOwners = (afs_int32 *) malloc (number*sizeof(afs_int32));
474     nUsers = nGroups = nAdds = nRems = nUDels = nGDels = 0;
475
476     while ((nFilled < number) || (nCleaned < number)) {
477         /* pick a user at random, using  */
478         u = random() % number;
479         if (!filled[u]) {
480             n = GetGroupLimit (number, u); /* get group limit for that user */
481             g = random() % (n+1);       /* pick a random group */
482             if (g == n) {               /* in a few cases create any user */
483                 n = number;             /* in the whole range */
484                 g = random() % n;
485             }
486             for (i=0; i<n; i++) {       /* rotate until unused one found */
487                 j = (g+i) % n;
488                 if (!population[u*number+j]) {
489                     /* add this user/group membership */
490                     AddUser (u, j);
491                     goto added;
492                 }
493             }
494             filled[u]++;
495             nFilled++;
496           added:;
497         }
498         if (!cleaned[u]) {
499             int base;
500             if (filled[u]) {            /* only clean above GroupLimit */
501                 base = GetGroupLimit (number, u);
502                 n = number - base;
503                 if (n == 0) goto iscleaned;
504                 g = random() % n;
505             }
506             else {
507                 base = 0;
508                 n = number;             /* pick a group from the whole range */
509                 g = random() % 2*n;     /* at random for removal */
510                 if (g >= n) goto remed; /* but half the time do nothing */
511             }
512             for (i=0; i<n; i++) {       /* rotate until used one found */
513                 j = (g+i) % n + base;
514                 if (population[u*number+j]) {
515                     /* remove this user/group membership */
516                     RemUser (u, j);
517                     goto remed;
518                 }
519             }
520             if (filled[u]) {            /* track finished ones */
521               iscleaned:
522                 cleaned[u]++;
523                 nCleaned++;
524             }
525           remed:;
526         }
527     }
528
529     /* check the membership list of all users for correctness */
530     printf ("Starting check of memberships\n");
531     glist = (afs_int32 *)malloc (number*sizeof(afs_int32));
532     for (u=0; u<number; u++) {
533         afs_int32 ui = users[u];
534         if (ui) {
535             int i, j;
536             int ng;                     /* number groups */
537             int (*proc)();              /* membership listing procedure */
538             int over;
539             prlist alist;
540
541             alist.prlist_len = 0;
542             alist.prlist_val = 0;
543             if (random() & 4) proc = PR_ListElements;
544             else proc = PR_GetCPS;
545             code = ubik_Call (proc, pruclient, 0, ui, &alist, &over);
546             if (code) {
547                 com_err (whoami, code,
548                          "getting membership list of (%di) using %s", ui,
549                          ((proc == PR_GetCPS) ? "GetCPR" : "ListElements"));
550                 exit (24);
551             }
552             if (over) {
553                 fprintf (stderr,
554                          "membership list for id %di too long\n", ui);
555             }
556             ng = 0;
557             for (i=0; i<number; i++)
558                 if (population[u*number+i])
559                     glist[ng++] = groups[i];
560             qsort (glist, ng, sizeof(afs_int32), IdCmp);
561             if (ng != (alist.prlist_len - ((proc == PR_GetCPS) ? 3 : 0))) {
562                 fprintf (stderr, "Membership list for %di of unexpected length: was %d but expected %d\n", ui, alist.prlist_len, ng);
563                 exit (20);
564             }
565             /* all the extra entries for the CPS should be at the end. */
566             code = 0;
567             for (i=0; i<ng; i++)
568                 if (alist.prlist_val[i] != glist[i]) {
569                     fprintf (stderr, "membership for %di not correct: was %di but expected %di\n", ui, alist.prlist_val[i], glist[i]);
570                     code ++;
571                 }
572             if (code) exit (21);
573             if (proc == PR_GetCPS) {
574                 if ((alist.prlist_val[i /* =ng */] != AUTHUSERID) ||
575                     (alist.prlist_val[++i] != ANYUSERID) ||
576                     (alist.prlist_val[++i] != ui)) {
577                     fprintf (stderr, "CPS doesn't have extra entries\n");
578                     exit (27);
579                 }
580             }
581             if (alist.prlist_val) free(alist.prlist_val);
582
583             /* User 0 is a member of all groups all of which should also be on
584              * the owner list of the caller or the ownerUser, although there
585              * may also be others.  Check this. */
586             if (u == 0) {
587                 prlist callerList;
588                 prlist ownerList;
589                 prlist lastGroupList;
590                 int i,j,k,l;
591
592                 if (ng != number) {
593                     fprintf (stderr, "User 0 not a member of all groups\n");
594                     exit (26);
595                 }
596
597 #define GETOWNED(xlist,xid) \
598   (xlist).prlist_val = 0; (xlist).prlist_len = 0; \
599   code = ubik_Call (PR_ListOwned, pruclient, 0, (xid), &(xlist), &over); \
600   if (code) { \
601       com_err (whoami, code, "getting owner list of (%di)", (xid)); \
602       exit (23); } \
603   if (over) \
604       { fprintf (stderr, "membership of id %di too long\n", (xid)); }
605
606                 GETOWNED (callerList, callerId);
607                 GETOWNED (ownerList, ownerUser);
608
609                 /* look for every entry in glist, in all the owner lists */
610                 for (i=j=k=l=0; i<number; i++) {
611                     while ((j < callerList.prlist_len) &&
612                            (callerList.prlist_val[j] < glist[i])) j++;
613                     while ((k < ownerList.prlist_len) &&
614                            (ownerList.prlist_val[k] < glist[i])) k++;
615 #define PRLISTCMP(l,i) \
616   (((l).prlist_len == 0) || (glist[i] != (l).prlist_val[(i)]))
617                     if (PRLISTCMP(callerList,j) &&
618                         PRLISTCMP(ownerList,k)) {
619                         for (l=0; l<number; l++) {
620                             if (groups[l] == glist[i]) {
621                                 if ((groupOwners[l] != callerId) &&
622                                     (groupOwners[l] != ownerUser)) {
623                                     GETOWNED (lastGroupList, groupOwners[l]);
624                                     if ((lastGroupList.prlist_len != 1) ||
625                                         (lastGroupList.prlist_val[0] != glist[i])) {
626                                         fprintf (stderr, "Group (%di) not on any owner list\n", glist[i]);
627                                         exit (25);
628                                     }
629                                 }
630                                 goto foundLast;
631                             }
632                         }
633                         fprintf (stderr, "unexpected group %di\n", glist[i]);
634                       foundLast:;
635                     }
636                 }
637                 if (callerList.prlist_val) free(callerList.prlist_val);
638                 if (ownerList.prlist_val) free(ownerList.prlist_val);
639                 if (lastGroupList.prlist_val) free(lastGroupList.prlist_val);
640             }
641         }
642     }
643
644     /* cleanup by deleting all the users and groups */
645     printf ("Starting deletion of users and groups\n");
646     for (i=0; i<number; i++) {
647         DeleteRandomId (users);
648         DeleteRandomId (groups);
649     }
650
651     printf ("Created/deleted %d/%d users and %d/%d groups; added %d and removed %d.\n",
652             nUsers, nUDels, nGroups, nGDels, nAdds, nRems);
653     return 0;
654 }
655
656 /* from ka_ConvertBytes included here to avoid circularity */
657 /* Converts a byte string to ascii.  Return the number of unconverted bytes. */
658
659 static int ka_ConvertBytes (ascii, alen, bs, bl)
660   char *ascii;                          /* output buffer */
661   int   alen;                           /* buffer length */
662   char  bs[];                           /* byte string */
663   int   bl;                             /* number of bytes */
664 {   int i;
665     unsigned char c;
666
667     alen--;                             /* make room for termination */
668     for (i=0; i < bl; i++) {
669         c = bs[i];
670         if (alen <= 0) return bl-i;
671         if (isalnum(c) || ispunct(c)) (*ascii++ = c), alen--;
672         else {
673             if (alen <= 3) return bl-i;
674             *ascii++ = '\\';
675             *ascii++ = (c>>6) + '0';
676             *ascii++ = (c>>3 & 7) + '0';
677             *ascii++ = (c&7) + '0';
678             alen -= 4;
679         }
680     }
681     *ascii = 0;                         /* terminate string */
682 }
683
684 /* This runs various tests on the server.  It creates, then deletes, a bunch of
685  * users and groups, so it would be safest to run it on a test database.
686  *
687  * These are the things I check for:
688  *   User names longer than PR_MAXNAMELEN - strlen(cellname).
689  *   Group names longer than PR_MAXNAMELEN.
690  *   User names containing all legal 8-bit ascii characters.  This excludes
691  *     only ':', '@', and '\n'.
692  *   Group names as above, but at least one colon is required, and the owner
693  *     must be correct.
694  */
695
696 TestPrServ (as, arock)
697   struct cmd_syndesc *as;
698   char *arock;
699 {
700     afs_int32 id;
701     char name[PR_MAXNAMELEN+1];
702     char creator[PR_MAXNAMELEN];        /* our name */
703     struct prcheckentry ent;
704     afs_int32 code;
705     int i,j;
706     int maxLen = PR_MAXNAMELEN-1 - strlen(lcell) - 1;
707
708     code = pr_Initialize(1, conf_dir,(char *)0);
709     if (code) {
710         com_err (whoami, code, "initializing pruser");
711         exit (1);
712     }
713
714     for (i=0; i<maxLen; i++) name[i] = 'a';
715     name[i]='a';                        /* too long a name... */
716     name[i+1]=0;
717     id = 0;
718     code = pr_CreateUser (name, &id);
719     if ((code != RXGEN_CC_MARSHAL) && (code != PRBADNAM)) {
720         com_err (whoami, code, "succeeded creating %s", name);
721         exit (2);
722     }
723     name[i]=0;
724     id = 0;
725     code = pr_CreateUser (name, &id);
726     if (code == PREXIST) {
727         fprintf (stderr, "group already exists, skipping\n");
728         pr_SNameToId (name, &id);
729     } else if (code) {
730         com_err (whoami, code, "failed creating %s", name);
731         exit (3);
732     }
733     if ((code = pr_ListEntry (id, &ent)) ||
734         (code = pr_SIdToName (ent.creator, creator))) {
735         com_err (whoami, code, "getting creator's name");
736         exit (5);
737     }
738     code = pr_DeleteByID (id);
739     if (code) {
740         com_err (whoami, code, "deleting %s", name);
741         exit (6);
742     }
743     /* now make sure the illegal chars are detected */
744     {   char *illegalChars;
745         for (illegalChars = "@:\n"; *illegalChars; illegalChars++) {
746             name[10] = *illegalChars;
747             id = 0;
748             code = pr_CreateUser (name, &id);
749             if (code != PRBADNAM) {
750                 com_err (whoami, code, "succeeded creating %s", name);
751                 exit (8);
752             }
753         }
754     }
755
756     for (i=1; i <= 255;) {              /* for all 8-bit ascii... */
757         j=0;                            /* build a new name */
758         while ((j<maxLen) && (i<=255)) {
759             if (!((i == ':') || (i == '@') || (i == '\n')))
760                 name[j++] = i;
761             i++;
762         }
763         name[j]=0;                      /* terminate string */
764         id = 0;
765         code = pr_CreateUser (name, &id);
766         if (code == PREXIST) {
767             fprintf (stderr, "user already exists, skipping\n");
768             pr_SNameToId (name, &id);
769         } else if (code) {
770             char ascii[BUFSIZ];
771             ka_ConvertBytes (ascii, sizeof(ascii), name, strlen(name));
772             com_err (whoami, code, "failed creating %s", ascii);
773             exit (4);
774         }
775         code = pr_DeleteByID (id);
776         if (code) {
777             com_err (whoami, code, "deleting %s", name);
778             exit (7);
779         }
780     }
781
782     /* now check group names */
783     strcpy (name, creator);
784     strcat (name, ":abcdefghijklmnopqrstuvwxyz");
785     name[0] = 1;                        /* bash the owner name */
786     id = 0;
787     code = pr_CreateGroup (name, &id);
788     if (code != PRNOENT) {              /* owner doesn't exist */
789         com_err (whoami, code, "succeeded creating %s", name);
790         exit (9);
791     }
792     name[0] = creator[0];               /* fix owner */
793     /* Make sure the illegal chars are detected */
794     {   char *illegalChars;
795         for (illegalChars = ":@\n"; *illegalChars; illegalChars++) {
796             name[strlen(creator)+10] = *illegalChars;
797             id = 0;
798             code = pr_CreateGroup (name, creator, &id);
799             if (code != PRBADNAM) {
800                 com_err (whoami, code, "succeeded creating %s", name);
801                 exit (10);
802             }
803         }
804     }
805     for (i=1; i <= 255;) {              /* for all 8-bit ascii... */
806         j=strlen(creator)+1;            /* build a new name */
807         while ((j<PR_MAXNAMELEN-1) && (i<=255)) {
808             if (!((i == ':') || (i == '@') || (i == '\n')))
809                 name[j++] = i;
810             i++;
811         }
812         name[j]=0;                      /* terminate string */
813         id = 0;
814         code = pr_CreateGroup (name, creator, &id);
815         if (code == PREXIST) {
816             fprintf (stderr, "group already exists, skipping\n");
817             pr_SNameToId (name, &id);
818         } else if (code) {
819             char ascii[BUFSIZ];
820             ka_ConvertBytes (ascii, sizeof(ascii), name, strlen(name));
821             com_err (whoami, code, "failed creating %s", ascii);
822             exit (4);
823         }
824         code = pr_DeleteByID (id);
825         if (code) {
826             com_err (whoami, code, "deleting %s", name);
827             exit (7);
828         }
829     }
830
831     printf ("All OK\n");
832     return 0;
833 }
834
835 static char tmp_conf_dir[128] = "";
836 static char tmp_conf_file[128] = "";
837 static char tmp_cell_file[128] = "";
838 static char tmp_noauth_file[128] = "";
839
840 static int MyAfterProc (as, arock)
841   struct cmd_syndesc *as;
842   char *arock;
843 {   afs_int32  code;
844     if (strlen (tmp_conf_file)) unlink (tmp_conf_file);
845     if (strlen (tmp_cell_file)) unlink (tmp_cell_file);
846     if (strlen (tmp_noauth_file)) unlink (tmp_noauth_file);
847     if (strlen (tmp_conf_dir)) rmdir (tmp_conf_dir);
848     return 0;
849 }
850
851 static int MyBeforeProc (as, arock)
852   struct cmd_syndesc *as;
853   char *arock;
854 {   afs_int32  code;
855     int   i;
856     char *cdir = 0;
857     int   noAuth = 0;
858     struct cmd_item *serverList = 0;
859     struct afsconf_dir *local_conf = 0; /* so we can default stuff nicely */
860     struct afsconf_cell cellinfo;
861
862     if (as->parms[12].items) {          /* if conf dir specified */
863         cdir = as->parms[12].items->data;
864         if (as->parms[13].items || as->parms[14].items || as->parms[15].items) {
865             printf ("Can't specify conf dir and other cell parameters\n");
866             return AFSCONF_SYNTAX;
867         }
868     }
869
870     /* if we need to default cell name or cell servers, get local conf info */
871
872     if (!(local_conf = afsconf_Open (AFSDIR_CLIENT_ETC_DIRPATH)) &&
873         !(local_conf = afsconf_Open (AFSDIR_SERVER_ETC_DIRPATH))){
874         printf("** Can't local configuration!\n");
875         return AFSCONF_NOCELL;
876     }
877
878     if (as->parms[13].items) {          /* if cell name specified */
879         lcstring (lcell, as->parms[13].items->data, sizeof(lcell));
880         code = afsconf_GetCellInfo (local_conf, lcell, 0, &cellinfo);
881         if (code == 0) strncpy (lcell, cellinfo.name, sizeof(lcell));
882     } else {
883         code = afsconf_GetLocalCell (local_conf, lcell, sizeof(lcell));
884         if (code) return code;
885     }
886
887     if (as->parms[14].items) {          /* noauth flag */
888         noAuth = 1;
889     }
890
891     if (as->parms[15].items) {          /* servers list */
892         serverList = as->parms[15].items;
893         for (i=0; serverList; i++, serverList = serverList->next) {
894             struct hostent *th;
895             if (i >= MAXHOSTSPERCELL) return AFSCONF_FULL;
896             strncpy (cellinfo.hostName[i], serverList->data, MAXHOSTCHARS);
897             th = gethostbyname(cellinfo.hostName[i]);
898             if (!th) return UBADHOST;
899             bcopy(th->h_addr, &cellinfo.hostAddr[i].sin_addr, sizeof(afs_int32));
900             cellinfo.hostAddr[i].sin_family = AF_INET;
901             cellinfo.hostAddr[i].sin_port = 0;
902         }
903         cellinfo.numServers = i;
904         strcpy (cellinfo.name, lcell);
905     } else {
906         code = afsconf_GetCellInfo (local_conf, lcell, 0, &cellinfo);
907         if (code) return code;
908     }
909
910     if (local_conf) afsconf_Close (local_conf);
911
912     if (cdir == 0) {
913         FILE *f;
914
915         sprintf (tmp_conf_dir, "%s/afsconf.%lu", gettmpdir(), (unsigned long) getpid());
916         code = mkdir (tmp_conf_dir, 0777);
917         if ((code < 0) && (errno != EEXIST)) {
918             com_err (whoami, errno, "can't create temporary afsconf dir: %s", cdir);
919             return errno;
920         }
921         
922         strcompose(tmp_conf_file, 128, tmp_conf_dir, "/", AFSDIR_CELLSERVDB_FILE, NULL);
923         f = fopen (tmp_conf_file, "w");
924         if (f == 0) {
925           cantcreate:
926             com_err (whoami, errno, "can't create conf file %s", tmp_conf_file);
927             return errno;
928         }
929         fprintf (f, ">%s\n", lcell);
930         for (i=0; i<cellinfo.numServers; i++) {
931             register unsigned char *tp = (unsigned char *)&cellinfo.hostAddr[i].sin_addr;
932             fprintf (f, "%d.%d.%d.%d\t#%s\n",
933                      tp[0], tp[1], tp[2], tp[3], cellinfo.hostName[i]);
934         }
935         if (fclose (f) == EOF) {
936           cantclose:
937             com_err (whoami, errno, "can't write to conf file %s", tmp_conf_file);
938             return errno;
939         }
940
941         strcompose(tmp_cell_file, 128, tmp_conf_dir, "/", AFSDIR_THISCELL_FILE, NULL);
942         f = fopen (tmp_cell_file, "w");
943         if (f == 0) goto cantcreate;
944         fprintf (f, "%s", lcell);
945         if (fclose(f) == EOF) goto cantclose;
946
947         strcompose(tmp_noauth_file, 128, tmp_conf_dir, "/", AFSDIR_NOAUTH_FILE, NULL);
948         if (noAuth) {
949             code = creat (tmp_noauth_file, 0777);
950             if (code && (errno != EEXIST)) return errno;
951         } else {                        /* make sure file doesn't exist */
952             code = unlink (tmp_noauth_file);
953             if (code && (errno != ENOENT)) return errno;
954         }
955     }
956
957     strncpy (conf_dir, tmp_conf_dir, sizeof(conf_dir));
958     conf = afsconf_Open (conf_dir);
959     if (conf == 0) return AFSCONF_NOTFOUND;
960     return 0;
961 }
962
963 static void add_std_args (ts)
964   register struct cmd_syndesc *ts;
965 {
966     cmd_Seek(ts, 12);
967     cmd_AddParm(ts, "-confdir", CMD_SINGLE, CMD_OPTIONAL, "AFS Conf dir pathname");
968     cmd_AddParm(ts, "-cell",   CMD_SINGLE, CMD_OPTIONAL, "Cell name");
969     cmd_AddParm(ts, "-noauth", CMD_FLAG,   CMD_OPTIONAL, "Don't authenticate");
970     cmd_AddParm(ts, "-servers", CMD_LIST,   CMD_OPTIONAL, "Server config");
971 }
972
973 int osi_audit()
974 {
975 /* OK, this REALLY sucks bigtime, but I can't tell who is calling
976  * afsconf_CheckAuth easily, and only *SERVERS* should be calling osi_audit
977  * anyway.  It's gonna give somebody fits to debug, I know, I know.
978  */
979 return 0;
980 }
981
982 #include "AFS_component_version_number.c"
983
984 main (argc, argv)
985   int   argc;
986   char *argv[];
987 {   afs_int32 code;
988     struct cmd_syndesc *ts;         /* ptr to parsed command line syntax */
989
990     whoami = argv[0];
991     initialize_cmd_error_table();
992     initialize_acfg_error_table();
993     initialize_ktc_error_table();
994     initialize_u_error_table();
995     initialize_pt_error_table();
996     initialize_rxk_error_table();
997
998 #ifdef AFS_NT40_ENV 
999     /* initialize winsock */
1000     if (afs_winsockInit()<0) {
1001       fprintf(stderr, "%s: couldn't initialize winsock. \n", whoami);
1002       exit(1);
1003     }
1004 #endif
1005
1006     cmd_SetBeforeProc(MyBeforeProc, (char *)0);
1007     cmd_SetAfterProc(MyAfterProc, (char *)0);
1008
1009     ts = cmd_CreateSyntax("usedIds", ListUsedIds, 0, "Find used (or unused) user (or group) ids");
1010     cmd_AddParm (ts, "-startId", CMD_SINGLE, CMD_OPTIONAL, "id to start checking");
1011     cmd_AddParm (ts, "-number", CMD_SINGLE, CMD_OPTIONAL, "number of ids to check");
1012     cmd_AddParm (ts, "-unused", CMD_FLAG, CMD_OPTIONAL, "print unused ids");
1013     add_std_args (ts);
1014
1015     ts = cmd_CreateSyntax("initcmd", TestPrServ, 0, "test the prserver");
1016     add_std_args (ts);
1017
1018     ts = cmd_CreateSyntax("testmanymembers", TestManyMembers, 0, "test creating users and groups w/ many members");
1019     cmd_AddParm (ts, "-number", CMD_SINGLE, 0, "number of users/groups to create");
1020     cmd_AddParm (ts, "-dropoff", CMD_SINGLE, CMD_OPTIONAL, "precentage for exponential dropoff");
1021     cmd_AddParm (ts, "-prefix", CMD_SINGLE, CMD_OPTIONAL, "naming prefix");
1022     cmd_AddParm (ts, "-long", CMD_FLAG, CMD_OPTIONAL, "show progress");
1023     cmd_AddParm (ts, "-seed", CMD_SINGLE, CMD_OPTIONAL, "random number seed");
1024     add_std_args (ts);
1025     cmd_CreateAlias(ts,"mm");
1026
1027
1028     code = cmd_Dispatch(argc, argv);
1029     if (code) com_err (whoami, code, "calling cmd_Dispatch");
1030     exit (code);
1031 }