ALINK="#FF0000">
LINUX GAZETTE
[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]

"Linux Gazette...making Linux just a little more fun!"


Make Your Virtual Console Log In Automatically

By Bryan Henderson


When you boot Linux, do you get a "login:" prompt on a bunch of virtual consoles and have to type in your username and password on each of them? Even though you're the only one who uses the system? Well, stop it. You can make these consoles come up all logged on and at a command prompt at every boot.

In case you're thinking that password prompt is necessary for security, think again. Chances are that if someone has access to your console keyboard, he also has access to your floppy disk drive and could easily insert his own system disk in there and be logged in as you in three minutes anyway. That password prompt is about as useful as an umbrella for fish.

Introduction

The method I'm going to describe for getting your virtual consoles logged in automatically consists of installing some software and changing a few lines in /etc/inittab. Before I do that, I'll take you on a mind-expanding journey through the land of getties and logins to see just how a Unix user gets logged in.

First, I must clarify that I'm talking about virtual consoles -- those are text consoles that you ordinarily switch between by pressing ALT-F2 or CTL-ALT-F2 and such. Shells that you see in windows on a graphical desktop are something else entirely. You can make those windows come up automatically at boot time too, but the process is quite a bit different and not covered by this article.

Also, consider serial terminals: The same technique discussed in this article for virtual consoles works for serial terminals, but may need some tweaking because the terminal may need some things such as baud rate and parity set.

How Logging In Works

Historical Background

In the traditional Unix system of old, the computer was in a locked room and users accessed the system via terminals in another room. The terminals were connected to serial ports. When the system first came up, it printed (we're back before CRT terminals -- they really did print) some identification information and then a "login:" prompt. Whoever wanted to use the computer would walk up to one of these terminals and type in his username, then his password, and then he would get a shell prompt and be "logged in."

Today, you see the same thing on Linux virtual consoles, though it doesn't make as much sense if you don't think about the history.

Getty

Let's go through the Linux boot process now and see how that login prompt gets up there.

When you first boot Linux, the kernel creates the init process. It is the first and last process to exist in any Linux system. All other processes in a Linux system are created either by init or by a descendant of init.

The init process normally runs a program called Sysvinit or something like it. It's worth pointing out that you can really run any program you like as init, naming the executable in Linux boot parameters. But the default is the executable /sbin/init, which is usually Sysvinit. Sysvinit takes its instructions from the file /etc/inittab.

To see how init works, do a man init and man inittab.

If you look in /etc/inittab, you will see the instructions that tell it to start a bunch of processes running a getty program, one process for each virtual console. Here is an example of a line from /etc/inittab that tells init to start a process running a getty on the virtual console /dev/tty5:

c5:235:respawn:/sbin/agetty 38400 tty5

In this case, the particular getty program is /sbin/agetty. On your system, you may be using /sbin/mingetty or any of a bunch of other programs. (Whatever the program, it's a good bet it has "getty" in its name. We call these getties because the very first one was simply called "getty," derived from "get teletype".)

Getty opens the specified terminal as the standard input, standard output, and standard error files for its process. It also assigns that terminal as the process' "controlling terminal" and sets the ownership and permissions on the terminal device to something safe (resetting whatever may have been set by the user of a previous login session).

So now you can see how the login prompt gets up on virtual console /dev/tty5. The kernel creates the init process, running Sysvinit. Sysvinit, as instructed by its /etc/inittab file, starts another process running a getty program, with parameters identifying /dev/tty5. The getty program prints "login:" on /dev/tty5 and waits for someone to type something.

Login

After you respond to getty's login prompt, getty execs the program login. (Actually, you can usually tell getty to execute any program of your choice, but /bin/login is normal); i.e. getty replaces itself with login. It's still the same process, though.

Bear in mind that this process was created by init, which is owned by the superuser. So this process, which is now running login, is also owned by the superuser.

The first thing login does is ask for your password. When you type it in, login determines if it's right or not. Assuming it is, login then proceeds to do the following things:

The next thing login does is exec your shell program (which can really be any program, but is normally a command shell, e.g. /bin/bash). I.e. it replaces itself with the shell program.

Login looks up your username in the file /etc/passwd to find all the information it needs, such as your password, uid, and shell program.

The Shell

The shell proceeds to run the system shell profile (/etc/profile) and your personal profile (typically the file .profile in your home directory), and ultimately display a command prompt ($ or %) on the terminal. This is the point at which you consider yourself logged in, and our journey is complete.

Automating Login

Ok, that was fun, but our purpose in this article is to explore a new kind of login -- an automated one.

Our goal is to do all those things that init, getty, login, and the shell do except without the username and password prompt.

There are a bunch of ways to do that, but I wrote the program qlogin to do it all very simply. qlogin performs the functions of getty and login. It gets called by init, like getty, and its last act is to call the shell program, like login.

So to set this up, all you have to do is replace the /etc/inittab line shown above with one something like this:

c4:235:respawn:/sbin/qlogin /dev/tty5 bryanh This logs in username bryanh to virtual console /dev/tty5 at boot time instead of going through the username and password prompt business.

Note that the "respawn" in the line above means that when the process ends, init will create a new one to take its place. In the traditional Unix system, that means when you log out of your shell, which causes the process to end, a new getty runs and the terminal gets a login prompt for the next user. In the qlogin case, it means when you log out of your shell, a new one comes up immediately to take its place. So if you want to reset a bunch of stuff in your login session, typing logout is a good way to do it.

Starting Slowly

You probably shouldn't install qlogin and then just dive right into changing all your getty's to qlogin's in /etc/inittab and reboot and see if it works. That would be pretty optimistic.

Diversity Is Good

First of all, I recommend that you not convert all your virtual consoles to qlogin ever. Use the tried and true getty/login system on at least one virtual console so that if you mess up something with qlogin, you can get into another virtual console and fix it. And if you mess up something with getty or login, you can get into another virtual console via qlogin and fix that!

Run It From A Shell

Before you go editing /etc/inittab and messing around with the init task, you should convince yourself you know what you're doing by running qlogin from a shell. Watch qlogin work with your own eyes. The problem with init, besides the fact that it's a very important process you don't want to break, is that it doesn't have a standard error file -- no way to give you error messages to tell you why it can't do what you thought you told it to do.

Usually, the indication from init that something is wrong is "id X spawning too fast. Disabled for 5 minutes." What that means is that the program (e.g. qlogin) that you told init to run runs into trouble and terminates immediately. Because it's a "respawn" entry, init simply generates a new process running the same program. And these processes start and crash repeatedly. init notices this and suspends the "respawn" procedure for 5 minutes in hopes that someone fixes the problem. But why is the program immediately crashing? Nobody knows except that program, and it's not telling.

So just invoke qlogin from a shell prompt, with the same arguments with which you would have init invoke it. Now qlogin will issue error messages if it crashes.

Of course, the shell from which you invoke qlogin had better be a superuser shell. Otherwise, I can tell you right now what your error message will be.

One Difference - Controlling Terminal

One tricky aspect of running qlogin from a shell is the matter of the controlling terminal. The login process you generate with qlogin will use the terminal you specify as its input and output terminal, but its controlling terminal will be the terminal where you typed "qlogin."

The reason for the difference is this: If you're a Linux process, when you open a terminal for input and you don't already have a controlling terminal, that terminal becomes your controlling terminal. But if you already have a controlling terminal, you just keep it. init does not have a controlling terminal, so neither does the qlogin child process it creates. But login shells have controlling terminals, and therefore the child processes you create by typing commands (such as qlogin) at shell prompts do too.

Where you will see the difference is when you type Control-C: It won't do anything. Control-C typed on a standard input device has no effect other than to include a Control-C character in the input stream. But Control-C on a controlling terminal causes the foreground processes associated with that terminal to get a SIGINT signal, which has the familiar effect of terminating the program.

All I'm saying is that if you log yourself on to /dev/tty5 by typing qlogin /dev/tty5 ... on /dev/tty1, then Control-C on /dev/tty5 will have no effect. Put the same qlogin /dev/tty5 ... command in /etc/inittab, and Control-C on /dev/tty5 will work fine.

Note: to be pedantic, I must admit that in saying Control-C, I am assuming that the terminal's TTY properties are set such that Control-C is the "interrupt character." You could use stty to make the interrupt character something else or not have one at all.

About Qlogin

qlogin isn't on your system, so you'll have to install it. Get it from ibiblio.org and follow the simple installation instructions. As you will find, a prerequisite is the Perl extension called User::Utmp, which probably also is not on your system, so you'll have to follow the instructions to get and install that too.

qlogin is written in Perl and is quite simple. So you can see for yourself the steps involved in logging in a user. And you can modify it to suit your particular needs.

One of the nice things about qlogin is that it's so basic that it doesn't even rely on configuration files. You can tell it everything it needs to know to log you in just with command line parameters. You can override your /etc/passwd file or log in a user that isn't even in /etc/passwd. You're in control.

Let's look at qlogin's options:

--command
the "command" (a kind of sloppy way to say a program plus its arguments) to run after qlogin exits. /bin/bash is typical.
--arg0
the Argument Zero value for the program that runs after qlogin exits, which is what shows up in a ps display.
--uid
the numeric user id for the process.
--gid
the numeric group id for the process.
--homedir
the home directory and initial current working directory for the process.
--utmp/--noutmp
determines whether qlogin logs the session in the user accounting database (utmp file).

And qlogin arguments specify the terminal device to use for the process.

All the details of using qlogin are in the documentation that comes with it.

Other Things You Can Do With Qlogin

So now you know how to make logged in shells come up automatically on the various virtual consoles. But with a simple change to the procedure, you can make other programs run automatically on certain virtual consoles or on serial terminals. Imagine a virtual console that runs the top system monitor program all the time. Just say

qlogin /dev/tty5 root --command=/bin/top --noutmp

Maybe your system is a point of sale system for a store. The terminals are serial terminals at the cashier stations. Cashiers don't want to log in to Linux and don't want to see a shell. If the POS program is /usr/local/bin/pos, you could do this:

qlogin /dev/ttyS1 cashier --uid=500 --gid=500 --command=/usr/local/bin/pos --arg0=POS --homedir=/ In this case, the pos program probably needs to do some initialization of the serial port, such as setting its baud rate. In the traditional Unix login model, getty does that before it puts up the login prompt.

Foreground Processes

[Your Editor asked Bryan, "I thought the system didn't have a concept of a foreground process; that's a fiction of the shell." Here's his response. --Iron]

I used to think that too; probably because of something I read in Bash documentation. However, the Linux kernel defines a "foreground process group." Every controlling terminal has a foreground process group. By default, it is the process group of the process that originally opened the terminal. But a process can set the foreground process group to any process group in its session with an ioctl.

I took a slight liberty in the article in referring to "foreground processes," which I think can easily be interpreted as "processes in the foreground process group."

I believe the only significance of the foreground process group (the kernel entity) is that the processes in that process group get the control-C and hangup signals.

Bash's job control uses that ioctl to make whatever your "foreground job" is the foreground process group for your terminal. That's why when you put something in the background, like "grep abc * &", control-C does not kill it. If you want to kill it, you have to "fg", causing Bash to ioctl it to the foreground, then Control-C.

Many years ago, before the Web when terminals mattered a lot more, I spent many hours combing through kernel code and experimenting to figure out process groups, sessions, controlling terminals, job control, SIGINT, SIGHUP, and the like. I could write a long article on it, but I think it's really arcane information.

[Readers: if you want to take him up on his offer for such "arcane information", ask in the Mailbag. Also remember that the Mailbag is where you can ask for articles on any other topic. --Iron]

Bryan Henderson

Bryan Henderson is an operating systems programmer from way back, working mostly on large scale computing systems. Bryan's love of computers began with a 110 baud connection to a local college for a high school class, but Bryan had little interest in home computers until Linux came out.


Copyright © 2001, Bryan Henderson.
Copying license http://www.linuxgazette.net/copying.html
Published in Issue 69 of Linux Gazette, August 2001

[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]