+ register struct pcred *pc = p->p_cred;
+ register gid_t rgid, egid;
+ int error;
+
+ if (uap->rgid == -1)
+ rgid = pc->p_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 != pc->p_rgid &&
+ * (error = suser(pc->pc_ucred, &p->p_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)
+ egid = pc->pc_ucred->cr_groups[0];
+ else
+ egid = uap->egid;
+ 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);
+ pc->pc_ucred = crcopy(pc->pc_ucred);
+ pc->pc_ucred->cr_groups[0] = egid;
+ pc->p_rgid = rgid;
+ p->p_flag |= SUGID;
+ return (0);