# Copyright 1999-2022 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # @ECLASS: user-info.eclass # @MAINTAINER: # base-system@gentoo.org (Linux) # Michał Górny <mgorny@gentoo.org> (NetBSD) # @SUPPORTED_EAPIS: 6 7 8 # @BLURB: Read-only access to user and group information case ${EAPI} in 6|7|8) ;; *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; esac if [[ -z ${_USER_INFO_ECLASS} ]]; then _USER_INFO_ECLASS=1 # @FUNCTION: egetent # @USAGE: <database> <key> # @DESCRIPTION: # Small wrapper for getent (Linux), nidump (< Mac OS X 10.5), # dscl (Mac OS X 10.5), and pw (FreeBSD) used in enewuser()/enewgroup(). # # Supported databases: group passwd # Warning: This function can be used only in pkg_* phases when ROOT is valid. egetent() { local db=$1 key=$2 [[ $# -ge 3 ]] && die "usage: egetent <database> <key>" case ${db} in passwd|group) ;; *) die "sorry, database '${db}' not yet supported; file a bug" ;; esac case ${CHOST} in *-freebsd*|*-dragonfly*) case ${db} in passwd) db="user" ;; *) ;; esac # lookup by uid/gid local opts if [[ ${key} == [[:digit:]]* ]] ; then [[ ${db} == "user" ]] && opts=( -u ) || opts=( -g ) fi # Handle different ROOT [[ -n ${ROOT} ]] && opts+=( -R "${ROOT}" ) pw show ${db} ${opts} "${key}" -q ;; *-openbsd*) grep "${key}:\*:" "${EROOT}/etc/${db}" ;; *) # getent does not support -R option, if we are working on a different # ROOT than /, fallback to grep technique. if [[ -z ${ROOT} ]]; then # ignore nscd output if we're not running as root type -p nscd >/dev/null && nscd -i "${db}" 2>/dev/null getent "${db}" "${key}" else if [[ ${key} =~ ^[[:digit:]]+$ ]]; then grep -E "^([^:]*:){2}${key}" "${ROOT}/etc/${db}" else grep "^${key}:" "${ROOT}/etc/${db}" fi fi ;; esac } # @FUNCTION: egetusername # @USAGE: <uid> # @DESCRIPTION: # Gets the username for given UID. egetusername() { [[ $# -eq 1 ]] || die "usage: egetusername <uid>" egetent passwd "$1" | cut -d: -f1 } # @FUNCTION: egetgroupname # @USAGE: <gid> # @DESCRIPTION: # Gets the group name for given GID. egetgroupname() { [[ $# -eq 1 ]] || die "usage: egetgroupname <gid>" egetent group "$1" | cut -d: -f1 } # @FUNCTION: egethome # @USAGE: <user> # @DESCRIPTION: # Gets the home directory for the specified user. egethome() { local pos [[ $# -eq 1 ]] || die "usage: egethome <user>" case ${CHOST} in *-freebsd*|*-dragonfly*) pos=9 ;; *) # Linux, NetBSD, OpenBSD, etc... pos=6 ;; esac egetent passwd "$1" | cut -d: -f${pos} } # @FUNCTION: egetshell # @USAGE: <user> # @DESCRIPTION: # Gets the shell for the specified user. egetshell() { local pos [[ $# -eq 1 ]] || die "usage: egetshell <user>" case ${CHOST} in *-freebsd*|*-dragonfly*) pos=10 ;; *) # Linux, NetBSD, OpenBSD, etc... pos=7 ;; esac egetent passwd "$1" | cut -d: -f${pos} } # @FUNCTION: egetcomment # @USAGE: <user> # @DESCRIPTION: # Gets the comment field for the specified user. egetcomment() { local pos [[ $# -eq 1 ]] || die "usage: egetcomment <user>" case ${CHOST} in *-freebsd*|*-dragonfly*) pos=8 ;; *) # Linux, NetBSD, OpenBSD, etc... pos=5 ;; esac egetent passwd "$1" | cut -d: -f${pos} } # @FUNCTION: egetgroups # @USAGE: <user> # @DESCRIPTION: # Gets all the groups user belongs to. The primary group is returned # first, then all supplementary groups. Groups are ','-separated. egetgroups() { [[ $# -eq 1 ]] || die "usage: egetgroups <user>" local egroups_arr if [[ -n "${ROOT}" ]]; then local pgroup=$(egetent passwd "$1" | cut -d: -f1) local sgroups=( $(grep -E ":([^:]*,)?$1(,[^:]*)?$" "${ROOT}/etc/group" | cut -d: -f1) ) # Remove primary group from list sgroups=${sgroups#${pgroup}} egroups_arr=( ${pgroup} ${sgroups[@]} ) else read -r -a egroups_arr < <(id -G -n "$1") fi local g groups=${egroups_arr[0]} # sort supplementary groups to make comparison possible while read -r g; do [[ -n ${g} ]] && groups+=",${g}" done < <(printf '%s\n' "${egroups_arr[@]:1}" | sort) echo "${groups}" } fi