qubesd_query.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #!/usr/bin/env python3.6
  2. import argparse
  3. import asyncio
  4. import signal
  5. import sys
  6. QUBESD_SOCK = '/var/run/qubesd.sock'
  7. try:
  8. asyncio.ensure_future
  9. except AttributeError:
  10. asyncio.ensure_future = asyncio.async
  11. parser = argparse.ArgumentParser(
  12. description='low-level qubesd interrogation tool')
  13. parser.add_argument('--connect', '-c', metavar='PATH',
  14. dest='socket',
  15. default=QUBESD_SOCK,
  16. help='path to qubesd UNIX socket (default: %(default)s)')
  17. parser.add_argument('--empty', '-e',
  18. dest='payload',
  19. action='store_false', default=True,
  20. help='do not read from stdin and send empty payload')
  21. parser.add_argument('src', metavar='SRC',
  22. help='source qube')
  23. parser.add_argument('method', metavar='METHOD',
  24. help='method name')
  25. parser.add_argument('dest', metavar='DEST',
  26. help='destination qube')
  27. parser.add_argument('arg', metavar='ARGUMENT',
  28. nargs='?', default='',
  29. help='argument to method')
  30. def sighandler(loop, signame, coro):
  31. print('caught {}, exiting'.format(signame))
  32. coro.cancel()
  33. loop.stop()
  34. @asyncio.coroutine
  35. def qubesd_client(socket, payload, *args):
  36. try:
  37. reader, writer = yield from asyncio.open_unix_connection(socket)
  38. except asyncio.CancelledError:
  39. return
  40. for arg in args:
  41. writer.write(arg.encode('ascii'))
  42. writer.write(b'\0')
  43. writer.write(payload)
  44. writer.write_eof()
  45. try:
  46. data = yield from reader.read()
  47. sys.stdout.buffer.write(data) # pylint: disable=no-member
  48. except asyncio.CancelledError:
  49. return
  50. finally:
  51. writer.close()
  52. def main(args=None):
  53. args = parser.parse_args(args)
  54. loop = asyncio.get_event_loop()
  55. # pylint: disable=no-member
  56. payload = sys.stdin.buffer.read() if args.payload else b''
  57. # pylint: enable=no-member
  58. coro = asyncio.ensure_future(qubesd_client(args.socket, payload,
  59. args.src, args.method, args.dest, args.arg))
  60. for signame in ('SIGINT', 'SIGTERM'):
  61. loop.add_signal_handler(getattr(signal, signame),
  62. sighandler, loop, signame, coro)
  63. try:
  64. loop.run_until_complete(coro)
  65. finally:
  66. loop.close()
  67. if __name__ == '__main__':
  68. main()