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