xdm on Linux

This describes how to configure xdm (X Display Manager) on a Gentoo Linux box for graphical logins. A default xdm looks pretty boring:



I wanted a more sophisticated look:



This howto assumes that you have already configured your X11 environment, and that you can start X11 by calling startx, startxfce, or the like.

Installation

As xdm is not installed by default, simply emerge it:

# emerge xdm
Configuration files are then placed into /etc/X11/xdm, whilst scripts are located in /usr/lib/X11/xdm.
On Gentoo Linux, xdm is not started by init directly. Instead, you have to enable xdm like any service:
# rc-update add xdm default

Configuration

  1. The script /usr/lib/X11/xdm/Xsetup_0 is called by xdm when the local X server is started. It is responsible for starting any tools and widgets on the login screen. We want a clock in the upper right corner, a console in the lower left corner, the matrix screensaver, and a system status along with a reboot and shutdown button in the lower right corner:
    #!/bin/sh
    
    xclock -geometry -0+0 -digital -update 1 -fn fixed -sharp &
    /etc/X11/xdm/xdm-buttons -geometry -0-0 &
    /usr/lib/misc/xscreensaver/xmatrix -density 10 -no-trace -no-knock-knock -root &
    xconsole -geometry 480x130+0-0 -daemon -notify -verbose -fn fixed 
    
    This script has to be executable:
    # chmod 0755 /usr/lib/X11/xdm/Xsetup_0
    
  2. The Tcl/Tk script /etc/X11/xdm/xdm-buttons shows a reboot and shutdown button. It takes the output of the command line tool uptime to display the number of currently logged in users, the uptime of the system, and the load average. These numbers are updated every 2 seconds:
    #!/usr/bin/wish
    
    proc reboot {} {
      exec /sbin/reboot
    }
    
    proc shutdown {} {
      exec /sbin/poweroff
    }
    
    proc updateinfo {} {
      global uptime users loadavg
      regexp {(.+),  (.+),  (.+)} [exec uptime] -> uptime users loadavg
      regexp {(up.+)} $uptime -> uptime
      regexp {: (.+)} $loadavg -> loadavg
      set loadavg "load avg:\n$loadavg"
      after 2000 updateinfo
    }
    
    label .uptime \
      -textvar uptime \
      -relief flat \
      -border 0 \
      -font Helvetica-8
    
    label .users \
      -textvar users \
      -relief flat \
      -border 0 \
      -font Helvetica-8
    
    label .loadavg \
      -textvar loadavg \
      -relief flat \
      -border 0 \
      -font Helvetica-8
    
    button .reboot \
      -text "Reboot" \
      -relief flat \
      -border 0 \
      -font Helvetica-18 \
      -command reboot
    
    button .shutdown \
      -text "Shutdown" \
      -relief flat \
      -border 0 \
      -font Helvetica-18 \
      -command shutdown
    
    updateinfo
    pack .shutdown .reboot .loadavg .users .uptime -fill x -side bottom
    
    This script has to be executable as well.
  3. After a user has been authenticated by xdm, it calls /usr/lib/X11/xdm/GiveConsole. Usually, this script just gives the user access to /dev/console. As xdm does not write to /var/log/wtmp, /var/run/utmp or /var/log/lastlog itself, we have to take care of that as well. Additionally, all tools and widgets started by Xsetup_0 are stopped, too:
    #!/bin/sh
    
    killall xconsole
    killall xclock
    killall xdm-buttons
    killall xmatrix
    chown $USER /dev/console
    exec /usr/bin/sessreg -a -l $DISPLAY $USER
    
    Make GiveConsole executable, too.
  4. When the user logs out, xdm calls /usr/lib/X11/xdm/TakeConsole to revoke permissions from /dev/console. Also, we remove the user's session from wtmp, utmp, and lastlog:
    #!/bin/sh
    
    /usr/bin/sessreg -d -l $DISPLAY $USER
    chmod 622 /dev/console
    chown root /dev/console
    
    Like all scripts, TakeConsole must be executable.
  5. The file /etc/X11/xdm/Xresources defines the overall appearance of the login screen, like fonts, colors, border sizes, and the greeting:
    Xcursor.theme: whiteglass
    
    xlogin*login.translations: #override \
    	CtrlR: abort-display()\n\
    	F1: set-session-argument(failsafe) finish-field()\n\
    	Delete: delete-character()\n\
    	Left: move-backward-character()\n\
    	Right: move-forward-character()\n\
    	Home: move-to-begining()\n\
    	End: move-to-end()\n\
    	CtrlKP_Enter: set-session-argument(failsafe) finish-field()\n\
    	KP_Enter: set-session-argument() finish-field()\n\
    	CtrlReturn: set-session-argument(failsafe) finish-field()\n\
    	Return: set-session-argument() finish-field()
    
    xlogin*greeting: Welcome to CLIENTHOST
    xlogin*namePrompt: \040\040\040\040\040\040\040Login:
    xlogin*passwdPrompt: Password:
    xlogin*fail: Login incorrect or forbidden by policy
    
    #if WIDTH > 800
    xlogin*greetFont: -adobe-helvetica-bold-o-normal--24-240-75-75-p-138-iso8859-1
    xlogin*font: -adobe-helvetica-medium-r-normal--18-180-75-75-p-98-iso8859-1
    xlogin*promptFont: -adobe-helvetica-bold-r-normal--18-180-75-75-p-103-iso8859-1
    xlogin*failFont: -adobe-helvetica-bold-r-normal--18-180-75-75-p-103-iso8859-1
    xlogin*greetFace:	Serif-18:bold
    xlogin*face: 		Helvetica-18
    xlogin*promptFace: 	Helvetica-18:bold
    xlogin*failFace: 	Helvetica-18:bold
    #else
    xlogin*greetFont: -adobe-helvetica-bold-o-normal--17-120-100-100-p-92-iso8859-1
    xlogin*font: -adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1
    xlogin*promptFont: -adobe-helvetica-bold-r-normal--12-120-75-75-p-70-iso8859-1
    xlogin*failFont: -adobe-helvetica-bold-o-normal--14-140-75-75-p-82-iso8859-1
    xlogin*greetFace:	Serif-18:bold:italic
    xlogin*face:		Helvetica-12
    xlogin*promptFace:	Helvetica-12:bold
    xlogin*failFace:	Helvetica-14:bold
    #endif
    
    #ifdef COLOR
    xlogin*borderWidth: 1
    xlogin*frameWidth: 1
    xlogin*innerFramesWidth: 1
    xlogin*shdColor: limegreen
    xlogin*hiColor: limegreen
    xlogin*background: black
    xlogin*foreground: green
    xlogin*greetColor: limegreen
    xlogin*failColor: green
    *Foreground: limegreen
    *Background: black
    #else
    xlogin*borderWidth: 3
    xlogin*frameWidth: 0
    xlogin*innerFramesWidth: 1
    xlogin*shdColor: black
    xlogin*hiColor: black
    #endif
    
    #if PLANES >= 8
    !xlogin*logoFileName: /usr/lib64/X11/xdm/pixmaps/xorg.xpm
    #else
    xlogin*logoFileName: /usr/lib64/X11/xdm/pixmaps/xorg-bw.xpm
    #endif
    xlogin*useShape: true
    xlogin*logoPadding: 10
    
    xlogin.Login.echoPasswd: true
    
    XConsole*borderWidth: 1
    XConsole.text.geometry:	480x130
    XConsole.verbose:	true
    XConsole*iconic:	true
    XConsole*font:		fixed
    
    Chooser*geometry:		700x500+300+200
    Chooser*allowShellResize:	false
    Chooser*viewport.forceBars:	true
    Chooser*label.font:		*-new century schoolbook-bold-i-normal-*-240-*
    Chooser*label.label:		XDMCP Host Menu from CLIENTHOST
    Chooser*list.font:		-*-*-medium-r-normal-*-*-230-*-*-c-*-iso8859-1
    Chooser*Command.font:		*-new century schoolbook-bold-r-normal-*-180-*
    
  6. Finally, each user has to create an executable file ~/.xsession in his or her home directory. It is called by xdm to start the user's X session, similar to ~/.xinit, which is called when the user starts X11 via startx. Thus, in most cases symlinking ~/.xsession to ~/.xinit is sufficient:
    $ ln -s ~/.xinit ~/.xsession
    
  7. Now reboot, or start xdm as user root:
    # rc-service xdm start
    

Files