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