1. 44
  1. 11

    GNU grep ships as a standalone executable (or at least, when I run which grep and dpkg -L grep, I don’t see any packaging dependencies for /usr/bin/grep)

    With ldd /usr/bin/grep on Arch I get dependencies on linux-vdso.so.1, libpcre.so.1, libc.so.6, libpthread.so.0 and /lib64/ld-linux-x86-64.so.2. Not sure, if any of these come shipped with Linux itself, but Arch at least lists glibc and pcre as package dependencies. Maybe it’s statically compiled on Debian-derivates? But is this even possible?

    One thing I know I can’t do for my personal projects is constantly dedicate time to working on it after I’ve “shipped”.

    I think this sentence describes a negative feeling which bugs me since a few years. When I was younger I constantly fiddled with things, but nowadays (with a job in software) I feel tired about my hobby projects and just want something to be finished, completed, working. And then continue with another hobby. And when I then decide to run my software again after 1 or 2 years I still want it to run. Which is something that with my current main language Python can break, e.g. because in Python 3.5 or so they made await a reserved keyword, so existing libraries broke. Maybe I should start writing C, not so much stuff changing there (every 10 years a new standard or so? and compilers will happily compile old versions).

    Now that I can point a finger at the feeling, I can start to think about actions. Maybe C for hobby really would be the solution.

    1. 10

      Damn, you’re right, it’s not a single executable. I’m getting something similar, I should know better than to figure /usr/bin contains single executables lol. I’ll post a correction and credit you :)

      1. 11

        Updated, hopefully this is better :) Thank you very much for the correction!

        On a side note, does anybody here know of good groups to get content editing for blog posts? I don’t have anybody to bounce drafts off of, which means these content errors keep getting through.

      2. 7

        As if C is the only alternative to Python. ;)

        If you want a high level language for future-proof software, OCaml maintainers take backwards compatibility very seriously, and OPAM (the package manager) is versioned and allows installing any old version of a library.

        With compiled languages, you can also make a statically linked binary so that you can still use the program even if building it requires big changes to the source. Rust and Go make that easy, but you can link anything with musl or another static C standard library.

        1. 3

          And when I then decide to run my software again after 1 or 2 years I still want it to run.

          Might I suggest Clojure? https://www.groundedsage.dev/posts/the-clojure-mindshare/#heading-stability

          1. 2

            linux-vdso is part of the kernel. ld-linux is the dynamic linker; you need it to run anything. Libc and libpthread provide the most basic possible functionality for interacting with the system, and it’s difficult to imagine something that doesn’t depend on them. Unfortunately, there are non-standard glibc features that some programs depend on, and that has caused problems in the past, but I can’t imagine that glibc depends on any of those.

            That leaves pcre as the only real dependency which–ok, it’s not technically freestanding, but I don’t think that really detracts from the point of the article. Not least because it’s fairly easy to make a grep that runs without it; it’s only used for the -P flag.

            1. 1

              Go doesn’t make use of libc for the most part. It does its own syscall interaction.

              1. 2

                Interesting. This makes me wonder where the border between kernel and libc actually sits. So, fopen(3) is implemented in libc. open(2) is more lowlevel and specified by POSIX, but where is it implemented? As it’s part of POSIX, I’d expect it to be implemented in the kernel. Go would then not use fopen(3), but open(2) to implement it’s I/O, right? Or is syscall(2) the only function directly talking to the kernel, and open(2) is already something in libc? Does someone know where to look for such information?

                I’m just curious. I don’t normally go that lowevel, but something not using libc sounds a bit arcane to me.

                1. 3

                  So at some level, syscall(2) is really a wrapper for the SYSCALL instruction (or similar for !AMD64). open(2) is a wrapper around syscall(2), but the semantics of how files are opened are implemented at the kernel level. At some level, to the program files don’t exist, but they are provided to the application by a very elaborate and consistent set of lies. Those lies are usually standardized by things like POSIX.

                  For a very abstract example, take this webassembly code. Files don’t exist in webassembly by itself, but by importing open and write from the webassembly environment, hello world can be written to the standard output of the host machine. Also see my talk on this.

                  TL;DR: syscalls don’t real, but the kernel lies and makes them appear real.

                  1. 2

                    Thank you!

                  2. 2

                    open() is implemented in libc, likely as a thin wrapper around the syscall instruction. Here, for instance, is how it’s implemented in my libc. But do note that it also needs to set errno (in that example, it’s handled by the syscall function), which is not something the kernel knows or cares about.

                    1. 1

                      Thank you!

            2. 9

              I agree with this post.

              This type of mentality is why I chose the most compatible and time-proven formats as the base of my project: Text files, and PGP. For the glue, I chose SQLite, Perl, and HTML.

              To simulate the first 20+ years of use, I made it compatible with older browsers: back to Mosaic 1.0 for now, and I plan to test on older platforms in the future.

              1. 5

                Not sure if this is satirical (I am an extremely gullible person), but that doesn’t sound too bad honestly. All a file is a bytestream frozen in time, and the only significance a file has beyond the fact that it’s a file is a parser that can make sense of it. cat that and send it on through it in the pipe.

                Mosaic sounds cool! I have an older T42 ThinkPad with Ubuntu 18.04 LTS and I’m looking forward to many more years of life out of that thing.

                1. 6

                  I’m not joking. Here’s a somewhat stable demo you’re welcome to play around with: http://rusrs.com/

                  Note that some optional features do require JS. Also, much of the interface is hidden under the “advanced options” setting, which is under Settings.

                2. 3

                  It was text files, GPG, and HTML for me. For a while, I used HTML 3.2 for L.C.D. of browser support. Lets one use those microbrowsers with more hardening possibilities.

                  1. 1

                    Sounds cool! What did you build? Can you share any code or specs?

                    1. 1

                      Those were just the formats I used. Simpler formats allowed simpler software that’s easy to use with isolation architectures. The software was already made.

                3. 7

                  JavaScript’s main issue from my perspective is that projects start to bitrot within weeks, not months or years, so they are long-term very expensive to maintain. Definitely not a tech you want to use for a 50 yr project.

                  1. 15

                    I think I sounded like a crazy JS hater, but I have to give people maintaining JS implementations credit: pure JS as implemented by web browsers is very resistant to bit rot. All toy scripts from a 1998 homepage still work. The DOM API has been very stable too, I’ve seen some 15 years old script still working as well as when they were new.

                    The NPM ecosystem and fantasy JS with modules it uses on the other hand… yeah, I wouldn’t bet on it. Lately I’ve made a web version of an OCaml lib that exports its functions through window.someFunction = ... so that the blob can remain useful even if compiling it to a JS blob from source becomes a lost technology.

                    1. 3

                      As a developer of tools, would you recommend a practical philosophy for developing end-user clients? I have a hard time wrapping my mind around clients.

                      Qt -> WebAssembly? A templating framework like Jinja? Pure HTML / CSS (leaning here the most)?

                      My inspirations are tools like tarsnap or pinboard.

                      1. 5

                        Unless you want to maintain heavyweight, OS-specific clients, pure HTML/CSS with JS sprinkles are my goto. As someone whose heavily steeped in the Rails community, I don’t agree with DHH on literally everything but I trust him when it comes to Rails+stimulus.js. For server-side infrastructure, I like Go and its stdlib and leverage them as much as possible. They have a very serious focus on backwards compatibility and minimizing unnecessary dependencies.

                        1. 2

                          That sounds about right to me> As I lose my React.js knowledge from my full-stack days I find myself appreciating Hugo the static site generator more and more, precisely because it’s just bare HTML/CSS in the end with the occasional minified JS script.

                          I’m very much a late adopter lol, haven’t gotten into Go yet. I like the single binaries and the performance of Go, but go get kind of terrified me when I first tried it out back in 2014. I’ll probably stick to Python 3 until Go 2 comes out and gets reviewed :)

                          Thank you for the advice!

                    2. 9

                      Yeah I’m big on this philosophy and a related idea is the “lindy effect”


                      I’m working on a shell because it’s been around for 50 years now, so I expect it to be around in 50 more years.

                      There’s an unbroken chain from Thompson shell in 1970, to Bourne shell, to Korn shell, to bash to Oil. Because Oil is compatible unlike other alternative shells. There is wisdom you’re abandoning when you break things – i.e. don’t throw the baby out with the bathwater.

                      When foundations are stable, you can make progress on top. The alternative is what I call “motion without progress”.

                      Funnily enough the only car I ever owned was a ’99 accord, which I sold a couple years ago :)

                      I also meant to blog about two designs I’ve encountered that have lasted 50 years:

                      • Ohm Walsh speakers. I bought mine new in 2014 but the design is unique and has been honed over 50 years. The company has basically makes one product, and continually makes it better without changing the design. That’s because it works and changing it would break it. Whenever people hear my speakers in person I can see the expression change on their face – they’re surprised.



                      https://ohmspeaker.com/technology/ – Unfortunately their ad copy is bad, but the speakers are an omnipolar design, and this is not bullshit, unlike most claims about audio.

                      • Brompton folding bikes. Also another company that made an advance 50 years ago and has been honing it since. Nice history of the company:


                      A folding bike is a surprisingly constrained engineering problem. It has to be small but hold your weight at the same time. When you get a design that works, changing it will break it. I had another folding bike designed in the 2000’s and it was shitty in multiple dimensions compared to the Brompton. They have been doing something real for all these decades.

                      1. 3

                        Oooooh I love your design taste! I’ve actually been looking at folding bikes for a couple years, but never pulled the trigger. Maybe if I move to a better apartment with an elevator or a less grungy bike room :)

                      2. 5

                        I’ve been both coding and consuming books and videos about how to be a good coder for many, many years.

                        Lately, I’ve been teaching what I call “Good Enough Programming”. If the code does something useful, and you can walk away from it, it’s good enough. All of this 50 year code is like that.

                        Oddly enough, nobody talks much about good enough programming. In fact, if you take a look around, it’s not the natural state of things. Projects go on forever and their software is always being tweaked, poked at, and updated. We’ve got a lot of coders wanting to be perfect, kick-ass programmers, but not a lot of coders writing good enough code. It’s very odd.

                        1. 3

                          I think the difference for software engineering is the trope of “changing the world”, which means hiring “animals” (Paul Graham’s essay: http://www.paulgraham.com/start.html) who pour in their heart and soul into somebody else’s property in a hope of attaining riches, which is held up by society as the goal to attain. Throw in the fact that the field is constantly 50% buzzed 20 year olds, and you get a culture of coders wanting to be perfect.

                          Kudos to you for fighting the good fight! Code that puts food on the table today and tomorrow is good enough and should allow you to sleep well at night.

                        2. 3

                          GNU Grep is older than the GNU project?

                          1. 3

                            Huh. Yeah I guess, probably for the same reason UNIX is older than Linux. That makes sense; Linux is a port of UNIX.

                            1. 5

                              What I meant was that grep is probably from 1974 (although I remember the story being that it’s even older). GNU grep (i.e. the grep by the GNU project, not by Ken Thompson) seems to have been released 1992.

                              1. 3

                                Oh. Yes. That’s a good point. :facepalm:

                                I’ll update the blog post and credit you. Thank you for pointing that out!

                                1. 1

                                  Updated and credited!

                              2. 3

                                Linux is a port of UNIX

                                Ssssh! I can hear them in the bushes, waiting to hear something like this!

                                1. 5

                                  They’re generally not subtle, the war cry of “ACTUALLY” echoes across the steppes, the thundering herd of GNUs approach rapidly to set things straight!

                            2. 4

                              The problem with JS is that no one needed it. Java applets and Flash were so popular exactly because JS was hopelessly inadequate for anything but toy scripts. Then people chose to make new versions of JS compatible with the old, toy version. Languages that compile to JS now is also a symptom—the APIs exposed via JS are adequate for the needs of modern web applications, but the language is not adequate for any sane development process. I believe the old JS was as safe to shed as blink tags, and WASM should have happened earlier. If nothing else, for digital preservation you can always build a compiler from 1996 JS to WASM. ;)

                              I do agree with the sentiment though. I’ve done quite a few software restoration projects, and it’s a real pleasure to see a codebase that can be built after decades with only minor adjustments.

                              1. 3

                                I don’t recall Java being popular for web apps—in fact, I remember the opposite having written a metasearch engine in Java back in 1996. It was slow, and there were issues with what Sun claimed Java could do vs. what it actually did.

                                Also, Java predated both Javascript and Flash (but not by much).

                                1. 3

                                  I thought the perception was opposite: Flash and Java were horrifically bloated and slow, whereas JS was pretty fast - not to mention everywhere. I definitely remember this as such, as applets were horrifically slow to load and use. If I encountered an applet, I would just navigate away out of frustration.

                                  Honestly, JS isn’t even that bad since ES5, and TypeScript adds a lot of value to it.

                                  1. 4

                                    Flash was one of the few things that were bloated and slow which I happily dealt with in exchange for the content. Stickdeath, Newgrounds, cool movie sites, interfaces I couldn’t code with HTML… Flash was a revolution in content presentation. Good we don’t need it any more past legacy support.

                                    100% agree on Java, though. Those apps had Flash’s drawbacks without its benefits. Only exception was Runescape. I was hooked on it a while.

                                    1. 2

                                      Thank you so much for reminding me about Stickdeath :D That was some funny shit right there.

                                      Also http://sieni.us/ animations.

                                      I doubt anything exists that can create that type of content as svg-on-javascript or whatever it would take. WebAssembly?

                                      1. 2

                                        Yeah, it kept us occupied during many lunch breaks. :) I found some on Youtube: the Anti-Auto Theft, Ice Cream Van, and quite a few goods ones in top of search. A few of those auto mods have strong, real-world applications in some areas (esp South Africa).

                                        Warning to innocent bystanders (err, readers): For those new to Stickdeath, it is ultra-NSFW. Unless you work remotely and aren’t on a video conference. Another argument in favor of remote work. (slow wink)

                                        Opportunity: If you get reprimanded or fired, we can have them make a Stickdeath cartoon featuring that boss with his or her name in the credits. Endless opportunities to make assholes famous in the Stickdeath universe.

                                        1. 2

                                          :D brilliant still!

                                          Too bad the quality on those and iirc the Salad Fingers videos (nsfw by some standards, I guess) aren’t the crystal sharp vectors of our youth…

                                    2. 3

                                      JS was super slow, and Flash wiped the floor with it performance-wise in number crunching, until V8 was released. But even then, and probably still now, without very careful management mutating the DOM comes with huge penalties compared to the Flash displaylist / scene graph.

                                      And yes, TypeScript is great- we’re finally back to where AS3 was 15 years ago.

                                      1. 3

                                        Well, we all hated them, but my point is that as developers we had to use them all the time when we needed functionality not provided by JS, and as users, we had to put up with them because there was no other way to get desired functionality through the web.

                                        Every video and sound hosting service before HTML5 video and audio was a thing. Every IP-KVM/IPMI/iLo. VMware vCenter. Almost every scientific visualization. Games in places where you weren’t allowed to install software. That was all Flash because JS couldn’t do it.

                                    3. 2

                                      I think grep at this point is a name + concept/interface + N working implementations. It hardly matters if it’s statically- or dynamically-linked, if it’s a giant bash script, &c. The options you pass matter, performance still matters, sure. But grep can be rewritten 10 times and we’ll still use it, because the name and the concept are just so compelling (like find | xargs, sooo good). I usually underestimate the value in unambitious interfaces & stable VMs, (tbh!).