
Ask HN: How do I make a shell? - instakill
Does anyone have any links to tutorials or whatever, on how to go about creating a shell from scratch? I&#x27;d like to have a hand at creating something like Bash.
======
frou_dh
The first thing to recognise is that is shell is not a special kind of
program. It's just a normal executable like everything else.

Next, recognise that a shell is a language, so you're basically building a
commandline programming language interpreter (like python and ruby offer). The
difference compared to a general-purpose language is that a shell language
traditionally has super-lightweight syntax for operations related to processes
and files.

The first step of building a language interpreter is being able to lex
(tokenize) and parse a stream of characters.

~~~
dozzie
> The first thing to recognise is that is shell is not a special kind of
> program. It's just a normal executable like everything else.

Except it works with several OS interfaces touched by very little other
programs (terminal mode, terminal's controlling process, process groups, job
control), so one has to learn those _somehow_.

> Next, recognise that a shell is a language, so you're basically building a
> commandline programming language interpreter

No, not really. You can have something that just splits line on spaces and
executes that as a program and arguments. Calling that a "language" is a quite
far stretch.

What misled you is that most (all?) of the _useful_ shells are programming
languages at the same time as command editors and code executors (in other
words, REPL). You just don't see what I described above, because it's awful to
work with.

~~~
frou_dh
I appreciate the elaboration but don't think you've infact refuted anything I
said.

I originally put "user-mode executable" but edited it to "normal executable"
to be more understandable.

I don't think it would be a stretch to call space-separated opaque values a
language. A very simple one, mind.

My answer was directed at someone dipping their toe in who explicitly
mentionined that they wanted to make a bash-esque (i.e. non-trivial language)
shell.

------
DougMerritt
Having written a number of shells, I can confidentally say that the actual
heart of one is the ability to execute a series of commands.

Doing this in a very high level language like Ruby is trivial; it does all the
work for you.

Doing this in C, as Bash does, requires learning some systems programming.
Under Unix/Linux that means using fork() to create a child process and then
having that child call exec() to run some specified command.

If not run "in the background", then the parent process needs to call some
variant of wait() to idle until the child is done.

If it is desired to have input and/or output different than the parent, say
for redirection of stdin/stdout/stderr, then one has to fiddle with variants
of dup() to arrange this.

In some sense, all of the features mentioned in the other comments are
optional, and the number of features in a sophisticated shell like Bash is
mindboggling, so it would be a good idea to figure out a "minimum viable
product" so that you can get your minimal desired feature set working before
the end of time.

~~~
tedmiston
When you say trivial, do you mean (roughly)?:

\- get input from the user

\- pipe it to a subprocess [1] -- ex. subprocess.call("somecmd", shell=True)

\- show output to the user

\- run this all inside a while true loop

Is it "cheating" to do it this way? Should the shell be responsible for
parsing a language, generating an underlying representation like an abstract
syntax tree, etc?

I'm speaking from the Python perspective but of course this idea is about the
same in any very high level language.

[1]: [https://docs.python.org/2/library/subprocess.html#using-
the-...](https://docs.python.org/2/library/subprocess.html#using-the-
subprocess-module)

~~~
DougMerritt
Yes, that is precisely what I mean by trivial; the things needed are builtin
to the Ruby/Python/Perl languages + standard class library, which makes it
very easy.

> Is it "cheating" to do it this way? Should the shell be responsible for ...

Depends on your goals. There is no absolute answer.

If you just want to get things done fast, use Ruby. If you want to understand
what Bash does, and learn more about systems programming, then do it the long
way.

------
Someone
One step at a time. Some of the things people expect of a shell:

\- can search $PATH for things to run (traversing $PATH),

\- ?must check 'executable' bit?

\- ?must discriminate scripts from binaries?

\- must exec things to be run

\- must intercept stdin, stdout, and stderr of things being run

\- pass arguments to programs

\- expand wild card characters (for UNIX shells. A in some sense more
reasonable alternative is to put wildcard expansion in a separate library and
let executables do wildcard expansion. That would prevent problems with
expanded command lines becoming too long)

\- allow for back tick substitutions

\- evaluate environment variables when interpreting arguments (again, this
_could_ be something left to programs to do. For this, I don't see a benefit,
though)

\- allow multiple commands on a line

\- allow redirection from and to files

\- build pipelines and execute them

\- has some builtins (mostly optional, to speed up things)

\- reading and interpreting .shellrc

\- control structures (if, for, etc.)

You can implement them in whatever order you want.

I would probably start like this:

\- a program that starts a single executable.

\- starting an executable and intercepting its output.

\- also sending it input

\- accept the name of the command to run on the command line, search for it,
and execute it.

\- allow sending arguments to the program to run

\- loop infinitely, running the executables whose names the user types in
(this is where your program becomes shell-like)

You will likely encounter many things I let out above (do you need to interact
with the terminal? How to handle Control-C, for example to nicely kill all
commands in a pipeline) or do not even know about, but I would tackle them
when I met them.

------
vmateixeira
Hope this can help [1]. Otherwise, if you just want an API wrapped up with
python [2].

[1] [http://brennan.io/2015/01/16/write-a-shell-
in-c/](http://brennan.io/2015/01/16/write-a-shell-in-c/)

[2] [http://www.ibm.com/developerworks/aix/library/au-
pythocli/](http://www.ibm.com/developerworks/aix/library/au-pythocli/)

------
schappim
I actually just saw this post on Wednesday: "Writing a Shell in 25 Lines of
Ruby Code"[1].

[1] [http://www.blackbytes.info/2016/07/writing-a-shell-in-
ruby/](http://www.blackbytes.info/2016/07/writing-a-shell-in-ruby/)

