Login Window Wallpaper Changer (Lion only)

This program allows you to make the OS X login window have a different wallpaper every time you start up your Mac, as well as a different quote. You must specify the wallpapers and the quotes as detailed below.

Please note that this program modifies system files. Use at your own risk. I am not responsible for any damages that may result from your use of the program.

To use this program, you must create a new C++ application in Xcode with the following code and build it. Note that you must have Boost::filesystem libraries installed and linked to the project in the project settings, as well as including the Boost directory in the header search paths, before you build it.

After building, create a folder called LoginWallpapers within your /Library directory, and put all the wallpapers in there. Then, create a file called lwwcdquotes.txt within /Library/Preferences, and put all the quotes in there, each on different lines.

Then, you must make the program a Startup Item so that it launches at every startup. To do this, go to /Library/StartupItems (if it is not created already, then create it). Create a folder called lwwcd (you may need admin privileges). In the lwwcd folder, place your built program (make sure it is called "lwwcd"), and then create a new file in the folder, called "StartupParameters.plist". The contents of that file should be as follows:

		<?xml version="1.0" encoding="UTF-8"?>
		<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
		<plist version="0.9">
		    <dict>
		        <key>Description</key>
		        <string>Login Window Wallpaper Changer</string>
		        <key>OrderPreference</key>
		        <string>Late</string>
		        <key>Provides</key>
		        <array>
		                <string>Login Window Wallpaper Changer</string>
		        </array>
		        <key>Uses</key>
		        <array>
		                <string>SystemLog</string>
		        </array>
		    </dict>
		</plist>
	

After doing so, you may need to adjust the privileges on the lwwcd folder. See here for more details.

The program code below could probably be rewritten to avoid using Boost libraries, and probably in a shell script that doesn't require Xcode, but at the time of writing I felt more comfortable using C++. Note that this code was written for Lion but should work with later releases.

	//  Created by Jonathan Campbell on 11-08-04.

	#include <iostream>
	#include <sys/types.h>
	#include <dirent.h>
	#include <stdio.h>
	#include <sys/stat.h> 
	#include <string> // std::string
	#include <fstream> // std::ifstream, std::ofstream
	#include <vector>

	#include <boost/filesystem.hpp>
	#include <boost/lambda/bind.hpp>

	using namespace std;
	using namespace boost::filesystem;
	using namespace boost::lambda;

	int main (int argc, const char * argv[])
	{   
		srand( (unsigned) time(0) );

	    path the_path( "/Library/LoginWallpapers" );
    
		// get the number of wallpapers.
	    int numWallpapers = std::count_if(directory_iterator(the_path), directory_iterator(), bind( static_cast<bool(*)(const path&)>(is_regular_file), bind( &directory_entry::path, _1 ) ) );
	
		// select a random number
		int paperChoice = (int) ( rand() % ( numWallpapers - 0 + 1 ) + 0 );
		
		struct dirent *de=NULL;
		DIR *d = opendir("/Library/LoginWallpapers");
		if (d == NULL)
		{
			cout << "Couldn't open /Library/LoginWallpapers/ directory." << endl;
			return 1;
		}
    
		int count = 0;
		string filename = "";
		while(de = readdir(d))
		{ // get the filename of the wallpaper corresponding to the random number.
	        if (strcmp(de->d_name, ".") == false || strcmp(de->d_name, "..") == false) continue;

	        count ++;
    	
	        printf("%s\n",de->d_name);
			if (count == paperChoice) { filename = de->d_name; break; }
		}
    
	  	closedir(d);
    	    
		struct stat stFileInfo; 
	  	int intStat; 
    
	  	// find out if we made a backup of the original login window background already 
	  	intStat = stat("/Library/LoginWallpapers/original.png",&stFileInfo); 
	  	if(intStat != 0)
		{ // file doesn't exist (original), so back it up.
			system("sudo mv /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/NSTexturedFullScreenBackgroundColor.png /Library/LoginWallpapers/original.png");
		}
	    else cout << "original exists so no backup" << endl;
    	
		// we've saved the original, so copy the new wallpaper over the old.
		string command = "sudo cp -f \"/Library/LoginWallpapers/" + filename + "\" /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/NSTexturedFullScreenBackgroundColor.png";
		system(command.c_str());
	
		// now we want to edit the plist file to add a random quote. first, get the quotes from a file.
	
		std::vector<string> quotes;
		std::ifstream loadf;
	
		cout << "Opening quotes file... ";
		loadf.open("/Library/Preferences/lwwcdquotes.txt");
		if (loadf.is_open()) {
			cout << "loading quotes... ";
			while ( !loadf.eof() ) {
				string tempQuote;
				getline(loadf, tempQuote);
				quotes.push_back(tempQuote);
			}
	        quotes.pop_back();
			loadf.close();
			loadf.clear();
			cout << "done."<< endl;
		}
		else
		{
			cout << "could not open quote file!";
			return 1;
		}
	
		// we got the quotes... now select one at random.
		int quoteChoice = (int) ( rand() % ( quotes.size() - 0 + 1 ) + 0 );
		string quote = quotes.at(quoteChoice);
		
		// now to edit the file...
		string commandTwo = "sudo defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText \"" + quote + "\"";        
		system(commandTwo.c_str());
	
		return 0;
	}

Bela Lugosi's dead
The bats have left the bell tower
The victims have been bled
Red velvet lines the black box

Bela Lugosi's Dead, Bauhaus