Cover V02, I05
Figure 1
Figure 2
Figure 3
Figure 4
Figure 5
Listing 1
Listing 2
Listing 3
Listing 4


Monitoring Login Activity

Chris Hare

I manage a technical group which has responsibility for administering corporate systems. Because the systems include a machine which runs anonymous access through several different methods, the group has to be concerned about who is accessing our systems. Similarly, we are periodically concerned about the login/logoff session activity which takes place. As our workplace is primarily an SCO shop, we could resort to using C2 security and the audit facilities which exist there. But we don't.

This article was born out of e-mail with another system administator who needs to be able to track login and logoff activity for later review. The article discusses several different methods which could be used. It does not touch on the use of C2 security, as a later article will discuss this environmment in detail.

The Login Process

The process of logging onto a UNIX system starts at system startup. All versions of UNIX have a system daemon named init which is responsible for starting system daemons and the getty process.

getty is responsible for printing a login message and collecting a user name. Once the user name is collected, getty executes login, which then prompts for a password. login validates the password/login name combination, and, if the combination is valid, creates an entry for the login in the /etc/wtmp file, then executes the user's login shell. If the login/password combination is incorrect, login asks for a login name again. (For more information on the login process, including password validation, see "How UNIX Password Controls Work," Sys Admin, vol. 1, no. 1, May/June 1992).

Using who

An understanding of the options and capabilities of the who command is essential to this discussion, largely because of its interaction with the /etc/wtmp file (which will be discussed in detail later). In this section, I describe the various options of the who command and provide example output.

The who command provides the following options (see Figure 1 and Figure 2 for more information on these options):

r -- run level. The "run" state of the machine. The most common run states are:

0 off
1/s single user or system maintenance mode
2 multi-user mode
3-5 other renditions of multi-user mode

b -- boot time. The date and time of the reboot.

t -- time changes. Records written when the date/time of the system is updated through some process.

p -- processes other than getty or users. Requires reading the /etc/wtmp file.

l -- login processes. Requires reading the /etc/wtmp file.

u -- useful information.

The /etc/wtmp file

The /etc/wtmp file is a historical record of all of the login activity on the system. In fact, a number of events are included in this file, and these can be listed using the who command. Listing 1 shows the structure associated with the /etc/wtmp file.

The entries which are included in this file include

  • Run-level changes -- These are almost exclusive to System V, as there are multiple run levels in this architecture, whereas BSD environments have multi-user, single-user, and off.

  • Boot time -- These records list the date/time when the system was booted.

  • Time changes -- When the system administrator or a time management program such as NTP (Network Time Protocol) services adjusts the system clock, two entries are made. One indicates the old time; the other, the new time.

  • Processes spawned by INIT -- Any process which is started by the init process will be recorded here.

  • Login process -- When a getty process is waiting for a login to occur, a record is written to indicate the state of the getty process.

    The information is stored in this file in binary form using the structure shown in Listing 1. As a result, the easiest way to look at the contents of /etc/wtmp is through the who command.

    Logging in and out with the Bourne and Korn Shells

    When a user logs in to a UNIX machine with a login shell of /bin/sh or /bin/ksh, the system file /etc/profile is executed before the file .profile in the user's $HOME directory.

    Since /etc/profile is executed for all users, you can put lines in this file to record the login. For example

    echo "LOGIN :`logname`:`tty`:`date`" > /usr/adm/logins

    will record the login. The information included is the login name, the tty where the login took place, and the date. The command above would generate the following output in the file /usr/adm/logins:

    chare:/dev/w2:Sun Jun 13 17:48:16 EST 1993

    Unlike the C shell, the Bourne and Korn shells have no built-in mechanism for tracking logouts. However, it's possible to fool the shell by having it trap the signal which signifies a logout, which is signal 0. The mechanism for accomplishing this is the shell's built-in signal handler. The command is trap, and the syntax used is

    trap "command to execute" signal ...

    Inserting this command in /etc/profile, as follows,

    trap "/usr/local/checkout `logname` `tty`" 0

    causes the command checkout to be run a signal 0 is received. At this point you may be wondering why I don't use a sub-shell. Signal handlers are not passed to child processes, so they will not see this handler. A good approach is to set the user's login name to a variable such as LOGNAME and the terminal being used to a variable named TTY. This increases the speed at which the logout is executed.

    So what is /usr/local/checkout? It could be as simple as the line used in /etc/profile for logging in, with a couple of changes:

    echo "LOGOUT:$LOGNAME:$TTY:`date`" > /usr/adm/logins

    Listing 2 shows a sample /etc/profile file with code added to support the login and checkout scripts. Listing 3 shows the checkout program, while Figure 3 shows the output of the login and logout programs in /usr/adm/logins.

    Logging in and out with the C shell

    For C shell users, the same approach is applicable. The primary difference to note is that /etc/profile is not executed, but /etc/cshrc is. The same syntax shown above for the /etc/profile applies here; the one minor difference is that it would be prudent to include the '!' after the '>' signs. This disables the no-clobber feature of the C shell, where it would normally be an error to append to a file if the file didn't already exist. An example is

    echo "LOGIN :`logname`:`tty`:`date`" >! \

    You can accomplish this through the use of the .logout file in the user's $HOME directory. This is somewhat inefficient as it means duplicating a small amount of information across all of the users on the system. The amount of information isn't really significant, but it is something to be considered.

    Again, the code fragment shown below, which is a variation of the /usr/local/checkout program, can be used for the .logout file.

    echo "LOGOUT:$LOGNAME:$TTY:`date`" >! \

    Again, note that the '!' is included to prevent problems with the no-clobber variable in the C shell.

    Report Generators

    The only reason for collecting information is so that you can look at it later. The shell script shown in Listing 4 takes the information from /usr/adm/logins and presents it in a meaningful fashion.

    This shell script is a simple one. It sorts /usr/adm/logins before processing, using the sort sequence

    1. username 2. direction (LOGIN/LOGOUT) 3. tty

    I chose this sequence to maintain the connectivity of logins to logouts where possible. Sample output of the program in Listing 4 is in Figure 5. This isn't the most complex reporting program in the world, but it illustrates the principle.


    While there are many ways of tracking login activity -- including the methods described here, as well as process accounting, security system auditing, and other services provided by individual vendors -- there are a few specific things to keep in mind.

    In order for the implementation discussed to be of value, the /usr/adm/logins file must be world writeable. This means that anyone could edit the file to change the contents. Furthermore, there are situations where the trap will not be set up and executed when the user logs out.

    One such case is with the AT&T UNIXPC and 3B1 series of computers, which have a graphical interface. This interface doesn't work like a shell, and therefore will not execute the trap set up in /etc/profile. In these cases, there will be no corresponding logout record, as illustrated in Figure 4.

    Some readers may ask why I didn't simply have /etc/profile execute, run a child shell for the user's interactive session, and, when the user exits with Control D, continue with /etc/profile, so that the logout information would be recorded. The problem here is that this would create an additional (and unncessary) process on the system. And while such a process would not consume much in the way of system resources, it would occupy a process slot in the process table, which can be a problem if you are losing 25 or more process slots for these activities. It might become necessary for the system administrator to make the process table bigger, and thereby increase the size of the kernel in RAM, thus decreasing the amount of usable RAM for user processes.

    For more information on system monitoring, see the articles "Getting the Info: u386mon" in Sys Admin, vol. 1, no. 3 (Sept/Oct 1992), and "Getting the Info: sar" in Sys Admin, vol. 1, no. 4 (Nov/Dec 1992). For further information on Shell Programming, see your system documentation, and for a specific discussion of a login session billing program, see UNIX/World, October 1986.

    About the Author

    Chris Hare is the Technical Services Manager for Choreo Systems, Inc. He has worked in the UNIX environment since 1986 and in 1988 became one of the first SCO authorized instructors in Canada. He teaches UNIX introductory, system administration, and programming classes. His current focus is on networking, Perl, and X. Chris can be reached at, or, which is his home.