From 1aaa380a60fa9d2b58aa1f5c97f06732ea781493 Mon Sep 17 00:00:00 2001 From: "Manuel Amador (Rudd-O)" Date: Fri, 3 Sep 2010 16:11:19 -0700 Subject: [PATCH] Split out user management as a waf tool --- tools/waf/usermgmt.py | 120 ++++++++++++++++++++++++++++++++++++++++++ wscript | 51 +----------------- wscript_build | 2 + wscript_configure | 1 + 4 files changed, 124 insertions(+), 50 deletions(-) create mode 100644 tools/waf/usermgmt.py diff --git a/tools/waf/usermgmt.py b/tools/waf/usermgmt.py new file mode 100644 index 00000000000..a140d17ebdc --- /dev/null +++ b/tools/waf/usermgmt.py @@ -0,0 +1,120 @@ +import Utils, Build +from TaskGen import feature, before +from Configure import ConfigurationError +import Options +import Task +import os + +def detect(conf): + if Options.platform == 'win32': return + path_list = ["/usr/local/sbin","/usr/sbin","/sbin"] + os.environ.get('PATH','').split(os.pathsep) + conf.find_program("useradd",var='USERADD',mandatory=True,path_list=path_list) + conf.find_program("userdel",var='USERDEL',mandatory=True,path_list=path_list) + +def set_options(opt): + if Options.platform == 'win32': return + og = opt.get_option_group('--force') + og.add_option('--nochown', + action = 'store_true', + help = 'do not create or remove user accounts or change file ownership on installed files', + default = False, + dest = 'NOUSERMGMT') + +def _subst_add_destdir(x,bld): + a = "${DESTDIR}" + x + a = a.replace("${DESTDIR}",Options.options.destdir) + a = Utils.subst_vars(a,bld.env) + if a.startswith("//"): a = a[1:] + return a +Build.BuildContext.subst_add_destdir = staticmethod(_subst_add_destdir) + +def _setownership(ctx,path,owner,group,mode=None): + if Options.platform == 'win32': return + if not hasattr(os,"getuid"): return + if os.getuid() != 0: return + if Options.options.NOUSERMGMT: return + + import pwd + import grp + import stat + from os import chown as _chown, chmod as _chmod + + def f(bld,path,owner,group,mode): + + try: uid = pwd.getpwnam(owner).pw_uid + except KeyError,e: + raise Utils.WafError("Before using setownership() you have to create the user with bld.createuser(username...)") + try: gid = grp.getgrnam(group).gr_gid + except KeyError,e: + raise Utils.WafError("Before using setownership() you have to create the user with bld.createuser(username...)") + + path = bld.subst_add_destdir(path,bld) + current_uid,current_gid = os.stat(path).st_uid,os.stat(path).st_gid + if current_uid != uid: + Utils.pprint("GREEN","* setting owner of %s to UID %s"%(path,uid)) + _chown(path,uid,current_gid) + current_uid = uid + if current_gid != gid: + Utils.pprint("GREEN","* setting group of %s to GID %s"%(path,gid)) + _chown(path,current_uid,gid) + current_gid = gid + if mode is not None: + current_mode = stat.S_IMODE(os.stat(path).st_mode) + if current_mode != mode: + Utils.pprint("GREEN","* adjusting permissions on %s to mode %o"%(path,mode)) + _chmod(path,mode) + current_mode = mode + + if ctx.is_install > 0: + ctx.add_post_fun(lambda ctx: f(ctx,path,owner,group,mode)) +Build.BuildContext.setownership = _setownership + +def _createuser(ctx,user,homedir,shell): + if Options.platform == 'win32': return + if not hasattr(os,"getuid"): return + if os.getuid() != 0: return + if Options.options.NOUSERMGMT: return + + def f(ctx,user,homedir,shell): + import pwd + try: + pwd.getpwnam(user).pw_uid + user_exists = True + except KeyError,e: + user_exists = False + if user_exists: return + + Utils.pprint("GREEN","* creating user %s"%user) + cmd = [ + ctx.env.USERADD, + '-M', + '-r', + '-s',shell, + '-d',homedir, + user, + ] + ret = Utils.exec_command(cmd) + if ret: raise Utils.WafError("Failed to run command %s"%cmd) + + def g(ctx,user,homedir,shell): + import pwd + try: + pwd.getpwnam(user).pw_uid + user_exists = True + except KeyError,e: + user_exists = False + if not user_exists: return + + Utils.pprint("GREEN","* removing user %s"%user) + cmd = [ + ctx.env.USERDEL, + user, + ] + ret = Utils.exec_command(cmd) + if ret: raise Utils.WafError("Failed to run command %s"%cmd) + + if ctx.is_install > 0: + ctx.add_pre_fun(lambda ctx: f(ctx,user,homedir,shell)) + elif ctx.is_install < 0: + ctx.add_pre_fun(lambda ctx: g(ctx,user,homedir,shell)) +Build.BuildContext.createuser = _createuser \ No newline at end of file diff --git a/wscript b/wscript index 2a039423637..3df0ab91573 100644 --- a/wscript +++ b/wscript @@ -199,14 +199,6 @@ def _getbuildnumber(): # FIXME implement for git return rev Utils.getbuildnumber = _getbuildnumber -def _subst_add_destdir(x,bld): - a = "${DESTDIR}" + x - a = a.replace("${DESTDIR}",Options.options.destdir) - a = Utils.subst_vars(a,bld.env) - if a.startswith("//"): a = a[1:] - return a -Build.BuildContext.subst_add_destdir = staticmethod(_subst_add_destdir) - def mkdir_p(directory): if not _isdir(directory): Utils.pprint("GREEN","Creating directory %s and necessary parents"%directory) @@ -360,48 +352,12 @@ def _substitute(self,listoffiles,install_to=None,cwd=None,dict=None,name=None,** if install_to is not None: self.install_as("%s/%s"%(install_to,inst), tgt, **kwargs) Build.BuildContext.substitute = _substitute -def _setownership(ctx,path,owner,group,mode=None): - def f(bld,path,owner,group,mode): - dochown = not Options.options.NOCHOWN \ - and hasattr(os,"getuid") and os.getuid() == 0 \ - and _chown \ - and _chmod \ - and pwd \ - and grp \ - and stat - if not dochown: return - - try: uid = pwd.getpwnam(owner).pw_uid - except KeyError,e: raise Utils.WafError("If installing as root, please either create a %s user or use the --nochown parameter of waf install to install the files as root"%owner) - try: gid = grp.getgrnam(group).gr_gid - except KeyError,e: raise Utils.WafError("If installing as root, please either create a %s group or use the --nochown parameter of waf install to install the files as root"%group) - - path = _subst_add_destdir(path,bld) - current_uid,current_gid = os.stat(path).st_uid,os.stat(path).st_gid - if current_uid != uid: - Utils.pprint("GREEN","* setting owner of %s to UID %s"%(path,uid)) - _chown(path,uid,current_gid) - current_uid = uid - if current_gid != gid: - Utils.pprint("GREEN","* setting group of %s to GID %s"%(path,gid)) - _chown(path,current_uid,gid) - current_gid = gid - if mode is not None: - current_mode = stat.S_IMODE(os.stat(path).st_mode) - if current_mode != mode: - Utils.pprint("GREEN","* adjusting permissions on %s to mode %o"%(path,mode)) - _chmod(path,mode) - current_mode = mode - - if Options.is_install: - ctx.add_post_fun(lambda ctx: f(ctx,path,owner,group,mode)) -Build.BuildContext.setownership = _setownership - def set_options(opt): """Register command line options""" opt.tool_options('gnu_dirs') opt.tool_options('tar',tooldir='tools/waf') opt.tool_options('mkisofs',tooldir='tools/waf') + opt.tool_options('usermgmt',tooldir='tools/waf') if platform.system() not in ['Windows',"Darwin"]: opt.tool_options('compiler_cc') opt.tool_options('python') opt.tool_options('tomcat',tooldir='tools/waf') @@ -439,11 +395,6 @@ def set_options(opt): default = False, dest = 'NODEPCHECK') inst_dir = opt.get_option_group('--force') # get the group that contains the force - inst_dir.add_option('--nochown', - action='store_true', - help = 'skip chown and chmod upon install (skipped on Windows or by non-root users by default)', - default = False, - dest = 'NOCHOWN') inst_dir.add_option('--preserve-config', action='store_true', help = 'do not install configuration files', diff --git a/wscript_build b/wscript_build index d6da48c6934..39aa0c7ec67 100644 --- a/wscript_build +++ b/wscript_build @@ -287,6 +287,8 @@ if buildpremium: # =================== Empty directory / symlink creation on install target ==================== +bld.createuser(bld.env.MSUSER,bld.env.MSENVIRON,'/bin/sh') + # 7. make log and cache dirs (this actually runs first) if bld.env.DISTRO in 'Windows Mac': pass else: diff --git a/wscript_configure b/wscript_configure index 07eaffceddb..068abb776b9 100644 --- a/wscript_configure +++ b/wscript_configure @@ -112,6 +112,7 @@ conf.check_message_2("%s"%conf.env.PREFIX,"GREEN") conf.check_tool('misc') conf.check_tool("gnu_dirs") conf.check_tool('tar') +conf.check_tool('usermgmt') try: conf.check_tool('mkisofs') except Configure.ConfigurationError,e: raise Configure.ConfigurationError, "The program genisoimage (or mkisofs) could not be found.\nOn Linux: ./waf installrpmdeps or ./waf installdebdeps according to your distro's package format.\nOn Windows: Use cygwin to install the mkisofs package, then ensure that the program is in your PATH."