xiwrap

slightly higher-level container setup utility
git clone https://git.ce9e.org/xiwrap.git

commit
fbdbeb1970b083fa58ec1479389d3d4dcfa04e0b
parent
317b6ad68d1d91c027bdefb6af561cc536d6bf27
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-06-20 14:07
support access to dbus system bus

Diffstat

M includes/gui 2 +-
M includes/portal 4 ++--
M xiwrap.py 97 ++++++++++++++++++++++++++++++++++++++++++++-----------------

3 files changed, 73 insertions, 30 deletions


diff --git a/includes/gui b/includes/gui

@@ -17,7 +17,7 @@ ro-bind-try $XDG_DATA_HOME/themes
   17    17 bind-try $XDG_CACHE_HOME/fontconfig
   18    18 bind-try $XDG_CACHE_HOME/thumbnails
   19    19 
   20    -1 dbus-talk org.a11y.Bus
   -1    20 dbus-session-talk org.a11y.Bus
   21    21 
   22    22 setenv GTK_USE_PORTAL 1
   23    23 include portal

diff --git a/includes/portal b/includes/portal

@@ -1,2 +1,2 @@
    1    -1 dbus-talk org.freedesktop.portal.Desktop
    2    -1 dbus-talk org.freedesktop.portal.Documents
   -1     1 dbus-session-talk org.freedesktop.portal.Desktop
   -1     2 dbus-session-talk org.freedesktop.portal.Documents

diff --git a/xiwrap.py b/xiwrap.py

@@ -28,11 +28,12 @@ The following options are available:
   28    28 --tmpfs DEST            Mount new tmpfs on DEST.
   29    29 --mqueue DEST           Mount new mqueue on DEST.
   30    30 --dir DEST              Create a directory at DEST.
   31    -1 --dbus-see NAME         Allow to see NAME on the session bus.
   32    -1 --dbus-talk NAME        Allow to talk to NAME on the session bus.
   33    -1 --dbus-own NAME         Allow to own NAME on the session bus.
   34    -1 --dbus-call NAME=RULE   Set a rule for method calls on NAME.
   35    -1 --dbus-broadcast NAME=RULE
   -1    31 --dbus-session-see NAME, --dbus-session-talk NAME, --dbus-session-own NAME,
   -1    32 --dbus-session-call NAME=RULE, --dbus-session-broadcast NAME=RULE,
   -1    33 --dbus-system-see NAME, --dbus-system-talk NAME, --dbus-system-own NAME,
   -1    34 --dbus-system-call NAME=RULE, --dbus-system-broadcast NAME=RULE
   -1    35                         Allow filtered access to dbus. See `man xdg-dbus-proxy`
   -1    36                         for detauls.
   36    37                         Set a rule for broadcast signals from NAME.
   37    38 --include FILE          Load additional options from FILE. FILE can be an
   38    39                         absolute path or relative to the current directory,
@@ -42,8 +43,10 @@ The following options are available:
   42    43                         starting with # are ignored.
   43    44 """
   44    45 
   45    -1 DBUS_SRC = f'{os.environ["XDG_RUNTIME_DIR"]}/dbus-proxy-{os.getpid()}'
   46    -1 DBUS_DEST = '$XDG_RUNTIME_DIR/bus'
   -1    46 DBUS_SESSION_SRC = f'{os.environ["XDG_RUNTIME_DIR"]}/dbus-session-proxy-{os.getpid()}'
   -1    47 DBUS_SESSION_DEST = '$XDG_RUNTIME_DIR/bus'
   -1    48 DBUS_SYSTEM_SRC = f'{os.environ["XDG_RUNTIME_DIR"]}/dbus-system-proxy-{os.getpid()}'
   -1    49 DBUS_SYSTEM_DEST = '/var/run/dbus/system_bus_socket'
   47    50 
   48    51 
   49    52 class RuleError(ValueError):
@@ -88,7 +91,8 @@ class RuleSet:
   88    91     def __init__(self):
   89    92         self.env = {}
   90    93         self.paths = {}
   91    -1         self.dbus = {}
   -1    94         self.dbus_session = {}
   -1    95         self.dbus_system = {}
   92    96         self.share = {}
   93    97         self.sync_fds = None
   94    98         self.debug = False
@@ -125,11 +129,9 @@ class RuleSet:
  125   129         else:
  126   130             raise RuleError(key, args)
  127   131 
  128    -1     def ensure_dbus(self):
  129    -1         if self.sync_fds is not None:
  130    -1             return
  131    -1         self.sync_fds = os.pipe2(0)
  132    -1         self.push_rule('ro-bind', [DBUS_SRC, DBUS_DEST], cwd=None)
   -1   132     def ensure_sync_fds(self):
   -1   133         if self.sync_fds is None:
   -1   134             self.sync_fds = os.pipe2(0)
  133   135 
  134   136     def push_rule(self, key, args, *, cwd):
  135   137         if key == 'include':
@@ -142,12 +144,29 @@ class RuleSet:
  142   144                 raise RuleError(key, args)
  143   145             self.share[key] = True
  144   146         elif key in [
  145    -1             'dbus-see', 'dbus-talk', 'dbus-own', 'dbus-call', 'dbus-broadcast'
   -1   147             'dbus-session-see',
   -1   148             'dbus-session-talk',
   -1   149             'dbus-session-own',
   -1   150             'dbus-session-call',
   -1   151             'dbus-session-broadcast',
   -1   152         ]:
   -1   153             if len(args) != 1:
   -1   154                 raise RuleError(key, args)
   -1   155             self.ensure_sync_fds()
   -1   156             self.push_rule('ro-bind', [DBUS_SESSION_SRC, DBUS_SESSION_DEST], cwd=None)
   -1   157             self.dbus_session[args[0]] = key.removeprefix('dbus-session-')
   -1   158         elif key in [
   -1   159             'dbus-system-see',
   -1   160             'dbus-system-talk',
   -1   161             'dbus-system-own',
   -1   162             'dbus-system-call',
   -1   163             'dbus-system-broadcast',
  146   164         ]:
  147   165             if len(args) != 1:
  148   166                 raise RuleError(key, args)
  149    -1             self.ensure_dbus()
  150    -1             self.dbus[args[0]] = key.removeprefix('dbus-')
   -1   167             self.ensure_sync_fds()
   -1   168             self.push_rule('ro-bind', [DBUS_SYSTEM_SRC, DBUS_SYSTEM_DEST], cwd=None)
   -1   169             self.dbus_system[args[0]] = key.removeprefix('dbus-system-')
  151   170         elif key == 'setenv':
  152   171             var, value = self.parse_env(key, args)
  153   172             self.env[var] = value
@@ -209,7 +228,8 @@ class RuleSet:
  209   228         ]
  210   229         if self.sync_fds is not None:
  211   230             cmd += ['--sync-fd', str(self.sync_fds[0])]
  212    -1             bus = expandvars(DBUS_DEST, self.env)
   -1   231         if self.dbus_session:
   -1   232             bus = expandvars(DBUS_SESSION_DEST, self.env)
  213   233             cmd += ['--setenv', 'DBUS_SESSION_BUS_ADDRESS', f'unix:path={bus}']
  214   234         for key in ['share-ipc', 'share-pid', 'share-net']:
  215   235             if not self.share.get(key):
@@ -227,17 +247,34 @@ class RuleSet:
  227   247                 cmd += [f'--{typ}', expandvars(src, os.environ), target]
  228   248         return cmd + bwrap_args
  229   249 
  230    -1     def build_dbus(self):
  231    -1         if self.sync_fds is None:
   -1   250     def build_dbus_session(self):
   -1   251         if not self.dbus_session:
  232   252             return None
  233   253         cmd = [
  234   254             'xdg-dbus-proxy',
  235   255             f'--fd={self.sync_fds[1]}',
  236   256             os.getenv('DBUS_SESSION_BUS_ADDRESS'),
  237    -1             DBUS_SRC,
   -1   257             DBUS_SESSION_SRC,
   -1   258             '--filter',
   -1   259         ]
   -1   260         for value, typ in sorted(self.dbus_session.items()):
   -1   261             cmd.append(f'--{typ}={value}')
   -1   262         return cmd
   -1   263 
   -1   264     def build_dbus_system(self):
   -1   265         if not self.dbus_system:
   -1   266             return None
   -1   267         cmd = [
   -1   268             'xdg-dbus-proxy',
   -1   269             f'--fd={self.sync_fds[1]}',
   -1   270             os.getenv(
   -1   271                 'DBUS_SYSTEM_BUS_ADDRESS',
   -1   272                 'unix:path=/var/run/dbus/system_bus_socket',
   -1   273             ),
   -1   274             DBUS_SYSTEM_SRC,
  238   275             '--filter',
  239   276         ]
  240    -1         for value, typ in sorted(self.dbus.items()):
   -1   277         for value, typ in sorted(self.dbus_system.items()):
  241   278             cmd.append(f'--{typ}={value}')
  242   279         return cmd
  243   280 
@@ -253,15 +290,21 @@ if __name__ == '__main__':
  253   290         print(USAGE)
  254   291         sys.exit(1)
  255   292     cmd = rules.build(tail)
  256    -1     dbus_cmd = rules.build_dbus()
   -1   293     dbus_system_cmd = rules.build_dbus_system()
   -1   294     dbus_session_cmd = rules.build_dbus_session()
  257   295     if rules.usage:
  258   296         print(USAGE)
  259   297     elif rules.debug:
  260   298         print(' '.join(cmd))
  261    -1         if dbus_cmd:
  262    -1             print(' '.join(dbus_cmd))
   -1   299         if dbus_system_cmd:
   -1   300             print(' '.join(dbus_system_cmd))
   -1   301         if dbus_session_cmd:
   -1   302             print(' '.join(dbus_session_cmd))
  263   303     else:
  264    -1         if dbus_cmd:
  265    -1             subprocess.Popen(dbus_cmd, pass_fds=[rules.sync_fds[1]])
  266    -1             os.read(rules.sync_fds[0], 1)
   -1   304         if dbus_system_cmd:
   -1   305             subprocess.Popen(dbus_system_cmd, pass_fds=[rules.sync_fds[1]])
   -1   306             os.read(rules.sync_fds[0], 8)
   -1   307         if dbus_session_cmd:
   -1   308             subprocess.Popen(dbus_session_cmd, pass_fds=[rules.sync_fds[1]])
   -1   309             os.read(rules.sync_fds[0], 8)
  267   310         os.execvp('/usr/bin/bwrap', cmd)