+getgroups()
+{
+ register struct a {
+ u_int gidsetsize;
+ int *gidset;
+ } *uap = (struct a *)u.u_ap;
+ register int *gp;
+
+ for (gp = &u.u_groups[NGROUPS]; gp > u.u_groups; gp--)
+ if (gp[-1] >= 0)
+ break;
+ if (uap->gidsetsize < gp - u.u_groups) {
+ u.u_error = EINVAL;
+ return;
+ }
+ uap->gidsetsize = gp - u.u_groups;
+ u.u_error = copyout((caddr_t)u.u_groups, (caddr_t)uap->gidset,
+ uap->gidsetsize * sizeof (u.u_groups[0]));
+ if (u.u_error)
+ return;
+ u.u_r.r_val1 = uap->gidsetsize;
+}
+
+setpgrp()
+{
+ register struct proc *p;
+ register struct a {
+ int pid;
+ int pgrp;
+ } *uap = (struct a *)u.u_ap;
+
+ if (uap->pid == 0)
+ uap->pid = u.u_procp->p_pid;
+ p = pfind(uap->pid);
+ if (p == 0) {
+ u.u_error = ESRCH;
+ return;
+ }
+/* need better control mechanisms for process groups */
+ if (p->p_uid != u.u_uid && u.u_uid && !inferior(p)) {
+ u.u_error = EPERM;
+ return;
+ }
+ p->p_pgrp = uap->pgrp;
+}
+
+setreuid()
+{
+ struct a {
+ int ruid;
+ int euid;
+ } *uap;
+ register int ruid, euid;
+
+ uap = (struct a *)u.u_ap;
+ ruid = uap->ruid;
+ if (ruid == -1)
+ ruid = u.u_ruid;
+ if (u.u_ruid != ruid && u.u_uid != ruid && !suser())
+ return;
+ euid = uap->euid;
+ if (euid == -1)
+ euid = u.u_uid;
+ if (u.u_ruid != euid && u.u_uid != euid && !suser())
+ return;
+ /*
+ * Everything's okay, do it.
+ */
+#ifdef QUOTA
+ if (u.u_quota->q_uid != ruid) {
+ qclean();
+ qstart(getquota(ruid, 0, 0));
+ }
+#endif
+ u.u_procp->p_uid = ruid;
+ u.u_ruid = ruid;
+ u.u_uid = euid;
+}
+
+setregid()