Building a Shell

95 points by ingve 4 hours ago on hackernews | 16 comments

zokier | 3 hours ago

Bit of pedantry but I don't think traditional unix shell (like this) follows repl model; the shell is not usually doing printing of the result of evaluation. Instead the printing happens more as a side effect of the commands.

jermaustin1 | 2 hours ago

I remember my first shell programming I ever did was batch in windows back in the 3.11/95 days.

The first line was always to turn off echo, and I've always wondered why that was a decision for batch script. Or I'm misremembering. 30 years of separation makes it hard to remember the details.

enoint | an hour ago

Echo in that case prints command lines before executing them. Its analog is `set -x` rather than `echo`.

skydhash | an hour ago

It’s a shell, not the whole thing. The whole thing is the shell+kernel+programs.

lvales | 3 hours ago

Building a shell is a great exercise, but honestly having to deal with string parsing is such a bother that it robs like 2/3 of the joy along the way. I once built a very simple one in Go [0] as a learning exercise and I stopped once I started getting frustrated with all the corner cases.

[0] https://github.com/lourencovales/codecrafters/blob/master/sh...

healeycodes | 3 hours ago

Author here, and yeah, I agree. I skipped writing a parser altogether and just split on whitespace and `|` so that I could get to the interesting bits.

For side-projects, I have to ask myself if I'm writing a parser, or if I'm building something else; e.g. for a toy programming language, it's way more fun to start with an AST and play around, and come back to the parser if you really fall in love with it.

ferguess_k | 39 minutes ago

Can say the same for control characters in terminals. I even think maybe it's just easier to ditch them all and use QT to build a "terminal" with clickable urls, something similar to what TempleOS does.
Had an assignment to build a shell in a week, how hard could it be?

  controlling terminal
  session leader
  job control
The parser was easy in comparison.

emersion | 2 hours ago

Some time ago I've written an article about a particular aspect of shells, job control: https://emersion.fr/blog/2019/job-control/

rigorclaw | 2 hours ago

The pipe implementation section is really clean. Working through fork/exec/dup2 by hand like this is one of those exercises that makes you appreciate how much composability Unix got right. Processes that know nothing about each other just work together because they read stdin and write stdout. I built something similar years ago and the moment pipes actually worked felt like unlocking a cheat code.

austy69 | 2 hours ago

Fun read. Wonder if you are able to edit text in the shell, or if you need to implement a gap buffer to allow it?

healeycodes | an hour ago

Editing the current line works because I brought in https://man7.org/linux/man-pages/man3/readline.3.html towards the end so I could support editing, tab completion, and history.

IIRC readline uses a `char *` internally since the length of a user-edited line is fairly bounded.

austy69 | an hour ago

Very cool. Currently working on the beginning of a small text editor so this part seemed interesting and was curious of any overlap. Thanks for the interesting post!

wei03288 | 26 minutes ago

The pipe section is the part that changes how you think about processes. Once you've manually done the dup2 dance — close write-end in parent, close read-end in child, wire them up — it stops being magic and starts being obvious why `grep | sort | uniq` works at all. The thing that surprised me building a similar toy was how late in the process job control has to come: you can get a working pipe chain surprisingly fast, and then job control (SIGTSTP, tcsetpgrp, the whole mess) costs 5x more than everything else combined.

hexer303 | 17 minutes ago

Unix shells are conceptually simple but hide a surprising amount of complexity under the hood that we take for granted. I recently had build my own PTY controller. There were so many edge-cases to deal with. It took weeks of stress testing and writing many tests to get it right.

dirk94018 | 11 minutes ago

Interesting. I wanted to do toast | bash to let the AI drive the computer but the bash shell really got in the way. Too much complexity. The things that annoy humans, $ expansion, special characters, etc don't work for AI either. Ended up writing a custom shell for AI (and humans). When a tool gets in the way, sometimes it just time to change the tool.