738548a8e4
With a VMExecGUI variant that waits for a session. See QubesOS/qubes-issues#4850.
60 lines
1.4 KiB
Python
60 lines
1.4 KiB
Python
import sys
|
|
import os
|
|
import re
|
|
|
|
|
|
class DecodeError(ValueError):
|
|
pass
|
|
|
|
|
|
ESCAPE_RE = re.compile(br'--|-([A-F0-9]{2})')
|
|
|
|
|
|
def decode_part(part):
|
|
if not re.match(r'^[a-zA-Z0-9._-]*$', part):
|
|
raise DecodeError('illegal characters found')
|
|
|
|
part = part.encode('ascii')
|
|
|
|
# Check if no '-' remains outside of legal escape sequences.
|
|
if b'-' in ESCAPE_RE.sub(b'', part):
|
|
raise DecodeError("'-' can be used only in '-HH' or '--'")
|
|
|
|
def convert(m):
|
|
if m.group(0) == b'--':
|
|
return b'-'
|
|
num = int(m.group(1), 16)
|
|
return bytes([num])
|
|
|
|
return ESCAPE_RE.sub(convert, part)
|
|
|
|
|
|
def decode(arg):
|
|
'''
|
|
Decode the argument for executing. The format is as follows:
|
|
- individual parts are split by '+'
|
|
- bytes are escaped as '-HH' (where HH is hex code, capital letters only)
|
|
- literal '-' is encoded as '--'
|
|
- otherwise, only [a-zA-Z0-9._] are allowed
|
|
|
|
:param arg: argument, as a string
|
|
:returns: list of exec arguments (each as bytes)
|
|
'''
|
|
return [decode_part(part) for part in arg.split('+')]
|
|
|
|
|
|
def main(argv=sys.argv):
|
|
if len(argv) != 2:
|
|
print('This service requires exactly one argument', file=sys.stderr)
|
|
exit(1)
|
|
try:
|
|
command = decode(argv[1])
|
|
except DecodeError as e:
|
|
print('Decode error: {}'.format(e), file=sys.stderr)
|
|
exit(1)
|
|
os.execvp(command[0], command)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|