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