Skip to content

pjtunstall/0-shell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

0-shell

Table of Contents

What is this?

A simple shell written in Rust. 0-shell is one of the 01-Edu projects. According to the brief, it should implement at least the following ten commands, four built-in and six external--see below regarding this distinction:

Built-in:

  • echo
  • exit
  • cd
  • pwd

External:

  • ls, including the flags -l, -a and -F
  • cat
  • cp
  • rm, including the flag -r
  • mv
  • mkdir

Also, Ctrl + D to exit the shell. We're told that these commands "need to be implemented from scratch, without calling any external binaries."

Related to the last point, but somewhat unclear to me is the following paragraph:

Through the 0-shell you will get to the core of the Unix system and explore an important part of this system’s API which is the process creation and synchronization. Executing a command inside a shell implies creating a new process, which execution and final state will be monitored by its parents processes. This set of functions will be the key to success for your project.

A normal shell would itself handle cd, exit, pwd, echo (built-in commands), but call external binaries for ls, cat, cp, rm, mv, mkdir (external commands). (To check this for a given shell, you can enter type <command>.) I'm guessing this paragraph is a relic of the task as it was originally conceived, before commit 9e308f2: "fix(0shell): remove mandatory use of low-level system calls and make it bonus". An alternative possibility is that the authors intended to make a distinction between internal and external binaries, and have us spawn a new process for any of the commands that I've labeled external. But the advice to take BusyBox as an example points towards 0-shell being a single executable.

Audit

Prompt

The 01Edu instructions say, "This interpreter must display at least a simple $". To make my shell more distinctive, I chose to take $ in a generic sense; I claim my "simple $" looks like this: . Or, to put it another way, my program displays "at least a simple $"--in fact, it something does better than that: it displays a .

echo something

One of the audit instructions is:

Try to run the command "echo "something!"". Do the same in your computer terminal.

It then asks, "Can you confirm that the displayed message of the project is exactly the same as the computer terminal?" I've made the following assumptions about the text to be entered, besides the obvious one that "your computer terminal" is not also running 0-shell!

  • The outer quotes are to be omitted, as in the instruction for the next item.
  • The text inside those outer quotes is to be entered unchanged in shells which don't use ! as a special character for history expension, such as PowerShell and fish.
  • In shells with default history expension (such as Bash, Zsh, csh, and tcsh), the ! is to be escaped with a preceding \. Otherwise, Bash and Zsh will display dquote> in response to any input till you close the inner quotes.
  • In POSIX shell (sh), dash, and ksh, that have optional histotory expansion, the text should be entered depending on which option is currently selected. I gather the default is no history expansion with !.
  • It's my understanding that BusyBox's default shell (ash) does not treat ! as special (it lacks history expansion by default, similar to dash). However, if built with hush (another shell included in BusyBox), history expansion with ! can be optionally enabled.

Since there is no requirement to implement special behavior for ! or guidance on which shell to use as a standard (unless we can take the mention on BusyBox as a hint), I take this to be an oversight.

Last orders, please

See integration.rs for an integration test that covers the last section of the audit (before the bonus questions). I've assumed that the omission of txt extension from new_doc.txt on the third mention is accidental.

Regarding the name

The root directory and repo are named 0-shell, as required by the brief. Unfortunately clashing convetions have resulted in almost the maximum conceivable variants! Rust's build tool, Cargo, doesn't allow a package name to begin with a numeral, hence the package is called zero-shell and the lib and bin crates zero_shell according to Rust convention. When you build the project, either with cargo run (to build and run in one step) or cargo build (to build only) or cargo build --release (to build in release mode), a build script will rename the binary to 0_shell. It insists on an underscore in place of the dash. I gather this makes the name more broadly compatible across operating systems, so I've decided not to process it further (e.g. wrapping the call to Cargo in a shell script, or using a Cargo extension or a build system like make).

Testing

Tests should be run in single-threaded mode ...

cargo test -- --test-threads=1

... rather than in the default parallel mode, cargo test. This is necessary to prevent tests that change the current directory from interfering with tests that check the identity of the current ditectory, or the existence or nonexistence or contents of files they've created in it. The success test for pwd, for example, expects the current directory to be 0-shell, but the cd test temporarily changes the current directory. The integration test in integration.rs also changes the current directory briefly.

Further

See todo.md for possible further developments and topics to explore.

About

01Founders project to write a simple shell.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages