uninitialized-20040417
[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 /*
11  *                      (3) add new pts commands:
12  *
13  *                          Interactive - allow the pts command
14  *                                        to be run interactively.
15  *                          Quit        - quit interactive mode.
16  *                          Source      - allow input to come from a file(s).
17  *                          Sleep       - pause for a specified number
18  *                                        of seconds.
19  *
20  */
21
22 #include <afsconfig.h>
23 #include <afs/param.h>
24
25 RCSID
26     ("$Header$");
27
28 #include <stdio.h>
29 #include <string.h>
30 #ifdef  AFS_AIX32_ENV
31 #include <signal.h>
32 #endif
33 #include <ctype.h>
34 #include <sys/types.h>
35 #include <errno.h>
36 #include <afs/cmd.h>
37 #ifdef AFS_NT40_ENV
38 #include <winsock2.h>
39 #include <WINNT/afsevent.h>
40 #else
41 #include <netinet/in.h>
42 #endif
43 #include <afs/cellconfig.h>
44 #include <rx/rx.h>
45 #include <rx/xdr.h>
46 #include "ptclient.h"
47 #include "pterror.h"
48 #include <afs/afsutil.h>
49
50 #undef FOREIGN
51
52 char *whoami;
53 int force = 0;
54
55 #if defined(SUPERGROUPS)
56
57 /*
58  *  Add new pts commands:
59  *
60  *      Interactive - allow the pts command to be run interactively.
61  *      Quit        - quit interactive mode.
62  *      Source      - allow input to come from a file(s).
63  *      Sleep       - pause for a specified number of seconds.
64  */
65
66 static int finished;
67 static FILE *source;
68 extern struct ubik_client *pruclient;
69
70 struct sourcestack {
71     struct sourcestack *s_next;
72     FILE *s_file;
73 } *shead;
74
75 int
76 Interactive(as)
77      register struct cmd_syndesc *as;
78 {
79     finished = 0;
80     return 0;
81 }
82
83 int
84 Quit(as)
85      register struct cmd_syndesc *as;
86 {
87     finished = 1;
88     return 0;
89 }
90
91 int
92 Source(as)
93      register struct cmd_syndesc *as;
94 {
95     FILE *fd;
96     struct sourcestack *sp;
97
98     finished = 0;
99     if (!as->parms[0].items) {
100 /* can this happen? */
101         return 1;
102     }
103     fd = fopen(as->parms[0].items->data, "r");
104     if (!fd) {
105         perror(as->parms[0].items->data);
106         return errno;
107     }
108     sp = (struct sourcestack *)malloc(sizeof *sp);
109     if (!sp) {
110         return errno ? errno : ENOMEM;
111     } else {
112         sp->s_next = shead;
113         sp->s_file = source;
114         shead = sp;
115         source = fd;
116     }
117     return 0;
118 }
119
120 int
121 Sleep(as)
122      register struct cmd_syndesc *as;
123 {
124     int delay;
125     if (!as->parms[0].items) {
126 /* can this happen? */
127         return 1;
128     }
129     delay = atoi(as->parms[0].items->data);
130     IOMGR_Sleep(delay);
131 }
132
133 int
134 popsource()
135 {
136     register struct sourcestack *sp;
137     if (!(sp = shead))
138         return 0;
139     if (source != stdin)
140         fclose(source);
141     source = sp->s_file;
142     shead = sp->s_next;
143     free((char *)sp);
144     return 1;
145 }
146
147 #endif /* SUPERGROUPS */
148
149 int
150 osi_audit()
151 {
152 /* OK, this REALLY sucks bigtime, but I can't tell who is calling
153  * afsconf_CheckAuth easily, and only *SERVERS* should be calling osi_audit
154  * anyway.  It's gonna give somebody fits to debug, I know, I know.
155  */
156     return 0;
157 }
158
159 int
160 GetGlobals(as)
161      register struct cmd_syndesc *as;
162 {
163     register afs_int32 code;
164     char *cell;
165     afs_int32 sec = 1;
166
167     whoami = as->a0name;
168
169     if (!strcmp(as->name, "help"))
170         return 0;
171     if (as->parms[16].items)
172         cell = as->parms[16].items->data;
173     else
174         cell = 0;
175     if (as->parms[17].items)
176         sec = 0;
177
178     if (as->parms[18].items) {  /* testing? */
179         code = pr_Initialize(sec, AFSDIR_SERVER_ETC_DIRPATH, cell);
180     } else {
181         code = pr_Initialize(sec, AFSDIR_CLIENT_ETC_DIRPATH, cell);
182     }
183     if (code) {
184         com_err(whoami, code, "while initializing");
185         return code;
186     }
187     if (as->parms[19].items)
188         force = 1;
189     return code;
190 }
191
192 int
193 CleanUp(as)
194      register struct cmd_syndesc *as;
195 {
196 #if defined(SUPERGROUPS)
197     if (as && !strcmp(as->name, "help"))
198         return 0;
199     if (pruclient) {
200         /* Need to shutdown the ubik_client & other connections */
201         pr_End();
202         rx_Finalize();
203     }
204 #else
205     if (!strcmp(as->name, "help"))
206         return 0;
207     /* Need to shutdown the ubik_client & other connections */
208     pr_End();
209     rx_Finalize();
210 #endif /* SUPERGROUPS */
211
212     return 0;
213 }
214
215 CreateGroup(as)
216      register struct cmd_syndesc *as;
217 {
218     register afs_int32 code;
219     afs_int32 id;
220     char *owner;
221     struct cmd_item *namei;
222     struct cmd_item *idi;
223
224     namei = as->parms[0].items;
225     idi = as->parms[2].items;
226     if (as->parms[1].items)
227         owner = as->parms[1].items->data;
228     else
229         owner = NULL;
230
231     while (namei) {
232         if (idi) {
233             code = util_GetInt32(idi->data, &id);
234             if (code) {
235                 com_err(whoami, code, "because group id was: '%s'",
236                         idi->data);
237                 return code;
238             }
239             if (id >= 0) {
240                 code = PRBADARG;
241                 com_err(whoami, code, "because group id %d was not negative",
242                         id);
243                 return code;
244             }
245 #if defined(SUPERGROUPS)
246             if (id == 0) {
247                 printf("0 isn't a valid user id; aborting\n");
248                 return EINVAL;
249             }
250 #endif
251             idi = idi->next;
252         } else
253             id = 0;
254
255         code = pr_CreateGroup(namei->data, owner, &id);
256         if (code) {
257             if (owner || id)
258                 com_err(whoami, code,
259                         "; unable to create group %s with id %d%s%s%s%s",
260                         namei->data, id, owner ? " owned by '" : "",
261                         owner ? owner : "", owner ? "'" : "",
262                         (force ? " (ignored)" : ""));
263             else
264                 com_err(whoami, code, "; unable to create group %s %s",
265                         namei->data, (force ? "(ignored)" : ""));
266             if (!force)
267                 return code;
268         }
269         printf("group %s has id %d\n", namei->data, id);
270         namei = namei->next;
271     }
272     return 0;
273 }
274
275 CreateUser(as)
276      register struct cmd_syndesc *as;
277 {
278     register afs_int32 code;
279     afs_int32 id;
280     struct cmd_item *namei;
281     struct cmd_item *idi;
282
283     namei = as->parms[0].items;
284     idi = as->parms[1].items;
285
286     while (namei) {
287         if (idi) {
288             code = util_GetInt32(idi->data, &id);
289             if (code) {
290                 com_err(whoami, code, "because id was: '%s'", idi->data);
291                 return code;
292             }
293             if (id == 0) {
294                 printf("0 isn't a valid user id; aborting\n");
295                 return EINVAL;
296             }
297             idi = idi->next;
298         } else
299             id = 0;
300
301         code = pr_CreateUser(namei->data, &id);
302         if (code) {
303             if (id)
304                 com_err(whoami, code,
305                         "; unable to create user %s with id %d %s",
306                         namei->data, id, (force ? "(ignored)" : ""));
307             else
308                 com_err(whoami, code, "; unable to create user %s %s",
309                         namei->data, (force ? "(ignored)" : ""));
310             if (!force)
311                 return code;
312         }
313         printf("User %s has id %d\n", namei->data, id);
314         namei = namei->next;
315     }
316     return 0;
317 }
318
319
320 #ifdef notdef
321 int
322 GetNameOrId(as, lids, lnames)
323      register struct cmd_syndesc *as;
324      struct idlist *lids;
325      struct namelist *lnames;
326 {
327     register afs_int32 code = 0;
328     int n = 0;
329     struct cmd_item *i;
330     int goodCount;
331
332     if (!(as->parms[0].items || as->parms[1].items)) {
333         com_err(whoami, 0, "must specify either a name or an id.");
334         return -1;
335     }
336     if (as->parms[0].items && as->parms[1].items) {
337         com_err(whoami, 0, "can't specify both a name and id.");
338         return -1;
339     }
340
341     goodCount = 0;
342     lids->idlist_len = 0;
343     lids->idlist_val = 0;
344
345     if (as->parms[0].items) {   /* name */
346         struct namelist names;  /* local copy, if not ret. names */
347         struct namelist *nl;
348
349         names.namelist_val = 0; /* so it gets freed later if needed */
350         if (lnames)
351             nl = lnames;
352         else
353             nl = &names;
354
355         n = 0;                  /* count names */
356         for (i = as->parms[0].items; i; i = i->next)
357             n++;
358         nl->namelist_val = (prname *) malloc(n * PR_MAXNAMELEN);
359         nl->namelist_len = n;
360         n = 0;
361         for (i = as->parms[0].items; i; i = i->next)
362             strncpy(nl->namelist_val[n++], i->data, PR_MAXNAMELEN);
363
364         code = pr_NameToId(nl, lids);
365         if (code)
366             com_err(whoami, code, "so couldn't look up names");
367         else {
368             for (n = 0; n < lids->idlist_len; n++) {
369                 if ((lids->idlist_val[n] == ANONYMOUSID)) {
370                     com_err(whoami, PRNOENT, "so couldn't look up id for %s",
371                             nl->namelist_val[n]);
372                 } else
373                     goodCount++;
374             }
375             /* treat things as working if any of the lookups worked */
376             if (goodCount == 0)
377                 code = PRNOENT;
378         }
379
380         if (names.namelist_val)
381             free(names.namelist_val);
382     } else if (as->parms[1].items) {    /* id */
383         n = 0;
384         for (i = as->parms[1].items; i; i = i->next)
385             n++;
386         lids->idlist_val = (afs_int32 *) malloc(n * sizeof(afs_int32));
387         lids->idlist_len = n;
388         n = 0;
389         for (i = as->parms[1].items; i; i = i->next) {
390             code = util_GetInt32(i->data, &lids->idlist_val[n]);
391             if (code)
392                 com_err(whoami, code =
393                         PRNOENT, "because a bogus id '%s' was specified",
394                         i->data);
395             n++;
396         }
397         if (!code && lnames) {
398             lnames->namelist_val = 0;
399             lnames->namelist_len = 0;
400             code = pr_IdToName(lids, lnames);
401             if (code)
402                 com_err(whoami, code, "translating ids");
403         }
404     }
405     if (code) {
406         if (lids->idlist_val)
407             free(lids->idlist_val);
408         return -1;
409     }
410     return 0;
411 }
412 #endif
413
414
415 int
416 GetNameOrId(as, lids, lnames)
417      register struct cmd_syndesc *as;
418      struct idlist *lids;
419      struct namelist *lnames;
420 {
421     register afs_int32 code = 0;
422     int n = 0, nd = 0, nm = 0, id, x;
423     struct cmd_item *i;
424     struct namelist names, tnames;      /* local copy, if not ret. names */
425     struct idlist ids, tids;    /* local copy, if not ret. ids */
426     int goodCount = 0;
427
428     for (i = as->parms[0].items; i; i = i->next)
429         n++;
430     lids->idlist_val = (afs_int32 *) malloc(n * sizeof(afs_int32));
431     lids->idlist_len = n;
432     ids.idlist_val = (afs_int32 *) malloc(n * sizeof(afs_int32));
433     ids.idlist_len = n;
434     names.namelist_val = (prname *) malloc(n * PR_MAXNAMELEN);
435     names.namelist_len = n;
436     if (lnames) {
437         lnames->namelist_val = (prname *) malloc(n * PR_MAXNAMELEN);
438         lnames->namelist_len = 0;
439     }
440     for (i = as->parms[0].items; i; i = i->next) {
441         tnames.namelist_val = (prname *) malloc(PR_MAXNAMELEN);
442         strncpy(tnames.namelist_val[0], i->data, PR_MAXNAMELEN);
443         tnames.namelist_len = 1;
444         tids.idlist_len = 0;
445         tids.idlist_val = 0;
446         code = pr_NameToId(&tnames, &tids);
447         if ((!code && (tids.idlist_val[0] != 32766))
448             || (code = util_GetInt32(i->data, &id))) {
449             /* Assume it's a name instead */
450             strncpy(names.namelist_val[nm++], i->data, PR_MAXNAMELEN);
451         } else {
452             ids.idlist_val[nd++] = id;
453         }
454         free(tnames.namelist_val);
455     }
456     names.namelist_len = nm;
457     ids.idlist_len = nd;
458     tids.idlist_len = nd = nm = 0;
459     tids.idlist_val = 0;
460     code = pr_NameToId(&names, &tids);
461     if (code)
462         com_err(whoami, code, "so couldn't look up names");
463     else {
464         for (n = 0; n < tids.idlist_len; n++) {
465             if ((tids.idlist_val[n] == ANONYMOUSID)) {
466                 com_err(whoami, PRNOENT, "so couldn't look up id for %s",
467                         names.namelist_val[n]);
468             } else
469                 goodCount++;
470             lids->idlist_val[nd] = tids.idlist_val[n];
471             if (lnames)
472                 strcpy(lnames->namelist_val[nd], names.namelist_val[n]);
473             nd++;
474         }
475     }
476     for (x = 0; x < ids.idlist_len; x++) {
477         lids->idlist_val[nd + x] = ids.idlist_val[x];
478     }
479     lids->idlist_len = nd + x;
480     if (!code && lnames) {
481         tnames.namelist_val = 0;
482         tnames.namelist_len = 0;
483         code = pr_IdToName(&ids, &tnames);
484         if (code)
485             com_err(whoami, code, "translating ids");
486         else
487             goodCount++;
488         if (lnames) {
489             for (x = 0; x < ids.idlist_len; x++)
490                 strcpy(lnames->namelist_val[nd + x], tnames.namelist_val[x]);
491             lnames->namelist_len = nd + x;
492         }
493     }
494     /* treat things as working if any of the lookups worked */
495     if (goodCount == 0)
496         code = PRNOENT;
497     if (code) {
498         if (lids->idlist_val)
499             free(lids->idlist_val);
500         return -1;
501     }
502     return 0;
503 }
504
505
506 AddToGroup(as)
507      register struct cmd_syndesc *as;
508 {
509     register afs_int32 code;
510     struct cmd_item *u, *g;
511
512     for (u = as->parms[0].items; u; u = u->next) {
513         for (g = as->parms[1].items; g; g = g->next) {
514             code = pr_AddToGroup(u->data, g->data);
515             if (code) {
516                 com_err(whoami, code,
517                         "; unable to add user %s to group %s %s", u->data,
518                         g->data, (force ? "(ignored)" : ""));
519                 if (!force)
520                     return code;
521             }
522         }
523     }
524     return 0;
525 }
526
527 RemoveFromGroup(as)
528      register struct cmd_syndesc *as;
529 {
530     register afs_int32 code;
531     struct cmd_item *u, *g;
532
533     for (u = as->parms[0].items; u; u = u->next) {
534         for (g = as->parms[1].items; g; g = g->next) {
535             code = pr_RemoveUserFromGroup(u->data, g->data);
536             if (code) {
537                 com_err(whoami, code,
538                         "; unable to remove user %s from group %s %s",
539                         u->data, g->data, (force ? "(ignored)" : ""));
540                 if (!force)
541                     return code;
542             }
543         }
544     }
545     return 0;
546 }
547
548 ListMembership(as)
549      register struct cmd_syndesc *as;
550 {
551     register afs_int32 code;
552     idlist ids;
553     namelist names;
554     int i;
555     namelist list;
556     int j;
557
558     if (GetNameOrId(as, &ids, &names))
559         return PRBADARG;
560
561     for (i = 0; i < ids.idlist_len; i++) {
562         afs_int32 id = ids.idlist_val[i];
563         char *name = names.namelist_val[i];
564
565         if (id == ANONYMOUSID)
566             continue;           /* bad entry */
567
568         list.namelist_val = 0;
569         list.namelist_len = 0;
570         code = pr_IDListMembers(ids.idlist_val[i], &list);
571         if (code) {
572             com_err(whoami, code, "; unable to get membership of %s (id: %d)",
573                     name, id);
574             continue;
575         }
576         if (id < 0)
577             printf("Members of %s (id: %d) are:\n", name, id);
578         else
579             printf("Groups %s (id: %d) is a member of:\n", name, id);
580
581         for (j = 0; j < list.namelist_len; j++)
582             printf("  %s\n", list.namelist_val[j]);
583         if (list.namelist_val)
584             free(list.namelist_val);
585     }
586     if (ids.idlist_val)
587         free(ids.idlist_val);
588     if (names.namelist_val)
589         free(names.namelist_val);
590     return 0;
591 }
592
593 Delete(as)
594      register struct cmd_syndesc *as;
595 {
596     register afs_int32 code;
597     idlist ids;
598     namelist names;
599     int i;
600
601     if (GetNameOrId(as, &ids, &names))
602         return PRBADARG;
603
604     for (i = 0; i < ids.idlist_len; i++) {
605         afs_int32 id = ids.idlist_val[i];
606         char *name = names.namelist_val[i];
607
608         if (id == ANONYMOUSID)
609             continue;
610
611         code = pr_DeleteByID(id);
612         if (code) {
613             com_err(whoami, code, "deleting %s (id: %d) %s", name, id,
614                     (force ? "(ignored)" : ""));
615             if (!force)
616                 return code;
617         }
618     }
619     if (ids.idlist_val)
620         free(ids.idlist_val);
621     if (names.namelist_val)
622         free(names.namelist_val);
623     return 0;
624 }
625
626 /* access bit translation info */
627
628 char *flags_upcase = "SOMA ";   /* legal all access values */
629 char *flags_dncase = "s mar";   /* legal member acces values */
630 int flags_shift[5] = { 2, 1, 2, 2, 1 }; /* bits for each */
631
632 CheckEntry(as)
633      register struct cmd_syndesc *as;
634 {
635     register afs_int32 code;
636     afs_int32 rcode = 1;
637     int i, flag = 0, admin = 0;
638     namelist lnames, names;
639     idlist ids;
640     idlist lids;
641     struct prcheckentry aentry;
642
643     if (GetNameOrId(as, &ids, &names))
644         return PRBADARG;
645
646     lids.idlist_len = 2;
647     lids.idlist_val = (afs_int32 *) malloc(sizeof(afs_int32) * 2);
648     lnames.namelist_len = 0;
649     lnames.namelist_val = 0;
650
651     for (i = 0; i < ids.idlist_len; i++) {
652         afs_int32 id = ids.idlist_val[i];
653
654         if (id == ANONYMOUSID)
655             continue;
656
657         rcode = 0;
658         code = pr_ListEntry(id, &aentry);
659         if (code) {
660             rcode = code;
661             com_err(whoami, code, "; unable to find entry for (id: %d)", id);
662             continue;
663         }
664
665         lids.idlist_val[0] = aentry.owner;
666         lids.idlist_val[1] = aentry.creator;
667         code = pr_IdToName(&lids, &lnames);
668         if (code) {
669             rcode = code;
670             com_err(whoami, code,
671                     "translating owner (%d) and creator (%d) ids",
672                     aentry.owner, aentry.creator);
673             continue;
674         }
675         printf("Name: %s, id: %d, owner: %s, creator: %s,\n", aentry.name,
676                aentry.id, lnames.namelist_val[0], lnames.namelist_val[1]);
677         printf("  membership: %d", aentry.count);
678         {
679             char access[6];
680             afs_int32 flags = aentry.flags;
681             int j, s, new;
682             char c;
683             access[5] = 0;      /* null-terminate the string */
684             for (j = 4; j >= 0; j--) {
685                 s = flags_shift[j];
686                 if (s == 1)
687                     new = flags & 1;
688                 else
689                     new = flags & 3;
690                 if (new == 0)
691                     c = '-';
692                 else if (new == 1) {
693                     c = flags_dncase[j];
694                     if (c == ' ')
695                         c = flags_upcase[j];
696                 } else if (new == 2)
697                     c = flags_upcase[j];
698                 else
699                     c = 'X';
700                 access[j] = c;
701                 flags >>= s;
702             }
703             printf(", flags: %s", access);
704         }
705         if (aentry.id == SYSADMINID)
706             admin = 1;
707         else if (!pr_IsAMemberOf(aentry.name, "system:administrators", &flag)) {
708             if (flag)
709                 admin = 1;
710         }
711         if (admin)
712             printf(", group quota: unlimited");
713         else
714             printf(", group quota: %d", aentry.ngroups);
715 #if FOREIGN
716         printf(", foreign user quota=%d", aentry.nusers);
717 #endif
718         printf(".\n");
719     }
720
721     if (lnames.namelist_val)
722         free(lnames.namelist_val);
723     if (lids.idlist_val)
724         free(lids.idlist_val);
725     if (ids.idlist_val)
726         free(ids.idlist_val);
727
728     return (rcode);
729 }
730
731 ListEntries(as)
732      struct cmd_syndesc *as;
733 {
734     afs_int32 code = 0;
735     afs_int32 flag, startindex, nentries, nextstartindex;
736     struct prlistentries *entriesp = 0, *e;
737     afs_int32 i;
738
739     flag = PRUSERS;
740     if (as->parms[1].items)
741         flag = PRGROUPS;
742     if (as->parms[0].items)
743         flag |= PRUSERS;
744
745     printf("Name                          ID  Owner Creator\n");
746     for (startindex = 0; startindex != -1; startindex = nextstartindex) {
747         code =
748             pr_ListEntries(flag, startindex, &nentries, &entriesp,
749                            &nextstartindex);
750         if (code) {
751             com_err(whoami, code, "; unable to list entries\n");
752             if (entriesp)
753                 free(entriesp);
754             break;
755         }
756
757         /* Now display each of the entries we read */
758         for (i = 0, e = entriesp; i < nentries; i++, e++) {
759             printf("%-25s %6d %6d %7d \n", e->name, e->id, e->owner,
760                    e->creator);
761         }
762         if (entriesp)
763             free(entriesp);
764     }
765     return code;
766 }
767
768 ChownGroup(as)
769      register struct cmd_syndesc *as;
770 {
771     register afs_int32 code;
772     char *name;
773     char *owner;
774
775     name = as->parms[0].items->data;
776     owner = as->parms[1].items->data;
777     code = pr_ChangeEntry(name, "", 0, owner);
778     if (code)
779         com_err(whoami, code, "; unable to change owner of %s to %s", name,
780                 owner);
781     return code;
782 }
783
784 ChangeName(as)
785      register struct cmd_syndesc *as;
786 {
787     register afs_int32 code;
788     char *oldname;
789     char *newname;
790
791     oldname = as->parms[0].items->data;
792     newname = as->parms[1].items->data;
793     code = pr_ChangeEntry(oldname, newname, 0, "");
794     if (code)
795         com_err(whoami, code, "; unable to change name of %s to %s", oldname,
796                 newname);
797     return code;
798 }
799
800 ListMax(as)
801      register struct cmd_syndesc *as;
802 {
803     register afs_int32 code;
804     afs_int32 maxUser, maxGroup;
805
806     code = pr_ListMaxUserId(&maxUser);
807     if (code)
808         com_err(whoami, code, "getting maximum user id");
809     else {
810         code = pr_ListMaxGroupId(&maxGroup);
811         if (code)
812             com_err(whoami, code, "getting maximum group id");
813         else {
814             printf("Max user id is %d and max group id is %d.\n", maxUser,
815                    maxGroup);
816         }
817     }
818     return code;
819 }
820
821 SetMax(as)
822      register struct cmd_syndesc *as;
823 {
824     register afs_int32 code;
825     afs_int32 maxid;
826
827     code = 0;
828     if (as->parms[1].items) {
829         /* set user max */
830         code = util_GetInt32(as->parms[1].items->data, &maxid);
831         if (code) {
832             com_err(whoami, code, "because id was: '%s'",
833                     as->parms[1].items->data);
834         } else {
835             code = pr_SetMaxUserId(maxid);
836             if (code)
837                 com_err(whoami, code, "so couldn't set Max User Id to %d",
838                         maxid);
839         }
840     }
841     if (as->parms[0].items) {
842         /* set group max */
843         code = util_GetInt32(as->parms[0].items->data, &maxid);
844         if (code) {
845             com_err(whoami, code, "because id was: '%s'",
846                     as->parms[0].items->data);
847         } else {
848             code = pr_SetMaxGroupId(maxid);
849             if (code)
850                 com_err(whoami, code, "so couldn't set Max Group Id to %d",
851                         maxid);
852         }
853     }
854     if (!as->parms[0].items && !as->parms[1].items) {
855         code = PRBADARG;
856         printf("Must specify at least one of group or user.\n");
857     }
858     return code;
859 }
860
861 SetFields(as)
862      register struct cmd_syndesc *as;
863 {
864     register afs_int32 code;
865     idlist ids;
866     namelist names;
867     int i;
868     afs_int32 mask, flags, ngroups, nusers;
869
870     if (GetNameOrId(as, &ids, &names))
871         return PRBADARG;
872
873     mask = 0;
874     nusers = 0;
875     ngroups = 0;
876
877     if (as->parms[1].items) {   /* privacy bits */
878         char *access = as->parms[1].items->data;
879         int new;
880
881         if (strpbrk(access, "76543210") != 0) { /* all octal digits */
882             sscanf(access, "%lo", &flags);
883         } else {                /* interpret flag bit names */
884             if (strlen(access) != 5) {
885               form_error:
886                 printf("Access bits must be of the form 'somar', not %s\n",
887                        access);
888                 return PRBADARG;
889             }
890             if (strpbrk(access, "somar-") == 0)
891                 goto form_error;
892             flags = 0;
893             for (i = 0; i < 5; i++) {
894                 if (access[i] == flags_upcase[i])
895                     new = 2;
896                 else if (access[i] == flags_dncase[i])
897                     new = 1;
898                 else if (access[i] == '-')
899                     new = 0;
900                 else {
901                     printf
902                         ("Access bits out of order or illegal:\n  must be a combination of letters from '%s' or '%s' or hyphen, not %s\n",
903                          flags_upcase, flags_dncase, access);
904                     return PRBADARG;
905                 }
906                 flags <<= flags_shift[i];
907                 if (flags_shift[i] == 1) {
908                     if (new)
909                         flags |= 1;
910                 } else
911                     flags |= new;
912             }
913         }
914         mask |= PR_SF_ALLBITS;
915     }
916     if (as->parms[2].items) {   /* limitgroups */
917         code = util_GetInt32(as->parms[2].items->data, &ngroups);
918         if (code) {
919             com_err(whoami, code, "because ngroups was: '%s'",
920                     as->parms[2].items->data);
921             return code;
922         }
923         mask |= PR_SF_NGROUPS;
924     }
925 #if FOREIGN
926     if (as->parms[3].items) {   /* limitgroups */
927         code = util_GetInt32(as->parms[3].items->data, &nusers);
928         if (code) {
929             com_err(whoami, code, "because nusers was: '%s'",
930                     as->parms[3].items->data);
931             return code;
932         }
933         mask |= PR_SF_NUSERS;
934     }
935 #endif
936
937     for (i = 0; i < ids.idlist_len; i++) {
938         afs_int32 id = ids.idlist_val[i];
939         char *name = names.namelist_val[i];
940         if (id == ANONYMOUSID)
941             continue;
942         code = pr_SetFieldsEntry(id, mask, flags, ngroups, nusers);
943         if (code) {
944             com_err(whoami, code, "; unable to set fields for %s (id: %d)",
945                     name, id);
946             return code;
947         }
948     }
949     if (ids.idlist_val)
950         free(ids.idlist_val);
951     if (names.namelist_val)
952         free(names.namelist_val);
953     return 0;
954 }
955
956 ListOwned(as)
957      register struct cmd_syndesc *as;
958 {
959     register afs_int32 code;
960     idlist ids;
961     namelist names;
962     namelist list;
963     int i, j;
964     afs_int32 more;
965
966     if (GetNameOrId(as, &ids, &names))
967         return PRBADARG;
968
969     for (i = 0; i < ids.idlist_len; i++) {
970         afs_int32 oid = ids.idlist_val[i];
971         char *name = names.namelist_val[i];
972
973         if (oid == ANONYMOUSID)
974             continue;
975
976         if (oid)
977             printf("Groups owned by %s (id: %d) are:\n", name, oid);
978         else
979             printf("Orphaned groups are:\n");
980         more = 0;
981         do {
982             list.namelist_val = 0;
983             list.namelist_len = 0;
984             code = pr_ListOwned(oid, &list, &more);
985             if (code) {
986                 com_err(whoami, code,
987                         "; unable to get owner list for %s (id: %d)", name,
988                         oid);
989                 break;
990             }
991
992             for (j = 0; j < list.namelist_len; j++)
993                 printf("  %s\n", list.namelist_val[j]);
994             if (list.namelist_val)
995                 free(list.namelist_val);
996         } while (more);
997     }
998
999     if (ids.idlist_val)
1000         free(ids.idlist_val);
1001     if (names.namelist_val)
1002         free(names.namelist_val);
1003     return 0;
1004 }
1005
1006 static void
1007 add_std_args(ts)
1008      register struct cmd_syndesc *ts;
1009 {
1010     char test_help[AFSDIR_PATH_MAX];
1011
1012     sprintf(test_help, "use config file in %s", AFSDIR_SERVER_ETC_DIRPATH);
1013
1014     cmd_Seek(ts, 16);
1015     cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
1016     cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL, "run unauthenticated");
1017     cmd_AddParm(ts, "-test", CMD_FLAG, CMD_OPTIONAL | CMD_HIDE, test_help);
1018     cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL,
1019                 "Continue oper despite reasonable errors");
1020 }
1021
1022 /*
1023 static void add_NameOrId_args (ts)
1024   register struct cmd_syndesc *ts;
1025 {
1026     cmd_AddParm(ts,"-name",CMD_LIST,CMD_OPTIONAL,"user or group name");
1027     cmd_AddParm(ts,"-id",CMD_LIST,CMD_OPTIONAL,"user or group id");
1028 }
1029 */
1030
1031 #include "AFS_component_version_number.c"
1032
1033 int
1034 main(argc, argv)
1035      int argc;
1036      char **argv;
1037 {
1038     register afs_int32 code;
1039     register struct cmd_syndesc *ts;
1040 #if defined(SUPERGROUPS)
1041     char line[2048];
1042     char *cp, *lastp;
1043     int parsec;
1044     char *parsev[CMD_MAXPARMS];
1045     char *savec;
1046 #endif
1047 #ifdef WIN32
1048     WSADATA WSAjunk;
1049 #endif
1050
1051 #ifdef WIN32
1052     WSAStartup(0x0101, &WSAjunk);
1053 #endif
1054
1055 #ifdef  AFS_AIX32_ENV
1056     /*
1057      * The following signal action for AIX is necessary so that in case of a 
1058      * crash (i.e. core is generated) we can include the user's data section 
1059      * in the core dump. Unfortunately, by default, only a partial core is
1060      * generated which, in many cases, isn't too useful.
1061      */
1062     struct sigaction nsa;
1063
1064     sigemptyset(&nsa.sa_mask);
1065     nsa.sa_handler = SIG_DFL;
1066     nsa.sa_flags = SA_FULLDUMP;
1067     sigaction(SIGSEGV, &nsa, NULL);
1068 #endif
1069
1070     ts = cmd_CreateSyntax("creategroup", CreateGroup, 0,
1071                           "create a new group");
1072     cmd_AddParm(ts, "-name", CMD_LIST, 0, "group name");
1073     cmd_AddParm(ts, "-owner", CMD_SINGLE, CMD_OPTIONAL, "owner of the group");
1074     cmd_AddParm(ts, "-id", CMD_LIST, CMD_OPTIONAL,
1075                 "id (negated) for the group");
1076     add_std_args(ts);
1077     cmd_CreateAlias(ts, "cg");
1078
1079     ts = cmd_CreateSyntax("createuser", CreateUser, 0, "create a new user");
1080     cmd_AddParm(ts, "-name", CMD_LIST, 0, "user name");
1081     cmd_AddParm(ts, "-id", CMD_LIST, CMD_OPTIONAL, "user id");
1082     add_std_args(ts);
1083     cmd_CreateAlias(ts, "cu");
1084
1085     ts = cmd_CreateSyntax("adduser", AddToGroup, 0, "add a user to a group");
1086     cmd_AddParm(ts, "-user", CMD_LIST, 0, "user name");
1087     cmd_AddParm(ts, "-group", CMD_LIST, 0, "group name");
1088     add_std_args(ts);
1089
1090     ts = cmd_CreateSyntax("removeuser", RemoveFromGroup, 0,
1091                           "remove a user from a group");
1092     cmd_AddParm(ts, "-user", CMD_LIST, 0, "user name");
1093     cmd_AddParm(ts, "-group", CMD_LIST, 0, "group name");
1094     add_std_args(ts);
1095
1096     ts = cmd_CreateSyntax("membership", ListMembership, 0,
1097                           "list membership of a user or group");
1098     cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1099     add_std_args(ts);
1100     cmd_CreateAlias(ts, "groups");
1101
1102     ts = cmd_CreateSyntax("delete", Delete, 0,
1103                           "delete a user or group from database");
1104     cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1105     add_std_args(ts);
1106
1107     ts = cmd_CreateSyntax("examine", CheckEntry, 0, "examine an entry");
1108     cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1109     add_std_args(ts);
1110     cmd_CreateAlias(ts, "check");
1111
1112     ts = cmd_CreateSyntax("chown", ChownGroup, 0,
1113                           "change ownership of a group");
1114     cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "group name");
1115     cmd_AddParm(ts, "-owner", CMD_SINGLE, 0, "new owner");
1116     add_std_args(ts);
1117
1118     ts = cmd_CreateSyntax("rename", ChangeName, 0, "rename user or group");
1119     cmd_AddParm(ts, "-oldname", CMD_SINGLE, 0, "old name");
1120     cmd_AddParm(ts, "-newname", CMD_SINGLE, 0, "new name");
1121     add_std_args(ts);
1122     cmd_CreateAlias(ts, "chname");
1123
1124     ts = cmd_CreateSyntax("listmax", ListMax, 0, "list max id");
1125     add_std_args(ts);
1126
1127     ts = cmd_CreateSyntax("setmax", SetMax, 0, "set max id");
1128     cmd_AddParm(ts, "-group", CMD_SINGLE, CMD_OPTIONAL, "group max");
1129     cmd_AddParm(ts, "-user", CMD_SINGLE, CMD_OPTIONAL, "user max");
1130     add_std_args(ts);
1131
1132     ts = cmd_CreateSyntax("setfields", SetFields, 0,
1133                           "set fields for an entry");
1134     cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1135     cmd_AddParm(ts, "-access", CMD_SINGLE, CMD_OPTIONAL, "set privacy flags");
1136     cmd_AddParm(ts, "-groupquota", CMD_SINGLE, CMD_OPTIONAL,
1137                 "set limit on group creation");
1138 #if FOREIGN
1139     cmd_AddParm(ts, "-userquota", CMD_SINGLE, CMD_OPTIONAL,
1140                 "set limit on foreign user creation");
1141 #endif
1142     add_std_args(ts);
1143
1144     ts = cmd_CreateSyntax("listowned", ListOwned, 0,
1145                           "list groups owned by an entry or zero id gets orphaned groups");
1146     cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1147     add_std_args(ts);
1148
1149     ts = cmd_CreateSyntax("listentries", ListEntries, 0,
1150                           "list users/groups in the protection database");
1151     cmd_AddParm(ts, "-users", CMD_FLAG, CMD_OPTIONAL, "list user entries");
1152     cmd_AddParm(ts, "-groups", CMD_FLAG, CMD_OPTIONAL, "list group entries");
1153     add_std_args(ts);
1154
1155 #if defined(SUPERGROUPS)
1156
1157     ts = cmd_CreateSyntax("interactive", Interactive, 0,
1158                           "enter interactive mode");
1159     add_std_args(ts);
1160     cmd_CreateAlias(ts, "in");
1161
1162     ts = cmd_CreateSyntax("quit", Quit, 0, "exit program");
1163     add_std_args(ts);
1164
1165     ts = cmd_CreateSyntax("source", Source, 0, "read commands from file");
1166     cmd_AddParm(ts, "-file", CMD_SINGLE, 0, "filename");
1167     add_std_args(ts);
1168
1169     ts = cmd_CreateSyntax("sleep", Sleep, 0, "pause for a bit");
1170     cmd_AddParm(ts, "-delay", CMD_SINGLE, 0, "seconds");
1171     add_std_args(ts);
1172
1173 #endif /* SUPERGROUPS */
1174
1175     cmd_SetBeforeProc(GetGlobals, 0);
1176
1177 #if defined(SUPERGROUPS)
1178     finished = 1;
1179     if (code = cmd_Dispatch(argc, argv)) {
1180         CleanUp(0);
1181         exit(1);
1182     }
1183     source = stdin;
1184     while (!finished) {
1185         if (isatty(fileno(source)))
1186             fprintf(stderr, "pts> ");
1187         if (!fgets(line, sizeof line, source)) {
1188             if (!popsource())
1189                 break;
1190             continue;
1191         }
1192         lastp = 0;
1193         for (cp = line; *cp; ++cp)
1194             if (!isspace(*cp))
1195                 lastp = 0;
1196             else if (!lastp)
1197                 lastp = cp;
1198         if (lastp)
1199             *lastp = 0;
1200         if (!*line)
1201             continue;
1202         code =
1203             cmd_ParseLine(line, parsev, &parsec,
1204                           sizeof(parsev) / sizeof(*parsev));
1205         if (code) {
1206             com_err(whoami, code, "parsing line: <%s>", line);
1207             exit(2);
1208         }
1209         savec = parsev[0];
1210         parsev[0] = argv[0];
1211         code = cmd_Dispatch(parsec, parsev);
1212         parsev[0] = savec;
1213         cmd_FreeArgv(parsev);
1214     }
1215     CleanUp(0);
1216     exit(0);
1217
1218 #else /* SUPERGROUPS */
1219
1220     cmd_SetAfterProc(CleanUp, 0);
1221     code = cmd_Dispatch(argc, argv);
1222     exit(code != 0);
1223 #endif /* SUPERGROUPS */
1224 }