Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / ptserver / pts.c
blob0035f5bacc8a7a49139d8d3946cefbaeb73df597
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
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 */
10 #include <afsconfig.h>
11 #include <afs/param.h>
14 #include <stdio.h>
15 #include <string.h>
16 #ifdef AFS_AIX32_ENV
17 #include <signal.h>
18 #endif
19 #include <ctype.h>
20 #include <sys/types.h>
21 #include <errno.h>
22 #include <afs/cmd.h>
23 #ifdef AFS_NT40_ENV
24 #include <winsock2.h>
25 #include <WINNT/afsevent.h>
26 #include <WINNT/afsreg.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 "ptuser.h"
35 #include "pterror.h"
36 #include "ptprototypes.h"
37 #include <afs/afsutil.h>
38 #include <afs/com_err.h>
40 #undef FOREIGN
42 char *whoami;
43 int force = 0;
45 static int finished;
46 static FILE *source;
47 extern struct ubik_client *pruclient;
49 struct sourcestack {
50 struct sourcestack *s_next;
51 FILE *s_file;
52 } *shead;
54 struct authstate {
55 int sec;
56 const char *confdir;
57 char cell[MAXCELLCHARS];
60 static int CleanUp(struct cmd_syndesc *as, void *arock);
62 static int
63 pts_Interactive(struct cmd_syndesc *as, void *arock)
65 source = stdin;
66 finished = 0;
67 return 0;
70 static int
71 pts_Quit(struct cmd_syndesc *as, void *arock)
73 finished = 1;
74 return 0;
77 static int
78 pts_Source(struct cmd_syndesc *as, void *arock)
80 FILE *fd;
81 struct sourcestack *sp;
83 finished = 0;
84 if (!as->parms[0].items) {
85 /* can this happen? */
86 return 1;
88 fd = fopen(as->parms[0].items->data, "r");
89 if (!fd) {
90 perror(as->parms[0].items->data);
91 return errno;
93 sp = (struct sourcestack *)malloc(sizeof *sp);
94 if (!sp) {
95 return errno ? errno : ENOMEM;
96 } else {
97 sp->s_next = shead;
98 sp->s_file = source;
99 shead = sp;
100 source = fd;
102 return 0;
105 static int
106 pts_Sleep(struct cmd_syndesc *as, void *arock)
108 int delay;
109 if (!as->parms[0].items) {
110 /* can this happen? */
111 return 1;
113 delay = atoi(as->parms[0].items->data);
114 #ifdef AFS_PTHREAD_ENV
115 sleep(delay);
116 #else
117 IOMGR_Sleep(delay);
118 #endif
119 return 0;
122 static int
123 popsource(void)
125 struct sourcestack *sp;
126 if (!(sp = shead))
127 return 0;
128 if (source != stdin)
129 fclose(source);
130 source = sp->s_file;
131 shead = sp->s_next;
132 free((char *)sp);
133 return 1;
137 osi_audit(void)
139 /* OK, this REALLY sucks bigtime, but I can't tell who is calling
140 * afsconf_CheckAuth easily, and only *SERVERS* should be calling osi_audit
141 * anyway. It's gonna give somebody fits to debug, I know, I know.
143 return 0;
146 #ifdef AFS_NT40_ENV
147 static DWORD
148 win32_enableCrypt(void)
150 HKEY parmKey;
151 DWORD dummyLen;
152 DWORD cryptall = 0;
153 DWORD code;
155 /* Look up configuration parameters in Registry */
156 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
157 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
158 if (code != ERROR_SUCCESS) {
159 dummyLen = sizeof(cryptall);
160 RegQueryValueEx(parmKey, "SecurityLevel", NULL, NULL,
161 (BYTE *) &cryptall, &dummyLen);
163 RegCloseKey (parmKey);
165 return cryptall;
167 #endif /* AFS_NT40_ENV */
169 static int
170 GetGlobals(struct cmd_syndesc *as, void *arock)
172 struct authstate *state = (struct authstate *) arock;
173 afs_int32 code;
174 char *cell = NULL;
175 afs_int32 sec;
176 int changed = 0;
177 const char* confdir;
179 whoami = as->a0name;
181 if (!strcmp(as->name, "help"))
182 return 0;
184 if (*state->cell) {
185 cell = state->cell;
187 sec = state->sec;
189 if (state->confdir == NULL) {
190 changed = 1;
193 if (as->parms[16].items) {
194 changed = 1;
195 cell = as->parms[16].items->data;
197 if (as->parms[17].items) { /* -noauth */
198 changed = 1;
199 sec = 0;
201 if (as->parms[20].items) { /* -localauth */
202 changed = 1;
203 sec = 2;
205 if (as->parms[21].items) { /* -auth */
206 changed = 1;
207 sec = 1;
209 if (as->parms[22].items /* -encrypt */
210 #ifdef AFS_NT40_ENV
211 || win32_enableCrypt()
212 #endif /* AFS_NT40_ENV */
214 changed = 1;
215 sec = 3;
217 if (as->parms[18].items || as->parms[20].items) { /* -test, -localauth */
218 changed = 1;
219 confdir = AFSDIR_SERVER_ETC_DIRPATH;
220 } else {
221 if (sec == 2)
222 confdir = AFSDIR_SERVER_ETC_DIRPATH;
223 else
224 confdir = AFSDIR_CLIENT_ETC_DIRPATH;
226 if (changed) {
227 CleanUp(as, arock);
228 code = pr_Initialize(sec, confdir, cell);
229 } else {
230 code = 0;
232 if (code) {
233 afs_com_err(whoami, code, "while initializing");
234 return code;
236 state->sec = sec;
237 state->confdir = confdir;
238 if (cell && cell != state->cell)
239 strncpy(state->cell, cell, MAXCELLCHARS-1);
241 force = 0;
242 if (as->parms[19].items)
243 force = 1;
245 return code;
248 static int
249 CleanUp(struct cmd_syndesc *as, void *arock)
251 if (as && !strcmp(as->name, "help"))
252 return 0;
253 if (pruclient) {
254 /* Need to shutdown the ubik_client & other connections */
255 pr_End();
256 rx_Finalize();
258 return 0;
261 static int
262 CreateGroup(struct cmd_syndesc *as, void *arock)
264 afs_int32 code;
265 afs_int32 id;
266 char *owner;
267 struct cmd_item *namei;
268 struct cmd_item *idi;
270 namei = as->parms[0].items;
271 idi = as->parms[2].items;
272 if (as->parms[1].items)
273 owner = as->parms[1].items->data;
274 else
275 owner = NULL;
277 while (namei) {
278 if (idi) {
279 code = util_GetInt32(idi->data, &id);
280 if (code) {
281 afs_com_err(whoami, code, "because group id was: '%s'",
282 idi->data);
283 return code;
285 if (id == 0) {
286 printf("0 isn't a valid group id; aborting\n");
287 return EINVAL;
289 if (id > 0) {
290 code = PRBADARG;
291 afs_com_err(whoami, code, "because group id %d was not negative",
292 id);
293 return code;
296 idi = idi->next;
297 } else
298 id = 0;
300 code = pr_CreateGroup(namei->data, owner, &id);
301 if (code) {
302 if (owner || id)
303 afs_com_err(whoami, code,
304 "; unable to create group %s with id %d%s%s%s%s",
305 namei->data, id, owner ? " owned by '" : "",
306 owner ? owner : "", owner ? "'" : "",
307 (force ? " (ignored)" : ""));
308 else
309 afs_com_err(whoami, code, "; unable to create group %s %s",
310 namei->data, (force ? "(ignored)" : ""));
311 if (!force)
312 return code;
314 printf("group %s has id %d\n", namei->data, id);
315 namei = namei->next;
317 return 0;
320 static int
321 CreateUser(struct cmd_syndesc *as, void *arock)
323 afs_int32 code;
324 afs_int32 id;
325 struct cmd_item *namei;
326 struct cmd_item *idi;
328 namei = as->parms[0].items;
329 idi = as->parms[1].items;
331 while (namei) {
332 if (idi) {
333 code = util_GetInt32(idi->data, &id);
334 if (code) {
335 afs_com_err(whoami, code, "because id was: '%s'", idi->data);
336 return code;
338 if (id == 0) {
339 printf("0 isn't a valid user id; aborting\n");
340 return EINVAL;
342 if (id < 0) {
343 code = PRBADARG;
344 afs_com_err(whoami, code, "because user id %d was not positive",
345 id);
346 return code;
348 idi = idi->next;
349 } else
350 id = 0;
352 code = pr_CreateUser(namei->data, &id);
353 if (code) {
354 if (id)
355 afs_com_err(whoami, code,
356 "; unable to create user %s with id %d %s",
357 namei->data, id, (force ? "(ignored)" : ""));
358 else
359 afs_com_err(whoami, code, "; unable to create user %s %s",
360 namei->data, (force ? "(ignored)" : ""));
361 if (!force)
362 return code;
364 printf("User %s has id %d\n", namei->data, id);
365 namei = namei->next;
367 return 0;
371 #ifdef notdef
372 static int
373 GetNameOrId(struct cmd_syndesc *as, struct idlist *lids, struct namelist *lnames)
375 afs_int32 code = 0;
376 int n = 0;
377 struct cmd_item *i;
378 int goodCount;
380 if (!(as->parms[0].items || as->parms[1].items)) {
381 afs_com_err(whoami, 0, "must specify either a name or an id.");
382 return -1;
384 if (as->parms[0].items && as->parms[1].items) {
385 afs_com_err(whoami, 0, "can't specify both a name and id.");
386 return -1;
389 goodCount = 0;
390 lids->idlist_len = 0;
391 lids->idlist_val = 0;
393 if (as->parms[0].items) { /* name */
394 struct namelist names; /* local copy, if not ret. names */
395 struct namelist *nl;
397 names.namelist_val = 0; /* so it gets freed later if needed */
398 if (lnames)
399 nl = lnames;
400 else
401 nl = &names;
403 n = 0; /* count names */
404 for (i = as->parms[0].items; i; i = i->next)
405 n++;
406 nl->namelist_val = (prname *) malloc(n * PR_MAXNAMELEN);
407 nl->namelist_len = n;
408 n = 0;
409 for (i = as->parms[0].items; i; i = i->next)
410 strncpy(nl->namelist_val[n++], i->data, PR_MAXNAMELEN);
412 code = pr_NameToId(nl, lids);
413 if (code)
414 afs_com_err(whoami, code, "so couldn't look up names");
415 else {
416 for (n = 0; n < lids->idlist_len; n++) {
417 if ((lids->idlist_val[n] == ANONYMOUSID)) {
418 afs_com_err(whoami, PRNOENT, "so couldn't look up id for %s",
419 nl->namelist_val[n]);
420 } else
421 goodCount++;
423 /* treat things as working if any of the lookups worked */
424 if (goodCount == 0)
425 code = PRNOENT;
428 if (names.namelist_val)
429 free(names.namelist_val);
430 } else if (as->parms[1].items) { /* id */
431 n = 0;
432 for (i = as->parms[1].items; i; i = i->next)
433 n++;
434 lids->idlist_val = (afs_int32 *) malloc(n * sizeof(afs_int32));
435 lids->idlist_len = n;
436 n = 0;
437 for (i = as->parms[1].items; i; i = i->next) {
438 code = util_GetInt32(i->data, &lids->idlist_val[n]);
439 if (code)
440 afs_com_err(whoami, code =
441 PRNOENT, "because a bogus id '%s' was specified",
442 i->data);
443 n++;
445 if (!code && lnames) {
446 lnames->namelist_val = 0;
447 lnames->namelist_len = 0;
448 code = pr_IdToName(lids, lnames);
449 if (code)
450 afs_com_err(whoami, code, "translating ids");
453 if (code) {
454 if (lids->idlist_val)
455 free(lids->idlist_val);
456 return -1;
458 return 0;
460 #endif
463 static int
464 GetNameOrId(struct cmd_syndesc *as, struct idlist *lids,
465 struct namelist *lnames)
467 afs_int32 code = 0;
468 int n = 0, nd = 0, nm = 0, id, x;
469 struct cmd_item *i;
470 struct namelist names, tnames; /* local copy, if not ret. names */
471 struct idlist ids, tids; /* local copy, if not ret. ids */
472 int goodCount = 0;
474 for (i = as->parms[0].items; i; i = i->next)
475 n++;
476 lids->idlist_val = (afs_int32 *) malloc(n * sizeof(afs_int32));
477 lids->idlist_len = n;
478 ids.idlist_val = (afs_int32 *) malloc(n * sizeof(afs_int32));
479 ids.idlist_len = n;
480 names.namelist_val = (prname *) malloc(n * PR_MAXNAMELEN);
481 names.namelist_len = n;
482 if (lnames) {
483 lnames->namelist_val = (prname *) malloc(n * PR_MAXNAMELEN);
484 lnames->namelist_len = 0;
486 for (i = as->parms[0].items; i; i = i->next) {
487 tnames.namelist_val = (prname *) malloc(PR_MAXNAMELEN);
488 strncpy(tnames.namelist_val[0], i->data, PR_MAXNAMELEN);
489 tnames.namelist_len = 1;
490 tids.idlist_len = 0;
491 tids.idlist_val = 0;
492 code = pr_NameToId(&tnames, &tids);
493 if ((!code && (tids.idlist_val[0] != 32766))
494 || (code = util_GetInt32(i->data, &id))) {
495 /* Assume it's a name instead */
496 strncpy(names.namelist_val[nm++], i->data, PR_MAXNAMELEN);
497 } else {
498 ids.idlist_val[nd++] = id;
500 free(tnames.namelist_val);
502 names.namelist_len = nm;
503 ids.idlist_len = nd;
504 tids.idlist_len = nd = nm = 0;
505 tids.idlist_val = 0;
506 code = pr_NameToId(&names, &tids);
507 if (code)
508 afs_com_err(whoami, code, "so couldn't look up names");
509 else {
510 for (n = 0; n < tids.idlist_len; n++) {
511 if (tids.idlist_val[n] == ANONYMOUSID) {
512 afs_com_err(whoami, PRNOENT, "so couldn't look up id for %s",
513 names.namelist_val[n]);
514 } else
515 goodCount++;
516 lids->idlist_val[nd] = tids.idlist_val[n];
517 if (lnames)
518 strcpy(lnames->namelist_val[nd], names.namelist_val[n]);
519 nd++;
522 for (x = 0; x < ids.idlist_len; x++) {
523 lids->idlist_val[nd + x] = ids.idlist_val[x];
525 lids->idlist_len = nd + x;
526 if (!code && lnames) {
527 tnames.namelist_val = 0;
528 tnames.namelist_len = 0;
529 code = pr_IdToName(&ids, &tnames);
530 if (code)
531 afs_com_err(whoami, code, "translating ids");
532 else
533 goodCount++;
534 if (lnames) {
535 for (x = 0; x < ids.idlist_len; x++)
536 strcpy(lnames->namelist_val[nd + x], tnames.namelist_val[x]);
537 lnames->namelist_len = nd + x;
540 /* treat things as working if any of the lookups worked */
541 if (goodCount == 0)
542 code = PRNOENT;
543 if (code) {
544 if (lids->idlist_val)
545 free(lids->idlist_val);
546 return -1;
548 return 0;
552 static int
553 AddToGroup(struct cmd_syndesc *as, void *arock)
555 afs_int32 code;
556 struct cmd_item *u, *g;
558 for (u = as->parms[0].items; u; u = u->next) {
559 for (g = as->parms[1].items; g; g = g->next) {
560 code = pr_AddToGroup(u->data, g->data);
561 if (code) {
562 afs_com_err(whoami, code,
563 "; unable to add user %s to group %s %s", u->data,
564 g->data, (force ? "(ignored)" : ""));
565 if (!force)
566 return code;
570 return 0;
573 static int
574 RemoveFromGroup(struct cmd_syndesc *as, void *arock)
576 afs_int32 code;
577 struct cmd_item *u, *g;
579 for (u = as->parms[0].items; u; u = u->next) {
580 for (g = as->parms[1].items; g; g = g->next) {
581 code = pr_RemoveUserFromGroup(u->data, g->data);
582 if (code) {
583 afs_com_err(whoami, code,
584 "; unable to remove user %s from group %s %s",
585 u->data, g->data, (force ? "(ignored)" : ""));
586 if (!force)
587 return code;
591 return 0;
594 static int
595 ListMembership(struct cmd_syndesc *as, void *arock)
597 afs_int32 code;
598 idlist ids;
599 namelist names;
600 int i;
601 namelist list;
602 int j;
604 if (GetNameOrId(as, &ids, &names))
605 return PRBADARG;
607 for (i = 0; i < ids.idlist_len; i++) {
608 afs_int32 id = ids.idlist_val[i];
609 char *name = names.namelist_val[i];
611 if (id == ANONYMOUSID)
612 continue; /* bad entry */
614 list.namelist_val = 0;
615 list.namelist_len = 0;
616 if (as->parms[2].items) { /* -expandgroups */
617 code = pr_IDListExpandedMembers(id, &list);
618 if (!code)
619 printf("Expanded ");
620 } else {
621 code = pr_IDListMembers(id, &list);
623 if (code) {
624 afs_com_err(whoami, code, "; unable to get membership of %s (id: %d)",
625 name, id);
626 continue;
628 if (id < 0)
629 printf("Members of %s (id: %d) are:\n", name, id);
630 else
631 printf("Groups %s (id: %d) is a member of:\n", name, id);
633 for (j = 0; j < list.namelist_len; j++)
634 printf(" %s\n", list.namelist_val[j]);
635 if (list.namelist_val)
636 free(list.namelist_val);
637 if (as->parms[1].items && id < 0) { /* -supergroups */
638 list.namelist_val = 0;
639 list.namelist_len = 0;
640 code = pr_ListSuperGroups(ids.idlist_val[i], &list);
641 if (code == RXGEN_OPCODE) {
642 continue; /* server does not support supergroups */
643 } else if (code != 0) {
644 afs_com_err(whoami, code,
645 "; unable to get supergroups of %s (id: %d)",
646 name, id);
647 continue;
649 printf("Groups %s (id: %d) is a member of:\n", name, id);
650 for (j = 0; j < list.namelist_len; j++)
651 printf(" %s\n", list.namelist_val[j]);
652 if (list.namelist_val)
653 free(list.namelist_val);
656 if (ids.idlist_val)
657 free(ids.idlist_val);
658 if (names.namelist_val)
659 free(names.namelist_val);
660 return 0;
663 static int
664 Delete(struct cmd_syndesc *as, void *arock)
666 afs_int32 code;
667 idlist ids;
668 namelist names;
669 int i;
671 if (GetNameOrId(as, &ids, &names))
672 return PRBADARG;
674 for (i = 0; i < ids.idlist_len; i++) {
675 afs_int32 id = ids.idlist_val[i];
676 char *name = names.namelist_val[i];
678 if (id == ANONYMOUSID)
679 continue;
681 code = pr_DeleteByID(id);
682 if (code) {
683 afs_com_err(whoami, code, "deleting %s (id: %d) %s", name, id,
684 (force ? "(ignored)" : ""));
685 if (!force)
686 return code;
689 if (ids.idlist_val)
690 free(ids.idlist_val);
691 if (names.namelist_val)
692 free(names.namelist_val);
693 return 0;
696 /* access bit translation info */
698 char *flags_upcase = "SOMA "; /* legal all access values */
699 char *flags_dncase = "s mar"; /* legal member acces values */
700 int flags_shift[5] = { 2, 1, 2, 2, 1 }; /* bits for each */
702 static int
703 CheckEntry(struct cmd_syndesc *as, void *arock)
705 afs_int32 code;
706 afs_int32 rcode = 1;
707 int i, flag = 0, admin = 0;
708 namelist lnames, names;
709 idlist ids;
710 idlist lids;
711 struct prcheckentry aentry;
713 if (GetNameOrId(as, &ids, &names))
714 return PRBADARG;
716 lids.idlist_len = 2;
717 lids.idlist_val = (afs_int32 *) malloc(sizeof(afs_int32) * 2);
718 lnames.namelist_len = 0;
719 lnames.namelist_val = 0;
721 for (i = 0; i < ids.idlist_len; i++) {
722 afs_int32 id = ids.idlist_val[i];
724 if (id == ANONYMOUSID)
725 continue;
727 rcode = 0;
728 code = pr_ListEntry(id, &aentry);
729 if (code) {
730 rcode = code;
731 afs_com_err(whoami, code, "; unable to find entry for (id: %d)", id);
732 continue;
735 lids.idlist_val[0] = aentry.owner;
736 lids.idlist_val[1] = aentry.creator;
737 code = pr_IdToName(&lids, &lnames);
738 if (code) {
739 rcode = code;
740 afs_com_err(whoami, code,
741 "translating owner (%d) and creator (%d) ids",
742 aentry.owner, aentry.creator);
743 continue;
745 printf("Name: %s, id: %d, owner: %s, creator: %s,\n", aentry.name,
746 aentry.id, lnames.namelist_val[0], lnames.namelist_val[1]);
747 printf(" membership: %d", aentry.count);
749 char access[6];
750 afs_int32 flags = aentry.flags;
751 int j, s, new;
752 char c;
753 access[5] = 0; /* null-terminate the string */
754 for (j = 4; j >= 0; j--) {
755 s = flags_shift[j];
756 if (s == 1)
757 new = flags & 1;
758 else
759 new = flags & 3;
760 if (new == 0)
761 c = '-';
762 else if (new == 1) {
763 c = flags_dncase[j];
764 if (c == ' ')
765 c = flags_upcase[j];
766 } else if (new == 2)
767 c = flags_upcase[j];
768 else
769 c = 'X';
770 access[j] = c;
771 flags >>= s;
773 printf(", flags: %s", access);
775 if (aentry.id == SYSADMINID)
776 admin = 1;
777 else if (!pr_IsAMemberOf(aentry.name, "system:administrators", &flag)) {
778 if (flag)
779 admin = 1;
781 if (admin)
782 printf(", group quota: unlimited");
783 else
784 printf(", group quota: %d", aentry.ngroups);
785 #if FOREIGN
786 printf(", foreign user quota=%d", aentry.nusers);
787 #endif
788 printf(".\n");
791 if (lnames.namelist_val)
792 free(lnames.namelist_val);
793 if (lids.idlist_val)
794 free(lids.idlist_val);
795 if (ids.idlist_val)
796 free(ids.idlist_val);
798 return (rcode);
801 static int
802 ListEntries(struct cmd_syndesc *as, void *arock)
804 afs_int32 code = 0;
805 afs_int32 flag, startindex, nentries, nextstartindex;
806 struct prlistentries *entriesp = 0, *e;
807 afs_int32 i;
809 flag = PRUSERS;
810 if (as->parms[1].items)
811 flag = PRGROUPS;
812 if (as->parms[0].items)
813 flag |= PRUSERS;
815 printf("Name ID Owner Creator\n");
816 for (startindex = 0; startindex != -1; startindex = nextstartindex) {
817 code =
818 pr_ListEntries(flag, startindex, &nentries, &entriesp,
819 &nextstartindex);
820 if (code) {
821 afs_com_err(whoami, code, "; unable to list entries");
822 if (entriesp)
823 free(entriesp);
824 break;
827 /* Now display each of the entries we read */
828 for (i = 0, e = entriesp; i < nentries; i++, e++) {
829 printf("%-25s %6d %6d %7d \n", e->name, e->id, e->owner,
830 e->creator);
832 if (entriesp)
833 free(entriesp);
835 return code;
838 static int
839 ChownGroup(struct cmd_syndesc *as, void *arock)
841 afs_int32 code;
842 char *name;
843 char *owner;
845 name = as->parms[0].items->data;
846 owner = as->parms[1].items->data;
847 code = pr_ChangeEntry(name, "", 0, owner);
848 if (code)
849 afs_com_err(whoami, code, "; unable to change owner of %s to %s", name,
850 owner);
851 return code;
854 static int
855 ChangeName(struct cmd_syndesc *as, void *arock)
857 afs_int32 code;
858 char *oldname;
859 char *newname;
861 oldname = as->parms[0].items->data;
862 newname = as->parms[1].items->data;
863 code = pr_ChangeEntry(oldname, newname, 0, "");
864 if (code)
865 afs_com_err(whoami, code, "; unable to change name of %s to %s", oldname,
866 newname);
867 return code;
870 static int
871 ListMax(struct cmd_syndesc *as, void *arock)
873 afs_int32 code;
874 afs_int32 maxUser, maxGroup;
876 code = pr_ListMaxUserId(&maxUser);
877 if (code)
878 afs_com_err(whoami, code, "getting maximum user id");
879 else {
880 code = pr_ListMaxGroupId(&maxGroup);
881 if (code)
882 afs_com_err(whoami, code, "getting maximum group id");
883 else {
884 printf("Max user id is %d and max group id is %d.\n", maxUser,
885 maxGroup);
888 return code;
891 static int
892 SetMaxCommand(struct cmd_syndesc *as, void *arock)
894 afs_int32 code;
895 afs_int32 maxid;
897 code = 0;
898 if (as->parms[1].items) {
899 /* set user max */
900 code = util_GetInt32(as->parms[1].items->data, &maxid);
901 if (code) {
902 afs_com_err(whoami, code, "because id was: '%s'",
903 as->parms[1].items->data);
904 } else {
905 code = pr_SetMaxUserId(maxid);
906 if (code)
907 afs_com_err(whoami, code, "so couldn't set Max User Id to %d",
908 maxid);
911 if (as->parms[0].items) {
912 /* set group max */
913 code = util_GetInt32(as->parms[0].items->data, &maxid);
914 if (code) {
915 afs_com_err(whoami, code, "because id was: '%s'",
916 as->parms[0].items->data);
917 } else {
918 code = pr_SetMaxGroupId(maxid);
919 if (code)
920 afs_com_err(whoami, code, "so couldn't set Max Group Id to %d",
921 maxid);
924 if (!as->parms[0].items && !as->parms[1].items) {
925 code = PRBADARG;
926 printf("Must specify at least one of group or user.\n");
928 return code;
931 static int
932 SetFields(struct cmd_syndesc *as, void *arock)
934 afs_int32 code;
935 idlist ids;
936 namelist names;
937 int i;
938 afs_int32 mask, flags=0, ngroups, nusers;
940 if (GetNameOrId(as, &ids, &names))
941 return PRBADARG;
943 mask = 0;
944 nusers = 0;
945 ngroups = 0;
947 if (as->parms[1].items) { /* privacy bits */
948 char *access = as->parms[1].items->data;
949 int new;
951 if (strpbrk(access, "76543210") != 0) { /* all octal digits */
952 sscanf(access, "%lo", (long unsigned int *) &flags);
953 } else { /* interpret flag bit names */
954 if (strlen(access) != 5) {
955 form_error:
956 printf("Access bits must be of the form 'somar', not %s\n",
957 access);
958 return PRBADARG;
960 if (strpbrk(access, "somar-") == 0)
961 goto form_error;
962 flags = 0;
963 for (i = 0; i < 5; i++) {
964 if (access[i] == flags_upcase[i])
965 new = 2;
966 else if (access[i] == flags_dncase[i])
967 new = 1;
968 else if (access[i] == '-')
969 new = 0;
970 else {
971 printf
972 ("Access bits out of order or illegal:\n must be a combination of letters from '%s' or '%s' or hyphen, not %s\n",
973 flags_upcase, flags_dncase, access);
974 return PRBADARG;
976 flags <<= flags_shift[i];
977 if (flags_shift[i] == 1) {
978 if (new)
979 flags |= 1;
980 } else
981 flags |= new;
984 mask |= PR_SF_ALLBITS;
986 if (as->parms[2].items) { /* limitgroups */
987 code = util_GetInt32(as->parms[2].items->data, &ngroups);
988 if (code) {
989 afs_com_err(whoami, code, "because ngroups was: '%s'",
990 as->parms[2].items->data);
991 return code;
993 mask |= PR_SF_NGROUPS;
995 #if FOREIGN
996 if (as->parms[3].items) { /* limitgroups */
997 code = util_GetInt32(as->parms[3].items->data, &nusers);
998 if (code) {
999 afs_com_err(whoami, code, "because nusers was: '%s'",
1000 as->parms[3].items->data);
1001 return code;
1003 mask |= PR_SF_NUSERS;
1005 #endif
1007 for (i = 0; i < ids.idlist_len; i++) {
1008 afs_int32 id = ids.idlist_val[i];
1009 char *name = names.namelist_val[i];
1010 if (id == ANONYMOUSID)
1011 continue;
1012 code = pr_SetFieldsEntry(id, mask, flags, ngroups, nusers);
1013 if (code) {
1014 afs_com_err(whoami, code, "; unable to set fields for %s (id: %d)",
1015 name, id);
1016 return code;
1019 if (ids.idlist_val)
1020 free(ids.idlist_val);
1021 if (names.namelist_val)
1022 free(names.namelist_val);
1023 return 0;
1026 static int
1027 ListOwned(struct cmd_syndesc *as, void *arock)
1029 afs_int32 code;
1030 idlist ids;
1031 namelist names;
1032 namelist list;
1033 int i, j;
1034 afs_int32 more;
1036 if (GetNameOrId(as, &ids, &names))
1037 return PRBADARG;
1039 for (i = 0; i < ids.idlist_len; i++) {
1040 afs_int32 oid = ids.idlist_val[i];
1041 char *name = names.namelist_val[i];
1043 if (oid == ANONYMOUSID)
1044 continue;
1046 if (oid)
1047 printf("Groups owned by %s (id: %d) are:\n", name, oid);
1048 else
1049 printf("Orphaned groups are:\n");
1050 more = 0;
1051 do {
1052 list.namelist_val = 0;
1053 list.namelist_len = 0;
1054 code = pr_ListOwned(oid, &list, &more);
1055 if (code) {
1056 afs_com_err(whoami, code,
1057 "; unable to get owner list for %s (id: %d)", name,
1058 oid);
1059 break;
1062 for (j = 0; j < list.namelist_len; j++)
1063 printf(" %s\n", list.namelist_val[j]);
1064 if (list.namelist_val)
1065 free(list.namelist_val);
1066 } while (more);
1069 if (ids.idlist_val)
1070 free(ids.idlist_val);
1071 if (names.namelist_val)
1072 free(names.namelist_val);
1073 return 0;
1076 static void
1077 add_std_args(struct cmd_syndesc *ts)
1079 char test_help[AFSDIR_PATH_MAX];
1081 sprintf(test_help, "use config file in %s", AFSDIR_SERVER_ETC_DIRPATH);
1083 cmd_Seek(ts, 16);
1084 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
1085 cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL, "run unauthenticated");
1086 cmd_AddParm(ts, "-test", CMD_FLAG, CMD_OPTIONAL | CMD_HIDE, test_help);
1087 cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL,
1088 "Continue oper despite reasonable errors");
1089 cmd_AddParm(ts, "-localauth", CMD_FLAG, CMD_OPTIONAL,
1090 "use local authentication");
1091 cmd_AddParm(ts, "-auth", CMD_FLAG, CMD_OPTIONAL,
1092 "use user's authentication (default)");
1093 cmd_AddParm(ts, "-encrypt", CMD_FLAG, CMD_OPTIONAL,
1094 "encrypt commands");
1098 static void add_NameOrId_args (ts)
1099 struct cmd_syndesc *ts;
1101 cmd_AddParm(ts,"-name",CMD_LIST,CMD_OPTIONAL,"user or group name");
1102 cmd_AddParm(ts,"-id",CMD_LIST,CMD_OPTIONAL,"user or group id");
1106 #include "AFS_component_version_number.c"
1109 main(int argc, char **argv)
1111 afs_int32 code;
1112 struct cmd_syndesc *ts;
1114 char line[2048];
1115 char *cp, *lastp;
1116 int parsec;
1117 char *parsev[CMD_MAXPARMS];
1118 char *savec;
1119 struct authstate state;
1121 #ifdef WIN32
1122 WSADATA WSAjunk;
1123 #endif
1125 #ifdef WIN32
1126 WSAStartup(0x0101, &WSAjunk);
1127 #endif
1129 #ifdef AFS_AIX32_ENV
1131 * The following signal action for AIX is necessary so that in case of a
1132 * crash (i.e. core is generated) we can include the user's data section
1133 * in the core dump. Unfortunately, by default, only a partial core is
1134 * generated which, in many cases, isn't too useful.
1136 struct sigaction nsa;
1138 sigemptyset(&nsa.sa_mask);
1139 nsa.sa_handler = SIG_DFL;
1140 nsa.sa_flags = SA_FULLDUMP;
1141 sigaction(SIGSEGV, &nsa, NULL);
1142 #endif
1144 memset(&state, 0, sizeof(state));
1145 state.sec = 1; /* default is auth */
1147 ts = cmd_CreateSyntax("creategroup", CreateGroup, NULL,
1148 "create a new group");
1149 cmd_AddParm(ts, "-name", CMD_LIST, 0, "group name");
1150 cmd_AddParm(ts, "-owner", CMD_SINGLE, CMD_OPTIONAL, "owner of the group");
1151 cmd_AddParm(ts, "-id", CMD_LIST, CMD_OPTIONAL,
1152 "id (negated) for the group");
1153 add_std_args(ts);
1154 cmd_CreateAlias(ts, "cg");
1156 ts = cmd_CreateSyntax("createuser", CreateUser, NULL, "create a new user");
1157 cmd_AddParm(ts, "-name", CMD_LIST, 0, "user name");
1158 cmd_AddParm(ts, "-id", CMD_LIST, CMD_OPTIONAL, "user id");
1159 add_std_args(ts);
1160 cmd_CreateAlias(ts, "cu");
1162 ts = cmd_CreateSyntax("adduser", AddToGroup, NULL, "add a user to a group");
1163 cmd_AddParm(ts, "-user", CMD_LIST, 0, "user name");
1164 cmd_AddParm(ts, "-group", CMD_LIST, 0, "group name");
1165 add_std_args(ts);
1167 ts = cmd_CreateSyntax("removeuser", RemoveFromGroup, NULL,
1168 "remove a user from a group");
1169 cmd_AddParm(ts, "-user", CMD_LIST, 0, "user name");
1170 cmd_AddParm(ts, "-group", CMD_LIST, 0, "group name");
1171 add_std_args(ts);
1173 ts = cmd_CreateSyntax("membership", ListMembership, NULL,
1174 "list membership of a user or group");
1175 cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1176 cmd_AddParm(ts, "-supergroups", CMD_FLAG, CMD_OPTIONAL, "show supergroups");
1177 cmd_AddParm(ts, "-expandgroups", CMD_FLAG, CMD_OPTIONAL, "expand super and sub group membership");
1178 add_std_args(ts);
1179 cmd_CreateAlias(ts, "groups");
1181 ts = cmd_CreateSyntax("delete", Delete, NULL,
1182 "delete a user or group from database");
1183 cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1184 add_std_args(ts);
1186 ts = cmd_CreateSyntax("examine", CheckEntry, NULL, "examine an entry");
1187 cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1188 add_std_args(ts);
1189 cmd_CreateAlias(ts, "check");
1191 ts = cmd_CreateSyntax("chown", ChownGroup, NULL,
1192 "change ownership of a group");
1193 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "group name");
1194 cmd_AddParm(ts, "-owner", CMD_SINGLE, 0, "new owner");
1195 add_std_args(ts);
1197 ts = cmd_CreateSyntax("rename", ChangeName, NULL, "rename user or group");
1198 cmd_AddParm(ts, "-oldname", CMD_SINGLE, 0, "old name");
1199 cmd_AddParm(ts, "-newname", CMD_SINGLE, 0, "new name");
1200 add_std_args(ts);
1201 cmd_CreateAlias(ts, "chname");
1203 ts = cmd_CreateSyntax("listmax", ListMax, NULL, "list max id");
1204 add_std_args(ts);
1206 ts = cmd_CreateSyntax("setmax", SetMaxCommand, NULL, "set max id");
1207 cmd_AddParm(ts, "-group", CMD_SINGLE, CMD_OPTIONAL, "group max");
1208 cmd_AddParm(ts, "-user", CMD_SINGLE, CMD_OPTIONAL, "user max");
1209 add_std_args(ts);
1211 ts = cmd_CreateSyntax("setfields", SetFields, NULL,
1212 "set fields for an entry");
1213 cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1214 cmd_AddParm(ts, "-access", CMD_SINGLE, CMD_OPTIONAL, "set privacy flags");
1215 cmd_AddParm(ts, "-groupquota", CMD_SINGLE, CMD_OPTIONAL,
1216 "set limit on group creation");
1217 #if FOREIGN
1218 cmd_AddParm(ts, "-userquota", CMD_SINGLE, CMD_OPTIONAL,
1219 "set limit on foreign user creation");
1220 #endif
1221 add_std_args(ts);
1223 ts = cmd_CreateSyntax("listowned", ListOwned, NULL,
1224 "list groups owned by an entry or zero id gets orphaned groups");
1225 cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1226 add_std_args(ts);
1228 ts = cmd_CreateSyntax("listentries", ListEntries, NULL,
1229 "list users/groups in the protection database");
1230 cmd_AddParm(ts, "-users", CMD_FLAG, CMD_OPTIONAL, "list user entries");
1231 cmd_AddParm(ts, "-groups", CMD_FLAG, CMD_OPTIONAL, "list group entries");
1232 add_std_args(ts);
1234 ts = cmd_CreateSyntax("interactive", pts_Interactive, NULL,
1235 "enter interactive mode");
1236 add_std_args(ts);
1237 cmd_CreateAlias(ts, "in");
1239 ts = cmd_CreateSyntax("quit", pts_Quit, NULL, "exit program");
1240 add_std_args(ts);
1242 ts = cmd_CreateSyntax("source", pts_Source, NULL, "read commands from file");
1243 cmd_AddParm(ts, "-file", CMD_SINGLE, 0, "filename");
1244 add_std_args(ts);
1246 ts = cmd_CreateSyntax("sleep", pts_Sleep, NULL, "pause for a bit");
1247 cmd_AddParm(ts, "-delay", CMD_SINGLE, 0, "seconds");
1248 add_std_args(ts);
1250 cmd_SetBeforeProc(GetGlobals, &state);
1252 finished = 1;
1253 source = NULL;
1254 if ((code = cmd_Dispatch(argc, argv))) {
1255 CleanUp(NULL, NULL);
1256 exit(1);
1258 while (source && !finished) {
1259 if (isatty(fileno(source)))
1260 fprintf(stderr, "pts> ");
1261 if (!fgets(line, sizeof line, source)) {
1262 if (!popsource())
1263 break;
1264 continue;
1266 lastp = 0;
1267 for (cp = line; *cp; ++cp)
1268 if (!isspace(*cp))
1269 lastp = 0;
1270 else if (!lastp)
1271 lastp = cp;
1272 if (lastp)
1273 *lastp = 0;
1274 if (!*line)
1275 continue;
1276 code =
1277 cmd_ParseLine(line, parsev, &parsec,
1278 sizeof(parsev) / sizeof(*parsev));
1279 if (code) {
1280 afs_com_err(whoami, code, "parsing line: <%s>", line);
1281 exit(2);
1283 savec = parsev[0];
1284 parsev[0] = argv[0];
1285 code = cmd_Dispatch(parsec, parsev);
1286 parsev[0] = savec;
1287 cmd_FreeArgv(parsev);
1289 CleanUp(NULL, NULL);
1290 exit(0);