Setting up a multi-user system with Linux
By Paul Dunne
I am writing this article in what I am pleased to call my library
(though it is really a living room). It is marvelously quiet - no
humming fans, no whirring disk drives - in fact, there is no computer
in the room at all. I am typing on a ancient Wyse 30 terminal,
linked to my Linux box in the office upstairs by ten meters of null
modem cable. One of the disadvantages of the personal computer is
that it really needs a room of its own, or at least a room with a
considerable portion of space given over to it and its paraphernalia.
This is clearly not an ideal way of using a computer: one would not
think of going to a special room to read a magazine, so why do so
when you wish to look at a web page? Linux's inherent multi-user
capabilities and its support for terminals offers an answer. In this
article, I shall describe how to set up a Linux box to support a
number of terminals.
How Linux talks to terminals: getty
A stand-alone Linux box already supports multiple terminals, due to
the virtual console support built into the kernel. Each of the
screens accessible on the console monitor through an Alt-Fkey
combination is treated as a separate terminal. This can be
illustrated by a `ps' listing, which should show some lines like this:
5831 p 5 S 0:00 /sbin/agetty 38400 tty5
Support for real terminals starts along similar lines. First, it is
necessary to tell the system to run a `getty' process on each port
to which a terminal will be attached. The ports would normally
be serial lines. A normal PC has only two of these, but there
are cheap multi-port serial cards available, which provide 4, 8,
16 or even more additional serial lines, while taking up only one
interrupt ( and an expansion slot on the motherboard, of course ).
I use a cheap clone of the AST Fourport card, which as the name
implies gives me four extra serial ports.
Configuring the serial ports
The extra serial ports must have corresponding devices created in
/dev, and these must be configured using the setserial program. The
devices may already exist; if not, creating them is simple. The mknod
command is used (look up the man page!) e.g.
mknod -m 666 /dev/ttyS4 c 4 68
Where c says it is a character special device (the alternative
is b for block, e.g. a disk), and the two numbers following the
device file name are the major and minor numbers respectively.
For serial input, the major number is 4; for serial output, 5.
The minor number is the port number plus 64 (you ask why? I don't
know!) The -m option, as you've probably guessed from the look of
it, sets their permissions on the file.
The following devices exist on my system. Note the major and
minor numbers. /dev/ttyS4-7 and /dev/cua4-7 are the control devices
for my additional serial lines.
crw--w--w- 1 root root 4, 64 Sep 24 19:44 /dev/ttyS0
crw--w--w- 1 root root 4, 65 Sep 20 19:42 /dev/ttyS1
crw-rw-rw- 1 root root 4, 66 Jan 23 1980 /dev/ttyS2
crw-rw-rw- 1 root root 4, 67 Sep 24 19:36 /dev/ttyS3
crw-rw-rw- 1 root other 4, 68 Nov 17 16:53 /dev/ttyS4
crw-rw-rw- 1 root other 4, 69 Nov 17 16:56 /dev/ttyS5
crw-rw-rw- 1 root other 4, 70 Nov 17 16:56 /dev/ttyS6
crw-rw-rw- 1 root other 4, 71 Nov 17 16:56 /dev/ttyS7
crw-rw-rw- 1 root tty 5, 64 Apr 1 1993 /dev/cua0
crw-rw-rw- 2 uucp staff 5, 65 Oct 7 21:42 /dev/cua1
crw-rw-rw- 1 root tty 5, 66 Apr 11 1993 /dev/cua2
crw-rw-rw- 1 paul staff 5, 67 Nov 21 09:16 /dev/cua3
crw-rw-rw- 1 root tty 5, 68 Sep 20 13:11 /dev/cua4
crw-r--r-- 1 root root 5, 69 Sep 20 13:12 /dev/cua5
crw-r--r-- 1 root root 5, 70 Sep 20 13:12 /dev/cua6
crw-r--r-- 1 root root 5, 71 Sep 20 13:12 /dev/cua7
The setserial program is essential to configure the additional
serial ports. The README file that comes with the source says it
all, really: "[setserial] allows you to look at and change various
attributes of a serial device, including its port, its IRQ, and
other serial port options." It comes with an rc.serial script
which with a little tuning will do everything you need.
In /etc/rc.local, I have the following lines:
if [ -f /etc/rc.serial ]; then
Add an entry for getty to use for your terminal in /etc/gettydefs.
Here is a sample of some entries, from my system (I got them from
the Serial HOWTO).
# 38400 bps Dumb Terminal entry
DT38400# B38400 CS8 CLOCAL # B38400 SANE -ISTRIP CLOCAL #@S @L login: #DT38400
# 19200 bps Dumb Terminal entry
DT19200# B19200 CS8 CLOCAL # B19200 SANE -ISTRIP CLOCAL #@S @L login: #DT19200
# 9600 bps Dumb Terminal entry
DT9600# B9600 CS8 CLOCAL # B9600 SANE -ISTRIP CLOCAL #@S @L login: #DT9600
If you want, you can make getty print interesting things in the
login banner. In my examples, I have the system name and the serial
line printed. You can add other things (again, this stuff is from the
@B The current (evaluated at the time the @B is seen) bps rate.
@D The current date, in MM/DD/YY.
@L The serial line to which getty is attached.
@S The system name.
@T The current time, in HH:MM:SS (24-hour).
@U The number of currently signed-on users. This is a
count of the number of entries in the /etc/utmp file
that have a non-null ut_name field.
@V The value of VERSION, as given in the defaults file.
To display a single '@' character, use either '\@' or '@@'.
Edit your /etc/inittab file to run getty on the serial port
(substituting in the correct information for your environment -
port, speed, and default terminal type):
S1:456:respawn:/sbin/getty ttyS1 DT9600 vt100
- Restart your system.
How Linux knows what to say: termcap/terminfo
This was the first attempt at providing Unix with a device-independent
interface for screen-handling. /etc/termcap is a simple text
file, containing terse, machine-friendly descriptions of terminal
capabilities.The idea is that the application queries the environment
to find out what type of screen it is writing to ( typically defined
in an environment variable called TERM or TERMCAP ), then looks up
the matching definition in the termcap file. Here is the termcap
definition I use for my Wyse 30's (I found it posted to
comp.os.linux.hardware some time ago):
# wyse 50 stuff -- extracted from a sparc13 termcap file -- jiw 9/4/95
# Notes by tpm seem to indicate 'wyse' entry works best ... so did
# setup on terminal for 'ADDSVP' emulation and Enhance ON. tpm notes:
# The following seems to be the best mode to run a Wyse-50 in. It works
# with Emacs using this termcap entry. Wyse mode seems to be a loser.
# Note that you have to manually set emulation mode to ADDSVP and turn
# ENHANCE on. --tpm
# Tab support, better is and rs, and wyse-nk added Jan85 by sun!gnu
# pd 23/10-del :am;del tabs entry
wyse-vp|wyse30|Wyse 30 in ADDS Viewpoint emulation mode with "enhance" on:\
:le=^H:bs:li#24:co#80:cm=\EY%+ %+ :cd=\Ek:ce=\EK:nd=^F:\
# This is the same as above, but with no keys. This makes vi ^F, ^B, work.
wyse-vp-nk|wyse-nk|wyse30|addsviewpoint|Wyse 30 in ADDS Viewpoint enhanced mode with cursor keys gone:\
# The Wyse-50 does not correctly emulate a Televideo 925.
vw|w9|wyse925|wyse-925|Wyse-50 emulating tvi925:\
A more efficient system developed at Bell Labs.
Look at the manual page for tic - the program that makes terminfo database entries from termcap descriptions.
Why you need both
Unless you have built all your applications yourself, and chosen only
those that conform to your chosen method of handling the screen, you
will likely have a mix of applications, some using termcap, some
How the terminal hears, and talks back: cabling
The cabling needed for a basic serial connection to a terminal is very
simple. Just three wires need to be connected, as follows:
RxD Receive Data 2 - 3 TxD Transmit Data
TxD Transmit Data 3 - 2 RxD Receive Data
GND Signal Ground 7 - 7 GND Signal Ground
This will work, but allows for no hardware handshaking. A full
null-modem configuration is as follows:
DCD Carrier Detect 1 - 20 DTR Data Terminal Ready
RxD Receive Data 2 - 2 TxD Transmit Data
TxD Transmit Data 3 - 3 RxD Receive Data
DTR Data Terminal Ready 4 - 6 DSR Data Set Ready
DTR Data Terminal Ready 4 - 8 DCD Carrier Detect
GND Signal Ground 5 - 7 GND Signal Ground
DSR Data Set Ready 6 - 20 DTR Data Terminal Ready
RTS Request To Send 7 - 5 CTS Clear To Send
CTS Clear To Send 8 - 4 RTS Request To Send
As my terminals could be configured to use no handshaking, as I
was fixing up my own cables with their appropriate connectors, and
as I hate soldering, I took the former route! It works just fine.
Coping with difficult terminals
My Wyse 30's are not the most modern of devices, and I could not
get a termcap / terminfo definition of them. Instead, I use their
ADDS Viewpoint emulation mode instead, and use definitions intended
for that terminal. This emulation appears to be less than perfect,
however, and I have some problems. Some applications, such as
emacs and some versions of vi (nvi in particular) are confused by
the auto scroll feature. Therefore, I need to use a vi clone other
than my usual nvi when I am working on a terminal. Also, the "less"
pager loses a line per page from the viewed file, so I had to put
up with using "more" instead. To set up all this automatically,
I have the following code in /etc/profile.
excerpt from /etc/profile:
# chose appropriate terminal settings
case $basetty in
ttyS*) export TERM=wyse-nk; alias vi='elvis'; export PAGER=more ;;
tty*) export TERM=linux ;;
For some reason, though, this alias doesn't work with applications
that get their information about what text editor to use from a file
e.g. MH with .mh_profile. To overcome this, I had to be a short
shell script (named "vi", natch!) into my personal bin directory,
and let that decide which real vi I should use. It's just the same
code as in /etc/profile.
So, at the end of it all, we have a cheap and simple way to set up a
multi-user system. I think that any REAL operating system has to
offer this capability (multi-user support just "slots in" on top of
multi-tasking, after all). Certainly, it has made my use of my Linux
box much more productive, by allowing me access to it from several
different locations in my house.