2020-11-25 22:36:03 +00:00
|
|
|
#!/usr/bin/python3
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# key-mapper - GUI for device specific keyboard mappings
|
2021-01-02 23:08:33 +00:00
|
|
|
# Copyright (C) 2021 sezanzeb <proxima@hip70890b.de>
|
2020-11-25 22:36:03 +00:00
|
|
|
#
|
|
|
|
# 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
|
2020-12-05 17:49:52 +00:00
|
|
|
import glob
|
2020-11-25 22:36:03 +00:00
|
|
|
import getpass
|
2020-12-05 17:49:52 +00:00
|
|
|
import subprocess
|
2020-12-04 16:16:39 +00:00
|
|
|
import os
|
2020-11-25 22:36:03 +00:00
|
|
|
|
|
|
|
from keymapper.logger import logger
|
2020-12-01 10:01:11 +00:00
|
|
|
from keymapper.paths import USER
|
2020-12-26 22:19:33 +00:00
|
|
|
from keymapper.daemon import is_service_running
|
2020-11-25 22:36:03 +00:00
|
|
|
|
|
|
|
|
2020-12-05 16:56:21 +00:00
|
|
|
def check_group(group):
|
2020-12-05 17:49:52 +00:00
|
|
|
"""Check if the required group is active and log if not."""
|
2020-12-05 16:56:21 +00:00
|
|
|
try:
|
2020-12-05 17:49:52 +00:00
|
|
|
in_group = USER in grp.getgrnam(group).gr_mem
|
2020-12-05 16:56:21 +00:00
|
|
|
except KeyError:
|
2020-12-05 17:49:52 +00:00
|
|
|
# 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 = (
|
2020-12-27 14:38:08 +00:00
|
|
|
'Some devices may not be accessible without being in the '
|
2020-12-24 00:26:34 +00:00
|
|
|
f'"{group}" user group.'
|
2020-12-05 17:49:52 +00:00
|
|
|
)
|
|
|
|
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 '
|
2020-12-27 14:38:08 +00:00
|
|
|
'using it. Some devices may not be accessible. Please log out and '
|
2020-12-05 22:40:02 +00:00
|
|
|
'back in or restart'
|
2020-12-05 17:49:52 +00:00
|
|
|
)
|
|
|
|
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):
|
2020-12-05 22:40:02 +00:00
|
|
|
msg = (
|
2020-12-05 17:49:52 +00:00
|
|
|
'Rights to write to /dev/uinput are missing, keycodes cannot '
|
2020-12-24 00:26:34 +00:00
|
|
|
'be injected.'
|
2020-12-05 17:49:52 +00:00
|
|
|
)
|
2020-12-05 22:40:02 +00:00
|
|
|
logger.error(msg)
|
|
|
|
return msg
|
2020-12-05 17:49:52 +00:00
|
|
|
|
|
|
|
return None
|
2020-12-05 16:56:21 +00:00
|
|
|
|
|
|
|
|
2020-11-25 22:36:03 +00:00
|
|
|
def can_read_devices():
|
2020-12-06 11:40:58 +00:00
|
|
|
"""Get a list of problems before key-mapper can be used properly."""
|
2020-12-05 17:49:52 +00:00
|
|
|
if getpass.getuser() == 'root':
|
2020-12-06 11:40:58 +00:00
|
|
|
return []
|
2020-12-05 17:49:52 +00:00
|
|
|
|
|
|
|
input_check = check_group('input')
|
|
|
|
plugdev_check = check_group('plugdev')
|
2020-11-25 22:36:03 +00:00
|
|
|
|
2020-12-04 16:16:39 +00:00
|
|
|
# ubuntu. funnily, individual devices in /dev/input/ have write permitted.
|
2020-12-26 22:19:33 +00:00
|
|
|
if not is_service_running():
|
|
|
|
can_write = check_injection_rights()
|
|
|
|
else:
|
|
|
|
can_write = None
|
2020-12-04 16:16:39 +00:00
|
|
|
|
2020-12-06 11:40:58 +00:00
|
|
|
ret = [
|
|
|
|
check for check
|
|
|
|
in [can_write, input_check, plugdev_check]
|
|
|
|
if check is not None
|
|
|
|
]
|
2020-11-25 22:36:03 +00:00
|
|
|
|
2020-12-05 17:49:52 +00:00
|
|
|
return ret
|