Skip to content

stty: stty -F /dev/tty reports incorrect baud rate on PowerPC64 Little-endian #11708

Open

Description

@BAMF0

(This has been forwarded from Launchpad Bug #2146427)

Problem

stty reports an incorrect baud rate on ppc64le systems.

Reproduce

On a ppc64le system, run:

stty -F /dev/tty

This outputs:

speed 15 baud; line = 0;
-brkint ixon -imaxbel iutf8

To compare with GNU, run:

gnustty -F /dev/tty

This outputs the correct baud rate:

speed 38400 baud; line = 0;
-brkint -imaxbel iutf8

System

  • OS release: Ubuntu 26.04 (Development branch)
  • uutils coreutils version: 0.7.0-0ubuntu1
  • CPU architecture: ppc64le

Activity

  1. oech3 commented on Apr 9, 2026

    @oech3
    Contributor

    BaudRate is enum on old glibc. So I guess 15 is internal value.

  2. CyberSarvesh commented on Apr 15, 2026

    @CyberSarvesh

    I looked into this and it seems the issue comes from how stty formats the baud rate rather than how it’s retrieved.

    On ppc64le, cfgetospeed appears to return an enum value (e.g. 15 for B38400), similar to other PowerPC targets. However, in stty.rs, the cfg conditions only treat:

    • powerpc
    • powerpc64 (big-endian)

    as requiring enum → string conversion.

    Because of this, ppc64le falls into the generic path:

    not(all(target_arch = "powerpc64", target_endian = "big"))

    and the raw value (15) is printed instead of being mapped to 38400.

    It seems that all powerpc64 targets (including little-endian) should use the mapping logic via BAUD_RATES.

    I can work on a patch to extend the cfg conditions accordingly if that approach looks correct and make the pr immediately if that makes sense.

  3. BAMF0 commented on Apr 15, 2026

    @BAMF0
    ContributorAuthor

    @CyberSarvesh Interesting! When building uutils coreutils on ppc64le I received a compilation error saying that the datatype was u32 and not the expected baud rate enum (see #11282)

  4. CyberSarvesh commented on Apr 15, 2026

    @CyberSarvesh

    That’s really interesting—and I think I’m seeing the discrepancy you’re referring to.

    In my ppc64le test environment (via QEMU), cfgetospeed appears to return a BaudRate, which causes the original code (printing speed directly) to fail with:

    Image

    However, based on #11282, it seems that in other environments the same function returns a u32, which would make the mapping logic fail instead.

    So it looks like the behavior of cfgetospeed on ppc64le is environment-dependent.

    I think the correct approach here might be to handle both cases explicitly rather than relying solely on architecture checks.

    I can work on a version that supports both u32 and BaudRate if that makes sense.

  5. BAMF0 commented on Apr 15, 2026

    @BAMF0
    ContributorAuthor

    Thanks for testing it out. This is indeed weird. I have tried compiling your fix in another ppc64le environment, and there it builds successfully! I think you may be right in that this is environment dependent and not strictly architecture dependent.

  6. CyberSarvesh commented on Apr 15, 2026

    @CyberSarvesh

    Thanks for verifying that!!!
    Since the behavior seems to vary across environments, I was wondering if it might make more sense to focus on making the mapping logic more robust, rather than relying purely on architecture-based conditions.
    For example i was thinking along the lines of handling both representations of cfgetospeed (whether it behaves like a BaudRate or a numeric value) in a unified way.
    Maybe this can be environment independent or anything you are thinking about specific to this?
    Happy to explore if this approach sounds logical enough.

  7. BAMF0 commented on Apr 15, 2026

    @BAMF0
    ContributorAuthor

    Yes I think that might be a good idea. Intuitively, I think we could assume that the value should always correspond to a BaudRate enum on ppc64le systems. The problem is likely whether we can directly map the enum integer value to the BaudRate naively. Looking at the definition in the nix crate seems to suggest that 15 maps to 38400 on Linux, which is correct for my provided bug.

  8. CyberSarvesh commented on Apr 15, 2026

    @CyberSarvesh

    I took a closer look at the BaudRate definition in the nix crate, and it does seem to align with what you mentioned.

    Although BaudRate is exposed as an enum, the underlying values correspond to the constants defined in the system headers. For example, B38400 maps to 15, which matches what we’re seeing in the output.

    I also verified this in /usr/include, where B38400 is defined with the same value, so the numeric representation appears to be consistent at the libc level.

    Image

    This suggests that even when cfgetospeed returns a raw integer, it still maps reliably to a valid BaudRate, which makes the mapping approach viable across both cases.

    Given this, it might make sense for us to focus on a mapping-based approach that works consistently across environments, rather than relying on architecture-specific assumptions.

  9. oech3 commented on Apr 15, 2026

    @oech3
    Contributor

    Can we support any baudrate instead of enum baudrate on all Linux targets?

  10. CyberSarvesh commented on Apr 15, 2026

    @CyberSarvesh

    We could go with that, but I think the BaudRate enum still has value in terms of providing well-defined, expected values. That seems to align with how stty is currently structured.

  11. oech3 commented on Apr 15, 2026

    @oech3
    Contributor

    We use enum because it is restricted by dependencies instead of we want to do that.
    GNU supports any bauds on Linux and recient glibc.

  12. oech3 commented on Apr 15, 2026

    @oech3
    Contributor

    Moreover, gny-stty 51 && uutils-stty panics on unsupported targets. It is why we have read-only support for any baud on Linux except for ppc targets.

  13. CyberSarvesh commented on Apr 15, 2026

    @CyberSarvesh

    So the enum is more of a constraint from the current dependencies rather than the intended behavior, and the goal is to support arbitrary baud rates similar to GNU.
    That also makes sense why the current approach can panic on unsupported values and why ppc targets behave differently.

    I’ll keep that in mind while adjusting the approach here. If I’m not mistaken, we likely need to rely more on the underlying numeric representation and map it consistently, rather than depending on architecture-specific handling.

    I’d be happy to work on updating the implementation along these lines if that sounds reasonable.

  14. oech3 commented on Apr 15, 2026

    @oech3
    Contributor

    Also note that we are currentry migrating to rustix and libc from nix. If enum is glibc's restriction, you can try to use rustix's raw backend for this.

  15. 7 remaining items

  16. BAMF0 commented on Apr 16, 2026

    @BAMF0
    ContributorAuthor

    Yes I think that is the way to go. Otherwise this would be a fix, on top of a fix, that would later get patched with the previous fix to compile correctly.

  17. CyberSarvesh commented on Apr 16, 2026

    @CyberSarvesh

    I have replaced the entire architecture checking block with this piece of code its working on my ppc64le container i think the logic is enough for a fix but open to suggestions for dealing with edge cases and others. The speed variable was already declared before hand.

        //We have chosen to go with a platform independent approach due to issues caused in issue
        //#11708 for ppc64le.
    
        let speed_val = speed as u32;
    
        let speed_str = BAUD_RATES
            .iter()
            .find(|(_, rate)| (*rate as u32) == speed_val)
            .map(|(text, _)| *text)
            .unwrap_or("unknown");
    
        printer.print(&translate!("stty-output-speed", "speed" => speed_str));
    
  18. BAMF0 commented on Apr 16, 2026

    @BAMF0
    ContributorAuthor

    Nice! If you want to update your PR with this I can have a go at building and testing it. The BaudRate enum is unit-only (I don't see that changing) and we have the u32 representation as well so the:

    let speed_val = speed as u32;

    should be alright.

  19. CyberSarvesh commented on Apr 16, 2026

    @CyberSarvesh

    I have implemented the changes and you can try them out and tell me if it looks good enough or some changes that would make it better.

  20. CyberSarvesh commented on Apr 16, 2026

    @CyberSarvesh

    The changes seems to work only in Linux environments but seem to break in macos,freebsd environments .
    Seems like we would have to go back to the some kind of target_os kind of scenario.

  21. oech3 commented on Apr 16, 2026

    @oech3
    Contributor

    BSD platforms have any baud only.

  22. CyberSarvesh commented on Apr 16, 2026

    @CyberSarvesh

    Thanks for pointing that out does this code make sense i have made the code different in this case

    let speed_val = speed as u32;
    
    let speed_str = {
        #[cfg(not(bsd))]
        {
            BAUD_RATES
                .iter()
                .find(|(_, rate)| (*rate as u32) == speed_val)
                .map(|(text, _)| (*text).to_string())
                .unwrap_or_else(|| "unknown".to_string())
        }
    
        #[cfg(bsd)]
        {
            speed_val.to_string()
        }
    };
    
    printer.print(&translate!("stty-output-speed", "speed" => speed_str));
    

    I also checked it locally for all the build systems in this case:-

    FreeBSD:-

    Image

    Macos(ARM Based):-

    Image

    Macos(Intel based):-

    Image

    Do you think its good enough at the moment or any kind of changes anyone would want to recommed.

  23. oech3 commented on Apr 16, 2026

    @oech3
    Contributor

    Non PPC linux needs read-only any baud support to avoid panic with newer glibc.

  24. CyberSarvesh commented on Apr 16, 2026

    @CyberSarvesh

    In that case i think its best for a fix is that if the baud rate is mappable like 15 is to 38400 we just give out the mapped out values but in case of any other value we will give out the arbitrary value like 12345 as given to us should i try to implement something like that.

  25. oech3 commented on Apr 16, 2026

    @oech3
    Contributor

    I think it has a risk of incorrect mapping.

  26. CyberSarvesh commented on Apr 16, 2026

    @CyberSarvesh

    I mean you saying along the lines of like suppose we have a real baud rate value of 15 and by this code logic i accidently print 38400 instead right?

  27. oech3 commented on Apr 16, 2026

    @oech3
    Contributor

    Yes.

  28. CyberSarvesh commented on Apr 16, 2026

    @CyberSarvesh

    On ppc64le, the value from cfgetospeed can represent either an encoded constant or a raw baud value due to issue from nix, and there’s no reliable way to distinguish between them. Because of that, mapping via BAUD_RATES can lead to incorrect interpretation and inconsistency. You have any leads i can work on ,maybe research it a bit to maybe think along those lines.

  29. oech3 commented on Apr 16, 2026

    @oech3
  30. oech3 commented on Oct 13, 2026

    @oech3
    Contributor

    I'm trying on rustix (u32 baud) migration at #15299 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions