penguins-eggs
Version:
A remaster system tool, compatible with Almalinux, Alpine, Arch, Debian, Devuan, Fedora, Manjaro, Opensuse, Ubuntu and derivatives
200 lines (199 loc) • 10 kB
JavaScript
/**
* ./src/classes/ovary.d/create-xdg-autostart.ts
* penguins-eggs v.25.12.x / ecmascript 2020
* author: Piero Proietti
* email: piero.proietti@gmail.com
* license: MIT
*/
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { exec } from '../../lib/utils.js';
import Xdg from '../xdg.js';
import Pacman from '../pacman.js';
import PveLive from '../pve-live.js';
// Setup __dirname per moduli ESM
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
/**
* Crea la configurazione XDG Autostart e gestisce l'autologin universale
*/
export async function createXdgAutostart(theme = 'eggs', myAddons, myLinks = [], noicons = false) {
if (this.verbose) {
console.log('Ovary: createXdgAutostart (Native TS implementation)');
}
const mergedRoot = this.settings.work_dir.merged;
const newuser = this.settings.config.user_opt;
/**
* Helper per gestire file e directory in modo nativo
*/
const copyToLiveroot = (srcRelative, destRelative) => {
const src = path.resolve(__dirname, srcRelative);
const dest = path.join(mergedRoot, destRelative);
if (fs.existsSync(src)) {
fs.mkdirSync(path.dirname(dest), { recursive: true });
fs.copyFileSync(src, dest);
}
};
/**
* 1. ICONE & ASSETS
*/
const assets = ['eggs.png', 'krill.svg', 'leaves.svg'];
for (const asset of assets)
copyToLiveroot(`../../../assets/${asset}`, `/usr/share/icons/${asset}`);
copyToLiveroot('../../../assets/penguins-eggs.desktop', '/usr/share/applications/penguins-eggs.desktop');
/**
* 2. INSTALLER & POLKIT
*/
let installerLink = 'install-system.desktop';
if (Pacman.calamaresExists()) {
copyToLiveroot(`../../../addons/${theme}/theme/applications/install-system.desktop`, '/usr/share/applications/install-system.desktop');
const policyPath = '/usr/share/polkit-1/actions/io.calamares.calamares.policy';
copyToLiveroot('../../../assets/calamares/io.calamares.calamares.policy', policyPath);
const fullPolicyPath = path.join(mergedRoot, policyPath);
if (fs.existsSync(fullPolicyPath)) {
let policy = fs.readFileSync(fullPolicyPath, 'utf8');
policy = policy.replaceAll(/<(allow_any|allow_inactive|allow_active)>.*?<\/\1>/g, '<$1>yes</$1>');
fs.writeFileSync(fullPolicyPath, policy, 'utf8');
}
}
else if (Pacman.packageIsInstalled('live-installer')) {
installerLink = 'penguins-live-installer.desktop';
copyToLiveroot('../../../assets/penguins-live-installer.desktop', '/usr/share/applications/penguins-live-installer.desktop');
}
else if (Pacman.packageIsInstalled('ubiquity')) {
installerLink = 'penguins-ubiquity-installer.desktop';
copyToLiveroot('../../../assets/penguins-ubiquity-installer.desktop', '/usr/share/applications/penguins-ubiquity-installer.desktop');
}
else {
installerLink = 'penguins-krill.desktop';
copyToLiveroot('../../../assets/penguins-krill.desktop', '/usr/share/applications/penguins-krill.desktop');
}
/**
* 3. ADDONS
*/
if (myAddons.adapt)
copyToLiveroot('../../../addons/eggs/adapt/applications/eggs-adapt.desktop', '/usr/share/applications/eggs-adapt.desktop');
if (myAddons.rsupport) {
copyToLiveroot('../../../addons/eggs/rsupport/applications/eggs-rsupport.desktop', '/usr/share/applications/eggs-rsupport.desktop');
copyToLiveroot('../../../addons/eggs/rsupport/artwork/eggs-rsupport.png', '/usr/share/icons/eggs-rsupport.png');
}
if (myAddons.pve) {
const pve = new PveLive();
pve.create(mergedRoot);
copyToLiveroot('../../../addons/eggs/pve/artwork/eggs-pve.png', '/usr/share/icons/eggs-pve.png');
copyToLiveroot('../../../addons/eggs/pve/applications/eggs-pve.desktop', '/usr/share/applications/eggs-pve.desktop');
}
/**
* 4. SCRIPT AUTOSTART (Icone Desktop e Trust)
*/
const autostartDir = path.join(mergedRoot, '/etc/xdg/autostart');
copyToLiveroot('../../../assets/penguins-links-add.desktop', '/etc/xdg/autostart/penguins-links-add.desktop');
const scriptPath = path.join(mergedRoot, '/usr/bin/penguins-links-add.sh');
let scriptText = '#!/bin/sh\nDESKTOP=$(xdg-user-dir DESKTOP)\n';
// Attendiamo che la cartella Desktop esista
scriptText += 'while [ ! -d "$DESKTOP" ]; do sleep 1; DESKTOP=$(xdg-user-dir DESKTOP); done\n';
scriptText += `cp /usr/share/applications/${installerLink} "$DESKTOP"\n`;
if (!noicons)
scriptText += 'cp /usr/share/applications/penguins-eggs.desktop "$DESKTOP"\n';
for (const link of myLinks)
scriptText += `cp /usr/share/applications/${link}.desktop "$DESKTOP"\n`;
if (Pacman.packageIsInstalled('cosmic-session') || Pacman.packageIsInstalled('gdm3') || Pacman.packageIsInstalled('gdm')) {
// FIX GNOME/COSMIC
scriptText += 'sleep 2\n';
scriptText += 'chown $(id -u):$(id -g) "$DESKTOP"/*.desktop\n';
scriptText += 'chmod a+x "$DESKTOP"/*.desktop\n';
// Forza il tipo stringa per il metadato trusted
scriptText += 'for f in "$DESKTOP"/*.desktop; do gio set -t string "$f" metadata::trusted true || true; done\n';
scriptText += 'touch "$DESKTOP"/*.desktop\n';
}
else if (Pacman.packageIsInstalled('xfce4-session')) {
// FIX XFCE4
scriptText += 'sleep 2\n';
scriptText += 'chown $(id -u):$(id -g) "$DESKTOP"/*.desktop\n';
scriptText += 'chmod +x "$DESKTOP"/*.desktop\n';
// Calcolo checksum sicuro (senza awk per evitare problemi di escaping)
scriptText += 'for f in "$DESKTOP"/*.desktop; do\n';
scriptText += ' SHA=$(sha256sum "$f" | cut -d" " -f1)\n';
scriptText += ' gio set -t string "$f" metadata::xfce-exe-checksum "$SHA"\n';
scriptText += 'done\n';
}
else if (Pacman.packageIsInstalled('lxqt-session')) {
// FIX LXQT
scriptText += 'sleep 5\n'; // Aumentato sleep per dare tempo a PCManFM-Qt
scriptText += 'chown $(id -u):$(id -g) "$DESKTOP"/*.desktop\n';
scriptText += 'chmod +x "$DESKTOP"/*.desktop\n';
// LXQt moderno usa gio/metadata se gvfs è presente
scriptText += 'if command -v gio >/dev/null 2>&1; then\n';
scriptText += ' for f in "$DESKTOP"/*.desktop; do\n';
scriptText += ' gio set -t string "$f" metadata::trusted true || true\n';
scriptText += ' done\n';
scriptText += 'fi\n';
scriptText += 'touch "$DESKTOP"/*.desktop\n';
}
else {
scriptText += 'chmod +x "$DESKTOP"/*.desktop\n';
}
fs.mkdirSync(path.dirname(scriptPath), { recursive: true });
fs.writeFileSync(scriptPath, scriptText, 'utf8');
await exec(`chmod a+x ${scriptPath}`);
/**
* 5. LOGICA AUTOLOGIN UNIVERSALE E SETUP UTENTE
*/
// Sblocco utente (Shadow & PAM)
try {
await exec(`chroot ${mergedRoot} usermod -p "" ${newuser}`);
await exec(`chroot ${mergedRoot} passwd -u ${newuser}`);
}
catch {
if (this.verbose)
console.log('Ovary: error unlocking');
}
// --- FIX PAM: Aggiunti sddm e sddm-autologin alla lista ---
const pamServices = ['common-auth', 'greetd', 'gdm-password', 'login', 'sddm', 'sddm-autologin'];
for (const s of pamServices) {
const p = path.join(mergedRoot, `/etc/pam.d/${s}`);
if (fs.existsSync(p)) {
let c = fs.readFileSync(p, 'utf8');
c = c.replaceAll(/pam_unix\.so(?!.*nullok)/g, 'pam_unix.so nullok');
fs.writeFileSync(p, c, 'utf8');
}
}
// --- FIX CRITICO PER SDDM/LIGHTDM: Setup Home Directory e Gruppi ---
// Questo blocco DEVE essere fuori dai condizionali del Display Manager
// per assicurare che la home sia scrivibile dall'utente (es. .Xauthority)
const userHome = path.join(mergedRoot, 'home', newuser);
if (!fs.existsSync(userHome))
fs.mkdirSync(userHome, { recursive: true });
await exec(`chroot ${mergedRoot} chown -R ${newuser}:${newuser} /home/${newuser}`);
await exec(`chroot ${mergedRoot} usermod -aG video,render,input,tty,audio,storage,power,network ${newuser}`);
// --- CONFIGURAZIONE DISPLAY MANAGER ---
// CASO COSMIC/GREETD: Bypass totale del Display Manager
if (Pacman.packageIsInstalled('greetd')) {
// 1. Forza login automatico su TTY1 tramite Getty
const gettyDir = path.join(mergedRoot, '/etc/systemd/system/getty@tty1.service.d');
fs.mkdirSync(gettyDir, { recursive: true });
const gettyConf = `[Service]\nExecStart=\nExecStart=-/sbin/agetty --autologin ${newuser} --noclear %I $TERM\n`;
fs.writeFileSync(path.join(gettyDir, 'override.conf'), gettyConf, 'utf8');
// 2. Script che lancia la sessione
const startScript = path.join(mergedRoot, '/usr/bin/eggs-start-cosmic');
const startContent = `#!/bin/bash\nif [[ -z $DISPLAY && $(tty) == /dev/tty1 ]]; then\n exec dbus-run-session cosmic-session\nfi\n`;
fs.writeFileSync(startScript, startContent, 'utf8');
await exec(`chmod a+x ${startScript}`);
// 3. Esegui lo script al login della shell
const profilePath = path.join(userHome, '.bash_profile');
fs.writeFileSync(profilePath, `[[ -f /usr/bin/eggs-start-cosmic ]] && . /usr/bin/eggs-start-cosmic\n`, 'utf8');
// Disabilitiamo greetd per evitare conflitti
try {
await exec(`chroot ${mergedRoot} systemctl disable greetd`);
}
catch { }
}
else {
// Altri Display Manager (SDDM, GDM, LightDM, etc.)
// Xdg.autologin configura solo il file di conf del DM
await Xdg.autologin(newuser, mergedRoot);
}
if (this.verbose)
console.log(`Ovary: Autologin and Desktop links configured for user: ${newuser}`);
}