Rob's Blog (rss feed) (mastodon)

2025 2024 2023 2022 2021 2020 2019 2018 2017 2016 2015 2014 2013 2012 2011 2010 2009 2008 2007 2006 2005 2004 2002


March 31, 2026

So many weird little demands on time, mostly spinning out of the Signal groups set up to counter ICE and now being used for general community stuff.

Stood anti-ice watch in front of the "education center" a block away (ESL school, day care, and job training) twice today (and twice yesterday), once the half-hour shift I signed up for and once because somebody called out sick for an earlier slot and I'm right around the corner.

Some lady needed help moving (she's not supposed to lift heavy things so soon after her heart attack), and I biked there and put in 45 minutes. She was only paying $1200/month for an (admittedly old) entire house, we're paying more than that for a 1 bedroom apartment (new construction in an excellent location). Broke my bike's front wheel reflector trying to put it back up on the racks, I should take it to the bike store I got it from and have them fix it.

Talked to the apartment across the street about the big empty grass area between them and the gas station, and they say they don't own it (the city took/bought it from them years ago), so yes it _is_ correctly marked on google maps as municipal greenspace (but too small to be a named park). I want to put a community garden there, and am trying to work out the process. (There's an online map of community gardens that says there's another one on the block, but that turns out to be inside said apartment building. (They have one inside the building for residents. Light court I guess?)

That said, I emailed the people who maintain the map on the theory they might know the procedure for getting a community garden recognized by the city (so they don't mow it) and maybe testing for lead in the soil or something? Needing raised beds would make it WAY harder to garden, although maybe flowers for a few years could soak up the lead? There's remediation strategies. It's had 30 years of constantly being rained on since 1995.)

(I stole a little bit of dirt from it to start my tomato seeds in a cardboard egg carton, on the theory that even if the soil's terrible it's a couple ounces going into a big pot of store bought soil. Not that I tested the store-bought soil for heavy metals or PCBs either. Or invasive species for that matter...)


March 30, 2026

Laptop battery was dead again when I pulled it out of the bag, it still isn't configured to wake up and suspend-to-disk when the battery keeping the DRAM alive runs out. (It lasts 2-3 days in the bag, and the last time I downloaded email was 4 days ago.) *shrug* Getting used to it. It didn't come up much when my laptop was a thing I used every day, but now...

Ok, the hfd = 10 reset that seems out of place in run_lines() is already in expand_redir(), and the other obvious use for it is fpathopen() which is called from sh_main() to get a FILE * to our shell script which is called before expand_redir() or run_lines() ever gets called so will start at fd 0 (stdin). Right, that's a bug. (Resetting it extra times isn't bad because next_hfd() will find the next available filehandle and thus pass over used ones, it's just an optimization not to start at 10 _every_ time but remember the last one we used. So let's move that first reset to sh_main() and trust expand_redir() to do it elsewhere. It's not going off the top of the 1024 range without basically filehandle exhaustion, because even a call to "source" goes through expand_redir to get there.

Why is pp->urd in the sh_process instance? The lifetime of the redirects isn't the lifetime of the process: the process can live way longer (backgrounded or in a pipeline) than the unredirect context lives in the host. (The delete list belongs in the process because it holds temporary allocations used to construct the argv[] array that job control may need to print later, but the redirects are either for a NOFORK that returns and then gets immediately cleaned up, or they're for a child process that forks or vforks and then immediately gets cleaned up.

When we "exec 2>&1" it doesn't look like it frees the HFDs. It should free the HFDs. I don't think I have an ONLY free the HFDs option. I should add a test for that.

Hmmm, "echo | cat" needs to fork the echo because echo can output a lot of data (how much varies per kernel version and I HATE THAT) but in any case it seems like enough data to fill up the pipe buffer and block, which would prevent a NOFORK echo from returning which would hang the shell. The rule is any command in a pipeline runs as a child process even when it's a builtin, and it looks from the debug spam like it's not doing that. (Which is part but not all of the problem with the bug I've been trying to fix.) I should add a test for that...

Huh, "help ulimit" in bash says ulimit -p is pipe buffer size... in 512 byte units, and bash's ulimit -p says 8 hence 4096 bytes, but rm -f done; { echo $(seq 1 10000); touch done; } | while [ ! -e done ]; do sleep .1; done doesn't block. But seq 1 100000 does: 49k vs 589k output respectively. Meanwhile toybox's ulimit -p says 65536 which matches observed reality and has units in bytes so programs can parse the damn output. Grr, I want to make a test that reliably tests but the measuring plumbing is buggy and nonportable on the gnu side of the fence. (Before even asking netbsd.)

Right, seq 1 23000 produces a little under 131072 bytes of output which is big enough to hork the default pipe buffer but small enough to work under old kernels' environment space limitations.

How _do_ I make a test for echo $BIGSTRING | thingy where I want to check that echo exits when thingy doesn't consume its input? If thingy exits then the pipe _closes_ which unblocks the echo (hits EOF and the writes fail so it discards the write() contents and presumably notices and error exits if it's reasonably written). The problem with my first attempt is it's inherently TWO commands in a { block } which needs to get backgrounded whatever builtins it's doing. (Which I've implemented, and maybe that's a separate test but it's not what I'm trying to test HERE.) If thingy consumes its input that unblocks the echo...

Ah, duh: the second command can consume the pipe output, if the echo didn't background it would block BEFORE launching the next command. (Sort of the point of the test.) So piping it to wc -c or similar is fine.


March 29, 2026

Went as a delegate to the DFL caucus. Took all day. (Carpooled there at 9:30am, thought it might go until 5pm, it lasted until 8:30.)

Robyn won the nomination/endorsement, which is great. (Jamael's answer to THREE different questions was how he'd raise taxes on a different group each time, rather than try to understand how the machinery of local government works and actually fix anything. I'm all for guillotining the billionaires and pumping their loot back into the economy, but that's not the same as governing efficiently. At least one of his tax increases was sales taxes, which are regressive. Plus he went negative in the primary and Robyn didn't. The third candidate self-detonated on the first question by refusing to commit to ending their campaign if they didn't get the nomination at this conference, and were not taken seriously after that.)

I spent the rest of the day getting behind other people's agendas and pushing. (And wisting at large amounts of leftover cheese from lunch catering that I wasn't in a position to take home. And snarking at the convention organization: Robyn ran the caucuses before stepping down to be a candidate, and it shows. The new people were... new at it.)


March 26, 2026

Evening at my sister's making signs for the "even fewer kings" protest this weekend. Fade wasn't up for socializing (said hi in the parking lot when my sister came to pick me up) so we made one for her too.

(Monday I made it to the hyperlocal at the same church as the tuesday thing, which turned into a sign making arts and crafts thing after about fifteen minutes, but I didn't make one there because I'd already scheduled the evening at my sister's.)

My brother cornered me for 2 hours to tell me about his love for probiotics, so I missed the Monarca zoom on election defense, but there's apparently another one next thursday? Yay...


March 23, 2026

Fade has this week off (spring break), so I've been hanging around her rather than doing much programming. That said...

The sequencing problem with toysh pipes is it's doing the cleanup on the NEXT loop through run_lines(), not long into processing the next TT.ff->pl pipeline segment. But the "have I run out of input" test at the start of the loop is before that cleanup.

The pipe logic actually has two halves: "I'm leaving an output pipe for next time" and "I have an input pipe left over from last time", and yes both can be active at once ala the middle command in a "one | two | three" pipeline is both leaving a pipe for three and consuming a pipe from one. All that is set up AROUND run_command() because of flow control blocks: "one | if true; two; deux; dos; ni; fi | three" runs two, deux, dos, and ni, all with input piped from one and output piped to three. Which means pipes and redirects aren't JUST an attribute of individual commands but can persist within a larger context (hence the cleanup living at the blk level). And of course all this has to nest to make "one | if true; cat < potato; two | three; fi | four" work (where the output of "one" is consumed by "two", yes all this needs regression tests).

The flow control blocks are the reason the cleanup isn't just right after the block that sets them up finishes processing: for type 0 (commands) that's when we're done, but for type 1 (start of block) they get set up and then persist until type 3 (end of block) gets processed.

Except it's more complicated than that: flow control blocks each have THREE pipeline segments: a type 1 "start" segment, a type 2 "gearshift" segment, and type 3 pipeline segment, ala if/then/fi or do/while/done. When the type 1 segment is processed it looks ahead to the type 3 to perform the attached redirects, piping, backgrounding, etc. In between types 1 and 2 are "test" segments (usually type 0 commands to run but sometimes special syntax like "for ((;;))" or even OTHER BLOCKS because "if if false; then false; else false; fi; then true; fi" is valid shell). When you hit a type 2 it means you were running the test part of a flow control block so you look back at the corresponding type 1 to see what to do with the test's result. And if you hit a type 3 you look back at the type 1 to see if you're in a loop.

Speaking of which, I need a test to make sure "for i in one; do if break; then echo hello; fi; echo hi; done" cleans itself up properly. (It looks like it did last release, but I need to get a context with ASAN working again and enable leak detection...)

So pipes and redirects need to persist. The problem is the cleanup for "last time left me an input pipe" is currently too lazy, and happens after "I'm out of pipeline segments, read more input" which can read from the "last time left me an input pipe" place and treat it as code to run. Not because the function call stack has the wrong FILE *, but because we changed what the underlying file descriptors mean in a way that the FILE * doesn't know about. (The ANSI committe prentending C is not Unix was a mistake, and remains a mistake, leaving us with two different I/O systems that can get out of sync in a bunch of little ways.)

What's the sequencing of each pass through the run_lines() loop (operating o the sh_fcall TT.ff stack)...


March 20, 2026

Laptop rebooted. It resumed from suspend to a backlit but black screen, half a minute of poking at everything I could think of couldn't get a response out of it, nor did it suspend again when the lid closed, so I hard power cycled it. Lost all my open windows, which there were quite a lot of. (Tabsplosion in computing is sort of like black smoke in combustion: it means the process is going inefficiently and accumulating a lot of half-finished backlog to clean up later.)

The thing I _want_ to get done (completely ignoring email etc) is fixing the "echo | cat" bug in toysh. The problem is a sequencing issue with redirects: an interactive shell immediately exits after running that because the "read next line from stdin" reads from the pipe that just provided EOF to cat, not from the original stdin.

To support nommu the parent shell process performs the redirects on itself before forking off the child process, saving each redirection action to a list so it can undo them all again after spawing a child process that inherits those filehandles. Each call to save_redirect(urd, from, to) mostly does dup3(to, next_hfd(), FD_CLOEXEC) then dup2(from, to), unredirect(urd) moves the saved filehandles back down and closes the saved copies. (I say "mostly" bbecause for example <&- closes a filehandle for the child, which the parent needs to save and put back.) The call to next_hfd() returns an unused "high" filehandle starting at TT.hfd (reset to 10 each call to expand_redir() and incremented by the search), using the fcntl(TT.hfd, F_GETFL) trick in a loop to check whether a filehandle is open or not.

And this worked great for a long time, but when I redid/unified the function call list last year I broke it, because I made struct sh_fcall popping off the TT.ff lazy to ensure command line argument lifetimes would last longer than the command was using them (there's a string garbage collection list in there), but the unredirects in the same struct need to happen _before_ certain other things happen or you get the "echo | cat" problem.

Part of the problem is readline() wants a FILE *, which seems to save the fact it got EOF from fd0 and doesn't try to read it _again_ after we dup2() a new fd0 in place. So the strategy of "read from TT.ff->source, end_fcall() at EOF, loop" breaks if two things think they're reading from the global "stdin" variable (a static FILE * instance) but were actually trying to read from different file DESCRIPTORS.

And part of the problem is you can pipe at the end of blocks (ala "if true; do echo; fi | cat") not just between commands, so the pipe logic needs to be peformed on block type 0 (individual commands) and block type 1 (flow control start blocks) which means it can't live in run_command() which doesn't known/care about blocks but has to wrap _around_ it in run_lines(). Which is part of the reason run_command() can't deal with its own lifetime rules internally and there's this layering issue.

I think the malloc() lifetime issue that made me defer the TT.ff popping was backgrounding and job control? If I run thingy & and then go "jobs" I should see "thingy" in the job list, so it can't run garbage collection on the "delete" list expand_redir() saved its allocations into until the child process goes away. But that's why that delete list lives in TT.ff->pp which is a struct sh_process instance, which in the case of backgrounding gets transplanted out of TT.ff into TT.jobs. (I need to do another full pass on job control, I did most of it sitting at the tables outside the geology building at UT and got derailed by covid and work Jeff needed me to do on various projects and selling the old house and probably a bit of post-covid rain fog to be honest.

This is PROBABLY a fairly small fix if I can work out exactly what needs to happen, but it also smells like I've got the layering wrong and need to add a "here's a pipe" argument to run_command() so it CAN handle its lifetime stuff internally. (Which is only called from one place. It's not inlined because it's conceptually its own thing and the calling code is elaborate enough already.)

This is one of those "I need to sit down and FOCUS and afterwards I may actually wind up removing unnecessary complexity" things. Alas focus has been in short supply recently because anxiety.

No, moving the pipe stuff to an argument doesn't work for multiple reasons: it's transitional _between_ sh_pipeline instances (it's the output of one and the input into the next) and run_command() is only called for type 0 not type 1. This is why the unredirect list lives in the block stack (TT.ff->blk) so if true; echo one; echo 1; if true; echo two; echo 2; if true; echo three; echo 3; fi > three; fi > two; fi > one can reuse stdout 3 times to 3 different destinations each wrapping multiple commands and it all goes to the right place and unrolls again afterwards. You can even have redirects on the individual "echo" commands (or pipes between them) and it should all nest and unstack again properly.

Assuming the lazy evaluation and EOF being sticky in FILE * don't screw stuff up.

Hmmm, is the fix just not using the global "stdin" but instead opening a new FILE * at each level? No, it shouldn't BE trying to readline() from that with the wrong fd0, we already KNOW we've exhausted that function context and it should get popped before looping.


March 19, 2026

Okay, at least that's something. As a friend said, "The high-pressure scam thing really is a serious problem." And if they'd come out and said this was what they were doing up front, I'd presumably have made peace with it. But this smells like backing down in the face of the developer base rebelling. They did what they thought they could get away with.

Sigh, I should poke at cleaning up toysh, and treat "try to get the last ever version of Linux From Scratch building under mkroot" as a goal with a hard deadline of December 31 (by which time I need to force push an empty toybox repo to github, with a README explaining that Gavin "spyware" Newsom is why. (Ageless Linux put up a stalking horse explicitly trying to get sued by replacing the /etc/os-release file in Debian with their own ownership claim, and mkroot has had an /etc/os-release file for two years now. Which means $7500 per download fines, because Gavin "spyware" Newsom is copying Texas' model to enforce a law based on Ken Paxton's supreme court case. (How does ANYBODY think that ken doll is a democrat at this point?)


March 18, 2026

Largely checked out from programming. Vaguely looking at healthcare jobs, state government, or just applying at Aldi, but mostly curled up in a ball waiting for the Boomers to die.


March 17, 2026

I inadvisably clicked "send" on another rant at the google/android guys for being regime collaborators and generally enshittifying because I just don't find this fun anymore, and checked to see if my ELC talks were still pending so I could cancel them... but yesterday they approved a 1 hour rerun of "Simplest possible Linux System" and shot down the other two. (Including the one I Jeff and I were working on together, running Linux in VHDL simulation.)

Kinda wanna nope out of the entire ecosystem. If it's not standing up for itself on the age "verification" thing... I already have zero interest in vibe coded rust. Just like I had zero interest in "quantum computing".

The problem is programming's been my main hobby since I was 11. Before I ever heard of Linux, or the internet, or even bulletin boards. I started with BASIC listings in print magazines, thinking I could maybe get published in Compute's Gazette. I miss Linux User Groups and the #busybox IRC channel circa 2003. The linux-kernel mailing list was already too toxic for me to deal with in 2017.

I'm disgusted with _Linux_. And android. But I still enjoy puttering with programs the way other people enjoy crossword puzzles.

Doesn't mean I need to upload them anywhere though.


March 16, 2026

My android 12 "fit" app should NOT be constantly using network data (my step count and presumably location are nobody else's business; I walk around with my phone in airplane mode most of the time but it saves and dumps data to "the cloud" on the next reconnect) and of course the various youtube videos saying I can revoke network permissions from it don't work on my Pixel 3a running the last stock AOSP release (I can see how much data it used but not tell it to _stop_: the only permission it has is "physical activity" and yet it's used 251k of data so far since March 4).

I'm assuming the reason it's used 74k of background data even though I have background data toggled off is because the full description of the toggle is "enable usage of mobile data in the background". It will happily still send data to google's cloud every time I connect to wifi, without even opening the app! I cannot make it stop without installing a "third party firewall", which has the "ad blocker" problem of how do I know THAT'S not spyware...

I reinstalled adb from debian's repo and got my phone into debug mode, and google's horrible AI suggested a command for yanking network permissions from an app which of course didn't work. I looked down the page for an actual human saying how to do anything but Google can't find those anymore, but I eventually figured it out despite --help being an unrecognized option. (Google's LLM summary had the arguments in the wrong order. I only bothered humoring that at all because it's GOOGLE'S PRODUCT which I asked GOOGLE'S PAGE about, thus getting the wrong answer.)

And THEN the reason the command didn't work was because:

$ adb shell cmd connectivity set-package-networking-enabled false com.google.android.apps.fitness
java.lang.UnsupportedOperationException: setUidRule is not available on pre-T devices

I gave up and did a "clear storage" on "fit", and removed its permission to track steps. When I ran it again it wanted me to associate my phone's google account (exactly what I'm trying to AVOID) and agree to a terms of service (not happening, it's a STEP COUNTER). I'd rather not have the data myself than be constantly streaming it to somebody else's data collection server. Searched for alternative step counter apps and the consensus is I'd have to install f-droid. (Maybe I can get a standalone step counter for christmas. One that doesn't even know who I am. Walmart's got one for eight bucks but I don't want to give walmart money either. Random chinese sites have them for $3.)

So if you're wondering why I'm refusing to upgrade my phone... I don't trust Google's post Feb 5, 2019 management, and am slowly weaning myself off of depending on a phone for anything. I should get a wifi tablet to watch video with. (I download video from hidive and watch in airplane mode because that way it doesn't reset the app every time I reopen it, losing my place in the downloaded video. Hidive's app is terribly written, and will try to reconnect to its servers to show me an intro screen every time the app is opened, even if it had a paused downloaded video playing already. I similarly download stuff from netflix to watch it, although they limit downloads to twice a year for a given program. What I really need to do is get my own dvds, rip them to my laptop (legal if I own the DVD!), copy them to a local web server on one of those Orange PI boards (still need to set that up), download them to a tablet from the local IP, and then watch them while out walking. Heck, I could even use Fade's old Android phone with no sim card in it, just connect to wifi long enough to get files on it then disconnect again. Antennapod already seems to work like I want, although I expect it have to move to f-droid soon...)


March 13, 2026

I added swapon -a (somebody asked), and need to test it, which is a bit squishy because doing stuff as root on my development laptop is always nerve wracking. I want mkroot with multiple swap partitions, but last time I sat down to do that I went down the rathole of getting current linux building mkroot and don't want to reopen that can of worms JUST now.

Technically I added swapon -a, -e, -U, and -L to toybox because as long as I was there, I had todo items. Chopped the UUID and LABEL checking for swap partions out of blkid.c (it's tiny if you're only checking for one). And as long as it's parsing /etc/fstab it now understands noauto and nofail, which really means understanding "auto" and "fail" and the existing comma_scan() plumbing handles "thing" and "nothing" toggling what it's searching for on and off possibly repeatedly in the same string. (So prepend "auto," to the fstab option string as a default and then let it get switched off.)

Couple of judgement calls in there: swapon -a checks fstab but swapon "blah" doesn't (swapoff honoring "user" is an OOM killer waiting to happen), which means swapon /dev/sda2 won't honor "nofail" in fstab, you'd have to say -e. (But if you say swapon -ae it'll default all the entries to nofail and you'd have to put "fail" in the option string to error on those.)

Which of course raises the question of WHICH failures are covered by nofail. Presumably this was for swap being on removable media (or network block devices), and thus not always present? The scratched DVD was throwing read errors, I'm pretty sure THAT isn't the kind of error they were talking about. Also, swapon -a run a second time and the partitions already being mounted presumably isn't an error even in the absence of nofail? Or is it?

Which led me to run the host swapon -a under strace to see what it did and how it handled the return values... and it never called swapon(2) because it read /proc/swaps after reading /etc/fstab (and read /proc/partitions too for some reason) and then made no swapon() calls. Which just seems overengineered.

Huh, and the Devuan Daedalus install screwed up. I partitioned 16 gigs of swap space last time I reformatted this latop, and the system isn't using it. Instead the install created a 256 meg /swapfile in the root directory. (Which would explain a couple of Very Unhappy situations my laptop's gotten into since then: it has 16 gigs of ram but 1/4 gig of swap, when it runs out of ram that's basically it.)

I tried to check if that 16 gig partition with type swap is formatted for swap, but debian's "file" says it's a block device (yes I know) and file -k says... it's a block device. (What does "keep going" mean to you? Grrrr. Yeah I should have done -s but didn't think of it at the time.) Alright, try swapon... and /proc/swaps says it swapped on. (I don't THINK it auto-formats partitions. That would suck if I ever accidentally told it to swapon /dev/sda1 as root and it ate my root filesystem. Even gnu isn't THAT stupid? Bueller? Bueller?) Right, swapoff the other one, edit /etc/fstab to point to the right place, and hope next boot everything works out coherently.

Ok, I should do a mkroot with partitioned block device so I can do two swap partitions (one for -L and one for -U: it can't find swap FILES that way because it would have to search every file in the filesystem instead of just the partitions listed in /proc/partitions: unstable partition order remains a horrible thing the scsi bigots inflicted upon linux, which nobody EVER had to worry about until the scsi bigots broke it). And add a couple swap files so "nofail" and "noauto" have something to play with. And swapon/swapoff. (Hmmm, some tests are really testing MULTIPLE commands together. Design question...)

Actually, can I do all that via loopback without requiring a partitioned hda or block device? (Can linux mount a swap file on a partitioned loopback device? I don't know...)

Which brings us back to scripts/test.sh running under mkroot ala toysh. I don't just want to manually run tests, I want to record them in a regression test script. Runs as root, requires system to be in a special state.


March 12, 2026

Many moons ago I got Penn and Teller's "bullshit" series from Mark (which is quite good, and not available on any obvious streaming service), but I can only find seasons 4, 5, and 6. My local library has the first season, and I thought they might have the rest in storage because they're in a tiny space while their original building undergoes year-long renovations.

(The day Renee Good was killed was the first time I walked to their new place, in sneakers with the tread mostly worn off because I walk a LOT, and I slipped on the ice and sprained my wrist. I fell and hurt it AGAIN at the big Powderhorn Park protest that weekend, and it's JUST NOW holding weight again when I stand up or sit down on the floor. Might have broken it, but with a $20k annual deductible in my health insurance it's not broken ENOUGH to have a professional look at. My sister got me Big Clompy Boots and I haven't fallen once while wearing them, and I'm back in shorts now anyway because it's in the 60's. Miniskirt and go-go boot weather, breathy flutes, psychadelic tie-dye colors, etc.)

Anyway, the library did NOT have seasons 2 and 3 in storage, but they were able to get them through inter-library loan from what the stickers proclain to be the Rochester Public Library. And season 2 was great, but Seaons 3 does not seem to want to play in VNC. (I dug up a USB DVD player and installed the Linux plugin to VNC that lets it decrypt DVDs, but our game consoles are still in boxes, which are in my sister's custody: I dropped them off in her garage, but she emptied said garage into a storage unit when her furnace needed replacing and they needed the garage as assembly space. I've been there twice to take a couple boxes away each time, but am maybe 5% of the way through the total and it's sorting mostly for disposal because we haven't got anywhere in the apartment to unpack it TO. We did get another bookshelf though.)

I _think_the problem is DVD menu navigation? When you point VNC at a disk it doesn't give you a directory of files, it runs the menu scripts to do all the weird navigation things, and when I click on "play episode" VNC goes to a blank VNC logo screen as if the video it was playing ended. Possibly some kind of crash? I can probably dig up wherever it's mounted the decrypted filesystem and find the actual files and play the episodes, but haven't yet. This would go on the todo list except for the inherent deadline of having borrowed it from a library.

The third season 3 DVD is a bit scratched up and does a lot of seeking when it first goes in, then gives intermittent data read errors, but I've gotten the menu to come up and then fail to play episodes, which is the same problem disks 1 and 2 of that season (which seem clean) have. DVD menus are written in their own language which unfortunately seems to be called the "DVD virtual machine" which is a name basicaly impossible to google for, even though there are entire books on it.

Anyway, VNC implements this, but appears not to quite get it right in the case of this particular set of menus? Or at least I THINK that's what's happening? (Could be some weird copy prevention nonsense breaking a player, tale as old as Angela Lansbury.)

I also got Season 1 of Dragon Maid from the library, and have already returned it. But Season 2 is not in the inter-library loan system because it was only ever released on blu-ray, not DVD, and they apparently only do DVDs. Which I prefer because the extra resolution never did anything for me (I have terrible vision and tend to watch on small screens anyway) and our blu-ray player was the praystation III which is in a box in a stack of boxes in a storage cube in a cavern in a canyon excavated for a mine... I'm pretty sure the USB-DVD player I dug out of a box only does DVDs, not blu-ray.


March 11, 2026

Back to the state capitol to meet the house representative (1:30 in the Centennial building: when I asked for directions yesterday at the capitol the guard said "building that looks like it was built in the 1970s" and he wasn't wrong). With a day's warning, they could reserve half hour in a conference room. Fancy.

Except the representative himself (Samakab Hussein) was called away (one of his constituents got kidnapped) so I met with the legislative assistant. Gave her my pitch (she seemed convinced) and left her with three of the pages from the packet: the one they'd made two copies of, and two of my "talking points" things I was supposed to use, which had various statistics. Things like a quarter of minnesota's education budget is going to health insurance this year: any initiative you have to staff is borked by the out of control insurance industry. ("Health insurance is not health care" was one of the few useful talking points from yesterday's 3 hours. Very nice little chocolate mini-jelly-donuts though. From costco, apparently.)

Those pages _didn't_ say that United Health's profit was $12 billion last year: I looked that up myself. Every dime of which is money diverted away from providing care, and how is THAT not fraud? How is having people with no medical credentials making medical care decisians (I.E. denials) not fraud? Republicans scream "fraud" all the time because every accusation a confession (if they could mentally model other people, they wouldn't be conservatives). But the state has auditors and hospitals have a duty of care, while the insurance companies have an incentive never to pay for anything (deny all: they built an AI system with a 90% error rate HOW IS THAT NOT FRAUD)...

Anyway, she took notes and said she'd pass the info on to the actual legislator when he got back. Yay?


March 10, 2026

It's hca-mn legislative action day. Following up on thursday's zoom.

Minnesota is already paying for minnesota's healthcare, the goal of hca-mn is to remove billions of dollars of middleman profits and eliminate two enormous bureaucracies that exist to cancel each other out. Money that goes to insurance company shareholders does not go to care, each hopsital has staff fighting the insurance company claims denials and demands for pre-approvals. The fire department is never "out of network". the police don't have a deductible, public school teachers don't have a copayment.

Anyway, that was the elevator pitch I arrived with. I was told not to say any of that and to read verbatim from the scripts they provided, because hca-mn wanted legislators to "hear from their constituents"... but WHAT they should hear was the organizers words. We were there to be mouthpieces. Yay. (She didn't QUITE phrase it like that, but it was the gist. I did not say "fuck off" to her face, but it was close.)

This "legislative action day" is a coproduction of two sister organizations: Health Care for All Minnesota (HCA-MN) and Physicians for a National Health Program (PNAP). The first group is retired medical works and the second is retired physicians. (So the actual doctors and nurses in one, and everybody else who works at the hospital in the other.) I'm neither, I just thought hca-mn had a nice booth at the state fair and joined yet another mailing list. It _does_ mean that in my mid-50s my presence brought down the average age of the room, but they're fighting the good fight as best they can...

The day started with 3 hours of preaching to the choir, which I'd hoped would have more "training on how to do this" but no. It did have speeches from the two legislators behind the bills (an older gentleman with a bow tie and a middle aged lady in a tweed jacket). Both very nice, reasonably smart, and FRUSTRATING to listen to because they kept spending multiple minutes wrestling with issues you could sound bite in two sentences. (For example, when people opposing single payer health care lose the argument, they interpose a "public option" to drain support away from single payer. A public option is to single payer what school vouchers are to public education: divide and conquer, let the middlemen keep selling snake oil and sucking away public money from those they fool. The nice lady spent about five minutes NOT saying that, instead treating it as a hard problem to explain to people. No, it's just school choice vouchers in a new context. Look at it from the other direction and it's an obvious attack meant to undermine the system we actually want.)

The schedule sheet said I should contact my state house member and hand one sheet of paper to their legislative assistant. I tried to do this, but hca-mn secheduled their "legislative action day" at the same time as some other group that outnumbered us by an order of magnitude and were... I remember "aipac" but that wasn't it, they were making sure a tax on baseball statdiums didn't change because it paid for some education thing...? (The line into the centennial building's security checkin ran out the door and the person behind me and the person in front of me were talking to each other past me. They all had green folders with their acronym on them instead of the blue folder with my name on it that hca-mn had handed me. They were all twentysomething university students, not retirees. They were very loud, and they were wall-to-wall flooding the zone. Seemed more effective than what we were doing.)

Eventually got into the centennial building and directions to the corkboard area that had handout sheets with every legislator's phone number. Called my house member's assistant, waited fifteen minutes near the vending machines, and got a call back. (From "scam likely" but it was the number I'd called. Turned out to be the legislator's land line. Thanks google.) The legislator's assistant said she came down but could not find me in the crowd. We rescheduled for tomorrow.

Met my state Senator! The one who's retiring and Robin is running to succeed. (Secede? Successorate. Replace.) That was a proper appointment, at 2:30, in theory with a group of 6 of us (senators have larger districts than house members) but just me and one other person actually showed up. I did not even refer to the organizers' script, at least partly out of spite.

The other guy was a retired physician who worked for the VA so he had more to usefully say to her than I did, but she was already on board and our pitch was preaching to the choir. We reminded her which two bills were up this session. She took a picture of the two of us for her newsletter.

I still seem to be unusually good at in-person marketing, which isn't an endorsement of my skills but a commentary on how BAD most other people seem to be at it. It's just working out how to enthuse at people who DON'T already know what you're talking about, so you've got to hook them long enough to carefully target well-edited infodumps, preferably with some memorable one liners in there. I still can't close to save my life, but enthusing at you about a thing that's seriously cool? I've been doing that since I was five. (Plus I tutored in college and wound up with the difficult cases because I'd actually try to figure out how far I needed to back up, to where information could attach to what they already knew, clean up misconceptions, and fill in the holes THIS person needed. Then I taught night courses at the local community college early in my career (same but for groups), and wrote those stock market investment columns for 3 years (here's this cool thing I just learned), was the linux-kernel Documentation maintainer (tech writing), and of course I launched two science fiction conventions (recruiting the staff, guests, vendors, and attendees, both in person and running our advertising campaigns and the "heartbeat blog" and so on: cold pitches to new people). It all sort of slots together.

Again, can't close to save my life (I learned "marketing is not sales" studying Coca-Cola back in the Motley Fool days, my brother is a born salesbeing, I am not), but if I honestly think something is cool I can generally manage to spread the enthusiasm to a new victim. :)

But again, she was already on board. ("Not selling past the close" is another thing I learned along the way. Take the win and stop pushing.)


March 6, 2026

Went to Robin Gully's thingy at a brewery. (Within my definition of walking distance: about 2 and a half miles each way. Hey, the ice has mostly melted, not quite flip-flop weather yet but normal sneakers with one layer of socks.)

Met her husband, the head of the city's health care workers' union, who pointed me at the application process for healthcare jobs that provide health insurance with 20 hours/week. (I'm paying $700/month for my $20k annual deductible catastrophic-only plan, just making THAT go away would mean we could live on Fade's salary without dipping into savings.) And it pays a dollar an hour more than working at Aldi's, and offers a regular schedule because union.

(I really should look at programming jobs, but my industry went toxic, I don't want to move away from Fade for work, and it's just no fun anymore.)


March 5, 2026

The "how to lobby your state government" Zoom training for hca-mn.org's legislative action day on the 10th seemed generally useful, so I poked a couple of the signal chats about their next one on sunday.

Alas, their website doesn't have any useful info about this, it was just in the email newsletter (which is not on the website either!) so I can't link people to it. Their site currently has a full-screen pop-up about it when you go there, but it reads like an ad so I dismissed in the first couple times without it registering at all, and There's no actual PAGE I can link people to. (They have a google calendar that mentions it, but doesn't tell you much or send you anywhere useful from that day's calendar entry.)

So I cheated slightly and handed out the link to Sunday's zoom training, which is a sequence break but how ELSE am I supposed to get the word out? (For a lobbying organization they're terrible at online outreach. They had a good booth at the state fair, which is how I got involved, but that itself seems a bit of a weird way to recruit? Then again the organization seems to be entirely staffed by retirees, an impression the zoom training I just attended strongly reinforced.

Aha, they have LAST YEAR's training and toolkit online. The zoom call made a point that last year they had 4 bills up for consideration and this year they have 2 bills, so what they're lobbying for this time is less complex. I was going "hey, all those icewatch people are looking to pivot to more sustainable and impactful ways to help, and learning to lobby the state government seems like a good idea in general"...


March 4, 2026

Switched my phone off of T-mobile, because they advertised their partnership with starlink at me. (They're still the least worst option, mostly because they're majority owned by Deutsche Telecom and operate in accordance with German law which outlaws larges swathes of american enshittification and cyberstalking. But you do not get to ADVERTISE your partnership with Elon Musk at me and keep my business.)

Thought about going to that "boost" or whatever it is with an office next to the green line stop, but it turns out their underlying carrier is AT&T which is up there with amazon and faceboot in the evil department, so I went with my original first choice (mint), which T-mobile bought in 2023 so it's not REALLY a switch but it does cut what we're paying in half while protesting their partnership with Elon Musk's starlink. (When people online are making unpaid testimonials about it, probably worth a look. Although I think that was before T-mobile bought it. Ryan Reynolds was only ever a spokesbeing, he's not a techie actually making phone stuff better or worse.)

I break everything of course, but taking that into account the process was surprisingly painless. I needed my account number and a "transfer pin" to transfer the number, so I went to the closest t-mobile store a week and change ago, where I interacted with a man who insisted I couldn't do anything useful through him and had to do everything important over the phone (by calling 611). I came back an hour later to have them at least look up my account number because Fade set up direct monthly payment from our bank account (*shudder*), so I get texts from them about that (one with the amount and a second when they zero out the balance) but haven't received paper bills from them in years and I never set up an online account. (I go in to talk to humans when I need to. My flirtation with boost was because they had an office with people in it... but everything else was worse.)

I was talking to a nice woman who agreed to look up my account number... when the same man came up and interrupted the woman I was talking to and repeated that I could not be helped in that office while he drew breath. "He has to call 611, what he wants to do can't be done here." What I wanted to do was get my account number, which she was about to do until you interrupted and mansplained over her you fucking asshole (didn't say it to his face, wouldn't have helped). At which point I was ACTIVELY GLAD to be leaving T-mobile because it means I never have to talk to that specific man ever again. I DID NOT ASK FOR YOUR INVOLVEMENT. Sigh...

Anyway, after he derailed me I went home, and yes 611 got me a transfer pin and my account number but the agent was CONVINCED my phone was locked, despite me having purchased it by mail from Google and brought it _to_ T-mobile years ago. (I wanted the option to reimage it to do toybox development on android, but never did.) So I had to reinstall their t-mobile unlock app which said it had never been locked. (Which I ALREADY KNEW but their cloud server needed to talk to the app on the phone to override their bad account info probably left over from a legacy migration: I'd been on t-mobile FOREVER. Moved there from sprint in... I want to say 2013? Or did I move BACK to sprint and then get rolled back to T-mobile when they bought Sprint? I think those are the only two carriers I've been on since I got my first cell phone in the dot-com era, but I have a vague recollection of going back and forth more than once. Anyway: their account for me was borked, as usual.)

Fade and I then engaged with Mint's website long enough to learn A) it's cheaper to move our lines individually (that way we each get the introductory half-price year, which is 1/4 what we were paying before instead of 1/2), B) don't move the primary line FIRST or T-mobile will get confused, C) I wanted a physical sim not a digital sim which would take a week to arrive by mail.

So we had Mint mail me a sim card, during which the first transfer pin expired, and then we thought the sim card might be lost in the mail until we thought to check the package delivery room (The card is smaller than an SD card but of course it came in an envelope too big to fit in the mailbox. Since it wasn't a "package" and our normal US postal service being dropped it off, it wound up in the mail room without generating a notification that we had a package in the apartment's app. Of course the apartment has an app.)

So now I had the sim card, and Fade wanted an e-sim anyway, so we could transfer the lines! I called T-mobile's 611 again and got another pin, and had ANOTHER go-round with the "but your phone is locked!" people and REINSTALLED the unlock app and read what it said to them until they admitted their backend was wrong (again), and asked them if the previous agent had put a note in my file about this? (Apparently not.) And asked them to enter a support ticket against their backend after the agent noticed that although it said it was locked it didn't give her an option to UNLOCK it (there should be a pulldown, there was not: it was HARDWIRED as locked in the system somehow). Also, they noticed that the address they had on file for me was the Texas one (which hasn't even forwarded mail for most of a year now), and corrected it so they could send my last bill (except it's direct deduction from the bank account... but that may stop when the account gets canceled? Or something?)

And then with the new pin, we peeled Fade's phone off from the joint account and transferred it to T-mobile and everything went fine, and that whole process took like fifteen minutes.

And then it was my turn: I removed my new phone case (not disintegrating!) and Fade dug up a pin (physical poky kind) I could use to extract the old sim card (there's a little hole you have to poke, I used to have a metal tool for this in texas), and I put in the new sim and the phone went "mint" where it used to say tmobile, and I connected to the apartment wireless and downloaded the app and went through the proccess and everything was happy right up until the screen where I submitted the old account number, transfer pin, phone number, and zip code (presumably the current one since even t-mobile has now updated it although propagation delay...?) and it tried to transfer them... and it failed. Did not say WHY it failed. It let me retry! Which failed again.

So I took off the case again and swapped back to the old sim card so I could call 611 (which is not a generally useful number, nor one I could now call from Fade's phone which was on mint instead of t-mobile: it turns out there IS an 800 number for T-mobile which at the asshole at the store didn't give me but I did not have it at this point) and ask them what had happened. And they sent me to the transfer pin people, which generated me a new pin... which was identical to the previous pin. (Thrillingly secure, this whole process.) And then went "oh, your phone is still locked, obviously that's the problem" and transferred me to the phone unlock person. Again. Who wanted the t-mobile unlock app installed again. And I went "didn't the previous person leave a note in my account about this?"

During all this somebody said something that made me think "maybe I need to have the OLD sim in the phone while transferring the number?" (Which seems nuts: if I get a new locked phone from my new carrier, how do I transfer the number? I can't connect the new phone to the old carrier, isn't that what "locked" means?)

Nevertheless when I selected the mint app it opened to the retry screen, and I clicked retry now the t-mobile sim was back in it, and it went through! And suddenly the lady was saying that my phone had switched in her system to "unlocked", and I said it was because I'd just transferred the number and the old account was now closed. This coversation then went on for, I kid you not, six more minutes of me repeating obvious things I'd already told them and/or were self-evident. "Yes, your system was broken but the twelve year old record that obviously had some version skew and didn't survive system migrations intact got deleted when the account was closed. Because the account is now closed. Because I have already migrated the number to mint. As I said, I did it on the app while talking to you. The problem was I needed the old sim card in the phone to do it, which the instructions didn't specify. No the phone was not locked, if it was locked I couldn't have migrated it, which I have already done."

Six minutes. I didn't want to just hang up because I wanted acknowledgement that they wouldn't try to UNDO it somewhow to unnecessarily "fix" things.

So yeah, run the number transfer with the old sim card in the phone, THEN switch to the new sim card. They should say this in the instructions.

Haven't tried tethering yet (in theory I get 20gb/month) but it otherwise does signal and mastodon and streams videos about as well as it did before. (Maybe an extra 3 seconds latency starting a video at the beginning, which I don't care. Quality's the same. Youtube has decided that "shorts" display at the worst possible quality even on wifi, and are thus pixelated garbage half the time, but it was doing that a week ago.)


March 3, 2026

[Backdated entry, spent several days not sleeping well. Mostly figuring out WHEN things happened from my email "sent" box, what I posted to mastodon, and scrolling back in the household signal channel. Yes I got our household chat moved to signal when discord announced "age verification". Yes Fuzzy is still on it despite living in NYC now.]

Gavin "spyware" Newsom deciding to outlaw general purpose computing took away all desire to do hobbyist programming for a bit. Back to do basically janitorial tasks finishing up stuff I was in the middle of already. (And because the OpenBSD people pointed out they've been scrupulously under CANADIAN law all along ever since that was necessary to dodge stupid clinton-era "encryption is an ITAR munition" export regulation bullshit, so rebasing to OpenBSD remains an option. I'd still have to delete mkroot off the web since the Linux Foundation and its employees on linux-kernel immediately capituated and collaborated.)

And no, moving to another country wouldn't be enough unless I could also get citizenship in another country and renounce my US citizenship, thanks to Obama-era banking regulations meaning they can still 100% come after my money because US citizens can't get a foreign bank accounts anymore. The billionaire imposition of serfdom is well advanced at this point, kind of surprising the guillotines haven't come out. (Luigi doesn't count, a CEO is merely the highest ranking employee of a billionaire, they don't own the company they take orders from the owners and get replaced if they don't perform. It's nice to have goals, but sometimes you need to aim higher.)

At least Motorola parterned with GrapheneOS so I can get an officially supported non-AOSP phone to upgrade to, after Google destroys Android in september. (Although I'd presumably reinstall it with a version built from source to wipe Gavin Newsom's spyware. Eh, that's far enough in the future nothing's predictable these days...)


February 28, 2026

Tried to build mkroot against 7.0-rc1 kernel source and x86-64 can't find its initramfs. 6.17 still works fine. Bisected it to commit 3f0cbfb8a107 which CAN'T be the problem, and yet building that commit fails but building commit^1 succeeds so yes it's that patch: "riscv: add ISA extension parsing for Zilsd and Zclsd".

Wait:

$ git show 3f0cbfb8a107 | diffstat
include/asm/hwcap.h |    2 ++
kernel/cpufeature.c |   24 ++++++++++++++++++++++++

Those are not the two files modified by the patch? Ah, yes they are it just truncated the paths to the right removing the arch/riscv from the front.

All the files modified by this patch live under arch/riscv, which I am not building. I am building x86-64. Modifying files in some OTHER arch directory shouldn't be ABLE to break the current architecture, they DON'T GET PARSED. Did they fuck something up in the Makefiles?

The behavior change is "Failed to execute /init (error -2)" which is ENOENT I.E. file not found. What are the boot messages differences... Clock speed differences (bogomips etc) have trivial jitter.

-RAMDISK: [mem 0x0ff63000-0x0ffdffff]
+RAMDISK: [mem 0x0ff6b000-0x0ffdffff]

Why? (Just ASLR, or is that meaningful?)

-Memory: 242576K/261624K available (...18016K reserved)
+Memory: 242608K/261624K available (...17984K reserved)

Correlated difference.

-Freeing initrd memory: 500K +Freeing initrd memory: 468K

And again. What do the initramfs files say?

$ ls -o root*/x86_64/initramfs.cpio.gz
-rw-r--r-- 1 landley 511260 Feb 28 09:35 root2/x86_64/initramfs.cpio.gz
-rw-r--r-- 1 landley 476037 Feb 28 09:51 root/x86_64/initramfs.cpio.gz

The fuck? The working one is bigger. Why is it bigger. Because the other one doesn't have the sh and route entries from pending in the build. But that's BEFORE it looks at the kernel source? The build/airlock directories under root and root2 are the same.

This is beyond "this kernel patch can't be it", it's into "the kernel SOURCE can't affect this" territory. Is the new build plumbing changing behavior every other build? The ".config file already exists" vs ".config file doesn't exist yet" paths behaving differently in a way that ping-pongs between them?


February 26, 2026

Found out about Gavin Newsom's doxing law. (And Apple signing on to do worldwide doxing. And how android lied about backing down from killing sideloading.)

Didn't sleep at all last night.

Probably have to take mkroot down before Jan 1st. We'll see how the legal challenges go, but $7k fine/download for open source free speech under a supreme court that already affirmed project 2025's porn ban (everybody: into a burqua now)...

I'm used to the magats doing horrible things. They can't disappoint me and have tied themselves to an octegenarian fuhrer. It's the boomercrats, Elizabeth Warren sponsoring Kosa etc. We have to replace BOTH parties at the same time.

AOC modeling herself on FDR is why she goes by her initials and called it the "Green New Deal", and Nancy Pelosi dedicated the dregs of her career to preventing AOC from ever being able to give an "I welcome their hatred" speech in front of a cheering crowd. Only right-wing populism is allowed, left-wing populism that would guillotine the billionaires is never allowed as an option by the DNC.


February 25, 2026

I don't entirely understand Elliott's reasoning for android snapshotting the toybox header files. You can avoid recreating the genconfig.sh scripts, but make.sh writes several things into generated/ unconditionally. (The reason scripts/prereq has snapshot header files is it's not running make.sh, it's calling the compiler directly to make a binary from the headers it's got.)

Almost all the inputs consumed by make.sh and genconfig.sh are files checked into toybox: the exceptions are the .configure file you supply, and _used_ to run a couple of compile time probes to ask questions about hte system but the rewrite calls cc -E -dM - on empty input to dump all the compiler's predefined macros, and then greps through the list for a couple entries (FDPIC indicating nommu, and ANDROID indicating bionic) so it can set configure entries. Those are the only non-toybox data sources I'm aware of, everything else should be files in the repository. And the prereq stuff creates and uses a toybox-prereq binary to provide sed and such, which you could statically link against musl and snapshot instead if you wanted to...

(In theory I could remove $GSED and friends now that I've got the prereq plumbing, but I'm not ready to go there yet.)


February 24, 2026

Haven't been blogging much while ICE attacks my city, lots of mstdn.jp posts but mostly not about programming...

Still, "I look up and multiple weeks have passed" is a bit much. I thought getting my codeberg account up was in that gap (turns out it was last month), but... I never blogged about it? And I never _tweeted_ about it (well, mastodoned about it) nor posted to the mailing list, which came as a bit of a surprise. (Yeah, I was meaning to include it in the next release notes, but DUDE...) Mastodon itself is (intentionally) unsearchable, so I re-downloaded my archive and updated my mirror which lets me ctrl-f through for text. I've been posting there a LOT (too much, it's a stress reaction) but not about codeberg. Huh...

I went back and inserted some blog text about it on the day I did the git commit, which... may have been the day _after_ I got the account working? I don't quite remember at this point (which is why I blog: lab notebook).

Mastodon itself is (intentionally) unsearchable, so I re-downloaded my archive and updated my mirror which lets me ctrl-f through for text.

Went to Wendy's for the first time in forever, because while unpacking we found two gift cards Fade's parents gave us back in 2022, and they apparently don't expire. It's a very nostalgic experience, but I can see why they're dying. You cannot buy ANYTHING for a dollar here anymore. The "biggie bag" is $6 now, the burger and fries in it each got smaller, and the frosty keychain's gone up to $3. Their Dr. Pepper tastes like the syrup's been sitting in the pipes long enough for the aspartame to break down and stop being sweet, which takes at least 2 years. There's tape over the electrical outlets, and the padded seats have the tables upright over them with the chairs stacked on top, only the hard benches are available. There's still money on the gift cards so I'll probably be back, but it's not cost effective otherwise.

Poking at swapon -a (because somebody sent a feature request via Microsoft Github), and -U and -L while I'm at it, and I've got most of it in now (and UUID= and LABEL= fstab entries), although adding support for any of that to swapoff probably means merging the two of them into the same toys/*/swapon.c file so they can share the infrastructure.

The /etc/fstab traversal is common with mount but small, the UUID and LABEL checking is harvested from blkid.c but as a small specific check rather than a table traversal of lots of different filesystem types. A 3.6 rontgen solution, as it were...)

The problem now is I need to test it, and I dowanna do that on my laptop, so I need to set up a mkroot image with multiple swap devices. Hmmm...

Maybe the balcony solar bill here in minneapolis will pass? Here's hoping...


February 19, 2026

Cancelled crunchyroll back on the 5th, but the service was paid through for a bit, which ran out today. Their new "privacy policy" which had nothing to do with privacy (I am altering the deal, pray I dodn't alter it any further) was the last straw, but Fade clicked through it on the website to get to the "unsubscribe" page which coincidentally unlocked my phone's app (same account), which is why I could still watch a few more series to the end after unsubscribing.

I'd been noticing a lot of censorship in the episodes for months, as in rewatching series turned into a game of "what's changed since last time". (The first Dragon Maid episode on Youtube still has the original scene where you see Tohru's naked back from the waist up for a few seconds, but on the streaming service they've photoshoped it so Kobayashi is now standing between said back and the camera. Meaning the characters are no longer facing each other, one of them is yelling off into space while standing BEHIND the other, they had no reason to move, it makes no sense...)

Funimation used to have much less censorship than crunchyroll, so of course crunchyroll bought funimation (and then dropped half the series they used to have rather than migrating them over). Attempted monopolization does not endear a service to me: "you must use this you have no choice" ain't gonna fly with a linux user who's never had a faceboot account.

And the update before this one started sneaking ads into things, so far just "also on crunchroll" ads for some OTHER series with an immediate skip button, but I know how frog boiling works.

And of course I watched 2/3 of "Noble on the brink of ruin" with what HAD to be AI generated subtitles, such as "Flammable soil? Oh, you mean flammable soil!" when someone was spreading asphalt to make a road. (That is not a _human_ failure mode. The whole story was just inexplicably bad in a "how did something with a plot this incoherent get this much spent on its animation" until I figured out the translation was utter garbage and MAYBE there was a story I wasn't getting.)

If they don't go out of business, their successors won't learn.

Before that we canceled Hulu, so Fade could get Apple TV long enough to watch Murderbot (which was to the books what the in-show Sanctuary Moon clips are to the rest of the show, and my mental model of Murderbot is basically Black Widow, not a dude. The author's a woman (she/her pronouns and everything), and Scarlet Johanson would have done MUCH better playing THIS androgynous killing machine than that "avatar: the last racebender" live action anime remake I didn't watch. Americans can't do Dr. Who and should not attempt to remake anime either. I mean yeah, Boris Scherbina's kid did a good acting job, but androgynous and capable of blending into a crowd he was not. Being miscast is not a question of talent or skill.)

Trying to get my money's worth out of Hi-Dive before that enshittifies as well. (I'm expecting it to be externally imposed by Project 2025, which is now being pushed by blue dog democrats jumping on the "sex: the boomers are done with it, scrub all mention from society" bandwagon. I know society has pendulums, but going from legalizing gay mawwiage to bringing back the Comstock Acts? Really?)

To be honest, Netflix has about as much anime as any other service. And that's without a VPN.


February 7, 2026

I get (and respond to) emails:

On 2/2/26 06:19, XXX wrote:
> i guess i'm just writing this email because i want some advice i'm 20 and i
> feel stuck i have no direction i have the same interest as you but i'm not
> as good as you idk any path i should follow i dont wanna be a developer
> because man thats just going to get taken over by ai well i mean
> everything will get taken over by ai in tech idk i just wanna make money
> hahah

I'm not sure I have a lot of advice. I've never focused on what was lucrative, I focused on what was fun enough that I could keep at it without jumping off my balcony when I got home from work.

I fell in love with the idea of computers when I saw my grandmother's atari 800 with a basic cartridge (this thing does what I tell it to do!). My family got a commodore 64 for christmas when I was 10 and by new years it lived in my room. I've been banging away at them for fun ever since.

I resisted doing a computer science degree in college because I thought that might take the fun out of it (wound up with a double major because I took comp-sci courses in things I'd already self-taught to pull up my GPA until the second major basically fell in my lap).

That said, back when I had more energy I taught night courses at community college (in programming, because that's what I had a degree in and they cared) and wrote stock market investment columns for 3 years (no credentials whatsoever but it was the dot-com boom: The Motley Fool was just starting and they thought I asked good questions on the web forums). Neither earned even a quarter what my day job did but they were basically "hobbies with an externally imposed deadline to keep me doing it, and somebody specific who would be disappointed in me if I didn't".

There's no amount of money you can earn that you can't spend. To make ends meet I kept expenses down (paid off my student loans, cut up my credit cards, etc. I have a debit card but no _credit_ card, and yes that makes renting cars really difficult). And then put money into things I couldn't easily take it back out of (for example I bought stock with a dividend reinvestment plan and did NOT connected it to my bank account but instead mailed them checks: it takes a month to get money BACK out of that sort of thing, you mail in the form asking them to sell some, they process those forms in batches twice a month, they mail you the result as a check). I am VERY BAD with money, so I just expect it. If I have a credit card I will run it up, so I don't have one. (I pay cash for as much as possible, both so I can physically see the money leave making it real, and because reporting every transaction I make to the right-wing loons trying to outlaw birth control in a system that controls who is ALLOWED to receive money, with https://thenib.com/payment-processors-vs-porn/ transitioning smoothly to https://www.theguardian.com/world/2025/jul/29/mastercard-visa-backlash-adult-games-removed-online-stores-steam-itchio-ntwnfb to https://www.cnn.com/2026/01/26/tech/tiktok-ice-censorship-glitch-cec and just... I'd like to keep alive this quaint tradition of anonymous payments with no special permission required of sender or receiver and no tithe to billionaires extracted...)

Beyond just "not spending it all at the first crisis" (I.E. THE HARD PART), savings is about multipliers, not addition. At a certain point compound interest is going to do more for you than earnings will. Sad truth of capitalism. (I.E. the current dominant religion; praying five times a day towards mecca? That's nothing, we have ad breaks every 8 minutes. Viewing it AS a religion may help to cope with it: money is made up the same way football scores are, but if you tell a priest banker that they'll burn you at the stake evict you to freeze/starve under a bridge.)

If you can save $1000/year and it earns 10% annually (the average return of an S&P 500 index fund) then as soon as you have $10k saved up the interest is contributing more than your savings are. On average, anyway, reality is a lot more volatile, but in the long run it's averaged out that way for centuries now.

The big thing to keep in mind is the Boomers are lead poisoned, because of "leaded gasoline" back in the 1920s through 1990s. They inhaled MASSIVE quantities of tetraethyl lead exhaust, both pediatric and chronic exposure, and it got in the water and in the food and everywhere. They could compensate when they were younger (used tons of coffee and cigarettes cocaine and such to overcome the cognitive deficits with extra effort), but once they started going senile they became the most gullible and stupid generation in history.

The start of the baby boom was 1946 (D-Day plus 9 months) and the midpoint of the Baby Boom was 1955 (half of all boomers were born before then according to the census people). The actuarial tables say the average lifespan in the USA is 79 (well 77 after covid but...) and 1955+79=2034. Which means the LD50 on the baby boom is still most of a decade out, and we'll have to deal with them succumbing to every nigerian spam email and our phones all ringing off the hook with "medicare advantage" fraud until then. And the primary example of elder abuse is the maga movement. (There's always been a crazy 27% but stack mass elder abuse from lead poisoning on top of that and you get the modern political environment.)

Which means that somebody a lot younger than me (Gen X) may be able to wait this crap out and rebuild afterwards. Somebody like me is likely to be well past retirement age before enough Boomers are dead for the fever to break and actual rebuilding to start. (Medicare for all, universal basic income delivered via postal banking, real privacy protections)


February 6, 2026

Linux From Scratch has announced its end of life, which I guess means it's no longer a moving target which should make having mkroot build it easier?

Cancelled crunchyroll. I'm not gonna pay money to help them make the world a worse place. (You don't have to learn, you can die and thus make space for someone else.)


February 5, 2026

The "hamline/midway coalition newsletter", a snapshot of a couple dozen blocks between Minneapolis and St Paul fighting off a fascist invasion.

Music fair! Constitutional observer training! Parking updates! Blood drive! Zine making! Community Conversation with Parks Director Andy Rodriguez! Stand with our community at Masjid Da’wah! Sidewalk salt recommendations! Food Pantries! Three places to report ICE activity! Diaper, Formula, Hygiene, and Medical Supply Hub!

(So much more on mastodon than here. Who knows when this'll actually get posted...)


February 3, 2026

Submitted a few talk proposals to ELC. The one I really WANT to do is Jeff and me running Linux under VHDL simulation, which could really be multiple talks (do you want more of a "making a real product" focus or more "using this for Linux bringup" focus)... heck just a survey of what all the things you need to get working in the full ecosystem (toolflows, toolchains, RTOS which is your rom bringup even if you then load Linux, board design/manufacturing/testing with FPGA, mask and asic manufacturing and packaging and mounting and how you get your tape of chips into _their_ board assembly inventory across customs and language barriers...)

And while I was there I proposed a mkroot walkthrough talk, and a redo of Building the Simplest Possible Linux System recycling the 2017 talk description (hopefully trimmed down into something that MIGHT fit in an hour)...

We'll see what (if anything) the committee bites on.


February 2, 2026

Crunchyroll just forced an app upgrade (second time in a month, "you cannot continue with this version") and there's a new TOS you must agree to (I have not) full of "teenagers aren't people" and "VPN verbotten" clauses.

Thinking of cancelling. Plenty of anime on netflix and hidive, and I should get more DVDs. Crunchyroll is censorship central and it's started playing ads before videos (with an immediate skip button so far but only to boil the frog) even before this.


January 31, 2026

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.


January 24, 2026

ICE murdered another observer, bit distracted today.


January 23, 2026

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.)


January 22, 2026

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.)


January 21, 2026

I still dunno why I never receved copies back of this post, but I posted to the list again today and THAT one I got a copy sent back to me. So yay.


January 20, 2026

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.)


January 18, 2026

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...


January 16, 2026

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


January 12, 2026

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).


January 11, 2026

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...


January 10, 2026

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...


January 9, 2026

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.


January 8, 2026

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.)


January 7, 2026

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...)


January 6, 2026

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.


January 5, 2026

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.)


January 1, 2026

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...


Back to 2025