|
Message-ID: <20240411165556.GB4163@brightrain.aerifal.cx> Date: Thu, 11 Apr 2024 12:55:56 -0400 From: Rich Felker <dalias@...c.org> To: musl@...ts.openwall.com Subject: Re: making termios BOTHER speeds work On Thu, Apr 11, 2024 at 10:24:56AM -0400, Rich Felker wrote: > Since it's come up again, I'm looking at what it would take to get > support for custom baud rates in termios working. This topic is > something of a mess, as it involves discrepancies between our termios > structure and the kernel termios/termios2 structures. > > Szabolcs Nagy did some of the initial research on the mismatched > definitions in 2016: https://www.openwall.com/lists/musl/2016/04/26/3 > > Basically, it looks like what happened was that we tried to match the > glibc generic ABI (an early goal of lots of stuff in musl) as long as > it lined up with the kernel termios (not termios2) ioctl structure, > but deviated when it wouldn't (powerpc had c_line and c_cc order > flipped and we followed kernel on that), and didn't do glibc > arch-specific mistakes (like mips omitting the __c_[io]speed fields). > > If we had used the kernel value of NCCS everywhere, rather than the > inflated glibc value of 32, we could add BOTHER support just by > attempting TCSETS2 using the caller's termios structure, and only > falling back if it doesn't work. In theory we *could* change to do > this now. The __c_[io]speed members are not in the public namespace, > and NCCS could be reduced to accommodate them as long as the overall > struct size was preserved. This might be ~ugly~ for programs built > with the old NCCS of 32, which might copy c_cc past its new end, but > they'd just be moving stuff to/from the reserved speed fields they > couldn't yet be using. The worst part about this seems to be that we'd > be introducing more arch-specific versions of bits/termios.h, since > the "generic" definition we have now actually has different layout > depending on the arch's alignment requirements. I think this only > affects m68k (where it's 2 rather than 4 byte alignment for int), so > maybe it's not a big deal to add just one. > > The alternative is to only use the caller-provided termios in-place in > the case where we can get by without termios2 interfaces: that is, > when either BOTHER is not set (classic POSIX baud flags), or TCSETS2 > is not defined (plain termios already supports BOTHER for this arch). > Otherwise, translate to a kernel termios2 form, which really requires > nothing other than knowing an arch-defined offset for the speed > fields. > > For going the other direction (tcgetattr) it's even easier: we're > allowed to clobber the caller buffer, so just try TCGETS2 and move the > speeds from their kernel offset into the libc member offsset. > > I think this second approach is probably better, but I'm open to > reasons why it might not be. One thing I hadn't even considered yet is how the application is expected to set custom speeds. We don't expose BOTHER, and while we could expose it and put the c_[io]speed members in the public namespace for direct access, it's not clear that this is the right way to do it. glibc's approach seems to be having cfset[io]speed accept values other than the symbolic B constants, which POSIX allows and mentions in the RATIONALE: There is nothing to prevent an implementation accepting as an extension a number (such as 126), and since the encoding of the Bxxx symbols is not specified, this can be done to avoid introducing ambiguity. https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html This seems like it's the better approach. It does have values 0-15 and 4096-4111 as impossible-to-set because they overlap with B constants, but these are not useful speeds. Of course it might be useful to look at what applications expect to be able to do. Looking at the existing code, it seems like Linux already had separate input baud encoded in the bits of c_cflag (CIBAUD mask), but we're not using that. It's not yet clear to me whether these work and whether we should be using them. POSIX is also unhelpful/wrong on how to determine if "split baud" is supported. The RATIONALE for cfgetispeed says: Setting the input baud rate to zero was a mechanism to allow for split baud rates. Clarifications in this volume of POSIX.1-2017 have made it possible to determine whether split rates are supported and to support them without having to treat zero as a special case. However, tcgetattr specifies: If the terminal device supports different input and output baud rates, the baud rates stored in the termios structure returned by tcgetattr() shall reflect the actual baud rates, even if they are equal. If differing baud rates are not supported, the rate returned as the output baud rate shall be the actual baud rate. If the terminal device does not support split baud rates, the input baud rate stored in the termios structure shall be the output rate (as one of the symbolic values). Which clearly gives the *same behavior* in both the case where split rates are supported but the same, and the case where split rates are not supported. I have no idea what they intended here. I think before this can move forward we need to have a better understanding of what POSIX is supposed to require here and what Linux actually does. Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.