first commit

This commit is contained in:
Stefan Hacker
2026-02-18 22:01:54 +01:00
commit 5464e553b3
35 changed files with 5432 additions and 0 deletions
+94
View File
@@ -0,0 +1,94 @@
//go:build linux
package service
import (
"fmt"
"os"
"os/exec"
"path/filepath"
)
const systemdUnitTemplate = `[Unit]
Description=USB Client (%s mode)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=%s %s --config %s
Restart=always
RestartSec=5
User=root
[Install]
WantedBy=multi-user.target
`
const serviceName = "usb-client"
// Install creates and enables a systemd service
func Install(mode, configPath string) error {
// Find the executable
exePath, err := os.Executable()
if err != nil {
return fmt.Errorf("finding executable: %w", err)
}
exePath, err = filepath.Abs(exePath)
if err != nil {
return fmt.Errorf("resolving path: %w", err)
}
absConfigPath, err := filepath.Abs(configPath)
if err != nil {
return fmt.Errorf("resolving config path: %w", err)
}
unitContent := fmt.Sprintf(systemdUnitTemplate, mode, exePath, mode, absConfigPath)
unitPath := fmt.Sprintf("/etc/systemd/system/%s.service", serviceName)
if err := os.WriteFile(unitPath, []byte(unitContent), 0644); err != nil {
return fmt.Errorf("writing unit file: %w (need root?)", err)
}
// Reload systemd
if err := exec.Command("systemctl", "daemon-reload").Run(); err != nil {
return fmt.Errorf("daemon-reload: %w", err)
}
// Enable and start
if err := exec.Command("systemctl", "enable", serviceName).Run(); err != nil {
return fmt.Errorf("enable: %w", err)
}
if err := exec.Command("systemctl", "start", serviceName).Run(); err != nil {
return fmt.Errorf("start: %w", err)
}
return nil
}
// Uninstall stops and removes the systemd service
func Uninstall() error {
// Stop and disable
exec.Command("systemctl", "stop", serviceName).Run()
exec.Command("systemctl", "disable", serviceName).Run()
// Remove unit file
unitPath := fmt.Sprintf("/etc/systemd/system/%s.service", serviceName)
os.Remove(unitPath)
// Reload
exec.Command("systemctl", "daemon-reload").Run()
return nil
}
// Status returns the systemd service status
func Status() (string, error) {
out, err := exec.Command("systemctl", "status", serviceName).CombinedOutput()
if err != nil {
return string(out), nil // status returns non-zero for inactive services
}
return string(out), nil
}
+17
View File
@@ -0,0 +1,17 @@
//go:build windows
package service
import "fmt"
func Install(mode, configPath string) error {
return fmt.Errorf("Windows service installation not yet implemented")
}
func Uninstall() error {
return fmt.Errorf("Windows service uninstallation not yet implemented")
}
func Status() (string, error) {
return "not implemented on Windows", nil
}