I wrote a QEMU patch to provide more memory on the sh4 r2d board emulation.
It requires a matching kernel, because the free memory space in the mapping is BEFORE the standard mapping so you have to move the start DOWN rather than expanding it up. It's not just that an old kernel won't see the extra memory, it's that qemu's builtin bootloader (the -kernel -initrd and -append options) load data relative to the start of the memory block rather than the end, so a kernel that doesn't know the new memory layout can't find its resources and relocate itself.
In theory, switching to device tree would fix at least some of that. (Not 100% sure about the relocation part because there's a pathological memory range where copy to and copy from overlap, and the "to" addresses are absolute physical addresses where the kernel expects its function pointers to live. Unless a kernel can be a PIE binary...)
I'd like to do a device tree version of the r2d board based on the turtle board's device tree plumbing, but as with so many things I'd like to do, I just don't have the spoons with the world (and the linux community) on fire.
ICE murdered another observer, bit distracted today.
Each toysh pipeline segment has a "type" field, which is:
During parsing, there are some extra types (because parentheses are handled strangely):
There are three different "do" variants we can be waiting for (which have an A, B, or C after the NUL terminator in the expect string:
The "match byte after NUL" part is tested with smemcmp() instead of memcmp() because memcmp doesn't stop at hte first differing byte but continues for the whole range even AFTER a difference is detected, which breaks asan when the string we're comparing against is shorter that range but differs before ending: smemcmp() is just the naive byte-by-byte for loop which reliably produces the right answer without segfaults. (See also strncpy() being useless because it zeroes ALL the bytes after the NUL byte, which is hardly ever what I want: sprintf("%.*s", len, str) does what I usually want.)
Spent most of the day heading to and from the IRS office to hand over a money order.
Our "married filing jointly" taxes got paid under Fade's identity theft number, not mine, but I'm the Primary Whatis (because misogyny?) even though Fade pays the bills (because the stream of late notices and small fines when _I_ handled the paperwork perpetually at the last minute made her nervous).
It's just northwest of the Mall of America. Got lost going through the Mall of America because I underestimated "get off on the blue line, then walk out of the mall to the north" as a thing I'd need to seriously plan for. And then got lost repeatedly on the way back but eventually found a bus heading towards St Paul until it could intersect the green line.
Yeah errands are easier to run when you have a car, but it's not worth the car part. I should look into that Evie thing. (It's a municipal electric car2go, for car-based errands when you don't want to pay $100/month just for the parking space.)
As long as ELC is in Minneapolis this year anyway I should submit some talk proposals. Maybe one about mkroot, and an updated version of "building the simplest possible linux system". I should also try to build Linux From Scratch (as is) then start swapping in individual toybox commands, like I did for aboriginal linux a quarter century ago. (I'm old.)
Jeff won't set foot back in the states while the orange one draws breath (Alan Cox stopped coming under Dubyah and still hasn't that I know of; there's a reason there's an ELC Europe and Plumber's was in Tokyo this year, and SPECIFICALLY why defcon moved to Europe, and that reason is "republican fascism".) But Jeff can dial in to co-present remotely, and we're thinking maybe "Running Linux under VHDL simulation" might be a good talk? I.E. the J1 simulation stuff we've been doing under NVC, add an 8 meg block of virtual SRAM (a ridiculous amount to have in real hardware because SRAM _eats_ power and turns it to heat, but like 50 lines of C to simulate), then port Linux to it (probably just a new device tree).
In theory we just need a new kernel .config and device tree to add a single processor j1 target with different memory map and no I/O devices other than serial console and spi flash. Hmmm, we should whip up a device tree for the r2d board QEMU emulates too.
Creating linux support for a new piece of hardware from scratch like that would be a good talk in and of itself. (What IS a minimal arch/blah contents, starting from scratch? I dunno how, but I dunno how to do MOST things I document before I set out to document them. I'm writing up the results of learning a thing I wanted to read about instead of reverse engineer and discover experimentally, so nobody else has to and everybody else can think the thing I wrote up was trivial and that I did no real work because they didn't have to.)
Edited and uploaded a few blog entries. Up to July 11th of last year! Woo!
Got Codeberg account working, pushed toybox there, and added it to the .git/configure "origin" list git push sends to. (Created a new key with openssh instead of dropbear, uploaded that, and it worked.)
Changed links in the toybox repo to point to codeberg instead of github, but there's a backlog of github issues todo and Elliott's unlikely to move while I'm still updating the old one any time soon...
Distracted by ICE attacking my city, and what little laptop focus I had went to stuff for Jeff. Where was I...
The fundamental problem with the toysh "premature exit after a pipe" issue is the layering's got conflicting design ideas after the last big rewrite.
So toysh is driven by "the fcall stack" which is a doubly linked list of struct sh_fcall, and then each instance of that has a struct sh_blockstack *blk (singly) linked list.
Each each fcall tracks the next source of lines to run, such as a function() call to a saved block of parsed lines or a source or eval statement providing a new FILE * to read unparsed lines from. It's a stack because a function can call another function which calls eval which calls source file.sh which calls another function and so on.
The block stack tracks curly brackets, parentheses, our if/else nesting level, and any other collation of statements that can be skipped or repeated, or collectively attach a redirect to the end of ala: if true; then echo hello; fi > file.txt
The block stack is a member of the fcall struct so "return" statements can jump out of the current block. (When you pop an fcall, you pop all its block stack, because "return" jumps out of out however many nested if/for/{ levels you're in.) Trailing redirects on { } <blah and such go in the block stack's "end" pointer (which should point to the type 3 ending block in the pipeline, also lets break jump ahead without traversing because we already parsed all this earlier). run_lines() does the redirects for pipeline segments, saving them into the current fcall's top block structure. The problem is, when this is the root fcall context (which is what prompts for new lines interactively), the cleanup isn't to POP it. And then there's signal handling, which is basically inserting function calls into the fcall stack:
$ trap 'echo hello' USR1
landley@driftwood:~/toybox/clean$ { echo thingy; kill -USR1 $$; sleep 1; echo else;} | tee out.txt
thingy
else
hello
I did a "git bisect" and the "echo | cat" bug was introduced in commit 7a2f81c82d1c which was the big rewrite replacing do_source() with entirely different logic. So not exactly _surprising_, but I am CLEARLY missing a test. (And I even have the "expect in shell" plumbing to test interactive stuff! Sigh.)
Unfortunately knowing "the giant plumbing rewrite broke it" doesn't help me easily revert the breakage, but what it LOOKS like is there's no unredirect on the last command in a pipe. (Which way back in the day ran in the current bash process even in bash, and Chet said he changed that for a reason I don't remember? Sigh,I need to reread all the old threads and make todo lists and test cases for every single point of interest I can fish out of them, but I just haven't had the spoons what with the Boomers not being dead yet.)
Anyway, it's sort of a "missing flush" situation, really. Yesterday I was tracking down "why on earth is there still an open fd 3 when run_command() gets called" and the answer is because that's the other end of the pipe which it'll need later for the next command to receive the output of the command its currently launching. It's already marked CLOEXEC, but since "echo" is a builtin we never exec so those cloexecs don't take effect (for non-mayfork commands, the child is a fork() but not an exec, at least in the with-mmu codepath). I _think_ that's ok for all the toybox commands? Having random inherited file descriptors greater than stdin/out/err isn't gonna break anything (modulo filehandle exhaustion) in any command I can think of, and if they ever DO exec something else those CLOEXEC annotations would take effect at that point.
I guess one edge case would be "shell calling shell as a child", ala "sh nohup sh" or some such? But only if the resulting shell script manualy referred to specific filehandles. A non-exec call to oneit -3 could also get unhappy (because fd3 is magic in that case), but you _have_ to exec that one for it to do its job. There's also a "too much stack used" check that forces an exec() after at a certain recursion level, which would also clean up the CLOEXEC filehandles...)
Anyway, that's a side issue, and one I was already aware of at some point.
So what is currently calling unredirect? pop_block() is calling it on TT.ff->blk->urd (mostly for the "if true; then echo hello; fi > /dev/null" block level pipes/redirects). And end_fcall() is calling it for ff->pp->urd which is probably what's missing here. (Or deferred to the point of uselessness: it's not the closes that's the problem, it's the "put stdin back where it belongs" that's the problem. That you CAN'T defer past where it needs to happen.) What else: pipe_subshell() has a local unredirect block to clean up its own redirects around a call to run_subshell(). And finally run_lines() is manually calling unredirect(TT.ff->blk->urd) which SEEMS like a duplicate of pop_block()?
Why are block unredirects being handled in two places? Do we clean out a block WITHOUT popping the structure off the list, and then reuse the struct? (Unlikely, but I've rewritten this code enough times I don't immediately remember which version is current, especially after spending most of 2025 going "not this shit again" and, to be honest, failing to cope until it got bad enough to get ANGRY again.) What's going on here...
Ok, first of all annotate all those calls and both the pop_block() and end_fcall() unredirects are indeed being called... with NULL arguments. Which is a NOP that gets filtered out before the printf I'd added to unredirect earlier. And then the prompt happens (and fails to read anything, which is treated as EOF on stdin) and then ANOTHER pop_block() happens and THAT one moves FD 10 (the first high file descriptor and where stdin got saved to) down to 0... before exiting the shell.
So there's a sequencing issue. Except what's really going on is the block level that's being treated as an interactive read from stdin... isn't. The NEXT block level is the interactive read from stdin. It should not be PROMPTING for the "nothing to read from the empty pipe" level before it's done the cleanup, the cleanup from popping that block is what gets us the stdin file descriptor we need to prompt for and read from.
Each block level can have redirections attached: source file < blah1; function ^lt; blah2; if true; then while read i < blah3; do echo $i; done < blah4; fi < blah5
And when it gets done with ALL of that there's an enclosing level that may or may not be interactive prompting for more input (or may be sh -c "string" or sh script.sh or sh < thingy from a non-terminal source meaning not interactive unless they explicitly said -i which just gets weird).
I posted a thing to the toybox mailing list and never got a copy emailed back to me. Dunno why. (I wonder if anybody else got it, or if this is another "dreamhost's infrastructure found a new way to fail". The message is there in the web archive!)
Anyway, during that I found a brown paper bag bug in current toysh which is that "thing | thing" exits right afterwards because the unredirect is returning to the shell prompt with stdin closed. (Oops. That's one of the more recent commits, it USED to work. I have TESTED that.)
So today I'm switching on the DEBUG output and trying to figure out where it's getting confused. There's already a debug_show_fds that iterates through /proc/self/fds to list all open filehandles and what they think they point to, which is a good snapshot. (The internal data structures are one thing, but "these are the filehandles this process currently has open" can't lie. And the way save_redirect() and unredirect() work is they dup2() filehandles up above 10 and then dup2() them back down to the original number.
This is for nommu support: doing it all in the parent before vfork() means the child has a lot less cleanup to do before it can exec() the new executable. Basically it can just loop through and close its copy of the high filehandles, then call exec. Since close() can almost never fail (the one exception I'm aware of is NFS, which I actively do not care about) this means the vforked child doesn't have to worry about error handling while it's blocking the parent and sharing a heap and so on. The vfork() syscall in linux/kernel/fork.c is just clone(CLONE_VFORK|CLONE_VM) which means the child has a separate filehandle table (I.E. it does NOT have CLONE_FILES), so the child can close() anything it likes without affecting the parent process.
That said, the PARENT then needs to unredirect() which means it needs to dup2() all the high filehandles down and then close them. (There isn't a "move filehandle" operation, you have to dup2() and then close() the old one if you want to move one file descriptor to be on a different number. Part of the unavoidable error handling of doing that is the potential for filehandle exhaustion: every time you request a new filehandle there might not BE another one available, becuase Linux has a maximum number of open filehandles systemwide and you could be in the middle of the file version of a forkbomb. So the parent should do all that, not the vfork child.)
This USED to work right, but apparently I broke it (doing the alias work maybe? Lot of reording what happens when there...) and "echo | cat" now exits the shell (after drawing the next prompt, as if I'd hit ctrl-D to close stdin.)
Sigh, I should also do another round of blog entry editing. The version on the website currently ends with July 30 of last year...
Slipped and fell down again at the protest. Sigh. I was JUST feeling better from the last fall...
The only time I saw ICE was when the bus driver pointed them out like a tour gide on the way to Powderhorn Park ("if you'd like to film, that's ICE reading license plates in the SUV next to us"). Got about 4 seconds, decent views of both faces for the inevitable crowdsourced doxing of the lot of them for new neremberg trials, posted it to Mastodon. (And while waiting for said neuremberg trials we can protest any strip mall whose mall cop used to be in the SS.)
The protest at powderhorn park was nice, crowd size was "too big to be counted from the ground". Mostly on the west side of the park, and public transit dropped off on the east side, and the park is a bowl (greenspace to catch floods I guess?) so we all had to go down a large frozen slope and back up a large frozen slope on the other side to get to where the people were, which was NOT FUN. (Again, more organization would be nice.)
I got REALLY cold after about 45 minutes of standing in "too crowded to move" (but at least they were an excellent windbreak). Next time: double socks, scarf, hat, layer a hoodie under the jacket. Wound up in the "parade down the street" part of the proceedings (apparently there was one), and then after had us heading back in the direction of the bus anyway so I decided not to push it and kept going buswards when the march turned north. Stuck to the street rather than the sidewalks (less treacherous, more salt)... and hit black ice and fell down again a block later anyway.
Had time to contemplate that "bringing ice against minnesota, that'll show them" is metaphysically dumb, and the murdered lady whose name we kept repeating was "Renee Good" meaning we are literally on the side of good. The ONE thing previous iterations of fascists managed semi-competence at was public relations (no Mussolini never made the trains run on time, he just claimed he did and shot anyone who contradicted him), and these clowns keep faceplanting even at that. Lying is their core competency, and their own second reich keep screwing EVEN THAT UP.
Fell on my back this time, so no fresh insult to my knees but I think I properly sprained my left wrist this time. (And banged up right fingers. And my headphones went flying but I think they survived. Wasn't wearning my laptop backpack because I'm not handing that over to confiscatory iceholes. Even my phone had a 7 digit PIN, was in airplane mode, and was turned off the whole time. Plenty of people were filming everything, my "last service update in 2022" android instance doesn't need to connect to the stingrays, thanks.)
Got helped up again, toddled down the street to the next intersection, got yelled at by the traffic directing lady for "distracting" her when I tried to ask directions, went to the corner and sat on the sidewalk for a bit (it was very cold) until a nice lady named Mara helped me up and walked me to the right bus. (I was... less functional than I'd like. Once again, the amount of OK you feel right after sprawling onto freezing asphalt seems to be a high point you will decline from going forward. I mostly don't notice being in my 50s, but I don't get banged up on a regular basis either. Also, Texas didn't have a lot of "you've been out in freezing weather over an hour, now pull off some physical challenges!" opportunities to practice under that particular debuf.)
Made it home without frostbite. Lay down. Typing it all up the next day.
I need to do all that again (and again, and again...) which means I should tackle my email and finish signing up for whatever lists I need to be on...
Got the email, haven't done anything with it yet. (But yay, I'm caught up on deleting spam! I was a month and half behind at one point.)
Speaking of email, I got a Call For Papers for ELC in Minneapolis May 18-20. (It's following me!) I suppose if there are literally zero travel expenses (well, $2 each way for public transit) I should come up with a talk proposal, but... have I really been doing anything I went to tell people about? [LINK] "Things the Linux community is doing that drive me away from it" seems an unlikely topic to get greenlit (nor particularly _useful_). Maybe the j-core stuff, although Jeff won' set foot in trumplandia. Or maybe I could talk about our "minimal-lib, bsd 2.11, netbsd, linux" layering strategy for, let's be honest, escaping linux's geriatric implosion. Or I could finally give a talk about mkroot to the ELC guys. (I gave one at TXLF a year or so back but I don't think I really nailed it, and never got a link to the video...)
I did not make it to the bookstore either, despite it only being a 15 minute walk away, because when I started down the sidewalk on University Ave next to Aldi's (basically the green line but walking instead of riding) it was a treacherous ice moonscape and I noped right back out of that and went in to the warm Aldi's instead. (It's replaced HEB as the "daily visit to get out of the house", which is nice. Fresh Thyme at the previous place occasionally had some nice loss leaders, especially in the meat department or baked goods on clearance, but was otherwise competing with Whole Foods for the snooty rich person dollar.)
I phoned said bookstore, and they say the next protest the signs could be used at is tomorrow at 1pm at Powderhorn Park. Which is an hour away by public transit, but at least it's a saturday so I can borrow Fade's rail pass.
Fade doesn't know where people are finding all the sudden protests to go to around minneapolis either, or where to go to confront the iceholes BEFORE they murder innocent citizens. (I see pictures of crowds on the news but haven't personally noticed them in my meager wanderings around St. Paul.) She suggested I look at local author Naiomi Kritzer's bluesky, which linked to a "defend 612" zoom orientation, which wanted name and email to sign up, which I wibbled about for a while (online security!) but signed up for at the last minute anyway. And stayed through the meditation exercise where we were supposed to feel the ground and thank the air or some such, because I want information dammit.
Eventually they got around to vaguely useful information: ice watch does what it says on the tin. You get a whistle, blow short bursts if iceholes get out of their SUVs, and long bursts if they actually grab someone. Film everything (whatever they say about it). That's it, otherwise try to stay 10 feet away when they haven't actually killed someone yet. The current hotspots are south minneapolis, although today they made it north to the stadium (where Fade and I used to live).
They mostly keep in touch on Signal, but their original whole-minneapolis signal channel hit a 1k person cap (as did tonight's Zoom tutorial thing, I was lucky to get in) and their more granular ones are all for downtown minneapolis (not St. Paul), and they've had a HUGE SURGE of signups since the murder (ahem, the most recent murder, it is apparently the 36th we know of this regime, but again missing white woman syndrome and this one was local and recent). Anyway, they promised to email everybody in the chat (since we had to give emails to sign up for the chat) with instructions on how to join a St. Paul regional signal that can crowdsource ice sightings and such.
The text chat attached to the zoom mentioned a bookstore is having a sign making event tomorrow, presumably somebody there will know where the next actual protest is. (Despite all the aches from the fall, I can "go stand around and chant" with the best of them.)
The musical pairing with today's blog entry is Johnny Cash's "hurt", albeit with "dumbass" rather than "self-harm" overtones in this instance.
So I finally walked to the new library location, which said the introductory japanese book I'd inter-library-loaned came in the day the old location closed. (And then they reopened in the new place on the 3rd.) This was my first mistake.
I went to the old location first, to hit the Sun Foods next door, which still hasn't restocked checkerboard ice tea. They have the with-pearls version from the same "chin chin" manufacturer, which is Japanese for "penis penis" but this is from taiwan so... maybe it means the same? Anyway, I inhaled a boba long ago and had it lodged in my lung for WEEKS until I stopped noticing (for all I know it's still there, although it's been like 20 years now) and... I prefer the all-tea version instead of non-beverage ballast. Alas, waiting and making sad faces. (Last time I was there, they had ground beef for $1.90/lb which... how? It tasted fine, should have stocked up, now it's $3.50/lb which is still "suspiciously cheap" but at "osha violations" rather than "downer cows" level...)
Resuming the Quest For Library, I hit a patch of sidewalk that had been shoveled but meltwater from nearby snow ran into it and then the part in sunlight was fine but the part in shadow was a layer of ice over water. Fell hard on my knee and wrists, then on my ass (keeping backpack with laptop OUT of the water). Stayed there for a bit soaking through going "ow" until a nice man got out of his car and helped me up. Hobbled the remaining half block to the new library location (I could SEE it from where I was), hung around in the warm for an hour thinking I would recover and instead felt worse. (Which is apparently normal for winter falls in minneapolis but I didn't know that. Bruising, poison ivy, sunburn, and winter falls onto concrete all gradually register their severity sometime after the fact.)
They THOUGHT they had my ILL book, but it wasn't on the reserved shelf, and after ten minutes they declared defeat. (I'm assuming it got lost in the move.) It took some dissuading to convince them NOT to pull a new copy from yet another library. (It took so long to fulfill the first request because all the copies at the other libraries were checked out, it's a popular book, I can GET other japanese learning resources and don't want to deprive the system of books that may disappear into a black hole.)
The new library location is less than half the size of the old location and they estimate they have about a quarter of the materials. (For example, the old place had the Dragon Maid blue ray, the new one does not. Also, obviously smaller "materials" room, way less shelf space.)
The collection they DO have out tends to have a lot of "Season 5 of Penn and Teller's Bullshit" (that is literally the name of their old TV show, it was quite good) but NOT season one of... anything, that I've noticed. (I can get those through inter-library loan, which might possibly mean pulling it out of a box at the old location being renovated, where the other 3/4 of their collection presumably still is?) I asked how long the renovations would take and they think they'd be lucky to move back there before the end of the year.
Hobbled home VERY SLOWLY, made it without another incident. Took TWO ibuprofen and lay down a lot. Things that logically shouldn't hurt, hurt anyway.
Came home to find that a different kind of ice murdered a white woman today. A very christian, vaguely photogenic, three small children, already triggering "missing white woman syndrome" even among the maggot base. Lots and lots of protests, which A) I hadn't heard about (how do people get notified of these things in time to GO to them?), B) am too banged up to helpfully attend tonight, but tomorrow I should find informational resources for this stuff. (I checked the "no kings" protest website right after the last protest to see when the next one was, and the concept of doing another protest after the "largest protests in history" seemed not to have occurred to them. Fucking useless, what are the city level resources here...)
FINALLY left the apartment (after going no farther than Aldi's all holiday break) because Fade's meds needed to be picked up and I can do that during the day while she's at work.
(Fade and I have very traditional gender roles. She goes to work before the sun comes up using her doctorate full-time with something that at least provides health insurance for HER, and while she's gone I tidy the house and do the dishes and walk the dog and run errands like refilling her meds at the pharmacy that's only open while she's at work, and make sure there's a hot dinner and cold beer waiting for her when she gets home. Extremely traditional.)
Since I'd bought the green line ticket anyway (she has a rail pass I can borrow on evenings and weekends, but she takes it to work with her), I went to the bookstore in downtown St Paul I'd ordered Fade a christmas present from ("The fabric of civilization", Hank Green interviewed the author and it sounded fun), and bought another book while I was there (I didn't know the third "legends and lattes" book was out, bought the hardcover), and then since I was in the area I visited the Habitrails, which I haven't been in since 2013. Alas I couldn't navigate back to my old stomping grounds: some giant bank skyscraper is closed which cuts of about 1/4 of the habitrails from the rest of it (unless you go outside and back in), and by the time I figured that out (I was stuck in the small isolated part) I'd hit my 10k steps and went back to the green line.
I'm having regular-ish calls with Jeff to work out j-core software strategy going forward. We need toolchain, toolflow, simulation, bootloader, and kernel builds.
The limiting factor is Jeff's time, he's CEO _and_ chief architect on the hardware side (chip design, board design, high voltage electrical design, sensor design, signal analysis...) and then the software side has FIVE major forks (toolflows to make chip masks using ghdl/yosis/openroad, C toolchains to build target code, Linux base OS image, RTOS image (sometimes used standalone or sometimes it's the ROM/bootloader that brings p Linux, and then all the application software which is itself a half-dozen major projects...)
Plus we've got simulation versions, that's kind of another fork...
I'd like to get all this packaged properly, with reproducible builds and automated regression testing and so on, but JUST THAT would be a full-time job without doing any actual _development_.
Not that Jeff can afford to pay me anywhere near full time right now. (Or at least he gets a better bang for the buck from japanese engineers, and gets to tell non-US customers that a tariff tantrum doesn't directly affect his supply chains.)
Then again, we're no longer maintaining two households (and put the equity from the house sale into an S&P 500 index fund) and haven't had a car since 2018, so I haven't really pressed the issue.
I'm basically a househusband doing little work-from-home projects here and there. I keep thinking I should just go get a job shelving boxes at Aldi. It is, at least, the opposite of a Bullshit Job.
Recruiters still wave stuff at me from time to time, but between "spend 6 months in a strange city not seeing your family" and the job ITSELF being either LLM fuckery or defense contracting under Hegseth... I'm describing myself as semi-retired at this point. Fade and I are no longer maintaining two households (and we put the equity from the house sale into an S&P 500 index fund) and haven't had a car since 2018. If her job provided spousal health insurance so I didn't have to buy it on the exchange, we'd be in pretty good shape.
I don't particularly _want_ to contribute to maga's economy, refuse to work for any company that donated to the Epstein Ballroom (yes there's a list), and every time a recruiter starts describing a job (some offering $100/hour) I wind up thinking "I keep hearing about desperate people who REALLY NEED the money" and I want to stay out of their way. I am not currently desperate. To permanently retire on what I've got I'd have to live like a monk, and possibly stop buying health insurance, and hope the coming LLM crash isn't much _worse_ than 1929, and that Fade stays employed, and it would be nice if some fraction of Social security still exists not long after age 70. But it's technically POSSIBLE. (If the stock market stays broken it would be trivial, but I don't remotely trust that.)
Or I could get a weekend job running a cash register to save it for a more comfortable retirement. (Literally flipping burgers would be FAR preferable to EVER dealing with vibe coded rust.)
Trying to add SIGWINCH support to demo_scankey, in preparation for implementing toysh line editing, and Linux terminal editing really, really, REALLY shouldn't be this hard.
The fundamental problem is that the terminal is PARTLY a series of stacked lines of arbitrary length, but also PARTLY an X/Y display window. And neither of them is complete.
If you resize the terminal it redraws the stacked lines in its history buffer, and if any of those lines are wider than the current terminal width they take up mutiple Y position slots (so the top of screen can be in the middle of one of these lines). This mostly does what you want: historical text automatically reflows (to an extent) when the terminal window is resized.
Except when you output a backspace character, it stops at the left edge of the screen. It does NOT ever subtract from your Y coordinate, it just stays stuck at the left edge of the screen. Printing more data will go "down", but backspace will never go "up", even though you're in the middle of a long (multi-row) line that will automatically reflow if you change the terminal width because it REMEMBERS what was connected.
In theory I can keep track of my cursor position and detect when I'm at the left edge, so I can do an ansi "go up" and an ansi "jump to the right edge" to move the cursor around. In practice, resizing with the mouse is an asynchronous action that can happen at any time and the running program gets notified an arbitrary amount of time later, with no locking between resize events happening and output going to the terminal's output pty, so your X and Y position can change out from under you. (When you increase the screen it moves the existing data down, which means if you've cleared the screen it adds the new blank lines at the TOP of the screen, changing your Y position. Your X position also moves when the width changes based on this wrapping BS as the historical text including the line you're on gets reflowed, especially when the screen gets narrower.)
When you do backspace so your cursor's not at the end of the current line of text that's been printed, printing more is in overwrite mode not insert mode. There are more ANSI commands to address this incorrectly: the ansi P command will delete the character at the cursor and pull the line to the left, but if you cursor up and do this it still won't pull characters from the line below, instead it will leave a space at the right edge and BREAK THE LINE so it wraps as two independent lines now. No seriously, try doing yes 123456789 | sed 20q | xargs; echo -e '\e[2A\e[P\n' in an 80x25 terminal and then change the terminal width.
Here's an even crazier one: the @ command inserts characters (which you need to do in insert mode), scrolling its line to the right... but it only scrolls the CURRENT row. Anything that goes off the right edge is deleted. But the multi-line string ISN'T BROKEN when you do this, it still wraps as one long multiline entity, now with spaces inserted at one point and corresponding chracters yanked out at a point further along (where the right edge of the screen was one that line). (If you replace the P with @ in the above example, doing 3P makes it slightly ore obvious. I also did 10P to see if maybe it was "column edges with space vs non-space" like cut and paste does, but nope. Doesn't seem to matter.)
I can't just clear the screen and redraw it a lot because I don't HAVE the historical data. (I can neither read nor directly control the backscroll buffer, that I know of.) Some other program ran and wrote output to the terminal, then my shell ran and wrote stuff. The fact I'm trying to do interactive line editing is a somewhat transient state of affairs patching the behavior of this historical text buffer in situ, but I can only move in SCREEN coordinates to affect multi-line backscroll buffer text entries, which aren't the same thing.
Oh, XFCE also has terminal resizing bugs, by the way: the "resize -s ROWS COLS" command works, and yes it's in that order so 80 by 25 has to be "resize -s 25 80". EXCEPT, if you try to change the number of columns it doesn't actually change but it THINKS it changed, when you're in 80 x 25 and you say "resize -s 80 25" the screen then lies about its width while you're resizing it and refuses to go what it THINKS is 4 columns but is actually more like 40. (it thinks it's hit a minimum early). And I haven't found a way to fix it except closing every tab in the terminal window so I can close that terminal window and open a new one that isn't borked. (My other attempts to resize just made it worse, deltas from where it was in the wrong direction.)
I remember arguing with this long ago, and putting line editing back on the shelf...