📦 daymxn / dShell

📄 README.md · 196 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196<p align="center">
<img src="https://i.imgur.com/xhSqaLL.png" />
</p>

![GitHub release (latest by date)](https://img.shields.io/github/v/release/daymxn/dShell?style=flat-square)
![GitHub last commit (branch)](https://img.shields.io/github/last-commit/daymxn/dShell/master?style=flat-square)
![GitHub issues](https://img.shields.io/github/issues/daymxn/dShell?style=flat-square)
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/daymxn/dShell?style=flat-square)
![GitHub](https://img.shields.io/github/license/daymxn/dShell?style=flat-square)

# dShell

Another toy shell that serves no true purpose beyond being an engineer's µarch baby.

Learn more about my journey in developing the initial release of this shell <a href="https://daymxn.com/writeups/view/dshell">on my website.</a>
## Usage/Examples

### Builtins

Builtins are predefined commands built into the shell.
If the first argument of a `COMMAND` (otherwise known as the WORD) is equal to
any of the builtin functions, then said builtin functions will be called instead
of being executed. This is true regardless if you have a valid form of the program
on your PATH.

`help` - prints a list of all builtins

```custom
dShell $ > help
----- dShell -----
Builtin commands: 
~ cd
~ help
~ exit
```

`cd` - change the working directory

```custom
dShell $ > cd help
dShell $/help > 
```

`exit` - terminate the shell

```custom
dShell $ > exit

Process finished with exit code 0
```

### Logical Operators

Logical operators provide a way for simple commands to be followed by other
simple commands.
Logical operators can not be followed or superseded by other logical operators.

AND [`&&`] - following command will only execute if the exit status is `EXIT_SUCESS`

```custom
dShell $ > ls
Testing
dShell $ > mkdir Testing && cd Testing
mkdir: cannot create directory ‘TestDirectory’: File exists
dShell $ > mkdir Testing2 && cd Testing2
dShell $/Testing2 >
```

OR [`||`] - following command will only execute if the exit status is NOT `EXIT_SUCESS`

```custom
dShell $ > ls
Testing
dShell $ > mkdir Testing && cd Testing
mkdir: cannot create directory ‘TestDirectory’: File exists
dShell $/Testing > 
```


NOT [`!`] - flips the exit status of the following command

```custom
dShell $ > ls
Testing
dShell $ > ! mkdir Testing && cd Testing
mkdir: cannot create directory ‘TestDirectory’: File exists
dShell $/Testing > 
```

ENDCOMMAND [`;`] - separates commands from one another

```custom
dShell $ > ls pwd
ls: cannot access 'pwd': No such file or directory
dShell $ > ls;pwd
Testing
/home/daymon/dShell/cmake-build-debug
```

### Pipes

Pipes (labeled `PIPE` or `|`) push the STDOUT of one command to the STDIN of another.

```custom
dShell $ > tail test.txt | grep "Hello"
Hello World!
```

Pipes must be precceded and followed by a `COMMAND` or `SUBSHELL`.
Preceeding or following `PIPE` with anything else is undefined.

Pipes are good for a single `COMMAND`.
To continue the `PIPE`, follow the `COMMAND` with another `PIPE`


### Redirection

Redirection allows you to write the STDOUT of a `COMMAND` to a specified file.

```custom
dShell $ > tail test.txt >> test2.txt
dShell $ > tail test2.txt
Hello World!
```

Redirection comes in two forms: `REDIRECT_TO` [`>`] and `REDIRECT_TO_OVERWRITE` [`>>`]. Both are
identical in nature, except that one *appends* the input to the file, wheres the other
*overwrites* the file to contain the input.

Redirection does not make any straight assumptions about your input. If you provide a
complex command to a redirection, the redirection will evaluate the complex command and
utilize the first string streamed to STDOUT as the input (or output). What this means is that
you can do things like this:

```custom
dShell $ > tail test.txt > (cd ./testdirectory && ls && grep "test3")
```

You are not limited to programs either, you can provide either the input
or output as straight string literals.

```custom
dShell $ > "Hello world!" > test3.txt && "Goodbye world!" >> test3.txt
dShell $ > tail test3.txt
Hello world!
Goodbye world!
```

### Subshells

Subshells allow you to branch execution into a seperate process.

```
dShell $ > (cd Test && pwd)
/home/daymon/dShell/cmake-build-debug/Test
dShell $ > pwd
/home/daymon/dShell/cmake-build-debug
```

Initilized with a `SUBSHELL_START` [`(`] and ended with a `SUBSHELL_END` [`)`],
these two symbols create a `SUBSHELL`.

Subshells also support pipes!

```
dShell $ > (cd Test && tail test.txt) | grep "Hello"
Hello World!
```
## Roadmap

- Fix open issues

- Generate unit tests for everything

- Implement addition builtins

- Add support for pre-evaluated arguments


## Acknowledgements

- [Stephen Brennan's classic tutorial](https://brennan.io/2015/01/16/write-a-shell-in-c/)
- [Introduction to Systems Programming: a Hands-on Approach](https://www.cs.purdue.edu/homes/grr/SystemsProgrammingBook/)
- [The Linux Programming Interface: A Linux and UNIX System Programming Handbook](https://www.amazon.com/Linux-Programming-Interface-System-Handbook/dp/1593272200)
- [flex & bison: Text Processing Tools](https://www.amazon.com/flex-bison-Text-Processing-Tools/dp/0596155972)

## License

[Apache 2.0](https://github.com/daymxn/dShell/blob/master/LICENSE)


## Authors

- [@daymxn](https://www.github.com/daymxn)