2 * Copyright 2000, International Business Machines Corporation and others.
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
12 #include <afs/param.h>
19 #include <sys/types.h>
24 #include <WINNT/afsevent.h>
26 #include <netinet/in.h>
28 #include <afs/cellconfig.h>
33 #include <afs/afsutil.h>
43 /* OK, this REALLY sucks bigtime, but I can't tell who is calling
44 * afsconf_CheckAuth easily, and only *SERVERS* should be calling osi_audit
45 * anyway. It's gonna give somebody fits to debug, I know, I know.
51 register struct cmd_syndesc *as;
53 register afs_int32 code;
59 if (!strcmp(as->name,"help")) return 0;
60 if (as->parms[16].items)
61 cell = as->parms[16].items->data;
63 if (as->parms[17].items)
66 if (as->parms[18].items) { /* testing? */
67 code = pr_Initialize(sec, AFSDIR_SERVER_ETC_DIRPATH, cell);
70 code = pr_Initialize(sec, AFSDIR_CLIENT_ETC_DIRPATH, cell);
73 com_err (whoami, code, "Couldn't initialize");
76 if (as->parms[19].items)
82 register struct cmd_syndesc *as;
84 if (!strcmp(as->name,"help")) return;
85 /* Need to shutdown the ubik_client & other connections */
91 register struct cmd_syndesc *as;
93 register afs_int32 code;
96 struct cmd_item *namei;
99 namei = as->parms[0].items;
100 idi = as->parms[2].items;
101 if (as->parms[1].items)
102 owner = as->parms[1].items->data;
107 code = util_GetInt32 (idi->data, &id);
109 com_err (whoami, code,
110 "because group id was: '%s'", idi->data);
115 com_err (whoami, code,
116 "because group id %d was not negative", id);
122 code = pr_CreateGroup (namei->data, owner, &id);
125 com_err (whoami, code,
126 "; unable to create group %s with id %d owned by '%s' %s",
127 namei->data, id, owner, (force?"(ignored)":""));
128 else com_err (whoami, code,
129 "; unable to create group %s %s", namei->data, (force?"(ignored)":""));
133 printf ("group %s has id %d\n", namei->data, id);
140 register struct cmd_syndesc *as;
142 register afs_int32 code;
144 struct cmd_item *namei;
145 struct cmd_item *idi;
147 namei = as->parms[0].items;
148 idi = as->parms[1].items;
152 code = util_GetInt32 (idi->data, &id);
154 com_err (whoami, code, "because id was: '%s'", idi->data);
158 printf ("0 isn't a valid user id; aborting\n");
164 code = pr_CreateUser (namei->data, &id);
166 if (id) com_err (whoami, code,
167 "; unable to create user %s with id %d %s",
168 namei->data, id, (force?"(ignored)":""));
169 else com_err (whoami, code,
170 "; unable to create user %s %s", namei->data, (force?"(ignored)":""));
174 printf ("User %s has id %d\n", namei->data, id);
182 int GetNameOrId (as, lids, lnames)
183 register struct cmd_syndesc *as;
185 struct namelist *lnames;
187 register afs_int32 code = 0;
192 if (!(as->parms[0].items || as->parms[1].items)) {
193 com_err (whoami, 0, "must specify either a name or an id.");
196 if (as->parms[0].items && as->parms[1].items) {
197 com_err (whoami, 0, "can't specify both a name and id.");
202 lids->idlist_len = 0;
203 lids->idlist_val = 0;
205 if (as->parms[0].items) { /* name */
206 struct namelist names; /* local copy, if not ret. names */
209 names.namelist_val = 0; /* so it gets freed later if needed */
210 if (lnames) nl = lnames;
213 n = 0; /* count names */
214 for (i=as->parms[0].items; i; i=i->next) n++;
215 nl->namelist_val = (prname *)malloc(n*PR_MAXNAMELEN);
216 nl->namelist_len = n;
218 for (i=as->parms[0].items; i; i=i->next)
219 strncpy (nl->namelist_val[n++], i->data, PR_MAXNAMELEN);
221 code = pr_NameToId (nl, lids);
222 if (code) com_err (whoami, code, "so couldn't look up names");
224 for (n=0; n<lids->idlist_len; n++) {
225 if ((lids->idlist_val[n] == ANONYMOUSID)) {
226 com_err (whoami, PRNOENT,
227 "so couldn't look up id for %s", nl->namelist_val[n]);
231 /* treat things as working if any of the lookups worked */
232 if (goodCount==0) code = PRNOENT;
235 if (names.namelist_val) free (names.namelist_val);
237 else if (as->parms[1].items) { /* id */
239 for (i=as->parms[1].items; i; i=i->next) n++;
240 lids->idlist_val = (afs_int32 *)malloc(n*sizeof(afs_int32));
241 lids->idlist_len = n;
243 for (i=as->parms[1].items; i; i=i->next) {
244 code = util_GetInt32 (i->data, &lids->idlist_val[n]);
246 com_err (whoami, code=PRNOENT,
247 "because a bogus id '%s' was specified", i->data);
250 if (!code && lnames) {
251 lnames->namelist_val = 0;
252 lnames->namelist_len = 0;
253 code = pr_IdToName (lids, lnames);
254 if (code) com_err (whoami, code, "translating ids");
258 if (lids->idlist_val) free (lids->idlist_val);
266 int GetNameOrId (as, lids, lnames)
267 register struct cmd_syndesc *as;
269 struct namelist *lnames;
271 register afs_int32 code = 0;
272 int n = 0, nd = 0, nm = 0, id, x;
274 struct namelist names, tnames; /* local copy, if not ret. names */
275 struct idlist ids, tids; /* local copy, if not ret. ids */
278 for (i = as->parms[0].items; i; i = i->next) n++;
279 lids->idlist_val = (afs_int32 *)malloc(n*sizeof(afs_int32));
280 lids->idlist_len = n;
281 ids.idlist_val = (afs_int32 *)malloc(n*sizeof(afs_int32));
283 names.namelist_val = (prname *)malloc(n*PR_MAXNAMELEN);
284 names.namelist_len = n;
286 lnames->namelist_val = (prname *)malloc(n*PR_MAXNAMELEN);
287 lnames->namelist_len = 0;
289 for (i=as->parms[0].items; i; i=i->next) {
290 tnames.namelist_val = (prname *)malloc(PR_MAXNAMELEN);
291 strncpy (tnames.namelist_val[0], i->data, PR_MAXNAMELEN);
292 tnames.namelist_len = 1;
295 code = pr_NameToId(&tnames, &tids);
296 if ((!code && (tids.idlist_val[0] != 32766)) || (code = util_GetInt32 (i->data, &id))) {
297 /* Assume it's a name instead */
298 strncpy (names.namelist_val[nm++], i->data, PR_MAXNAMELEN);
300 ids.idlist_val[nd++] = id;
302 free(tnames.namelist_val);
304 names.namelist_len = nm;
306 tids.idlist_len = nd = nm = 0;
308 code = pr_NameToId (&names, &tids);
309 if (code) com_err (whoami, code, "so couldn't look up names");
311 for (n=0; n < tids.idlist_len; n++) {
312 if ((tids.idlist_val[n] == ANONYMOUSID)) {
313 com_err (whoami, PRNOENT,
314 "so couldn't look up id for %s", names.namelist_val[n]);
317 lids->idlist_val[nd] = tids.idlist_val[n];
319 strcpy(lnames->namelist_val[nd], names.namelist_val[n]);
323 for (x=0; x < ids.idlist_len; x++) {
324 lids->idlist_val[nd+x] = ids.idlist_val[x];
326 lids->idlist_len = nd+x;
327 if (!code && lnames) {
328 tnames.namelist_val = 0;
329 tnames.namelist_len = 0;
330 code = pr_IdToName (&ids, &tnames);
331 if (code) com_err (whoami, code, "translating ids");
334 for (x=0; x < ids.idlist_len; x++)
335 strcpy(lnames->namelist_val[nd+x], tnames.namelist_val[x]);
336 lnames->namelist_len = nd+x;
339 /* treat things as working if any of the lookups worked */
340 if (goodCount==0) code = PRNOENT;
342 if (lids->idlist_val) free (lids->idlist_val);
350 register struct cmd_syndesc *as;
352 register afs_int32 code;
353 struct cmd_item *u, *g;
355 for (u=as->parms[0].items; u; u=u->next) {
356 for (g=as->parms[1].items; g; g=g->next) {
357 code = pr_AddToGroup (u->data, g->data);
359 com_err (whoami, code,
360 "; unable to add user %s to group %s %s",
361 u->data, g->data, (force?"(ignored)":""));
371 register struct cmd_syndesc *as;
373 register afs_int32 code;
374 struct cmd_item *u, *g;
376 for (u=as->parms[0].items; u; u=u->next) {
377 for (g=as->parms[1].items; g; g=g->next) {
378 code = pr_RemoveUserFromGroup (u->data, g->data);
380 com_err (whoami, code,
381 "; unable to remove user %s from group %s %s",
382 u->data, g->data, (force?"(ignored)":""));
392 register struct cmd_syndesc *as;
394 register afs_int32 code;
401 if (GetNameOrId(as, &ids, &names)) return PRBADARG;
403 for (i=0; i<ids.idlist_len; i++) {
404 afs_int32 id = ids.idlist_val[i];
405 char *name = names.namelist_val[i];
407 if (id == ANONYMOUSID) continue; /* bad entry */
409 list.namelist_val = 0;
410 list.namelist_len = 0;
411 code = pr_IDListMembers(ids.idlist_val[i],&list);
413 com_err (whoami, code,
414 "; unable to get membership of %s (id: %d)", name, id);
417 if (id < 0) printf ("Members of %s (id: %d) are:\n", name, id);
418 else printf ("Groups %s (id: %d) is a member of:\n", name, id);
420 for (j=0; j<list.namelist_len; j++)
421 printf(" %s\n", list.namelist_val[j]);
422 if (list.namelist_val) free (list.namelist_val);
424 if (ids.idlist_val) free (ids.idlist_val);
425 if (names.namelist_val) free (names.namelist_val);
430 register struct cmd_syndesc *as;
432 register afs_int32 code;
437 if (GetNameOrId (as, &ids, &names)) return PRBADARG;
439 for (i=0; i<ids.idlist_len; i++) {
440 afs_int32 id = ids.idlist_val[i];
441 char *name = names.namelist_val[i];
443 if (id == ANONYMOUSID) continue;
445 code = pr_DeleteByID (id);
447 com_err (whoami, code, "deleting %s (id: %d) %s", name, id, (force?"(ignored)":""));
452 if (ids.idlist_val) free (ids.idlist_val);
453 if (names.namelist_val) free (names.namelist_val);
457 /* access bit translation info */
459 char *flags_upcase = "SOMA "; /* legal all access values */
460 char *flags_dncase = "s mar"; /* legal member acces values */
461 int flags_shift[5] = {2,1,2,2,1}; /* bits for each */
464 register struct cmd_syndesc *as;
466 register afs_int32 code;
468 int i, flag = 0, admin = 0;
469 namelist lnames, names;
472 struct prcheckentry aentry;
474 if (GetNameOrId (as, &ids, &names)) return PRBADARG;
477 lids.idlist_val = (afs_int32 *)malloc(sizeof(afs_int32)*2);
478 lnames.namelist_len = 0;
479 lnames.namelist_val = 0;
481 for (i=0; i<ids.idlist_len; i++) {
482 afs_int32 id = ids.idlist_val[i];
484 if (id == ANONYMOUSID) continue;
487 code = pr_ListEntry (id, &aentry);
490 com_err (whoami, code, "; unable to find entry for (id: %d)", id);
494 lids.idlist_val[0] = aentry.owner;
495 lids.idlist_val[1] = aentry.creator;
496 code = pr_IdToName (&lids, &lnames);
499 com_err (whoami, code,
500 "translating owner (%d) and creator (%d) ids",
501 aentry.owner, aentry.creator);
504 printf("Name: %s, id: %d, owner: %s, creator: %s,\n",
505 aentry.name, aentry.id,
506 lnames.namelist_val[0], lnames.namelist_val[1]);
507 printf (" membership: %d", aentry.count);
509 afs_int32 flags = aentry.flags;
512 access[5] = 0; /* null-terminate the string */
513 for (j=4; j>=0; j--) {
515 if (s == 1) new = flags & 1;
516 else new = flags & 3;
517 if (new == 0) c = '-';
520 if (c == ' ') c = flags_upcase[j];
521 } else if (new == 2) c = flags_upcase[j];
526 printf(", flags: %s", access);
528 if (aentry.id == SYSADMINID)
530 else if (!pr_IsAMemberOf (aentry.name, "system:administrators", &flag)) {
535 printf (", group quota: unlimited");
537 printf (", group quota: %d", aentry.ngroups);
539 printf (", foreign user quota=%d", aentry.nusers);
545 if (lnames.namelist_val) free(lnames.namelist_val);
546 if (lids.idlist_val) free(lids.idlist_val);
547 if (ids.idlist_val) free(ids.idlist_val);
553 struct cmd_syndesc *as;
556 afs_int32 flag, startindex, nentries, nextstartindex;
557 struct prlistentries *entriesp=0, *e;
561 if (as->parms[1].items) flag = PRGROUPS;
562 if (as->parms[0].items) flag |= PRUSERS;
564 printf("Name ID Owner Creator\n");
565 for (startindex = 0; startindex!=-1; startindex=nextstartindex) {
566 code = pr_ListEntries(flag, startindex, &nentries, &entriesp, &nextstartindex);
568 com_err (whoami, code, "; unable to list entries\n");
569 if (entriesp) free(entriesp);
573 /* Now display each of the entries we read */
574 for (i=0,e=entriesp; i<nentries; i++,e++) {
575 printf("%-25s %6d %6d %7d \n", e->name, e->id, e->owner, e->creator);
577 if (entriesp) free(entriesp);
583 register struct cmd_syndesc *as;
585 register afs_int32 code;
589 name = as->parms[0].items->data;
590 owner = as->parms[1].items->data;
591 code = pr_ChangeEntry (name, "", 0, owner);
592 if (code) com_err (whoami, code,
593 "; unable to change owner of %s to %s", name, owner);
598 register struct cmd_syndesc *as;
600 register afs_int32 code;
604 oldname = as->parms[0].items->data;
605 newname = as->parms[1].items->data;
606 code = pr_ChangeEntry (oldname, newname, 0, "");
607 if (code) com_err (whoami, code,
608 "; unable to change name of %s to %s",
614 register struct cmd_syndesc *as;
616 register afs_int32 code;
617 afs_int32 maxUser, maxGroup;
619 code = pr_ListMaxUserId (&maxUser);
621 com_err (whoami, code, "getting maximum user id");
623 code = pr_ListMaxGroupId (&maxGroup);
624 if (code) com_err (whoami, code, "getting maximum group id");
626 printf("Max user id is %d and max group id is %d.\n",
634 register struct cmd_syndesc *as;
636 register afs_int32 code;
640 if (as->parms[1].items) {
642 code = util_GetInt32 (as->parms[1].items->data, &maxid);
644 com_err (whoami, code,
645 "because id was: '%s'", as->parms[1].items->data);
648 code = pr_SetMaxUserId (maxid);
650 com_err (whoami, code,
651 "so couldn't set Max User Id to %d", maxid);
654 if (as->parms[0].items) {
656 code = util_GetInt32 (as->parms[0].items->data, &maxid);
658 com_err (whoami, code,
659 "because id was: '%s'", as->parms[0].items->data);
662 code = pr_SetMaxGroupId (maxid);
664 com_err (whoami, code,
665 "so couldn't set Max Group Id to %d", maxid);
668 if (!as->parms[0].items && !as->parms[1].items) {
670 printf("Must specify at least one of group or user.\n");
676 register struct cmd_syndesc *as;
678 register afs_int32 code;
682 afs_int32 mask, flags, ngroups, nusers;
684 if (GetNameOrId (as, &ids, &names)) return PRBADARG;
688 if (as->parms[1].items) { /* privacy bits */
689 char *access = as->parms[1].items->data;
692 if (strpbrk (access, "76543210") != 0) { /* all octal digits */
693 sscanf (access, "%lo", &flags);
694 } else { /* interpret flag bit names */
695 if (strlen(access) != 5) {
697 printf ("Access bits must be of the form 'somar', not %s\n", access);
700 if (strpbrk(access, "somar-") == 0) goto form_error;
702 for (i=0; i<5; i++) {
703 if (access[i] == flags_upcase[i]) new = 2;
704 else if (access[i] == flags_dncase[i]) new = 1;
705 else if (access[i] == '-') new = 0;
707 printf ("Access bits out of order or illegal:\n must be a combination of letters from '%s' or '%s' or hyphen, not %s\n", flags_upcase, flags_dncase, access);
710 flags <<= flags_shift[i];
711 if (flags_shift[i] == 1) {
717 mask |= PR_SF_ALLBITS;
719 if (as->parms[2].items) { /* limitgroups */
720 code = util_GetInt32 (as->parms[2].items->data, &ngroups);
722 com_err (whoami, code, "because ngroups was: '%s'",
723 as->parms[2].items->data);
726 mask |= PR_SF_NGROUPS;
729 if (as->parms[3].items) { /* limitgroups */
730 code = util_GetInt32 (as->parms[3].items->data, &nusers);
732 com_err (whoami, code, "because nusers was: '%s'",
733 as->parms[3].items->data);
736 mask |= PR_SF_NUSERS;
740 for (i=0; i<ids.idlist_len; i++) {
741 afs_int32 id = ids.idlist_val[i];
742 char *name = names.namelist_val[i];
743 if (id == ANONYMOUSID) continue;
744 code = pr_SetFieldsEntry (id, mask, flags, ngroups, nusers);
746 com_err (whoami, code,
747 "; unable to set fields for %s (id: %d)", name, id);
751 if (ids.idlist_val) free (ids.idlist_val);
752 if (names.namelist_val) free (names.namelist_val);
757 register struct cmd_syndesc *as;
758 { register afs_int32 code;
765 if (GetNameOrId (as, &ids, &names)) return PRBADARG;
767 for (i=0; i<ids.idlist_len; i++) {
768 afs_int32 oid = ids.idlist_val[i];
769 char *name = names.namelist_val[i];
771 if (oid == ANONYMOUSID) continue;
773 if (oid) printf("Groups owned by %s (id: %d) are:\n", name, oid);
774 else printf ("Orphaned groups are:\n");
777 list.namelist_val = 0;
778 list.namelist_len = 0;
779 code = pr_ListOwned(oid, &list, &more);
781 com_err (whoami, code,
782 "; unable to get owner list for %s (id: %d)",
787 for (j=0; j<list.namelist_len; j++)
788 printf (" %s\n", list.namelist_val[j]);
789 if (list.namelist_val) free(list.namelist_val);
793 if (ids.idlist_val) free (ids.idlist_val);
794 if (names.namelist_val) free (names.namelist_val);
798 static void add_std_args (ts)
799 register struct cmd_syndesc *ts;
801 char test_help[AFSDIR_PATH_MAX];
803 sprintf(test_help, "use config file in %s", AFSDIR_SERVER_ETC_DIRPATH);
806 cmd_AddParm(ts,"-cell",CMD_SINGLE,CMD_OPTIONAL,"cell name");
807 cmd_AddParm(ts,"-noauth",CMD_FLAG,CMD_OPTIONAL,"run unauthenticated");
808 cmd_AddParm(ts,"-test", CMD_FLAG,CMD_OPTIONAL|CMD_HIDE, test_help);
809 cmd_AddParm(ts,"-force",CMD_FLAG,CMD_OPTIONAL,"Continue oper despite reasonable errors");
813 static void add_NameOrId_args (ts)
814 register struct cmd_syndesc *ts;
816 cmd_AddParm(ts,"-name",CMD_LIST,CMD_OPTIONAL,"user or group name");
817 cmd_AddParm(ts,"-id",CMD_LIST,CMD_OPTIONAL,"user or group id");
821 #include "AFS_component_version_number.c"
823 int main (argc, argv)
827 register afs_int32 code;
828 register struct cmd_syndesc *ts;
832 * The following signal action for AIX is necessary so that in case of a
833 * crash (i.e. core is generated) we can include the user's data section
834 * in the core dump. Unfortunately, by default, only a partial core is
835 * generated which, in many cases, isn't too useful.
837 struct sigaction nsa;
839 sigemptyset(&nsa.sa_mask);
840 nsa.sa_handler = SIG_DFL;
841 nsa.sa_flags = SA_FULLDUMP;
842 sigaction(SIGSEGV, &nsa, NULL);
845 ts = cmd_CreateSyntax("creategroup",CreateGroup,0,"create a new group");
846 cmd_AddParm(ts,"-name",CMD_LIST,0,"group name");
847 cmd_AddParm(ts,"-owner",CMD_SINGLE,CMD_OPTIONAL,"owner of the group");
848 cmd_AddParm(ts,"-id",CMD_LIST,CMD_OPTIONAL,"id (negated) for the group");
850 cmd_CreateAlias(ts,"cg");
852 ts = cmd_CreateSyntax("createuser",CreateUser,0,"create a new user");
853 cmd_AddParm(ts,"-name",CMD_LIST,0,"user name");
854 cmd_AddParm(ts,"-id",CMD_LIST,CMD_OPTIONAL,"user id");
856 cmd_CreateAlias(ts,"cu");
858 ts = cmd_CreateSyntax("adduser",AddToGroup,0,"add a user to a group");
859 cmd_AddParm(ts, "-user",CMD_LIST,0,"user name");
860 cmd_AddParm(ts, "-group",CMD_LIST,0,"group name");
863 ts = cmd_CreateSyntax("removeuser",RemoveFromGroup,0,
864 "remove a user from a group");
865 cmd_AddParm(ts,"-user",CMD_LIST,0,"user name");
866 cmd_AddParm(ts,"-group",CMD_LIST,0,"group name");
869 ts = cmd_CreateSyntax ("membership",ListMembership, 0,
870 "list membership of a user or group");
871 cmd_AddParm(ts,"-nameorid",CMD_LIST,0,"user or group name or id");
873 cmd_CreateAlias(ts,"groups");
875 ts = cmd_CreateSyntax ("delete", Delete, 0,
876 "delete a user or group from database");
877 cmd_AddParm(ts,"-nameorid",CMD_LIST,0,"user or group name or id");
880 ts = cmd_CreateSyntax ("examine", CheckEntry, 0, "examine an entry");
881 cmd_AddParm(ts,"-nameorid",CMD_LIST,0,"user or group name or id");
883 cmd_CreateAlias (ts, "check");
885 ts = cmd_CreateSyntax("chown",ChownGroup,0,"change ownership of a group");
886 cmd_AddParm(ts,"-name",CMD_SINGLE,0,"group name");
887 cmd_AddParm(ts,"-owner",CMD_SINGLE,0,"new owner");
890 ts = cmd_CreateSyntax("rename",ChangeName,0,"rename user or group");
891 cmd_AddParm(ts,"-oldname",CMD_SINGLE,0,"old name");
892 cmd_AddParm(ts,"-newname",CMD_SINGLE,0,"new name");
894 cmd_CreateAlias(ts, "chname");
896 ts = cmd_CreateSyntax("listmax",ListMax,0,"list max id");
899 ts = cmd_CreateSyntax("setmax",SetMax,0,"set max id");
900 cmd_AddParm(ts,"-group",CMD_SINGLE,CMD_OPTIONAL,"group max");
901 cmd_AddParm(ts,"-user",CMD_SINGLE,CMD_OPTIONAL,"user max");
904 ts = cmd_CreateSyntax("setfields",SetFields,0,"set fields for an entry");
905 cmd_AddParm(ts,"-nameorid",CMD_LIST,0,"user or group name or id");
906 cmd_AddParm (ts, "-access", CMD_SINGLE, CMD_OPTIONAL,
907 "set privacy flags");
908 cmd_AddParm (ts, "-groupquota", CMD_SINGLE, CMD_OPTIONAL,
909 "set limit on group creation");
911 cmd_AddParm (ts, "-userquota", CMD_SINGLE, CMD_OPTIONAL,
912 "set limit on foreign user creation");
916 ts = cmd_CreateSyntax
917 ("listowned", ListOwned, 0,
918 "list groups owned by an entry or zero id gets orphaned groups");
919 cmd_AddParm(ts,"-nameorid",CMD_LIST,0,"user or group name or id");
922 ts = cmd_CreateSyntax
923 ("listentries", ListEntries, 0,
924 "list users/groups in the protection database");
925 cmd_AddParm(ts, "-users", CMD_FLAG, CMD_OPTIONAL, "list user entries");
926 cmd_AddParm(ts, "-groups", CMD_FLAG, CMD_OPTIONAL, "list group entries");
929 cmd_SetBeforeProc(GetGlobals,0);
930 cmd_SetAfterProc(CleanUp,0);
931 code = cmd_Dispatch(argc,argv);