#
# Copyright OpenEmbedded Contributors
#
# SPDX-License-Identifier: MIT
#

# In order to support a deterministic set of 'dynamic' users/groups,
# we need a function to reformat the params based on a static file
def update_useradd_static_config(d):
    import itertools
    import re
    import errno
    import oe.useradd

    def list_extend(iterable, length, obj = None):
        """Ensure that iterable is the specified length by extending with obj
        and return it as a list"""
        return list(itertools.islice(itertools.chain(iterable, itertools.repeat(obj)), length))

    def merge_files(file_list, exp_fields):
        """Read each passwd/group file in file_list, split each line and create
        a dictionary with the user/group names as keys and the split lines as
        values. If the user/group name already exists in the dictionary, then
        update any fields in the list with the values from the new list (if they
        are set)."""
        id_table = dict()
        for conf in file_list.split():
            try:
                with open(conf, "r") as f:
                    for line in f:
                        if line.startswith('#'):
                            continue
                        # Make sure there always are at least exp_fields
                        # elements in the field list. This allows for leaving
                        # out trailing colons in the files.
                        fields = list_extend(line.rstrip().split(":"), exp_fields)
                        if fields[0] not in id_table:
                            id_table[fields[0]] = fields
                        else:
                            id_table[fields[0]] = list(map(lambda x, y: x or y, fields, id_table[fields[0]]))
            except IOError as e:
                if e.errno == errno.ENOENT:
                    pass

        return id_table

    def handle_missing_id(id, type, pkg, files, var, value):
        # For backwards compatibility we accept "1" in addition to "error"
        error_dynamic = d.getVar('USERADD_ERROR_DYNAMIC')
        msg = 'Recipe %s, package %s: %sname "%s" does not have a static ID defined.' % (d.getVar('PN'), pkg, type, id)
        if files:
            msg += " Add %s to one of these files: %s" % (id, files)
        else:
            msg += " %s file(s) not found in BBPATH: %s" % (var, value)
        if error_dynamic == 'error' or error_dynamic == '1':
            raise NotImplementedError(msg)
        elif error_dynamic == 'warn':
            bb.warn(msg)
        elif error_dynamic == 'skip':
            raise bb.parse.SkipRecipe(msg)

    # Return a list of configuration files based on either the default
    # files/group or the contents of USERADD_GID_TABLES, resp.
    # files/passwd for USERADD_UID_TABLES.
    # Paths are resolved via BBPATH.
    def get_table_list(d, var, default):
        files = []
        bbpath = d.getVar('BBPATH')
        tables = d.getVar(var)
        if not tables:
            tables = default
        for conf_file in tables.split():
            files.append(bb.utils.which(bbpath, conf_file))
        return (' '.join(files), var, default)

    # We parse and rewrite the useradd components
    def rewrite_useradd(params, is_pkg):
        parser = oe.useradd.build_useradd_parser()

        newparams = []
        users = None
        for param in oe.useradd.split_commands(params):
            try:
                uaargs = parser.parse_args(oe.useradd.split_args(param))
            except Exception as e:
                bb.fatal("%s: Unable to parse arguments for USERADD_PARAM:%s '%s': %s" % (d.getVar('PN'), pkg, param, e))

            # Read all passwd files specified in USERADD_UID_TABLES or files/passwd
            # Use the standard passwd layout:
            #  username:password:user_id:group_id:comment:home_directory:login_shell
            #
            # If a field is left blank, the original value will be used.  The 'username'
            # field is required.
            #
            # Note: we ignore the password field, as including even the hashed password
            # in the useradd command may introduce a security hole.  It's assumed that
            # all new users get the default ('*' which prevents login) until the user is
            # specifically configured by the system admin.
            if not users:
                files, table_var, table_value = get_table_list(d, 'USERADD_UID_TABLES', 'files/passwd')
                users = merge_files(files, 7)

            type = 'system user' if uaargs.system else 'normal user'
            if uaargs.LOGIN not in users:
                handle_missing_id(uaargs.LOGIN, type, pkg, files, table_var, table_value)
                newparams.append(param)
                continue

            field = users[uaargs.LOGIN]

            if uaargs.uid and field[2] and (uaargs.uid != field[2]):
                bb.warn("%s: Changing username %s's uid from (%s) to (%s), verify configuration files!" % (d.getVar('PN'), uaargs.LOGIN, uaargs.uid, field[2]))
            uaargs.uid = field[2] or uaargs.uid

            # Determine the possible groupname
            # Unless the group name (or gid) is specified, we assume that the LOGIN is the groupname
            #
            # By default the system has creation of the matching groups enabled
            # So if the implicit username-group creation is on, then the implicit groupname (LOGIN)
            # is used, and we disable the user_group option.
            #
            if uaargs.gid:
                uaargs.groupname = uaargs.gid
            elif uaargs.user_group is not False:
                uaargs.groupname = uaargs.LOGIN
            else:
                uaargs.groupname = 'users'
            uaargs.groupid = field[3] or uaargs.groupname

            if uaargs.groupid and uaargs.gid != uaargs.groupid:
                newgroup = None
                if not uaargs.groupid.isdigit():
                    # We don't have a group number, so we have to add a name
                    bb.debug(1, "Adding group %s!" % uaargs.groupid)
                    newgroup = "%s %s" % (' --system' if uaargs.system else '', uaargs.groupid)
                elif uaargs.groupname and not uaargs.groupname.isdigit():
                    # We have a group name and a group number to assign it to
                    bb.debug(1, "Adding group %s (gid %s)!" % (uaargs.groupname, uaargs.groupid))
                    newgroup = "-g %s %s" % (uaargs.groupid, uaargs.groupname)
                else:
                    # We want to add a group, but we don't know it's name... so we can't add the group...
                    # We have to assume the group has previously been added or we'll fail on the adduser...
                    # Note: specifying the actual gid is very rare in OE, usually the group name is specified.
                    bb.warn("%s: Changing gid for login %s to %s, verify configuration files!" % (d.getVar('PN'), uaargs.LOGIN, uaargs.groupid))

                uaargs.gid = uaargs.groupid
                uaargs.user_group = None
                if newgroup and is_pkg:
                    groupadd = d.getVar("GROUPADD_PARAM:%s" % pkg)
                    if groupadd:
                        # Only add the group if not already specified
                        if not uaargs.groupname in groupadd:
                            d.setVar("GROUPADD_PARAM:%s" % pkg, "%s; %s" % (groupadd, newgroup))
                    else:
                        d.setVar("GROUPADD_PARAM:%s" % pkg, newgroup)

            uaargs.comment = "'%s'" % field[4] if field[4] else uaargs.comment
            uaargs.home_dir = field[5] or uaargs.home_dir
            uaargs.shell = field[6] or uaargs.shell

            # Should be an error if a specific option is set...
            if not uaargs.uid or not uaargs.uid.isdigit() or not uaargs.gid:
                 handle_missing_id(uaargs.LOGIN, type, pkg, files, table_var, table_value)

            # Reconstruct the args...
            newparam  = ['', ' --defaults'][uaargs.defaults]
            newparam += ['', ' --base-dir %s' % uaargs.base_dir][uaargs.base_dir != None]
            newparam += ['', ' --comment %s' % uaargs.comment][uaargs.comment != None]
            newparam += ['', ' --home-dir %s' % uaargs.home_dir][uaargs.home_dir != None]
            newparam += ['', ' --expiredate %s' % uaargs.expiredate][uaargs.expiredate != None]
            newparam += ['', ' --inactive %s' % uaargs.inactive][uaargs.inactive != None]
            newparam += ['', ' --gid %s' % uaargs.gid][uaargs.gid != None]
            newparam += ['', ' --groups %s' % uaargs.groups][uaargs.groups != None]
            newparam += ['', ' --skel %s' % uaargs.skel][uaargs.skel != None]
            newparam += ['', ' --key %s' % uaargs.key][uaargs.key != None]
            newparam += ['', ' --no-log-init'][uaargs.no_log_init]
            newparam += ['', ' --create-home'][uaargs.create_home is True]
            newparam += ['', ' --no-create-home'][uaargs.create_home is False]
            newparam += ['', ' --no-user-group'][uaargs.user_group is False]
            newparam += ['', ' --non-unique'][uaargs.non_unique]
            if uaargs.password != None:
                newparam += ['', ' --password %s' % uaargs.password][uaargs.password != None]
            newparam += ['', ' --root %s' % uaargs.root][uaargs.root != None]
            newparam += ['', ' --system'][uaargs.system]
            newparam += ['', ' --shell %s' % uaargs.shell][uaargs.shell != None]
            newparam += ['', ' --uid %s' % uaargs.uid][uaargs.uid != None]
            newparam += ['', ' --user-group'][uaargs.user_group is True]
            newparam += ' %s' % uaargs.LOGIN

            newparams.append(newparam)

        return ";".join(newparams).strip()

    # We parse and rewrite the groupadd components
    def rewrite_groupadd(params, is_pkg):
        parser = oe.useradd.build_groupadd_parser()

        newparams = []
        groups = None
        for param in oe.useradd.split_commands(params):
            try:
                # If we're processing multiple lines, we could have left over values here...
                gaargs = parser.parse_args(oe.useradd.split_args(param))
            except Exception as e:
                bb.fatal("%s: Unable to parse arguments for GROUPADD_PARAM:%s '%s': %s" % (d.getVar('PN'), pkg, param, e))

            # Read all group files specified in USERADD_GID_TABLES or files/group
            # Use the standard group layout:
            #  groupname:password:group_id:group_members
            #
            # If a field is left blank, the original value will be used. The 'groupname' field
            # is required.
            #
            # Note: similar to the passwd file, the 'password' filed is ignored
            # Note: group_members is ignored, group members must be configured with the GROUPMEMS_PARAM
            if not groups:
                files, table_var, table_value = get_table_list(d, 'USERADD_GID_TABLES', 'files/group')
                groups = merge_files(files, 4)

            type = 'system group' if gaargs.system else 'normal group'
            if gaargs.GROUP not in groups:
                handle_missing_id(gaargs.GROUP, type, pkg, files, table_var, table_value)
                newparams.append(param)
                continue

            field = groups[gaargs.GROUP]

            if field[2]:
                if gaargs.gid and (gaargs.gid != field[2]):
                    bb.warn("%s: Changing groupname %s's gid from (%s) to (%s), verify configuration files!" % (d.getVar('PN'), gaargs.GROUP, gaargs.gid, field[2]))
                gaargs.gid = field[2]

            if not gaargs.gid or not gaargs.gid.isdigit():
                handle_missing_id(gaargs.GROUP, type, pkg, files, table_var, table_value)

            # Reconstruct the args...
            newparam  = ['', ' --force'][gaargs.force]
            newparam += ['', ' --gid %s' % gaargs.gid][gaargs.gid != None]
            newparam += ['', ' --key %s' % gaargs.key][gaargs.key != None]
            newparam += ['', ' --non-unique'][gaargs.non_unique]
            if gaargs.password != None:
                newparam += ['', ' --password %s' % gaargs.password][gaargs.password != None]
            newparam += ['', ' --root %s' % gaargs.root][gaargs.root != None]
            newparam += ['', ' --system'][gaargs.system]
            newparam += ' %s' % gaargs.GROUP

            newparams.append(newparam)

        return ";".join(newparams).strip()

    # The parsing of the current recipe depends on the content of
    # the files listed in USERADD_UID/GID_TABLES. We need to tell bitbake
    # about that explicitly to trigger re-parsing and thus re-execution of
    # this code when the files change.
    bbpath = d.getVar('BBPATH')
    for varname, default in (('USERADD_UID_TABLES', 'files/passwd'),
                             ('USERADD_GID_TABLES', 'files/group')):
        tables = d.getVar(varname)
        if not tables:
            tables = default
        for conf_file in tables.split():
            bb.parse.mark_dependency(d, bb.utils.which(bbpath, conf_file))

    # Load and process the users and groups, rewriting the adduser/addgroup params
    useradd_packages = d.getVar('USERADD_PACKAGES') or ""

    for pkg in useradd_packages.split():
        # Groupmems doesn't have anything we might want to change, so simply validating
        # is a bit of a waste -- only process useradd/groupadd
        useradd_param = d.getVar('USERADD_PARAM:%s' % pkg)
        if useradd_param:
            #bb.warn("Before: 'USERADD_PARAM:%s' - '%s'" % (pkg, useradd_param))
            d.setVar('USERADD_PARAM:%s' % pkg, rewrite_useradd(useradd_param, True))
            #bb.warn("After:  'USERADD_PARAM:%s' - '%s'" % (pkg, d.getVar('USERADD_PARAM:%s' % pkg)))

        groupadd_param = d.getVar('GROUPADD_PARAM:%s' % pkg)
        if groupadd_param:
            #bb.warn("Before: 'GROUPADD_PARAM:%s' - '%s'" % (pkg, groupadd_param))
            d.setVar('GROUPADD_PARAM:%s' % pkg, rewrite_groupadd(groupadd_param, True))
            #bb.warn("After:  'GROUPADD_PARAM:%s' - '%s'" % (pkg, d.getVar('GROUPADD_PARAM:%s' % pkg)))

    # Load and process extra users and groups, rewriting only adduser/addgroup params
    pkg = d.getVar('PN')
    extrausers = d.getVar('EXTRA_USERS_PARAMS') or ""

    #bb.warn("Before:  'EXTRA_USERS_PARAMS' - '%s'" % (d.getVar('EXTRA_USERS_PARAMS')))
    new_extrausers = []
    for cmd in oe.useradd.split_commands(extrausers):
        if re.match('''useradd (.*)''', cmd):
            useradd_param = re.match('''useradd (.*)''', cmd).group(1)
            useradd_param = rewrite_useradd(useradd_param, False)
            cmd = 'useradd %s' % useradd_param
        elif re.match('''groupadd (.*)''', cmd):
            groupadd_param = re.match('''groupadd (.*)''', cmd).group(1)
            groupadd_param = rewrite_groupadd(groupadd_param, False)
            cmd = 'groupadd %s' % groupadd_param

        new_extrausers.append(cmd)

    new_extrausers.append('')
    d.setVar('EXTRA_USERS_PARAMS', ';'.join(new_extrausers))
    #bb.warn("After:  'EXTRA_USERS_PARAMS' - '%s'" % (d.getVar('EXTRA_USERS_PARAMS')))


python __anonymous() {
    if not bb.data.inherits_class('nativesdk', d) \
        and not bb.data.inherits_class('native', d):
        try:
            update_useradd_static_config(d)
        except NotImplementedError as f:
            bb.debug(1, "Skipping recipe %s: %s" % (d.getVar('PN'), f))
            raise bb.parse.SkipRecipe(f)
}
