1*4882a593Smuzhiyuninherit useradd_base 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun# base-passwd-cross provides the default passwd and group files in the 4*4882a593Smuzhiyun# target sysroot, and shadow -native and -sysroot provide the utilities 5*4882a593Smuzhiyun# and support files needed to add and modify user and group accounts 6*4882a593SmuzhiyunDEPENDS:append:class-target = " base-files shadow-native shadow-sysroot shadow base-passwd" 7*4882a593SmuzhiyunPACKAGE_WRITE_DEPS += "shadow-native" 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun# This preinstall function can be run in four different contexts: 10*4882a593Smuzhiyun# 11*4882a593Smuzhiyun# a) Before do_install 12*4882a593Smuzhiyun# b) At do_populate_sysroot_setscene when installing from sstate packages 13*4882a593Smuzhiyun# c) As the preinst script in the target package at do_rootfs time 14*4882a593Smuzhiyun# d) As the preinst script in the target package on device as a package upgrade 15*4882a593Smuzhiyun# 16*4882a593Smuzhiyunuseradd_preinst () { 17*4882a593SmuzhiyunOPT="" 18*4882a593SmuzhiyunSYSROOT="" 19*4882a593Smuzhiyun 20*4882a593Smuzhiyunif test "x$D" != "x"; then 21*4882a593Smuzhiyun # Installing into a sysroot 22*4882a593Smuzhiyun SYSROOT="$D" 23*4882a593Smuzhiyun OPT="--root $D" 24*4882a593Smuzhiyun 25*4882a593Smuzhiyun # Make sure login.defs is there, this is to make debian package backend work 26*4882a593Smuzhiyun # correctly while doing rootfs. 27*4882a593Smuzhiyun # The problem here is that if /etc/login.defs is treated as a config file for 28*4882a593Smuzhiyun # shadow package, then while performing preinsts for packages that depend on 29*4882a593Smuzhiyun # shadow, there might only be /etc/login.def.dpkg-new there in root filesystem. 30*4882a593Smuzhiyun if [ ! -e $D${sysconfdir}/login.defs -a -e $D${sysconfdir}/login.defs.dpkg-new ]; then 31*4882a593Smuzhiyun cp $D${sysconfdir}/login.defs.dpkg-new $D${sysconfdir}/login.defs 32*4882a593Smuzhiyun fi 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun # user/group lookups should match useradd/groupadd --root 35*4882a593Smuzhiyun export PSEUDO_PASSWD="$SYSROOT" 36*4882a593Smuzhiyunfi 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun# If we're not doing a special SSTATE/SYSROOT install 39*4882a593Smuzhiyun# then set the values, otherwise use the environment 40*4882a593Smuzhiyunif test "x$UA_SYSROOT" = "x"; then 41*4882a593Smuzhiyun # Installing onto a target 42*4882a593Smuzhiyun # Add groups and users defined only for this package 43*4882a593Smuzhiyun GROUPADD_PARAM="${GROUPADD_PARAM}" 44*4882a593Smuzhiyun USERADD_PARAM="${USERADD_PARAM}" 45*4882a593Smuzhiyun GROUPMEMS_PARAM="${GROUPMEMS_PARAM}" 46*4882a593Smuzhiyunfi 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun# Perform group additions first, since user additions may depend 49*4882a593Smuzhiyun# on these groups existing 50*4882a593Smuzhiyunif test "x`echo $GROUPADD_PARAM | tr -d '[:space:]'`" != "x"; then 51*4882a593Smuzhiyun echo "Running groupadd commands..." 52*4882a593Smuzhiyun # Invoke multiple instances of groupadd for parameter lists 53*4882a593Smuzhiyun # separated by ';' 54*4882a593Smuzhiyun opts=`echo "$GROUPADD_PARAM" | cut -d ';' -f 1 | sed -e 's#[ \t]*$##'` 55*4882a593Smuzhiyun remaining=`echo "$GROUPADD_PARAM" | cut -d ';' -f 2- | sed -e 's#[ \t]*$##'` 56*4882a593Smuzhiyun while test "x$opts" != "x"; do 57*4882a593Smuzhiyun perform_groupadd "$SYSROOT" "$OPT $opts" 58*4882a593Smuzhiyun if test "x$opts" = "x$remaining"; then 59*4882a593Smuzhiyun break 60*4882a593Smuzhiyun fi 61*4882a593Smuzhiyun opts=`echo "$remaining" | cut -d ';' -f 1 | sed -e 's#[ \t]*$##'` 62*4882a593Smuzhiyun remaining=`echo "$remaining" | cut -d ';' -f 2- | sed -e 's#[ \t]*$##'` 63*4882a593Smuzhiyun done 64*4882a593Smuzhiyunfi 65*4882a593Smuzhiyun 66*4882a593Smuzhiyunif test "x`echo $USERADD_PARAM | tr -d '[:space:]'`" != "x"; then 67*4882a593Smuzhiyun echo "Running useradd commands..." 68*4882a593Smuzhiyun # Invoke multiple instances of useradd for parameter lists 69*4882a593Smuzhiyun # separated by ';' 70*4882a593Smuzhiyun opts=`echo "$USERADD_PARAM" | cut -d ';' -f 1 | sed -e 's#[ \t]*$##'` 71*4882a593Smuzhiyun remaining=`echo "$USERADD_PARAM" | cut -d ';' -f 2- | sed -e 's#[ \t]*$##'` 72*4882a593Smuzhiyun while test "x$opts" != "x"; do 73*4882a593Smuzhiyun perform_useradd "$SYSROOT" "$OPT $opts" 74*4882a593Smuzhiyun if test "x$opts" = "x$remaining"; then 75*4882a593Smuzhiyun break 76*4882a593Smuzhiyun fi 77*4882a593Smuzhiyun opts=`echo "$remaining" | cut -d ';' -f 1 | sed -e 's#[ \t]*$##'` 78*4882a593Smuzhiyun remaining=`echo "$remaining" | cut -d ';' -f 2- | sed -e 's#[ \t]*$##'` 79*4882a593Smuzhiyun done 80*4882a593Smuzhiyunfi 81*4882a593Smuzhiyun 82*4882a593Smuzhiyunif test "x`echo $GROUPMEMS_PARAM | tr -d '[:space:]'`" != "x"; then 83*4882a593Smuzhiyun echo "Running groupmems commands..." 84*4882a593Smuzhiyun # Invoke multiple instances of groupmems for parameter lists 85*4882a593Smuzhiyun # separated by ';' 86*4882a593Smuzhiyun opts=`echo "$GROUPMEMS_PARAM" | cut -d ';' -f 1 | sed -e 's#[ \t]*$##'` 87*4882a593Smuzhiyun remaining=`echo "$GROUPMEMS_PARAM" | cut -d ';' -f 2- | sed -e 's#[ \t]*$##'` 88*4882a593Smuzhiyun while test "x$opts" != "x"; do 89*4882a593Smuzhiyun perform_groupmems "$SYSROOT" "$OPT $opts" 90*4882a593Smuzhiyun if test "x$opts" = "x$remaining"; then 91*4882a593Smuzhiyun break 92*4882a593Smuzhiyun fi 93*4882a593Smuzhiyun opts=`echo "$remaining" | cut -d ';' -f 1 | sed -e 's#[ \t]*$##'` 94*4882a593Smuzhiyun remaining=`echo "$remaining" | cut -d ';' -f 2- | sed -e 's#[ \t]*$##'` 95*4882a593Smuzhiyun done 96*4882a593Smuzhiyunfi 97*4882a593Smuzhiyun} 98*4882a593Smuzhiyun 99*4882a593Smuzhiyunuseradd_sysroot () { 100*4882a593Smuzhiyun # Pseudo may (do_prepare_recipe_sysroot) or may not (do_populate_sysroot_setscene) be running 101*4882a593Smuzhiyun # at this point so we're explicit about the environment so pseudo can load if 102*4882a593Smuzhiyun # not already present. 103*4882a593Smuzhiyun # PSEUDO_SYSROOT can contain references to the build architecture and COMPONENT_DIR 104*4882a593Smuzhiyun # so needs the STAGING_FIXME below 105*4882a593Smuzhiyun export PSEUDO="${FAKEROOTENV} ${PSEUDO_SYSROOT}${bindir_native}/pseudo" 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun # Explicitly set $D since it isn't set to anything 108*4882a593Smuzhiyun # before do_prepare_recipe_sysroot 109*4882a593Smuzhiyun D=${STAGING_DIR_TARGET} 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun # base-passwd's postinst may not have run yet in which case we'll get called later, just exit. 112*4882a593Smuzhiyun # Beware that in some cases we might see the fake pseudo passwd here, in which case we also must 113*4882a593Smuzhiyun # exit. 114*4882a593Smuzhiyun if [ ! -f $D${sysconfdir}/passwd ] || 115*4882a593Smuzhiyun grep -q this-is-the-pseudo-passwd $D${sysconfdir}/passwd; then 116*4882a593Smuzhiyun exit 0 117*4882a593Smuzhiyun fi 118*4882a593Smuzhiyun 119*4882a593Smuzhiyun # It is also possible we may be in a recipe which doesn't have useradd dependencies and hence the 120*4882a593Smuzhiyun # useradd/groupadd tools are unavailable. If there is no dependency, we assume we don't want to 121*4882a593Smuzhiyun # create users in the sysroot 122*4882a593Smuzhiyun if ! command -v useradd; then 123*4882a593Smuzhiyun bbwarn "command useradd not found!" 124*4882a593Smuzhiyun exit 0 125*4882a593Smuzhiyun fi 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun # Add groups and users defined for all recipe packages 128*4882a593Smuzhiyun GROUPADD_PARAM="${@get_all_cmd_params(d, 'groupadd')}" 129*4882a593Smuzhiyun USERADD_PARAM="${@get_all_cmd_params(d, 'useradd')}" 130*4882a593Smuzhiyun GROUPMEMS_PARAM="${@get_all_cmd_params(d, 'groupmems')}" 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun # Tell the system to use the environment vars 133*4882a593Smuzhiyun UA_SYSROOT=1 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun useradd_preinst 136*4882a593Smuzhiyun} 137*4882a593Smuzhiyun 138*4882a593Smuzhiyun# The export of PSEUDO in useradd_sysroot() above contains references to 139*4882a593Smuzhiyun# ${PSEUDO_SYSROOT} and ${PSEUDO_LOCALSTATEDIR}. Additionally, the logging 140*4882a593Smuzhiyun# shell functions use ${LOGFIFO}. These need to be handled when restoring 141*4882a593Smuzhiyun# postinst-useradd-${PN} from the sstate cache. 142*4882a593SmuzhiyunEXTRA_STAGING_FIXMES += "PSEUDO_SYSROOT PSEUDO_LOCALSTATEDIR LOGFIFO" 143*4882a593Smuzhiyun 144*4882a593Smuzhiyunpython useradd_sysroot_sstate () { 145*4882a593Smuzhiyun scriptfile = None 146*4882a593Smuzhiyun task = d.getVar("BB_CURRENTTASK") 147*4882a593Smuzhiyun if task == "package_setscene": 148*4882a593Smuzhiyun bb.build.exec_func("useradd_sysroot", d) 149*4882a593Smuzhiyun elif task == "prepare_recipe_sysroot": 150*4882a593Smuzhiyun # Used to update this recipe's own sysroot so the user/groups are available to do_install 151*4882a593Smuzhiyun scriptfile = d.expand("${RECIPE_SYSROOT}${bindir}/postinst-useradd-${PN}") 152*4882a593Smuzhiyun bb.build.exec_func("useradd_sysroot", d) 153*4882a593Smuzhiyun elif task == "populate_sysroot": 154*4882a593Smuzhiyun # Used when installed in dependent task sysroots 155*4882a593Smuzhiyun scriptfile = d.expand("${SYSROOT_DESTDIR}${bindir}/postinst-useradd-${PN}") 156*4882a593Smuzhiyun 157*4882a593Smuzhiyun if scriptfile: 158*4882a593Smuzhiyun bb.utils.mkdirhier(os.path.dirname(scriptfile)) 159*4882a593Smuzhiyun with open(scriptfile, 'w') as script: 160*4882a593Smuzhiyun script.write("#!/bin/sh\n") 161*4882a593Smuzhiyun bb.data.emit_func("useradd_sysroot", script, d) 162*4882a593Smuzhiyun script.write("useradd_sysroot\n") 163*4882a593Smuzhiyun os.chmod(scriptfile, 0o755) 164*4882a593Smuzhiyun} 165*4882a593Smuzhiyun 166*4882a593Smuzhiyundo_prepare_recipe_sysroot[postfuncs] += "${SYSROOTFUNC}" 167*4882a593SmuzhiyunSYSROOTFUNC:class-target = "useradd_sysroot_sstate" 168*4882a593SmuzhiyunSYSROOTFUNC = "" 169*4882a593Smuzhiyun 170*4882a593SmuzhiyunSYSROOT_PREPROCESS_FUNCS += "${SYSROOTFUNC}" 171*4882a593Smuzhiyun 172*4882a593SmuzhiyunSSTATEPREINSTFUNCS:append:class-target = " useradd_sysroot_sstate" 173*4882a593Smuzhiyun 174*4882a593Smuzhiyundo_package_setscene[depends] += "${USERADDSETSCENEDEPS}" 175*4882a593Smuzhiyundo_populate_sysroot_setscene[depends] += "${USERADDSETSCENEDEPS}" 176*4882a593SmuzhiyunUSERADDSETSCENEDEPS:class-target = "${MLPREFIX}base-passwd:do_populate_sysroot_setscene pseudo-native:do_populate_sysroot_setscene shadow-native:do_populate_sysroot_setscene ${MLPREFIX}shadow-sysroot:do_populate_sysroot_setscene" 177*4882a593SmuzhiyunUSERADDSETSCENEDEPS = "" 178*4882a593Smuzhiyun 179*4882a593Smuzhiyun# Recipe parse-time sanity checks 180*4882a593Smuzhiyundef update_useradd_after_parse(d): 181*4882a593Smuzhiyun useradd_packages = d.getVar('USERADD_PACKAGES') 182*4882a593Smuzhiyun 183*4882a593Smuzhiyun if not useradd_packages: 184*4882a593Smuzhiyun bb.fatal("%s inherits useradd but doesn't set USERADD_PACKAGES" % d.getVar('FILE', False)) 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun for pkg in useradd_packages.split(): 187*4882a593Smuzhiyun d.appendVarFlag("do_populate_sysroot", "vardeps", "USERADD_PARAM:%s GROUPADD_PARAM:%s GROUPMEMS_PARAM:%s" % (pkg, pkg, pkg)) 188*4882a593Smuzhiyun if not d.getVar('USERADD_PARAM:%s' % pkg) and not d.getVar('GROUPADD_PARAM:%s' % pkg) and not d.getVar('GROUPMEMS_PARAM:%s' % pkg): 189*4882a593Smuzhiyun bb.fatal("%s inherits useradd but doesn't set USERADD_PARAM, GROUPADD_PARAM or GROUPMEMS_PARAM for package %s" % (d.getVar('FILE', False), pkg)) 190*4882a593Smuzhiyun 191*4882a593Smuzhiyunpython __anonymous() { 192*4882a593Smuzhiyun if not bb.data.inherits_class('nativesdk', d) \ 193*4882a593Smuzhiyun and not bb.data.inherits_class('native', d): 194*4882a593Smuzhiyun update_useradd_after_parse(d) 195*4882a593Smuzhiyun} 196*4882a593Smuzhiyun 197*4882a593Smuzhiyun# Return a single [GROUP|USER]ADD_PARAM formatted string which includes the 198*4882a593Smuzhiyun# [group|user]add parameters for all USERADD_PACKAGES in this recipe 199*4882a593Smuzhiyundef get_all_cmd_params(d, cmd_type): 200*4882a593Smuzhiyun import string 201*4882a593Smuzhiyun 202*4882a593Smuzhiyun param_type = cmd_type.upper() + "_PARAM:%s" 203*4882a593Smuzhiyun params = [] 204*4882a593Smuzhiyun 205*4882a593Smuzhiyun useradd_packages = d.getVar('USERADD_PACKAGES') or "" 206*4882a593Smuzhiyun for pkg in useradd_packages.split(): 207*4882a593Smuzhiyun param = d.getVar(param_type % pkg) 208*4882a593Smuzhiyun if param: 209*4882a593Smuzhiyun params.append(param.rstrip(" ;")) 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun return "; ".join(params) 212*4882a593Smuzhiyun 213*4882a593Smuzhiyun# Adds the preinst script into generated packages 214*4882a593Smuzhiyunfakeroot python populate_packages:prepend () { 215*4882a593Smuzhiyun def update_useradd_package(pkg): 216*4882a593Smuzhiyun bb.debug(1, 'adding user/group calls to preinst for %s' % pkg) 217*4882a593Smuzhiyun 218*4882a593Smuzhiyun """ 219*4882a593Smuzhiyun useradd preinst is appended here because pkg_preinst may be 220*4882a593Smuzhiyun required to execute on the target. Not doing so may cause 221*4882a593Smuzhiyun useradd preinst to be invoked twice, causing unwanted warnings. 222*4882a593Smuzhiyun """ 223*4882a593Smuzhiyun preinst = d.getVar('pkg_preinst:%s' % pkg) or d.getVar('pkg_preinst') 224*4882a593Smuzhiyun if not preinst: 225*4882a593Smuzhiyun preinst = '#!/bin/sh\n' 226*4882a593Smuzhiyun preinst += 'bbnote () {\n\techo "NOTE: $*"\n}\n' 227*4882a593Smuzhiyun preinst += 'bbwarn () {\n\techo "WARNING: $*"\n}\n' 228*4882a593Smuzhiyun preinst += 'bbfatal () {\n\techo "ERROR: $*"\n\texit 1\n}\n' 229*4882a593Smuzhiyun preinst += 'perform_groupadd () {\n%s}\n' % d.getVar('perform_groupadd') 230*4882a593Smuzhiyun preinst += 'perform_useradd () {\n%s}\n' % d.getVar('perform_useradd') 231*4882a593Smuzhiyun preinst += 'perform_groupmems () {\n%s}\n' % d.getVar('perform_groupmems') 232*4882a593Smuzhiyun preinst += d.getVar('useradd_preinst') 233*4882a593Smuzhiyun # Expand out the *_PARAM variables to the package specific versions 234*4882a593Smuzhiyun for rep in ["GROUPADD_PARAM", "USERADD_PARAM", "GROUPMEMS_PARAM"]: 235*4882a593Smuzhiyun val = d.getVar(rep + ":" + pkg) or "" 236*4882a593Smuzhiyun preinst = preinst.replace("${" + rep + "}", val) 237*4882a593Smuzhiyun d.setVar('pkg_preinst:%s' % pkg, preinst) 238*4882a593Smuzhiyun 239*4882a593Smuzhiyun # RDEPENDS setup 240*4882a593Smuzhiyun rdepends = d.getVar("RDEPENDS:%s" % pkg) or "" 241*4882a593Smuzhiyun rdepends += ' ' + d.getVar('MLPREFIX', False) + 'base-passwd' 242*4882a593Smuzhiyun rdepends += ' ' + d.getVar('MLPREFIX', False) + 'shadow' 243*4882a593Smuzhiyun # base-files is where the default /etc/skel is packaged 244*4882a593Smuzhiyun rdepends += ' ' + d.getVar('MLPREFIX', False) + 'base-files' 245*4882a593Smuzhiyun d.setVar("RDEPENDS:%s" % pkg, rdepends) 246*4882a593Smuzhiyun 247*4882a593Smuzhiyun # Add the user/group preinstall scripts and RDEPENDS requirements 248*4882a593Smuzhiyun # to packages specified by USERADD_PACKAGES 249*4882a593Smuzhiyun if not bb.data.inherits_class('nativesdk', d) \ 250*4882a593Smuzhiyun and not bb.data.inherits_class('native', d): 251*4882a593Smuzhiyun useradd_packages = d.getVar('USERADD_PACKAGES') or "" 252*4882a593Smuzhiyun for pkg in useradd_packages.split(): 253*4882a593Smuzhiyun update_useradd_package(pkg) 254*4882a593Smuzhiyun} 255*4882a593Smuzhiyun 256*4882a593Smuzhiyun# Use the following to extend the useradd with custom functions 257*4882a593SmuzhiyunUSERADDEXTENSION ?= "" 258*4882a593Smuzhiyun 259*4882a593Smuzhiyuninherit ${USERADDEXTENSION} 260