/*
* call-seq:
* Process::GID.change_privilege(integer) => fixnum
*
* Change the current process's real and effective group ID to that
* specified by _integer_. Returns the new group ID. Not
* available on all platforms.
*
* [Process.gid, Process.egid] #=> [0, 0]
* Process::GID.change_privilege(33) #=> 33
* [Process.gid, Process.egid] #=> [33, 33]
*/
static VALUE
p_gid_change_privilege(obj, id)
VALUE obj, id;
{
int gid;
check_gid_switch();
gid = NUM2INT(id);
if (geteuid() == 0) { /* root-user */
if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (setgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (getgid() == gid) {
if (SAVED_GROUP_ID == gid) {
if (setregid(-1, gid) < 0) rb_sys_fail(0);
} else {
if (gid == 0) { /* (r,e,s) == (root, y, x) */
if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
if (setregid(gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
} else { /* (r,e,s) == (z, y, x) */
if (setregid(0, 0) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = 0;
if (setregid(gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
}
} else {
if (setregid(gid, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
if (getgid() == gid) {
if (SAVED_GROUP_ID == gid) {
if (setegid(gid) < 0) rb_sys_fail(0);
} else {
if (gid == 0) {
if (setegid(gid) < 0) rb_sys_fail(0);
if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = 0;
if (setrgid(0) < 0) rb_sys_fail(0);
} else {
if (setrgid(0) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = 0;
if (setegid(gid) < 0) rb_sys_fail(0);
if (setrgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
}
} else {
if (setegid(gid) < 0) rb_sys_fail(0);
if (setrgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
}
rb_notimplement();
} else { /* unprivileged user */
if (setresgid((getgid() == gid)? -1: gid,
(getegid() == gid)? -1: gid,
(SAVED_GROUP_ID == gid)? -1: gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (SAVED_GROUP_ID == gid) {
if (setregid((getgid() == gid)? -1: gid,
(getegid() == gid)? -1: gid) < 0) rb_sys_fail(0);
} else if (getgid() != gid) {
if (setregid(gid, (getegid() == gid)? -1: gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
} else if (/* getgid() == gid && */ getegid() != gid) {
if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (setregid(gid, -1) < 0) rb_sys_fail(0);
} else { /* getgid() == gid && getegid() == gid */
if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (setregid(gid, -1) < 0) rb_sys_fail(0);
}
if (SAVED_GROUP_ID == gid) {
if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
} else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
if (getgid() != gid) {
if (setrgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
} else {
if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (setrgid(gid) < 0) rb_sys_fail(0);
}
} else if (/* getegid() != gid && */ getgid() == gid) {
if (setegid(gid) < 0) rb_sys_fail(0);
if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
if (setrgid(gid) < 0) rb_sys_fail(0);
} else {
errno = EPERM;
rb_sys_fail(0);
}
if (getgid() == gid) {
/* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
if (setgid(gid) < 0) rb_sys_fail(0);
SAVED_GROUP_ID = gid;
} else {
errno = EPERM;
rb_sys_fail(0);
}
if (getgid() == gid && SAVED_GROUP_ID == gid) {
if (setegid(gid) < 0) rb_sys_fail(0);
} else {
errno = EPERM;
rb_sys_fail(0);
}
if (getgid() == gid && SAVED_GROUP_ID == gid) {
if (setgid(gid) < 0) rb_sys_fail(0);
} else {
errno = EPERM;
rb_sys_fail(0);
}
rb_notimplement();
}
return INT2FIX(gid);
}