[H-GEN] motd

Anthony Towns aj at azure.humbug.org.au
Fri May 22 08:35:13 EDT 1998


On Thu, May 21, 1998 at 02:21:53PM +1000, Paul Gearon wrote:
> Is there some way to run /usr/games/fortune for the when 
> /etc/motd is read?  

Like just about everything Unixy, there's More Than One Way To Do
It.

Even before you introduce Perl into the equation.

The first option, and the way most people would do it, is to add
something like
	echo
	/usr/games/fortune
	echo
into /etc/profile (for bash and sh users) and /etc/csh.login (for
csh and tcsh (?) users).

But that's really quite boring, and lacks that je ne sais quoi to
make this post really worthwhile.

Byron's already posted his infamous named pipe fortune hack, so
I guess that's out of the equation too, as horribily lovely as
it may be.

Well, there's one other way of doing it.

It's a powerful way. It's a way that once done, is hard to get
rid of by accident -- you can't accidently rm a file and have to
do it again, and you don't have to worry about keeping some
while loop running to keep your pipe full.

It's a way that involves C programming.

It's obsessive.

It's compulsive.

It got deleted when I got logged off cello at lunch today.



But it's not only all of that...

It's also worth repeating.


So what exactly *are* we going to do? Well, my friends, what we're 
going to do is make use of the underlying principles of Free 
Software, and we're going to extend login(1) to directly support
fortune(1).

As it always should've.

Now I suppose this is going to strike some of you as an unusual 
sort of thing to do. ``Modify a program just coz I want a fortune?
Isn't that kind of, well, obsessive compulsive?'' I can already
hear you stuttering in abject disgust.

Well, yeah. It is. But hey. It's not like I've got any assignments
due tomorrow. Nor the day after, in an incredible stroke of luck,
so what the hell?

Anyway, the first thing to do is to get the source and have a look
through it. [0] [2]

And the first thing we look for is something about motd's. [3]

And the first thing we find is that, apart from the boring Makefiles
and docs and junk like that, is that the only *interesting* files [4]
that have much to do with motd's are:
	./libmisc/motd.c
	./src/login.c
	./src/su.c

And, with the luck of someone who's very lucky indeed, we find that
two of those three files (the latter two, in particular), only
refer to motd's by calling a function that, wonder of wonders, is
defined in the first.

So now we take a deep breath and start looking at some C code.

Oh. 

Oh Yes. 

Oh. Oh. Oh ghod. Oh. Oh, my. Oh, yes. Oh _yes_. Oooohhhh... Aaaaah. 
Ohohoh. Aaaaaaa.. OH Yes. OH MAN YES! OOOOHHHHHHHHH YYYYEEEEEEEESSSS! 
Oh yeah, oh baby yeah.

Aaaaahhhh.


Errr.

Yeah.

And we find to our, errr, restrained joy, that there's exactly one
function in motd.c, that's it's the `void motd(void)' thingo that
login.c and su.c wanted, and that more than that it's only a couple
of dozen lines.

Well. Apart from all the comments, and disclaimers, and terms and
stuff.

But like any good compiler, the competent hacker ignores anything
that begins with a /* and ends with a */.

For that matter, so does any incompetent hacker.

And most wannabes.

And, I'd not hesitate to imagine, a goodly number of engineers,
run of the mill code-grinders, wizards, gurus, and just about
everyone else who churns out code for pleasure or profit.

Well, with the exception of dedicated academics of course.

And we're probably better off if we can get them reading and
critquing the commenting rather than letting them lose on
something that might actualy do something that the computer
sees.

Ugh.

Ummm, guys. Please, please, *please* comment your code. If not
for your own sake, do it for the children. Some day your nanny-
robot may have code that was *shudder* looked at by a *quiver*
by a *shake* by an... by an academic.

So anyway. We're basically left with something that looks like

void
motd(void)
{
        FILE    *fp;
        char    motdlist[BUFSIZ], *motdfile, *mb;
        register int    c;

        if ((mb = getdef_str("MOTD_FILE")) == NULL)
                return;

        strncpy(motdlist, mb, sizeof(motdlist));
        motdlist[sizeof(motdlist)-1] = '\0';

        for (mb = motdlist ; (motdfile = strtok(mb,":")) != NULL ; mb = NULL) {
                if ((fp = fopen(motdfile, "r")) != NULL) {
                        while ((c = getc (fp)) != EOF)
                                putchar (c);
                        fclose (fp);
                }
        }
        fflush (stdout);
}

And we don't really want to change any of that -- we don't want to
get rid of the motd (if we did, we could quite happily just set
/etc/login.defs:MOTD_FILE to empty, or empty the file /etc/motd), 
we just want to add a fortune after it.

So we want to add some code to do a fortune thingy after the i
	fflush (stdout);
line.

Now, to get the fortune thingy, we basically just want to run
/usr/games/fortune, and then keep going. The traditional way of
doing this is a fork-exec construct that looks something like:

	pid_t child;
	switch( child = fork() ) {
	  case -1: /* error, couldn't fork */
		break; /* silently ignore */
	  case 0: /* child process */
		execl( "/usr/games/fortune", "/usr/games/fortune", NULL );
		/* should never be reached, if it is, silently ignore */
		exit(0);
	  default: /* parent process, child == child's pid */
		/* wait for the fortune to happen, then continue... */
		waitpid( child, NULL, 0 );
		break;
	}

(see the manpages for fork(2), execl(3), and waitpid(2) to work out
what all this means. I did)

We probably also want to add a
	puts("");
before and after that block so we don't get our motd, our fortune
and our "Last login:" stuff all bunched up in a block, too, but
I'll leave minor cosmetic details for the gentle reader to worry
her or himself about.

Now that's not quite all we need to consider, because login(1) is
a setuid root program, so we need to be *very* careful that our
new login doesn't hideously compromise our system. A sensible thing
to do would be, for example, to drop root priveleges before exec'ing
fortune.

And of course, we really should check that fortune's actually *there*
before trying to run it and stuff, and it'd probably be nice to add 
an /etc/login.defs option to specify alternate locations for fortune,
or let you use a different program entirely or something. And it'd
probably be sensible to extend the man page and other stuff to 
actually describe all this.

But sensible isn't really what this email's about, and I'm not
going to be running this on *my* system, so really, what do I
care?

Then we go ahead and compile [5] and install our new login binary,
and there we are.

We have logins straight after our motd's. [6]

Bet you never guessed it was that easy, hey?

Cheers,
aj

[0] I know. Slackware and *BSD people are sitting there saying
    ``Well, that was hard. Stupid newbie package lusers get it so
easy these days.'' while those of you with commercial Unices are
thumbing through your wallets and chequebooks wondering, ``Sources?
Ouch. Can I afford to spend *that much* just for fortune?'' [1]

[1] I'm saving the RedHat jibes for bigger things. Be patient.

[2] $ dpkg --search `which login`
    $ dpkg --print-avail login
    ftp.questnet.net.au: 
      /pub/debian/dists/*/main/source/shadow.{dsc,diff.gz,orig.tar.gz}
    $ dpkg-source -x shadow.dsc

[3] find -type f | xargs grep -l "motd"

[4] Interesting \In"ter*est'ing\, adj 1. Of or relating to the C
    programming language [see also K&R, The Bible, Unix]

[5] $ fakeroot debian/rules binary-arch

[6] viz:

] azure login: aj
] Password: 
] Linux azure 2.0.33 #1 Fri May 15 19:45:40 EST 1998 i586 unknown
]
] Copyright (C) 1993-1998 Software in the Public Interest, and others
] 
] Most of the programs included with the Debian GNU/Linux system are
] freely redistributable; the exact distribution terms for each program
] are described in the individual files in /usr/doc/*/copyright
] 
] Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
] permitted by applicable law.
] 
] The use of COBOL cripples the mind; its teaching should, therefore, be
] regarded as a criminal offence.
]                 -- Edsger W. Dijkstra, SIGPLAN Notices, Volume 17, Number 5
]
] Last login: Fri May 22 22:28:00 on ttyp3 from localhost.
] You have mail.
] 
] [aj at azure ~]$ 

-- 
Anthony Towns <aj at humbug.org.au> <http://azure.humbug.org.au/~aj/>
I don't speak for anyone save myself. PGP encrypted mail preferred.

      ``It's not a vision, or a fear. It's just a thought.''
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 434 bytes
Desc: not available
URL: <http://lists.humbug.org.au/pipermail/general/attachments/19980522/7f3438e9/attachment.sig>


More information about the General mailing list