pts-args-checking-when-calling-com-err-20010314
[openafs.git] / src / ptserver / pts.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 #ifndef lint
11 #endif
12 #include <afs/param.h>
13 #include <stdio.h>
14 #include <string.h>
15 #ifdef  AFS_AIX32_ENV
16 #include <signal.h>
17 #endif
18 #include <ctype.h>
19 #include <sys/types.h>
20 #include <errno.h>
21 #include <afs/cmd.h>
22 #ifdef AFS_NT40_ENV
23 #include <winsock2.h>
24 #include <WINNT/afsevent.h>
25 #else
26 #include <netinet/in.h>
27 #endif
28 #include <afs/cellconfig.h>
29 #include <rx/rx.h>
30 #include <rx/xdr.h>
31 #include "ptclient.h"
32 #include "pterror.h"
33 #include <afs/afsutil.h>
34
35 #undef FOREIGN
36
37 char *whoami;
38 int force = 0;
39
40
41 int osi_audit()
42 {
43 /* OK, this REALLY sucks bigtime, but I can't tell who is calling
44  * afsconf_CheckAuth easily, and only *SERVERS* should be calling osi_audit
45  * anyway.  It's gonna give somebody fits to debug, I know, I know.
46  */
47 return 0;
48 }
49
50 int GetGlobals (as)
51   register struct cmd_syndesc *as;
52 {
53     register afs_int32 code;
54     char *cell;
55     afs_int32 sec = 1;
56
57     whoami = as->a0name;
58
59     if (!strcmp(as->name,"help")) return 0;
60     if (as->parms[16].items) 
61         cell = as->parms[16].items->data;
62     else cell = 0;
63     if (as->parms[17].items)
64         sec = 0;
65     
66     if (as->parms[18].items) {          /* testing? */
67         code = pr_Initialize(sec, AFSDIR_SERVER_ETC_DIRPATH, cell);
68     }
69     else {
70         code = pr_Initialize(sec, AFSDIR_CLIENT_ETC_DIRPATH, cell);
71     }
72     if (code) {
73         com_err (whoami, code, "Couldn't initialize");
74         return code;
75     }
76     if (as->parms[19].items)
77         force = 1;
78     return code;
79 }
80
81 int CleanUp (as)
82   register struct cmd_syndesc *as;
83 {
84     if (!strcmp(as->name,"help")) return;
85     /* Need to shutdown the ubik_client & other connections */
86     pr_End();
87     rx_Finalize();
88
89     return 0;
90 }
91
92 CreateGroup (as)
93   register struct cmd_syndesc *as;
94 {
95     register afs_int32 code;
96     afs_int32 id;
97     char *owner;
98     struct cmd_item *namei;
99     struct cmd_item *idi;
100
101     namei = as->parms[0].items;
102     idi = as->parms[2].items;
103     if (as->parms[1].items)
104         owner = as->parms[1].items->data;
105     else owner = NULL;
106
107     while (namei) {
108         if (idi) {
109             code = util_GetInt32 (idi->data, &id);
110             if (code) {
111                 com_err (whoami, code,
112                          "because group id was: '%s'", idi->data);
113                 return code;
114             }
115             if (id >= 0) {
116                 code = PRBADARG;
117                 com_err (whoami, code,
118                          "because group id %d was not negative", id);
119                 return code;
120             }
121             idi = idi->next;
122         } else id = 0;
123
124         code = pr_CreateGroup (namei->data, owner, &id);
125         if (code) {
126             if (owner || id) 
127                 com_err (whoami, code,
128                          "; unable to create group %s with id %d%s%s%s%s",
129                          namei->data, id, owner ? " owned by '" : "",
130                          owner ? owner : "",
131                          owner ? "'" : "",
132                          (force ? " (ignored)" : ""));
133             else com_err (whoami, code,
134                          "; unable to create group %s %s", namei->data, (force?"(ignored)":""));
135             if (!force)
136                 return code;
137         }
138         printf ("group %s has id %d\n", namei->data, id);
139         namei = namei->next;
140     }
141     return 0;
142 }
143
144 CreateUser (as)
145   register struct cmd_syndesc *as;
146 {
147     register afs_int32 code;
148     afs_int32 id;
149     struct cmd_item *namei;
150     struct cmd_item *idi;
151
152     namei = as->parms[0].items;
153     idi = as->parms[1].items;
154
155     while (namei) {
156         if (idi) {
157             code = util_GetInt32 (idi->data, &id);
158             if (code) {
159                 com_err (whoami, code, "because id was: '%s'", idi->data);
160                 return code;
161             }
162             if (id == 0) {
163                 printf ("0 isn't a valid user id; aborting\n");
164                 return EINVAL;
165             }
166             idi = idi->next;
167         } else id = 0;
168
169         code = pr_CreateUser (namei->data, &id);
170         if (code) {
171             if (id) com_err (whoami, code,
172                              "; unable to create user %s with id %d %s",
173                              namei->data, id, (force?"(ignored)":""));
174             else com_err (whoami, code,
175                           "; unable to create user %s %s", namei->data, (force?"(ignored)":""));
176             if (!force)
177                 return code;
178         }
179         printf ("User %s has id %d\n", namei->data, id);
180         namei = namei->next;
181     }
182     return 0;
183 }
184
185
186 #ifdef notdef
187 int GetNameOrId (as, lids, lnames)
188   register struct cmd_syndesc *as;
189   struct idlist *lids;
190   struct namelist *lnames;
191 {
192     register afs_int32 code = 0;
193     int n = 0;
194     struct cmd_item *i;
195     int goodCount;
196
197     if (!(as->parms[0].items || as->parms[1].items)) {
198         com_err (whoami, 0, "must specify either a name or an id.");
199         return -1;
200     }
201     if (as->parms[0].items && as->parms[1].items) {
202         com_err (whoami, 0, "can't specify both a name and id.");
203         return -1;
204     }
205
206     goodCount = 0;
207     lids->idlist_len = 0;
208     lids->idlist_val = 0;
209
210     if (as->parms[0].items) {           /* name */
211         struct namelist names;          /* local copy, if not ret. names */
212         struct namelist *nl;
213
214         names.namelist_val = 0;         /* so it gets freed later if needed */
215         if (lnames) nl = lnames;
216         else nl = &names;
217
218         n = 0;                          /* count names */
219         for (i=as->parms[0].items; i; i=i->next) n++;
220         nl->namelist_val = (prname *)malloc(n*PR_MAXNAMELEN);
221         nl->namelist_len = n;
222         n = 0;
223         for (i=as->parms[0].items; i; i=i->next)
224             strncpy (nl->namelist_val[n++], i->data, PR_MAXNAMELEN);
225
226         code = pr_NameToId (nl, lids);
227         if (code) com_err (whoami, code, "so couldn't look up names");
228         else {
229             for (n=0; n<lids->idlist_len; n++) {
230                 if ((lids->idlist_val[n] == ANONYMOUSID)) {
231                     com_err (whoami, PRNOENT,
232                              "so couldn't look up id for %s", nl->namelist_val[n]);
233                 }
234                 else goodCount++;
235             }
236             /* treat things as working if any of the lookups worked */
237             if (goodCount==0) code = PRNOENT;
238         }
239         
240         if (names.namelist_val) free (names.namelist_val);
241     }
242     else if (as->parms[1].items) {      /* id */
243         n = 0;
244         for (i=as->parms[1].items; i; i=i->next) n++;
245         lids->idlist_val = (afs_int32 *)malloc(n*sizeof(afs_int32));
246         lids->idlist_len = n;
247         n = 0;
248         for (i=as->parms[1].items; i; i=i->next) {
249             code = util_GetInt32 (i->data, &lids->idlist_val[n]);
250             if (code)
251                 com_err (whoami, code=PRNOENT,
252                          "because a bogus id '%s' was specified", i->data);
253             n++;
254         }
255         if (!code && lnames) {
256             lnames->namelist_val = 0;
257             lnames->namelist_len = 0;
258             code = pr_IdToName (lids, lnames);
259             if (code) com_err (whoami, code, "translating ids");
260         }
261     }
262     if (code) {
263         if (lids->idlist_val) free (lids->idlist_val);
264         return -1;
265     }
266     return 0;
267 }
268 #endif
269
270
271 int GetNameOrId (as, lids, lnames)
272   register struct cmd_syndesc *as;
273   struct idlist *lids;
274   struct namelist *lnames;
275 {
276     register afs_int32 code = 0;
277     int n = 0, nd = 0, nm = 0, id, x;
278     struct cmd_item *i;
279     struct namelist names, tnames;      /* local copy, if not ret. names */
280     struct idlist ids, tids;            /* local copy, if not ret. ids */
281     int goodCount = 0;
282
283     for (i = as->parms[0].items; i; i = i->next) n++;
284     lids->idlist_val = (afs_int32 *)malloc(n*sizeof(afs_int32));
285     lids->idlist_len = n;
286     ids.idlist_val = (afs_int32 *)malloc(n*sizeof(afs_int32));
287     ids.idlist_len = n;
288     names.namelist_val = (prname *)malloc(n*PR_MAXNAMELEN);
289     names.namelist_len = n;
290     if (lnames) {
291         lnames->namelist_val = (prname *)malloc(n*PR_MAXNAMELEN);
292         lnames->namelist_len = 0;
293     }
294     for (i=as->parms[0].items; i; i=i->next) {
295         tnames.namelist_val = (prname *)malloc(PR_MAXNAMELEN);
296         strncpy (tnames.namelist_val[0], i->data, PR_MAXNAMELEN);           
297         tnames.namelist_len = 1;
298         tids.idlist_len =  0;
299         tids.idlist_val = 0;
300         code = pr_NameToId(&tnames, &tids);
301         if ((!code && (tids.idlist_val[0] != 32766)) || (code = util_GetInt32 (i->data, &id))) {
302             /* Assume it's a name instead */
303             strncpy (names.namelist_val[nm++], i->data, PR_MAXNAMELEN);     
304         } else {
305             ids.idlist_val[nd++] = id;
306         }
307         free(tnames.namelist_val);
308     }
309     names.namelist_len = nm;
310     ids.idlist_len = nd;
311     tids.idlist_len = nd = nm = 0;
312     tids.idlist_val = 0;
313     code = pr_NameToId (&names, &tids);
314     if (code) com_err (whoami, code, "so couldn't look up names");
315     else {
316         for (n=0; n < tids.idlist_len; n++) {
317             if ((tids.idlist_val[n] == ANONYMOUSID)) {
318                 com_err (whoami, PRNOENT,
319                          "so couldn't look up id for %s", names.namelist_val[n]);
320             } else 
321                 goodCount++;
322             lids->idlist_val[nd] = tids.idlist_val[n];
323             if (lnames)
324                 strcpy(lnames->namelist_val[nd], names.namelist_val[n]);            
325             nd++;
326         }
327     }
328     for (x=0; x < ids.idlist_len; x++) {
329         lids->idlist_val[nd+x] = ids.idlist_val[x];
330     }
331     lids->idlist_len = nd+x;    
332     if (!code && lnames) {
333         tnames.namelist_val = 0;
334         tnames.namelist_len = 0;
335         code = pr_IdToName (&ids, &tnames);
336         if (code) com_err (whoami, code, "translating ids");
337         else goodCount++;
338         if (lnames) {
339             for (x=0; x < ids.idlist_len; x++)
340                 strcpy(lnames->namelist_val[nd+x], tnames.namelist_val[x]);         
341             lnames->namelist_len = nd+x;
342         }
343     }
344     /* treat things as working if any of the lookups worked */
345     if (goodCount==0) code = PRNOENT;
346     if (code) {
347         if (lids->idlist_val) free (lids->idlist_val);
348         return -1;
349     }
350     return 0;
351 }
352
353
354 AddToGroup(as)
355   register struct cmd_syndesc *as;
356 {
357     register afs_int32 code;
358     struct cmd_item *u, *g;
359
360     for (u=as->parms[0].items; u; u=u->next) {
361         for (g=as->parms[1].items; g; g=g->next) {
362             code = pr_AddToGroup (u->data, g->data);
363             if (code) {
364                 com_err (whoami, code,
365                          "; unable to add user %s to group %s %s",
366                          u->data, g->data, (force?"(ignored)":""));
367                 if (!force)
368                     return code;
369             }
370         }
371     }
372     return 0;
373 }
374
375 RemoveFromGroup (as)
376   register struct cmd_syndesc *as;
377 {
378     register afs_int32 code;
379     struct cmd_item *u, *g;
380
381     for (u=as->parms[0].items; u; u=u->next) {
382         for (g=as->parms[1].items; g; g=g->next) {
383             code = pr_RemoveUserFromGroup (u->data, g->data);
384             if (code) {
385                 com_err (whoami, code,
386                          "; unable to remove user %s from group %s %s",
387                          u->data, g->data, (force?"(ignored)":""));
388                 if (!force)
389                     return code;
390             }
391         }
392     }
393     return 0;
394 }
395
396 ListMembership (as)
397   register struct cmd_syndesc *as;
398 {
399     register afs_int32 code;
400     idlist ids;
401     namelist names;
402     int i;
403     namelist list;
404     int j;
405
406     if (GetNameOrId(as, &ids, &names)) return PRBADARG;
407
408     for (i=0; i<ids.idlist_len; i++) {
409         afs_int32 id = ids.idlist_val[i];
410         char *name = names.namelist_val[i];
411
412         if (id == ANONYMOUSID) continue;        /* bad entry */
413
414         list.namelist_val = 0;
415         list.namelist_len = 0;
416         code = pr_IDListMembers(ids.idlist_val[i],&list);
417         if (code) {
418             com_err (whoami, code,
419                      "; unable to get membership of %s (id: %d)", name, id);
420             continue;
421         }
422         if (id < 0) printf ("Members of %s (id: %d) are:\n", name, id);
423         else printf ("Groups %s (id: %d) is a member of:\n", name, id);
424
425         for (j=0; j<list.namelist_len; j++)
426             printf("  %s\n", list.namelist_val[j]);
427         if (list.namelist_val) free (list.namelist_val);
428     }
429     if (ids.idlist_val) free (ids.idlist_val);
430     if (names.namelist_val) free (names.namelist_val);
431     return 0;
432 }
433
434 Delete (as)
435   register struct cmd_syndesc *as;
436 {
437     register afs_int32 code;
438     idlist ids;
439     namelist names;
440     int i;
441
442     if (GetNameOrId (as, &ids, &names)) return PRBADARG;
443
444     for (i=0; i<ids.idlist_len; i++) {
445         afs_int32 id = ids.idlist_val[i];
446         char *name = names.namelist_val[i];
447
448         if (id == ANONYMOUSID) continue;
449
450         code = pr_DeleteByID (id);
451         if (code) {
452             com_err (whoami, code, "deleting %s (id: %d) %s", name, id, (force?"(ignored)":""));
453             if (!force)
454                 return code;
455         }
456     }
457     if (ids.idlist_val) free (ids.idlist_val);
458     if (names.namelist_val) free (names.namelist_val);
459     return 0;
460 }
461
462 /* access bit translation info */
463
464 char *flags_upcase = "SOMA ";           /* legal all access values */
465 char *flags_dncase = "s mar";           /* legal member acces values */
466 int   flags_shift[5] = {2,1,2,2,1};     /* bits for each */
467
468 CheckEntry (as)
469   register struct cmd_syndesc *as;
470 {
471     register afs_int32 code;
472     afs_int32 rcode = 1;
473     int i, flag = 0, admin = 0;
474     namelist lnames, names;
475     idlist ids;
476     idlist lids;
477     struct prcheckentry aentry;
478
479     if (GetNameOrId (as, &ids, &names)) return PRBADARG;
480
481     lids.idlist_len = 2;
482     lids.idlist_val = (afs_int32 *)malloc(sizeof(afs_int32)*2);
483     lnames.namelist_len = 0;
484     lnames.namelist_val = 0;
485
486     for (i=0; i<ids.idlist_len; i++) {
487         afs_int32 id = ids.idlist_val[i];
488
489         if (id == ANONYMOUSID) continue;
490
491         rcode = 0;
492         code = pr_ListEntry (id, &aentry);
493         if (code) {
494             rcode = code;
495             com_err (whoami, code, "; unable to find entry for (id: %d)", id);
496             continue;
497         }
498
499         lids.idlist_val[0] = aentry.owner;
500         lids.idlist_val[1] = aentry.creator;
501         code = pr_IdToName (&lids, &lnames);
502         if (code) {
503             rcode = code;
504             com_err (whoami, code,
505                      "translating owner (%d) and creator (%d) ids",
506                      aentry.owner, aentry.creator);
507             continue;
508         }
509         printf("Name: %s, id: %d, owner: %s, creator: %s,\n",
510                aentry.name, aentry.id,
511                lnames.namelist_val[0], lnames.namelist_val[1]);
512         printf ("  membership: %d", aentry.count);
513         {   char access[6];
514             afs_int32 flags = aentry.flags;
515             int  j, s, new;
516             char c;
517             access[5] = 0;      /* null-terminate the string */
518             for (j=4; j>=0; j--) {
519                 s = flags_shift[j];
520                 if (s == 1) new = flags & 1;
521                 else new = flags & 3;
522                 if (new == 0) c = '-';
523                 else if (new == 1) {
524                     c = flags_dncase[j];
525                     if (c == ' ') c = flags_upcase[j];
526                 } else if (new == 2) c = flags_upcase[j];
527                 else c = 'X';
528                 access[j] = c;
529                 flags >>= s;
530             }
531             printf(", flags: %s", access);
532         }
533         if (aentry.id == SYSADMINID) 
534             admin = 1;
535         else if (!pr_IsAMemberOf (aentry.name, "system:administrators", &flag)) {
536             if (flag)
537                 admin = 1;
538         }
539         if (admin)
540             printf (", group quota: unlimited");                    
541         else
542             printf (", group quota: %d", aentry.ngroups);
543 #if FOREIGN
544         printf (", foreign user quota=%d", aentry.nusers);
545 #endif
546         printf (".\n");
547     }
548
549   done:
550     if (lnames.namelist_val) free(lnames.namelist_val);
551     if (lids.idlist_val) free(lids.idlist_val);
552     if (ids.idlist_val) free(ids.idlist_val);
553
554     return(rcode);
555 }
556
557 ListEntries (as)
558   struct cmd_syndesc *as;
559 {
560   afs_int32 code=0;
561   afs_int32 flag, startindex, nentries, nextstartindex;
562   struct prlistentries *entriesp=0, *e;
563   afs_int32 i;
564
565   flag = PRUSERS;
566   if (as->parms[1].items) flag  = PRGROUPS;
567   if (as->parms[0].items) flag |= PRUSERS;
568   
569   printf("Name                          ID  Owner Creator\n");
570   for (startindex = 0; startindex!=-1; startindex=nextstartindex) {
571      code = pr_ListEntries(flag, startindex, &nentries, &entriesp, &nextstartindex);
572      if (code) {
573         com_err (whoami, code, "; unable to list entries\n");
574         if (entriesp) free(entriesp);
575         break;
576      }
577
578      /* Now display each of the entries we read */
579      for (i=0,e=entriesp; i<nentries; i++,e++) {
580         printf("%-25s %6d %6d %7d \n", e->name, e->id, e->owner, e->creator);
581      }
582      if (entriesp) free(entriesp);
583   }
584   return code;
585 }
586
587 ChownGroup (as)
588   register struct cmd_syndesc *as;
589 {
590     register afs_int32 code;
591     char *name;
592     char *owner;
593
594     name = as->parms[0].items->data;
595     owner = as->parms[1].items->data;
596     code = pr_ChangeEntry (name, "", 0, owner);
597     if (code) com_err (whoami, code,
598                        "; unable to change owner of %s to %s", name, owner);
599     return code;
600 }
601
602 ChangeName (as)
603   register struct cmd_syndesc *as;
604 {
605     register afs_int32 code;
606     char *oldname;
607     char *newname;
608
609     oldname = as->parms[0].items->data;
610     newname = as->parms[1].items->data;
611     code = pr_ChangeEntry (oldname, newname, 0, "");
612     if (code) com_err (whoami, code,
613                        "; unable to change name of %s to %s",
614                        oldname, newname);
615     return code;
616 }
617
618 ListMax (as)
619   register struct cmd_syndesc *as;
620 {
621     register afs_int32 code;
622     afs_int32 maxUser, maxGroup;
623
624     code = pr_ListMaxUserId (&maxUser);
625     if (code) 
626         com_err (whoami, code, "getting maximum user id");
627     else {
628         code = pr_ListMaxGroupId (&maxGroup);
629         if (code) com_err (whoami, code, "getting maximum group id");
630         else {
631             printf("Max user id is %d and max group id is %d.\n",
632                    maxUser, maxGroup);      
633         }
634     }
635     return code;
636 }
637
638 SetMax (as)
639   register struct cmd_syndesc *as;
640 {
641     register afs_int32 code;
642     afs_int32 maxid;
643
644     code = 0;
645     if (as->parms[1].items) {
646         /* set user max */
647         code = util_GetInt32 (as->parms[1].items->data, &maxid);
648         if (code) {
649             com_err (whoami, code,
650                      "because id was: '%s'", as->parms[1].items->data);
651         }
652         else {
653             code = pr_SetMaxUserId (maxid);
654             if (code)
655                 com_err (whoami, code,
656                          "so couldn't set Max User Id to %d", maxid);
657         }
658     }
659     if (as->parms[0].items) {
660         /* set group max */
661         code = util_GetInt32 (as->parms[0].items->data, &maxid);
662         if (code) {
663             com_err (whoami, code,
664                      "because id was: '%s'", as->parms[0].items->data);
665         }
666         else {
667             code = pr_SetMaxGroupId (maxid);
668             if (code)
669                 com_err (whoami, code,
670                          "so couldn't set Max Group Id to %d", maxid);
671         }
672     }
673     if (!as->parms[0].items && !as->parms[1].items) {
674         code = PRBADARG;
675         printf("Must specify at least one of group or user.\n");
676     }
677     return code;
678 }
679
680 SetFields (as)
681   register struct cmd_syndesc *as;
682 {
683     register afs_int32 code;
684     idlist ids;
685     namelist names;
686     int i;
687     afs_int32 mask, flags, ngroups, nusers;
688
689     if (GetNameOrId (as, &ids, &names)) return PRBADARG;
690
691     mask = 0;
692     nusers = 0;
693     if (as->parms[1].items) {           /* privacy bits */
694         char *access = as->parms[1].items->data;
695         int   new;
696
697         if (strpbrk (access, "76543210") != 0) { /* all octal digits */
698             sscanf (access, "%lo", &flags);
699         } else {                        /* interpret flag bit names */
700             if (strlen(access) != 5) {
701               form_error:
702                 printf ("Access bits must be of the form 'somar', not %s\n", access);
703                 return PRBADARG;
704             }
705             if (strpbrk(access, "somar-") == 0) goto form_error;
706             flags = 0;
707             for (i=0; i<5; i++) {
708                 if (access[i] == flags_upcase[i]) new = 2;
709                 else if (access[i] == flags_dncase[i]) new = 1;
710                 else if (access[i] == '-') new = 0;
711                 else {
712                     printf ("Access bits out of order or illegal:\n  must be a combination of letters from '%s' or '%s' or hyphen, not %s\n", flags_upcase, flags_dncase, access);
713                     return PRBADARG;
714                 }
715                 flags <<= flags_shift[i];
716                 if (flags_shift[i] == 1) {
717                     if (new) flags |= 1;
718                 }
719                 else flags |= new;
720             }
721         }
722         mask |= PR_SF_ALLBITS;
723     }
724     if (as->parms[2].items) {           /* limitgroups */
725         code = util_GetInt32 (as->parms[2].items->data, &ngroups);
726         if (code) {
727             com_err (whoami, code, "because ngroups was: '%s'",
728                      as->parms[2].items->data);
729             return code;
730         }
731         mask |= PR_SF_NGROUPS;
732     }
733 #if FOREIGN
734     if (as->parms[3].items) {           /* limitgroups */
735         code = util_GetInt32 (as->parms[3].items->data, &nusers);
736         if (code) {
737             com_err (whoami, code, "because nusers was: '%s'",
738                      as->parms[3].items->data);
739             return code;
740         }
741         mask |= PR_SF_NUSERS;
742     }
743 #endif
744
745     for (i=0; i<ids.idlist_len; i++) {
746         afs_int32 id = ids.idlist_val[i];
747         char *name = names.namelist_val[i];
748         if (id == ANONYMOUSID) continue;
749         code = pr_SetFieldsEntry (id, mask, flags, ngroups, nusers);
750         if (code) {
751             com_err (whoami, code,
752                      "; unable to set fields for %s (id: %d)", name, id);
753             return code;
754         }
755     }
756     if (ids.idlist_val) free (ids.idlist_val);
757     if (names.namelist_val) free (names.namelist_val);
758     return 0;
759 }           
760
761 ListOwned (as)
762   register struct cmd_syndesc *as;
763 {   register afs_int32 code;
764     idlist ids;
765     namelist names;
766     namelist list;
767     int i,j;
768     afs_int32 more;
769
770     if (GetNameOrId (as, &ids, &names)) return PRBADARG;
771
772     for (i=0; i<ids.idlist_len; i++) {
773         afs_int32 oid = ids.idlist_val[i];
774         char *name = names.namelist_val[i];
775
776         if (oid == ANONYMOUSID) continue;
777
778         if (oid) printf("Groups owned by %s (id: %d) are:\n", name, oid);
779         else printf ("Orphaned groups are:\n");
780         more = 0;
781         do {
782            list.namelist_val = 0;
783            list.namelist_len = 0;
784            code = pr_ListOwned(oid, &list, &more);
785            if (code) {
786               com_err (whoami, code,
787                        "; unable to get owner list for %s (id: %d)",
788                        name, oid);
789               break;
790            }
791
792            for (j=0; j<list.namelist_len; j++)
793               printf ("  %s\n", list.namelist_val[j]);
794            if (list.namelist_val) free(list.namelist_val);
795         } while (more);
796     }
797
798     if (ids.idlist_val) free (ids.idlist_val);
799     if (names.namelist_val) free (names.namelist_val);
800     return 0;
801 }
802
803 static void add_std_args (ts)
804   register struct cmd_syndesc *ts;
805 {
806     char test_help[AFSDIR_PATH_MAX];
807
808     sprintf(test_help, "use config file in %s", AFSDIR_SERVER_ETC_DIRPATH);
809
810     cmd_Seek(ts,16);
811     cmd_AddParm(ts,"-cell",CMD_SINGLE,CMD_OPTIONAL,"cell name");
812     cmd_AddParm(ts,"-noauth",CMD_FLAG,CMD_OPTIONAL,"run unauthenticated");
813     cmd_AddParm(ts,"-test", CMD_FLAG,CMD_OPTIONAL|CMD_HIDE, test_help);
814     cmd_AddParm(ts,"-force",CMD_FLAG,CMD_OPTIONAL,"Continue oper despite reasonable errors");
815 }
816
817 /*
818 static void add_NameOrId_args (ts)
819   register struct cmd_syndesc *ts;
820 {
821     cmd_AddParm(ts,"-name",CMD_LIST,CMD_OPTIONAL,"user or group name");
822     cmd_AddParm(ts,"-id",CMD_LIST,CMD_OPTIONAL,"user or group id");
823 }
824 */
825
826 #include "AFS_component_version_number.c"
827
828 int main (argc, argv)
829   int argc;
830   char **argv;
831 {
832     register afs_int32 code;
833     register struct cmd_syndesc *ts;
834
835 #ifdef  AFS_AIX32_ENV
836     /*
837      * The following signal action for AIX is necessary so that in case of a 
838      * crash (i.e. core is generated) we can include the user's data section 
839      * in the core dump. Unfortunately, by default, only a partial core is
840      * generated which, in many cases, isn't too useful.
841      */
842     struct sigaction nsa;
843     
844     sigemptyset(&nsa.sa_mask);
845     nsa.sa_handler = SIG_DFL;
846     nsa.sa_flags = SA_FULLDUMP;
847     sigaction(SIGSEGV, &nsa, NULL);
848 #endif
849
850     ts = cmd_CreateSyntax("creategroup",CreateGroup,0,"create a new group");
851     cmd_AddParm(ts,"-name",CMD_LIST,0,"group name");
852     cmd_AddParm(ts,"-owner",CMD_SINGLE,CMD_OPTIONAL,"owner of the group");
853     cmd_AddParm(ts,"-id",CMD_LIST,CMD_OPTIONAL,"id (negated) for the group");
854     add_std_args (ts);
855     cmd_CreateAlias(ts,"cg");
856
857     ts = cmd_CreateSyntax("createuser",CreateUser,0,"create a new user");
858     cmd_AddParm(ts,"-name",CMD_LIST,0,"user name");
859     cmd_AddParm(ts,"-id",CMD_LIST,CMD_OPTIONAL,"user id");
860     add_std_args (ts);
861     cmd_CreateAlias(ts,"cu");
862
863     ts = cmd_CreateSyntax("adduser",AddToGroup,0,"add a user to a group");
864     cmd_AddParm(ts, "-user",CMD_LIST,0,"user name");
865     cmd_AddParm(ts, "-group",CMD_LIST,0,"group name");
866     add_std_args (ts);
867
868     ts = cmd_CreateSyntax("removeuser",RemoveFromGroup,0,
869                           "remove a user from a group");
870     cmd_AddParm(ts,"-user",CMD_LIST,0,"user name");
871     cmd_AddParm(ts,"-group",CMD_LIST,0,"group name");
872     add_std_args (ts);
873
874     ts = cmd_CreateSyntax ("membership",ListMembership, 0,
875                            "list membership of a user or group");
876     cmd_AddParm(ts,"-nameorid",CMD_LIST,0,"user or group name or id");
877     add_std_args (ts);
878     cmd_CreateAlias(ts,"groups");
879
880     ts = cmd_CreateSyntax ("delete", Delete, 0,
881                            "delete a user or group from database");
882     cmd_AddParm(ts,"-nameorid",CMD_LIST,0,"user or group name or id");
883     add_std_args (ts);
884
885     ts = cmd_CreateSyntax ("examine", CheckEntry, 0, "examine an entry");
886     cmd_AddParm(ts,"-nameorid",CMD_LIST,0,"user or group name or id");
887     add_std_args (ts);
888     cmd_CreateAlias (ts, "check");
889
890     ts = cmd_CreateSyntax("chown",ChownGroup,0,"change ownership of a group");
891     cmd_AddParm(ts,"-name",CMD_SINGLE,0,"group name");
892     cmd_AddParm(ts,"-owner",CMD_SINGLE,0,"new owner");
893     add_std_args (ts);
894
895     ts = cmd_CreateSyntax("rename",ChangeName,0,"rename user or group");
896     cmd_AddParm(ts,"-oldname",CMD_SINGLE,0,"old name");
897     cmd_AddParm(ts,"-newname",CMD_SINGLE,0,"new name");
898     add_std_args (ts);
899     cmd_CreateAlias(ts, "chname");
900
901     ts = cmd_CreateSyntax("listmax",ListMax,0,"list max id");
902     add_std_args (ts);
903
904     ts = cmd_CreateSyntax("setmax",SetMax,0,"set max id");
905     cmd_AddParm(ts,"-group",CMD_SINGLE,CMD_OPTIONAL,"group max");
906     cmd_AddParm(ts,"-user",CMD_SINGLE,CMD_OPTIONAL,"user max");
907     add_std_args (ts);
908
909     ts = cmd_CreateSyntax("setfields",SetFields,0,"set fields for an entry");
910     cmd_AddParm(ts,"-nameorid",CMD_LIST,0,"user or group name or id");
911     cmd_AddParm (ts, "-access", CMD_SINGLE, CMD_OPTIONAL,
912                  "set privacy flags"); 
913     cmd_AddParm (ts, "-groupquota", CMD_SINGLE, CMD_OPTIONAL,
914                  "set limit on group creation"); 
915 #if FOREIGN
916     cmd_AddParm (ts, "-userquota", CMD_SINGLE, CMD_OPTIONAL,
917                  "set limit on foreign user creation"); 
918 #endif
919     add_std_args (ts);
920
921     ts = cmd_CreateSyntax
922         ("listowned", ListOwned, 0,
923          "list groups owned by an entry or zero id gets orphaned groups");
924     cmd_AddParm(ts,"-nameorid",CMD_LIST,0,"user or group name or id");
925     add_std_args (ts);
926     
927     ts = cmd_CreateSyntax
928         ("listentries", ListEntries, 0,
929          "list users/groups in the protection database");
930     cmd_AddParm(ts, "-users",  CMD_FLAG, CMD_OPTIONAL, "list user entries");
931     cmd_AddParm(ts, "-groups", CMD_FLAG, CMD_OPTIONAL, "list group entries");
932     add_std_args (ts);
933     
934     cmd_SetBeforeProc(GetGlobals,0);
935     cmd_SetAfterProc(CleanUp,0);
936     code = cmd_Dispatch(argc,argv);
937     exit (code != 0);
938 }
939