6666 Horizontal ,
6767 Vertical ,
6868 VerticalGroup ,
69- HorizontalGroup ,
7069)
7170
7271from textual .reactive import reactive
@@ -295,49 +294,6 @@ def render_keybinding(inp_str: str) -> str:
295294 return "+" .join (key_tokens )
296295
297296
298- class RootUserBusModal (ModalScreen [bool ]):
299- """
300- Present a simple screen to inform the user that they
301- are about to access the `root --user` service bus,
302- which usually leads to a crash.
303-
304- Returns their selection.
305- """
306-
307- BINDINGS = [
308- Binding ("escape" , "close" , "Close" , show = True ),
309- ]
310- AUTO_FOCUS = "#no"
311-
312- def __init__ (
313- self ,
314- ** kwargs ,
315- ):
316- super ().__init__ (** kwargs )
317-
318- def compose (self ) -> ComposeResult :
319- with VerticalGroup ():
320- yield Markdown (
321- "# About to access **root --user** bus\n "
322- + "Usually the `root` user does _not_ have a dedicated `--user` bus. "
323- + "The application will crash if you try to connect to a non-existing bus. "
324- + "Are you sure you want to connect to it?\n \n "
325- + "You can update the settings to auto-accept this question if this is what you want."
326- )
327- with HorizontalGroup ():
328- yield Button ("No" , id = "no" , variant = "primary" )
329- yield Button ("Yes" , id = "yes" , variant = "warning" )
330- yield Footer ()
331-
332- def action_close (self ) -> None :
333- self .dismiss (False )
334-
335- def on_button_pressed (self , event : Button .Pressed ) -> None :
336- if event .button .id == "no" :
337- self .dismiss (False )
338- self .dismiss (True )
339-
340-
341297class SystemctlActionScreen (ModalScreen [Optional [str ]]):
342298 """
343299 Present a screen with the configured systemctl actions.
@@ -923,15 +879,6 @@ class Settings(BaseSettings):
923879 Note: The output is not trimmed when a pager or editor is opened!""" ),
924880 )
925881
926- auto_accept_connection_to_root_user_bus : bool = Field (
927- default = False ,
928- description = dedent ("""\
929- By default, the user is asked if they actually want to connect
930- to the `root --user` bus, as this usually crashes the running program.
931- If this option is `True`, the question is skipped.
932- """ ),
933- )
934-
935882 # https://github.com/tinted-theming/home?tab=readme-ov-file
936883 @classmethod
937884 def settings_customise_sources (
@@ -1818,20 +1765,25 @@ def compose(self) -> ComposeResult:
18181765 )
18191766
18201767
1821- # FUTURE: Maybe call it 'allowed' mode?
18221768def derive_startup_mode (startup_mode : StartupMode ) -> str :
1823- if is_root ():
1824- # if user == `root` then only system is allowed
1825- return "system"
1769+ mode : str
18261770 if startup_mode == StartupMode ("auto" ):
18271771 fallback : StartupMode = StartupMode ("user" )
18281772 fp = get_isd_cached_state_json_file_path ()
18291773 if fp .exists ():
1830- return json .loads (fp .read_text ()).get ("mode" , fallback )
1774+ mode = json .loads (fp .read_text ()).get ("mode" , fallback )
18311775 else :
1832- return fallback
1776+ mode = fallback
18331777 else :
1834- return startup_mode
1778+ mode = startup_mode
1779+ if mode == "user" and is_root ():
1780+ if systemctl_is_system_running (mode = "user" ).returncode == 0 :
1781+ return "user"
1782+ else :
1783+ # If it is not possible to connect to the `root` users `--user` bus,
1784+ # fallback to system
1785+ return "system"
1786+ return mode
18351787
18361788
18371789def cached_search_term () -> str :
@@ -1841,6 +1793,14 @@ def cached_search_term() -> str:
18411793 return ""
18421794
18431795
1796+ def systemctl_is_system_running (* , mode : str ) -> subprocess .CompletedProcess [str ]:
1797+ return subprocess .run (
1798+ systemctl_args_builder ("is-system-running" , mode = mode , units = []),
1799+ capture_output = True ,
1800+ text = True ,
1801+ )
1802+
1803+
18441804# class SettingsError(ModalScreen):
18451805# def __init__(
18461806# self, settings: Settings, exception: Exception, *args, **kwargs
@@ -2183,20 +2143,7 @@ def action_copy_unit_path(self) -> None:
21832143 self .app .copy_to_clipboard (path )
21842144 self .notify (f"Copied '{ path } ' to the clipboard." )
21852145
2186- async def wants_root_user_bus (self ) -> bool :
2187- """
2188- Ask the user if they know what they actually want to connect to the
2189- user-bus of the `root` user.
2190- """
2191- prev_focus = self .focused
2192- self .set_focus (None )
2193- do_switch = await self .app .push_screen_wait (RootUserBusModal ())
2194- self .set_focus (prev_focus )
2195- return do_switch
2196-
2197- # `work` is required to push the screen for `wants_root_user_bus`.
2198- @work
2199- async def action_toggle_mode (self ) -> None :
2146+ def action_toggle_mode (self ) -> None :
22002147 """
22012148 Toggle the current `bus`.
22022149 Try to protect the user from accidentally crashing the program by trying
@@ -2205,12 +2152,18 @@ async def action_toggle_mode(self) -> None:
22052152
22062153 - <https://github.com/isd-project/isd/issues/30>
22072154 """
2208- if (
2209- is_root ()
2210- and self .mode == "system"
2211- and not self .settings .auto_accept_connection_to_root_user_bus
2212- ):
2213- if not (await self .wants_root_user_bus ()):
2155+ if is_root () and self .mode == "system" :
2156+ # Test if `root` user can actually connect to a `--user` bus.
2157+ proc = systemctl_is_system_running (mode = "user" )
2158+ if proc .returncode != 0 :
2159+ self .notify (
2160+ "Could not connect to `root` users `--user` bus.\n "
2161+ + "Usually, this does not work, as the `root` user does not have any `user` services.\n "
2162+ + "The connection was tested via `systemctl --user is-system-running` as `root` user with the full error message below:\n \n "
2163+ + proc .stderr ,
2164+ severity = "error" ,
2165+ timeout = 60 ,
2166+ )
22142167 return
22152168
22162169 self .mode = "system" if self .mode == "user" else "user"
0 commit comments