|
| 1 | +Labs Assignment for 2018 - Simple Shell |
| 2 | +======================================= |
| 3 | +Write a simple Unix/Linux shell. |
| 4 | + |
| 5 | +When you are done, we prefer to get a link to you github project but you |
| 6 | +can send it to us via email (a single tar file) as well. Your project |
| 7 | +must provide a Makefile so that running the "make" command does build |
| 8 | +the shell in the binary called 'mysh' (this saves us the work when running |
| 9 | +automated tests). |
| 10 | + |
| 11 | +The first phase must be finished and handed to us before the end of the |
| 12 | +Winter semester, ie. Jan 13, 2019. All examples shown below must work |
| 13 | +as expected. |
| 14 | + |
| 15 | +The second phase must be finished and handed over to us before the end |
| 16 | +of the Summer semester, ie. by June 30, 2019. |
| 17 | + |
| 18 | +The deadlines are hard requirements, please stick to the schedule. |
| 19 | + |
| 20 | +Obviously, you can send us the whole thing in one step before the first |
| 21 | +deadline, no need to separate the project in two parts. |
| 22 | + |
| 23 | +If in doubt, please ask a question. |
| 24 | + |
| 25 | +C Style |
| 26 | +------- |
| 27 | +Please choose a good C style, for example http://mff.devnull.cz/cstyle/, |
| 28 | +or pick another existing cstyle (e.g. https://man.openbsd.org/style). |
| 29 | +Please do not invent your own C style. |
| 30 | + |
| 31 | +Implementation notes |
| 32 | +-------------------- |
| 33 | +We are interested in you dealing with the Unix/Linux stuff you learn in |
| 34 | +the class, so please do not spend time writing a linked list |
| 35 | +implementation or a command line parser (the latter is much harder that |
| 36 | +one might think). |
| 37 | + |
| 38 | +For getting the input line, we recommend the readline library, see "man |
| 39 | +readline". You should find it on any Linux, *BSDm, MacOS, or Solaris |
| 40 | +machine. By using readline, you get line editing, history, completion, |
| 41 | +etc. for free. Another alternative is libtecla. |
| 42 | + |
| 43 | +For tokenizing and parsing the command line, we suggest you to use |
| 44 | +GNU flex(1) and bison(1). They are easy to use and you should also find |
| 45 | +it virtually everywhere, already installed. We recommend O'Reilly's |
| 46 | +book "flex & bison", the first 30 pages should be all you need for this |
| 47 | +project. I believe you can find the book online. |
| 48 | + |
| 49 | +You will probably need a linked list implementation. We suggest you use |
| 50 | +macros from <queue.h>, those are proven macros. See "man queue" for |
| 51 | +more information. STAIL_* macros should be all you need. |
| 52 | + |
| 53 | +FYI, our implementation of the complete 1st phase is 550 lines long, |
| 54 | +including flex and bison source files, and using the usual C style from |
| 55 | +http://mff.devnull.cz/cstyle/. |
| 56 | + |
| 57 | +It goes without saying it is an individual, not a team project. Do not |
| 58 | +use code written by other fellow students. The idea is you learn by |
| 59 | +coding your own project. |
| 60 | + |
| 61 | +Test scenario |
| 62 | +------------- |
| 63 | +Use any Unix/Linux/MacOS system you want but make sure your code builds |
| 64 | +and works on a Linux machine in the MFF UK lab, e.g. |
| 65 | +u-pl1.us.oracle.com. |
| 66 | + |
| 67 | +Use Valgrind to make sure you do not mismanage memory. Valgrind is |
| 68 | +installed on machines in the MFF UK Unix lab. |
| 69 | + |
| 70 | +Phase 1 |
| 71 | +------- |
| 72 | +Note - the "mysh$" prompt in examples below represents the behavior of |
| 73 | +the shell you implement. The "Bash$" prompt represents the system shell |
| 74 | +you start your shell from. |
| 75 | + |
| 76 | +- Honor and use the existing PATH you get from your parent shell, i.e. |
| 77 | + so that one can use "ls" and the command will execute. |
| 78 | + |
| 79 | +- ^C (= SIGINT) in the prompt kills the current unfinished line and |
| 80 | + offers a new prompt (same way as bash does it). E.g: |
| 81 | + |
| 82 | + mysh$ ls xxx^C |
| 83 | + mysh$ |
| 84 | + |
| 85 | +- An empty command just prints a new prompt (as bash does it). E.g. |
| 86 | + |
| 87 | + mysh$ <SPACE><SPACE><SPACE><ENTER> |
| 88 | + mysh$ |
| 89 | + |
| 90 | +- Implement simple foreground command execution. Commands may be |
| 91 | + separated with a semicolon. Any number of commands separated by a |
| 92 | + semicolon must be supported (i.e. until you reach some other system |
| 93 | + limits): |
| 94 | + |
| 95 | + - i.e. "cmd [; cmd2 [; cmd3 ...]]] |
| 96 | + - for example: |
| 97 | + |
| 98 | + mysh$ date |
| 99 | + Mon Oct 8 04:51:27 PDT 2018 |
| 100 | + mysh$ |
| 101 | + |
| 102 | + mysh$ /usr/bin/echo X |
| 103 | + X |
| 104 | + mysh$ |
| 105 | + |
| 106 | + mysh$ echo X; date; echo Z |
| 107 | + X |
| 108 | + Monday, October 8, 2018 at 11:36:04 AM CEST |
| 109 | + Z |
| 110 | + mysh$ |
| 111 | + |
| 112 | + Whitespace should not matter, i.e.: |
| 113 | + |
| 114 | + mysh$ echo X;date;echo Z |
| 115 | + X |
| 116 | + Monday, October 8, 2018 at 11:36:04 AM CEST |
| 117 | + Z |
| 118 | + mysh$ |
| 119 | + |
| 120 | +- A semicolon after the last command is legal (as is in bash). E.g: |
| 121 | + |
| 122 | + mysh$ echo x; |
| 123 | + x |
| 124 | + |
| 125 | + However, the following is not legal: |
| 126 | + |
| 127 | + mysh$ date;; |
| 128 | + error:1: syntax error near unexpected token ';' |
| 129 | + mysh$ |
| 130 | + |
| 131 | +- Implement an internal "exit" to exit the shell. E.g.: |
| 132 | + |
| 133 | + Bash$ ./mysh |
| 134 | + mysh$ exit |
| 135 | + Bash$ echo $? |
| 136 | + 0 |
| 137 | + Bash$ |
| 138 | + |
| 139 | +- ^D (i.e. Ctrl-D) exits the interactive shell as well (same as the |
| 140 | + "exit" internal command). Again, see bash for an example. |
| 141 | + |
| 142 | +- Implement an internal "cd" command. It works in three modes: |
| 143 | + |
| 144 | + - "cd" goes to $HOME |
| 145 | + - "cd -" goes to previous directory |
| 146 | + - "cd <dir>" goes to "<dir>" |
| 147 | + |
| 148 | + |
| 149 | + The internal cd must set the PWD and OLDPWD environment variables |
| 150 | + (again see bash). |
| 151 | + |
| 152 | + E.g.: |
| 153 | + |
| 154 | + mysh$ pwd |
| 155 | + /data/maish |
| 156 | + mysh$ cd |
| 157 | + mysh$ pwd |
| 158 | + /home/jpechane |
| 159 | + mysh$ cd - |
| 160 | + mysh$ pwd |
| 161 | + /data/maish |
| 162 | + mysh$ cd /tmp |
| 163 | + mysh$ pwd |
| 164 | + /tmp |
| 165 | + mysh$ cd - |
| 166 | + mysh$ pwd |
| 167 | + /data/maish |
| 168 | + |
| 169 | +- The "-c" option is supported as in any other usual shell. |
| 170 | + |
| 171 | + E.g.: |
| 172 | + |
| 173 | + Bash$ mysh -c "echo XXX; date" |
| 174 | + XXX |
| 175 | + Monday, October 8, 2018 at 1:36:56 PM CEST |
| 176 | + Bash$ |
| 177 | + |
| 178 | +- The '#" comment is supported. E.g.: |
| 179 | + |
| 180 | + mysh$ echo X # comment |
| 181 | + X |
| 182 | + mysh$ # another comment |
| 183 | + mysh$ |
| 184 | + |
| 185 | + Or: |
| 186 | + |
| 187 | + ./mysh -c 'date; echo X # comment' |
| 188 | + Wednesday, October 10, 2018 at 10:10:09 AM CEST |
| 189 | + X |
| 190 | + |
| 191 | + Comments must also work in the non-interactive mode, see below. |
| 192 | + |
| 193 | +- The non-interactive mode is supported. |
| 194 | + |
| 195 | + - i.e. 'mysh test.sh' must work and the commands from the file |
| 196 | + are executed sequentially. |
| 197 | + |
| 198 | + - the shell errors out on first syntax error as a usual shell |
| 199 | + does. E.g: |
| 200 | + |
| 201 | + Bash$ cat test.sh |
| 202 | + echo X |
| 203 | + date |
| 204 | + ;; |
| 205 | + echo Y |
| 206 | + |
| 207 | + Bash$ ./mysh test.sh |
| 208 | + X |
| 209 | + Monday, October 8, 2018 at 11:38:16 AM CEST |
| 210 | + error:3: syntax error near unexpected token ';' |
| 211 | + Bash$ |
| 212 | + |
| 213 | + - shell must treat syntax errors gracefully. Print the line |
| 214 | + number where the problem occured. See the error message |
| 215 | + above. |
| 216 | + |
| 217 | +- In all modes, the return value of your shell is the return value of |
| 218 | + the last command (or pipeline) executed or some specific error on a |
| 219 | + syntax error (e.g. bash returns 2, ksh returns 3). E.g. if we use |
| 220 | + return value of 254 for a syntax error, it will look like this: |
| 221 | + |
| 222 | + Bash$ ./mysh -c "grep XXX123 /etc/passwd" |
| 223 | + Bash$ echo $? |
| 224 | + 1 |
| 225 | + |
| 226 | + Bash$ ./mysh -c ';;' |
| 227 | + error:1: syntax error near unexpected token ';' |
| 228 | + Bash$ echo $? |
| 229 | + 254 |
| 230 | + |
| 231 | + mysh$ grep XXX123 /etc/passwd |
| 232 | + mysh$ exit |
| 233 | + Bash$ echo $? |
| 234 | + 1 |
| 235 | + |
| 236 | + mysh$ grep XXX123 /etc/passwd |
| 237 | + mysh$ ^D |
| 238 | + Bash$ echo $? |
| 239 | + 1 |
| 240 | + |
| 241 | + mysh$ ls; ; |
| 242 | + error:1: syntax error near unexpected token ';' |
| 243 | + mysh$ exit |
| 244 | + Bash$ echo $? |
| 245 | + 254 |
| 246 | + |
| 247 | +- return value of unknown command is 127 (as in bash). E.g: |
| 248 | + |
| 249 | + Bash$ ./mysh -c 'xxx123' |
| 250 | + mysh: xxx123: No such file or directory |
| 251 | + Bash$ echo $? |
| 252 | + 127 |
| 253 | + |
| 254 | +- error and warning messages from the shell itself go to standard error |
| 255 | + output. E.g. the message "mysh: xxx123: No such file or directory" |
| 256 | + from above goes to stderr. |
| 257 | + |
| 258 | +- the interactive shell must handle SIGINT well (= killing the |
| 259 | + foreground process via ^C). I.e.: |
| 260 | + |
| 261 | + mysh$ sleep 100 |
| 262 | + ^CKilled by signal 2. |
| 263 | + mysh$ |
| 264 | + |
| 265 | + However, also see the paragraph about killing the unfinished command |
| 266 | + line with ^C. Both must work as explained. |
| 267 | + |
| 268 | + The "Killed by..." message also goes to stderr. |
| 269 | + |
| 270 | +- it would be nice if you put the current working directory in the |
| 271 | + prompt, like this: |
| 272 | + |
| 273 | + mysh:/data/mysh$ cd / |
| 274 | + mysh:/$ cd /tmp |
| 275 | + mysh:/tmp$ |
| 276 | + |
| 277 | +Phase 2 |
| 278 | +------- |
| 279 | +- pipes |
| 280 | +- redirections (>, <, >>) |
| 281 | +- background execution via & |
| 282 | + |
| 283 | +Specific examples will be provided till the end of November but it must |
| 284 | +work in the usual fashion. For example, this works in any normal |
| 285 | +Unix/LInux shell, i.e. the redirection does not have to be at the end: |
| 286 | + |
| 287 | + mysh$ > output date |
| 288 | + mysh$ cat output |
| 289 | + Wednesday, October 10, 2018 at 10:12:53 AM CEST |
| 290 | + |
| 291 | +And pipelines may be separated by a semicolon, i.e. it's an extension of |
| 292 | +the 1st phase: |
| 293 | + |
| 294 | + mysh$ cat /etc/passwd | wc -l; echo X | grep X |
| 295 | + 26 |
| 296 | + X |
| 297 | + |
| 298 | +Anything not listed is not required |
| 299 | +----------------------------------- |
| 300 | +I.e. we do NOT require any of these below: |
| 301 | + |
| 302 | +- variable support (i.e. "echo $HOME" nor "XXX=value ./a.out") |
| 303 | +- "export" internal command |
| 304 | +- job control |
| 305 | +- support for $? etc. |
| 306 | +- strings, i.e. the following is not required: |
| 307 | + |
| 308 | + $ echo "xxx yy" |
| 309 | + xxx yy |
| 310 | +- `` and $( ... ) |
| 311 | + |
| 312 | +vim:tw=72 |
| 313 | +vim:ft=conf |
0 commit comments