Initial IBM OpenAFS 1.0 tree
[openafs.git] / src / ptserver / ptclient.c
1 /* Copyright (C) 1990, 1998 Transarc Corporation - All rights reserved */
2 /*
3  * (C) COPYRIGHT IBM CORPORATION 1988
4  * LICENSED MATERIALS - PROPERTY OF IBM
5  */
6
7 #include <afs/param.h>
8 #ifdef  AFS_AIX32_ENV
9 #include <signal.h>
10 #endif
11 #include <sys/types.h>
12 #ifdef AFS_NT40_ENV
13 #include <winsock2.h>
14 #include <WINNT/afsevent.h>
15 #else
16 #include <netinet/in.h>
17 #endif
18 #include <stdio.h>
19 #include <rx/xdr.h>
20 #include <rx/rx.h>
21 #include <string.h>
22 #include <afs/stds.h>
23 #include <afs/com_err.h>
24 #include <afs/cellconfig.h>
25 #include "ptclient.h"
26 #include "pterror.h"
27 #include <afs/afsutil.h>
28
29
30 afs_int32 security = 0;
31 char confdir[AFSDIR_PATH_MAX];
32
33 char *whoami;
34
35 extern struct ubik_client *pruclient;
36
37 static int ignoreExist = 0;
38 static char line[256];
39 static char *lineProgress;
40
41 #define WHITESPACE " \t\n"
42
43 #ifndef AFS_PTHREAD_ENV
44 int osi_audit()
45 {
46 /* OK, this REALLY sucks bigtime, but I can't tell who is calling
47  * afsconf_CheckAuth easily, and only *SERVERS* should be calling osi_audit
48  * anyway.  It's gonna give somebody fits to debug, I know, I know.
49  */
50 return 0;
51 }
52 #endif /* !AFS_PTHREAD_ENV */
53
54 int GetToken (format, l)
55   char *format;
56   afs_int32 *l;
57 {
58     int c;
59
60     *l = 0;
61     if (lineProgress == 0) lineProgress = line;
62     c = sscanf (lineProgress, format, l);
63     if (c != 1) return -1;
64     /* skip the white space */
65     lineProgress += strspn (lineProgress, WHITESPACE);
66     /* skip to end of token */
67     lineProgress = strpbrk (lineProgress, WHITESPACE);
68     return 0;
69 }
70
71 #define GetInt32(l) GetToken ("%d", l)
72 #define GetXInt32(l) GetToken ("%x", l)
73
74 int GetString (s, slen)
75   char *s;
76   int   slen;
77 {
78     char *beg;
79     int   l;
80     int   code;
81
82     if (lineProgress == 0) lineProgress = line;
83     /* skip the white space */
84     lineProgress += strspn (lineProgress, WHITESPACE);
85
86     /* check for quoted string and find end */
87     beg = lineProgress;
88     if (*beg == '"') {
89         l = strcspn (++beg, "\"");
90         if (l == strlen(beg)) return -1; /* unbalanced quotes */
91         lineProgress = beg+l+1;
92     } else {
93         l = strcspn (beg, WHITESPACE);
94         lineProgress += l;
95     }
96     if (l >= slen) {                    /* don't return too much */
97         code = -1;
98         l = slen-1;
99     } else code = 0;
100
101     strncpy (s, beg, l);
102     s[l] = 0;                           /* null termination */
103     return code;
104 }
105
106 int CodeOk (code)
107   afs_int32 code;
108 {
109     if (!ignoreExist) return code;
110     return code && (code != PREXIST) && (code != PRIDEXIST);
111 }
112
113 int PrintEntry (ea, e, indent)
114   afs_int32 ea;
115   struct prentry *e;
116   int indent;
117 {
118     /* handle screwed up versions of DumpEntry */
119     if (e->flags & PRCONT) {
120         afs_int32 id = *(afs_int32 *)(e->name);
121         if ((id != PRBADID) && ((id > (1<<24)) || (id < -(1<<24)))) {
122             /* assume server incorrectly swapped these bytes... */
123             int i = 0;
124             while (i<sizeof(e->name)) {
125                 char temp;
126                 temp = e->name[i];
127                 e->name[i] = e->name[i+3];
128                 e->name[i+3] = temp;
129                 temp = e->name[i+1];
130                 e->name[i+1] = e->name[i+2];
131                 e->name[i+2] = temp;
132                 i += 4;
133             }
134         }
135     }
136     return pr_PrintEntry (stdout, /*host order*/1, ea, e, indent);
137 }
138
139 #ifndef AFS_PTHREAD_ENV
140
141 /* main program */
142
143 #include "AFS_component_version_number.c"
144
145 main(argc, argv)
146 int argc;
147 char **argv; 
148 {
149     register afs_int32 code;
150     char op[8];
151     char name[PR_MAXNAMELEN];
152     afs_int32 id, oid, gid;
153     afs_int32 pos;
154     int i;
155     struct prentry entry;
156     prlist alist;
157     idlist lid;
158     namelist lnames;
159     afs_int32 *ptr;
160     char *foo;
161     afs_int32 over;
162     char *cell;
163
164 #ifdef  AFS_AIX32_ENV
165     /*
166      * The following signal action for AIX is necessary so that in case of a 
167      * crash (i.e. core is generated) we can include the user's data section 
168      * in the core dump. Unfortunately, by default, only a partial core is
169      * generated which, in many cases, isn't too useful.
170      */
171     struct sigaction nsa;
172     
173     sigemptyset(&nsa.sa_mask);
174     nsa.sa_handler = SIG_DFL;
175     nsa.sa_flags = SA_FULLDUMP;
176     sigaction(SIGSEGV, &nsa, NULL);
177 #endif
178     whoami = argv[0];
179
180     initialize_pt_error_table();
181
182     strcpy(confdir, AFSDIR_CLIENT_ETC_DIRPATH);
183     cell = 0;
184     i = 1;
185     while (i<argc) {
186         int arglen = strlen(argv[i]);
187         char arg[256];
188         lcstring (arg, argv[i], sizeof(arg));
189 #define IsArg(a) (strncmp (arg,a, arglen) == 0)
190         if (IsArg("-testconfdir"))
191             strncpy (confdir, argv[++i], sizeof(confdir));
192         else if (IsArg("client"))
193           strncpy(confdir, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confdir));
194         else if (IsArg("server"))
195           strncpy(confdir, AFSDIR_SERVER_ETC_DIRPATH, sizeof(confdir));
196         else if (IsArg("0") || IsArg("1") || IsArg("2"))
197             security = atoi(argv[i]);
198         else if (IsArg("-ignoreexist"))
199             ignoreExist++;
200         else if (IsArg("-cell"))
201             cell = argv[++i];
202         else {
203             printf ("Usage is: 'prclient [-testconfdir <dir> | server | client] [0 | 1 | 2] [-ignoreExist] [-cell <cellname>]\n");
204             exit (1);
205         }
206         i++;
207     }
208
209     printf ("Using CellServDB file in %s\n", confdir);
210     if (security == 0)
211         printf ("Making unauthenticated connection to prserver\n");
212
213     code = pr_Initialize (security, confdir, cell);
214     if (code) {
215         com_err (whoami, code, "Couldn't initialize protection library");
216         exit(1);
217     }
218     
219     while (1) {
220         char *s;
221
222         printf("pr> ");
223         s = fgets(line, sizeof(line), stdin);
224         if (s == NULL) break;
225         lineProgress = 0;
226
227         code = GetString (op, sizeof(op));
228         if (code) {
229             com_err (whoami, PRBADARG,
230                      "error reading opcode in line '%s', got '%.*s'",
231                      line, sizeof(op), op);
232             exit(1);
233         }
234         if (strlen(op) == 0) continue;          /* no input */
235
236         if (!strcmp(op, "cr")) {
237             if (GetString (name, sizeof(name)) ||
238                 GetInt32 (&id) ||
239                 GetInt32 (&oid)) code = PRBADARG;
240             /* use ubik_Call to do the work, finding an up server and handling
241                 the job of finding a sync site, if need be */
242             else code = ubik_Call(PR_INewEntry, pruclient,0, name, id, oid);
243             if (CodeOk(code))
244                 com_err (whoami, code, "on %s %s %d %d", op, name, id, oid);
245         }
246         else if (!strcmp(op, "sf")) {
247             afs_int32 mask, access, gq, uq;
248             if (GetInt32 (&id) ||
249                 GetXInt32 (&mask) ||
250                 GetXInt32 (&access) ||
251                 GetInt32 (&gq) ||
252                 GetInt32 (&uq)) code = PRBADARG;
253             else code = ubik_Call(PR_SetFieldsEntry, pruclient,0,
254                                   id, mask, access, gq, uq, 0,0);
255             if (CodeOk(code))
256                 com_err (whoami, code, "on %s %d %x %x %d %d",
257                          op, id, mask, access, gq, uq);
258         }
259         else if (!strcmp(op, "ce")) {
260             char newname[PR_MAXNAMELEN];
261             afs_int32 newid;
262             if (GetInt32 (&id) ||
263                 GetString (newname, sizeof(newname)) ||
264                 GetInt32 (&oid) ||
265                 GetInt32 (&newid)) code = PRBADARG;
266             else code = ubik_Call(PR_ChangeEntry, pruclient,0,
267                                   id, newname, oid, newid);
268             if (CodeOk(code))
269                 com_err (whoami, code, "on %s %d %s %d %d",
270                          op, id, newname, oid, newid);
271         }
272         else if (!strcmp(op,"wh")) {
273             /* scanf("%d",&id); */
274             if (GetInt32 (&id)) code = PRBADARG;
275             else code = ubik_Call(PR_WhereIsIt, pruclient, 0, id, &pos);
276             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
277             else printf("location %d\n",pos);
278         }
279         else if (!strcmp(op,"du")) {
280             bzero(&entry,sizeof(entry));
281             /* scanf("%d",&pos); */
282             if (GetInt32 (&pos)) code = PRBADARG;
283             else code = ubik_Call(PR_DumpEntry, pruclient, 0, pos, &entry);
284             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
285             if (code == PRSUCCESS) {
286                 PrintEntry (pos, &entry, /*indent*/0);
287 #if 0
288                 printf("The contents of the entry for %d are:\n",entry.id);
289                 printf("flags %d next %d\n",entry.flags,entry.next);
290                 printf("Groups (or members) \n");
291                 for (i=0;i<PRSIZE;i++)
292                     printf("%d\n",entry.entries[i]);
293                 printf("nextID %d nextname %d name %s\n",entry.nextID,entry.nextName,entry.name);
294                 printf("owner %d creator %d\n",entry.owner, entry.creator);
295 #endif
296             }
297         }
298         else if (!strcmp(op,"add") || !strcmp(op,"au")) {
299             /* scanf("%d %d",&id,&gid); */
300             if (GetInt32 (&id) ||
301                 GetInt32 (&gid)) code = PRBADARG;
302             else code = ubik_Call(PR_AddToGroup,pruclient,0,id,gid);
303             if (CodeOk(code))
304                 com_err (whoami, code, "on %s %d %d", op, id, gid);
305         }
306         else if (!strcmp(op,"iton")) {
307             lid.idlist_val = (afs_int32 *)malloc(20*sizeof(afs_int32));
308             ptr = lid.idlist_val;
309             lid.idlist_len = 0;
310             foo = line;
311             skip(&foo);
312             while ((lid.idlist_len < 20) && (sscanf(foo,"%d",ptr) != EOF)) {
313                 lid.idlist_len++;
314                 skip(&foo);
315                 ptr++;
316             }
317             if (*foo) {
318                 fprintf (stderr, "too many values specified; max is %d\n", 20);
319             }
320             lnames.namelist_val = 0;
321             lnames.namelist_len = 0;
322             code = ubik_Call(PR_IDToName,pruclient,0,&lid,&lnames);
323             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
324             if (code == PRSUCCESS) {
325                 for (i=0;i<lnames.namelist_len;i++) {
326                     printf("id %d name %s\n",lid.idlist_val[i],lnames.namelist_val[i]);
327                 }
328                 free(lnames.namelist_val);
329             }
330             free(lid.idlist_val);
331             lid.idlist_val = 0;
332             lid.idlist_len = 0;
333         }
334         else if (!strcmp(op,"ntoi")) {
335             lnames.namelist_val = (prname *)malloc(PR_MAXLIST*PR_MAXNAMELEN);
336             lnames.namelist_len = 0;
337             foo = line;
338             skip(&foo);
339             for (i=0; ((lnames.namelist_len < PR_MAXLIST) &&
340                        (sscanf(foo,"%s",lnames.namelist_val[i]) != EOF));
341                  i++) {
342                 lnames.namelist_len++;
343                 skip(&foo);
344             }
345             if (*foo) {
346                 fprintf (stderr, "too many values specified; max is %d\n", PR_MAXLIST);
347             }
348             lid.idlist_val = 0;
349             lid.idlist_len = 0;
350             code = ubik_Call(PR_NameToID,pruclient,0,&lnames,&lid);
351             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
352             if (code == PRSUCCESS) {
353                 for (i=0;i<lid.idlist_len;i++)
354                     printf("name %s id %d\n",lnames.namelist_val[i],lid.idlist_val[i]);
355                 free(lid.idlist_val);
356             }
357             free(lnames.namelist_val);
358             lnames.namelist_val = 0;
359             lnames.namelist_len = 0;
360         }
361         else if (!strcmp(op,"del")) {
362             /* scanf("%d",&id); */
363             if (GetInt32 (&id)) code = PRBADARG;
364             else code = ubik_Call(PR_Delete, pruclient,0,id);
365             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
366         }
367         else if (!strcmp(op,"dg")) {
368       /* scanf("%d",&id); */
369             if (GetInt32 (&id)) code = PRBADARG;
370             else code = ubik_Call(PR_Delete,pruclient,0,id);
371             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
372         }
373         else if (!strcmp(op,"rm")) {
374             /* scanf("%d %d",&id,&gid); */
375             if (GetInt32 (&id) ||
376                 GetInt32 (&gid)) code = PRBADARG;
377             else code = ubik_Call(PR_RemoveFromGroup,pruclient,0,id,gid);
378             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
379         }
380         else if (!strcmp(op,"l")) {
381             alist.prlist_len = 0;
382             alist.prlist_val = 0;
383             /* scanf("%d",&id); */
384             if (GetInt32 (&id)) code = PRBADARG;
385             else code = ubik_Call(PR_GetCPS,pruclient,0,id, &alist, &over);
386             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
387             if (code == PRSUCCESS) {
388                 ptr = alist.prlist_val;
389                 if (over) {
390                     printf("Number of groups greater than PR_MAXGROUPS!\n");
391                     printf("Excess of %d.\n",over);
392                 }
393                 for (i=0;i<alist.prlist_len;i++,ptr++)
394                     printf("%d\n",*ptr);
395                 free(alist.prlist_val);
396                 alist.prlist_len = 0;
397                 alist.prlist_val = 0;
398             }
399         }
400         else if (!strcmp(op,"nu")) {
401             /* scanf("%s",name); */
402             if (GetString (name, sizeof(name))) code = PRBADARG;
403             else code = pr_CreateUser(name,&id);
404             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
405             if (code == PRSUCCESS) 
406                 printf("Id is %d.\n",id);
407         }
408         else if (!strcmp(op,"ng")) {
409             /* scanf("%s",name); */
410             if (GetString (name, sizeof(name))) code = PRBADARG;
411             else code = ubik_Call(PR_NewEntry,pruclient,0,name,1,&id);
412             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
413             if (code == PRSUCCESS) 
414                 printf("Id is %d.\n",id);
415         }
416         else if (!strcmp(op,"lm")) {
417             code = ubik_Call(PR_ListMax,pruclient,0,&id,&gid);
418             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
419             if (code == PRSUCCESS)
420                 printf("Max user id is %d, max (really min) group is %d.\n",
421                        id,gid);
422         }
423         else if (!strcmp(op,"smu")) {
424             /* scanf("%d",&id); */
425             if (GetInt32 (&id)) code = PRBADARG;
426             else code = ubik_Call(PR_SetMax, pruclient, 0,id,0);
427             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
428         }
429         else if (!strcmp(op,"smg")) {
430             /* scanf("%d",&id); */
431             if (GetInt32 (&id)) code = PRBADARG;
432             else code = ubik_Call(PR_SetMax, pruclient, 0,id,1);
433             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
434         }
435         else if (!strcmp(op,"sin")) {
436             /* scanf("%d",&id); */
437             if (GetInt32 (&id)) code = PRBADARG;
438             else code = pr_SIdToName(id,name);
439             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
440             if (code == PRSUCCESS)
441                 printf("id %d name %s\n",id,name);
442         }
443         else if (!strcmp(op,"sni")) {
444             /* scanf("%s",name); */
445             if (GetString (name, sizeof(name))) code = PRBADARG;
446             else code = pr_SNameToId(name,&id);
447             if (CodeOk(code)) printf("%s\n",pr_ErrorMsg(code));
448             if (code == PRSUCCESS)
449                 printf("name %s id %d\n",name,id);
450         }
451         else if (!strcmp(op,"fih")) {
452             char tname[128];
453             struct PrUpdateEntry uentry;
454             bzero(&uentry, sizeof(uentry));
455             /* scanf("%s",name); */
456             if (GetString (name, sizeof(name))) {
457                 code = PRBADARG;
458                 continue;
459             }
460             code = pr_SNameToId(name,&id);
461             if (CodeOk(code)) {
462                 printf("%s\n",pr_ErrorMsg(code));
463                 continue;
464             }
465             code = pr_SIdToName(id, tname);
466             if (code == PRSUCCESS) {
467                 printf("Warning: Id hash for %s (id %d) seems correct at the db; rehashing it anyway\n", name, id);
468 /*              continue;*/
469             }
470             uentry.Mask = PRUPDATE_IDHASH;
471             code = ubik_Call(PR_UpdateEntry, pruclient, 0,0,name,&uentry);
472             if (code) {
473                 printf("Failed to update entry %s (err=%d)\n", name, code);
474                 continue;
475             }
476         }
477         else if (!strcmp(op,"fnh")) {
478             int tid;
479             struct PrUpdateEntry uentry;
480             bzero(&uentry, sizeof(uentry));
481             /* scanf("%d", &id); */
482             if (GetInt32 (&id)) {
483                 code = PRBADARG;
484                 continue;
485             }
486             code = pr_SIdToName(id, name);
487             if (CodeOk(code)) {
488                 printf("%s\n",pr_ErrorMsg(code));
489                 continue;
490             }
491             code = pr_SNameToId(name, &tid);
492             if (code == PRSUCCESS) {
493                 printf("Name hash for %d (name is %s) seems correct at the db; rehashing it anyway\n", id, name);
494 /*              continue;*/
495             }
496             uentry.Mask = PRUPDATE_NAMEHASH;
497             code = ubik_Call(PR_UpdateEntry, pruclient, 0,id,"_foo_",&uentry);
498             if (code) {
499                 printf("Failed to update entry with id %d (err=%d)\n", id, code);
500                 continue;
501             }
502         }
503         else if (!strcmp(op,"?")) 
504             PrintHelp();
505         else if (!strcmp(op,"q")) exit(0);
506         else printf("Unknown op: '%s'! ? for help\n", op);
507     }
508 }
509
510
511 PrintHelp()
512 {
513     printf("cr name id owner - create entry with name and id.\n");
514     printf("wh id  - what is the offset into database for id?\n");
515     printf("du offset - dump the contents of the entry at offset.\n");
516     printf("add uid gid - add user uid to group gid.\n");
517     printf("iton id* - translate the list of id's to names.\n");
518     printf("ntoi name* - translate the list of names to ids.\n");
519     printf("del id - delete the entry for id.\n");
520     printf("dg gid - delete the entry for group gid.\n");
521     printf("rm id gid - remove user id from group gid.\n");
522     printf("l id - get the CPS for id.\n");
523     printf("nu name - create new user with name - returns an id.\n");
524     printf("ng name - create new group with name - returns an id.\n");
525     printf("lm  - list max user id and max (really min) group id.\n");
526     printf("smu - set max user id.\n");
527     printf("smg - set max group id.\n");
528     printf("sin id - single iton.\n");
529     printf("sni name - single ntoi.\n");
530     printf("fih name - fix id hash for <name>.\n");
531     printf("fnh id - fix name hash for <id>.\n");
532     printf("q - quit.\n?- this message.\n");
533 }
534
535
536 skip(s)
537 char **s;
538 {
539     while (**s != ' ' && **s != '\0') (*s)++;
540     while (**s == ' ') (*s)++;
541 }
542 #endif /* !AFS_PTHREAD_ENV */