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