With the system calls learned in the class and a few additional ones, you are ready to control processes in the system. Let's build my amazing shell with those system calls.
-
Shell is a program that gets inputs from users, interpretes the inputs, and processes them accordingly. Command Prompt in Windows, Bourne Shell (
bash
) in Linux, and zsh in macOSX are the examples of shell. -
An user can enter a command by writing a sentence on the shell and press the "Enter" key. Upon receiving the input, the shell parses the requests into command tokens, and processes the request according to the first token (i.e.,
tokens[0]
). -
The shell always assumes that the first token is the filename of the executable to run EXCEPT FOR
exit
,cd
, andalias
(see belows for the descriptions for those). The shell executes the executable with the rest of the tokens as the arguments. For example, if an user inputsls -al /home/sce213
, the shell will executels
executable with-al
and/home/sce213
as its arguments.
-
The shell program
mash
(My Amazing SHell) awaits your command line input after printing out "$" as the prompt. When you enter a line of command the framework tokenizes the command withparse_command()
and callsrun_command()
with the tokens. Implement following features starting inrun_command()
. -
Currently, the shell keeps getting input commands and processes them until the user enters
exit
. In that case, the shell program exits.
-
When the shell gets a command, it should run the executable as explained above. Each command can be comprised of one exeutable followed by zero or more arguments. For example;
$ /bin/ls # 0 argument list_head.h Makefile pa1.c parser.c parser.h README.md types.h $ ls # 0 argument list_head.h Makefile pa1.c parser.c parser.h README.md types.h $ pwd # 0 argument /home/sanghoon/os/pa1 $ cp pa1.c pa1-backup.c # two arguments $ ls list_head.h Makefile pa1-backup.c pa1.c parser.c parser.h README.md types.h $ exit
-
The shell may execute the executable using the p-variant of the
exec()
system call family so that the executable file is automatically checked from the$PATH
environment variable. -
The shell should print the prompt only after the executed process is exited.
-
Your task is to EXECUTE external executables (such as
ls
,pwd
, andcp
), NOT to implement the feature of the commands. -
When the specified executable cannot be executed for some reasons, print out the following message to
stderr
.if (unable to execute the specified command) { fprintf(stderr, "Unable to execute %s\n", the first token of the command); }
$ blah blahhhh # Enter a non-existing executable Unable to execute blah $
-
Use
toy
program which is included in the template code for your development and testing. It simply prints out the arguments it receives, so you can check whether your implementation handles input commands properly.$ ./toy arg1 arg2 arg3 arg4 pid = xxxxxx argc = 5 argv[0] = ./toy argv[1] = arg1 argv[2] = arg2 argv[3] = arg3 argv[4] = arg4 done!
-
Hint:
fork(2), exec(3), wait(2), waitpid(2)
-
Imagine when you browse folders with the Explorer. When you select the "New Folder" item in the menu, a new folder will be created in the currently viewing folder. You can change the current folder by selecting one of folders in the directory.
-
The shell has the similar concept called current working directory. The shell is treated as running in the current working directory and the location of files is computed from the current working directory. You can check the current working directory with
/bin/pwd
command. -
Implement
cd
, a special command manipulating the current working directory. This command is special in that this feature is not handled by executing executables but the shell understands the command and processes itself. In this sense, this type of command is called a built-in command. -
Each user has one's home directory which is denoted by
~
. The actual path is defined in$HOME
environment variable. Makecd
command to understand it$ pwd /home/directory/of/your/account # Assume this is the home directory of the user $ cd /somewhere/i/dont/know $ pwd /somewhere/i/dont/know $ cd ~ $ pwd /home/directory/of/your/account $ cd /somewhere/i/know $ pwd /somewhere/i/know $ cd # Equivalent to cd ~ $ pwd /home/directory/of/your/account
-
Hints:
chdir(2), getenv(3), environ(7)
-
It is very boring and error-prone to enter the long command whenever you need to ask the shell to do something repeatedly. For example, one of the most frequently used command is
ls -al
. It would be awesome if we can define an aliasll
forls -al
and the shell doesls -al
when we enterll
only!! -
So, your task is to implement the
alias
command. Likecd
, thealias
is a built-in command processed by the shell itself rather than executing a program. -
You can define an alias for a word as follows:
$ ls -al # The full command list_head.h Makefile pa1.c parser.c parser.h README.md types.h $ alias ll ls -al # Define an alias for ll $ ll # The shell runs ls -al list_head.h Makefile pa1.c parser.c parser.h README.md types.h $ alias xyz echo Hello world # Define xyz to echo Hello world $ xyz Hello world $ alias zzz operating systems $ echo SCE213 zzz PA1 # Process the keyword in the middle of command SCE213 operating systems PA1
-
The shell should be able to process an unlimited number of aliases. This implies you need to use a list to maintain the defined aliases.
-
When you enter
alias
without any following arguments, the shell should list up currently defined aliases. The alias defined earlier should come before later ones. You should print the aliases intostderr
to get graded properly. Also handle spaces carefully so that there is no trailing space.$ alias ll: ls -al xyz: echo Hello world zzz: operating systems
-
The word in the translated with alias should not be translated again with another alias.
$ alias xyz Hello world $ alias world Korea $ echo xyz Hello world $ echo world Korea $ echo xyz world Hello world Korea # 'world' is translated from xyz so it is not translated again to Korea
-
Hint
- If
tokens[]
were a list of words, you might be able to implement the feature easily by replacing a word with multiple words. - Take care of the string in
tokens[]
which are allocated and deallocated in the functions inparser.c
. It is advised to have a look at them before fiddling withtokens[]
.
- If
-
As we discussed in the class, we can connect two processes with an ordinary pipe. Implement this feature.
-
You may enter two commands with the pipe symbol
|
in between. All output of the first command should be carried to the input of the second command.$ cat pa1.c | sort -n $ echo hello_my_cruel_world | cut -c2-5
-
Note that the shell should be sane after processing the pipe.
-
Aliases should be applied to the both commands before and after the pipe symbol.
-
(Updated Apr 4) You may assume that bulit-in commands are not used when using the pipe. In other words, only external commands will be used for using the pipe in this PA.
-
Hints
pipe(2)
anddup2(2)
.- Implement incrementally. First check whether the pipe symbol exists in the tokens. If not, just do execute the command. If exists, split the tokens into two pars and feed them to two different processes which are connected through a pipe.
- You will not be able to implement this feature by manually getting the output of the first process in a buffer and sending it to the second process. Check the sample code in the lecture slide.
- For your coding practice, the compiler is set to halt on some (important) warnings. Write your code to fully comply the C99 standard.
- You can define/change edit whatever you want in
pa1.c
. Also you may leaveinitialize()
andfinalizne()
blank if you don't need them. - You may not use some or all of the hinted system calls.
- DO NOT USE
system()
system call. You will get 0 pts if you use it. - DO NOT implement external programs' features by yourself (e.g., printing out a message to handle
echo
command, listing the current directory to handlels
command, etc). You will not get any point in this case. - It is advised to test your code on your computer first and to implement incrementally. Some sample inputs are included under
testcase
directory. Try to input each line or just run./mash < [input file]
. - FYI, the instructor's implementation took ~250 lines of C code. Believe me, the implementation is not difficult if you fully understand the concepts of processes.
-
310 pts in total
-
Source: pa1.c (270 pts in total)
- You can submit up to 30 times to PASubmit.
- Points will be prorated by testcase results.
-
Document: One PDF document (30 pts). It should include ALL the followings;
-
Outline how programs are launched and arguments are passed
-
How you implemented the alias feature
-
Your strategy to implement the pipe, including how many forks did you used and for what?
-
AND lessons learned
-
NO MORE THAN FOUR PAGES
-
DO NOT INCLUDE COVER PAGE, YOUR NAME, NOR STUDENT ID
-
DO NOT INCLUDE ANY CODE NOR SCREENSHOT IN THE DOCUMENT
-
COMPLY THE STATEMENTS OTHERWISE YOU WILL GET 0 pts for documentation
-
-
Git repository URL at git.ajou.ac.kr (10 pts)
- To get the points, you should actually use the repository to manage your code (i.e., have more than two commits which are hours aparts). You will not get any point if you just committed your final code or the repository is not properly cloned.
- How to create your repository to submit:
- Clone this repository into your computer, create a private project from http://git.ajou.ac.kr, and push the local repository onto the gitlab repository.
- Or create a private repository by importing the handout repository as a new project.
- How to submit your git repository
- Generate a deploy token from Settings/Repository/Deploy Token. Make sure you're working with deploy token not deploy key.
- Register at PASubmit using the repository URL and deploy token.
- PASubmit only accepts the repository address over HTTP. SSH URL will be rejected.
- For the slip token policy, the grading will happen after the deadline. So, the deploy token should valid through the due date + 4 days.
-
Free to make a question through AjouBb. However, YOU MIGHT NOT GET AN ANSWER IF THE ISSUE/TOPIC IS ALREADY DISCUSSED ON THIS HANDOUT.
-
QUESTIONS OVER EMAIL WILL BE IGNORED unless it concerns your privacy.