We define register_command function for adding a built-in function to our built-in commmand hash map. Then, we define init function and register the built-in cd function there.
Notice the line register_command("cd", cd). The first argument is a command name. The second argument is a reference to a function. In order to let cd, in the second argument, refer to the cd function reference in yosh/builtins/cd.py, we have to put the following line in yosh/builtins/__init__.py.
```
from yosh.builtins.cd import *
```
Therefore, in yosh/shell.py, when we import * from yosh.builtins, we get cd function reference that is already imported by yosh.builtins.
We’ve done preparing our code. Let’s try by running our shell as a module python -m yosh.shell at the same level as the yosh directory.
Now, our cd command should change our shell directory correctly while non-built-in commands still work too. Cool.
#### exit
Here comes the last piece: to exit gracefully.
We need a function that changes the shell status to be SHELL_STATUS_STOP. So, the shell loop will naturally break and the shell program will end and exit.
As same as cd, if we fork and exec exit in a child process, the parent process will still remain inact. Therefore, the exit function is needed to be a shell built-in function.
Let’s start by creating a new file called exit.py in the builtins folder.
```
yosh_project
|-- yosh
|-- builtins
| |-- __init__.py
| |-- cd.py
| |-- exit.py
|-- __init__.py
|-- constants.py
|-- shell.py
```
The exit.py defines the exit function that just returns the status to break the main loop.
```
from yosh.constants import *
def exit(args):
return SHELL_STATUS_STOP
```
Then, we import the exit function reference in `yosh/builtins/__init__.py`.
```
from yosh.builtins.cd import *
from yosh.builtins.exit import *
```
Finally, in shell.py, we register the exit command in `init()` function.
```
...
# Register all built-in commands here
def init():
register_command("cd", cd)
register_command("exit", exit)
...
```
That’s all!
Try running python -m yosh.shell. Now you can enter exit to quit the program gracefully.
### Final Thought
I hope you enjoy creating yosh (your own shell) like I do. However, my version of yosh is still in an early stage. I don’t handle several corner cases that can corrupt the shell. There are a lot of built-in commands that I don’t cover. Some non-built-in commands can also be implemented as built-in commands to improve performance (avoid new process creation time). And, a ton of features are not yet implemented (see Common features and Differing features).
I’ve provided the source code at github.com/supasate/yosh. Feel free to fork and play around.
Now, it’s your turn to make it real Your Own SHell.