#!/usr/bin/python3
# Lancé par l'installation d'une nouvelle version de p2i-bureau (en root) :
# affiche, dans chaque session P2i ouverte, la fenêtre qui propose de
# redémarrer. Ne fait rien s'il n'y a pas de session (construction de l'image,
# mise à jour automatique pendant que personne n'est connecté).
import glob
import os
import pwd
import subprocess
import sys

version = sys.argv[1] if len(sys.argv) > 1 else ""

# Raison du redémarrage en attente, affichée dans Réglages. /run est vidé au
# redémarrage : l'indication disparaît d'elle-même.
try:
    os.makedirs("/run/p2i", exist_ok=True)
    raison = ("Mise à jour installée : P2i OS " + version if version else "Mise à jour du bureau P2i installée") \
        + ". Les nouveautés seront actives après le redémarrage."
    with open("/run/p2i/redemarrage", "w", encoding="utf-8") as f:
        f.write(raison + "\n")
    os.chmod("/run/p2i/redemarrage", 0o644)
except OSError:
    pass
GARDER = ("XDG_", "WAYLAND_DISPLAY", "DISPLAY", "DBUS_SESSION_BUS_ADDRESS", "QT_", "P2I_", "XCURSOR_",
          "LANG", "LC_", "LANGUAGE", "HOME", "USER", "LOGNAME", "PATH", "SHELL", "LIBGL_")


def environnement(pid):
    try:
        brut = open(f"/proc/{pid}/environ", "rb").read().decode("utf-8", "replace")
    except OSError:
        return None
    env = dict(l.split("=", 1) for l in brut.split("\0") if "=" in l)
    return {c: v for c, v in env.items() if c.startswith(GARDER)}


faits = set()
for chemin in glob.glob("/proc/[0-9]*/cmdline"):
    pid = chemin.split("/")[2]
    try:
        ligne = open(chemin, "rb").read()
        uid = os.stat(f"/proc/{pid}").st_uid
    except OSError:
        continue
    # Le Dock tourne dans toute session P2i ouverte : il sert de repère.
    if b"/usr/share/p2i/apps/menu.py" not in ligne or uid in faits or uid < 1000:
        continue
    env = environnement(pid)
    if not env or "WAYLAND_DISPLAY" not in env:
        continue
    faits.add(uid)
    try:
        compte = pwd.getpwuid(uid)
    except KeyError:
        continue

    def changer(compte=compte):
        os.setsid()
        os.initgroups(compte.pw_name, compte.pw_gid)
        os.setgid(compte.pw_gid)
        os.setuid(compte.pw_uid)

    subprocess.run(["pkill", "-u", str(uid), "-f", "/usr/share/p2i/apps/redemarrage.py"],
                   capture_output=True)
    try:
        subprocess.Popen(["/usr/bin/p2i-redemarrage", version], env=env, cwd=compte.pw_dir,
                         preexec_fn=changer, stdin=subprocess.DEVNULL,
                         stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, close_fds=True)
    except OSError:
        pass
