# module Process::UID

The `Process::UID` module contains a collection of module functions which can be used to portably get, set, and switch the current process’s real, effective, and saved user IDs.

### Public Class Methods

Process::UID.change_privilege(user) → integer click to toggle source

Change the current process’s real and effective user ID to that specified by user. Returns the new user ID. Not available on all platforms.

    [Process.uid, Process.euid]          #=> [0, 0]
    Process::UID.change_privilege(31)    #=> 31
    [Process.uid, Process.euid]          #=> [31, 31]

    static VALUE
    p_uid_change_privilege(VALUE obj, VALUE id)
    {
        rb_uid_t uid;

        check_uid_switch();

        uid = OBJ2UID(id);

        if (geteuid() == 0) { /* root-user */
    #if defined(HAVE_SETRESUID)
            if (setresuid(uid, uid, uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
    #elif defined(HAVE_SETUID)
            if (setuid(uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
    #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
            if (getuid() == uid) {
                if (SAVED_USER_ID == uid) {
                    if (setreuid(-1, uid) < 0) rb_sys_fail(0);
                }
                else {
                    if (uid == 0) { /* (r,e,s) == (root, root, x) */
                        if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
                        if (setreuid(SAVED_USER_ID, 0) < 0) rb_sys_fail(0);
                        SAVED_USER_ID = 0; /* (r,e,s) == (x, root, root) */
                        if (setreuid(uid, uid) < 0) rb_sys_fail(0);
                        SAVED_USER_ID = uid;
                    }
                    else {
                        if (setreuid(0, -1) < 0) rb_sys_fail(0);
                        SAVED_USER_ID = 0;
                        if (setreuid(uid, uid) < 0) rb_sys_fail(0);
                        SAVED_USER_ID = uid;
                    }
                }
            }
            else {
                if (setreuid(uid, uid) < 0) rb_sys_fail(0);
                SAVED_USER_ID = uid;
            }
    #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
            if (getuid() == uid) {
                if (SAVED_USER_ID == uid) {
                    if (seteuid(uid) < 0) rb_sys_fail(0);
                }
                else {
                    if (uid == 0) {
                        if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
                        SAVED_USER_ID = 0;
                        if (setruid(0) < 0) rb_sys_fail(0);
                    }
                    else {
                        if (setruid(0) < 0) rb_sys_fail(0);
                        SAVED_USER_ID = 0;
                        if (seteuid(uid) < 0) rb_sys_fail(0);
                        if (setruid(uid) < 0) rb_sys_fail(0);
                        SAVED_USER_ID = uid;
                    }
                }
            }
            else {
                if (seteuid(uid) < 0) rb_sys_fail(0);
                if (setruid(uid) < 0) rb_sys_fail(0);
                SAVED_USER_ID = uid;
            }
    #else
            (void)uid;
            rb_notimplement();
    #endif
        }
        else { /* unprivileged user */
    #if defined(HAVE_SETRESUID)
            if (setresuid((getuid() == uid)? (rb_uid_t)-1: uid,
                          (geteuid() == uid)? (rb_uid_t)-1: uid,
                          (SAVED_USER_ID == uid)? (rb_uid_t)-1: uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
    #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
            if (SAVED_USER_ID == uid) {
                if (setreuid((getuid() == uid)? (rb_uid_t)-1: uid,
                             (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
                    rb_sys_fail(0);
            }
            else if (getuid() != uid) {
                if (setreuid(uid, (geteuid() == uid)? (rb_uid_t)-1: uid) < 0)
                    rb_sys_fail(0);
                SAVED_USER_ID = uid;
            }
            else if (/* getuid() == uid && */ geteuid() != uid) {
                if (setreuid(geteuid(), uid) < 0) rb_sys_fail(0);
                SAVED_USER_ID = uid;
                if (setreuid(uid, -1) < 0) rb_sys_fail(0);
            }
            else { /* getuid() == uid && geteuid() == uid */
                if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
                if (setreuid(SAVED_USER_ID, uid) < 0) rb_sys_fail(0);
                SAVED_USER_ID = uid;
                if (setreuid(uid, -1) < 0) rb_sys_fail(0);
            }
    #elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
            if (SAVED_USER_ID == uid) {
                if (geteuid() != uid && seteuid(uid) < 0) rb_sys_fail(0);
                if (getuid() != uid && setruid(uid) < 0) rb_sys_fail(0);
            }
            else if (/* SAVED_USER_ID != uid && */ geteuid() == uid) {
                if (getuid() != uid) {
                    if (setruid(uid) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = uid;
                }
                else {
                    if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = uid;
                    if (setruid(uid) < 0) rb_sys_fail(0);
                }
            }
            else if (/* geteuid() != uid && */ getuid() == uid) {
                if (seteuid(uid) < 0) rb_sys_fail(0);
                if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
                SAVED_USER_ID = uid;
                if (setruid(uid) < 0) rb_sys_fail(0);
            }
            else {
                rb_syserr_fail(EPERM, 0);
            }
    #elif defined HAVE_44BSD_SETUID
            if (getuid() == uid) {
                /* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
                if (setuid(uid) < 0) rb_sys_fail(0);
                SAVED_USER_ID = uid;
            }
            else {
                rb_syserr_fail(EPERM, 0);
            }
    #elif defined HAVE_SETEUID
            if (getuid() == uid && SAVED_USER_ID == uid) {
                if (seteuid(uid) < 0) rb_sys_fail(0);
            }
            else {
                rb_syserr_fail(EPERM, 0);
            }
    #elif defined HAVE_SETUID
            if (getuid() == uid && SAVED_USER_ID == uid) {
                if (setuid(uid) < 0) rb_sys_fail(0);
            }
            else {
                rb_syserr_fail(EPERM, 0);
            }
    #else
            rb_notimplement();
    #endif
        }
        return id;
    }

euid → integer click to toggle source
Process::UID.eid → integer
Process::Sys.geteuid → integer

Returns the effective user ID for the current process.

    Process.euid # => 501

    static VALUE
    proc_geteuid(VALUE obj)
    {
        rb_uid_t euid = geteuid();
        return UIDT2NUM(euid);
    }

Process::UID.from_name(name) → uid click to toggle source

Get the user ID by the name. If the user is not found, `ArgumentError` will be raised.

    Process::UID.from_name("root") #=> 0
    Process::UID.from_name("nosuchuser") #=> can't find user for nosuchuser (ArgumentError)

    static VALUE
    p_uid_from_name(VALUE self, VALUE id)
    {
        return UIDT2NUM(OBJ2UID(id));
    }

Process::UID.grant_privilege(user) → integer click to toggle source
Process::UID.eid= user → integer

`Set` the effective user ID, and if possible, the saved user ID of the process to the given user. Returns the new effective user ID. Not available on all platforms.

    [Process.uid, Process.euid]          #=> [0, 0]
    Process::UID.grant_privilege(31)     #=> 31
    [Process.uid, Process.euid]          #=> [0, 31]

    static VALUE
    p_uid_grant_privilege(VALUE obj, VALUE id)
    {
        rb_seteuid_core(OBJ2UID(id));
        return id;
    }

Process::UID.re_exchange → integer click to toggle source

Exchange real and effective user IDs and return the new effective user ID. Not available on all platforms.

    [Process.uid, Process.euid]   #=> [0, 31]
    Process::UID.re_exchange      #=> 0
    [Process.uid, Process.euid]   #=> [31, 0]

    static VALUE
    p_uid_exchange(VALUE obj)
    {
        rb_uid_t uid;
    #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
        rb_uid_t euid;
    #endif

        check_uid_switch();

        uid = getuid();
    #if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID))
        euid = geteuid();
    #endif

    #if defined(HAVE_SETRESUID)
        if (setresuid(euid, uid, uid) < 0) rb_sys_fail(0);
        SAVED_USER_ID = uid;
    #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
        if (setreuid(euid,uid) < 0) rb_sys_fail(0);
        SAVED_USER_ID = uid;
    #else
        rb_notimplement();
    #endif
        return UIDT2NUM(uid);
    }

Process::UID.re_exchangeable? → true or false click to toggle source

Returns `true` if the real and effective user IDs of a process may be exchanged on the current platform.

    static VALUE
    p_uid_exchangeable(VALUE _)
    {
    #if defined(HAVE_SETRESUID)
        return Qtrue;
    #elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
        return Qtrue;
    #else
        return Qfalse;
    #endif
    }

uid → integer click to toggle source
Process::UID.rid → integer
Process::Sys.getuid → integer

Returns the (real) user ID of the current process.

    Process.uid # => 1000

    static VALUE
    proc_getuid(VALUE obj)
    {
        rb_uid_t uid = getuid();
        return UIDT2NUM(uid);
    }

Process::UID.sid_available? → true or false click to toggle source

Returns `true` if the current platform has saved user ID functionality.

    static VALUE
    p_uid_have_saved_id(VALUE _)
    {
    #if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
        return Qtrue;
    #else
        return Qfalse;
    #endif
    }

Process::UID.switch → integer click to toggle source
Process::UID.switch {|| block} → object

Switch the effective and real user IDs of the current process. If a block is given, the user IDs will be switched back after the block is executed. Returns the new effective user ID if called without a block, and the return value of the block if one is given.

    static VALUE
    p_uid_switch(VALUE obj)
    {
        rb_uid_t uid, euid;

        check_uid_switch();

        uid = getuid();
        euid = geteuid();

        if (uid != euid) {
            proc_seteuid(uid);
            if (rb_block_given_p()) {
                under_uid_switch = 1;
                return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID);
            }
            else {
                return UIDT2NUM(euid);
            }
        }
        else if (euid != SAVED_USER_ID) {
            proc_seteuid(SAVED_USER_ID);
            if (rb_block_given_p()) {
                under_uid_switch = 1;
                return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid);
            }
            else {
                return UIDT2NUM(uid);
            }
        }
        else {
            rb_syserr_fail(EPERM, 0);
        }

        UNREACHABLE_RETURN(Qnil);
    }