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