Resolve missing printf args
[openafs.git] / src / ptserver / ptutils.c
index ce71577..dfa54ee 100644 (file)
@@ -1,13 +1,13 @@
 /*
  * 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
  */
 
-/* 
+/*
  *                      (5) Add functions to process supergroups:
  *                          ChangeIDEntry(), RemoveFromSGEntry(),
  *                          AddToSGEntry(), GetListSG2().
 
 #include <afsconfig.h>
 #include <afs/param.h>
+#include <afs/stds.h>
 
-RCSID
-    ("$Header$");
+#include <roken.h>
 
-#include <afs/stds.h>
-#include <sys/types.h>
-#include <stdio.h>
-#ifdef AFS_NT40_ENV
-#include <winsock2.h>
-#else
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
 #include <lock.h>
 #include <ubik.h>
 #include <rx/xdr.h>
 #include <afs/com_err.h>
 #include <afs/cellconfig.h>
+
 #include "ptserver.h"
 #include "pterror.h"
-#include <stdlib.h>
+#include "ptprototypes.h"
 
 /* Foreign cells are represented by the group system:authuser@cell*/
 #define AUTHUSER_GROUP "system:authuser"
 
-
+extern int restricted;
 extern struct ubik_dbase *dbase;
 extern struct afsconf_dir *prdir;
 extern int pr_noAuth;
-extern int IDCmp();
 
-extern afs_int32 AddToEntry();
+static int inRange(struct prentry *cellEntry, afs_int32 aid);
+static afs_int32 allocNextId(struct ubik_trans *, struct prentry *);
+static int AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size);
+
 static char *whoami = "ptserver";
 
+int prp_user_default = PRP_USER_DEFAULT;
+int prp_group_default = PRP_GROUP_DEFAULT;
+
 #if defined(SUPERGROUPS)
 
 #include "map.h"
 
 afs_int32 depthsg = 5;         /* Maximum iterations used during IsAMemberOF */
-extern int IDCmp();
 afs_int32 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist * alist,
                     afs_int32 * sizeP, afs_int32 depth);
-afs_int32 allocNextId(struct ubik_trans *, struct prentry *);
 
 struct map *sg_flagged;
 struct map *sg_found;
@@ -88,13 +77,11 @@ struct map *sg_found;
  *  so we can always tell if we're writing a group record.
  */
 
-int (*pt_save_dbase_write) ();
+int (*pt_save_dbase_write)(struct ubik_dbase *, afs_int32, void *, afs_int32,
+                           afs_int32);
 
 int
-pt_mywrite(tdb, fno, bp, pos, count)
-     struct ubik_dbase *tdb;
-     afs_int32 fno, pos, count;
-     char *bp;
+pt_mywrite(struct ubik_dbase *tdb, afs_int32 fno, void *bp, afs_int32 pos, afs_int32 count)
 {
     afs_uint32 headersize = ntohl(cheader.headerSize);
 
@@ -113,71 +100,52 @@ pt_mywrite(tdb, fno, bp, pos, count)
            c = ENTRYSIZE - o;
            if (c > l)
                c = l;
+#define xPT(p,x) ((((struct prentry *)(p))->flags & htonl(PRTYPE)) == htonl(x))
 #if DEBUG_SG_MAP
            if (o)
                fprintf(stderr, "Writing %d bytes of entry @ %#lx(+%d)\n", c,
                        p - o, o);
            else if (c == ENTRYSIZE)
                fprintf(stderr,
-                       "Writing %d bytes of entry @ %#lx (%d<%s>,%d)\n", c,
-                       p, ((struct prentry *)cp)->flags,
-                       (((struct prentry *)cp)->flags & PRTYPE) ==
-                       PRUSER ? "user" : (((struct prentry *)cp)->
-                                          flags & PRTYPE) ==
-                       PRFREE ? "free" : (((struct prentry *)cp)->
-                                          flags & PRTYPE) ==
-                       PRGRP ? "group" : (((struct prentry *)cp)->
-                                          flags & PRTYPE) ==
-                       PRCONT ? "cont" : (((struct prentry *)cp)->
-                                          flags & PRTYPE) ==
-                       PRCELL ? "cell" : (((struct prentry *)cp)->
-                                          flags & PRTYPE) ==
-                       PRFOREIGN ? "foreign" : (((struct prentry *)cp)->
-                                                flags & PRTYPE) ==
-                       PRINST ? "sub/super instance" : "?",
-                       ((struct prentry *)cp)->id);
+                       "Writing %d bytes of entry @ %#lx (%d<%s>,%d)\n",
+                       c, p, ntohl(((struct prentry *)cp)->flags),
+                       xPT(cp,PRUSER) ? "user" : xPT(cp,PRFREE) ? "free" :
+                       xPT(cp,PRGRP) ? "group" : xPT(cp,PRCONT) ? "cont" :
+                       xPT(cp,PRCELL) ? "cell" : xPT(cp,PRFOREIGN) ? "foreign" :
+                       xPT(cp,PRINST) ? "sub/super instance" : "?",
+                       ntohl(((struct prentry *)cp)->id));
            else if (c >= 8)
                fprintf(stderr,
                        "Writing first %d bytes of entry @ %#lx (%d<%s>,%d)\n",
-                       c, p, ((struct prentry *)cp)->flags,
-                       (((struct prentry *)cp)->flags & PRTYPE) ==
-                       PRUSER ? "user" : (((struct prentry *)cp)->
-                                          flags & PRTYPE) ==
-                       PRFREE ? "free" : (((struct prentry *)cp)->
-                                          flags & PRTYPE) ==
-                       PRGRP ? "group" : (((struct prentry *)cp)->
-                                          flags & PRTYPE) ==
-                       PRCONT ? "cont" : (((struct prentry *)cp)->
-                                          flags & PRTYPE) ==
-                       PRCELL ? "cell" : (((struct prentry *)cp)->
-                                          flags & PRTYPE) ==
-                       PRFOREIGN ? "foreign" : (((struct prentry *)cp)->
-                                                flags & PRTYPE) ==
-                       PRINST ? "sub/super instance" : "?",
-                       ((struct prentry *)cp)->id);
+                       c, p, ntohl(((struct prentry *)cp)->flags),
+                       xPT(cp,PRUSER) ? "user" : xPT(cp,PRFREE) ? "free" :
+                       xPT(cp,PRGRP) ? "group" : xPT(cp,PRCONT) ? "cont" :
+                       xPT(cp,PRCELL) ? "cell" : xPT(cp,PRFOREIGN) ? "foreign" :
+                       xPT(cp,PRINST) ? "sub/super instance" : "?",
+                       ntohl(((struct prentry *)cp)->id));
            else
                fprintf(stderr, "Writing %d bytes of entry @ %#lx\n", c, p);
 #endif
-           if (!o && c >= 8
-               && (((struct prentry *)cp)->flags & PRTYPE) == PRGRP) {
+           if (!o && c >= 8 && xPT(cp,PRGRP)) {
 #if DEBUG_SG_MAP
-               if (in_map(sg_found, -((struct prentry *)cp)->id))
+               if (in_map(sg_found, -ntohl(((struct prentry *)cp)->id)))
                    fprintf(stderr, "Unfound: Removing group %d\n",
-                           ((struct prentry *)cp)->id);
-               if (in_map(sg_flagged, -((struct prentry *)cp)->id))
+                           ntohl(((struct prentry *)cp)->id));
+               if (in_map(sg_flagged, -ntohl(((struct prentry *)cp)->id)))
                    fprintf(stderr, "Unflag: Removing group %d\n",
-                           ((struct prentry *)cp)->id);
+                           ntohl(((struct prentry *)cp)->id));
 #endif
                sg_found =
                    bic_map(sg_found,
-                           add_map(NIL_MAP, -((struct prentry *)cp)->id));
+                       add_map(NIL_MAP, -ntohl(((struct prentry *)cp)->id)));
                sg_flagged =
                    bic_map(sg_flagged,
-                           add_map(NIL_MAP, -((struct prentry *)cp)->id));
+                       add_map(NIL_MAP, -ntohl(((struct prentry *)cp)->id)));
            }
            cp += c;
            p += c;
            l -= c;
+#undef xPT
        }
     }
     return (*pt_save_dbase_write) (tdb, fno, bp, pos, count);
@@ -188,7 +156,8 @@ pt_mywrite(tdb, fno, bp, pos, count)
  *  just after ubik_ServerInit.
  */
 
-pt_hook_write()
+void
+pt_hook_write(void)
 {
     extern struct ubik_dbase *ubik_dbase;
     if (ubik_dbase->write != pt_mywrite) {
@@ -200,23 +169,18 @@ pt_hook_write()
 #endif /* SUPERGROUPS */
 
 /* CorrectUserName - Check to make sure a user name is OK.  It must not include
- *   either a colon (or it would look like a group) or an atsign (or it would
- *   look like a foreign user).  The length is checked as well to make sure
- *   that the user name, an atsign, and the local cell name will fit in
- *   PR_MAXNAMELEN.  This is so this user can fit in another cells database as
- *   a foreign user with our cell name tacked on.  This is a predicate, so it
- *   return one if name is OK and zero if name is bogus. */
+ *   either a colon (or it would look like a group) or a newline (which can
+ *   confuse some ptdb code, depending on the format we're reading from).
+ *   This is a predicate, so it return one if name is OK and zero if name is
+ *   bogus. */
 
 static int
-CorrectUserName(name)
-     char *name;
+CorrectUserName(char *name)
 {
-    extern int pr_realmNameLen;
-
     /* We accept foreign names, so we will deal with '@' later */
     if (strchr(name, ':') || strchr(name, '\n'))
        return 0;
-    if (strlen(name) >= PR_MAXNAMELEN - pr_realmNameLen - 1)
+    if (strlen(name) >= PR_MAXNAMELEN)
        return 0;
     return 1;
 }
@@ -227,15 +191,13 @@ CorrectUserName(name)
  * rename, which then compares the correct name with the requested new name. */
 
 static afs_int32
-CorrectGroupName(ut, aname, cid, oid, cname)
-     struct ubik_trans *ut;
-     char aname[PR_MAXNAMELEN];        /* name for group */
-     afs_int32 cid;            /* caller id */
-     afs_int32 oid;            /* owner of group */
-     char cname[PR_MAXNAMELEN];        /* correct name for group */
+CorrectGroupName(struct ubik_trans *ut, char aname[PR_MAXNAMELEN],     /* name for group */
+                afs_int32 cid,         /* caller id */
+                afs_int32 oid,         /* owner of group */
+                afs_int32 admin,       /* non-zero if admin */
+                char cname[PR_MAXNAMELEN])     /* correct name for group */
 {
     afs_int32 code;
-    int admin;
     char *prefix;              /* ptr to group owner part */
     char *suffix;              /* ptr to group name part */
     char name[PR_MAXNAMELEN];  /* correct name for group */
@@ -243,10 +205,6 @@ CorrectGroupName(ut, aname, cid, oid, cname)
 
     if (strlen(aname) >= PR_MAXNAMELEN)
        return PRBADNAM;
-    admin = pr_noAuth || IsAMemberOf(ut, cid, SYSADMINID);
-
-    if (oid == 0)
-       oid = cid;
 
     /* Determine the correct prefix for the name. */
     if (oid == SYSADMINID)
@@ -281,6 +239,13 @@ CorrectGroupName(ut, aname, cid, oid, cname)
 
     strcpy(name, aname);       /* in case aname & cname are same */
     suffix = strchr(name, ':');
+    /* let e.g. pt_util create groups with "wrong" names (like
+     * an orphan whose parent ID was reused).  Check that they look like
+     * groups (with a colon) or otherwise are good user names. */
+    if (pr_noAuth) {
+       strcpy(cname, aname);
+       goto done;
+    }
     if (suffix == 0) {
        /* sysadmin can make groups w/o ':', but they must still look like
         * legal user names. */
@@ -308,12 +273,10 @@ CorrectGroupName(ut, aname, cid, oid, cname)
 }
 
 int
-AccessOK(ut, cid, tentry, mem, any)
-     struct ubik_trans *ut;
-     afs_int32 cid;            /* caller id */
-     struct prentry *tentry;   /* object being accessed */
-     int mem;                  /* check membership in aid, if group */
-     int any;                  /* if set return true */
+AccessOK(struct ubik_trans *ut, afs_int32 cid,         /* caller id */
+        struct prentry *tentry,        /* object being accessed */
+        int mem,                       /* check membership in aid, if group */
+        int any)                       /* if set return true */
 {
     afs_int32 flags;
     afs_int32 oid;
@@ -323,6 +286,17 @@ AccessOK(ut, cid, tentry, mem, any)
        return 1;
     if (cid == SYSADMINID)
        return 1;               /* special case fileserver */
+    if (restricted && !IsAMemberOf(ut, cid, SYSADMINID)) {
+        if (mem == PRP_ADD_MEM || mem == PRP_REMOVE_MEM) {
+            /* operation is for adding/removing members from a group */
+            return 0;
+        }
+        if (mem == 0 && any == 0) {
+            /* operation is for modifying an entry (or some administrative
+             * global operations) */
+            return 0;
+        }
+    }
     if (tentry) {
        flags = tentry->flags;
        oid = tentry->owner;
@@ -332,9 +306,9 @@ AccessOK(ut, cid, tentry, mem, any)
     }
     if (!(flags & PRACCESS)) { /* provide default access */
        if (flags & PRGRP)
-           flags |= PRP_GROUP_DEFAULT;
+           flags |= prp_group_default;
        else
-           flags |= PRP_USER_DEFAULT;
+           flags |= prp_user_default;
     }
 
     if (flags & any)
@@ -360,28 +334,27 @@ AccessOK(ut, cid, tentry, mem, any)
 }
 
 afs_int32
-CreateEntry(at, aname, aid, idflag, flag, oid, creator)
-     struct ubik_trans *at;
-     char aname[PR_MAXNAMELEN];
-     afs_int32 *aid;
-     afs_int32 idflag;
-     afs_int32 flag;
-     afs_int32 oid;
-     afs_int32 creator;
+CreateEntry(struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid, afs_int32 idflag, afs_int32 flag, afs_int32 oid, afs_int32 creator)
 {
     /* get and init a new entry */
     afs_int32 code;
     afs_int32 newEntry;
+    afs_int32 admin;
     struct prentry tentry, tent;
     char *atsign;
 
     memset(&tentry, 0, sizeof(tentry));
 
-    if ((oid == 0) || (oid == ANONYMOUSID))
+    admin = pr_noAuth || IsAMemberOf(at, creator, SYSADMINID);
+
+    if (oid == 0 || oid == ANONYMOUSID) {
+       if (!admin && creator == 0)
+           return PRBADARG;
        oid = creator;
+    }
 
     if (flag & PRGRP) {
-       code = CorrectGroupName(at, aname, creator, oid, tentry.name);
+       code = CorrectGroupName(at, aname, creator, oid, admin, tentry.name);
        if (code)
            return code;
        if (strcmp(aname, tentry.name) != 0)
@@ -398,9 +371,7 @@ CreateEntry(at, aname, aid, idflag, flag, oid, creator)
     newEntry = AllocBlock(at);
     if (!newEntry)
        return PRDBFAIL;
-#ifdef PR_REMEMBER_TIMES
     tentry.createTime = time(0);
-#endif
 
     if (flag & PRGRP) {
        tentry.flags = PRGRP;
@@ -443,7 +414,7 @@ CreateEntry(at, aname, aid, idflag, flag, oid, creator)
        }
     } else {
        /* A foreign user: <name>@<cell>. The foreign user is added to
-        * its representing group. It is 
+        * its representing group. It is
         */
        char *cellGroup;
        afs_int32 pos, n;
@@ -452,10 +423,8 @@ CreateEntry(at, aname, aid, idflag, flag, oid, creator)
        /* To create the user <name>@<cell> the group AUTHUSER_GROUP@<cell>
         * must exist.
         */
-       cellGroup =
-           (char *)malloc(strlen(AUTHUSER_GROUP) + strlen(atsign) + 1);
-       strcpy(cellGroup, AUTHUSER_GROUP);
-       strcat(cellGroup, atsign);
+       if (asprintf(&cellGroup, "%s%s", AUTHUSER_GROUP, atsign) < 0)
+           return PRNOMEM;
        pos = FindByName(at, cellGroup, &centry);
        free(cellGroup);
        if (!pos)
@@ -473,7 +442,7 @@ CreateEntry(at, aname, aid, idflag, flag, oid, creator)
                return PRBADARG;
            tentry.id = *aid;
        } else {
-           /* Allocate an ID special for this foreign user. It is based 
+           /* Allocate an ID special for this foreign user. It is based
             * on the representing group's id and nusers count.
             */
            tentry.id = allocNextId(at, &centry);
@@ -495,9 +464,14 @@ CreateEntry(at, aname, aid, idflag, flag, oid, creator)
 
        /* write updated entry for group */
        code = pr_Write(at, 0, pos, &centry, sizeof(centry));
+       if (code)
+           return PRDBFAIL;
 
        /* Now add the new user entry to the database */
-       tentry.creator = creator;
+       if (creator == 0)
+           tentry.creator = tentry.id;
+       else
+           tentry.creator = creator;
        *aid = tentry.id;
        code = pr_WriteEntry(at, 0, newEntry, &tentry);
        if (code)
@@ -573,7 +547,7 @@ CreateEntry(at, aname, aid, idflag, flag, oid, creator)
            }
 
            /* Admins don't get charged for creating a group.
-            * If in noAuth mode, you get changed for it but you 
+            * If in noAuth mode, you get changed for it but you
             * are still allowed to create as many groups as you want.
             */
            admin = ((creator == SYSADMINID)
@@ -599,7 +573,10 @@ CreateEntry(at, aname, aid, idflag, flag, oid, creator)
        tentry.ngroups = tentry.nusers = 20;
     }
 
-    tentry.creator = creator;
+    if (creator == 0)
+       tentry.creator = tentry.id;
+    else
+       tentry.creator = creator;
     *aid = tentry.id;
     code = pr_WriteEntry(at, 0, newEntry, &tentry);
     if (code)
@@ -633,10 +610,7 @@ CreateEntry(at, aname, aid, idflag, flag, oid, creator)
  * entry if appropriate */
 
 afs_int32
-RemoveFromEntry(at, aid, bid)
-     struct ubik_trans *at;
-     afs_int32 aid;
-     afs_int32 bid;
+RemoveFromEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 bid)
 {
     afs_int32 code;
     struct prentry tentry;
@@ -656,9 +630,7 @@ RemoveFromEntry(at, aid, bid)
     code = pr_ReadEntry(at, 0, temp, &tentry);
     if (code != 0)
        return code;
-#ifdef PR_REMEMBER_TIMES
     tentry.removeTime = time(0);
-#endif
     for (i = 0; i < PRSIZE; i++) {
        if (tentry.entries[i] == aid) {
            tentry.entries[i] = PRBADID;
@@ -724,13 +696,9 @@ RemoveFromEntry(at, aid, bid)
  * entry if appropriate */
 
 afs_int32
-ChangeIDEntry(at, aid, newid, bid)
-     register struct ubik_trans *at;
-     register afs_int32 aid;
-     register afs_int32 bid;
-     afs_int32 newid;
+ChangeIDEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 newid, afs_int32 bid)
 {
-    register afs_int32 code;
+    afs_int32 code;
     struct prentry tentry;
     struct contentry centry;
     afs_int32 temp;
@@ -760,7 +728,7 @@ ChangeIDEntry(at, aid, newid, bid)
     }
 
     nptr = tentry.next;
-    while (nptr != NULL) {
+    while (nptr) {
        code = pr_ReadCoEntry(at, 0, nptr, &centry);
        if (code != 0)
            return code;
@@ -796,12 +764,9 @@ ChangeIDEntry(at, aid, newid, bid)
  * continuation entry if appropriate */
 
 afs_int32
-RemoveFromSGEntry(at, aid, bid)
-     register struct ubik_trans *at;
-     register afs_int32 aid;
-     register afs_int32 bid;
+RemoveFromSGEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 bid)
 {
-    register afs_int32 code;
+    afs_int32 code;
     struct prentry tentry;
     struct prentryg *tentryg;
     struct contentry centry;
@@ -821,9 +786,7 @@ RemoveFromSGEntry(at, aid, bid)
     code = pr_ReadEntry(at, 0, temp, &tentry);
     if (code != 0)
        return code;
-#ifdef PR_REMEMBER_TIMES
-    tentry.removeTime = time((afs_int32 *) 0);
-#endif
+    tentry.removeTime = time(NULL);
     tentryg = (struct prentryg *)&tentry;
     for (i = 0; i < SGSIZE; i++) {
        if (tentryg->supergroup[i] == aid) {
@@ -840,7 +803,7 @@ RemoveFromSGEntry(at, aid, bid)
     }
     hloc = 0;
     nptr = tentryg->nextsg;
-    while (nptr != NULL) {
+    while (nptr) {
        code = pr_ReadCoEntry(at, 0, nptr, &centry);
        if (code != 0)
            return code;
@@ -886,7 +849,7 @@ RemoveFromSGEntry(at, aid, bid)
        }                       /* for all coentry slots */
        hloc = nptr;
        nptr = centry.next;
-       bcopy((char *)&centry, (char *)&hentry, sizeof(centry));
+       memcpy(&hentry, &centry, sizeof(centry));
     }                          /* while there are coentries */
     return PRNOENT;
 }
@@ -897,10 +860,7 @@ RemoveFromSGEntry(at, aid, bid)
  * groups, putting groups owned by it on orphan chain, and freeing the space */
 
 afs_int32
-DeleteEntry(at, tentry, loc)
-     struct ubik_trans *at;
-     struct prentry *tentry;
-     afs_int32 loc;
+DeleteEntry(struct ubik_trans *at, struct prentry *tentry, afs_int32 loc)
 {
     afs_int32 code;
     struct contentry centry;
@@ -963,7 +923,7 @@ DeleteEntry(at, tentry, loc)
     }
 #endif /* SUPERGROUPS */
     nptr = tentry->next;
-    while (nptr != (afs_int32) NULL) {
+    while (nptr != 0) {
        code = pr_ReadCoEntry(at, 0, nptr, &centry);
        if (code != 0)
            return PRDBFAIL;
@@ -1051,11 +1011,7 @@ DeleteEntry(at, tentry, loc)
  * Note the entry is written out by this routine. */
 
 afs_int32
-AddToEntry(tt, entry, loc, aid)
-     struct ubik_trans *tt;
-     struct prentry *entry;
-     afs_int32 loc;
-     afs_int32 aid;
+AddToEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
 {
     afs_int32 code;
     afs_int32 i;
@@ -1069,9 +1025,7 @@ AddToEntry(tt, entry, loc, aid)
 
     if (entry->id == aid)
        return PRINCONSISTENT;
-#ifdef PR_REMEMBER_TIMES
     entry->addTime = time(0);
-#endif
     for (i = 0; i < PRSIZE; i++) {
        if (entry->entries[i] == aid)
            return PRIDEXIST;
@@ -1088,7 +1042,7 @@ AddToEntry(tt, entry, loc, aid)
     }
     last = 0;
     nptr = entry->next;
-    while (nptr != (afs_int32) NULL) {
+    while (nptr != 0) {
        code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
        if (code != 0)
            return code;
@@ -1168,13 +1122,9 @@ AddToEntry(tt, entry, loc, aid)
  * Note the entry is written out by this routine. */
 
 afs_int32
-AddToSGEntry(tt, entry, loc, aid)
-     struct ubik_trans *tt;
-     struct prentry *entry;
-     afs_int32 loc;
-     afs_int32 aid;
+AddToSGEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
 {
-    register afs_int32 code;
+    afs_int32 code;
     afs_int32 i;
     struct contentry nentry;
     struct contentry aentry;
@@ -1182,14 +1132,12 @@ AddToSGEntry(tt, entry, loc, aid)
     afs_int32 nptr;
     afs_int32 last;            /* addr of last cont. block */
     afs_int32 first = 0;
-    afs_int32 cloc;
+    afs_int32 cloc = 0;
     afs_int32 slot = -1;
 
     if (entry->id == aid)
        return PRINCONSISTENT;
-#ifdef PR_REMEMBER_TIMES
-    entry->addTime = time((afs_int32 *) 0);
-#endif
+    entry->addTime = time(NULL);
     entryg = (struct prentryg *)entry;
     for (i = 0; i < SGSIZE; i++) {
        if (entryg->supergroup[i] == aid)
@@ -1207,7 +1155,7 @@ AddToSGEntry(tt, entry, loc, aid)
     }
     last = 0;
     nptr = entryg->nextsg;
-    while (nptr != NULL) {
+    while (nptr) {
        code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
        if (code != 0)
            return code;
@@ -1267,7 +1215,7 @@ AddToSGEntry(tt, entry, loc, aid)
     memset(&aentry, 0, sizeof(aentry));
     aentry.flags |= PRCONT;
     aentry.id = entry->id;
-    aentry.next = NULL;
+    aentry.next = 0;
     aentry.entries[0] = aid;
     code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
     if (code != 0)
@@ -1281,25 +1229,21 @@ AddToSGEntry(tt, entry, loc, aid)
 #endif /* SUPERGROUPS */
 
 afs_int32
-AddToPRList(alist, sizeP, id)
-     prlist *alist;
-     int *sizeP;
-     afs_int32 id;
+AddToPRList(prlist *alist, int *sizeP, afs_int32 id)
 {
-    char *tmp;
+    afs_int32 *tmp;
     int count;
 
     if (alist->prlist_len >= *sizeP) {
        count = alist->prlist_len + 100;
        if (alist->prlist_val) {
-           tmp =
-               (char *)realloc(alist->prlist_val, count * sizeof(afs_int32));
+           tmp = realloc(alist->prlist_val, count * sizeof(afs_int32));
        } else {
-           tmp = (char *)malloc(count * sizeof(afs_int32));
+           tmp = malloc(count * sizeof(afs_int32));
        }
        if (!tmp)
            return (PRNOMEM);
-       alist->prlist_val = (afs_int32 *) tmp;
+       alist->prlist_val = tmp;
        *sizeP = count;
     }
     alist->prlist_val[alist->prlist_len++] = id;
@@ -1307,11 +1251,7 @@ AddToPRList(alist, sizeP, id)
 }
 
 afs_int32
-GetList(at, tentry, alist, add)
-     struct ubik_trans *at;
-     struct prentry *tentry;
-     prlist *alist;
-     afs_int32 add;
+GetList(struct ubik_trans *at, struct prentry *tentry, prlist *alist, afs_int32 add)
 {
     afs_int32 code;
     afs_int32 i;
@@ -1362,8 +1302,12 @@ GetList(at, tentry, alist, add)
                return code;
 #endif
        }
-       if (count++ > 50)
-           IOMGR_Poll(), count = 0;
+       if (count++ > 50) {
+#ifndef AFS_PTHREAD_ENV
+           IOMGR_Poll();
+#endif
+           count = 0;
+       }
     }
 
     if (add) {                 /* this is for a CPS, so tack on appropriate stuff */
@@ -1378,20 +1322,17 @@ GetList(at, tentry, alist, add)
                return code;
        }
     }
+#ifndef AFS_PTHREAD_ENV
     if (alist->prlist_len > 100)
        IOMGR_Poll();
+#endif
     qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
     return PRSUCCESS;
 }
 
 
 afs_int32
-GetList2(at, tentry, tentry2, alist, add)
-     struct ubik_trans *at;
-     struct prentry *tentry;
-     struct prentry *tentry2;
-     prlist *alist;
-     afs_int32 add;
+GetList2(struct ubik_trans *at, struct prentry *tentry, struct prentry *tentry2, prlist *alist, afs_int32 add)
 {
     afs_int32 code = 0;
     afs_int32 i;
@@ -1421,7 +1362,7 @@ GetList2(at, tentry, tentry2, alist, add)
     }
 
     nptr = tentry->next;
-    while (nptr != (afs_uint32) NULL) {
+    while (nptr != 0) {
        /* look through cont entries */
        code = pr_ReadCoEntry(at, 0, nptr, &centry);
        if (code != 0)
@@ -1443,8 +1384,12 @@ GetList2(at, tentry, tentry2, alist, add)
 #endif
        }
        nptr = centry.next;
-       if (count++ > 50)
-           IOMGR_Poll(), count = 0;
+       if (count++ > 50) {
+#ifndef AFS_PTHREAD_ENV
+           IOMGR_Poll();
+#endif
+           count = 0;
+       }
     }
 
     for (i = 0; i < PRSIZE; i++) {
@@ -1459,7 +1404,7 @@ GetList2(at, tentry, tentry2, alist, add)
 
     if (!code) {
        nptr = tentry2->next;
-       while (nptr != (afs_uint32) NULL) {
+       while (nptr != 0) {
            /* look through cont entries */
            code = pr_ReadCoEntry(at, 0, nptr, &centry);
            if (code != 0)
@@ -1474,8 +1419,12 @@ GetList2(at, tentry, tentry2, alist, add)
                    break;
            }
            nptr = centry.next;
-           if (count++ > 50)
-               IOMGR_Poll(), count = 0;
+           if (count++ > 50) {
+#ifndef AFS_PTHREAD_ENV
+               IOMGR_Poll();
+#endif
+               count = 0;
+           }
        }
     }
     if (add) {                 /* this is for a CPS, so tack on appropriate stuff */
@@ -1490,8 +1439,10 @@ GetList2(at, tentry, tentry2, alist, add)
                return code;
        }
     }
+#ifndef AFS_PTHREAD_ENV
     if (alist->prlist_len > 100)
        IOMGR_Poll();
+#endif
     qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
     return PRSUCCESS;
 }
@@ -1499,14 +1450,9 @@ GetList2(at, tentry, tentry2, alist, add)
 #if defined(SUPERGROUPS)
 
 afs_int32
-GetListSG2(at, gid, alist, sizeP, depth)
-     struct ubik_trans *at;
-     afs_int32 gid;
-     prlist *alist;
-     afs_int32 depth;
-     afs_int32 *sizeP;
+GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist *alist, afs_int32 *sizeP, afs_int32 depth)
 {
-    register afs_int32 code;
+    afs_int32 code;
     struct prentry tentry;
     struct prentryg *tentryg = (struct prentryg *)&tentry;
     afs_int32 i;
@@ -1578,7 +1524,7 @@ GetListSG2(at, gid, alist, sizeP, depth)
     }
 
     nptr = tentryg->nextsg;
-    while (nptr != NULL) {
+    while (nptr) {
        didsomething = 1;
        /* look through cont entries */
        code = pr_ReadCoEntry(at, 0, nptr, &centry);
@@ -1601,15 +1547,19 @@ GetListSG2(at, gid, alist, sizeP, depth)
                return code;
        }
        nptr = centry.next;
-       if (count++ > 50)
-           IOMGR_Poll(), count = 0;
+       if (count++ > 50) {
+#ifndef AFS_PTHREAD_ENV
+           IOMGR_Poll();
+#endif
+           count = 0;
+       }
     }
 #if DEBUG_SG_MAP
     fprintf(stderr, "] for gid %d, done [flag=%s]\n", gid,
            didsomething ? "TRUE" : "FALSE");
     if (predictflagged && didsomething != predictfound)
        fprintf(stderr, "**** for gid=%d, didsomething=%d predictfound=%d\n",
-               didsomething, predictfound);
+               gid, didsomething, predictfound);
 #endif
     if (didsomething)
        sg_found = add_map(sg_found, -gid);
@@ -1620,12 +1570,9 @@ GetListSG2(at, gid, alist, sizeP, depth)
 }
 
 afs_int32
-GetSGList(at, tentry, alist)
-     struct ubik_trans *at;
-     struct prentry *tentry;
-     prlist *alist;
+GetSGList(struct ubik_trans *at, struct prentry *tentry, prlist *alist)
 {
-    register afs_int32 code;
+    afs_int32 code;
     afs_int32 i;
     struct contentry centry;
     struct prentryg *tentryg;
@@ -1649,7 +1596,7 @@ GetSGList(at, tentry, alist)
     }
 
     nptr = tentryg->nextsg;
-    while (nptr != NULL) {
+    while (nptr) {
        /* look through cont entries */
        code = pr_ReadCoEntry(at, 0, nptr, &centry);
        if (code != 0)
@@ -1664,12 +1611,18 @@ GetSGList(at, tentry, alist)
                return code;
        }
        nptr = centry.next;
-       if (count++ > 50)
-           IOMGR_Poll(), count = 0;
+       if (count++ > 50) {
+#ifndef AFS_PTHREAD_ENV
+           IOMGR_Poll();
+#endif
+           count = 0;
+       }
     }
 
+#ifndef AFS_PTHREAD_ENV
     if (alist->prlist_len > 100)
        IOMGR_Poll();
+#endif
     qsort((char *)alist->prlist_val, (int)alist->prlist_len,
          sizeof(afs_int32), IDCmp);
     return PRSUCCESS;
@@ -1677,10 +1630,7 @@ GetSGList(at, tentry, alist)
 #endif /* SUPERGROUPS */
 
 afs_int32
-GetOwnedChain(ut, next, alist)
-     struct ubik_trans *ut;
-     afs_int32 *next;
-     prlist *alist;
+GetOwnedChain(struct ubik_trans *ut, afs_int32 *next, prlist *alist)
 {
     afs_int32 code;
     struct prentry tentry;
@@ -1701,20 +1651,23 @@ GetOwnedChain(ut, next, alist)
        }
        if (code)
            return code;
-       if (count++ > 50)
-           IOMGR_Poll(), count = 0;
+       if (count++ > 50) {
+#ifndef AFS_PTHREAD_ENV
+           IOMGR_Poll();
+#endif
+           count = 0;
+       }
     }
+#ifndef AFS_PTHREAD_ENV
     if (alist->prlist_len > 100)
        IOMGR_Poll();
+#endif
     qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
     return PRSUCCESS;
 }
 
 afs_int32
-GetMax(at, uid, gid)
-     struct ubik_trans *at;
-     afs_int32 *uid;
-     afs_int32 *gid;
+GetMax(struct ubik_trans *at, afs_int32 *uid, afs_int32 *gid)
 {
     *uid = ntohl(cheader.maxID);
     *gid = ntohl(cheader.maxGroup);
@@ -1722,10 +1675,7 @@ GetMax(at, uid, gid)
 }
 
 afs_int32
-SetMax(at, id, flag)
-     struct ubik_trans *at;
-     afs_int32 id;
-     afs_int32 flag;
+SetMax(struct ubik_trans *at, afs_int32 id, afs_int32 flag)
 {
     afs_int32 code;
     if (flag & PRGRP) {
@@ -1746,32 +1696,70 @@ SetMax(at, id, flag)
     return PRSUCCESS;
 }
 
-afs_int32
-read_DbHeader(tt)
-     struct ubik_trans *tt;
+static afs_int32
+UpdateCache(struct ubik_trans *tt, void *rock)
 {
     afs_int32 code;
 
-    if (!ubik_CacheUpdate(tt))
-       return 0;
-
     code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
     if (code != 0) {
-       com_err(whoami, code, "Couldn't read header");
+       afs_com_err(whoami, code, "Couldn't read header");
     }
     return code;
 }
 
+afs_int32
+read_DbHeader(struct ubik_trans *tt)
+{
+    return ubik_CheckCache(tt, UpdateCache, NULL);
+}
+
 int pr_noAuth;
-afs_int32 initd = 0;
 
-afs_int32
-Initdb()
+/**
+ * reads in db cache from ubik.
+ *
+ * @param[in] ut ubik transaction
+ * @param[out] rock  opaque pointer to an int*, which on success will be set
+ *                   to 1 if we need to build the database, or 0 if we do not
+ *
+ * @return operation status
+ *   @retval 0 success
+ */
+static afs_int32
+Initdb_check(struct ubik_trans *tt, void *rock)
 {
+    int *build_rock = rock;
     afs_int32 code;
-    struct ubik_trans *tt;
     afs_int32 len;
 
+    len = sizeof(cheader);
+    code = pr_Read(tt, 0, 0, (char *)&cheader, len);
+    if (code != 0) {
+       afs_com_err(whoami, code, "couldn't read header");
+       return code;
+    }
+    if ((ntohl(cheader.version) == PRDBVERSION)
+       && ntohl(cheader.headerSize) == sizeof(cheader)
+       && ntohl(cheader.eofPtr) != 0
+       && FindByID(tt, ANONYMOUSID) != 0) {
+       /* database exists, so we don't have to build it */
+       *build_rock = 0;
+       return 0;
+    }
+
+    /* else we need to build a database */
+    *build_rock = 1;
+    return 0;
+}
+
+afs_int32
+Initdb(void)
+{
+    struct ubik_trans *tt;
+    int build = 0;
+    afs_int32 code;
+
     /* init the database.  We'll try reading it, but if we're starting
      * from scratch, we'll have to do a write transaction. */
 
@@ -1785,52 +1773,34 @@ Initdb()
        ubik_AbortTrans(tt);
        return code;
     }
-    if (!initd) {
-       initd = 1;
-    } else if (!ubik_CacheUpdate(tt)) {
-       code = ubik_EndTrans(tt);
-       return code;
-    }
 
-    len = sizeof(cheader);
-    code = pr_Read(tt, 0, 0, (char *)&cheader, len);
-    if (code != 0) {
-       com_err(whoami, code, "couldn't read header");
+    code = ubik_CheckCache(tt, Initdb_check, &build);
+    if (code) {
        ubik_AbortTrans(tt);
        return code;
     }
-    if ((ntohl(cheader.version) == PRDBVERSION)
-       && ntohl(cheader.headerSize) == sizeof(cheader)
-       && ntohl(cheader.eofPtr) != (afs_uint32) NULL
-       && FindByID(tt, ANONYMOUSID) != 0) {
-       /* database exists, so we don't have to build it */
-       code = ubik_EndTrans(tt);
-       if (code)
-           return code;
-       return PRSUCCESS;
-    }
-    /* else we need to build a database */
-    code = ubik_EndTrans(tt);
-    if (code)
-       return code;
 
-    /* Only rebuild database if the db was deleted (the header is zero) and we
-     * are running noAuth. */
-    {
+    if (build) {
+       /* Only rebuild database if the db was deleted (the header is zero) */
        char *bp = (char *)&cheader;
        int i;
-       for (i = 0; i < sizeof(cheader); i++)
+       for (i = 0; i < sizeof(cheader); i++) {
            if (bp[i]) {
                code = PRDBBAD;
-               com_err(whoami, code,
+               afs_com_err(whoami, code,
                        "Can't rebuild database because it is not empty");
-               return code;
+               break;
            }
+       }
+    }
+
+    if (code) {
+       ubik_EndTrans(tt);
+    } else {
+       code = ubik_EndTrans(tt);
     }
-    if (!pr_noAuth) {
-       code = PRDBBAD;
-       com_err(whoami, code,
-               "Can't rebuild database because not running NoAuth");
+    if (code || !build) {
+       /* either we encountered an error, or we don't need to build the db */
        return code;
     }
 
@@ -1849,9 +1819,15 @@ Initdb()
      * actually have been a good database out there.  Now that we have a
      * real write transaction, make sure things are still bad.
      */
+    code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
+    if (code != 0) {
+       afs_com_err(whoami, code, "couldn't read header");
+       ubik_AbortTrans(tt);
+       return code;
+    }
     if ((ntohl(cheader.version) == PRDBVERSION)
        && ntohl(cheader.headerSize) == sizeof(cheader)
-       && ntohl(cheader.eofPtr) != (afs_uint32) NULL
+       && ntohl(cheader.eofPtr) != 0
        && FindByID(tt, ANONYMOUSID) != 0) {
        /* database exists, so we don't have to build it */
        code = ubik_EndTrans(tt);
@@ -1864,7 +1840,7 @@ Initdb()
     if ((code = set_header_word(tt, version, htonl(PRDBVERSION)))
        || (code = set_header_word(tt, headerSize, htonl(sizeof(cheader))))
        || (code = set_header_word(tt, eofPtr, cheader.headerSize))) {
-       com_err(whoami, code, "couldn't write header words");
+       afs_com_err(whoami, code, "couldn't write header words");
        ubik_AbortTrans(tt);
        return code;
     }
@@ -1874,7 +1850,7 @@ Initdb()
     code = CreateEntry               \
        (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
     if (code) {                              \
-       com_err (whoami, code, "couldn't create %s with id %di.",       \
+       afs_com_err (whoami, code, "couldn't create %s with id %di.",   \
                 (name), (id));       \
        ubik_AbortTrans(tt);          \
        return code;                  \
@@ -1892,7 +1868,7 @@ Initdb()
      * it back to 0 */
     code = set_header_word(tt, maxID, 0);      /* correct in any byte order */
     if (code) {
-       com_err(whoami, code, "couldn't reset max id");
+       afs_com_err(whoami, code, "couldn't reset max id");
        ubik_AbortTrans(tt);
        return code;
     }
@@ -1904,23 +1880,20 @@ Initdb()
 }
 
 afs_int32
-ChangeEntry(at, aid, cid, name, oid, newid)
-     struct ubik_trans *at;
-     afs_int32 aid;
-     afs_int32 cid;
-     char *name;
-     afs_int32 oid;
-     afs_int32 newid;
+ChangeEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 cid, char *name, afs_int32 oid, afs_int32 newid)
 {
     afs_int32 code;
-    afs_int32 i, nptr, pos;
+    afs_int32 i, pos;
 #if defined(SUPERGROUPS)
     afs_int32 nextpos;
-#endif
+#else
+    afs_int32 nptr;
     struct contentry centry;
+#endif
     struct prentry tentry, tent;
     afs_int32 loc;
     afs_int32 oldowner;
+    afs_int32 admin;
     char holder[PR_MAXNAMELEN];
     char temp[PR_MAXNAMELEN];
     char oldname[PR_MAXNAMELEN];
@@ -1934,16 +1907,17 @@ ChangeEntry(at, aid, cid, name, oid, newid)
     code = pr_ReadEntry(at, 0, loc, &tentry);
     if (code)
        return PRDBFAIL;
+    if (restricted && !IsAMemberOf(at, cid, SYSADMINID))
+       return PRPERM;
     if (tentry.owner != cid && !IsAMemberOf(at, cid, SYSADMINID)
        && !IsAMemberOf(at, cid, tentry.owner) && !pr_noAuth)
        return PRPERM;
-#ifdef PR_REMEMBER_TIMES
     tentry.changeTime = time(0);
-#endif
+    admin = pr_noAuth || IsAMemberOf(at, cid, SYSADMINID);
 
     /* we're actually trying to change the id */
     if (newid && (newid != aid)) {
-       if (!IsAMemberOf(at, cid, SYSADMINID) && !pr_noAuth)
+       if (!admin)
            return PRPERM;
 
        pos = FindByID(at, newid);
@@ -2006,7 +1980,7 @@ ChangeEntry(at, aid, cid, name, oid, newid)
                break;
        }
        pos = tentry.next;
-       while (pos != NULL) {
+       while (pos) {
 #define centry  (*(struct contentry*)&tent)
            code = pr_ReadCoEntry(at, 0, pos, &centry);
            if ((centry.id != aid)
@@ -2060,7 +2034,7 @@ ChangeEntry(at, aid, cid, name, oid, newid)
                return code;
        }
        /* Look through cont entries too. This needs to be broken into
-        * seperate transaction so that no one transaction becomes too 
+        * seperate transaction so that no one transaction becomes too
         * large to complete.
         */
        for (nptr = tentry.next; nptr; nptr = centry.next) {
@@ -2102,7 +2076,7 @@ ChangeEntry(at, aid, cid, name, oid, newid)
        tentry.owner = oid;
        /* The entry must be written through first so Remove and Add routines
         * can operate on disk data */
-       code = pr_WriteEntry(at, 0, loc, (char *)&tentry);
+       code = pr_WriteEntry(at, 0, loc, &tentry);
        if (code)
            return PRDBFAIL;
 
@@ -2134,7 +2108,11 @@ ChangeEntry(at, aid, cid, name, oid, newid)
            /* don't let foreign cell groups change name */
            if (atsign != NULL)
                return PRPERM;
-           code = CorrectGroupName(at, name, cid, tentry.owner, tentry.name);
+
+           if (tentry.owner == 0 || tentry.owner == ANONYMOUSID)
+               tentry.owner = cid;
+
+           code = CorrectGroupName(at, name, cid, tentry.owner, admin, tentry.name);
            if (code)
                return code;
 
@@ -2169,7 +2147,7 @@ ChangeEntry(at, aid, cid, name, oid, newid)
        if (code != PRSUCCESS)
            return code;
        strncpy(tentry.name, name, PR_MAXNAMELEN);
-       code = pr_WriteEntry(at, 0, loc, (char *)&tentry);
+       code = pr_WriteEntry(at, 0, loc, &tentry);
        if (code)
            return PRDBFAIL;
        code = AddToNameHash(at, tentry.name, loc);
@@ -2181,7 +2159,7 @@ ChangeEntry(at, aid, cid, name, oid, newid)
 }
 
 
-afs_int32
+static afs_int32
 allocNextId(struct ubik_trans * at, struct prentry * cellEntry)
 {
     /* Id's for foreign cell entries are constructed as follows:
@@ -2199,20 +2177,20 @@ allocNextId(struct ubik_trans * at, struct prentry * cellEntry)
     }
 
     cellEntry->nusers = htonl(id);
-    /* use the field nusers to keep 
+    /* use the field nusers to keep
      * the next available id in that
      * foreign cell's group. Note :
      * It would seem more appropriate
      * to use ngroup for that and nusers
      * to enforce the quota, however pts
-     * does not have an option to change 
+     * does not have an option to change
      * foreign users quota yet  */
 
     id = (id << 16) | cellid;
     return id;
 }
 
-int
+static int
 inRange(struct prentry *cellEntry, afs_int32 aid)
 {
     afs_uint32 id, cellid, groupid;
@@ -2221,7 +2199,7 @@ inRange(struct prentry *cellEntry, afs_int32 aid)
     /*
      * The only thing that we want to make sure here is that
      * the id is in the legal range of this group. If it is
-     * a duplicate we don't care since it will get caught 
+     * a duplicate we don't care since it will get caught
      * in a different check.
      */
 
@@ -2230,9 +2208,9 @@ inRange(struct prentry *cellEntry, afs_int32 aid)
     if (cellid != groupid)
        return 0;               /* not in range */
 
-    /* 
+    /*
      * if we got here we're ok but we need to update the nusers
-     * field in order to get the id correct the next time that 
+     * field in order to get the id correct the next time that
      * we try to allocate it automatically
      */
 
@@ -2243,10 +2221,8 @@ inRange(struct prentry *cellEntry, afs_int32 aid)
 
 }
 
-AddAuthGroup(tentry, alist, size)
-     struct prentry *tentry;
-     prlist *alist;
-     afs_int32 *size;
+static int
+AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size)
 {
     if (!(strchr(tentry->name, '@')))
        return (AddToPRList(alist, size, AUTHUSERID));