Messages in this thread | | | Date | Sat, 14 Mar 1998 22:34:08 -0500 | From | "Theodore Y. Ts'o" <> | Subject | Re: Warning, cua2 opened, ... |
| |
Date: Sat, 14 Mar 1998 21:22:13 -0500 (EST) From: Kenneth Albanowski <kjahds@kjahds.com>
Perhaps a handy little kernel warning on first use of a /dev/cuaxx (a la broken flock), along with some Documentation describing exactly _what_ is wrong is the cua devices, _why_ the tty devices should be used instead, and _how_ programs should be converted to do this. Without that sort of documentation, a conversion like this isn't much fun, or very fair to the folks who just use the things without understanding them.
What started this thread was the change in 2.1.90 which warns on the use of a /dev/cuaxx that the device is deprecated; that's going to be the standard behaviour for 2.2, with the expected removal of the cuaxx devices in the 2.4 release. So yes, there will be a kernel warning.
It's fair that there be an explanation in the Documentation directory describing what's wrong with the cua devices, and how the tty devices should be used instead. I'll work on writing that up.
Put simply, the problem with the /dev/cuaXX devices is that the locking between the cua devices and the ttySxx device is horribly complicated and doeosn't work all that well. It works if you have a single callout application, and a single dialin application, but there's nothing that locks out two different callout applications wanting to use the same tty device. The right answer is to use a tty lock file, as documented in the Linux Filesystem Standard.
The other use of the /dev/cuaXX device is for people who want to be able to open the tty device as if CLOCAL is always set. The kernel sets CLOCAL by default, but sometimes other programs clear CLOCAL, and then shell scripts which assume that you can just let the shell open the tty device start hanging. This is admittedly a slightly more reasonable way to use the cuaXX devices, but not all systems support the callout devices, and POSIX doesn't require it.
I suppose at this point I could take a page from the glibc folks, and say that gratuitously breaking programs that make assumptions beyond what is promised by various POSIX and ANSI standards is _good_, because ultimately makes the programs/shell scripts/whatever more portable. However, since I despise this attitude, it would be most hypocritical for me to take it. But for those of you who do subscribe to this philosophy, see below --- I'll tell you how to make your programs portable. (And those people who defend glibc on these grounds are hereby forbidden to complain to me that I'm deprecating the cua devices. :-)
Instead, I'll note that many programs support using the proper POSIX tty devices directly:
* pppd/chat works just fine with ttySxx. I've even written up a quick guide for how to configure the latest version of pppd, and it doesn't require using the callout devices. Said quick hide was sent out to linux-ppp for comments, but it didn't get any. I'll be happy to resend it. (Why the HOWTO guide recommends using /dev/cuaXX I'm not sure; but it should be fixed.)
* mgetty not only works fine with the POSIX tty devices, it strongly recommends that you not use the callout devices at all, since they only cause problems with mgetty's tty locking.
* kermit works just fine with POSIX ttys.
Also, all tty programs will work fine as long as the CLOCAL flag is set on a particular tty. If you have some device which is not a modem, and which permanently needs to have the CLOCAL flag set, you can either just simply make sure your programs don't clear it for some wrong-headed reason, or you can use the TIOCSLCKTERMIOS to lock the CLOCAL flag and hence prevent other programs from accidentally clearing the CLOCAL flag. This could be done at boot-time, since TICOSLCKTERMIOS must be executed by root.
Fixing your programs ====================
The proper way to open POSIX tty devices is as follows. First, open them with the O_NONBLOCK flag; this guarantees that they won't block waiting for carrier detect. Secondly, use the fcntl() call to clear the O_NONBLOCK flag (unless you really want to do non-blocking i/o). Yes, POSIX overloaded the meaning of O_NONBLOCK; so sue them. It means that you have to execute an extra system call or two to clear O_NONBLOCK after the open finishes, but that really isn't that hard to do.
Fixing your shell scripts is a little bit harder. In general, you should think about avoiding statements like:
echo "foo bar" > /dev/cua0
If there's a way to let the program (like PPPD) take over that functionality, that's probably the right way to go. Failing that, make sure CLOCAL is set before letting the shell open a tty. The stty command ideally should have a -f option which would allow stty to open the tty device for you. The BSDI stty has this feature; the GNU shell-utils' stty doesn't (yet) --- I intend to add this feature to our stty command. In the meantime, you can use the following program to set the CLOCAL flag. It also serves as a good demonstration of how to open a tty from a C program:
/* * clocal.c * * Usage: clocal <device> * */
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <termios.h> #include <fcntl.h> #include <errno.h>
int main(int argc, char **argv) { int ttyfd, i, fdflags; struct termios tios;
if (argc != 2) { fprintf(stderr, "usage: %s device\n", argv[0]); exit(1); }
while ((ttyfd = open(argv[1], O_NONBLOCK | O_RDONLY, 0)) < 0) { if (errno == EINTR) continue; perror(argv[1]); exit(1); } if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1 || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) perror("couldn't reset non-blocking mode");
if (tcgetattr(ttyfd, &tios) < 0) { fprintf(stderr, "tcgetattr: %m(%d)", strerror(errno), errno); exit(1); } tios.c_cflag |= CLOCAL; if (tcsetattr(ttyfd, TCSAFLUSH, &tios) < 0) { fprintf(stderr, "tcsetattr: %m(%d)", strerror(errno), errno); exit(1); } close(ttyfd); return 0; }
- Ted
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu
| |