Whoever looked at /etc/motd on ubuntu and thought, HEY, I KNOW WHAT THIS NEEDS – SHELL SCRIPTS! can kindly go die. Seriously? /etc/update-motd.d?

Ubuntu introduced the update-motd framework, by which the motd(5) is dynamically assembled from a collection of scripts at login.

…Okay, great. Where’s /etc/default/STOP_IT?

You know what’s even better then making something overcomplicated? Changing decades of expected behavior and not providing a way to, say, opt out. I don’t want to run a fuckload of stupid shell scripts every time I login that do super informative tasks like telling me the IP address assigned to my loopback device. I also don’t want to be told that I should use Landscape, or that there are 83 processes running on my machine.

Still, I could accept all of this if you could just make it go away….but you can’t.

root@tessier:~# cat > /etc/motd FUCK YOU

Nope….still there.

Want to know what’s even better? Deprecating /etc/motd and not updating its own manpage:

NAME motd - message of the day DESCRIPTION The contents of /etc/motd are displayed by login(1) after a successful login but just before it executes the login shell. The abbreviation "motd" stands for "message of the day", and this file has been traditionally used for exactly that (it requires much less disk space than mail to all users). On Debian GNU/Linux this file is a symbolic link pointing to /var/run. The contents of this file are regenerated upon every system boot based on the contents of /etc/motd.tail.

Way to win, guys!

It would be fine, completely fine, if this was just some cron job that could just be disabled (preferably with an /etc/default switch!). I could live with that. It’s reasonable behavior. Before Lucid, that was basically what was happening:

NAME update-motd - Automatically update the message-of-the-day (MOTD) SYNOPSIS update-motd [--disable|--enable|--force] [d|hourly|daily|weekly|monthly] OPTIONS --disable Prevent update-motd from running. This is useful for temporarily disabling automatic updates of /etc/motd by the /etc/cron.d/update-motd cronjob. Note that this regenerates a base MOTD without the update-motd additions, and then exits.

But, no, no, this is far more insidious. /etc/motd was sooooo 1980, bro!

Regular files are for losers, don’t you want to use w3m to update your MOTD with headlines from Google News? Shit, I mean, why use a plain file when you can use a PAM module?

So, here it is, in login and sshd:

# Prints the motd upon succesful login # (Replaces the `MOTD_FILE' option in login.defs) session optional pam_motd.so

Okay, disabling that results in nothing being printed. And hey, the manpage for pam_motd helpfully says:

NAME pam_motd - Display the motd file SYNOPSIS pam_motd.so [motd=/path/filename] DESCRIPTION pam_motd is a PAM module that can be used to display arbitrary motd (message of the day) files after a successful login. By default the /etc/motd file is shown. The message size is limited to 64KB. OPTIONS motd=/path/filename The /path/filename file is displayed as message of the day.

….Uh oh. /etc/motd is shown by default? That doesn’t sound right! Well, maybe the module will actually accept the option its manpage advertises:

session optional pam_motd.so motd=/etc/motd

Hahaha! Of course not! Why would that work?! I still get a bunch of shit output from shell scripts.

Okay, fine. Now, I really want to know why:

root@tessier:/usr/src# locate pam_motd.so /lib/security/pam_motd.so root@tessier:/usr/src# dpkg -S /lib/security/pam_motd.so libpam-modules: /lib/security/pam_motd.so root@tessier:/usr/src# apt-get source libpam-modules Reading package lists... Done Building dependency tree Reading state information... Done Picking 'pam' as source package instead of 'libpam-modules' NOTICE: 'pam' packaging is maintained in the 'Bzr' version control system at: https://code.launchpad.net/~ubuntu-core-dev/pam/ubuntu Please use: bzr get https://code.launchpad.net/~ubuntu-core-dev/pam/ubuntu to retrieve the latest (possibly unreleased) updates to the package.

…At this point, words fail me.

But, hey, let’s just take a look at the source, first. I want to know what’s going on, at least. It seems really unlikely that pam_motd is just blithely ignoring its options:

PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { int retval = PAM_IGNORE; int fd; const char *motd_path = NULL; char *mtmp = NULL; if (flags & PAM_SILENT) { return retval; } for (; argc-- > 0; ++argv) { if (!strncmp(*argv,"motd=",5)) { motd_path = 5 + *argv; if (*motd_path != '\0') { D(("set motd path: %s", motd_path)); } else { motd_path = NULL; pam_syslog(pamh, LOG_ERR, "motd= specification missing argument - ignored"); } } else pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);

…Huh. Okay, looks completely reasonable. Now, for shits and giggles, let’s check out that “updated” source, on the chance it’s different. I install bzr, and dutifully ask it to fetch what I need:

bzr get https://code.launchpad.net/~ubuntu-core-dev/pam/ubuntu Branched 836 revision(s).

….Did that really just take as long as I thought? This machine has a gigabit connection to the Internet. I must be imagining something.

time bzr get https://code.launchpad.net/~ubuntu-core-dev/pam/ubuntu Branched 836 revision(s). real 0m42.193s user 0m10.690s sys 0m0.290s

….Okay, I wasn’t imagining something. It must have downloaded a TON of source!

root@tessier:/usr/src/ubuntu# du -sh 19M .

…Oh. I guess not. But, hey, fuck git, or something.

Still! Finally, now we have the Magic Ubuntu Source, which may or may not be the same as the APT Source. Why there isn’t an apt-get magicubuntusource is beyond me.

But, hey, at least Ubuntu’s APT is kind enough to tell me I may need to not use it.

On further examination, the source for the file is the same. Okay, I guess my bone to pick is somewhere else. Let’s look at the patches getting applied as part of the dpkg build process:

Patch for Ubuntu bug #399071 Provide a more dynamic MOTD, based on the short-lived update-motd project. Authors: Dustin Kirkland Upstream status: not yet submitted Index: pam-1.0.1/modules/pam_motd/pam_motd.c

Oh. I see what you did there.

Looking at the patches, suddenly, I am enlightened:

/* Run the update-motd dynamic motd scripts, outputting to /var/run/motd. If /etc/motd -> /var/run/motd, the displayed MOTD will be dynamic. Otherwise, the admin can force a static MOTD by breaking that symlink and publishing into an /etc/motd text file. */

Huh. Okay then. Guess I’ll just go “publish” into my text file.

root@tessier:/etc# rm -rf motd && echo "DO I WORK NOW??" > /etc/motd

[aisling:~]$ ssh tessier DO I WORK NOW???? Last login: Tue Oct 19 13:47:20 2010 from pool-98-110-153-141.bstnma.fios.verizon.net

Well, THAT was a great usage of my time.

So…the best way to fix the pernicious issue of displaying /etc/motd to the end user (read: cat) was 1) to make a PAM module responsible for it, 2) get rid of the “old way” of updating it (cron job), and last but not least, 3) add a completely undocumented behavior (if /etc/motd is a symlink, it is dynamic) that contradicts the man page for said module.

I’m going back to blaming Ubuntu. I also need to step out of the room and have an aneurysm now.