HNHacker News
TopNewBestAskShowJobs

spc476

3,328 karma · joined July 9, 2008

blog: http://boston.conman.org email: sean@conman.org
submissionscomments
spc476··on C's Flexible Integer Sizes Were Not a Design Mistake
The _MAX and _MIN, along with CHAR_BIT, was defined for C89 (the first standard for C) 37 years ago, so it was possible to choose the appropriate type. I recall using the C preprocessor to define fixed (or at least, minimum) types for needed values:

    #include <limits.h>
    #if INT_MIN == 32767 && INT_MIN >= 2147483647L
    # error too small
    #else
    # error just right
    #endif
It was C99 (27 years ago) where we got the fixed sized integers. So how do you define "relatively" here?
spc476··on Web security is too hard
It's probably easier for the marketing department to get a new domain up and running that it is for a new subdomain within their own company. Battling Business Units and all that.
spc476··on Teach yourself programming in ten years (1998)
The two major distinctions in computer languages (in my opinion) are declarative and imperative.

For declarative, where you describe what you want, not how to get it, you have Prolog, Make and SQL (maybe others but I haven't heard of them). Yes, they technically aren't purely declarative as they usually have an escape hatch to imperative for performance reasons, but you can get quite far with them just in a declarative style.

The imperative, where you tell the computer how to do something, you have procedural (Pascal, Ada, C, BASIC, Cobol, Fortran) that's your classical programming style of actions working on data. There's object oriented (Smalltalk, Java, Erlang) which structures things a bit differently than procedural, where data is told what to do (via methods or message passing). Functional languages are more about avoiding globals and controlling side effects (and typically are lazily evaluated, but I don't think that's foundational to functional). You have concatenative (Forth, Postscript, Joy) which centers around a point-free style of programming (implicit data on the stack instead of explicit in variables) and data-flow (or array-centric) languages (APL, J, K) which work natively on array data.

Each of these paradigms have their pros and cons. Procedural if you have a lot of actions on a small set of types. Object oriented if you have a lot of types and a small set of actions. Functional if you want easy-to-reason about code. Data-flow to help with parallelism. Concatenative if you don't want to name piece of data. Declarative to have the computer figure things out for you. All of these I can see a reason to use in production.

spc476··on I don't think AI will make your processes go faster
TCC did several years ago. It could boot Linux from source in under 10 seconds. It's wasn't that big of a C compiler. It's in the 50,000 lines of code range.
spc476··on IBM didn't want Microsoft to use the Tab key to move between dialog fields
Microsoft never removed it for MS-DOS. It just undocumented the calls required for this for years.
spc476··on Comparing the Z80 and 6502 to Their Relatives
In general, yes, the linker (if there is one) would have less to do.

Position independent code (PIC) on the 6809 is pretty easy [1], but it does increase the code side a bit, but the resulting code can be placed anywhere in memory with no changes and still work. As mentioned, Motorola intended to sell a ROM with IEEE-754 floating point routines for the 6809 (as the MC6839) that was PIC. As far as I could tell, they never did sell the ROM, but they did provide it (with source) for anyone to use.

[1] Relative branches instead of absolute jumps, using the index registers to address memory, as well as addressing relative to the program counter. You can still do jump tables, but instead of a list of addresses, they're just a list of relative jump instructions. That type of thing.

spc476··on Comparing the Z80 and 6502 to Their Relatives
I suspect the shadow registers were there to improve interrupt handling, reserve their use exclusively to an interrupt handler, and you could save time in not having to store registers in memory.
spc476··on Should QA exist?
At a previous job, the team I was on [1] had a dedicated QA engineer (unofficially---he was the only QA engineer that ever worked with our team). Before we got bought, we worked closely with the QA engineer. He had access to the source repo, could compile and test our stuff, and we constantly told him of new features we were working on to give him a heads up. During this time, we were our customer's (yes, we only worked with one customer, who was paying us seven figures per month for service) favorite vendor. Over the 10 years or so of this time, we had like two regressions hit production, and those were found during deployment and we could roll back immediately.

We then got bought out and new management put in. They siloed QA and made it impossible for us to even talk to them about what we were doing. Within a year, we had one deployment fail four times in a row and went from favorite vendor to "utter trash vendor we can't get rid of." Our QA engineer quit, as well as the rest of the team (I was the last to leave). I'm still surprised they still have that customer.

[1] We were the only team having to deal with SS7. It wasn't easy hiring programmers for it, and I think at the highest head count, we had like five members (including the manager when we had one [2], but not including QA, which was "officially" never a part of our team).

[2] If it was tough hiring programmers to deal with SS7, it was even harder to hire managers to deal with programmers dealing with SS7. I think for half the time I was there (over 10 years) I had no official manager and reported to a director or higher in the company.

spc476··on Hollywood Enters Oscars Weekend in Existential Crisis
I went through the lists. In 1985, of the top 10 movies, you had two direct sequels, two adaptations, leaving six original movies. In 2025, of the top 10 movies, you had two direct sequels, two remakes, three franchises (maybe sequels?), one that is a part II (so sequel?, also an adaptation), one adaptation and it seems one original movie. My, how times have changed.
spc476··on Hollywood Enters Oscars Weekend in Existential Crisis
Survivalship bias. Here's a list of movies released in 1985: <https://en.wikipedia.org/wiki/List_of_American_films_of_1985>. How many of those are good? How many have you heard of? Here's a list of movies released in 2025: <https://en.wikipedia.org/wiki/List_of_American_films_of_2025>. Same questions.
spc476··on Build Your Own Forth Interpreter
I've already done that---ANS Forth for the 6809 (https://github.com/spc476/ANS-Forth).
spc476··on I still don't understand this SYN attack, but now I can block it easily
When in the past you learned that the recommended value for the TTL was 64 and you didn't think any operating system would pick a value much larger than that.
spc476··on I still don't understand this SYN attack, but now I can block it easily
I'm checking the TTL of IP packets, which is only 8-bits in size, and in practice, are decremented per hop (the early IPv4 RFCs state it is in seconds; I doubt it was ever used that way). DNS TTLs are 32-bits in size and represent the number of seconds a DNS record can be cached, They are separate from the TTL of IP packets. The TTL for CDNs is specified in HTTP headers and again has its own specification.

Getting back to TTLs for IP packets---I recalled the recommended TTL of 64 from admittedly years ago. I just now checked my copy of _TCP/IP Illustrated, Volume 1_ by W. R. Stevens, published in 1994, so yeah, a few decades ago. Of all the Unix systems mentioned in that volume, they all defaulted to a TTL of 60, except for Solaris 2.2, which used 255 (surprised me!). I no longer have access to Solaris to check (did at my previous job) but I don't think there are many people using Solaris to view my site.

I've checked the page you linked, and they don't link to the source for the table given, where the various values of TTL denote forwarding scope or range, nor have I ever seen such a table before. I know my Linux and Mac OS-X systems use TTLs less than 70, and I can get content from other continents. My comment on that: [citation needed].

Wikipedia (https://en.wikipedia.org/wiki/Time_to_live) at least links to references, so I found a list of TTLs per OS (https://web.archive.org/web/20130212114759/http://www.map.me...), but given the OSes listed, it's probably also from a few decades ago, but the majority are around 60, with Windows NT being 128, Solaris 255 and VMS anywhere from 60 to 128 (depending on version). So the TTLs being over 100 makes sense for what I was seeing---possibly a bunch of zombie Window boxes participating in a half-assed SYN attack using Brazil IPs for some reason. I can't say I'm horribly upset at that. But actual readers on Windows is concerning. I have no easy way to test for that, and I'd hate to go back to having ~100 half-open connections on my server.

spc476··on I still don't understand this SYN attack, but now I can block it easily
Yes.

Yes.

No, it's always port 443. But yes, the destination doesn't ACK the connection.

No, the TTL just means it can make more hops; it doesn't mean the connection is kept open for longer.

No, the IP addresses are unique and rarely repeat.

spc476··on I still don't understand this SYN attack, but now I can block it easily
The destination IP address is my server, the one being attacked. I don't see the significant of the high-value octets.
spc476··on How I learned everything I know about programming
Yes.
spc476··on Why 451 Is Good for You – Greylisting Perspectives from the Early Noughties
Unless you whitelist the notification email, which I've has to do a few times.
spc476··on Why 451 Is Good for You – Greylisting Perspectives from the Early Noughties
In my 19 years of greylisting, I have yet to have legitimate email fail due to it. And it was one of the easiest ways to significantly decrease the amount of spam. It's been worth it in my opinion.
spc476··on AI is forcing us to write good code
You forgot difficult. How do you test a system call failure? How do you test a system call failure when the first N calls need to pass? Be careful how you answer, some answers technically fall into the "undefined behavior" category (if you are using C or C++).
spc476··on Project Gemini
There was (and still is to a degree) a group of people critical of TLS. One half of the group (which I think you belong to) bitch about it being mandatory. The other half bitched about the use of TLS instead of <bespoke encryption system they just read about that is better/easier/smaller than TLS>. TLS was the main point of Gemini.

And about the lack of file size: I proposed a way to sneak it in, and it was rejected outright. Oh well.

spc476··on BlackRock's Larry Fink: "Tokenization", Digital IDs, & Social Credit
Old Soviet joke: government pretends to pay us, we pretend to work.
spc476··on Singapore to cane scammers as billions lost in financial crimes
William Gibson got a lifetime ban for calling it "Disney with the death penalty" in a Wired article.
spc476··on </> Htmx – The Fetch()ening
And OpenAI was a non-profit. "Was" being the operative word.
spc476··on The hardest program I've ever written (2015)
If I didn't want opinions, I'd join a cult.
spc476··on Why do some radio towers blink?
Changing a radio tower light bulb is not for the weak of heart: https://www.youtube.com/watch?v=9b9LahaBJIk
spc476··on Tags to make HTML work like you expect
Such questions can be jarring though. I remember my "Unix Systems Programming" class in college. It's a third year course. The instructor was describing the layout of a process in memory, "here's the text segment, the data segment, etc." when a student asked, "Where do the comments go?"
spc476··on System.LongBool
And you can take the address of a _Bool, so it must be addressable, so the least it could be is sizeof(bool) == 1.
spc476··on Vibe engineering
And in my experience, it always comes down to "you're holding it wrong" or "that LLM is older than 20 minutes."
spc476··on Why I chose Lua for this blog
XSL is neat, and it is a functional language, but between XSL and XPath, it is quite verbose. Here's a small section of XSL I use to generate my website (not my blog):

    <xsl:choose>
    
      <!-- ... other code -->
      
      <xsl:when test="name(.) = 'subsection'">
        <xsl:choose>
          <xsl:when test="not(boolean(ancestor-or-self::*/@next)) or ancestor-or-self::*/@next != 'rev'">
            <xsl:if test="boolean(following-sibling::subsection[@listindex != 'no']/attribute::directory)">
              <link rel="next"  href="../{following-sibling::subsection[@listindex != 'no']/attribute::directory}" title="{following-sibling::subsection[@listindex != 'no']/child::title}"/>
            </xsl:if>
            <xsl:if test="boolean(preceding-sibling::subsection[@listindex != 'no'][position()=1]/attribute::directory)">
              <link rel="prev"  href="../{preceding-sibling::subsection[@listindex != 'no'][position()=1]/attribute::directory}" title="{preceding-sibling::subsection[@listindex != 'no'][position()=1]/child::title}"/>
            </xsl:if>
            <link rel="first" href="../{../subsection[@listindex != 'no'][position()=1]/@directory}" title="{../subsection[@listindex != 'no'][position()=1]/title}"/>
            <link rel="last"  href="../{../subsection[@listindex != 'no'][position()=last()]/@directory}" title="{../subsection[@listindex != 'no'][position()=last()]/title}"/>
          </xsl:when>
   
          <xsl:otherwise>
            <xsl:if test="boolean(preceding-sibling::subsection[@listindex != 'no'][position()=1]/attribute::directory)">
              <link rel="next" href="../{preceding-sibling::subsection[@listindex != 'no'][position()=1]/attribute::directory}" title="{preceding-sibling::subsection[@listindex != 'no'][position()=1]/child::title}"/>
            </xsl:if>
            <xsl:if test="boolean(following-sibling::subsection[@listindex != 'no']/attribute::directory)">
              <link rel="prev" href="../{following-sibling::subsection[@listindex != 'no']/attribute::directory}" title="{following-sibling::subsection[@listindex != 'no']/child::title}"/>
            </xsl:if>
            <link rel="first" href="../{../subsection[@listindex != 'no'][position()=last()]/@directory}" title="{../subsection[@listindex != 'no'][position()=last()]/title}"/>
            <link rel="last"  href="../{../subsection[@listindex != 'no'][position()=1]/@directory}" title="{../subsection[@listindex != 'no'][position()=1]/title}"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>

      <!-- ... other code ... -->
    </xsl:choose>
And yes, there is other code I've omitted for brevity. This is used to generate the navigation links for the site. I initially write this ... prior to 2009 (that's when I moved it into git). There have been some minor fixes to the XSL over the years, but it's largely unchanged (for a reason that I hope is obvious). Yes, I still use it, because it still works, and it's for a static website.
spc476··on Things you can do with a debugger but not with print debugging
The hardest bug I had to track down took over a month, and a debugger wouldn't have helped one bit.

On the development system, the program would only crash, under a heavy load, on the order of hours (like over 12 hours, sometimes over 24 hours). On the production system, on the order of minutes (usually less than a hour). But never immediately. The program itself was a single process, no threads what-so-ever. Core dumps were useless as they were inconsistent (the crash was never in the same place twice).

I do think that valgrind (had I known about it at the time) would have found it ... maybe. It might have caught the memory corruption, but not the actual root cause of the memory corruption. The root cause was a signal handler (so my "non-threaded code" was technically, "threaded code") calling non-async-safe functions, such as malloc() (not directly, but in code called by the signal handler). Tough lesson I haven't forgotten.

Page 1 of 34Next →