KDM and LightDM (at least with autologin) call the xsession-script with two arguments: the first is the path of the xsession script itself, while the second one are the actual arguments. The line to re-exec the script under systemd-cat only forwarded a single argument, therefore breaking LightDM and KDM login. This commit fixes the issue by always forwarding all the arguments.
		
			
				
	
	
		
			312 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			312 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
# This module declares the options to define a *display manager*, the
 | 
						|
# program responsible for handling X logins (such as xdm, kdm, gdb, or
 | 
						|
# SLiM).  The display manager allows the user to select a *session
 | 
						|
# type*.  When the user logs in, the display manager starts the
 | 
						|
# *session script* ("xsession" below) to launch the selected session
 | 
						|
# type.  The session type defines two things: the *desktop manager*
 | 
						|
# (e.g., KDE, Gnome or a plain xterm), and optionally the *window
 | 
						|
# manager* (e.g. kwin or twm).
 | 
						|
 | 
						|
{ config, lib, pkgs, ... }:
 | 
						|
 | 
						|
with lib;
 | 
						|
 | 
						|
let
 | 
						|
 | 
						|
  cfg = config.services.xserver;
 | 
						|
  xorg = pkgs.xorg;
 | 
						|
 | 
						|
  fontconfig = config.fonts.fontconfig;
 | 
						|
  xresourcesXft = pkgs.writeText "Xresources-Xft" ''
 | 
						|
    ${optionalString (fontconfig.dpi != 0) ''Xft.dpi: ${toString fontconfig.dpi}''}
 | 
						|
    Xft.antialias: ${if fontconfig.antialias then "1" else "0"}
 | 
						|
    Xft.rgba: ${fontconfig.subpixel.rgba}
 | 
						|
    Xft.lcdfilter: lcd${fontconfig.subpixel.lcdfilter}
 | 
						|
    Xft.hinting: ${if fontconfig.hinting.enable then "1" else "0"}
 | 
						|
    Xft.autohint: ${if fontconfig.hinting.autohint then "1" else "0"}
 | 
						|
    Xft.hintstyle: hint${fontconfig.hinting.style}
 | 
						|
  '';
 | 
						|
 | 
						|
  # file provided by services.xserver.displayManager.session.script
 | 
						|
  xsession = wm: dm: pkgs.writeScript "xsession"
 | 
						|
    ''
 | 
						|
      #! ${pkgs.bash}/bin/bash
 | 
						|
 | 
						|
      ${optionalString cfg.displayManager.logToJournal ''
 | 
						|
        if [ -z "$_DID_SYSTEMD_CAT" ]; then
 | 
						|
          _DID_SYSTEMD_CAT=1 exec ${config.systemd.package}/bin/systemd-cat -t xsession -- "$0" "$@"
 | 
						|
        fi
 | 
						|
      ''}
 | 
						|
 | 
						|
      . /etc/profile
 | 
						|
      cd "$HOME"
 | 
						|
 | 
						|
      # The first argument of this script is the session type.
 | 
						|
      sessionType="$1"
 | 
						|
      if [ "$sessionType" = default ]; then sessionType=""; fi
 | 
						|
 | 
						|
      ${optionalString (!cfg.displayManager.job.logsXsession && !cfg.displayManager.logToJournal) ''
 | 
						|
        exec > ~/.xsession-errors 2>&1
 | 
						|
      ''}
 | 
						|
 | 
						|
      ${optionalString cfg.startDbusSession ''
 | 
						|
        if test -z "$DBUS_SESSION_BUS_ADDRESS"; then
 | 
						|
          exec ${pkgs.dbus.dbus-launch} --exit-with-session "$0" "$sessionType"
 | 
						|
        fi
 | 
						|
      ''}
 | 
						|
 | 
						|
      # Handle being called by kdm.
 | 
						|
      if test "''${1:0:1}" = /; then eval exec "$1"; fi
 | 
						|
 | 
						|
      # Start PulseAudio if enabled.
 | 
						|
      ${optionalString (config.hardware.pulseaudio.enable) ''
 | 
						|
        ${optionalString (!config.hardware.pulseaudio.systemWide)
 | 
						|
          "${config.hardware.pulseaudio.package.out}/bin/pulseaudio --start"
 | 
						|
        }
 | 
						|
 | 
						|
        # Publish access credentials in the root window.
 | 
						|
        ${config.hardware.pulseaudio.package.out}/bin/pactl load-module module-x11-publish "display=$DISPLAY"
 | 
						|
      ''}
 | 
						|
 | 
						|
      # Tell systemd about our $DISPLAY. This is needed by the
 | 
						|
      # ssh-agent unit.
 | 
						|
      ${config.systemd.package}/bin/systemctl --user import-environment DISPLAY
 | 
						|
 | 
						|
      # Load X defaults.
 | 
						|
      ${xorg.xrdb}/bin/xrdb -merge ${xresourcesXft}
 | 
						|
      if test -e ~/.Xresources; then
 | 
						|
          ${xorg.xrdb}/bin/xrdb -merge ~/.Xresources
 | 
						|
      elif test -e ~/.Xdefaults; then
 | 
						|
          ${xorg.xrdb}/bin/xrdb -merge ~/.Xdefaults
 | 
						|
      fi
 | 
						|
 | 
						|
      # Speed up application start by 50-150ms according to
 | 
						|
      # http://kdemonkey.blogspot.nl/2008/04/magic-trick.html
 | 
						|
      rm -rf $HOME/.compose-cache
 | 
						|
      mkdir $HOME/.compose-cache
 | 
						|
 | 
						|
      # Work around KDE errors when a user first logs in and
 | 
						|
      # .local/share doesn't exist yet.
 | 
						|
      mkdir -p $HOME/.local/share
 | 
						|
 | 
						|
      unset _DID_SYSTEMD_CAT
 | 
						|
 | 
						|
      ${cfg.displayManager.sessionCommands}
 | 
						|
 | 
						|
      # Allow the user to execute commands at the beginning of the X session.
 | 
						|
      if test -f ~/.xprofile; then
 | 
						|
          source ~/.xprofile
 | 
						|
      fi
 | 
						|
 | 
						|
      # Allow the user to setup a custom session type.
 | 
						|
      if test -x ~/.xsession; then
 | 
						|
          exec ~/.xsession
 | 
						|
      else
 | 
						|
          if test "$sessionType" = "custom"; then
 | 
						|
              sessionType="" # fall-thru if there is no ~/.xsession
 | 
						|
          fi
 | 
						|
      fi
 | 
						|
 | 
						|
      # The session type is "<desktop-manager> + <window-manager>", so
 | 
						|
      # extract those.
 | 
						|
      windowManager="''${sessionType##* + }"
 | 
						|
      : ''${windowManager:=${cfg.windowManager.default}}
 | 
						|
      desktopManager="''${sessionType% + *}"
 | 
						|
      : ''${desktopManager:=${cfg.desktopManager.default}}
 | 
						|
 | 
						|
      # Start the window manager.
 | 
						|
      case $windowManager in
 | 
						|
        ${concatMapStrings (s: ''
 | 
						|
          (${s.name})
 | 
						|
            ${s.start}
 | 
						|
            ;;
 | 
						|
        '') wm}
 | 
						|
        (*) echo "$0: Window manager '$windowManager' not found.";;
 | 
						|
      esac
 | 
						|
 | 
						|
      # Start the desktop manager.
 | 
						|
      case $desktopManager in
 | 
						|
        ${concatMapStrings (s: ''
 | 
						|
          (${s.name})
 | 
						|
            ${s.start}
 | 
						|
            ;;
 | 
						|
        '') dm}
 | 
						|
        (*) echo "$0: Desktop manager '$desktopManager' not found.";;
 | 
						|
      esac
 | 
						|
 | 
						|
      ${optionalString (cfg.startDbusSession && cfg.updateDbusEnvironment) ''
 | 
						|
        ${pkgs.glib}/bin/gdbus call --session \
 | 
						|
          --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus \
 | 
						|
          --method org.freedesktop.DBus.UpdateActivationEnvironment \
 | 
						|
          "{$(env | ${pkgs.gnused}/bin/sed "s/'/\\\\'/g; s/\([^=]*\)=\(.*\)/'\1':'\2'/" \
 | 
						|
                  | ${pkgs.coreutils}/bin/paste -sd,)}"
 | 
						|
      ''}
 | 
						|
 | 
						|
      test -n "$waitPID" && wait "$waitPID"
 | 
						|
      exit 0
 | 
						|
    '';
 | 
						|
 | 
						|
  mkDesktops = names: pkgs.runCommand "desktops"
 | 
						|
    { # trivial derivation
 | 
						|
      preferLocalBuild = true;
 | 
						|
      allowSubstitutes = false;
 | 
						|
    }
 | 
						|
    ''
 | 
						|
      mkdir -p $out
 | 
						|
      ${concatMapStrings (n: ''
 | 
						|
        cat - > "$out/${n}.desktop" << EODESKTOP
 | 
						|
        [Desktop Entry]
 | 
						|
        Version=1.0
 | 
						|
        Type=XSession
 | 
						|
        TryExec=${cfg.displayManager.session.script}
 | 
						|
        Exec=${cfg.displayManager.session.script} '${n}'
 | 
						|
        X-GDM-BypassXsession=true
 | 
						|
        Name=${n}
 | 
						|
        Comment=
 | 
						|
        EODESKTOP
 | 
						|
      '') names}
 | 
						|
    '';
 | 
						|
 | 
						|
in
 | 
						|
 | 
						|
{
 | 
						|
 | 
						|
  options = {
 | 
						|
 | 
						|
    services.xserver.displayManager = {
 | 
						|
 | 
						|
      xauthBin = mkOption {
 | 
						|
        internal = true;
 | 
						|
        default = "${xorg.xauth}/bin/xauth";
 | 
						|
        description = "Path to the <command>xauth</command> program used by display managers.";
 | 
						|
      };
 | 
						|
 | 
						|
      xserverBin = mkOption {
 | 
						|
        type = types.path;
 | 
						|
        description = "Path to the X server used by display managers.";
 | 
						|
      };
 | 
						|
 | 
						|
      xserverArgs = mkOption {
 | 
						|
        type = types.listOf types.str;
 | 
						|
        default = [];
 | 
						|
        example = [ "-ac" "-logverbose" "-verbose" "-nolisten tcp" ];
 | 
						|
        description = "List of arguments for the X server.";
 | 
						|
        apply = toString;
 | 
						|
      };
 | 
						|
 | 
						|
      sessionCommands = mkOption {
 | 
						|
        type = types.lines;
 | 
						|
        default = "";
 | 
						|
        example =
 | 
						|
          ''
 | 
						|
            xmessage "Hello World!" &
 | 
						|
          '';
 | 
						|
        description = "Shell commands executed just before the window or desktop manager is started.";
 | 
						|
      };
 | 
						|
 | 
						|
      hiddenUsers = mkOption {
 | 
						|
        type = types.listOf types.str;
 | 
						|
        default = [ "nobody" ];
 | 
						|
        description = ''
 | 
						|
          A list of users which will not be shown in the display manager.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      session = mkOption {
 | 
						|
        default = [];
 | 
						|
        example = literalExample
 | 
						|
          ''
 | 
						|
            [ { manage = "desktop";
 | 
						|
                name = "xterm";
 | 
						|
                start = '''
 | 
						|
                  ''${pkgs.xterm}/bin/xterm -ls &
 | 
						|
                  waitPID=$!
 | 
						|
                ''';
 | 
						|
              }
 | 
						|
            ]
 | 
						|
          '';
 | 
						|
        description = ''
 | 
						|
          List of sessions supported with the command used to start each
 | 
						|
          session.  Each session script can set the
 | 
						|
          <varname>waitPID</varname> shell variable to make this script
 | 
						|
          wait until the end of the user session.  Each script is used
 | 
						|
          to define either a windows manager or a desktop manager.  These
 | 
						|
          can be differentiated by setting the attribute
 | 
						|
          <varname>manage</varname> either to <literal>"window"</literal>
 | 
						|
          or <literal>"desktop"</literal>.
 | 
						|
 | 
						|
          The list of desktop manager and window manager should appear
 | 
						|
          inside the display manager with the desktop manager name
 | 
						|
          followed by the window manager name.
 | 
						|
        '';
 | 
						|
        apply = list: rec {
 | 
						|
          wm = filter (s: s.manage == "window") list;
 | 
						|
          dm = filter (s: s.manage == "desktop") list;
 | 
						|
          names = flip concatMap dm
 | 
						|
            (d: map (w: d.name + optionalString (w.name != "none") (" + " + w.name))
 | 
						|
              (filter (w: d.name != "none" || w.name != "none") wm));
 | 
						|
          desktops = mkDesktops names;
 | 
						|
          script = xsession wm dm;
 | 
						|
        };
 | 
						|
      };
 | 
						|
 | 
						|
      job = {
 | 
						|
 | 
						|
        preStart = mkOption {
 | 
						|
          type = types.lines;
 | 
						|
          default = "";
 | 
						|
          example = "rm -f /var/log/my-display-manager.log";
 | 
						|
          description = "Script executed before the display manager is started.";
 | 
						|
        };
 | 
						|
 | 
						|
        execCmd = mkOption {
 | 
						|
          type = types.str;
 | 
						|
          example = literalExample ''
 | 
						|
            "''${pkgs.slim}/bin/slim"
 | 
						|
          '';
 | 
						|
          description = "Command to start the display manager.";
 | 
						|
        };
 | 
						|
 | 
						|
        environment = mkOption {
 | 
						|
          type = types.attrsOf types.unspecified;
 | 
						|
          default = {};
 | 
						|
          example = { SLIM_CFGFILE = "/etc/slim.conf"; };
 | 
						|
          description = "Additional environment variables needed by the display manager.";
 | 
						|
        };
 | 
						|
 | 
						|
        logsXsession = mkOption {
 | 
						|
          type = types.bool;
 | 
						|
          default = false;
 | 
						|
          description = ''
 | 
						|
            Whether the display manager redirects the
 | 
						|
            output of the session script to
 | 
						|
            <filename>~/.xsession-errors</filename>.
 | 
						|
          '';
 | 
						|
        };
 | 
						|
 | 
						|
      };
 | 
						|
 | 
						|
      logToJournal = mkOption {
 | 
						|
        type = types.bool;
 | 
						|
        default = true;
 | 
						|
        description = ''
 | 
						|
          By default, the stdout/stderr of sessions is written
 | 
						|
          to <filename>~/.xsession-errors</filename>. When this option
 | 
						|
          is enabled, it will instead be written to the journal.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
    };
 | 
						|
 | 
						|
  };
 | 
						|
 | 
						|
  config = {
 | 
						|
    services.xserver.displayManager.xserverBin = "${xorg.xorgserver.out}/bin/X";
 | 
						|
  };
 | 
						|
 | 
						|
  imports = [
 | 
						|
   (mkRemovedOptionModule [ "services" "xserver" "displayManager" "desktopManagerHandlesLidAndPower" ])
 | 
						|
  ];
 | 
						|
 | 
						|
}
 |