Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Execute shell commands #5

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 57 additions & 9 deletions evdevremapkeys.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import functools
from pathlib import Path
import signal
import os
import pwd


import daemon
Expand All @@ -37,14 +39,27 @@


@asyncio.coroutine
def handle_events(input, output, remappings):
def handle_events(input, output, remappings, user, commands, passunmapped):
while True:
events = yield from input.async_read() # noqa
for event in events:
if event.type == ecodes.EV_KEY and \
mapped = False

if remappings is not None and \
event.type == ecodes.EV_KEY and \
event.code in remappings:
mapped = True
remap_event(output, event, remappings)
else:

if commands is not None and \
event.type == ecodes.EV_KEY and \
event.code in commands:
mapped = True
if event.value == evdev.events.KeyEvent.key_down or\
event.value == evdev.events.KeyEvent.key_hold:
execute_command(event, user, commands)

if passunmapped and not mapped:
output.write_event(event)
output.syn()

Expand All @@ -56,6 +71,20 @@ def remap_event(output, event, remappings):
output.syn()


def execute_command(event, user, commands):
for command in commands[event.code]:
newpid = os.fork()
if newpid == 0:
if user is not None:
gid = pwd.getpwnam(user).pw_gid
uid = pwd.getpwnam(user).pw_uid
#group id needs to be set before the user id,
#otherwise the permissions are dropped too soon
os.setgid(gid)
os.setuid(uid)
os.execl('/bin/sh', '/bin/sh', '-c', command)


def load_config(config_override):
conf_path = None
if config_override is None:
Expand All @@ -73,15 +102,27 @@ def load_config(config_override):
with open(conf_path.as_posix(), 'r') as fd:
config = yaml.safe_load(fd)
for device in config['devices']:
device['remappings'] = resolve_ecodes(device['remappings'])
if 'remappings' in device:
device['remappings'] = resolve_ecodes_remappings(device['remappings'])
if 'commands' in device:
device['commands'] = resolve_ecodes_commands(device['commands'])

return config


def resolve_ecodes(by_name):
def resolve_ecodes_remappings(by_name):
by_id = {}
for key, values in by_name.items():
by_id[ecodes.ecodes[key]] = [ecodes.ecodes[value] for value in values]
if by_name is not None:
for key, values in by_name.items():
by_id[ecodes.ecodes[key]] = [ecodes.ecodes[value] for value in values]
return by_id


def resolve_ecodes_commands(by_name):
by_id = {}
if by_name is not None:
for key, values in by_name.items():
by_id[ecodes.ecodes[key]] = values;
return by_id


Expand Down Expand Up @@ -115,14 +156,18 @@ def register_device(device):
# EV_SYN is automatically added to uinput devices
del caps[ecodes.EV_SYN]

remappings = device['remappings']
remappings = device.get('remappings', None);
user = device.get('command_user', None);
commands = device.get('commands', None);
passunmapped = device.get('pass_unmapped', True);

extended = set(caps[ecodes.EV_KEY])
[extended.update(keys) for keys in remappings.values()]
caps[ecodes.EV_KEY] = list(extended)

output = UInput(caps, name=device['output_name'])

asyncio.ensure_future(handle_events(input, output, remappings))
asyncio.ensure_future(handle_events(input, output, remappings, user, commands, passunmapped))


@asyncio.coroutine
Expand All @@ -144,6 +189,9 @@ def run_loop(args):
functools.partial(asyncio.ensure_future,
shutdown(loop)))

#prevent defunct processes
signal.signal(signal.SIGCHLD, signal.SIG_IGN)

try:
loop.run_forever()
except KeyboardInterrupt:
Expand Down