@@ -2,6 +2,11 @@ Labs Assignment for 2018 - Simple Shell
22=======================================
33Write a simple Unix/Linux shell.
44
5+ Updates:
6+
7+ - [Nov 12, 2018] added redirection and pipe details, new paragraph
8+ "PROHIBITED FUNCTIONS", and limiting the language to C (i.e. no C++).
9+
510When you are done, we prefer to get a link to you github project but you
611can send it to us via email (a single tar file) as well. Your project
712must provide a Makefile so that running the "make" command does build
@@ -20,43 +25,68 @@ The deadlines are hard requirements, please stick to the schedule.
2025Obviously, you can send us the whole thing in one step before the first
2126deadline, no need to separate the project in two parts.
2227
23- If in doubt, please ask a question.
28+ If in doubt, please ask a question, and we strongly prefer you send it
29+ to the class mailing list, nswi015-l@mff.cuni.cz, so that others may
30+ benefit from the answers as well.
2431
2532C Style
2633-------
2734Please choose a good C style, for example http://mff.devnull.cz/cstyle/,
2835or pick another existing cstyle (e.g. https://man.openbsd.org/style).
2936Please do not invent your own C style.
3037
38+ This class is about Unix/Linux programming in C, so we only accept the C
39+ language, not C++.
40+
3141Implementation notes
3242--------------------
3343We are interested in you dealing with the Unix/Linux stuff you learn in
3444the class, so please do not spend time writing a linked list
3545implementation or a command line parser (the latter is much harder that
3646one might think).
3747
38- For getting the input line, we recommend the readline library, see "man
39- readline". You should find it on any Linux, *BSD, MacOS, or Solaris
40- machine. By using readline, you get line editing, history, completion ,
41- etc. for free. Another alternative is libtecla.
48+ For getting the input line, we recommend the " readline" library, see
49+ "man readline". You should find it on any Linux, *BSD, MacOS, or
50+ Solaris machine. By using readline, you get line editing, history,
51+ completion, etc. for free. Another alternative is libtecla.
4252
4353For tokenizing and parsing the command line, we suggest you to use
4454GNU flex(1) and bison(1). They are easy to use and you should also find
4555it virtually everywhere, already installed. We recommend O'Reilly's
46- book "flex & bison", having read through the first 30 pages should be
47- all you need for this project. I believe you can find the book online.
56+ book "flex & bison". Having read through the first 30 pages of the book
57+ should be all you need for this project. I believe you can find the
58+ book online.
4859
49- You will probably need a linked list implementation. We suggest you to
50- use macros from <queue.h>. See "man queue" for more information.
51- STAIL_* macros should be all you need.
60+ You will probably need a linked list implementation as using fixed sized
61+ arrays would not suffice. We suggest you to use macros from <queue.h>.
62+ See "man queue" for more information. STAIL_* and TAIL_* macros should
63+ be all you need.
5264
5365FYI, our implementation of the complete 1st phase is 560 lines long,
5466including flex and bison source files, and using the usual C style from
5567http://mff.devnull.cz/cstyle/.
5668
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.
69+ IT GOES WITHOUT SAYING IT IS AN INDIVIDUAL, NOT A TEAM PROJECT. DO NOT
70+ USE CODE WRITTEN BY OTHER FELLOW STUDENTS. THE IDEA IS YOU LEARN BY
71+ CODING YOUR OWN PROJECT.
72+
73+ PROHIBITED FUNCTIONS
74+ --------------------
75+ Family of fopen() functions et al are prohibited. Instead use functions
76+ from the printf(3) family, read(2), write(2), etc.
77+
78+ popen(3), system(3), and similar functions that fork() INSIDE are
79+ strictly prohibited. The only way to create a new process for you is to
80+ use fork(2).
81+
82+ You must NOT exec any shell from your code. I.e. if you have a pipeline
83+ "cat /etc/passwd | wc -l", the solution is not the following:
84+
85+ if (fork() == 0)
86+ execl("/bin/sh", "sh", "-c", "cat /etc/passwd | wc -l");
87+
88+ You really have to fork a new process for each command in a pipeline,
89+ and connect them together with pipes.
6090
6191Test scenario
6292-------------
@@ -290,46 +320,119 @@ you start your shell from.
290320
291321Phase 2
292322-------
293- - pipes
294-
295- - redirections
296- - "file >"
297- - "file <"
298- - ">> file"
299- - no need to implement ">&N" etc.
300- - whitespace is not significant (e.g. ">file", "> file" and
301- "> file" are all syntactically correct and equivalent)
323+ - implement pipes
324+ - implement the three basic redirections
302325
303- - background execution via &
326+ Pipelines
327+ ~~~~~~~~~
328+ The number of pipes in a pipeline is only limited by the machine
329+ resources. That means no static array for pipelines.
304330
305- Specific examples will be provided by the end of November but it must
306- work in the usual fashion. For example, this works in any normal
307- Unix/Linux shell, i.e. the redirection does not have to be at the end:
331+ So, for example, the following prints output of date(1):
308332
309- mysh$ > output date
310- mysh$ cat output
311- Wednesday, October 10, 2018 at 10:12:53 AM CEST
333+ mysh$ date | cat | cat | cat | cat | cat | cat | sort -n | uniq
312334
313- And pipelines may be separated by a semicolon, i.e. it's an extension of
314- the 1st phase:
335+ Pipelines may be separated by a semicolon, i.e. it's an extension of the
336+ 1st phase:
315337
316338 mysh$ cat /etc/passwd | wc -l; echo X | grep X
317339 26
318340 X
319341
342+ Note that the shell needs to wait for all commands in the pipeline to
343+ finish before printing out the next prompt. So you need to create the
344+ pipeline HORIZONTALLY, meaning the shell it a parent of ALL processes in
345+ the pipeline (remember, wait(2) only works on direct children). For
346+ example, the following will hang for 10 seconds before your shell
347+ returns a new prompt:
348+
349+ mysh$ date | sleep 10 | cat
350+
351+ If you only waited for the last command (cat(1) in this case), the shell
352+ would offer the next prompt right away which is NOT correct.
353+
354+ Note that sleep(1) does not read from its input, and does not write
355+ anything to STDOUT, so the cat(1) command finds no writer on the pipe
356+ and exits right away.
357+
358+ Redirections
359+ ~~~~~~~~~~~~
360+ Implement the three basic redirections:
361+
362+ - "> file"
363+ - "< file"
364+ - ">> file"
365+
366+ Note: there is no need to implement "2>xxx", ">&N" etc.
367+
368+ Whitespace is not significant (e.g. ">file", "> file" and "> file"
369+ are all syntactically correct and equivalent)
370+
371+ You may assume redirection operators always come at the end, if it helps
372+ you simplify the parsing, i.e.:
373+
374+ mysh$ cat /etc/passwd > output
375+ mysh$ cat < output >output2
376+
377+ You do NOT need to implement:
378+
379+ mysh$ >output cat /etc/passwd
380+ mysh$ cat >output /etc/passwd
381+
382+ The last redirection counts, ie. the following will append the output to
383+ "output3":
384+
385+ mysh$ date >output >output2 >>output3
386+
387+ And the following will print /etc/passwd ONLY:
388+
389+ mysh$ cat </etc/group </etc/passwd
390+
391+ And the following will write /etc/group to output3, truncating it if it
392+ existed beforehand:
393+
394+ mysh$ cat </etc/passwd </etc/group >output >>output2 >output3
395+
396+ Normal shells always create all files with ">" and ">>" but you do not
397+ need to do that. It's OK only to create the last one only.
398+
399+ Note that redirection comes after connecting the individual commands in
400+ the pipeline with pipes, so the following copies /etc/passwd to file
401+ "output", puts date's output to file "output2", and the last cat(1)
402+ finds no writer on the pipeline (since date(1) is printing to "output2"
403+ instead) and just exits finding STDIN empty:
404+
405+ $ cat /etc/passwd > output | date > output2 | cat
406+
320407Anything not listed above is NOT required
321408-----------------------------------------
322409I.e. we do NOT require any of these below:
323410
411+ - background execution via &
412+
324413- Variable support (i.e. "echo $HOME" nor "XXX=value ./a.out")
414+
325415- The "export" internal command.
326- - Job control.
416+
417+ - Job control. That also means there is no need to create a new process
418+ group for each pipeline (that's what a normal shell does). However,
419+ if you do, you will need to solve how background processes the control
420+ terminal as that was out of scope of our class.
421+
327422- Support for $? etc.
423+
328424- Strings, i.e. the following is not required:
329425
330426 $ echo "xxx yy"
331427 xxx yy
428+
332429- `` and $( ... )
333430
431+ - no complex commands like "if", "while", "for", "switch", etc.
432+
433+ - no line continuation with '\'
434+
435+ If unsure, either ask on our class mailing list or check what bash does.
436+
334437vim:tw=72
335438vim:ft=conf
0 commit comments