模块 Process::GID

Process::GID 模块包含一组模块函数,可用于便携式地获取、设置和切换当前进程的真实、有效和保存的组 ID。

公共类方法

Process::GID.change_privilege(group) → integer 点击切换源代码

将当前进程的真实和有效组 ID 更改为 group 指定的组 ID。返回新的组 ID。并非所有平台都可用。

[Process.gid, Process.egid]          #=> [0, 0]
Process::GID.change_privilege(33)    #=> 33
[Process.gid, Process.egid]          #=> [33, 33]
static VALUE
p_gid_change_privilege(VALUE obj, VALUE id)
{
    rb_gid_t gid;

    check_gid_switch();

    gid = OBJ2GID(id);

    if (geteuid() == 0) { /* root-user */
#if defined(HAVE_SETRESGID)
        if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
#elif defined HAVE_SETGID
        if (setgid(gid) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
        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;
        }
#elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
        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;
        }
#else
        rb_notimplement();
#endif
    }
    else { /* unprivileged user */
#if defined(HAVE_SETRESGID)
        if (setresgid((getgid() == gid)? (rb_gid_t)-1: gid,
                      (getegid() == gid)? (rb_gid_t)-1: gid,
                      (SAVED_GROUP_ID == gid)? (rb_gid_t)-1: gid) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
        if (SAVED_GROUP_ID == gid) {
            if (setregid((getgid() == gid)? (rb_uid_t)-1: gid,
                         (getegid() == gid)? (rb_uid_t)-1: gid) < 0)
                rb_sys_fail(0);
        }
        else if (getgid() != gid) {
            if (setregid(gid, (getegid() == gid)? (rb_uid_t)-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);
        }
#elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
        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 {
            rb_syserr_fail(EPERM, 0);
        }
#elif defined HAVE_44BSD_SETGID
        if (getgid() == gid) {
            /* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
            if (setgid(gid) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = gid;
        }
        else {
            rb_syserr_fail(EPERM, 0);
        }
#elif defined HAVE_SETEGID
        if (getgid() == gid && SAVED_GROUP_ID == gid) {
            if (setegid(gid) < 0) rb_sys_fail(0);
        }
        else {
            rb_syserr_fail(EPERM, 0);
        }
#elif defined HAVE_SETGID
        if (getgid() == gid && SAVED_GROUP_ID == gid) {
            if (setgid(gid) < 0) rb_sys_fail(0);
        }
        else {
            rb_syserr_fail(EPERM, 0);
        }
#else
        (void)gid;
        rb_notimplement();
#endif
    }
    return id;
}
egid → integer 点击切换源代码
Process::GID.eid → integer
Process::Sys.geteid → integer

返回当前进程的有效组 ID

Process.egid # => 500

并非所有平台都可用。

static VALUE
proc_getegid(VALUE obj)
{
    rb_gid_t egid = getegid();

    return GIDT2NUM(egid);
}
Process::GID.from_name(name) → gid 点击切换源代码

通过 name 获取组 ID。如果未找到组,将引发 ArgumentError

Process::GID.from_name("wheel") #=> 0
Process::GID.from_name("nosuchgroup") #=> can't find group for nosuchgroup (ArgumentError)
static VALUE
p_gid_from_name(VALUE self, VALUE id)
{
    return GIDT2NUM(OBJ2GID(id));
}
Process::GID.grant_privilege(group) → integer 点击切换源代码
Process::GID.eid = group → integer

Set 将进程的有效组 ID 以及可能的保存组 ID 设置为给定的 group。返回新的有效组 ID。并非所有平台都可用。

[Process.gid, Process.egid]          #=> [0, 0]
Process::GID.grant_privilege(31)     #=> 33
[Process.gid, Process.egid]          #=> [0, 33]
static VALUE
p_gid_grant_privilege(VALUE obj, VALUE id)
{
    rb_setegid_core(OBJ2GID(id));
    return id;
}
Process::GID.re_exchange → integer 点击切换源代码

交换真实和有效组 ID 并返回新的有效组 ID。并非所有平台都可用。

[Process.gid, Process.egid]   #=> [0, 33]
Process::GID.re_exchange      #=> 0
[Process.gid, Process.egid]   #=> [33, 0]
static VALUE
p_gid_exchange(VALUE obj)
{
    rb_gid_t gid;
#if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
    rb_gid_t egid;
#endif

    check_gid_switch();

    gid = getgid();
#if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID))
    egid = getegid();
#endif

#if defined(HAVE_SETRESGID)
    if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
    SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
    if (setregid(egid,gid) < 0) rb_sys_fail(0);
    SAVED_GROUP_ID = gid;
#else
    rb_notimplement();
#endif
    return GIDT2NUM(gid);
}
Process::GID.re_exchangeable? → true or false 点击切换源代码

如果当前平台可以交换进程的真实和有效组 ID,则返回 true

static VALUE
p_gid_exchangeable(VALUE _)
{
#if defined(HAVE_SETRESGID)
    return Qtrue;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
    return Qtrue;
#else
    return Qfalse;
#endif
}
gid → integer 点击切换源代码
Process::GID.rid → 整数
Process::Sys.getgid → 整数

返回当前进程的(真实)组 ID。

Process.gid # => 1000
static VALUE
proc_getgid(VALUE obj)
{
    rb_gid_t gid = getgid();
    return GIDT2NUM(gid);
}
Process::GID.sid_available? → true 或 false 点击切换源代码

如果当前平台具有保存组 ID 功能,则返回 true

static VALUE
p_gid_have_saved_id(VALUE _)
{
#if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
    return Qtrue;
#else
    return Qfalse;
#endif
}
Process::GID.switch → 整数 点击切换源代码
Process::GID.switch {|| block} → 对象

切换当前进程的有效组 ID 和真实组 ID。如果提供了 block,则在执行完 block 后,组 ID 将被切换回原值。如果在没有 block 的情况下调用,则返回新的有效组 ID;如果提供了 block,则返回 block 的返回值。

static VALUE
p_gid_switch(VALUE obj)
{
    rb_gid_t gid, egid;

    check_gid_switch();

    gid = getgid();
    egid = getegid();

    if (gid != egid) {
        proc_setegid(obj, GIDT2NUM(gid));
        if (rb_block_given_p()) {
            under_gid_switch = 1;
            return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID);
        }
        else {
            return GIDT2NUM(egid);
        }
    }
    else if (egid != SAVED_GROUP_ID) {
        proc_setegid(obj, GIDT2NUM(SAVED_GROUP_ID));
        if (rb_block_given_p()) {
            under_gid_switch = 1;
            return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid);
        }
        else {
            return GIDT2NUM(gid);
        }
    }
    else {
        rb_syserr_fail(EPERM, 0);
    }

    UNREACHABLE_RETURN(Qnil);
}