Return to BSD News archive
Newsgroups: comp.unix.bsd Path: sserve!manuel.anu.edu.au!munnari.oz.au!uunet!kithrup!hoptoad!decwrl!elroy.jpl.nasa.gov!swrinde!zaphod.mps.ohio-state.edu!caen!hellgate.utah.edu!fcom.cc.utah.edu!cs.weber.edu!terry From: terry@cs.weber.edu (A Wizard of Earth C) Subject: Re: uugetty for 386bsd Message-ID: <1992Oct26.220714.5667@fcom.cc.utah.edu> Sender: news@fcom.cc.utah.edu Organization: Weber State University (Ogden, UT) References: <1992Oct18.191610.1992@draco.bison.mb.ca> <1992Oct20.174948.742@fcom.cc.utah.edu> <Bwon4H.Lx8@flatlin.ka.sub.org> Date: Mon, 26 Oct 92 22:07:14 GMT Lines: 295 In article <Bwon4H.Lx8@flatlin.ka.sub.org> bad@flatlin.ka.sub.org (Christoph Badura) writes: >In <1992Oct20.174948.742@fcom.cc.utah.edu> terry@cs.weber.edu (A Wizard of Earth C) writes: >>The purpose of uugetty is twofold: > >>1) It waits for a return before spitting anything back; thus an >> improperly configured modem will continue to operate. >>2) It allows bidirectional use of modems. > >You have it backwards. > >The primary purpose of uugetty in *HDB* UUCP is to allow the use of >bidrectional modem lines *despite* the lack of properly interlocking >tty drivers. This is the reason why the uucp device lock files are >created. I guess this is true, as long as you only use UUCP and relate programs (like cu) to talk to serial pots. Of cours, if anything useful is ever required, like pcomm or tip, etc) which *isn't* part of the UUCP program suite, then you are SOL. It's clear from the HDB sources in SVR3.2 and SVR4.2 and SVR4.4 that the authors had access to UNIX sources. The tty driver interlock workarounds are unnecessary on these systems, and were they necessary, source mods to the tty drivers would have been preferrable. >Further, uugetty *only* waits for a return before spitting anything >back, iff it is called with the -r option. This is solely to prevent >two uugettys locking up by spitting login:s at each other on direct >lines. The "-r" option is correct; however, the reasoning for direct lines is somewhat of a misnomer. According to the comments in the UUCP sources, this was to avoid the "chatter" problem on modems with DCD forced high, not on direct lines. Sure, it will have this effect on direct lines, but this isn't the purpose. The hack can fail on direct lines when garbage is output on a warm or cold boot of one of the two systems involved. Generally, a direct line connection has the caller disable the getty/uugetty on it's side, and calls are one direction at set intervals, with uucico from cron tab. The additional failure here is that login sessions do not necessarily result in or clean up UUCP lock files, so there can still be some tromping on toes. The evidence for this is the secondary hack of the pid in the lock file being tested with a kill 0 to determine if the process that created the lock file is still around. The kill 0 hack is more evidence that HDB UUCP could have mandated changes to the tty behaviour if the O_EXCL behaviour was not obeyed. The failure here is the lack of a normalized take-over machanism. Any locks older than 90 minutes (by default) act as if the creating process does not exist -- yet another toe-tromping situation for long user/transfer sessions. >>Additionally, I object to uugetty's creation of UUCP style lockfiles. > >Why? Because they are not needed with properly interlocking tty >drivers? Or because HDB has to cope with all sorts of tty braindamage, >like say not properly interlocking tty drivers, on the various >platforms it runs on? The first reason -- "they are not needed with properly interlocking tty drivers". The second reason is not a consideration, given the origins and code access for the original HDB UUCP. Tty" brain damage" was not a stated consideration in the AT&T HDB code. >> HDB >>UUCP and clones do not correctly use the exclusivity mechanism from >>O_EXCL, which should be sufficient to this task. The existance of these >>lock files appears to be the result of a misunderstanding of what is >>called "the partial open hack" in sys2.c in the original SVR3.2 kernel; >>this is probably because "open order" was not understood with reference >>to O_EXCL not being reset on an O_NDELAY open -- > >What are you talking about. sys2.c knows zilch about O_NDELAY and >O_EXCL. There exists something called "the partial open hack". It is implemented as follows, to allow the openning and use of a modem control port without carrier detect being present: part_open( port) char *port; { int pfd; int realfd; if( ( pfd = open( port, O_RDWR|O_NDELAY)) == -1) return( -1); if( ( realfd = open( port, O_RDWR)) == -1) { close( pfd); return( -1); } close( pfd); return( realfd); } This, of course, doesn't show the alarm calls around the open()'s to insure a reasonable timeout. If part_open() returns a valid descriptor, it may be written to and read without DCD being present. Now lets take the SVR3.2 sys2.c, which is the release where HDB UUCP had it's first source release. The fact that sys2.c "knows zilch about O_NDELAY and O_EXCL" is precisely the problem, if one looks at the base implementation of cu or other packages which did not use O_NDELAY I/O to effect polling reads, but instead used 2 (or more) processes to allow them to hang in multiple simultaneous reads (SVR3.2 poll() only worked on network I/O, and select() wasn't really there yet). This was accomplished by cu using a fork(), where the parent read from the user and the child read from the serial port; other programs used a "reader" program to communicate data from the user or from the serial port to a common control program (TERM from Century Software was one such product). The purpose in doing this is to allow incoming and outgoing processing of the data stream (terminal emulation, file transfer, etc.). The problem is, if the uugetty() used O_EXCL, then the O_EXCL bit stayed set in the tty struct for realfd because of the way the O_NDELAY open of pfd effected the partial open hack state information. In particular, an O_NDELAY open does not reset the O_EXCL bit if someone else (like uugetty) has set it part way through an open. Is this a problem? By itself, no.... but in combination with trying to make cu work, yes. The problem is the duplication of the parent's open fd's for the child -- using the code in sys2.c -- during the fork. There are fourteen lines of code that need to be moved down about 30 lines to fix the problem -- so that children may inherit O_EXCL opened fd's from the parent that forked them. THIS IS WHAT KEPT cu FROM OPERATING IF O_EXCL WAS USED INSTEAD OF LOCK FILES FOR HDB uucico AND uugetty, EACH OF WHICH USE A SINGLE FD, UNLIKE cu. THe authors either didn't know about (or didn't bother to research how O_EXCL could be unset in the reference to the file. the way to do this is the following: new_part_open( port) char *port; { int pfd; int realfd; int uefd; alarm( 2); uefd = open( port, O_RDWR); alarm( 0); if( uefd != -1) close( uefd); if( ( pfd = open( port, O_RDWR|O_NDELAY)) == -1) return( -1); if( ( realfd = open( port, O_RDWR)) == -1) { close( pfd); return( -1); } close( pfd); return( realfd); } The addition code, which tries a non-O_NDELAY open, resets the O_EXCL bit, so that not only can the caller of new_part_open() used the returned fd, but that children will correctly inherit the parent's open fd to the serial port. Thus if uugetty() has the port open, the open will fail because of O_EXCL; otherwise, the alarm() will go off. I am not showing the errno handling code here, but it's pretty obvious. For more rigorous checking, the reference count on the fd should be bumped once per partial open in progress, and the following code fragment: int exfd; alarm( 2); exfd = open( port, O_RDWR)|O_EXCL; alarm( 0); if( exfd != -1) close( exfd); added and the errno checked to see if the open was denied for exclusivity reasons (this is necessary, since O_EXCL is unset on open by the uugetty before it exec's login; we can't so this in our program because our credentials aren't the correct ones to unset the O_EXCL). >> in actuality, a SVR3.2 >>UNIX will not reset and of the tty struct contents in the case of O_NDELAY. >>This was either intentional (unlikely), or the result of misplacing about >>12 lines of code in the dup2() system call implementation code, which is >>also used during a "partial open hack" operation. > >Again, what are you talking about? The partial open hack and how it interacts with O_EXCL for "non-partial" opens, as explained above. >SVR3 never reset the tty struct contents. It has always been the tty >drivers calling ttinit() to do so. And since the tty struct (and >ttinit() for that matter) know zilch about interlocking drivers, >O_EXCL, and O_NDELAY how could it possibly be done with the tty >struct? Precidely the problem, and precisely what new_part_open() does, which is why HDB should have used this code instead of going to bizarre lengths with the locking mechanism, which is, in reality, unnecessary. >And the dup2() system call has nothing to do with that either, because >SVR3 doesn't support dup2() anyway. dup2() doesn't deal with >"half-open" file descriptors, it doesn't deal with copen()/copen1() in >any way. And with opening the child fd's as a result of a fork() so that they can be inherited from the parent. In reality, it's the shared code part that's in error. >>In any case, Berkeley style calling units obviate the problem. > >Indeed. >> One of the major problems in >> the SCO implementation is the confusion of having two >> devices, both of which may operate simultaneously. Thus >> the call-out works, but on connection a local host "login:" >> is echoed down the line to the remote host. This is an >> error. Login should only be enabled on the "non calling >> unit" device. > >Huh? I have never seen that one and I run SCO. 1. login as root 2. enable tty1a 3. disable tty1A 4. call out on tty1A -or- 1. login as root 2. enable tty1A 3. disable tty1a 4. call out on tty1a -or- 1. enable both tty1A and tty1a (or tty14 if your SCO is real old) 2. call out. The main problem here is not only are there two devices that refer to the same port that aren't interlocked between them to prevent them from tromping on each other, but the problem can't be worked around because the device name isn't cannonized to one form or the other. The first case is the most obvious, where you enable a uugetty on the non-modem control device, which makes a lockfile for it, and then call out on the modem control device, and the lock file name doesn't match; thus even though there is a lock on the device, it doesn't prevent access to it. An interlock between the two would fix the problem. >> d) Flags information should not be shared between versions of >> the device ("calling unit" vs. "non calling unit"), but >> mode information should be. Thus baud rate is common, but >> O_EXCL and O_NDELAY are not. > >Give me a good reason why I shouldn't be able to have a 19200,8,N,1 >getty hanging on the dialin device while dialing out with 9600,7,e,2. Your getty is converted. This is *precisely* why you don't want shared flags. The open instances should maintain their own flags settings so the *can't* screw with each other. >> Note that this requires >> blocking O_NDELAY opens to the device when its counterpart >> is in use. This is acceptable, as it allows proper fail >> out on multiple getty's on the same device. > >I don't see a need for blocking a non-blocking open. Maybe it's >because I don't understand what you want this for. An example why a >non-blocking open shouldn't return EBUSY when the device's couterpart >is in use would be most helpfull. "blocking" in the sense of "interfering with", not "blocking" in the sense of "putting the caller to sleep until the operation can be completed". Sorry, about this -- it was inappropriate word choice on my part. Terry Lambert terry@icarus.weber.edu terry_lambert@novell.com --- Any opinions in this posting are my own and not those of my present or previous employers. -- ------------------------------------------------------------------------------- "I have an 8 user poetic license" - me Get the 386bsd FAQ from agate.berkeley.edu:/pub/386BSD/386bsd-0.1/unofficial -------------------------------------------------------------------------------