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