Skip to content
December 21, 2007 / gus3

Holiday Slideshow

Being the geek that I am, I like to challenge myself with new ideas. A few weeks ago, I decided that my latest challenge should be to create a Christmas slideshow. I could put up a few strings of flashy lights, maybe even hang a wreath, but why should I be like my neighbors? I have the power of Linux and Free Software at my fingertips; I should show it to them, right?

My requirements for the project were simple:

  1. It must start automatically after boot.
  2. It must have some privilege separation, for protection against my programming mistakes.
  3. Later, I decided it should not run during the day, when sunlight makes the slideshow pointless.

The first challenge was to decide on the hardware setup. I have two primary systems: my powerful desktop, my much weaker system for experiments. My desktop system is nowhere near a window, and I didn’t feel like moving my entire computer desk. I’m not sure the weaker system is capable of running a slideshow (yes, it really is that weak). I don’t have a VGA extension cable, but I do have lots of Cat5 for Ethernet. Ah, the distributed X protocol to the rescue! My desktop runs the slideshow, and the experimental system runs the X server. Already having a serial console on the experimental system is an additional benefit, because I can keep a text login for emergency rescues.

The second challenge was to find properly-licensed images suitable for viewing from the street. I leave this as an “exercise for the readers,” who might want pictures for Hanukkah, Sol Invictus, Kwanzaa, or even simply “Happy Birthday.” My only word of advice: try not to be too abstract or conceptual. Remember, this really is a show for the “man on the street”; as my geeky retired mother said, Nativity scenes should not look like pickles.

Finally, it was time to make it all work together. To meet requirement #1, I had to make sure the script was suitable for running from /etc/inittab. Bash scripting is my language of choice, but security isn’t really part of the language (hence requirement #2). I had initially decided to use Impress, but it proved to have difficulty with long-term stability, so I settled on using the GLslideshow module from the XScreensaver collection. The GLslideshow setup also uses less memory.

I wanted to make the setup reasonably portable, so I decided to keep the configuration in environment variables (as many as I could think of). These are the local user for the X server; the remote user and hostname for the GLslideshow client; and a local, writable directory for state management.

The X forwarding capability of OpenSSH makes it the preferred channel for connecting the X server and the GLslideshow client. My desktop system connects directly to the Internet via dial-out, so a mis-routed packet needs to be shielded from snooping. The OpenSSH project provides the ssh-keygen program for automating SSH connections, without requiring a password. On the experimental system running the X server, I logged in as myself and ran ssh-keygen, giving no password. The generated key allows unattended scripts to use
SSH sessions.

On the desktop system, I created a new user called “slideshow”, with only a home directory, but none of the skeleton files. On my Slackware system, this meant deleting the standard skeleton files after the fact, leaving only .ssh:

useradd -g users slideshow
cd /home/slideshow
rm -rf * .[a-z]*
# Be very careful NOT to use ".*"!
mkdir .ssh

Then I copied the .ssh/ file from the experimental system to the desktop, for password-less SSH connections:

cd .ssh
scp me@remote:.ssh/ authorized_keys
chmod 600 authorized_keys
chown slideshow:users authorized_keys

I confirmed this was correct, by opening an SSH session from the remote system to the local system, without requiring a password.

The GLslideshow program needed to know where to find the images on my desktop system. In a terminal window, I typed:

xhost +localhost
# A different user needs this for X access
su - slideshow

Then I clicked on the Advanced tab, selected “Choose Random Image” in the Image Manipulation block, and entered “/home/slideshow/wallpapers” as the directory containing the images. Closing the window saved the parameters.

Next, I created a script on the experimental system, to check the network connection and start the slideshow, if the time is between 5:00PM and 7:00AM. Okay, the script is actually the result of approximately 17 iterations. A few notes:

  1. I have tried to centralize configuration into the environment variables at the top of the script.
  2. Using -Y instead of -X bypasses certain security checks in OpenSSH’s X forwarding. This means it should be used only on a trusted network, with trusted systems.
  3. The parameters to glslideshow (no fading or panning) are chosen to minimize the network and CPU load on my experimental system.
  4. Checking that X is still running could surely be improved. Another process with the same PID as $XPID could appear, confusing the state management with a race condition.

With this script in /etc/rc.d, I made the following adjustments to /etc/inittab:

  1. I commented out all the c1-c6 lines, so that no login would interfere with the VGA screen. (I already had the serial console ttyS0 set up, from previous tinkering.)
  2. I changed the x1 line to read: x1:4:respawn:/etc/rc.d/

With that, I logged in as root and typed “telinit 4” to see if it would work. Voila! Every 20 seconds, a different image appeared.

Bearing in mind the networked nature of the script, I tested its recovery capability by rebooting my desktop. Sure enough, it restarted just fine. In fact, the slideshow was running on the experimental
system before my X login screen appeared on my desktop.

To make it fully automatic, I changed the default runlevel in the experimental system’s /etc/inittab to 4:


This is Slackware’s default X login runlevel; some (most?) Linux distros use runlevel 5 instead. A reboot of the experimental system made sure the slideshow script would survive a reboot.

Once everything was working together correctly, I put the monitor in the window, so that my neighbors and people walking and driving by could see it.

My experiment has been a personal success, bringing together my skills in Bash scripting, documentation chasing, and the old “scratch an itch” feeling.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: