Live data from Hacker News

Writing a Unix Shell – Part II

indradhanush.github.io

1–10 of 20 posts

Re: Writing a Unix Shell – Part II

#3
Still missing the check for fork returning -1, which would make your waitpid() hang forever, as -1 waits on all p̶i̶d̶s̶,̶ ̶e̶v̶e̶n̶ ̶i̶n̶i̶t̶.̶ children.

Edit: less problematic than my original wrong guess, but still bad for a shell, which eventually supports multiple concurrent children.

Re: Writing a Unix Shell – Part II

#4
post #3

Still missing the check for fork returning -1, which would make your waitpid() hang forever, as -1 waits on all p̶i̶d̶s̶,̶ ̶e̶v̶e̶n̶ ̶i̶n̶i̶t̶.̶ children. Edit: less problematic than my original wrong guess, but still bad for a shell, which eventually supports multiple concurrent children.

Wrong, waitpid(-1, ...) waits on all child processes of the current process, and would return -1 with errno set to ECHLD if there is no children.

The point about missing error checking still stands though!

Re: Writing a Unix Shell – Part II

#5
If you want to learn more about writing a shell from an undergraduate coursework perspective (and far closer to how bash does things), this is a chapter entirely on writing your own shell: https://www.cs.purdue.edu/homes/grr/SystemsProgrammingBook/B...

That PDF covers the basics of making your own shell (i.e. splitting input into tokens aka using a lexer, parsing the resulting tokens aka using yacc [a token parser], I/O redirection, piping, executing commands, wildcarding, interrupts, environmental variables, history, subshell, revising what you've typed without having to retype it, etc.).

Every undergraduate CS major at Purdue University is required to do the infamous shell lab (essentially, recreate csh). This project really taught me how shells work. Before doing this project, I could do the minimum in shells, but now I'm fairly competent at it.

Re: Writing a Unix Shell – Part II

#6
post #2

Thanks for continuing your series. This is a great illustration of how non-trivial a production quality shell is. Parsing input is "tricky" Each builtin needs comprehensive error handling

IRL, shells don't do string manipulation (well, technically everything becomes string manipulation at some point, but in this context not in the normal sense of the term). Shells generally use a lexer to split inputs up into tokens (generally using regex) [0] and then make sense of the inputs using a parser (the most famous of which is called yacc [1]).

[0]: I was going to link to Bash's lex file here, but they appear to do something funky which would require a non-trivial amount of time to find, understand, and write here. So, you'll just have to take my word on this. I give you wikipedia as a substitute: https://en.wikipedia.org/wiki/Lexical_analysis

[1]: https://git.savannah.gnu.org/cgit/bash.git/tree/parse.y

Re: Writing a Unix Shell – Part II

#7
post #4
post #3

Still missing the check for fork returning -1, which would make your waitpid() hang forever, as -1 waits on all p̶i̶d̶s̶,̶ ̶e̶v̶e̶n̶ ̶i̶n̶i̶t̶.̶ children. Edit: less problematic than my original wrong guess, but still bad for a shell, which eventually supports multiple concurrent children.

Wrong, waitpid(-1, ...) waits on all child processes of the current process, and would return -1 with errno set to ECHLD if there is no children. The point about missing error checking still stands though!

Ah, yes, any child...thanks for the catch.

Re: Writing a Unix Shell – Part II

#8

If you want to learn more about writing a shell from an undergraduate coursework perspective (and far closer to how bash does things), this is a chapter entirely on writing your own shell: https://www.cs.purdue.edu/homes/grr/SystemsProgrammingBook/B... That PDF covers the basics of making your own shell (i.e. splitting input into tokens aka using a lexer, parsing the resulting tokens aka using yacc [a token parser],…

Since not a lot of folk knew this at my shop: wordexp() is the posix library for lexing strings "like the shell".

Re: Writing a Unix Shell – Part II

#9

If you want to learn more about writing a shell from an undergraduate coursework perspective (and far closer to how bash does things), this is a chapter entirely on writing your own shell: https://www.cs.purdue.edu/homes/grr/SystemsProgrammingBook/B... That PDF covers the basics of making your own shell (i.e. splitting input into tokens aka using a lexer, parsing the resulting tokens aka using yacc [a token parser],…

I would not recommend using a lexer/parser generator for writing a shell, especially if you want to support things like backquote substitution and here-docs, since parsing and evaluating are interleaved. A recursive-descent parser is more flexible and suitable to the task.

Re: Writing a Unix Shell – Part II

#10
post #8

If you want to learn more about writing a shell from an undergraduate coursework perspective (and far closer to how bash does things), this is a chapter entirely on writing your own shell: https://www.cs.purdue.edu/homes/grr/SystemsProgrammingBook/B... That PDF covers the basics of making your own shell (i.e. splitting input into tokens aka using a lexer, parsing the resulting tokens aka using yacc [a token parser],…

Since not a lot of folk knew this at my shop: wordexp() is the posix library for lexing strings "like the shell".

Note that wordexp() will also, unless explicitly told otherwise, perform command substitution and thus is capable of executing other processes. Be wary of using it on untrusted input.
Post reply on HN