stty: setting a grouped control flag (e.g. cs7) does not clear existing group bits first
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 24.1k
- Forks
- 2k
- Avg merge
- 1d 5h
- Merged PRs (30d)
- 365
Description
Description:
When trying to set a CSIZE character size flag (cs5-cs7) on a terminal which already has cs8 set, the new value is silently ignored.
Sorry for the lengthy issue report, I'm relatively new to this and wanted to give as much info as possible.
Reproduction:
I was trying to set stty to cs7 and noticed an issue.
stty -a -F /dev/ttyA0 | grep -o 'cs[0-9]'
original output: cs8
stty -F /dev/ttyA0 cs7
run the state check again: stty -a -F /dev/ttyA0 | grep -o 'cs[0-9]'
output: cs8
GNU coreutils (albeit an old version in my case) will set it properly.
Presumed Root Cause
In apply_setting, we run setting.flag.apply(termios, !disable), showing just the control flags entry:
https://github.com/uutils/coreutils/blob/22bd03668a8b9f3b5daf7c863b5a92f263086986/src/uu/stty/src/stty.rs#L975-L980
That routes to termios.control_flags.set(*self, val), with val being !disable, or true
https://github.com/uutils/coreutils/blob/22bd03668a8b9f3b5daf7c863b5a92f263086986/src/uu/stty/src/stty.rs#L1298-L1307
From bitflags public.rs, set calls insert, insert calls union, and union is an OR operation:
https://github.com/bitflags/bitflags/blob/7cc8595e93d04d180d39e2f25242dca85dd71228/src/public.rs#L244-L250
https://github.com/bitflags/bitflags/blob/7cc8595e93d04d180d39e2f25242dca85dd71228/src/public.rs#L232-L234
https://github.com/bitflags/bitflags/blob/7cc8595e93d04d180d39e2f25242dca85dd71228/src/public.rs#L256-L258
Rust defines CS bits as the following:
pub const CSIZE: crate::tcflag_t = 0x00000030;
pub const CS6: crate::tcflag_t = 0x00000010;
pub const CS7: crate::tcflag_t = 0x00000020;
pub const CS8: crate::tcflag_t = 0x00000030;
(and cs5 is all 0's)
https://github.com/rust-lang/libc/blob/e879ee90b6cd8f79b352d4d4d1f8ca05f94f2f53/src/unix/linux_like/linux/gnu/b32/arm/mod.rs#L446-L449
So we take up bits 4:5, set at 00, 01, 10, 11 for cs5-8.
Evidence
The OR function is where we encounter issues. Because this is a 2-bit store, a simple OR does not set properly.
Setting cs5->cs6
Setting cs6 -> cs5
Setting cs6 -> cs7
Solution Ideas
I haven't looked at GNU source code, but my assumption is they would clear this bitmask before setting.
I think a proper solution would have us clearing/removing that bit group prior to the new application.
Additional Screenshots:
GNU cs8 -> 7
Uutils cs8 -> 7 (doesn't work)
GNU behavior with commands from "Evidence" section. Note that it sets correctly each time.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/uu/stty/src/stty.rs at apply_setting and the control_flags implementation around the referenced lines, then reproduce the transitions between cs5, cs6, cs7, and cs8 on a terminal device. Compare each result with stty -a and GNU stty; done means every requested character size replaces the existing group bits rather than retaining or combining them.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli, operating-systems
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100