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