reindent-20030715
[openafs.git] / src / ptserver / ptclient.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 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID
14     ("$Header$");
15
16 #ifdef  AFS_AIX32_ENV
17 #include <signal.h>
18 #endif
19 #include <sys/types.h>
20 #ifdef AFS_NT40_ENV
21 #include <winsock2.h>
22 #include <WINNT/afsevent.h>
23 #else
24 #include <netinet/in.h>
25 #include <netdb.h>
26 #endif
27 #include <stdio.h>
28 #include <rx/xdr.h>
29 #include <rx/rx.h>
30 #include <string.h>
31 #include <afs/stds.h>
32 #include <afs/com_err.h>
33 #include <afs/cellconfig.h>
34 #include "ptclient.h"
35 #include "pterror.h"
36 #include <afs/afsutil.h>
37
38
39 afs_int32 security = 0;
40 char confdir[AFSDIR_PATH_MAX];
41
42 char *whoami;
43
44 extern struct ubik_client *pruclient;
45
46 static int ignoreExist = 0;
47 static char line[256];
48 static char *lineProgress;
49
50 #define WHITESPACE " \t\n"
51
52 #ifndef AFS_PTHREAD_ENV
53 int
54 osi_audit()
55 {
56 /* OK, this REALLY sucks bigtime, but I can't tell who is calling
57  * afsconf_CheckAuth easily, and only *SERVERS* should be calling osi_audit
58  * anyway.  It's gonna give somebody fits to debug, I know, I know.
59  */
60     return 0;
61 }
62 #endif /* !AFS_PTHREAD_ENV */
63
64 int
65 GetToken(format, l)
66      char *format;
67      afs_int32 *l;
68 {
69     int c;
70
71     *l = 0;
72     if (lineProgress == 0)
73         lineProgress = line;
74     c = sscanf(lineProgress, format, l);
75     if (c != 1)
76         return -1;
77     /* skip the white space */
78     lineProgress += strspn(lineProgress, WHITESPACE);
79     /* skip to end of token */
80     lineProgress = strpbrk(lineProgress, WHITESPACE);
81     return 0;
82 }
83
84 #define GetInt32(l) GetToken ("%d", l)
85 #define GetXInt32(l) GetToken ("%x", l)
86
87 int
88 GetString(s, slen)
89      char *s;
90      int slen;
91 {
92     char *beg;
93     int l;
94     int code;
95
96     if (lineProgress == 0)
97         lineProgress = line;
98     /* skip the white space */
99     lineProgress += strspn(lineProgress, WHITESPACE);
100
101     /* check for quoted string and find end */
102     beg = lineProgress;
103     if (*beg == '"') {
104         l = strcspn(++beg, "\"");
105         if (l == strlen(beg))
106             return -1;          /* unbalanced quotes */
107         lineProgress = beg + l + 1;
108     } else {
109         l = strcspn(beg, WHITESPACE);
110         lineProgress += l;
111     }
112     if (l >= slen) {            /* don't return too much */
113         code = -1;
114         l = slen - 1;
115     } else
116         code = 0;
117
118     strncpy(s, beg, l);
119     s[l] = 0;                   /* null termination */
120     return code;
121 }
122
123 int
124 CodeOk(code)
125      afs_int32 code;
126 {
127     if (!ignoreExist)
128         return code;
129     return code && (code != PREXIST) && (code != PRIDEXIST);
130 }
131
132 int
133 PrintEntry(ea, e, indent)
134      afs_int32 ea;
135      struct prentry *e;
136      int indent;
137 {
138     /* handle screwed up versions of DumpEntry */
139     if (e->flags & PRCONT) {
140         afs_int32 id = *(afs_int32 *) (e->name);
141         if ((id != PRBADID) && ((id > (1 << 24)) || (id < -(1 << 24)))) {
142             /* assume server incorrectly swapped these bytes... */
143             int i = 0;
144             while (i < sizeof(e->name)) {
145                 char temp;
146                 temp = e->name[i];
147                 e->name[i] = e->name[i + 3];
148                 e->name[i + 3] = temp;
149                 temp = e->name[i + 1];
150                 e->name[i + 1] = e->name[i + 2];
151                 e->name[i + 2] = temp;
152                 i += 4;
153             }
154         }
155     }
156     return pr_PrintEntry(stdout, /*host order */ 1, ea, e, indent);
157 }
158
159 #ifndef AFS_PTHREAD_ENV
160
161 /* main program */
162
163 #include "AFS_component_version_number.c"
164
165 main(argc, argv)
166      int argc;
167      char **argv;
168 {
169     register afs_int32 code;
170     char op[8];
171     char name[PR_MAXNAMELEN];
172     afs_int32 id, oid, gid;
173     afs_int32 pos;
174     int i;
175     struct prentry entry;
176     prlist alist;
177     idlist lid;
178     namelist lnames;
179     struct hostent *hostinfo;
180     struct in_addr *hostaddr;
181     afs_int32 *ptr;
182     char *foo;
183     afs_int32 over;
184     char *cell;
185
186 #ifdef  AFS_AIX32_ENV
187     /*
188      * The following signal action for AIX is necessary so that in case of a 
189      * crash (i.e. core is generated) we can include the user's data section 
190      * in the core dump. Unfortunately, by default, only a partial core is
191      * generated which, in many cases, isn't too useful.
192      */
193     struct sigaction nsa;
194
195     sigemptyset(&nsa.sa_mask);
196     nsa.sa_handler = SIG_DFL;
197     nsa.sa_flags = SA_FULLDUMP;
198     sigaction(SIGSEGV, &nsa, NULL);
199 #endif
200     whoami = argv[0];
201
202     initialize_PT_error_table();
203
204     strcpy(confdir, AFSDIR_CLIENT_ETC_DIRPATH);
205     cell = 0;
206     i = 1;
207     while (i < argc) {
208         int arglen = strlen(argv[i]);
209         char arg[256];
210         lcstring(arg, argv[i], sizeof(arg));
211 #define IsArg(a) (strncmp (arg,a, arglen) == 0)
212         if (IsArg("-testconfdir"))
213             strncpy(confdir, argv[++i], sizeof(confdir));
214         else if (IsArg("client"))
215             strncpy(confdir, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confdir));
216         else if (IsArg("server"))
217             strncpy(confdir, AFSDIR_SERVER_ETC_DIRPATH, sizeof(confdir));
218         else if (IsArg("0") || IsArg("1") || IsArg("2"))
219             security = atoi(argv[i]);
220         else if (IsArg("-ignoreexist"))
221             ignoreExist++;
222         else if (IsArg("-cell"))
223             cell = argv[++i];
224         else {
225             printf
226                 ("Usage is: 'prclient [-testconfdir <dir> | server | client] [0 | 1 | 2] [-ignoreExist] [-cell <cellname>]\n");
227             exit(1);
228         }
229         i++;
230     }
231
232     printf("Using CellServDB file in %s\n", confdir);
233     if (security == 0)
234         printf("Making unauthenticated connection to prserver\n");
235
236     code = pr_Initialize(security, confdir, cell);
237     if (code) {
238         com_err(whoami, code, "Couldn't initialize protection library");
239         exit(1);
240     }
241
242     while (1) {
243         char *s;
244
245         printf("pr> ");
246         s = fgets(line, sizeof(line), stdin);
247         if (s == NULL)
248             break;
249         lineProgress = 0;
250
251         code = GetString(op, sizeof(op));
252         if (code) {
253             com_err(whoami, PRBADARG,
254                     "error reading opcode in line '%s', got '%.*s'", line,
255                     sizeof(op), op);
256             exit(1);
257         }
258         if (strlen(op) == 0)
259             continue;           /* no input */
260
261         if (!strcmp(op, "cr")) {
262             if (GetString(name, sizeof(name)) || GetInt32(&id)
263                 || GetInt32(&oid))
264                 code = PRBADARG;
265             /* use ubik_Call to do the work, finding an up server and handling
266              * the job of finding a sync site, if need be */
267             else
268                 code = ubik_Call(PR_INewEntry, pruclient, 0, name, id, oid);
269             if (CodeOk(code))
270                 com_err(whoami, code, "on %s %s %d %d", op, name, id, oid);
271         } else if (!strcmp(op, "sf")) {
272             afs_int32 mask, access, gq, uq;
273             if (GetInt32(&id) || GetXInt32(&mask) || GetXInt32(&access)
274                 || GetInt32(&gq) || GetInt32(&uq))
275                 code = PRBADARG;
276             else
277                 code =
278                     ubik_Call(PR_SetFieldsEntry, pruclient, 0, id, mask,
279                               access, gq, uq, 0, 0);
280             if (CodeOk(code))
281                 com_err(whoami, code, "on %s %d %x %x %d %d", op, id, mask,
282                         access, gq, uq);
283         } else if (!strcmp(op, "ce")) {
284             char newname[PR_MAXNAMELEN];
285             afs_int32 newid;
286             if (GetInt32(&id) || GetString(newname, sizeof(newname))
287                 || GetInt32(&oid) || GetInt32(&newid))
288                 code = PRBADARG;
289             else
290                 code =
291                     ubik_Call(PR_ChangeEntry, pruclient, 0, id, newname, oid,
292                               newid);
293             if (CodeOk(code))
294                 com_err(whoami, code, "on %s %d %s %d %d", op, id, newname,
295                         oid, newid);
296         } else if (!strcmp(op, "wh")) {
297             /* scanf("%d",&id); */
298             if (GetInt32(&id))
299                 code = PRBADARG;
300             else
301                 code = ubik_Call(PR_WhereIsIt, pruclient, 0, id, &pos);
302             if (CodeOk(code))
303                 printf("%s\n", pr_ErrorMsg(code));
304             else
305                 printf("location %d\n", pos);
306         } else if (!strcmp(op, "du")) {
307             memset(&entry, 0, sizeof(entry));
308             /* scanf("%d",&pos); */
309             if (GetInt32(&pos))
310                 code = PRBADARG;
311             else
312                 code = ubik_Call(PR_DumpEntry, pruclient, 0, pos, &entry);
313             if (CodeOk(code))
314                 printf("%s\n", pr_ErrorMsg(code));
315             if (code == PRSUCCESS) {
316                 PrintEntry(pos, &entry, /*indent */ 0);
317 #if 0
318                 printf("The contents of the entry for %d are:\n", entry.id);
319                 printf("flags %d next %d\n", entry.flags, entry.next);
320                 printf("Groups (or members) \n");
321                 for (i = 0; i < PRSIZE; i++)
322                     printf("%d\n", entry.entries[i]);
323                 printf("nextID %d nextname %d name %s\n", entry.nextID,
324                        entry.nextName, entry.name);
325                 printf("owner %d creator %d\n", entry.owner, entry.creator);
326 #endif
327             }
328         } else if (!strcmp(op, "add") || !strcmp(op, "au")) {
329             /* scanf("%d %d",&id,&gid); */
330             if (GetInt32(&id) || GetInt32(&gid))
331                 code = PRBADARG;
332             else
333                 code = ubik_Call(PR_AddToGroup, pruclient, 0, id, gid);
334             if (CodeOk(code))
335                 com_err(whoami, code, "on %s %d %d", op, id, gid);
336         } else if (!strcmp(op, "iton")) {
337             lid.idlist_val = (afs_int32 *) malloc(20 * sizeof(afs_int32));
338             ptr = lid.idlist_val;
339             lid.idlist_len = 0;
340             foo = line;
341             skip(&foo);
342             while ((lid.idlist_len < 20) && (sscanf(foo, "%d", ptr) != EOF)) {
343                 lid.idlist_len++;
344                 skip(&foo);
345                 ptr++;
346             }
347             if (*foo) {
348                 fprintf(stderr, "too many values specified; max is %d\n", 20);
349             }
350             lnames.namelist_val = 0;
351             lnames.namelist_len = 0;
352             code = ubik_Call(PR_IDToName, pruclient, 0, &lid, &lnames);
353             if (CodeOk(code))
354                 printf("%s\n", pr_ErrorMsg(code));
355             if (code == PRSUCCESS) {
356                 for (i = 0; i < lnames.namelist_len; i++) {
357                     printf("id %d name %s\n", lid.idlist_val[i],
358                            lnames.namelist_val[i]);
359                 }
360                 free(lnames.namelist_val);
361             }
362             free(lid.idlist_val);
363             lid.idlist_val = 0;
364             lid.idlist_len = 0;
365         } else if (!strcmp(op, "ntoi")) {
366             lnames.namelist_val =
367                 (prname *) malloc(PR_MAXLIST * PR_MAXNAMELEN);
368             lnames.namelist_len = 0;
369             foo = line;
370             skip(&foo);
371             for (i = 0;
372                  ((lnames.namelist_len < PR_MAXLIST)
373                   && (sscanf(foo, "%s", lnames.namelist_val[i]) != EOF));
374                  i++) {
375                 lnames.namelist_len++;
376                 skip(&foo);
377             }
378             if (*foo) {
379                 fprintf(stderr, "too many values specified; max is %d\n",
380                         PR_MAXLIST);
381             }
382             lid.idlist_val = 0;
383             lid.idlist_len = 0;
384             code = ubik_Call(PR_NameToID, pruclient, 0, &lnames, &lid);
385             if (CodeOk(code))
386                 printf("%s\n", pr_ErrorMsg(code));
387             if (code == PRSUCCESS) {
388                 for (i = 0; i < lid.idlist_len; i++)
389                     printf("name %s id %d\n", lnames.namelist_val[i],
390                            lid.idlist_val[i]);
391                 free(lid.idlist_val);
392             }
393             free(lnames.namelist_val);
394             lnames.namelist_val = 0;
395             lnames.namelist_len = 0;
396         } else if (!strcmp(op, "del")) {
397             /* scanf("%d",&id); */
398             if (GetInt32(&id))
399                 code = PRBADARG;
400             else
401                 code = ubik_Call(PR_Delete, pruclient, 0, id);
402             if (CodeOk(code))
403                 printf("%s\n", pr_ErrorMsg(code));
404         } else if (!strcmp(op, "dg")) {
405             /* scanf("%d",&id); */
406             if (GetInt32(&id))
407                 code = PRBADARG;
408             else
409                 code = ubik_Call(PR_Delete, pruclient, 0, id);
410             if (CodeOk(code))
411                 printf("%s\n", pr_ErrorMsg(code));
412         } else if (!strcmp(op, "rm")) {
413             /* scanf("%d %d",&id,&gid); */
414             if (GetInt32(&id) || GetInt32(&gid))
415                 code = PRBADARG;
416             else
417                 code = ubik_Call(PR_RemoveFromGroup, pruclient, 0, id, gid);
418             if (CodeOk(code))
419                 printf("%s\n", pr_ErrorMsg(code));
420         }
421 #if defined(SUPERGROUPS)
422         else if (!strcmp(op, "lsg")) {
423             alist.prlist_len = 0;
424             alist.prlist_val = 0;
425             /* scanf("%d",&id); */
426             if (GetInt32(&id))
427                 code = PRBADARG;
428             else
429                 code =
430                     ubik_Call(PR_ListSuperGroups, pruclient, 0, id, &alist,
431                               &over);
432             if (CodeOk(code))
433                 printf("%s\n", pr_ErrorMsg(code));
434             if (code == PRSUCCESS) {
435                 ptr = alist.prlist_val;
436                 if (over) {
437                     printf("Number of groups greater than PR_MAXGROUPS!\n");
438                     printf("Excess of %d.\n", over);
439                 }
440                 for (i = 0; i < alist.prlist_len; i++, ptr++)
441                     printf("%d\n", *ptr);
442                 free(alist.prlist_val);
443                 alist.prlist_len = 0;
444                 alist.prlist_val = 0;
445             }
446         }
447 #endif /* SUPERGROUPS */
448         else if (!strcmp(op, "l")) {
449             alist.prlist_len = 0;
450             alist.prlist_val = 0;
451             /* scanf("%d",&id); */
452             if (GetInt32(&id))
453                 code = PRBADARG;
454             else
455                 code = ubik_Call(PR_GetCPS, pruclient, 0, id, &alist, &over);
456             if (CodeOk(code))
457                 printf("%s\n", pr_ErrorMsg(code));
458             if (code == PRSUCCESS) {
459                 ptr = alist.prlist_val;
460                 if (over) {
461                     printf("Number of groups greater than PR_MAXGROUPS!\n");
462                     printf("Excess of %d.\n", over);
463                 }
464                 for (i = 0; i < alist.prlist_len; i++, ptr++)
465                     printf("%d\n", *ptr);
466                 free(alist.prlist_val);
467                 alist.prlist_len = 0;
468                 alist.prlist_val = 0;
469             }
470         } else if (!strcmp(op, "lh")) {
471             alist.prlist_len = 0;
472             alist.prlist_val = 0;
473             /* scanf("%d",&id); */
474             if (GetString(name, sizeof(name)))
475                 code = PRBADARG;
476             else if (!(hostinfo = gethostbyname(name)))
477                 code = PRBADARG;
478             else {
479                 hostaddr = hostinfo->h_addr_list[0];
480                 id = ntohl(hostaddr->s_addr);
481                 code =
482                     ubik_Call(PR_GetHostCPS, pruclient, 0, id, &alist, &over);
483             }
484             if (CodeOk(code))
485                 printf("%s\n", pr_ErrorMsg(code));
486             if (code == PRSUCCESS) {
487                 ptr = alist.prlist_val;
488                 if (over) {
489                     printf("Number of groups greater than PR_MAXGROUPS!\n");
490                     printf("Excess of %d.\n", over);
491                 }
492                 for (i = 0; i < alist.prlist_len; i++, ptr++)
493                     printf("%d\n", *ptr);
494                 free(alist.prlist_val);
495                 alist.prlist_len = 0;
496                 alist.prlist_val = 0;
497             }
498         }
499 #if defined(SUPERGROUPS)
500         else if (!strcmp(op, "m")) {
501             alist.prlist_len = 0;
502             alist.prlist_val = 0;
503             /* scanf("%d",&id); */
504             if (GetInt32(&id))
505                 code = PRBADARG;
506             else
507                 code =
508                     ubik_Call(PR_ListElements, pruclient, 0, id, &alist,
509                               &over);
510             if (CodeOk(code))
511                 printf("%s\n", pr_ErrorMsg(code));
512             if (code == PRSUCCESS) {
513                 ptr = alist.prlist_val;
514                 if (over) {
515                     printf("Number of groups greater than PR_MAXGROUPS!\n");
516                     printf("Excess of %d.\n", over);
517                 }
518                 for (i = 0; i < alist.prlist_len; i++, ptr++)
519                     printf("%d\n", *ptr);
520                 free(alist.prlist_val);
521                 alist.prlist_len = 0;
522                 alist.prlist_val = 0;
523             }
524         }
525 #endif /* SUPERGROUPS */
526         else if (!strcmp(op, "nu")) {
527             /* scanf("%s",name); */
528             if (GetString(name, sizeof(name)))
529                 code = PRBADARG;
530             else
531                 code = pr_CreateUser(name, &id);
532             if (CodeOk(code))
533                 printf("%s\n", pr_ErrorMsg(code));
534             if (code == PRSUCCESS)
535                 printf("Id is %d.\n", id);
536         } else if (!strcmp(op, "ng")) {
537             /* scanf("%s",name); */
538             if (GetString(name, sizeof(name)))
539                 code = PRBADARG;
540             else
541                 code = ubik_Call(PR_NewEntry, pruclient, 0, name, 1, &id);
542             if (CodeOk(code))
543                 printf("%s\n", pr_ErrorMsg(code));
544             if (code == PRSUCCESS)
545                 printf("Id is %d.\n", id);
546         } else if (!strcmp(op, "lm")) {
547             code = ubik_Call(PR_ListMax, pruclient, 0, &id, &gid);
548             if (CodeOk(code))
549                 printf("%s\n", pr_ErrorMsg(code));
550             if (code == PRSUCCESS)
551                 printf("Max user id is %d, max (really min) group is %d.\n",
552                        id, gid);
553         } else if (!strcmp(op, "smu")) {
554             /* scanf("%d",&id); */
555             if (GetInt32(&id))
556                 code = PRBADARG;
557             else
558                 code = ubik_Call(PR_SetMax, pruclient, 0, id, 0);
559             if (CodeOk(code))
560                 printf("%s\n", pr_ErrorMsg(code));
561         } else if (!strcmp(op, "smg")) {
562             /* scanf("%d",&id); */
563             if (GetInt32(&id))
564                 code = PRBADARG;
565             else
566                 code = ubik_Call(PR_SetMax, pruclient, 0, id, 1);
567             if (CodeOk(code))
568                 printf("%s\n", pr_ErrorMsg(code));
569         } else if (!strcmp(op, "sin")) {
570             /* scanf("%d",&id); */
571             if (GetInt32(&id))
572                 code = PRBADARG;
573             else
574                 code = pr_SIdToName(id, name);
575             if (CodeOk(code))
576                 printf("%s\n", pr_ErrorMsg(code));
577             if (code == PRSUCCESS)
578                 printf("id %d name %s\n", id, name);
579         } else if (!strcmp(op, "sni")) {
580             /* scanf("%s",name); */
581             if (GetString(name, sizeof(name)))
582                 code = PRBADARG;
583             else
584                 code = pr_SNameToId(name, &id);
585             if (CodeOk(code))
586                 printf("%s\n", pr_ErrorMsg(code));
587             if (code == PRSUCCESS)
588                 printf("name %s id %d\n", name, id);
589         } else if (!strcmp(op, "fih")) {
590             char tname[128];
591             struct PrUpdateEntry uentry;
592             memset(&uentry, 0, sizeof(uentry));
593             /* scanf("%s",name); */
594             if (GetString(name, sizeof(name))) {
595                 code = PRBADARG;
596                 continue;
597             }
598             code = pr_SNameToId(name, &id);
599             if (CodeOk(code)) {
600                 printf("%s\n", pr_ErrorMsg(code));
601                 continue;
602             }
603             code = pr_SIdToName(id, tname);
604             if (code == PRSUCCESS) {
605                 printf
606                     ("Warning: Id hash for %s (id %d) seems correct at the db; rehashing it anyway\n",
607                      name, id);
608 /*              continue;*/
609             }
610             uentry.Mask = PRUPDATE_IDHASH;
611             code = ubik_Call(PR_UpdateEntry, pruclient, 0, 0, name, &uentry);
612             if (code) {
613                 printf("Failed to update entry %s (err=%d)\n", name, code);
614                 continue;
615             }
616         } else if (!strcmp(op, "fnh")) {
617             int tid;
618             struct PrUpdateEntry uentry;
619             memset(&uentry, 0, sizeof(uentry));
620             /* scanf("%d", &id); */
621             if (GetInt32(&id)) {
622                 code = PRBADARG;
623                 continue;
624             }
625             code = pr_SIdToName(id, name);
626             if (CodeOk(code)) {
627                 printf("%s\n", pr_ErrorMsg(code));
628                 continue;
629             }
630             code = pr_SNameToId(name, &tid);
631             if (code == PRSUCCESS) {
632                 printf
633                     ("Name hash for %d (name is %s) seems correct at the db; rehashing it anyway\n",
634                      id, name);
635 /*              continue;*/
636             }
637             uentry.Mask = PRUPDATE_NAMEHASH;
638             code =
639                 ubik_Call(PR_UpdateEntry, pruclient, 0, id, "_foo_", &uentry);
640             if (code) {
641                 printf("Failed to update entry with id %d (err=%d)\n", id,
642                        code);
643                 continue;
644             }
645         }
646 #if defined(SUPERGROUPS)
647         else if (!strcmp(op, "fih")) {
648             char tname[128];
649             struct PrUpdateEntry uentry;
650             bzero(&uentry, sizeof(uentry));
651             /* scanf("%s",name); */
652             if (GetString(name, sizeof(name))) {
653                 code = PRBADARG;
654                 continue;
655             }
656             code = pr_SNameToId(name, &id);
657             if (CodeOk(code)) {
658                 printf("%s\n", pr_ErrorMsg(code));
659                 continue;
660             }
661             code = pr_SIdToName(id, tname);
662             if (code == PRSUCCESS) {
663                 printf
664                     ("Warning: Id hash for %s (id %d) seems correct at the db; rehashing it anyway\n",
665                      name, id);
666 /*              continue;*/
667             }
668             uentry.Mask = PRUPDATE_IDHASH;
669             code = ubik_Call(PR_UpdateEntry, pruclient, 0, 0, name, &uentry);
670             if (code) {
671                 printf("Failed to update entry %s (err=%d)\n", name, code);
672                 continue;
673             }
674         } else if (!strcmp(op, "fnh")) {
675             int tid;
676             struct PrUpdateEntry uentry;
677             bzero(&uentry, sizeof(uentry));
678             /* scanf("%d", &id); */
679             if (GetInt32(&id)) {
680                 code = PRBADARG;
681                 continue;
682             }
683             code = pr_SIdToName(id, name);
684             if (CodeOk(code)) {
685                 printf("%s\n", pr_ErrorMsg(code));
686                 continue;
687             }
688             code = pr_SNameToId(name, &tid);
689             if (code == PRSUCCESS) {
690                 printf
691                     ("Name hash for %d (name is %s) seems correct at the db; rehashing it anyway\n",
692                      id, name);
693 /*              continue;*/
694             }
695             uentry.Mask = PRUPDATE_NAMEHASH;
696             code =
697                 ubik_Call(PR_UpdateEntry, pruclient, 0, id, "_foo_", &uentry);
698             if (code) {
699                 printf("Failed to update entry with id %d (err=%d)\n", id,
700                        code);
701                 continue;
702             }
703         }
704 #endif /* SUPERGROUPS */
705         else if (!strcmp(op, "?"))
706             PrintHelp();
707         else if (!strcmp(op, "q"))
708             exit(0);
709         else
710             printf("Unknown op: '%s'! ? for help\n", op);
711     }
712 }
713
714
715 PrintHelp()
716 {
717     printf("cr name id owner - create entry with name and id.\n");
718     printf("wh id  - what is the offset into database for id?\n");
719     printf("du offset - dump the contents of the entry at offset.\n");
720     printf("add uid gid - add user uid to group gid.\n");
721     printf("iton id* - translate the list of id's to names.\n");
722     printf("ntoi name* - translate the list of names to ids.\n");
723     printf("del id - delete the entry for id.\n");
724     printf("dg gid - delete the entry for group gid.\n");
725     printf("rm id gid - remove user id from group gid.\n");
726     printf("l id - get the CPS for id.\n");
727     printf("lh host - get the host CPS for host.\n");
728 #if defined(SUPERGROUPS)
729     printf("lsg id - get the supergroups for id.\n");
730     printf("m id - list elements for id.\n");
731 #endif
732     printf("nu name - create new user with name - returns an id.\n");
733     printf("ng name - create new group with name - returns an id.\n");
734     printf("lm  - list max user id and max (really min) group id.\n");
735     printf("smu - set max user id.\n");
736     printf("smg - set max group id.\n");
737     printf("sin id - single iton.\n");
738     printf("sni name - single ntoi.\n");
739     printf("fih name - fix id hash for <name>.\n");
740     printf("fnh id - fix name hash for <id>.\n");
741     printf("q - quit.\n?- this message.\n");
742 }
743
744
745 skip(s)
746      char **s;
747 {
748     while (**s != ' ' && **s != '\0')
749         (*s)++;
750     while (**s == ' ')
751         (*s)++;
752 }
753 #endif /* !AFS_PTHREAD_ENV */