diff --git a/solixauto/service.py b/solixauto/service.py
index bcde3c7..1ff77d1 100644
--- a/solixauto/service.py
+++ b/solixauto/service.py
@@ -2,6 +2,7 @@ import os
import subprocess
import sys
from pathlib import Path
+from xml.sax.saxutils import escape as xml_escape
from . import paths
@@ -73,13 +74,20 @@ def environment():
def launchd_plist(profile_name):
- label = service_label(profile_name)
+ label = xml_escape(service_label(profile_name))
+ python = xml_escape(preferred_python())
script = script_path()
+ script_escaped = xml_escape(script)
+ working_dir = xml_escape(str(Path(script).parent))
+ profile_arg = xml_escape(profile_name)
log_dir = paths.LOG_DIR
env_entries = ""
for key, value in environment().items():
- env_entries += f" {key}\n {value}\n"
+ env_entries += (
+ f" {xml_escape(key)}\n"
+ f" {xml_escape(value)}\n"
+ )
env_block = ""
if env_entries:
@@ -90,6 +98,9 @@ def launchd_plist(profile_name):
" \n"
)
+ out_path = xml_escape(str(log_dir / f"{profile_name}.out.log"))
+ err_path = xml_escape(str(log_dir / f"{profile_name}.err.log"))
+
return f"""
@@ -100,15 +111,15 @@ def launchd_plist(profile_name):
ProgramArguments
- {preferred_python()}
- {script}
+ {python}
+ {script_escaped}
run
- {profile_name}
+ {profile_arg}
--quiet
WorkingDirectory
- {Path(script).parent}
+ {working_dir}
{env_block} RunAtLoad
@@ -120,19 +131,29 @@ def launchd_plist(profile_name):
60
StandardOutPath
- {log_dir / f"{profile_name}.out.log"}
+ {out_path}
StandardErrorPath
- {log_dir / f"{profile_name}.err.log"}
+ {err_path}
"""
+def _systemd_quote(value):
+ escaped = str(value).replace("\\", "\\\\").replace('"', '\\"')
+ return f'"{escaped}"'
+
+
def systemd_unit(profile_name):
script = script_path()
+ exec_start = " ".join(
+ _systemd_quote(token)
+ for token in (preferred_python(), script, "run", profile_name, "--quiet")
+ )
env_lines = "".join(
- f"Environment={key}={value}\n" for key, value in environment().items()
+ f"Environment={_systemd_quote(f'{key}={value}')}\n"
+ for key, value in environment().items()
)
return f"""[Unit]
@@ -141,7 +162,7 @@ After=network-online.target
[Service]
Type=simple
-ExecStart={preferred_python()} {script} run {profile_name} --quiet
+ExecStart={exec_start}
WorkingDirectory={Path(script).parent}
{env_lines}Restart=always
RestartSec=60
@@ -158,7 +179,7 @@ def windows_instructions(profile_name):
others. Use Task Scheduler:
schtasks /create /tn "{label}" /sc onlogon /rl highest ^
- /tr "\\"{preferred_python()}\\" \\"{script}\\" run {profile_name} --quiet"
+ /tr "\\"{preferred_python()}\\" \\"{script}\\" run \\"{profile_name}\\" --quiet"
To remove it: