+ egid = 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);
+}
+
+struct setgroups_args {
+ u_int gidsetsize;
+ gid_t *gidset;
+};
+/* ARGSUSED */
+setgroups(p, uap, retval)
+ struct proc *p;
+ struct setgroups_args *uap;
+ int *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);
+ if ((ngrp = uap->gidsetsize) > NGROUPS)
+ return (EINVAL);
+ pc->pc_ucred = crcopy(pc->pc_ucred);
+ if (error = copyin((caddr_t)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)
+struct setreuid_args {
+ int ruid;
+ int euid;
+};
+/* ARGSUSED */
+osetreuid(p, uap, retval)
+ register struct proc *p;
+ struct setreuid_args *uap;
+ int *retval;
+{
+ register struct pcred *pc = p->p_cred;
+ struct seteuid_args args;
+
+ /*
+ * we assume that the intent of setting ruid is to be able to get
+ * back ruid priviledge. So we make sure that we will be able to
+ * do so, but do not actually set the ruid.
+ */
+ if (uap->ruid != (uid_t)-1 && uap->ruid != pc->p_ruid &&
+ uap->ruid != pc->p_svuid)
+ return (EPERM);
+ if (uap->euid == (uid_t)-1)
+ return (0);
+ args.euid = uap->euid;
+ return (seteuid(p, &args, retval));
+}
+
+struct setregid_args {
+ int rgid;
+ int egid;
+};
+/* ARGSUSED */
+osetregid(p, uap, retval)
+ register struct proc *p;
+ struct setregid_args *uap;
+ int *retval;
+{
+ register struct pcred *pc = p->p_cred;
+ struct setegid_args args;
+
+ /*
+ * we assume that the intent of setting rgid is to be able to get
+ * back rgid priviledge. So we make sure that we will be able to
+ * do so, but do not actually set the rgid.
+ */
+ if (uap->rgid != (gid_t)-1 && uap->rgid != pc->p_rgid &&
+ uap->rgid != pc->p_svgid)
+ return (EPERM);
+ if (uap->egid == (gid_t)-1)
+ return (0);
+ args.egid = uap->egid;
+ return (setegid(p, &args, retval));