BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / kern / kern_prot.c
index 2a47782..f0fa590 100644 (file)
@@ -1,23 +1,36 @@
 /*
 /*
- * Copyright (c) 1982, 1986, 1989, 1990 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1989, 1990, 1991 Regents of the University
+ * of California.  All rights reserved.
  *
  *
- * Redistribution is only permitted until one year after the first shipment
- * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
- * binary forms are permitted provided that: (1) source distributions retain
- * this entire copyright notice and comment, and (2) distributions including
- * binaries display the following acknowledgement:  This product includes
- * software developed by the University of California, Berkeley and its
- * contributors'' in the documentation or other materials provided with the
- * distribution and in all advertising materials mentioning features or use
- * of this software.  Neither the name of the University nor the names of
- * its contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)kern_prot.c 7.15 (Berkeley) 7/26/90
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)kern_prot.c 7.21 (Berkeley) 5/3/91
  */
 
 /*
  */
 
 /*
@@ -27,7 +40,7 @@
 #include "param.h"
 #include "acct.h"
 #include "systm.h"
 #include "param.h"
 #include "acct.h"
 #include "systm.h"
-#include "user.h"
+#include "ucred.h"
 #include "proc.h"
 #include "timeb.h"
 #include "times.h"
 #include "proc.h"
 #include "timeb.h"
 #include "times.h"
@@ -42,7 +55,7 @@ getpid(p, uap, retval)
 
        *retval = p->p_pid;
 #ifdef COMPAT_43
 
        *retval = p->p_pid;
 #ifdef COMPAT_43
-       retval[1] = p->p_ppid;
+       retval[1] = p->p_pptr->p_pid;
 #endif
        return (0);
 }
 #endif
        return (0);
 }
@@ -54,20 +67,17 @@ getppid(p, uap, retval)
        int *retval;
 {
 
        int *retval;
 {
 
-       *retval = p->p_ppid;
+       *retval = p->p_pptr->p_pid;
        return (0);
 }
 
        return (0);
 }
 
+/* Get process group ID; note that POSIX getpgrp takes no parameter */
 getpgrp(p, uap, retval)
        struct proc *p;
 getpgrp(p, uap, retval)
        struct proc *p;
-       struct args {
-               int     pid;
-       } *uap;
+       void *uap;
        int *retval;
 {
 
        int *retval;
 {
 
-       if (uap->pid != 0 && (p = pfind(uap->pid)) == 0)
-               return (ESRCH);
        *retval = p->p_pgrp->pg_id;
        return (0);
 }
        *retval = p->p_pgrp->pg_id;
        return (0);
 }
@@ -79,9 +89,9 @@ getuid(p, uap, retval)
        int *retval;
 {
 
        int *retval;
 {
 
-       *retval = p->p_ruid;
+       *retval = p->p_cred->p_ruid;
 #ifdef COMPAT_43
 #ifdef COMPAT_43
-       retval[1] = u.u_cred->cr_uid;
+       retval[1] = p->p_ucred->cr_uid;
 #endif
        return (0);
 }
 #endif
        return (0);
 }
@@ -93,7 +103,7 @@ geteuid(p, uap, retval)
        int *retval;
 {
 
        int *retval;
 {
 
-       *retval = u.u_cred->cr_uid;
+       *retval = p->p_ucred->cr_uid;
        return (0);
 }
 
        return (0);
 }
 
@@ -104,18 +114,17 @@ getgid(p, uap, retval)
        int *retval;
 {
 
        int *retval;
 {
 
-       *retval = p->p_rgid;
+       *retval = p->p_cred->p_rgid;
 #ifdef COMPAT_43
 #ifdef COMPAT_43
-       retval[1] = u.u_cred->cr_groups[0];
+       retval[1] = p->p_ucred->cr_groups[0];
 #endif
        return (0);
 }
 
 /*
 #endif
        return (0);
 }
 
 /*
- * Get effective group ID.
- * The "egid" is groups[0], and thus could be obtained via getgroups;
- * this is somewhat painful to do correctly in a library function,
- * this the existence of this syscall.
+ * Get effective group ID.  The "egid" is groups[0], and could be obtained
+ * via getgroups.  This syscall exists because it is somewhat painful to do
+ * correctly in a library function.
  */
 /* ARGSUSED */
 getegid(p, uap, retval)
  */
 /* ARGSUSED */
 getegid(p, uap, retval)
@@ -124,7 +133,7 @@ getegid(p, uap, retval)
        int *retval;
 {
 
        int *retval;
 {
 
-       *retval = u.u_cred->cr_groups[0];
+       *retval = p->p_ucred->cr_groups[0];
        return (0);
 }
 
        return (0);
 }
 
@@ -136,6 +145,7 @@ getgroups(p, uap, retval)
        } *uap;
        int *retval;
 {
        } *uap;
        int *retval;
 {
+       register struct pcred *pc = p->p_cred;
        register gid_t *gp;
        register int *lp;
        register u_int ngrp;
        register gid_t *gp;
        register int *lp;
        register u_int ngrp;
@@ -143,13 +153,13 @@ getgroups(p, uap, retval)
        int error;
 
        if ((ngrp = uap->gidsetsize) == 0) {
        int error;
 
        if ((ngrp = uap->gidsetsize) == 0) {
-               *retval = u.u_cred->cr_ngroups;
+               *retval = pc->pc_ucred->cr_ngroups;
                return (0);
        }
                return (0);
        }
-       if (ngrp < u.u_cred->cr_ngroups)
+       if (ngrp < pc->pc_ucred->cr_ngroups)
                return (EINVAL);
                return (EINVAL);
-       ngrp = u.u_cred->cr_ngroups;
-       for (gp = u.u_cred->cr_groups, lp = groups; lp < &groups[ngrp]; )
+       ngrp = pc->pc_ucred->cr_ngroups;
+       for (gp = pc->pc_ucred->cr_groups, lp = groups; lp < &groups[ngrp]; )
                *lp++ = *gp++;
        if (error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
            ngrp * sizeof (groups[0])))
                *lp++ = *gp++;
        if (error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
            ngrp * sizeof (groups[0])))
@@ -160,7 +170,7 @@ getgroups(p, uap, retval)
 
 /* ARGSUSED */
 setsid(p, uap, retval)
 
 /* ARGSUSED */
 setsid(p, uap, retval)
-       struct proc *p;
+       register struct proc *p;
        void *uap;
        int *retval;
 {
        void *uap;
        int *retval;
 {
@@ -168,16 +178,16 @@ setsid(p, uap, retval)
        if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
                return (EPERM);
        } else {
        if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
                return (EPERM);
        } else {
-               pgmv(p, p->p_pid, 1);
+               enterpgrp(p, p->p_pid, 1);
                *retval = p->p_pid;
                return (0);
        }
 }
 
 /*
                *retval = p->p_pid;
                return (0);
        }
 }
 
 /*
- * set process group (setpgrp/setpgid)
+ * set process group (setpgid/old setpgrp)
  *
  *
- * caller does setpgrp(pid, pgid)
+ * caller does setpgid(targpid, targpgid)
  *
  * pid must be caller or child of caller (ESRCH)
  * if a child
  *
  * pid must be caller or child of caller (ESRCH)
  * if a child
@@ -188,94 +198,87 @@ setsid(p, uap, retval)
  * pid must not be session leader (EPERM)
  */
 /* ARGSUSED */
  * pid must not be session leader (EPERM)
  */
 /* ARGSUSED */
-setpgrp(cp, uap, retval)
-       struct proc *cp;
+setpgid(curp, uap, retval)
+       struct proc *curp;
        register struct args {
        register struct args {
-               int     pid;
-               int     pgid;
+               int     pid;    /* target process id */
+               int     pgid;   /* target pgrp id */
        } *uap;
        int *retval;
 {
        } *uap;
        int *retval;
 {
-       register struct proc *p;
-       register struct pgrp *pgrp;
+       register struct proc *targp;            /* target process */
+       register struct pgrp *pgrp;             /* target pgrp */
 
 
-       if (uap->pid != 0) {
-               if ((p = pfind(uap->pid)) == 0 || !inferior(p))
+       if (uap->pid != 0 && uap->pid != curp->p_pid) {
+               if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
                        return (ESRCH);
                        return (ESRCH);
-               if (p->p_session != cp->p_session)
+               if (targp->p_session != curp->p_session)
                        return (EPERM);
                        return (EPERM);
-               if (p->p_flag&SEXEC)
+               if (targp->p_flag&SEXEC)
                        return (EACCES);
        } else
                        return (EACCES);
        } else
-               p = cp;
-       if (SESS_LEADER(p))
+               targp = curp;
+       if (SESS_LEADER(targp))
                return (EPERM);
        if (uap->pgid == 0)
                return (EPERM);
        if (uap->pgid == 0)
-               uap->pgid = p->p_pid;
-       else if ((uap->pgid != p->p_pid) &&
-               (((pgrp = pgfind(uap->pgid)) == 0) || 
-                  pgrp->pg_mem == NULL ||
-                  pgrp->pg_session != u.u_procp->p_session))
-               return (EPERM);
-       /*
-        * done checking, now do it
-        */
-       pgmv(p, uap->pgid, 0);
+               uap->pgid = targp->p_pid;
+       else if (uap->pgid != targp->p_pid)
+               if ((pgrp = pgfind(uap->pgid)) == 0 ||
+                   pgrp->pg_session != curp->p_session)
+                       return (EPERM);
+       enterpgrp(targp, uap->pgid, 0);
        return (0);
 }
 
 /* ARGSUSED */
 setuid(p, uap, retval)
        return (0);
 }
 
 /* ARGSUSED */
 setuid(p, uap, retval)
-       register struct proc *p;
+       struct proc *p;
        struct args {
                int     uid;
        } *uap;
        int *retval;
 {
        struct args {
                int     uid;
        } *uap;
        int *retval;
 {
+       register struct pcred *pc = p->p_cred;
        register uid_t uid;
        int error;
 
        uid = uap->uid;
        register uid_t uid;
        int error;
 
        uid = uap->uid;
-       if (uid != p->p_ruid && (error = suser(u.u_cred, &u.u_acflag)))
+       if (uid != pc->p_ruid &&
+           (error = suser(pc->pc_ucred, &p->p_acflag)))
                return (error);
        /*
                return (error);
        /*
-        * Everything's okay, do it.
-        * Copy credentials so other references do not
-        * see our changes.
+        * Everything's okay, do it.  Copy credentials so other references do
+        * not see our changes.
         */
         */
-       if (u.u_cred->cr_ref > 1)
-               u.u_cred = crcopy(u.u_cred);
-       u.u_cred->cr_uid = uid;
-       p->p_uid = uid;
-       p->p_ruid = uid;
-       p->p_svuid = uid;
+       pc->pc_ucred = crcopy(pc->pc_ucred);
+       pc->pc_ucred->cr_uid = uid;
+       pc->p_ruid = uid;
+       pc->p_svuid = uid;
        return (0);
 }
 
 /* ARGSUSED */
 seteuid(p, uap, retval)
        return (0);
 }
 
 /* ARGSUSED */
 seteuid(p, uap, retval)
-       register struct proc *p;
+       struct proc *p;
        struct args {
                int     euid;
        } *uap;
        int *retval;
 {
        struct args {
                int     euid;
        } *uap;
        int *retval;
 {
+       register struct pcred *pc = p->p_cred;
        register uid_t euid;
        int error;
 
        euid = uap->euid;
        register uid_t euid;
        int error;
 
        euid = uap->euid;
-       if (euid != p->p_ruid && euid != p->p_svuid &&
-           (error = suser(u.u_cred, &u.u_acflag)))
+       if (euid != pc->p_ruid && euid != pc->p_svuid &&
+           (error = suser(pc->pc_ucred, &p->p_acflag)))
                return (error);
        /*
                return (error);
        /*
-        * Everything's okay, do it.
-        * Copy credentials so other references do not
-        * see our changes.
+        * Everything's okay, do it.  Copy credentials so other references do
+        * not see our changes.
         */
         */
-       if (u.u_cred->cr_ref > 1)
-               u.u_cred = crcopy(u.u_cred);
-       u.u_cred->cr_uid = euid;
-       p->p_uid = euid;
+       pc->pc_ucred = crcopy(pc->pc_ucred);
+       pc->pc_ucred->cr_uid = euid;
        return (0);
 }
 
        return (0);
 }
 
@@ -287,17 +290,17 @@ setgid(p, uap, retval)
        } *uap;
        int *retval;
 {
        } *uap;
        int *retval;
 {
+       register struct pcred *pc = p->p_cred;
        register gid_t gid;
        int error;
 
        gid = uap->gid;
        register gid_t gid;
        int error;
 
        gid = uap->gid;
-       if (gid != p->p_rgid && (error = suser(u.u_cred, &u.u_acflag)))
+       if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
                return (error);
                return (error);
-       if (u.u_cred->cr_ref > 1)
-               u.u_cred = crcopy(u.u_cred);
-       p->p_rgid = gid;
-       u.u_cred->cr_groups[0] = gid;
-       p->p_svgid = gid;               /* ??? */
+       pc->pc_ucred = crcopy(pc->pc_ucred);
+       pc->pc_ucred->cr_groups[0] = gid;
+       pc->p_rgid = gid;
+       pc->p_svgid = gid;              /* ??? */
        return (0);
 }
 
        return (0);
 }
 
@@ -309,16 +312,16 @@ setegid(p, uap, retval)
        } *uap;
        int *retval;
 {
        } *uap;
        int *retval;
 {
+       register struct pcred *pc = p->p_cred;
        register gid_t egid;
        int error;
 
        egid = uap->egid;
        register gid_t egid;
        int error;
 
        egid = uap->egid;
-       if (egid != p->p_rgid && egid != p->p_svgid &&
-           (error = suser(u.u_cred, &u.u_acflag)))
+       if (egid != pc->p_rgid && egid != pc->p_svgid &&
+           (error = suser(pc->pc_ucred, &p->p_acflag)))
                return (error);
                return (error);
-       if (u.u_cred->cr_ref > 1)
-               u.u_cred = crcopy(u.u_cred);
-       u.u_cred->cr_groups[0] = egid;
+       pc->pc_ucred = crcopy(pc->pc_ucred);
+       pc->pc_ucred->cr_groups[0] = egid;
        return (0);
 }
 
        return (0);
 }
 
@@ -332,79 +335,79 @@ osetreuid(p, uap, retval)
        } *uap;
        int *retval;
 {
        } *uap;
        int *retval;
 {
+       register struct pcred *pc = p->p_cred;
        register uid_t ruid, euid;
        int error;
 
        if (uap->ruid == -1)
        register uid_t ruid, euid;
        int error;
 
        if (uap->ruid == -1)
-               ruid = p->p_ruid;
+               ruid = pc->p_ruid;
        else
                ruid = uap->ruid;
        /*
        else
                ruid = uap->ruid;
        /*
-        * Allow setting real uid to previous effective,
-        * for swapping real and effective.
-        * This should be:
-        *   if (ruid != p->p_ruid && (error = suser(u.u_cred, &u.u_acflag)))
+        * Allow setting real uid to previous effective, for swapping real and
+        * effective.  This should be:
+        *
+        * if (ruid != pc->p_ruid &&
+        *     (error = suser(pc->pc_ucred, &p->p_acflag)))
         */
         */
-       if (ruid != p->p_ruid && ruid != u.u_cred->cr_uid /* XXX */ && 
-           (error = suser(u.u_cred, &u.u_acflag)))
+       if (ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
+           (error = suser(pc->pc_ucred, &p->p_acflag)))
                return (error);
        if (uap->euid == -1)
                return (error);
        if (uap->euid == -1)
-               euid = u.u_cred->cr_uid;
+               euid = pc->pc_ucred->cr_uid;
        else
                euid = uap->euid;
        else
                euid = uap->euid;
-       if (euid != u.u_cred->cr_uid && euid != p->p_ruid &&
-           euid != p->p_svuid && (error = suser(u.u_cred, &u.u_acflag)))
+       if (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid &&
+           euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag)))
                return (error);
        /*
                return (error);
        /*
-        * Everything's okay, do it.
-        * Copy credentials so other references do not
-        * see our changes.
+        * Everything's okay, do it.  Copy credentials so other references do
+        * not see our changes.
         */
         */
-       if (u.u_cred->cr_ref > 1)
-               u.u_cred = crcopy(u.u_cred);
-       u.u_cred->cr_uid = euid;
-       p->p_uid = euid;
-       p->p_ruid = ruid;
+       pc->pc_ucred = crcopy(pc->pc_ucred);
+       pc->pc_ucred->cr_uid = euid;
+       pc->p_ruid = ruid;
        return (0);
 }
 
 /* ARGSUSED */
 osetregid(p, uap, retval)
        return (0);
 }
 
 /* ARGSUSED */
 osetregid(p, uap, retval)
-       struct proc *p;
+       register struct proc *p;
        struct args {
                int     rgid;
                int     egid;
        } *uap;
        int *retval;
 {
        struct args {
                int     rgid;
                int     egid;
        } *uap;
        int *retval;
 {
+       register struct pcred *pc = p->p_cred;
        register gid_t rgid, egid;
        int error;
 
        if (uap->rgid == -1)
        register gid_t rgid, egid;
        int error;
 
        if (uap->rgid == -1)
-               rgid = p->p_rgid;
+               rgid = pc->p_rgid;
        else
                rgid = uap->rgid;
        /*
        else
                rgid = uap->rgid;
        /*
-        * Allow setting real gid to previous effective,
-        * for swapping real and effective.  This didn't really work
-        * correctly in 4.[23], but is preserved so old stuff doesn't fail.
-        * This should be:
-        *  if (rgid != p->p_rgid && (error = suser(u.u_cred, &u.u_acflag)))
+        * Allow setting real gid to previous effective, for swapping real and
+        * effective.  This didn't really work correctly in 4.[23], but is
+        * preserved so old stuff doesn't fail.  This should be:
+        *
+        * if (rgid != pc->p_rgid &&
+        *     (error = suser(pc->pc_ucred, &p->p_acflag)))
         */
         */
-       if (rgid != p->p_rgid && rgid != u.u_cred->cr_groups[0] /* XXX */ &&
-           (error = suser(u.u_cred, &u.u_acflag)))
+       if (rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_groups[0] /* XXX */ &&
+           (error = suser(pc->pc_ucred, &p->p_acflag)))
                return (error);
        if (uap->egid == -1)
                return (error);
        if (uap->egid == -1)
-               egid = u.u_cred->cr_groups[0];
+               egid = pc->pc_ucred->cr_groups[0];
        else
                egid = uap->egid;
        else
                egid = uap->egid;
-       if (egid != u.u_cred->cr_groups[0] && egid != p->p_rgid && 
-           egid != p->p_svgid && (error = suser(u.u_cred, &u.u_acflag)))
+       if (egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid &&
+           egid != pc->p_svgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
                return (error);
                return (error);
-       if (u.u_cred->cr_ref > 1)
-               u.u_cred = crcopy(u.u_cred);
-       p->p_rgid = rgid;
-       u.u_cred->cr_groups[0] = egid;
+       pc->pc_ucred = crcopy(pc->pc_ucred);
+       pc->pc_ucred->cr_groups[0] = egid;
+       pc->p_rgid = rgid;
        return (0);
 }
 #endif
        return (0);
 }
 #endif
@@ -418,21 +421,23 @@ setgroups(p, uap, retval)
        } *uap;
        int *retval;
 {
        } *uap;
        int *retval;
 {
+       register struct pcred *pc = p->p_cred;
        register gid_t *gp;
        register u_int ngrp;
        register int *lp;
        int error, groups[NGROUPS];
 
        register gid_t *gp;
        register u_int ngrp;
        register int *lp;
        int error, groups[NGROUPS];
 
-       if (error = suser(u.u_cred, &u.u_acflag))
+       if (error = suser(pc->pc_ucred, &p->p_acflag))
                return (error);
        if ((ngrp = uap->gidsetsize) > NGROUPS)
                return (EINVAL);
        if (error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
            ngrp * sizeof (groups[0])))
                return (error);
                return (error);
        if ((ngrp = uap->gidsetsize) > NGROUPS)
                return (EINVAL);
        if (error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
            ngrp * sizeof (groups[0])))
                return (error);
-       u.u_cred->cr_ngroups = ngrp;
+       pc->pc_ucred = crcopy(pc->pc_ucred);
+       pc->pc_ucred->cr_ngroups = ngrp;
        /* convert from int's to gid_t's */
        /* convert from int's to gid_t's */
-       for (gp = u.u_cred->cr_groups, lp = groups; ngrp--; )
+       for (gp = pc->pc_ucred->cr_groups, lp = groups; ngrp--; )
                *gp++ = *lp++;
        return (0);
 }
                *gp++ = *lp++;
        return (0);
 }
@@ -455,13 +460,15 @@ groupmember(gid, cred)
 }
 
 /*
 }
 
 /*
- * Test if the current user is the super user.
+ * Test whether the specified credentials imply "super-user"
+ * privilege; if so, and we have accounting info, set the flag
+ * indicating use of super-powers.
+ * Returns 0 or error.
  */
 suser(cred, acflag)
        struct ucred *cred;
        short *acflag;
 {
  */
 suser(cred, acflag)
        struct ucred *cred;
        short *acflag;
 {
-
        if (cred->cr_uid == 0) {
                if (acflag)
                        *acflag |= ASU;
        if (cred->cr_uid == 0) {
                if (acflag)
                        *acflag |= ASU;
@@ -491,7 +498,7 @@ crget()
 crfree(cr)
        struct ucred *cr;
 {
 crfree(cr)
        struct ucred *cr;
 {
-       int s = splimp();
+       int s = splimp();                       /* ??? */
 
        if (--cr->cr_ref != 0) {
                (void) splx(s);
 
        if (--cr->cr_ref != 0) {
                (void) splx(s);
@@ -510,6 +517,8 @@ crcopy(cr)
 {
        struct ucred *newcr;
 
 {
        struct ucred *newcr;
 
+       if (cr->cr_ref == 1)
+               return (cr);
        newcr = crget();
        *newcr = *cr;
        crfree(cr);
        newcr = crget();
        *newcr = *cr;
        crfree(cr);
@@ -545,10 +554,10 @@ getlogin(p, uap, retval)
        int *retval;
 {
 
        int *retval;
 {
 
-       if (uap->namelen > sizeof (p->p_logname))
-               uap->namelen = sizeof (p->p_logname);
-       return (copyout((caddr_t)p->p_logname, (caddr_t)uap->namebuf,
-           uap->namelen));
+       if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login))
+               uap->namelen = sizeof (p->p_pgrp->pg_session->s_login);
+       return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
+           (caddr_t) uap->namebuf, uap->namelen));
 }
 
 /*
 }
 
 /*
@@ -564,11 +573,12 @@ setlogin(p, uap, retval)
 {
        int error;
 
 {
        int error;
 
-       if (error = suser(u.u_cred, &u.u_acflag))
+       if (error = suser(p->p_ucred, &p->p_acflag))
                return (error);
                return (error);
-       error = copyinstr((caddr_t)uap->namebuf, (caddr_t)p->p_logname,
-           sizeof (p->p_logname) - 1, (int *) 0);
-       if (error == ENOENT)            /* name too long */
+       error = copyinstr((caddr_t) uap->namebuf,
+           (caddr_t) p->p_pgrp->pg_session->s_login,
+           sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0);
+       if (error == ENAMETOOLONG)
                error = EINVAL;
        return (error);
 }
                error = EINVAL;
        return (error);
 }