Date: Thu, 11 Sep 1997 10:26:17 +0000 (GMT)
From: Terry Lambert <tlambert@primenet.com>
To: nnd@itfs.nsk.su
Cc: current@FreeBSD.ORG
Subject: Re: PPP - why set CLOCAL for server ('-direct' mode) ?
Message-ID: <199709111026.DAA14233@usr05.primenet.com>
In-Reply-To: <5v7s4q$4ne@news.itfs.nsk.su> from "nnd@itfs.nsk.su" at Sep 11, 97 04:30:18 am
next in thread | previous in thread | raw e-mail | index | archive | help
> But then I must ask myself - if this are general
> 'stdin/stdout' files - what the hell does 'CLOCAL' means
> for them ?
"This is a modem control port, but you should treat it as if it
were a non-modem control port, and we were too stupid to remove
the duplicate devices".
The reason for the duplicate devices is long and complicated,
as is the reason for a user manipulable CLOCAL (mostly, it's
a stupid security hole that lets the next caller get your
shell when you set it after calling in).
Skip the article now, if you want to keep your sanity:
1) Initially, introduced by SCO Xenix, there was a modem
control ("ttyA") and non-modem control ("ttya") device.
The idea was to move the value which was traditionally
a compile-time flag. This was done by folding the flag
into the minor number instead.
NB: if you have a SunOS 4.x.x adminstrators guide, look
up UUCP configuration for inbound UUCP and modem calls
to see the flags; alternately, if you have a Telebit
product of any kind (a TrailBlazer is good) look in the
manual for SunOS installation instructions. Either one
will show you the flags I'm referencing.
The "calling unit" or "cu" device was the same device,
only renamed to indicate the existance of flags. In a
real BSD system, the calling unit and the tty device
never exist at the same time. In SunOS, these were
"ttya" and "cua", respectively.
The "a" ended up getting perverted to be a controller
descriptor for the old 4 port S-BUS boards and Ultrix
VAXEN boards. This means "ttya0" was "tty 0 on the
first serial controller, without the modem control
flags enabled" and "cua3" was "tty 3 on the first
serial controller, with the modem control flags
enabled".
God only knows how FreeBSD decided to use "tty0" and
"cua0" instead of "tty0/cu0" or "ttya0/cua0"... and
he's not talking. Probably, they should both be "a00",
with "a" being the "motherboard serial controller". Or
they should both be "00", and there should not be any
seperate namespace for seperate serial controllers at
all. Either way would make it less confusing.
2) Microport UNIX, and later, "Cubix"'s port of Microport
UNIX, introduced a non-modem device, a modem device, and
another modem device. These were "tty0", "tty0m", and
"tty0M".
The reason for having these exist simultaneously was
autmation of inbound and outbound connections.
In order to automate inbound vs. outbound before this,
you had to:
A) lock the port with a lockfile
B) modify /etc/ttys to turn the tty from "on"
to "off"
C) send SIGHUP to init (pid 1) to make it reread
the /etc/ttys, and kill of the getty it had started
D) do your call
E) put the /etc/ttys back
F) unlock the port by getting rid of the lockfile
G) send SIGHUP to init again to make it reread the
/etc/ttys, and restart the getty
Not very damn automatic, plus only root can HUP init.
In the new scheme, you either used "tty0" for a direct
connection OR you used one of the modem control ports.
If you used the modem control ports, you started a getty
on "tty0m", and it hung in the opening waiting for DCD,
loke all sane getty's are supposed to do, from time
immemorial.
Then if you wanted to call out, and there wasn't a DCD
present ("tty0m" wasn't actively open), then you'd open
"tty0M". This would *implicitly* lock the port for an
outbound call, and you only needed to make the lockfile
to keep other outbound calls from using the port at the
same time.
3) Enter Honey-Dan-Ber UUCP (or HDB uucp).
USL had considered this problem as well. They decided
to make a getty that looked for a lock file after it
opened (DCD present from dialout), and went to sleep
and woke up every so often and checked to see if the
lock file had gone away. The default was 300 seconds,
or 5 minutes. They called this monstrosity "uugetty".
In order to call out, the caller-outer had to open the
port with DCD not present, and not hang like (uu)getty
hung, waiting for DCD.
The way this was done was called "the partial open hack".
The hack operated by allowing any open to succeed, so long
as it was initiated *after* an open that had succeeded
(this let out the getty open, which was sleeping in the
tty waiting for DCD). It was a hack, because you had to
open the port with the O_NDELAY flag (in those days, the
O_NDELAY flag indicated non-blocking I/O, and there was no
way to turn it off: it was an open-time-only option).
So how do you get a non-non-blocking I/O open to succeed
without DCD present?
A) lock the port with a lockfile
B) open the port O_NDELAY; this will succeed even
if DCD isn't present.
C) open the port again without O_NDELAY. This will
succeed because the port is already open.
D) close the first fd. Now you are in business.
E) Call who you are going to call
F) DCD goes high, and the uugetty open succeeds
G) The uugetty sees the lock file, clses the port,
and goes to sleep for 5 minutes. It does this
over and over, until the lock file is not there
any more (wai 0-5 minutes to resume inbound calls).
H) When you are done, close the port.
I) Unlock the lock file
The only real feaure to come out of uugetty was direct
machine-to-machine seriallinks on non-modem control lines:
because it waited for a CR before putting up the prompt,
you could sometimes (not reliably, though), use it on
a dedicated bidirectional serial line between two
machines. Bigh whoop... 3COM, Lachman, and NRC had all
released TCP/IP for Xenix about that time, and Novell
was in the process of driving down ethernet boards into
the commodity market, so why do that?
4) In SCO Xenix, you used to use "enable" and "disable".
These were commands for printers, but they worked just as
well on getty.
Then SCO got HDB UUCP in Xenix 3.2 or so (at the same time,
they broke the serial driver so after an on-to-off DCD
transition, you had to reopen the port even if it wasn't
a controlling tty, mostly because of a bad rewrite of the
"revoke" primitive. For some reason, may people have been
trained to believe this is somehow the way it's supposed to
work. It's not.).
When they "got religion", they changed the suid on the old
enable/disable commands to make them only work with printers.
This was to convince everyone else that "they needed to get
religion, too". No one did, mosly because they went through
enough lockfile formats in one point rev to make it impossible
to interoperate with their newfound religion.
None of us got religion, for what it's worth. We just
chown'ed and chmod'ed the things back to what they were
supposed to be during our product installs.
Notes:
1) Why didn't they use O_EXCL, and just make the port exclusive?
Because they didn't have poll/select. That meant you had to
fork to get bidirectional I/O occurring simulataneously in
terminal programs like "cu" or "tip".
2) What was the partial-partial-open hack?
HDB attempted to use O_EXCL. They flubbed it, and it seems
that they hacked up the lock stuff as a last resort. The
world may never kow the true story. But the O_NDELAY code
bypassed the code that reset the tty flags, assuming they were
set to the default on the last close (tty devices are supposed
to reset to ground state when you close them, unlike FreeBSD's).
Because of this, the O_EXCL flag was set. This meant that if
you forked, the process would leave the O_EXCL set by uugetty,
and it wouldn't let the child process use the port. So you
had to reset the flags. But because of a screwup that put
11 lines of tty.c about 22 lines further up than it should
have been (these numbers are exact for SVR3.2), you had to
make a blocking open call to do it. Hence the p-p-o-h:
A) set an alarm for 2 seconds
B) blocking open the tty to reset O_EXCL
C) if the open worked, close it (inbound call at
exactly the rigt time); if not, reset the
alarm handler to pre-alarm state (before signals
could be told not to restart, you had to longjmp
from the alarm handler to get out of the open).
D) open O_NDELAY
...
3) Why does FreeBSD have two devices?
Nobody bloody knows... they aren't doing the SCO trick,
what with CLOCAL and the control device, and they aren't
doing the Microport trick. And flags could be done via
a sysctl anyway, nowadays. So no one knows, really.
4) Why are there still lockfiles?
Because we're too lazy to do things the right way: with
an open flag for modem control inbound and another for
modem control outbound, and O_EXCL-like flag used by
outbound programs to prevent two outbound at the same
time, but without preventing forking so you can implement
things like "ct" and "dialback".
Regards,
Terry Lambert
terry@lambert.org
---
Any opinions in this posting are my own and not those of my present
or previous employers.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199709111026.DAA14233>
