+ register struct pcred *pc = p->p_cred;
+ register gid_t egid;
+ int error;
+
+ egid = SCARG(uap, egid);
+ if (egid != pc->p_rgid && egid != pc->p_svgid &&
+ (error = suser(pc->pc_ucred, &p->p_acflag)))
+ return (error);
+ pc->pc_ucred = crcopy(pc->pc_ucred);
+ pc->pc_ucred->cr_groups[0] = egid;
+ p->p_flag |= P_SUGID;
+ return (0);
+}
+
+/* ARGSUSED */
+int
+setgroups(p, uap, retval)
+ struct proc *p;
+ struct setgroups_args /* {
+ syscallarg(u_int) gidsetsize;
+ syscallarg(gid_t *) gidset;
+ } */ *uap;
+ register_t *retval;
+{
+ register struct pcred *pc = p->p_cred;
+ register u_int ngrp;
+ int error;
+
+ if (error = suser(pc->pc_ucred, &p->p_acflag))
+ return (error);
+ ngrp = SCARG(uap, gidsetsize);
+ if (ngrp < 1 || ngrp > NGROUPS)
+ return (EINVAL);
+ pc->pc_ucred = crcopy(pc->pc_ucred);
+ if (error = copyin((caddr_t)SCARG(uap, gidset),
+ (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))
+ return (error);
+ pc->pc_ucred->cr_ngroups = ngrp;
+ p->p_flag |= P_SUGID;
+ return (0);
+}
+
+#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
+/* ARGSUSED */
+int
+compat_43_setreuid(p, uap, retval)
+ register struct proc *p;
+ struct compat_43_setreuid_args /* {
+ syscallarg(int) ruid;
+ syscallarg(int) euid;
+ } */ *uap;
+ register_t *retval;
+{
+ register struct pcred *pc = p->p_cred;
+ union {
+ struct setuid_args sa;
+ struct seteuid_args ea;
+ } args;
+
+ /*
+ * If ruid == euid then setreuid is being used to emulate setuid,
+ * just do it.
+ */
+ if (SCARG(uap, ruid) != -1 && SCARG(uap, ruid) == SCARG(uap, euid)) {
+ SCARG(&args.sa, uid) = SCARG(uap, ruid);
+ return (setuid(p, &args.sa, retval));