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