Thursday, June 10, 2010

I use the Unix utility screen to do my work. screen runs on my desktop which is always on and always connected to the Internet. I log into this machine's X windows console, and I also SSH to it from my laptop (sometimes I'm in very low bandwidth scenarios which is why I prefer screen to fancy solutions like VNC or NX).

Each time I log in, I can resume my terminals, but my DISPLAY enviornment variable is set wrong. Even more annoying, each time I start a new terminal in the screen session, it gets a DISPLAY variable based on the location I first started screen. How frustrating.

A while back, I wrote a wrapper script (I called it xscreen) around screen which did the following:
#!/bin/sh

RESETX=~/.resetx

rm -f ${RESETX}
echo "export DISPLAY=${DISPLAY}" > ${RESETX}

if env | grep -q XAUTHORITY; then
echo "export XAUTHORITY=${XAUTHORITY}" >> ${RESETX}
else
echo "unset XAUTHORITY" >> ${RESETX}
fi

screen "$@"
Basically, this script dumped the correct values of DISPLAY and XAUTHORITY into a script before launching screen. I could then source ~/.resetx and I'd have the right DISPLAY and XAUTHORITY variables set up. xscreen worked by grabbing the current values from the shell that starts screen since they're usually right. For me, this terminal is either a gnome-terminal running bash on my desktop which always has DISPLAY=:0.0 or a shell started by ssh -Y to my desktop. So it also has all the variables set up properly.

Despite this solution, I'd invariably still launch an X application and will wait and wait only to realize that the window probably popped up on my desktop. Or I'll run a command and I'll get an error saying it cannot connect to the display. Even worse is when I don't start the X app, but some other command (think, for example, git commit launching your favorite editor) does. The first invocation of one of those commands is almost certainly pointed at the wrong display.

Yesterday, I learned about the bash shell variable PROMPT_COMMAND. It gets run before displaying your prompt. This can be used for a variety of purposes including setting the title of your terminal window to your current directory. Well, I just threw in a source ~/.resetx into PROMPT_COMMAND and voila, my DISPLAY environment variable is (almost) always correct. I say almost, because you have to force a redraw of the prompt at least once, but that has not yet been an issue.

One more word of advice. I only wanted this messing with DISPLAY to happen when I'm in screen. After all, ~/.resetx is only correct if I've started screen. Conveniently, screen sets TERM to 'screen', so in my .bashrc it says:
case "$TERM" in
xterm*|rxvt*)
PROMPT_COMMAND='magic to reset my terminal window header'
;;
screen)
PROMPT_COMMAND="source ~/.resetx"
;;
*)
;;
esac

Now, I guess all of this is bash specific, but if you're not using bash, you should be ;)