pts: Fix stringop-overflow warnings
[openafs.git] / src / ptserver / pts.c
index 2cbddf0..90d6f16 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
+#include <roken.h>
 
-#include <stdio.h>
-#include <string.h>
-#ifdef AFS_AIX32_ENV
-#include <signal.h>
-#endif
 #include <ctype.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <afs/cmd.h>
+
 #ifdef AFS_NT40_ENV
-#include <winsock2.h>
 #include <WINNT/afsevent.h>
-#else
-#include <netinet/in.h>
+#include <WINNT/afsreg.h>
 #endif
+
 #include <afs/cellconfig.h>
+#include <afs/afsutil.h>
+#include <afs/com_err.h>
+#include <afs/cmd.h>
 #include <rx/rx.h>
 #include <rx/xdr.h>
+#include <rx/rxgk_int.h>
+
 #include "ptclient.h"
+#include "ptuser.h"
 #include "pterror.h"
-#include <afs/afsutil.h>
-#include <afs/com_err.h>
-
-#undef FOREIGN
+#include "ptprototypes.h"
 
 char *whoami;
 int force = 0;
@@ -50,22 +44,49 @@ struct sourcestack {
     FILE *s_file;
 } *shead;
 
-int
-pts_Interactive(struct cmd_syndesc *as, char *arock)
+struct authstate {
+    int sec;
+    const char *confdir;
+    char cell[MAXCELLCHARS];
+};
+
+/*
+ * Constants for add_std_args() global parameters. Start at offset 16, to try
+ * to avoid conflicting with any subcommand-specific parameters. If any
+ * subcommand uses more than 16 params, these constants will probably need to
+ * change.
+ */
+enum {
+    OPT_cell       = 16,
+    OPT_noauth     = 17,
+    OPT_test       = 18,
+    OPT_force      = 19,
+    OPT_localauth   = 20,
+    OPT_auth       = 21,
+    OPT_encrypt            = 22,
+    OPT_config     = 23,
+    OPT_rxgk       = 24,
+};
+
+static int CleanUp(struct cmd_syndesc *as, void *arock);
+
+static int
+pts_Interactive(struct cmd_syndesc *as, void *arock)
 {
+    source = stdin;
     finished = 0;
     return 0;
 }
 
-int
-pts_Quit(struct cmd_syndesc *as, char *arock)
+static int
+pts_Quit(struct cmd_syndesc *as, void *arock)
 {
     finished = 1;
     return 0;
 }
 
-int
-pts_Source(struct cmd_syndesc *as, char *arock)
+static int
+pts_Source(struct cmd_syndesc *as, void *arock)
 {
     FILE *fd;
     struct sourcestack *sp;
@@ -80,7 +101,7 @@ pts_Source(struct cmd_syndesc *as, char *arock)
        perror(as->parms[0].items->data);
        return errno;
     }
-    sp = (struct sourcestack *)malloc(sizeof *sp);
+    sp = malloc(sizeof *sp);
     if (!sp) {
        return errno ? errno : ENOMEM;
     } else {
@@ -92,8 +113,8 @@ pts_Source(struct cmd_syndesc *as, char *arock)
     return 0;
 }
 
-int
-pts_Sleep(struct cmd_syndesc *as, char *arock)
+static int
+pts_Sleep(struct cmd_syndesc *as, void *arock)
 {
     int delay;
     if (!as->parms[0].items) {
@@ -101,26 +122,30 @@ pts_Sleep(struct cmd_syndesc *as, char *arock)
        return 1;
     }
     delay = atoi(as->parms[0].items->data);
+#ifdef AFS_PTHREAD_ENV
+    sleep(delay);
+#else
     IOMGR_Sleep(delay);
+#endif
     return 0;
 }
 
-int
-popsource()
+static int
+popsource(void)
 {
-    register struct sourcestack *sp;
+    struct sourcestack *sp;
     if (!(sp = shead))
        return 0;
     if (source != stdin)
        fclose(source);
     source = sp->s_file;
     shead = sp->s_next;
-    free((char *)sp);
+    free(sp);
     return 1;
 }
 
 int
-osi_audit()
+osi_audit(void)
 {
 /* OK, this REALLY sucks bigtime, but I can't tell who is calling
  * afsconf_CheckAuth easily, and only *SERVERS* should be calling osi_audit
@@ -129,40 +154,134 @@ osi_audit()
     return 0;
 }
 
-int
-GetGlobals(struct cmd_syndesc *as, char *arock)
+#ifdef AFS_NT40_ENV
+static DWORD
+win32_enableCrypt(void)
+{
+    HKEY parmKey;
+    DWORD dummyLen;
+    DWORD cryptall = 0;
+    DWORD code;
+
+    /* Look up configuration parameters in Registry */
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
+                        0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
+    if (code != ERROR_SUCCESS) {
+        dummyLen = sizeof(cryptall);
+        RegQueryValueEx(parmKey, "SecurityLevel", NULL, NULL,
+                        (BYTE *) &cryptall, &dummyLen);
+    }
+    RegCloseKey (parmKey);
+
+    return cryptall;
+}
+#endif /* AFS_NT40_ENV */
+
+static int
+GetGlobals(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
-    char *cell;
-    afs_int32 sec = 1;
+    struct authstate *state = (struct authstate *) arock;
+    afs_int32 code;
+    char *cell = NULL;
+    afs_int32 sec;
+    int changed = 0;
+    const char* confdir;
+    RXGK_Level rxgk_level = RXGK_LEVEL_BOGUS;
 
     whoami = as->a0name;
 
     if (!strcmp(as->name, "help"))
        return 0;
-    if (as->parms[16].items)
-       cell = as->parms[16].items->data;
-    else
-       cell = 0;
-    if (as->parms[17].items)
+
+    if (*state->cell) {
+       cell = state->cell;
+    }
+    sec = state->sec;
+
+    if (state->confdir == NULL) {
+       changed = 1;
+    }
+
+    if (as->parms[OPT_cell].items) {
+       changed = 1;
+       cell = as->parms[OPT_cell].items->data;
+    }
+    if (as->parms[OPT_noauth].items) {
+       changed = 1;
        sec = 0;
+    }
+    if (as->parms[OPT_localauth].items) {
+       changed = 1;
+       sec = 2;
+    }
+    if (as->parms[OPT_auth].items) {
+       changed = 1;
+       sec = 1;
+    }
+    if (as->parms[OPT_encrypt].items
+#ifdef AFS_NT40_ENV
+        || win32_enableCrypt()
+#endif /* AFS_NT40_ENV */
+        ) {
+       changed = 1;
+       sec = 3;
+    }
+    if (as->parms[OPT_test].items || as->parms[OPT_localauth].items) {
+       changed = 1;
+       confdir = AFSDIR_SERVER_ETC_DIRPATH;
+    } else {
+       if (sec == 2)
+           confdir = AFSDIR_SERVER_ETC_DIRPATH;
+       else
+           confdir = AFSDIR_CLIENT_ETC_DIRPATH;
+    }
+
+    if (as->parms[OPT_config].items) { /* -config */
+       changed = 1;
+       confdir = as->parms[OPT_config].items->data;
+    }
+
+    if (as->parms[OPT_rxgk].items) {
+       char *rxgk_seclevel_str = as->parms[OPT_rxgk].items->data;
+       changed = 1;
+
+       if (strcmp(rxgk_seclevel_str, "clear") == 0)
+           rxgk_level = RXGK_LEVEL_CLEAR;
+       else if (strcmp(rxgk_seclevel_str, "auth") == 0)
+           rxgk_level = RXGK_LEVEL_AUTH;
+       else if (strcmp(rxgk_seclevel_str, "crypt") == 0)
+           rxgk_level = RXGK_LEVEL_CRYPT;
+       else {
+           fprintf(stderr, "Invalid argument to -rxgk: %s\n", rxgk_seclevel_str);
+           return 1;
+       }
+
+    }
 
-    if (as->parms[18].items) { /* testing? */
-       code = pr_Initialize(sec, AFSDIR_SERVER_ETC_DIRPATH, cell);
+    if (changed) {
+       CleanUp(as, arock);
+       code = pr_Initialize2(sec, confdir, cell, rxgk_level);
     } else {
-       code = pr_Initialize(sec, AFSDIR_CLIENT_ETC_DIRPATH, cell);
+       code = 0;
     }
     if (code) {
        afs_com_err(whoami, code, "while initializing");
        return code;
     }
-    if (as->parms[19].items)
+    state->sec = sec;
+    state->confdir = confdir;
+    if (cell && cell != state->cell)
+        strncpy(state->cell, cell, MAXCELLCHARS-1);
+
+    force = 0;
+    if (as->parms[OPT_force].items)
        force = 1;
+
     return code;
 }
 
-int
-CleanUp(struct cmd_syndesc *as, char *arock)
+static int
+CleanUp(struct cmd_syndesc *as, void *arock)
 {
     if (as && !strcmp(as->name, "help"))
        return 0;
@@ -174,10 +293,10 @@ CleanUp(struct cmd_syndesc *as, char *arock)
     return 0;
 }
 
-int
-CreateGroup(struct cmd_syndesc *as, char *arock)
+static int
+CreateGroup(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
+    afs_int32 code;
     afs_int32 id;
     char *owner;
     struct cmd_item *namei;
@@ -198,17 +317,16 @@ CreateGroup(struct cmd_syndesc *as, char *arock)
                        idi->data);
                return code;
            }
-           if (id >= 0) {
+           if (id == 0) {
+               fprintf(stderr, "0 isn't a valid group id; aborting\n");
+               return EINVAL;
+           }
+           if (id > 0) {
                code = PRBADARG;
                afs_com_err(whoami, code, "because group id %d was not negative",
                        id);
                return code;
            }
-           
-            if (id == 0) {
-               printf("0 isn't a valid user id; aborting\n");
-               return EINVAL;
-           }
 
            idi = idi->next;
        } else
@@ -234,10 +352,10 @@ CreateGroup(struct cmd_syndesc *as, char *arock)
     return 0;
 }
 
-int
-CreateUser(struct cmd_syndesc *as, char *arock)
+static int
+CreateUser(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
+    afs_int32 code;
     afs_int32 id;
     struct cmd_item *namei;
     struct cmd_item *idi;
@@ -253,9 +371,15 @@ CreateUser(struct cmd_syndesc *as, char *arock)
                return code;
            }
            if (id == 0) {
-               printf("0 isn't a valid user id; aborting\n");
+               fprintf(stderr, "0 isn't a valid user id; aborting\n");
                return EINVAL;
            }
+           if (id < 0) {
+               code = PRBADARG;
+               afs_com_err(whoami, code, "because user id %d was not positive",
+                       id);
+               return code;
+           }
            idi = idi->next;
        } else
            id = 0;
@@ -279,122 +403,41 @@ CreateUser(struct cmd_syndesc *as, char *arock)
 }
 
 
-#ifdef notdef
-int
-GetNameOrId(register struct cmd_syndesc *as, struct idlist *lids, struct namelist *lnames)
+static int
+GetNameOrId(struct cmd_syndesc *as, struct idlist *lids,
+           struct namelist *lnames)
 {
-    register afs_int32 code = 0;
-    int n = 0;
-    struct cmd_item *i;
-    int goodCount;
-
-    if (!(as->parms[0].items || as->parms[1].items)) {
-       afs_com_err(whoami, 0, "must specify either a name or an id.");
-       return -1;
-    }
-    if (as->parms[0].items && as->parms[1].items) {
-       afs_com_err(whoami, 0, "can't specify both a name and id.");
-       return -1;
-    }
-
-    goodCount = 0;
-    lids->idlist_len = 0;
-    lids->idlist_val = 0;
-
-    if (as->parms[0].items) {  /* name */
-       struct namelist names;  /* local copy, if not ret. names */
-       struct namelist *nl;
-
-       names.namelist_val = 0; /* so it gets freed later if needed */
-       if (lnames)
-           nl = lnames;
-       else
-           nl = &names;
-
-       n = 0;                  /* count names */
-       for (i = as->parms[0].items; i; i = i->next)
-           n++;
-       nl->namelist_val = (prname *) malloc(n * PR_MAXNAMELEN);
-       nl->namelist_len = n;
-       n = 0;
-       for (i = as->parms[0].items; i; i = i->next)
-           strncpy(nl->namelist_val[n++], i->data, PR_MAXNAMELEN);
-
-       code = pr_NameToId(nl, lids);
-       if (code)
-           afs_com_err(whoami, code, "so couldn't look up names");
-       else {
-           for (n = 0; n < lids->idlist_len; n++) {
-               if ((lids->idlist_val[n] == ANONYMOUSID)) {
-                   afs_com_err(whoami, PRNOENT, "so couldn't look up id for %s",
-                           nl->namelist_val[n]);
-               } else
-                   goodCount++;
-           }
-           /* treat things as working if any of the lookups worked */
-           if (goodCount == 0)
-               code = PRNOENT;
-       }
-
-       if (names.namelist_val)
-           free(names.namelist_val);
-    } else if (as->parms[1].items) {   /* id */
-       n = 0;
-       for (i = as->parms[1].items; i; i = i->next)
-           n++;
-       lids->idlist_val = (afs_int32 *) malloc(n * sizeof(afs_int32));
-       lids->idlist_len = n;
-       n = 0;
-       for (i = as->parms[1].items; i; i = i->next) {
-           code = util_GetInt32(i->data, &lids->idlist_val[n]);
-           if (code)
-               afs_com_err(whoami, code =
-                       PRNOENT, "because a bogus id '%s' was specified",
-                       i->data);
-           n++;
-       }
-       if (!code && lnames) {
-           lnames->namelist_val = 0;
-           lnames->namelist_len = 0;
-           code = pr_IdToName(lids, lnames);
-           if (code)
-               afs_com_err(whoami, code, "translating ids");
-       }
-    }
-    if (code) {
-       if (lids->idlist_val)
-           free(lids->idlist_val);
-       return -1;
-    }
-    return 0;
-}
-#endif
-
-
-int
-GetNameOrId(register struct cmd_syndesc *as, struct idlist *lids, struct namelist *lnames)
-{
-    register afs_int32 code = 0;
+    afs_int32 code = 0;
     int n = 0, nd = 0, nm = 0, id, x;
     struct cmd_item *i;
     struct namelist names, tnames;     /* local copy, if not ret. names */
     struct idlist ids, tids;   /* local copy, if not ret. ids */
     int goodCount = 0;
 
+    /* Initialise our outputs */
+    memset(lids, 0, sizeof(struct idlist));
+    if (lnames)
+       memset(lnames, 0, sizeof(struct namelist));
+
     for (i = as->parms[0].items; i; i = i->next)
        n++;
-    lids->idlist_val = (afs_int32 *) malloc(n * sizeof(afs_int32));
+
+    /* Nothing to do, so bail */
+    if (n == 0)
+       return 0;
+
+    lids->idlist_val = malloc(n * sizeof(afs_int32));
     lids->idlist_len = n;
-    ids.idlist_val = (afs_int32 *) malloc(n * sizeof(afs_int32));
+    ids.idlist_val = malloc(n * sizeof(afs_int32));
     ids.idlist_len = n;
-    names.namelist_val = (prname *) malloc(n * PR_MAXNAMELEN);
+    names.namelist_val = malloc(n * PR_MAXNAMELEN);
     names.namelist_len = n;
     if (lnames) {
-       lnames->namelist_val = (prname *) malloc(n * PR_MAXNAMELEN);
+       lnames->namelist_val = malloc(n * PR_MAXNAMELEN);
        lnames->namelist_len = 0;
     }
     for (i = as->parms[0].items; i; i = i->next) {
-       tnames.namelist_val = (prname *) malloc(PR_MAXNAMELEN);
+       tnames.namelist_val = malloc(PR_MAXNAMELEN);
        strncpy(tnames.namelist_val[0], i->data, PR_MAXNAMELEN);
        tnames.namelist_len = 1;
        tids.idlist_len = 0;
@@ -418,7 +461,7 @@ GetNameOrId(register struct cmd_syndesc *as, struct idlist *lids, struct namelis
        afs_com_err(whoami, code, "so couldn't look up names");
     else {
        for (n = 0; n < tids.idlist_len; n++) {
-           if ((tids.idlist_val[n] == ANONYMOUSID)) {
+           if (tids.idlist_val[n] == ANONYMOUSID) {
                afs_com_err(whoami, PRNOENT, "so couldn't look up id for %s",
                        names.namelist_val[n]);
            } else
@@ -439,12 +482,13 @@ GetNameOrId(register struct cmd_syndesc *as, struct idlist *lids, struct namelis
        code = pr_IdToName(&ids, &tnames);
        if (code)
            afs_com_err(whoami, code, "translating ids");
-       else
+       else {
            goodCount++;
-       if (lnames) {
-           for (x = 0; x < ids.idlist_len; x++)
-               strcpy(lnames->namelist_val[nd + x], tnames.namelist_val[x]);
-           lnames->namelist_len = nd + x;
+           if (lnames) {
+               for (x = 0; x < ids.idlist_len; x++)
+                   strcpy(lnames->namelist_val[nd + x], tnames.namelist_val[x]);
+               lnames->namelist_len = nd + x;
+           }
        }
     }
     /* treat things as working if any of the lookups worked */
@@ -459,10 +503,10 @@ GetNameOrId(register struct cmd_syndesc *as, struct idlist *lids, struct namelis
 }
 
 
-int
-AddToGroup(struct cmd_syndesc *as, char *arock)
+static int
+AddToGroup(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
+    afs_int32 code;
     struct cmd_item *u, *g;
 
     for (u = as->parms[0].items; u; u = u->next) {
@@ -480,10 +524,10 @@ AddToGroup(struct cmd_syndesc *as, char *arock)
     return 0;
 }
 
-int
-RemoveFromGroup(struct cmd_syndesc *as, char *arock)
+static int
+RemoveFromGroup(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
+    afs_int32 code;
     struct cmd_item *u, *g;
 
     for (u = as->parms[0].items; u; u = u->next) {
@@ -501,10 +545,10 @@ RemoveFromGroup(struct cmd_syndesc *as, char *arock)
     return 0;
 }
 
-int
-ListMembership(struct cmd_syndesc *as, char *arock)
+static int
+ListMembership(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
+    afs_int32 code;
     idlist ids;
     namelist names;
     int i;
@@ -523,7 +567,13 @@ ListMembership(struct cmd_syndesc *as, char *arock)
 
        list.namelist_val = 0;
        list.namelist_len = 0;
-       code = pr_IDListMembers(ids.idlist_val[i], &list);
+       if (as->parms[2].items) {       /* -expandgroups */
+           code = pr_IDListExpandedMembers(id, &list);
+           if (!code)
+               printf("Expanded ");
+       } else {
+           code = pr_IDListMembers(id, &list);
+       }
        if (code) {
            afs_com_err(whoami, code, "; unable to get membership of %s (id: %d)",
                    name, id);
@@ -538,6 +588,24 @@ ListMembership(struct cmd_syndesc *as, char *arock)
            printf("  %s\n", list.namelist_val[j]);
        if (list.namelist_val)
            free(list.namelist_val);
+       if (as->parms[1].items && id < 0) {     /* -supergroups */
+           list.namelist_val = 0;
+           list.namelist_len = 0;
+           code = pr_ListSuperGroups(ids.idlist_val[i], &list);
+           if (code == RXGEN_OPCODE) {
+               continue; /* server does not support supergroups */
+           } else if (code != 0) {
+               afs_com_err(whoami, code,
+                           "; unable to get supergroups of %s (id: %d)",
+                           name, id);
+               continue;
+           }
+           printf("Groups %s (id: %d) is a member of:\n", name, id);
+           for (j = 0; j < list.namelist_len; j++)
+               printf("  %s\n", list.namelist_val[j]);
+           if (list.namelist_val)
+               free(list.namelist_val);
+       }
     }
     if (ids.idlist_val)
        free(ids.idlist_val);
@@ -546,10 +614,10 @@ ListMembership(struct cmd_syndesc *as, char *arock)
     return 0;
 }
 
-int
-Delete(struct cmd_syndesc *as, char *arock)
+static int
+Delete(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
+    afs_int32 code;
     idlist ids;
     namelist names;
     int i;
@@ -585,22 +653,23 @@ char *flags_upcase = "SOMA ";     /* legal all access values */
 char *flags_dncase = "s mar";  /* legal member acces values */
 int flags_shift[5] = { 2, 1, 2, 2, 1 };        /* bits for each */
 
-int
-CheckEntry(struct cmd_syndesc *as, char *arock)
+static int
+CheckEntry(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
+    afs_int32 code;
     afs_int32 rcode = 1;
     int i, flag = 0, admin = 0;
     namelist lnames, names;
     idlist ids;
     idlist lids;
     struct prcheckentry aentry;
+    prname admins = "system:administrators";
 
     if (GetNameOrId(as, &ids, &names))
        return PRBADARG;
 
     lids.idlist_len = 2;
-    lids.idlist_val = (afs_int32 *) malloc(sizeof(afs_int32) * 2);
+    lids.idlist_val = malloc(sizeof(afs_int32) * 2);
     lnames.namelist_len = 0;
     lnames.namelist_val = 0;
 
@@ -660,7 +729,7 @@ CheckEntry(struct cmd_syndesc *as, char *arock)
        }
        if (aentry.id == SYSADMINID)
            admin = 1;
-       else if (!pr_IsAMemberOf(aentry.name, "system:administrators", &flag)) {
+       else if (!pr_IsAMemberOf(aentry.name, admins, &flag)) {
            if (flag)
                admin = 1;
        }
@@ -668,9 +737,6 @@ CheckEntry(struct cmd_syndesc *as, char *arock)
            printf(", group quota: unlimited");
        else
            printf(", group quota: %d", aentry.ngroups);
-#if FOREIGN
-       printf(", foreign user quota=%d", aentry.nusers);
-#endif
        printf(".\n");
     }
 
@@ -684,8 +750,8 @@ CheckEntry(struct cmd_syndesc *as, char *arock)
     return (rcode);
 }
 
-int
-ListEntries(struct cmd_syndesc *as, char *arock)
+static int
+ListEntries(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code = 0;
     afs_int32 flag, startindex, nentries, nextstartindex;
@@ -704,7 +770,7 @@ ListEntries(struct cmd_syndesc *as, char *arock)
            pr_ListEntries(flag, startindex, &nentries, &entriesp,
                           &nextstartindex);
        if (code) {
-           afs_com_err(whoami, code, "; unable to list entries\n");
+           afs_com_err(whoami, code, "; unable to list entries");
            if (entriesp)
                free(entriesp);
            break;
@@ -721,42 +787,44 @@ ListEntries(struct cmd_syndesc *as, char *arock)
     return code;
 }
 
-int
-ChownGroup(struct cmd_syndesc *as, char *arock)
+static int
+ChownGroup(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
+    afs_int32 code;
     char *name;
+    prname newname = "";
     char *owner;
 
     name = as->parms[0].items->data;
     owner = as->parms[1].items->data;
-    code = pr_ChangeEntry(name, "", 0, owner);
+    code = pr_ChangeEntry(name, newname, 0, owner);
     if (code)
        afs_com_err(whoami, code, "; unable to change owner of %s to %s", name,
                owner);
     return code;
 }
 
-int
-ChangeName(struct cmd_syndesc *as, char *arock)
+static int
+ChangeName(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
+    afs_int32 code;
     char *oldname;
     char *newname;
+    prname owner = "";
 
     oldname = as->parms[0].items->data;
     newname = as->parms[1].items->data;
-    code = pr_ChangeEntry(oldname, newname, 0, "");
+    code = pr_ChangeEntry(oldname, newname, 0, owner);
     if (code)
        afs_com_err(whoami, code, "; unable to change name of %s to %s", oldname,
                newname);
     return code;
 }
 
-int
-ListMax(struct cmd_syndesc *as, char *arock)
+static int
+ListMax(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
+    afs_int32 code;
     afs_int32 maxUser, maxGroup;
 
     code = pr_ListMaxUserId(&maxUser);
@@ -774,10 +842,10 @@ ListMax(struct cmd_syndesc *as, char *arock)
     return code;
 }
 
-int
-SetMax(struct cmd_syndesc *as, char *arock)
+static int
+SetMaxCommand(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
+    afs_int32 code;
     afs_int32 maxid;
 
     code = 0;
@@ -809,15 +877,15 @@ SetMax(struct cmd_syndesc *as, char *arock)
     }
     if (!as->parms[0].items && !as->parms[1].items) {
        code = PRBADARG;
-       printf("Must specify at least one of group or user.\n");
+       fprintf(stderr, "Must specify at least one of group or user.\n");
     }
     return code;
 }
 
-int
-SetFields(struct cmd_syndesc *as, char *arock)
+static int
+SetFields(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
+    afs_int32 code;
     idlist ids;
     namelist names;
     int i;
@@ -835,11 +903,11 @@ SetFields(struct cmd_syndesc *as, char *arock)
        int new;
 
        if (strpbrk(access, "76543210") != 0) { /* all octal digits */
-           sscanf(access, "%lo", &flags);
+           sscanf(access, "%lo", (long unsigned int *) &flags);
        } else {                /* interpret flag bit names */
            if (strlen(access) != 5) {
              form_error:
-               printf("Access bits must be of the form 'somar', not %s\n",
+               fprintf(stderr, "Access bits must be of the form 'somar', not %s\n",
                       access);
                return PRBADARG;
            }
@@ -854,8 +922,8 @@ SetFields(struct cmd_syndesc *as, char *arock)
                else if (access[i] == '-')
                    new = 0;
                else {
-                   printf
-                       ("Access bits out of order or illegal:\n  must be a combination of letters from '%s' or '%s' or hyphen, not %s\n",
+                   fprintf(stderr,
+                       "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);
                    return PRBADARG;
                }
@@ -878,17 +946,6 @@ SetFields(struct cmd_syndesc *as, char *arock)
        }
        mask |= PR_SF_NGROUPS;
     }
-#if FOREIGN
-    if (as->parms[3].items) {  /* limitgroups */
-       code = util_GetInt32(as->parms[3].items->data, &nusers);
-       if (code) {
-           afs_com_err(whoami, code, "because nusers was: '%s'",
-                   as->parms[3].items->data);
-           return code;
-       }
-       mask |= PR_SF_NUSERS;
-    }
-#endif
 
     for (i = 0; i < ids.idlist_len; i++) {
        afs_int32 id = ids.idlist_val[i];
@@ -909,10 +966,10 @@ SetFields(struct cmd_syndesc *as, char *arock)
     return 0;
 }
 
-int
-ListOwned(struct cmd_syndesc *as, char *arock)
+static int
+ListOwned(struct cmd_syndesc *as, void *arock)
 {
-    register afs_int32 code;
+    afs_int32 code;
     idlist ids;
     namelist names;
     namelist list;
@@ -960,23 +1017,39 @@ ListOwned(struct cmd_syndesc *as, char *arock)
 }
 
 static void
-add_std_args(register struct cmd_syndesc *ts)
+add_std_args(struct cmd_syndesc *ts)
 {
-    char test_help[AFSDIR_PATH_MAX];
+    char *test_help;
 
-    sprintf(test_help, "use config file in %s", AFSDIR_SERVER_ETC_DIRPATH);
+    if (asprintf(&test_help, "use config file in %s",
+                AFSDIR_SERVER_ETC_DIRPATH) < 0) {
+       test_help = strdup("use server config file");
+    }
 
-    cmd_Seek(ts, 16);
-    cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
-    cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL, "run unauthenticated");
-    cmd_AddParm(ts, "-test", CMD_FLAG, CMD_OPTIONAL | CMD_HIDE, test_help);
-    cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL,
-               "Continue oper despite reasonable errors");
+    cmd_AddParmAtOffset(ts, OPT_cell, "-cell", CMD_SINGLE, CMD_OPTIONAL,
+                       "cell name");
+    cmd_AddParmAtOffset(ts, OPT_noauth, "-noauth", CMD_FLAG, CMD_OPTIONAL,
+                       "run unauthenticated");
+    cmd_AddParmAtOffset(ts, OPT_test, "-test", CMD_FLAG,
+                       CMD_OPTIONAL | CMD_HIDE, test_help);
+    cmd_AddParmAtOffset(ts, OPT_force, "-force", CMD_FLAG, CMD_OPTIONAL,
+                       "Continue oper despite reasonable errors");
+    cmd_AddParmAtOffset(ts, OPT_localauth, "-localauth", CMD_FLAG,
+                       CMD_OPTIONAL, "use local authentication");
+    cmd_AddParmAtOffset(ts, OPT_auth, "-auth", CMD_FLAG, CMD_OPTIONAL,
+                       "use user's authentication (default)");
+    cmd_AddParmAtOffset(ts, OPT_encrypt, "-encrypt", CMD_FLAG, CMD_OPTIONAL,
+                       "encrypt commands");
+    cmd_AddParmAtOffset(ts, OPT_config, "-config", CMD_SINGLE, CMD_OPTIONAL,
+                       "config location");
+    cmd_AddParmAtOffset(ts, OPT_rxgk, "-rxgk", CMD_SINGLE, CMD_OPTIONAL,
+                       "rxgk security level to use");
+    free(test_help);
 }
 
 /*
 static void add_NameOrId_args (ts)
-  register struct cmd_syndesc *ts;
+  struct cmd_syndesc *ts;
 {
     cmd_AddParm(ts,"-name",CMD_LIST,CMD_OPTIONAL,"user or group name");
     cmd_AddParm(ts,"-id",CMD_LIST,CMD_OPTIONAL,"user or group id");
@@ -988,14 +1061,15 @@ static void add_NameOrId_args (ts)
 int
 main(int argc, char **argv)
 {
-    register afs_int32 code;
-    register struct cmd_syndesc *ts;
+    afs_int32 code;
+    struct cmd_syndesc *ts;
 
     char line[2048];
     char *cp, *lastp;
     int parsec;
     char *parsev[CMD_MAXPARMS];
     char *savec;
+    struct authstate state;
 
 #ifdef WIN32
     WSADATA WSAjunk;
@@ -1007,8 +1081,8 @@ main(int argc, char **argv)
 
 #ifdef AFS_AIX32_ENV
     /*
-     * The following signal action for AIX is necessary so that in case of a 
-     * crash (i.e. core is generated) we can include the user's data section 
+     * The following signal action for AIX is necessary so that in case of a
+     * crash (i.e. core is generated) we can include the user's data section
      * in the core dump. Unfortunately, by default, only a partial core is
      * generated which, in many cases, isn't too useful.
      */
@@ -1020,7 +1094,10 @@ main(int argc, char **argv)
     sigaction(SIGSEGV, &nsa, NULL);
 #endif
 
-    ts = cmd_CreateSyntax("creategroup", CreateGroup, 0,
+    memset(&state, 0, sizeof(state));
+    state.sec = 1; /* default is auth */
+
+    ts = cmd_CreateSyntax("creategroup", CreateGroup, NULL, 0,
                          "create a new group");
     cmd_AddParm(ts, "-name", CMD_LIST, 0, "group name");
     cmd_AddParm(ts, "-owner", CMD_SINGLE, CMD_OPTIONAL, "owner of the group");
@@ -1029,107 +1106,105 @@ main(int argc, char **argv)
     add_std_args(ts);
     cmd_CreateAlias(ts, "cg");
 
-    ts = cmd_CreateSyntax("createuser", CreateUser, 0, "create a new user");
+    ts = cmd_CreateSyntax("createuser", CreateUser, NULL, 0, "create a new user");
     cmd_AddParm(ts, "-name", CMD_LIST, 0, "user name");
     cmd_AddParm(ts, "-id", CMD_LIST, CMD_OPTIONAL, "user id");
     add_std_args(ts);
     cmd_CreateAlias(ts, "cu");
 
-    ts = cmd_CreateSyntax("adduser", AddToGroup, 0, "add a user to a group");
+    ts = cmd_CreateSyntax("adduser", AddToGroup, NULL, 0, "add a user to a group");
     cmd_AddParm(ts, "-user", CMD_LIST, 0, "user name");
     cmd_AddParm(ts, "-group", CMD_LIST, 0, "group name");
     add_std_args(ts);
 
-    ts = cmd_CreateSyntax("removeuser", RemoveFromGroup, 0,
+    ts = cmd_CreateSyntax("removeuser", RemoveFromGroup, NULL, 0,
                          "remove a user from a group");
     cmd_AddParm(ts, "-user", CMD_LIST, 0, "user name");
     cmd_AddParm(ts, "-group", CMD_LIST, 0, "group name");
     add_std_args(ts);
 
-    ts = cmd_CreateSyntax("membership", ListMembership, 0,
+    ts = cmd_CreateSyntax("membership", ListMembership, NULL, 0,
                          "list membership of a user or group");
     cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
+    cmd_AddParm(ts, "-supergroups", CMD_FLAG, CMD_OPTIONAL, "show supergroups");
+    cmd_AddParm(ts, "-expandgroups", CMD_FLAG, CMD_OPTIONAL, "expand super and sub group membership");
     add_std_args(ts);
     cmd_CreateAlias(ts, "groups");
 
-    ts = cmd_CreateSyntax("delete", Delete, 0,
+    ts = cmd_CreateSyntax("delete", Delete, NULL, 0,
                          "delete a user or group from database");
     cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
     add_std_args(ts);
 
-    ts = cmd_CreateSyntax("examine", CheckEntry, 0, "examine an entry");
+    ts = cmd_CreateSyntax("examine", CheckEntry, NULL, 0, "examine an entry");
     cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
     add_std_args(ts);
     cmd_CreateAlias(ts, "check");
 
-    ts = cmd_CreateSyntax("chown", ChownGroup, 0,
+    ts = cmd_CreateSyntax("chown", ChownGroup, NULL, 0,
                          "change ownership of a group");
     cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "group name");
     cmd_AddParm(ts, "-owner", CMD_SINGLE, 0, "new owner");
     add_std_args(ts);
 
-    ts = cmd_CreateSyntax("rename", ChangeName, 0, "rename user or group");
+    ts = cmd_CreateSyntax("rename", ChangeName, NULL, 0, "rename user or group");
     cmd_AddParm(ts, "-oldname", CMD_SINGLE, 0, "old name");
     cmd_AddParm(ts, "-newname", CMD_SINGLE, 0, "new name");
     add_std_args(ts);
     cmd_CreateAlias(ts, "chname");
 
-    ts = cmd_CreateSyntax("listmax", ListMax, 0, "list max id");
+    ts = cmd_CreateSyntax("listmax", ListMax, NULL, 0, "list max id");
     add_std_args(ts);
 
-    ts = cmd_CreateSyntax("setmax", SetMax, 0, "set max id");
+    ts = cmd_CreateSyntax("setmax", SetMaxCommand, NULL, 0, "set max id");
     cmd_AddParm(ts, "-group", CMD_SINGLE, CMD_OPTIONAL, "group max");
     cmd_AddParm(ts, "-user", CMD_SINGLE, CMD_OPTIONAL, "user max");
     add_std_args(ts);
 
-    ts = cmd_CreateSyntax("setfields", SetFields, 0,
+    ts = cmd_CreateSyntax("setfields", SetFields, NULL, 0,
                          "set fields for an entry");
     cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
     cmd_AddParm(ts, "-access", CMD_SINGLE, CMD_OPTIONAL, "set privacy flags");
     cmd_AddParm(ts, "-groupquota", CMD_SINGLE, CMD_OPTIONAL,
                "set limit on group creation");
-#if FOREIGN
-    cmd_AddParm(ts, "-userquota", CMD_SINGLE, CMD_OPTIONAL,
-               "set limit on foreign user creation");
-#endif
     add_std_args(ts);
 
-    ts = cmd_CreateSyntax("listowned", ListOwned, 0,
+    ts = cmd_CreateSyntax("listowned", ListOwned, NULL, 0,
                          "list groups owned by an entry or zero id gets orphaned groups");
     cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
     add_std_args(ts);
 
-    ts = cmd_CreateSyntax("listentries", ListEntries, 0,
+    ts = cmd_CreateSyntax("listentries", ListEntries, NULL, 0,
                          "list users/groups in the protection database");
     cmd_AddParm(ts, "-users", CMD_FLAG, CMD_OPTIONAL, "list user entries");
     cmd_AddParm(ts, "-groups", CMD_FLAG, CMD_OPTIONAL, "list group entries");
     add_std_args(ts);
 
-    ts = cmd_CreateSyntax("interactive", pts_Interactive, 0,
+    ts = cmd_CreateSyntax("interactive", pts_Interactive, NULL, 0,
                          "enter interactive mode");
     add_std_args(ts);
     cmd_CreateAlias(ts, "in");
 
-    ts = cmd_CreateSyntax("quit", pts_Quit, 0, "exit program");
+    ts = cmd_CreateSyntax("quit", pts_Quit, NULL, 0, "exit program");
     add_std_args(ts);
 
-    ts = cmd_CreateSyntax("source", pts_Source, 0, "read commands from file");
+    ts = cmd_CreateSyntax("source", pts_Source, NULL, 0, "read commands from file");
     cmd_AddParm(ts, "-file", CMD_SINGLE, 0, "filename");
     add_std_args(ts);
 
-    ts = cmd_CreateSyntax("sleep", pts_Sleep, 0, "pause for a bit");
+    ts = cmd_CreateSyntax("sleep", pts_Sleep, NULL, 0, "pause for a bit");
     cmd_AddParm(ts, "-delay", CMD_SINGLE, 0, "seconds");
     add_std_args(ts);
 
-    cmd_SetBeforeProc(GetGlobals, 0);
+    cmd_SetBeforeProc(GetGlobals, &state);
 
     finished = 1;
-    source = stdin;
-    if (code = cmd_Dispatch(argc, argv)) {
+    source = NULL;
+    if (cmd_Dispatch(argc, argv)) {
        CleanUp(NULL, NULL);
        exit(1);
     }
-    while (!finished) {
+    while (source && !finished) {
        if (isatty(fileno(source)))
            fprintf(stderr, "pts> ");
        if (!fgets(line, sizeof line, source)) {
@@ -1156,7 +1231,7 @@ main(int argc, char **argv)
        }
        savec = parsev[0];
        parsev[0] = argv[0];
-       code = cmd_Dispatch(parsec, parsev);
+       cmd_Dispatch(parsec, parsev);
        parsev[0] = savec;
        cmd_FreeArgv(parsev);
     }