#
# 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 = "%s - %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)
}
