ptserver: move allocation out of put_prentries() into listEntries()
[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             }
307         } else if (!strcmp(op, "add") || !strcmp(op, "au")) {
308             /* scanf("%d %d",&id,&gid); */
309             if (GetInt32(&id) || GetInt32(&gid))
310                 code = PRBADARG;
311             else
312                 code = ubik_PR_AddToGroup(pruclient, 0, id, gid);
313             if (CodeOk(code))
314                 afs_com_err(whoami, code, "on %s %d %d", op, id, gid);
315         } else if (!strcmp(op, "iton")) {
316             lid.idlist_val = malloc(20 * sizeof(afs_int32));
317             ptr = lid.idlist_val;
318             lid.idlist_len = 0;
319             foo = line;
320             skip(&foo);
321             while ((lid.idlist_len < 20) && (sscanf(foo, "%d", ptr) != EOF)) {
322                 lid.idlist_len++;
323                 skip(&foo);
324                 ptr++;
325             }
326             if (*foo) {
327                 fprintf(stderr, "too many values specified; max is %d\n", 20);
328             }
329             lnames.namelist_val = 0;
330             lnames.namelist_len = 0;
331             code = ubik_PR_IDToName(pruclient, 0, &lid, &lnames);
332             if (CodeOk(code))
333                 printf("%s\n", pr_ErrorMsg(code));
334             if (code == PRSUCCESS) {
335                 for (i = 0; i < lnames.namelist_len; i++) {
336                     printf("id %d name %s\n", lid.idlist_val[i],
337                            lnames.namelist_val[i]);
338                 }
339                 free(lnames.namelist_val);
340             }
341             free(lid.idlist_val);
342             lid.idlist_val = 0;
343             lid.idlist_len = 0;
344         } else if (!strcmp(op, "ntoi")) {
345             lnames.namelist_val = malloc(PR_MAXLIST * PR_MAXNAMELEN);
346             lnames.namelist_len = 0;
347             foo = line;
348             skip(&foo);
349             for (i = 0; ((lnames.namelist_len < PR_MAXLIST)
350                          && (sscanf(foo, "%63s", lnames.namelist_val[i]) !=
351                              EOF)); i++) {
352                 lnames.namelist_len++;
353                 skip(&foo);
354             }
355             if (*foo) {
356                 fprintf(stderr, "too many values specified; max is %d\n",
357                         PR_MAXLIST);
358             }
359             lid.idlist_val = 0;
360             lid.idlist_len = 0;
361             code = ubik_PR_NameToID(pruclient, 0, &lnames, &lid);
362             if (CodeOk(code))
363                 printf("%s\n", pr_ErrorMsg(code));
364             if (code == PRSUCCESS) {
365                 for (i = 0; i < lid.idlist_len; i++)
366                     printf("name %s id %d\n", lnames.namelist_val[i],
367                            lid.idlist_val[i]);
368                 free(lid.idlist_val);
369             }
370             free(lnames.namelist_val);
371             lnames.namelist_val = 0;
372             lnames.namelist_len = 0;
373         } else if (!strcmp(op, "del")) {
374             /* scanf("%d",&id); */
375             if (GetInt32(&id))
376                 code = PRBADARG;
377             else
378                 code = ubik_PR_Delete(pruclient, 0, id);
379             if (CodeOk(code))
380                 printf("%s\n", pr_ErrorMsg(code));
381         } else if (!strcmp(op, "dg")) {
382             /* scanf("%d",&id); */
383             if (GetInt32(&id))
384                 code = PRBADARG;
385             else
386                 code = ubik_PR_Delete(pruclient, 0, id);
387             if (CodeOk(code))
388                 printf("%s\n", pr_ErrorMsg(code));
389         } else if (!strcmp(op, "rm")) {
390             /* scanf("%d %d",&id,&gid); */
391             if (GetInt32(&id) || GetInt32(&gid))
392                 code = PRBADARG;
393             else
394                 code = ubik_PR_RemoveFromGroup(pruclient, 0, id, gid);
395             if (CodeOk(code))
396                 printf("%s\n", pr_ErrorMsg(code));
397         }
398 #if defined(SUPERGROUPS)
399         else if (!strcmp(op, "lsg")) {
400             alist.prlist_len = 0;
401             alist.prlist_val = 0;
402             /* scanf("%d",&id); */
403             if (GetInt32(&id))
404                 code = PRBADARG;
405             else
406                 code =
407                     ubik_PR_ListSuperGroups(pruclient, 0, id, &alist,
408                               &over);
409             if (CodeOk(code))
410                 printf("%s\n", pr_ErrorMsg(code));
411             if (code == PRSUCCESS) {
412                 ptr = alist.prlist_val;
413                 if (over) {
414                     printf("Number of groups greater than PR_MAXGROUPS!\n");
415                     printf("Excess of %d.\n", over);
416                 }
417                 for (i = 0; i < alist.prlist_len; i++, ptr++)
418                     printf("%d\n", *ptr);
419                 free(alist.prlist_val);
420                 alist.prlist_len = 0;
421                 alist.prlist_val = 0;
422             }
423         }
424 #endif /* SUPERGROUPS */
425         else if (!strcmp(op, "l")) {
426             alist.prlist_len = 0;
427             alist.prlist_val = 0;
428             /* scanf("%d",&id); */
429             if (GetInt32(&id))
430                 code = PRBADARG;
431             else
432                 code = ubik_PR_GetCPS(pruclient, 0, id, &alist, &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         } else if (!strcmp(op, "lh")) {
448             alist.prlist_len = 0;
449             alist.prlist_val = 0;
450             /* scanf("%d",&id); */
451             if (GetString(name, sizeof(name)))
452                 code = PRBADARG;
453             else if (!(hostinfo = gethostbyname(name)))
454                 code = PRBADARG;
455             else {
456                 hostaddr = (struct in_addr *)hostinfo->h_addr_list[0];
457                 id = ntohl(hostaddr->s_addr);
458                 code =
459                     ubik_PR_GetHostCPS(pruclient, 0, id, &alist, &over);
460             }
461             if (CodeOk(code))
462                 printf("%s\n", pr_ErrorMsg(code));
463             if (code == PRSUCCESS) {
464                 ptr = alist.prlist_val;
465                 if (over) {
466                     printf("Number of groups greater than PR_MAXGROUPS!\n");
467                     printf("Excess of %d.\n", over);
468                 }
469                 for (i = 0; i < alist.prlist_len; i++, ptr++)
470                     printf("%d\n", *ptr);
471                 free(alist.prlist_val);
472                 alist.prlist_len = 0;
473                 alist.prlist_val = 0;
474             }
475         }
476 #if defined(SUPERGROUPS)
477         else if (!strcmp(op, "m")) {
478             alist.prlist_len = 0;
479             alist.prlist_val = 0;
480             /* scanf("%d",&id); */
481             if (GetInt32(&id))
482                 code = PRBADARG;
483             else
484                 code =
485                     ubik_PR_ListElements(pruclient, 0, id, &alist,
486                               &over);
487             if (CodeOk(code))
488                 printf("%s\n", pr_ErrorMsg(code));
489             if (code == PRSUCCESS) {
490                 ptr = alist.prlist_val;
491                 if (over) {
492                     printf("Number of groups greater than PR_MAXGROUPS!\n");
493                     printf("Excess of %d.\n", over);
494                 }
495                 for (i = 0; i < alist.prlist_len; i++, ptr++)
496                     printf("%d\n", *ptr);
497                 free(alist.prlist_val);
498                 alist.prlist_len = 0;
499                 alist.prlist_val = 0;
500             }
501         }
502 #endif /* SUPERGROUPS */
503         else if (!strcmp(op, "nu")) {
504             /* scanf("%s",name); */
505             if (GetString(name, sizeof(name)))
506                 code = PRBADARG;
507             else
508                 code = pr_CreateUser(name, &id);
509             if (CodeOk(code))
510                 printf("%s\n", pr_ErrorMsg(code));
511             if (code == PRSUCCESS)
512                 printf("Id is %d.\n", id);
513         } else if (!strcmp(op, "ng")) {
514             /* scanf("%s",name); */
515             if (GetString(name, sizeof(name)))
516                 code = PRBADARG;
517             else
518                 code = ubik_PR_NewEntry(pruclient, 0, name, 1, oid, &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, "lm")) {
524             code = ubik_PR_ListMax(pruclient, 0, &id, &gid);
525             if (CodeOk(code))
526                 printf("%s\n", pr_ErrorMsg(code));
527             if (code == PRSUCCESS)
528                 printf("Max user id is %d, max (really min) group is %d.\n",
529                        id, gid);
530         } else if (!strcmp(op, "smu")) {
531             /* scanf("%d",&id); */
532             if (GetInt32(&id))
533                 code = PRBADARG;
534             else
535                 code = ubik_PR_SetMax(pruclient, 0, id, 0);
536             if (CodeOk(code))
537                 printf("%s\n", pr_ErrorMsg(code));
538         } else if (!strcmp(op, "smg")) {
539             /* scanf("%d",&id); */
540             if (GetInt32(&id))
541                 code = PRBADARG;
542             else
543                 code = ubik_PR_SetMax(pruclient, 0, id, 1);
544             if (CodeOk(code))
545                 printf("%s\n", pr_ErrorMsg(code));
546         } else if (!strcmp(op, "sin")) {
547             /* scanf("%d",&id); */
548             if (GetInt32(&id))
549                 code = PRBADARG;
550             else
551                 code = pr_SIdToName(id, name);
552             if (CodeOk(code))
553                 printf("%s\n", pr_ErrorMsg(code));
554             if (code == PRSUCCESS)
555                 printf("id %d name %s\n", id, name);
556         } else if (!strcmp(op, "sni")) {
557             /* scanf("%s",name); */
558             if (GetString(name, sizeof(name)))
559                 code = PRBADARG;
560             else
561                 code = pr_SNameToId(name, &id);
562             if (CodeOk(code))
563                 printf("%s\n", pr_ErrorMsg(code));
564             if (code == PRSUCCESS)
565                 printf("name %s id %d\n", name, id);
566         } else if (!strcmp(op, "fih")) {
567             char tname[128];
568             struct PrUpdateEntry uentry;
569             memset(&uentry, 0, sizeof(uentry));
570             /* scanf("%s",name); */
571             if (GetString(name, sizeof(name))) {
572                 code = PRBADARG;
573                 continue;
574             }
575             code = pr_SNameToId(name, &id);
576             if (CodeOk(code)) {
577                 printf("%s\n", pr_ErrorMsg(code));
578                 continue;
579             }
580             code = pr_SIdToName(id, tname);
581             if (code == PRSUCCESS) {
582                 printf
583                     ("Warning: Id hash for %s (id %d) seems correct at the db; rehashing it anyway\n",
584                      name, id);
585 /*              continue;*/
586             }
587             uentry.Mask = PRUPDATE_IDHASH;
588             code = ubik_PR_UpdateEntry(pruclient, 0, 0, name, &uentry);
589             if (code) {
590                 printf("Failed to update entry %s (err=%d)\n", name, code);
591                 continue;
592             }
593         } else if (!strcmp(op, "fnh")) {
594             int tid;
595             struct PrUpdateEntry uentry;
596             memset(&uentry, 0, sizeof(uentry));
597             /* scanf("%d", &id); */
598             if (GetInt32(&id)) {
599                 code = PRBADARG;
600                 continue;
601             }
602             code = pr_SIdToName(id, name);
603             if (CodeOk(code)) {
604                 printf("%s\n", pr_ErrorMsg(code));
605                 continue;
606             }
607             code = pr_SNameToId(name, &tid);
608             if (code == PRSUCCESS) {
609                 printf
610                     ("Name hash for %d (name is %s) seems correct at the db; rehashing it anyway\n",
611                      id, name);
612 /*              continue;*/
613             }
614             uentry.Mask = PRUPDATE_NAMEHASH;
615             code =
616                 ubik_PR_UpdateEntry(pruclient, 0, id, "_foo_", &uentry);
617             if (code) {
618                 printf("Failed to update entry with id %d (err=%d)\n", id,
619                        code);
620                 continue;
621             }
622         }
623 #if defined(SUPERGROUPS)
624         else if (!strcmp(op, "fih")) {
625             char tname[128];
626             struct PrUpdateEntry uentry;
627             memset(&uentry, 0, sizeof(uentry));
628             /* scanf("%s",name); */
629             if (GetString(name, sizeof(name))) {
630                 code = PRBADARG;
631                 continue;
632             }
633             code = pr_SNameToId(name, &id);
634             if (CodeOk(code)) {
635                 printf("%s\n", pr_ErrorMsg(code));
636                 continue;
637             }
638             code = pr_SIdToName(id, tname);
639             if (code == PRSUCCESS) {
640                 printf
641                     ("Warning: Id hash for %s (id %d) seems correct at the db; rehashing it anyway\n",
642                      name, id);
643 /*              continue;*/
644             }
645             uentry.Mask = PRUPDATE_IDHASH;
646             code = ubik_PR_UpdateEntry(pruclient, 0, 0, name, &uentry);
647             if (code) {
648                 printf("Failed to update entry %s (err=%d)\n", name, code);
649                 continue;
650             }
651         } else if (!strcmp(op, "fnh")) {
652             int tid;
653             struct PrUpdateEntry uentry;
654             memset(&uentry, 0, sizeof(uentry));
655             /* scanf("%d", &id); */
656             if (GetInt32(&id)) {
657                 code = PRBADARG;
658                 continue;
659             }
660             code = pr_SIdToName(id, name);
661             if (CodeOk(code)) {
662                 printf("%s\n", pr_ErrorMsg(code));
663                 continue;
664             }
665             code = pr_SNameToId(name, &tid);
666             if (code == PRSUCCESS) {
667                 printf
668                     ("Name hash for %d (name is %s) seems correct at the db; rehashing it anyway\n",
669                      id, name);
670 /*              continue;*/
671             }
672             uentry.Mask = PRUPDATE_NAMEHASH;
673             code =
674                 ubik_PR_UpdateEntry(pruclient, 0, id, "_foo_", &uentry);
675             if (code) {
676                 printf("Failed to update entry with id %d (err=%d)\n", id,
677                        code);
678                 continue;
679             }
680         }
681 #endif /* SUPERGROUPS */
682         else if (!strcmp(op, "?"))
683             PrintHelp();
684         else if (!strcmp(op, "q"))
685             exit(0);
686         else
687             printf("Unknown op: '%s'! ? for help\n", op);
688     }
689     return 0;
690 }
691
692
693 static void
694 PrintHelp(void)
695 {
696     printf("cr name id owner - create entry with name and id.\n");
697     printf("wh id  - what is the offset into database for id?\n");
698     printf("du offset - dump the contents of the entry at offset.\n");
699     printf("add uid gid - add user uid to group gid.\n");
700     printf("iton id* - translate the list of id's to names.\n");
701     printf("ntoi name* - translate the list of names to ids.\n");
702     printf("del id - delete the entry for id.\n");
703     printf("dg gid - delete the entry for group gid.\n");
704     printf("rm id gid - remove user id from group gid.\n");
705     printf("l id - get the CPS for id.\n");
706     printf("lh host - get the host CPS for host.\n");
707 #if defined(SUPERGROUPS)
708     printf("lsg id - get the supergroups for id.\n");
709     printf("m id - list elements for id.\n");
710 #endif
711     printf("nu name - create new user with name - returns an id.\n");
712     printf("ng name - create new group with name - returns an id.\n");
713     printf("lm  - list max user id and max (really min) group id.\n");
714     printf("smu - set max user id.\n");
715     printf("smg - set max group id.\n");
716     printf("sin id - single iton.\n");
717     printf("sni name - single ntoi.\n");
718     printf("fih name - fix id hash for <name>.\n");
719     printf("fnh id - fix name hash for <id>.\n");
720     printf("q - quit.\n?- this message.\n");
721 }
722
723 static void
724 skip(char **s)
725 {
726     while (**s != ' ' && **s != '\0')
727         (*s)++;
728     while (**s == ' ')
729         (*s)++;
730 }