mgetty
worksTo help you understand how mgetty works, here is an example of what happens in various circumstances when you use it to control a modem connected to a serial line, e.g. /dev/tty2a.
When the computer is booted, the operating system starts the init
process, which is responsible for making sure that gettys are running on
the appropiate i/o devices, e.g. virtual terminals, serial lines and
modems. init
reads its configuration file, /etc/inittab (on
System V), which tells it that the line /dev/tty2a should be
controlled by mgetty. It then creates an entry in /etc/utmp
(login
needs this, that’s why you can’t log in if you try to start
mgetty by hand), and forks a new mgetty
process, using the command
line specified.
When mgetty is started, it first checks if a valid lock file held by another process exists. If it does, this means that the port is in use, and mgetty will wait until the lock file goes away. Invalid lock files, e.g. for nonexistent processes (“stale” locks), are ignored.
Once the port is free, mgetty creates its own lockfile, initializes the
modem and removes its lock file again. Then it waits for something to
happen on the port. Note that it does not read any characters, it
just checks if there are any available for reading by using poll()
or select()
.
There are two possibilities once characters arrive, either a different
program (e.g. uucico
) has started dialing out or a ‘RING’ was
sent by the modem. In the first case, mgetty should leave the port
alone. This is easy if the program dialing out has created a valid
lock file: mgetty will find it, wait for it to go away and then exit (which
will cause init
to start a fresh mgetty
process, which will
then wait for the next call).
In the second case, when there is no lock file, mgetty assumes that
the phone is ringing, creates a lock file and reads the characters
available. If it finds a ‘RING’, it picks up the phone by sending
‘ATA’ and waits for the ‘CONNECT’ message. If the caller is
a fax machine, it saves the fax in the directory FAX_SPOOL_IN
(usually /var/spool/fax/incoming) and exits. If it is a modem,
it prints /etc/issue and displays a login prompt. Once it has
received a login string, it calls /bin/login
and lets it handle
things from here. login
will read the password and will then
start the user’s login shell, uucico
, a dialup SLIP link or
whatever, but mgetty doesn’t care about that. The lock file remains so
that no other programs will try to use the modem while somebody is logged in.
(If the login.config configuration file is used, mgetty can also call
other login programs than /bin/login
. See below for more details)
Once mgetty has terminated for whatever reason, init
might
reinitialize the port (this is why mgetty waits for lock files to go
away instead of quitting immediately) and will then start a new
mgetty
process, which will remove lock files left over from the
last login.
The lock file handling is tricky, but very important. It is essential that all programs that use the modem agree on one locking protocol, otherwise one program might not know that the modem is in use and will try to dial out anyway. A typical lock file is a file called /var/spool/lock/LCK..ttyxx, containing the process ID (PID) of the process currently using the modem. Other processes can read it and tell if the lock file belongs to an existing process or if it is “stale” and can be removed. This will obviously not work if the processes look for lock files in different places, or if one of them writes its PID in ASCII and another one tries to read it as a binary number (while mgetty and sendfax do not care whether foreign lock files are written in binary or ascii format, other programs do! mgetty can sometimes detect this problem, and will then log a warning).