You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
input-remapper/keymapper/dev/permissions.py

118 lines
3.5 KiB
Python

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# key-mapper - GUI for device specific keyboard mappings
# Copyright (C) 2020 sezanzeb <proxima@hip70890b.de>
#
# This file is part of key-mapper.
#
# key-mapper is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# key-mapper is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with key-mapper. If not, see <https://www.gnu.org/licenses/>.
"""To check if access to devices in /dev is possible."""
import grp
import glob
import getpass
import subprocess
import os
from keymapper.logger import logger
from keymapper.paths import USER
def check_group(group):
"""Check if the required group is active and log if not."""
# TODO test
try:
in_group = USER in grp.getgrnam(group).gr_mem
except KeyError:
# group doesn't exist. Ignore
return None
# check if files exist with that group in /dev. Even if plugdev
# exists, that doesn't mean that it is needed.
used_groups = [os.stat(path).st_gid for path in glob.glob('/dev/input/*')]
if grp.getgrnam(group).gr_gid not in used_groups:
return None
if not in_group:
msg = (
'Some devices may not be visible without being in the '
f'"{group}" user group. Try `sudo usermod -a -G {group} {USER}` '
'and log out and back in or restart.'
)
logger.warning(msg)
return msg
try:
groups = subprocess.check_output('groups').decode().split()
group_active = group in groups
except FileNotFoundError:
# groups command missing. Idk if any distro doesn't have it
# but if so, cover the case.
return None
if in_group and not group_active:
msg = (
f'You are in the "{group}" group, but your session is not yet '
'using it. Some devices may not be visible. Please log out and '
'back in or restart'
)
logger.warning(msg)
return msg
return None
def check_injection_rights():
"""Check if the user may write into /dev/uinput."""
if not os.access('/dev/uinput', os.W_OK):
msg = (
'Rights to write to /dev/uinput are missing, keycodes cannot '
f'be injected. Try `sudo setfacl -m u:{USER}:rw- /dev/uinput`'
)
logger.error(msg)
return msg
return None
def can_read_devices():
"""Help the user to setup correct permissions."""
if getpass.getuser() == 'root':
return None
input_check = check_group('input')
plugdev_check = check_group('plugdev')
# ubuntu. funnily, individual devices in /dev/input/ have write permitted.
can_write = check_injection_rights()
ret = []
if can_write is not None:
ret.append(can_write)
if input_check is not None:
ret.append(input_check)
if plugdev_check is not None:
ret.append(plugdev_check)
if len(ret) > 0:
logger.info(
'You can also use `sudo key-mapper-service --setup-permissions` '
'as a shortcut for mentioned commands.'
)
return ret