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