def set_selections(path=None, selection=None, clear=False, saltenv="base"):
    """
    Change package state in the dpkg database.

    The state can be any one of, documented in ``dpkg(1)``:

    - install
    - hold
    - deinstall
    - purge

    This command is commonly used to mark specific packages to be held from
    being upgraded, that is, to be kept at a certain version. When a state is
    changed to anything but being held, then it is typically followed by
    ``apt-get -u dselect-upgrade``.

    Note: Be careful with the ``clear`` argument, since it will start
    with setting all packages to deinstall state.

    Returns a dict of dicts containing the package names, and the new and old
    versions:

    .. code-block:: python

        {'<host>':
            {'<package>': {'new': '<new-state>',
                           'old': '<old-state>'}
            },
            ...
        }

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.set_selections selection='{"install": ["netcat"]}'
        salt '*' pkg.set_selections selection='{"hold": ["openssh-server", "openssh-client"]}'
        salt '*' pkg.set_selections salt://path/to/file
        salt '*' pkg.set_selections salt://path/to/file clear=True
    """
    ret = {}
    if not path and not selection:
        return ret
    if path and selection:
        err = (
            "The 'selection' and 'path' arguments to "
            "pkg.set_selections are mutually exclusive, and cannot be "
            "specified together"
        )
        raise SaltInvocationError(err)

    if isinstance(selection, str):
        try:
            selection = salt.utils.yaml.safe_load(selection)
        except (
            salt.utils.yaml.parser.ParserError,
            salt.utils.yaml.scanner.ScannerError,
        ) as exc:
            raise SaltInvocationError("Improperly-formatted selection: {}".format(exc))

    if path:
        path = __salt__["cp.cache_file"](path, saltenv)
        with salt.utils.files.fopen(path, "r") as ifile:
            content = [salt.utils.stringutils.to_unicode(x) for x in ifile.readlines()]
        selection = _parse_selections(content)

    if selection:
        valid_states = ("install", "hold", "deinstall", "purge")
        bad_states = [x for x in selection if x not in valid_states]
        if bad_states:
            raise SaltInvocationError(
                "Invalid state(s): {}".format(", ".join(bad_states))
            )

        if clear:
            cmd = ["dpkg", "--clear-selections"]
            if not __opts__["test"]:
                result = _call_apt(cmd, scope=False)
                if result["retcode"] != 0:
                    err = "Running dpkg --clear-selections failed: {}".format(
                        result["stderr"]
                    )
                    log.error(err)
                    raise CommandExecutionError(err)

        sel_revmap = {}
        for _state, _pkgs in get_selections().items():
            sel_revmap.update({_pkg: _state for _pkg in _pkgs})

        for _state, _pkgs in selection.items():
            for _pkg in _pkgs:
                if _state == sel_revmap.get(_pkg):
                    continue
                cmd = ["dpkg", "--set-selections"]
                cmd_in = "{} {}".format(_pkg, _state)
                if not __opts__["test"]:
                    result = _call_apt(cmd, scope=False, stdin=cmd_in)
                    if result["retcode"] != 0:
                        log.error("failed to set state %s for package %s", _state, _pkg)
                    else:
                        ret[_pkg] = {"old": sel_revmap.get(_pkg), "new": _state}
    return ret