Cdemu and gcdemu

For developer discussion on package requests
Message
Author
Dearth
Posts: 194
Joined: Sun Oct 09, 2022 8:57 am

Re: Cdemu and gcdemu

#11 Post by Dearth »


0x6A7232
Posts: 44
Joined: Sat Aug 20, 2022 12:42 am

Re: Cdemu and gcdemu

#12 Post by 0x6A7232 »

Stevo wrote: Thu Mar 07, 2024 1:03 am It's libmirage-plugin (from memory), it is a dependency. and it's also been ported over from DMO: https://mxrepo.com/mx/testrepo/pool/tes ... libmirage/

Tim has also sent me an init script for cdemu-daemon, so I will do an update for that that includes it.

Code: Select all

#!/bin/sh
### BEGIN INIT INFO
# Provides: cdemu-daemon
# Required-Start:       $syslog $local_fs $remote_fs 
# Required-Stop:        $syslog $local_fs $remote_fs 
# Short-Description: CDEmu daemon
### END INIT INFO

. /lib/lsb/init-functions
prog=cdemu-daemon
PIDFILE=/var/run/$prog.pid
DESC="CDEmu daemon"
start() {
        log_daemon_msg "Starting $DESC" "$prog"
        start_daemon -p $PIDFILE /usr/bin/cdemu-daemon --config-file "%h/.config/cdemu-daemon"
        if [ $? -ne 0 ]; then
                log_end_msg 1
                exit 1
        fi
        if [ $? -eq 0 ]; then
                log_end_msg 0
        fi
        exit 0
}

stop() {
        log_daemon_msg "Stopping $DESC" "$prog"
        killproc -p $PIDFILE /usr/bin/cdemu-daemon
        if [ $? -ne 0 ]; then
                log_end_msg 1
                exit 1
        fi
        if [ $? -eq 0 ]; then
                log_end_msg 0
        fi
}

force_reload() {
        stop
        start

}

case "$1" in
        start)
                start
                ;;
        stop)
                stop
                ;;
        force-reload)
                force_reload
                ;;
        restart)
                stop
                start
                ;;

        *)
                echo "$Usage: $prog {start|stop|force-reload|restart}"
                exit 2
esac
Is this implemented yet? It doesn't seem to be but if it is I need to re-install as it still only has the systemd service.

EDIT: Our friendly AI overlords had this to contribute (unsure if true) and some modifications suggested: (EDIT2: see the bottom for an improved version) (EDIT3: updated again, rsyslog script had an issue)

The provided init script for cdemu-daemon looks mostly correct but has a few issues that could prevent it from working properly on MX Linux with sysVinit. Specifically, the %h placeholder in the --config-file "%h/.config/cdemu-daemon" is meant for systemd’s user service, which expands %h to the user’s home directory. In a sysVinit script, this needs to be replaced with an explicit path or a method to determine the user’s home directory. Additionally, the script could benefit from minor improvements for robustness and compatibility with sysVinit conventions.
Below, I’ll provide a corrected and optimized sysVinit script for cdemu-daemon based on the provided information, the systemd unit, and the forum thread’s script. I’ll also explain why the provided script might not work as-is and how to install the new one.

Issues with the Provided Script
  • %h Placeholder: The --config-file "%h/.config/cdemu-daemon" uses a systemd-specific %h for the home directory. In a sysVinit script, this won’t resolve correctly and could cause the daemon to fail to start.
  • PID File Handling: The script assumes a PID file at /var/run/cdemu-daemon.pid, but it’s unclear if cdemu-daemon creates one. If it doesn’t, killproc and start_daemon might not work as expected.
  • User Context: The cdemu-daemon is designed to run as a user service (per the systemd user unit). Running it as root (default for sysVinit) might cause issues with DBus or config file access.
  • Error Handling: The script’s error handling could be simplified and made more consistent with other sysVinit scripts (like the rsyslogd example).
  • Missing Status Command: The script lacks a status command, which is useful for checking if the daemon is running.
Corrected sysVinit Script for cdemu-daemon

This script assumes cdemu-daemon should run as the user who owns the session (common for DBus user services). It uses su to run the daemon under the appropriate user context and resolves the home directory dynamically.
(EDIT2: See the bottom of this post for an improved revision)
(EDIT3: See the bottom of this post for another improved revision of rsyslog, and I found the stock rsyslog script as well)

Code: Select all

#!/bin/sh
### BEGIN INIT INFO
# Provides:          cdemu-daemon
# Required-Start:    $local_fs $remote_fs $syslog $network
# Required-Stop:     $local_fs $remote_fs $syslog $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: CDEmu daemon
# Description:       Starts the CDEmu daemon for virtual CD emulation
### END INIT INFO

. /lib/lsb/init-functions

DAEMON=/usr/bin/cdemu-daemon
NAME=cdemu-daemon
DESC="CDEmu daemon"
PIDFILE=/var/run/$NAME.pid
CONFIG_FILE="/home/$SUDO_USER/.config/cdemu-daemon"

# Exit if the daemon is not installed
test -x $DAEMON || exit 0

# Function to get the user to run the daemon
get_user() {
    # Use SUDO_USER if available, else fall back to a default user (e.g., first non-root user)
    if [ -n "$SUDO_USER" ]; then
        echo "$SUDO_USER"
    else
        # Alternatively, you could hardcode a user or query a default user
        echo "$(who | head -1 | awk '{print $1}')"
    fi
}

start() {
    log_daemon_msg "Starting $DESC" "$NAME"
    USER=$(get_user)
    if [ -z "$USER" ]; then
        log_failure_msg "Could not determine user to run $NAME"
        log_end_msg 1
        exit 1
    fi
    HOME_DIR=$(getent passwd "$USER" | cut -d: -f6)
    CONFIG_FILE="$HOME_DIR/.config/cdemu-daemon"
    # Start the daemon as the specified user
    start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE \
        --chuid "$USER" --exec $DAEMON -- --config-file "$CONFIG_FILE"
    log_end_msg $?
}

stop() {
    log_daemon_msg "Stopping $DESC" "$NAME"
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --exec $DAEMON
    log_end_msg $?
    # Clean up PID file
    rm -f $PIDFILE
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart|reload)
        stop
        sleep 1
        start
        ;;
    status)
        status_of_proc -p "$PIDFILE" "$DAEMON" "$NAME" && exit 0 || exit $?
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|reload|status}" >&2
        exit 1
        ;;
esac

exit 0
Key Changes and Explanations
    • User Context:
    • The script uses get_user to determine the user (prioritizing $SUDO_USER or falling back to the first logged-in user via who).
    • start-stop-daemon uses --chuid "$USER" to run the daemon as the specified user, ensuring DBus and config file access work correctly.
    • The home directory is resolved using getent passwd to construct the correct path to the config file.
    • PID File:
    • The script creates a PID file with --make-pidfile since cdemu-daemon may not generate one itself (common for user daemons).
    • The PID file is cleaned up on stop to avoid stale files.
    • Config File:
    • The %h is replaced with a dynamically resolved home directory path ($HOME_DIR/.config/cdemu-daemon).
    • This matches your manual command (cdemu-daemon --config-file ~/.config/cdemu-daemon).
    • Dependencies:
    • Added $network to Required-Start and Required-Stop since DBus services often require network connectivity.
    • Kept $local_fs, $remote_fs, and $syslog for compatibility with typical sysVinit dependencies.
    • Status Command:
    • Added a status command using status_of_proc for consistency with other init scripts (like the rsyslogd example).
    • Robustness:
    • Used start-stop-daemon for starting and stopping, which is more reliable than killproc or start_daemon.
    • Added error handling for cases where the user cannot be determined.
Installation Instructions

Create the Init Script:

Code: Select all

sudo nano /etc/init.d/cdemu-daemon
Copy and paste the script above, then save and exit.

Set permissions:

Code: Select all

sudo chmod 755 /etc/init.d/cdemu-daemon
Register the Script:
Enable the script to run at boot:

Code: Select all

sudo update-rc.d cdemu-daemon defaults
Test the Script:
Start the daemon:

Code: Select all

sudo /etc/init.d/cdemu-daemon start
Check status:

Code: Select all

sudo /etc/init.d/cdemu-daemon status
Stop the daemon:

Code: Select all

sudo /etc/init.d/cdemu-daemon stop
Restart to test reload:

Code: Select all

sudo /etc/init.d/cdemu-daemon restart
Verify Autostart:
Reboot your system and check if the gcdemu tray icon starts without errors. You can also check if the daemon is running:

Code: Select all

ps aux | grep cdemu-daemon
Notes
User Selection: The script assumes the daemon should run as the user who invoked sudo ($SUDO_USER) or the first logged-in user. If you have a specific user (e.g., your username), you can hardcode it by replacing the get_user function with:

Code: Select all

USER="your_username"
and removing the get_user function.

PID File: If cdemu-daemon doesn’t work well with --make-pidfile, you may need to adjust the script to handle the daemon without a PID file (e.g., using pgrep for stopping).

DBus Integration: The DBus service file (net.sf.cdemu.CDEmuDaemon.service) should work fine as-is since it doesn’t rely on systemd for activation (uses Exec=/bin/true).

MX Linux Shims: MX Linux’s systemd shims (e.g., systemd-sysvcompat) might interfere. If you encounter issues, ensure no conflicting systemd service is enabled:

Code: Select all

sudo systemctl disable cdemu-daemon.service
(This is a user service, so it might not be an issue, but worth checking.)

Why the Forum Script Might Not Work
The script from the MX Linux forum (viewtopic.php?p=768256#p768256) has the %h issue and assumes start_daemon and killproc work correctly with cdemu-daemon. These utilities are less reliable than start-stop-daemon for daemons that don’t manage their own PID files or run as non-root users. The corrected script above addresses these issues and aligns better with your working manual command.

Testing and Troubleshooting
If the daemon still fails to autostart:

Check the logs for errors:

Code: Select all

sudo tail -f /var/log/syslog
Run the daemon manually with verbose output (if available) to diagnose:

Code: Select all

/usr/bin/cdemu-daemon --config-file ~/.config/cdemu-daemon
Verify DBus connectivity:

Code: Select all

dbus-send --session --dest=net.sf.cdemu.CDEmuDaemon --type=method_call --print-reply /net/sf/cdemu/CDEmuDaemon net.sf.cdemu.CDEmuDaemon.Ping
If issues persist, share any error messages, and I can help refine the script.

This should resolve the autostart issue for cdemu-daemon on MX Linux 23.6 with sysVinit. Let me know if you need further assistance!

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

PS: The mentioned rsyslogd script (THIS IS **NOT** for cdemu! Just something the AI used as a reference point!!):

Code: Select all

#!/bin/sh
### BEGIN INIT INFO
# Provides:          rsyslog
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start rsyslog daemon
### END INIT INFO

. /lib/lsb/init-functions

DAEMON=/usr/sbin/rsyslogd
NAME=rsyslog
DESC="system logging daemon"
PIDFILE=/var/run/rsyslogd.pid

test -x $DAEMON || exit 0

case "$1" in
  start)
    log_daemon_msg "Starting $DESC" "$NAME"
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON
    log_end_msg $?
    ;;
  stop)
    log_daemon_msg "Stopping $DESC" "$NAME"
    start-stop-daemon --stop --quiet --pidfile $PIDFILE --exec $DAEMON
    log_end_msg $?
    ;;
  restart|reload)
    log_daemon_msg "Restarting $DESC" "$NAME"
    start-stop-daemon --stop --quiet --pidfile $PIDFILE --exec $DAEMON
    sleep 1
    start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON
    log_end_msg $?
    ;;
  status)
    status_of_proc -p $PIDFILE $DAEMON $NAME && exit 0 || exit $?
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|reload|status}" >&2
    exit 1
    ;;
esac

exit 0
Here's the systemd files for cdemu-daemon:
/usr/lib/systemd/user/cdemu-daemon.service

Code: Select all

[Unit]
Description=CDEmu daemon

[Service]
Type=dbus
BusName=net.sf.cdemu.CDEmuDaemon
ExecStart=/usr/bin/cdemu-daemon --config-file "%h/.config/cdemu-daemon"
Restart=no
This one seems to reference it:
/usr/share/dbus-1/services/net.sf.cdemu.CDEmuDaemon.service

Code: Select all

[D-BUS Service]
Name=net.sf.cdemu.CDEmuDaemon
SystemdService=cdemu-daemon.service
Exec=/bin/true

EDIT2: Here's the latest version of the cdemu-daemon init script with some improvements:

Code: Select all

#!/bin/sh
### BEGIN INIT INFO
# Provides:          cdemu-daemon
# Required-Start:    $local_fs $remote_fs $syslog $network
# Required-Stop:     $local_fs $remote_fs $syslog $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: CDEmu daemon
# Description:       Starts the CDEmu daemon for virtual CD emulation
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
export PATH

DAEMON=/usr/bin/cdemu-daemon
NAME=cdemu-daemon
DESC="CDEmu daemon"
PIDFILE=/var/run/$NAME.pid
DEFAULTFILE=/etc/default/cdemu-daemon
DODTIME=1

# Exit if the daemon is not installed
test -x $DAEMON || exit 0

. /lib/lsb/init-functions

# Include defaults if available
if [ -f $DEFAULTFILE ] ; then
    . $DEFAULTFILE
fi

# Function to get the user to run the daemon
get_user() {
    # Use SUDO_USER if available, else fall back to first non-root user
    if [ -n "$SUDO_USER" ]; then
        echo "$SUDO_USER"
    else
        echo "$(who | head -1 | awk '{print $1}')"
    fi
}

running_pid()
{
    pid=$1
    name=$2
    [ -z "$pid" ] && return 1
    [ ! -d /proc/$pid ] && return 1
    cmd=`cat /proc/$pid/cmdline | tr "\000" "\n" | head -n 1 | cut -d : -f 1`
    [ "$cmd" != "$name" ] && return 1
    return 0
}

running()
{
    [ ! -f "$PIDFILE" ] && return 1
    pid=`cat $PIDFILE`
    running_pid $pid $DAEMON || return 1
    return 0
}

force_stop()
{
    [ ! -f "$PIDFILE" ] && return
    if running ; then
        kill -15 $pid
        [ -n "$DODTIME" ] && sleep "$DODTIME"s
        if running ; then
            kill -9 $pid
            [ -n "$DODTIME" ] && sleep "$DODTIME"s
            if running ; then
                echo "Cannot kill $NAME (pid=$pid)!"
                exit 1
            fi
        fi
    fi
    rm -f $PIDFILE
    return 0
}

start()
{
    log_daemon_msg "Starting $DESC" "$NAME"
    if running ; then
        log_progress_msg "already running"
        log_end_msg 0
        exit 0
    fi
    USER=$(get_user)
    if [ -z "$USER" ]; then
        log_failure_msg "Could not determine user to run $NAME"
        log_end_msg 1
        exit 1
    fi
    HOME_DIR=$(getent passwd "$USER" | cut -d: -f6)
    CONFIG_FILE="$HOME_DIR/.config/cdemu-daemon"
    rm -f $PIDFILE
    start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE \
        --chuid "$USER" --exec $DAEMON -- --config-file "$CONFIG_FILE" $CDEMU_DAEMON_ARGS
    if running ; then
        log_end_msg 0
    else
        log_end_msg 1
    fi
}

stop()
{
    log_daemon_msg "Stopping $DESC" "$NAME"
    if ! running ; then
        log_progress_msg "not running"
        log_end_msg 0
        exit 0
    fi
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --exec $DAEMON
    ret=$?
    rm -f $PIDFILE
    if [ $ret -eq 0 ]; then
        log_end_msg 0
    else
        log_end_msg 1
    fi
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    force-stop)
        log_daemon_msg "Forcefully stopping $DESC" "$NAME"
        force_stop
        if ! running ; then
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;
    restart|reload)
        log_daemon_msg "Restarting $DESC" "$NAME"
        stop
        [ -n "$DODTIME" ] && sleep "$DODTIME"s
        start
        ;;
    status)
        log_daemon_msg "Checking status of $DESC" "$NAME"
        if running ; then
            log_progress_msg "running"
            log_end_msg 0
        else
            log_progress_msg "not running"
            log_end_msg 1
            if [ -f "$PIDFILE" ] ; then
                exit 1
            else
                exit 3
            fi
        fi
        ;;
    *)
        echo "Usage: $0 {start|stop|force-stop|restart|reload|status}" >&2
        exit 1
        ;;
esac

exit 0
Here's the updated rsyslogd script that those improvements were based on:

Code: Select all

#!/bin/sh
### BEGIN INIT INFO
# Provides:          rsyslog
# Required-Start:    $local_fs $remote_fs $syslog
# Required-Stop:     $local_fs $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start rsyslog daemon
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
export PATH

DAEMON=/usr/sbin/rsyslogd
NAME=rsyslog
DESC="system logging daemon"
PIDFILE=/var/run/rsyslogd.pid
DEFAULTFILE=/etc/default/rsyslog
DODTIME=1

test -x $DAEMON || exit 0
. /lib/lsb/init-functions

# Include defaults if available
if [ -f $DEFAULTFILE ] ; then
    . $DEFAULTFILE
fi

running_pid()
{
    pid=$1
    name=$2
    [ -z "$pid" ] && return 1
    [ ! -d /proc/$pid ] && return 1
    cmd=`cat /proc/$pid/cmdline | tr "\000" "\n" | head -n 1 | cut -d : -f 1`
    [ "$cmd" != "$name" ] && return 1
    return 0
}

running()
{
    [ ! -f "$PIDFILE" ] && return 1
    pid=`cat $PIDFILE`
    running_pid $pid $DAEMON || return 1
    return 0
}

force_stop()
{
    [ ! -f "$PIDFILE" ] && return
    if running ; then
        kill -15 $pid
        [ -n "$DODTIME" ] && sleep "$DODTIME"s
        if running ; then
            kill -9 $pid
            [ -n "$DODTIME" ] && sleep "$DODTIME"s
            if running ; then
                echo "Cannot kill $NAME (pid=$pid)!"
                exit 1
            fi
        fi
    fi
    rm -f $PIDFILE
    return 0
}

case "$1" in
    start)
        log_daemon_msg "Starting $DESC" "$NAME"
        if running ; then
            log_progress_msg "already running"
            log_end_msg 0
            exit 0
        fi
        rm -f $PIDFILE
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $RSYSLOGD_ARGS
        if running ; then
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;
    stop)
        log_daemon_msg "Stopping $DESC" "$NAME"
        if ! running ; then
            log_progress_msg "not running"
            log_end_msg 0
            exit 0
        fi
        start-stop-daemon --stop --quiet --pidfile $PIDFILE --exec $DAEMON
        ret=$?
        rm -f $PIDFILE
        if [ $ret -eq 0 ]; then
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;
    force-stop)
        log_daemon_msg "Forcefully stopping $DESC" "$NAME"
        force_stop
        if ! running ; then
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;
    restart|reload)
        log_daemon_msg "Restarting $DESC" "$NAME"
        start-stop-daemon --stop --quiet --pidfile $PIDFILE --exec $DAEMON
        [ -n "$DODTIME" ] && sleep "$DODTIME"s
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $RSYSLOGD_ARGS
        if running ; then
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;
    status)
        log_daemon_msg "Checking status of $DESC" "$NAME"
        if running ; then
            log_progress_msg "running"
            log_end_msg 0
        else
            log_progress_msg "not running"
            log_end_msg 1
            if [ -f "$PIDFILE" ] ; then
                exit 1
            else
                exit 3
            fi
        fi
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|reload|status|force-stop}" >&2
        exit 1
        ;;
esac

exit 0
EDIT3: Another update, of just the rsyslog script, with some improvements:

rsyslog (fixed issue that was causing segfault when using parallel processing for shutdowns -- rsyslog referenced Rsyslog as a requirement which resolved to rsyslog, causing a loop when startpar accessed the shutdown sequence in /etc/init.d/.depend.stop

Code: Select all

#!/bin/sh
### BEGIN INIT INFO
# Provides:          rsyslog
# Required-Start:    $local_fs $remote_fs $time
# Required-Stop:     $local_fs $remote_fs $time
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start rsyslog daemon
# Description:       System logging daemon
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
export PATH

DAEMON=/usr/sbin/rsyslogd
NAME=rsyslog
DESC="system logging daemon"
PIDFILE=/var/run/rsyslogd.pid
DEFAULTFILE=/etc/default/rsyslog
DODTIME=1

test -x $DAEMON || exit 0
. /lib/lsb/init-functions

# Include defaults if available
if [ -f $DEFAULTFILE ] ; then
    . $DEFAULTFILE
fi

running_pid()
{
    pid=$1
    name=$2
    [ -z "$pid" ] && return 1
    [ ! -d /proc/$pid ] && return 1
    cmd=`cat /proc/$pid/cmdline | tr "\000" "\n" | head -n 1 | cut -d : -f 1`
    [ "$cmd" != "$name" ] && return 1
    return 0
}

running()
{
    [ ! -f "$PIDFILE" ] && return 1
    pid=`cat $PIDFILE`
    running_pid $pid $DAEMON || return 1
    return 0
}

force_stop()
{
    [ ! -f "$PIDFILE" ] && return
    if running ; then
        kill -15 $pid
        [ -n "$DODTIME" ] && sleep "$DODTIME"s
        if running ; then
            kill -9 $pid
            [ -n "$DODTIME" ] && sleep "$DODTIME"s
            if running ; then
                echo "Cannot kill $NAME (pid=$pid)!"
                exit 1
            fi
        fi
    fi
    rm -f $PIDFILE
    return 0
}

case "$1" in
    start)
        log_daemon_msg "Starting $DESC" "$NAME"
        if running ; then
            log_progress_msg "already running"
            log_end_msg 0
            exit 0
        fi
        rm -f $PIDFILE
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $RSYSLOGD_ARGS
        if running ; then
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;
    stop)
        log_daemon_msg "Stopping $DESC" "$NAME"
        if ! running ; then
            log_progress_msg "not running"
            log_end_msg 0
            exit 0
        fi
        start-stop-daemon --stop --quiet --pidfile $PIDFILE --exec $DAEMON
        ret=$?
        rm -f $PIDFILE
        if [ $ret -eq 0 ]; then
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;
    force-stop)
        log_daemon_msg "Forcefully stopping $DESC" "$NAME"
        force_stop
        if ! running ; then
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;
    restart|reload)
        log_daemon_msg "Restarting $DESC" "$NAME"
        start-stop-daemon --stop --quiet --pidfile $PIDFILE --exec $DAEMON
        [ -n "$DODTIME" ] && sleep "$DODTIME"s
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $RSYSLOGD_ARGS
        if running ; then
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;
    status)
        log_daemon_msg "Checking status of $DESC" "$NAME"
        if running ; then
            log_progress_msg "running"
            log_end_msg 0
        else
            log_progress_msg "not running"
            log_end_msg 1
            if [ -f "$PIDFILE" ] ; then
                exit 1
            else
                exit 3
            fi
        fi
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|reload|status|force-stop}" >&2
        exit 1
        ;;
esac

exit 0
Here's the stock rsyslog init script which I found here:

Code: Select all

#! /bin/sh
### BEGIN INIT INFO
# Provides:          rsyslog
# Required-Start:    $remote_fs $time
# Required-Stop:     umountnfs $time
# X-Stop-After:      sendsigs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: enhanced syslogd
# Description:       Rsyslog is an enhanced multi-threaded syslogd.
#                    It is quite compatible to stock sysklogd and can be 
#                    used as a drop-in replacement.
### END INIT INFO
#
# Author: Michael Biebl <biebl@debian.org>
#
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="enhanced syslogd"
NAME=rsyslog
RSYSLOGD=rsyslogd
DAEMON=/usr/sbin/rsyslogd
PIDFILE=/run/rsyslogd.pid
SCRIPTNAME=/etc/init.d/$NAME
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
# Define LSB log_* functions.
. /lib/lsb/init-functions
do_start()
{
	# Return
	#   0 if daemon has been started
	#   1 if daemon was already running
	#   other if daemon could not be started or a failure occured
	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $RSYSLOGD_OPTIONS
}
do_stop()
{
	# Return
	#   0 if daemon has been stopped
	#   1 if daemon was already stopped
	#   other if daemon could not be stopped or a failure occurred
	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --exec $DAEMON
}
#
# Tell rsyslogd to close all open files
#
do_rotate() {
	start-stop-daemon --stop --signal HUP --quiet --pidfile $PIDFILE --exec $DAEMON
}
create_xconsole() {
	XCONSOLE=/dev/xconsole
	if [ "$(uname -s)" != "Linux" ]; then
		XCONSOLE=/run/xconsole
		ln -sf $XCONSOLE /dev/xconsole
	fi
	if [ ! -e $XCONSOLE ]; then
		mknod -m 640 $XCONSOLE p
		chown root:adm $XCONSOLE
		[ -x /sbin/restorecon ] && /sbin/restorecon $XCONSOLE
	fi
}
sendsigs_omit() {
	OMITDIR=/run/sendsigs.omit.d
	mkdir -p $OMITDIR
	ln -sf $PIDFILE $OMITDIR/rsyslog
}
case "$1" in
  start)
	log_daemon_msg "Starting $DESC" "$RSYSLOGD"
	create_xconsole
	do_start
	case "$?" in
		0) sendsigs_omit
		   log_end_msg 0 ;;
		1) log_progress_msg "already started"
		   log_end_msg 0 ;;
		*) log_end_msg 1 ;;
	esac
	;;
  stop)
	log_daemon_msg "Stopping $DESC" "$RSYSLOGD"
	do_stop
	case "$?" in
		0) log_end_msg 0 ;;
		1) log_progress_msg "already stopped"
		   log_end_msg 0 ;;
		*) log_end_msg 1 ;;
	esac
	;;
  rotate)
	log_daemon_msg "Closing open files" "$RSYSLOGD"
	do_rotate
	log_end_msg $?
	;;
  restart|force-reload)
	$0 stop
	$0 start
	;;
  try-restart)
	$0 status >/dev/null 2>&1 && $0 restart
	;;
  status)
	status_of_proc -p $PIDFILE $DAEMON $RSYSLOGD && exit 0 || exit $?
	;;
  *)
	echo "Usage: $SCRIPTNAME {start|stop|rotate|restart|force-reload|try-restart|status}" >&2
	exit 3
	;;
esac
:

0x6A7232
Posts: 44
Joined: Sat Aug 20, 2022 12:42 am

Re: Cdemu and gcdemu

#13 Post by 0x6A7232 »

Alright, double-post here, but after a bit of research, it seems that getting this to work correctly will require some wrangling. If you want to use sysVinit you'd need something like this, as sysVinit doesn't support systemd's --user function that loads services at user log in:

Code: Select all

#!/bin/sh
### BEGIN INIT INFO
# Provides:          cdemu-daemon
# Required-Start:    $local_fs $remote_fs $syslog $network $dbus
# Required-Stop:     $local_fs $remote_fs $syslog $network $dbus
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: CDEmu daemon
# Description:       Starts the CDEmu daemon for virtual CD emulation after a standard user logs in
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
export PATH

DAEMON=/usr/bin/cdemu-daemon
NAME=cdemu-daemon
DESC="CDEmu daemon"
PIDFILE=/var/run/$NAME.pid
DODTIME=1
# Maximum time to wait for user login (in seconds)
MAX_WAIT=300

# Exit if the daemon is not installed
test -x $DAEMON || exit 0

. /lib/lsb/init-functions

running_pid() {
    pid=$1
    name=$2
    [ -z "$pid" ] && return 1
    [ ! -d /proc/$pid ] && return 1
    cmd=$(cat /proc/$pid/cmdline | tr "\000" "\n" | head -n 1 | cut -d : -f 1)
    [ "$cmd" != "$name" ] && return 1
    return 0
}

running() {
    [ ! -f "$PIDFILE" ] && return 1
    pid=$(cat $PIDFILE)
    running_pid $pid $DAEMON || return 1
    return 0
}

# Function to find a logged-in standard user (UID >= 1000) with a D-Bus session
find_user() {
    # Check /run/user/* for active user sessions
    for dir in /run/user/*; do
        if [ -d "$dir" ]; then
            uid=$(basename "$dir")
            # Ensure UID is >= 1000 (standard user)
            if [ "$uid" -ge 1000 ]; then
                user=$(getent passwd "$uid" | cut -d: -f1)
                if [ -n "$user" ]; then
                    # Check if D-Bus session bus is available for this user
                    DBUS_ADDRESS=$(su - "$user" -c "echo \$DBUS_SESSION_BUS_ADDRESS" 2>/dev/null)
                    if [ -n "$DBUS_ADDRESS" ]; then
                        echo "$user"
                        return 0
                    fi
                fi
            fi
        fi
    done
    return 1
}

start() {
    log_daemon_msg "Starting $DESC" "$NAME"
    if running; then
        log_progress_msg "already running"
        log_end_msg 0
        exit 0
    fi
    
    # Run polling in the background to avoid blocking sysVinit
    (
        # Wait for a standard user to log in
        WAIT_TIME=0
        while [ $WAIT_TIME -lt $MAX_WAIT ]; do
            USER=$(find_user)
            if [ -n "$USER" ]; then
                HOME_DIR=$(getent passwd "$USER" | cut -d: -f6)
                CONFIG_FILE="$HOME_DIR/.config/cdemu-daemon"
                DBUS_ADDRESS=$(su - "$USER" -c "echo \$DBUS_SESSION_BUS_ADDRESS" 2>/dev/null)
                if [ -n "$DBUS_ADDRESS" ]; then
                    # Start the daemon for the detected user
                    rm -f $PIDFILE
                    start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE \
                        --chuid "$USER" --exec /bin/sh -- -c "DBUS_SESSION_BUS_ADDRESS=$DBUS_ADDRESS $DAEMON --config-file \"$CONFIG_FILE\""
                    if running; then
                        log_daemon_msg "Started $DESC for user $USER" "$NAME"
                        exit 0
                    else
                        log_failure_msg "Failed to start $DESC for user $USER"
                        exit 1
                    fi
                fi
            fi
            sleep 1
            WAIT_TIME=$((WAIT_TIME + 1))
        done
        log_failure_msg "Timeout waiting for a standard user login and D-Bus session bus"
        exit 1
    ) &
    log_end_msg 0
}

stop() {
    log_daemon_msg "Stopping $DESC" "$NAME"
    if ! running; then
        log_progress_msg "not running"
        log_end_msg 0
        exit 0
    fi
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --exec $DAEMON
    ret=$?
    rm -f $PIDFILE
    if [ $ret -eq 0 ]; then
        log_end_msg 0
    else
        log_end_msg 1
    fi
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart|force-reload)
        stop
        [ -n "$DODTIME" ] && sleep "$DODTIME"s
        start
        ;;
    status)
        log_daemon_msg "Checking status of $DESC" "$NAME"
        if running; then
            log_progress_msg "running"
            log_end_msg 0
        else
            log_progress_msg "not running"
            log_end_msg 1
            if [ -f "$PIDFILE" ]; then
                exit 1
            else
                exit 3
            fi
        fi
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|force-reload|status}" >&2
        exit 1
        ;;
esac

exit 0
However, it's much easier to use a .desktop file, put the following cdemu-daemon.desktop file in /etc/xdg/autostart (this should work for xfce, KDE, and GNOME, fluxbox would require fbautostart to process files in that location, or you could add it to ~/.config/autostart per-user (that per-user location also works for xfce, KDE, and GNOME)

Code: Select all

[Desktop Entry]
Type=Application
Exec=cdemu-daemon --config-file=%h/.config/cdemu-daemon
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
Name=CDEmu Daemon
Comment=Virtual CD/DVD drive daemon
The background on this update can be found here: https://x.com/i/grok/share/EElJzOi82EdHDdhlJBSEEUNKu

@Stevo
Stevo wrote: Tue Mar 05, 2024 1:53 am cdemu and gcdemu have been ported over for the MX 19 through 23 test repositories, and should be available soon.
(Not sure how to tag, so quoting)

EDIT: using the .desktop file method worked FLAWLESSLY -- I'm now listening to a mixed-mode data / audio CD loaded via .cue file (DESCENT: VERTIGO) and I am able to browse the files at the same time.
CAVEAT: the CD is on /dev/sr0 and some audio players expect it to be in another location.
Audacious complained about not being able to access cdda:// and Clementine wasn't able to open the disc, although it was able to detect it -- I think it only saw the data track? VLC works like a champ, and Asunder was able to detect the audio tracks for ripping.

0x6A7232
Posts: 44
Joined: Sat Aug 20, 2022 12:42 am

Re: Cdemu and gcdemu

#14 Post by 0x6A7232 »

An update, to handle when users boot with systemd:

Have the .desktop file point to a script that checks if the service is already running (which it should be if booted via SystemD?) and then if not launches.

So, here's the cdemu-daemon.desktop:

Code: Select all

[Desktop Entry]
Type=Application
Name=CDEmu Daemon
Comment=Virtual CD/DVD drive daemon
Exec=/usr/local/bin/cdemu-daemon-autostart.sh
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
Here's /usr/local/bin/cdemu-daemon-autostart.sh:

Code: Select all

#!/bin/bash

# Path to the cdemu-daemon executable
DAEMON=/usr/bin/cdemu-daemon
CONFIG_FILE="$HOME/.config/cdemu-daemon"

# Exit if the daemon is not installed
[ -x "$DAEMON" ] || exit 0

# Check if cdemu-daemon is already running for the current user
if pgrep -u "$USER" -x cdemu-daemon > /dev/null; then
    exit 0
fi

# Check if the system is running systemd
if [ "$(cat /proc/1/comm)" = "systemd" ]; then
    # Check if cdemu-daemon is managed by a systemd user service
    if systemctl --user status cdemu-daemon > /dev/null 2>&1; then
        # Systemd user service is managing cdemu-daemon; no need to start it
        exit 0
    fi
fi

# Start cdemu-daemon if not running (sysVinit or no systemd user service)
exec "$DAEMON" --config-file="$CONFIG_FILE"
Installation StepsPackage Configuration:

[*] Include the .desktop file in /etc/xdg/autostart/ during package installation.
[*] Include the bash script in /usr/local/bin/ with executable permissions (chmod +x).
[*] Add dbus-user-session as a dependency in the package’s control file.

Systemd User Service (Optional):

[*] If the package includes a systemd user service file (e.g., /usr/lib/systemd/user/cdemu-daemon.service), ensure it’s enabled by default for systemd users:

Code: Select all

[Unit]
Description=CDEmu daemon
[Service]
Type=dbus
BusName=net.sf.cdemu.CDEmuDaemon
ExecStart=/usr/bin/cdemu-daemon --config-file=%h/.config/cdemu-daemon
Restart=no
[Install]
WantedBy=default.target
[*] Include a post-install script to enable the user service for systemd users:

Code: Select all

systemctl --user enable cdemu-daemon.service
I **think** the systemd stuff (systemd user service and enabling it) is already handled with the default package, correct?

Anyways. Double check the above actually works as I haven't tested it (I don't use systemd).

Link: https://x.com/i/grok/share/xQlERVWChMh6j704GhzK9wPvH

Post Reply

Return to “Package Requests / Status”