0% found this document useful (0 votes)
3 views24 pages

11 Unix Shell

The document provides an overview of how a UNIX shell operates, detailing its role in executing commands, managing processes, and interacting with users. It contrasts the Command Line Interface (CLI) with the Graphical User Interface (GUI), highlighting the advantages of CLI in terms of flexibility and control. Additionally, it presents pseudo code for a simple shell implementation, explaining key functions such as fgets, strtok, fork, wait, and execvp, while also outlining an assignment to enhance the shell's functionality.

Uploaded by

gun2414180
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views24 pages

11 Unix Shell

The document provides an overview of how a UNIX shell operates, detailing its role in executing commands, managing processes, and interacting with users. It contrasts the Command Line Interface (CLI) with the Graphical User Interface (GUI), highlighting the advantages of CLI in terms of flexibility and control. Additionally, it presents pseudo code for a simple shell implementation, explaining key functions such as fgets, strtok, fork, wait, and execvp, while also outlining an assignment to enhance the shell's functionality.

Uploaded by

gun2414180
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

EE217: Software development environment and tools practice

Lecture 11:
How a UNIX shell works
What does the computer do for us?

• What does the computer do for us?

• Run programs

• Store data
• Communicate with each other
• Interact with us

• The interaction with us means...


Run
program!
Store
data!
Communicate with
other computer!

2
How can we use computer?

Run
program!
Store
data!
Communicate with
other computer!

How can we interact with the


computer?

• What is the way to use the computer?

• Telepathy? - No

• Speech? – No (well… kind of, these days)


• Rewiring? – Not nowdays (only before 1950s)
• Type the command you want

3
The shell: the program that initiate commands

Shell: the program initiates commands that users type

I want to run the program


“[Link]”!

Type Find the file


./[Link] “[Link]”!
Load the file
“[Link]”!
Return results Execute the “[Link]”
Shell from its main
function!

• Receives a string that contains the command from the user

• Interprets the string

• Lets the computer work on initiating the command that the user requested

There is Operating System (Kernel) between the shell and the computer
4
GUI vs. CLI

• GUI (Graphic User Interface) • CLI (Command Line Interface)

• Use mouse, windows, icons • Use only keyboard, shell, commands

• Easy to use • Hard to use


• It has limitations to use some programs • It supports almost all programs

• make, server-managing program • It allows combining processes and

• Cannot combine processes or adjust I/O adjusting I/O with pipe, redirection

• ex: Windows, Gnome, KDE • ex: Powershell (Windows), Bash, Zsh

5
Very simple pseudo code of the shell

int i, pid;
char *token, command[2000], *arguments[10];
① Get the command
fgets(command, sizeof(command), stdin);
command[strlen(command)-1] = 0;

token = strtok(command, “ “);


if (token == NULL) {exit(-1);}

arguments[0] = token; ② Delimit command by space bar


for (i = 1; i<10; i++) {
token = strtok(NULL, “ “); ③ Compose argument array
if (token == NULL)
break;
arguments[i] = token;
}
arguments[i] = NULL;

pid = fork(); ④ fork child process


if (pid != 0){
wait(NULL); ⑤ the parent process waits for exit of the child
} else {
execvp(arguments[0], arguments); ⑥ the child changes its execution image to
}
arguments[0]

6
Very simple pseudo code of the shell
Let us assume that a user typed
“echo hello quasi shell”

• Note that this simple shell has some limitations

• Executes only one command

• Users can type only 2,000 characters in maximum


• Users can use only 10 options in maximum
• It cannot change directory (cd)

• It doesn’t have environment variables such as $PATH

• So users have to specify the full path of the program such as


“/bin/echo” and not just “echo”
• In this lecture, for ease of understanding, we omit the full path
• If you use execvp(), execvpe(), execlp()(note “p” in the names),
it automatically finds the binary in $PATH

• It doesn’t support the pipe and the redirection


7
Functions you must know

• fgets

• strtok

• fork

• wait

• execvp

8
fgets

char *fgets(char *s, int size, FILE *stream);

• It reads at most (size – 1) characters from stream and stores them into

the buffer pointed to by s

• The scanf cannot read string containing “ “ (space) while fgets can!

• The NULL is stored after the last character in the buffer

• Returns s on success, NULL on fail

• ex) Getting inputs from a user by the keyboard (stdin)

char buf[200];

fgets(buf, sizeof(buf), stdin);

9
strtok

char *strtok(char *str, const char *delim);


• It breaks a string pointed by str into a sequence of zero or more nonempty tokens

based on the string pointed by delim

• The first call and subsequent calls are different

• First use: The string to be parsed should be specified in str

• Subsequent calls: The str must be NULL

• Returns a pointer to the next token, or NULL if there are no more tokens

• ex) Parsing a simple string “Hello, World and Universe”

char str[] = “Hello, World and Universe” ,

char* token;

token = strtok(str, “ “); // token = “Hello,”

token = strtok(NULL, “ “); // token = “World”

token = strtok(NULL, “ “); // token = “and”

token = strtok(NULL, “ “); // token = “Universe”

10
fork

pid_t fork(void)

• It creates a new process by duplicating the calling process

• The new process is referred to as the child process

• The calling process is referred to as the parent process

• Returns 0 to the child, and pid of the child to the parent

pid_t pid;
pid = fork();

if (pid == 0)

printf(“I am a child” );

else

printf(“I am a parent and I have a child who has pid %d” , pid);

11
wait

pid_t wait(int *wstatus)

• It sleeps until a state of a child is changed and stores the changed state in wstatus

• Usually, it is used to wait until a state of a child is changed to EXITED

• If the wstatus is NULL, it just returns without storing changed state

• Returns process id of the child process whose state is changed

pid = fork();

if (pid != 0) {

int status;

printf(“I am a parent and I am going to wait for my child”);

wait(&status);

printf(“The state of my child is changed. The status is %d”, status);

12
execvpe

int execvp(const char *filename, char *const argv[]);


int execvpe(const char *filename, char *const argv[], char
*const envp[]);

• It executes the program pointed to by filename with arguments in the array

argv, and environment variables in the array evnp

• Returns error code on fail, no return on success

• ex) Execute echo program

char *filename = “echo”;

char *argv[] = { “echo”, “Hello,”, “and”, “Universe” , NULL};

execvp(filename, argv);

13
Very simple pseudo code of the shell (1)

int i, pid;
char *token, command[2000], *arguments[10];

fgets(command, sizeof(command), stdin);


command[strlen(command)-1] = 0;

token = strtok(command, “ “);


arguments[0] = token;
...

• Reads the string from stdin and saves it at command

• Assume that we typed “echo hello quasi shell”,


the buffer command is like below:
command

e c h o h e l l o q u a s i s h e l l \n 0 ... ?
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 1999

14
Very simple pseudo code of the shell (2)

int i, pid;
char *token, command[2000], *arguments[10];

fgets(command, sizeof(command), stdin);


command[strlen(command)-1] = 0;

token = strtok(command, “ “);


arguments[0] = token;
...

• The character ‘\n’ should be removed for executing the command

• Replace the character ‘\n’ with ‘\0’ so that the newline character is

removed from the string


command command[strlen(command)
-1]

e c h o h e l l o q u a s i s h e l l \0 0 ... 0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 1999

15
Very simple pseudo code of the shell (3)

int i, pid;
char *token, command[2000], *arguments[10];

fgets(command, sizeof(command), stdin);


command[strlen(command)-1] = 0;

token = strtok(command, “ “);


arguments[0] = token;
...
• Delimits command by “ “, and returns the start address of the delimited
string
• Finds “ “ and replaces “ “ with ‘\0’

• Saves position where it scanned in its static variable


command token Saves this position at static variable

e c h o \0 h e l l o q u a s i s h e l l \0 0 ... 0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 1999

16
Very simple pseudo code of the shell (4)

int i, pid;
char *token, command[2000], *arguments[10];

fgets(command, sizeof(command), stdin);


command[strlen(command)-1] = 0;

token = strtok(command, “ “);


arguments[0] = token;
...

• Allocates new buffer and copies contents of the delimited argument in the

buffer
command token

e c h o \0 h e l l o q u a s i s h e l l \0 0 ... 0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 1999

arguments[0]

17
Very simple pseudo code of the shell
...
for (i = 1; i<10; i++) {
token = strtok(NULL, “ “);
if (token == NULL)
break;

arguments[i] = token;
}
arguments[i] = NULL;
...
• Continues to delimit the command

• If strtok gets NULL as its first parameter, it starts to delimit from the

position saved in its static variable


st rd
Changed at 1 Changed at 3 loop
command token loop Changed at 2 nd

loop

e c h o \0 h e l l o \0 q u a s i \0 s h e l l \0 0 …

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

18
Very simple pseudo code of the shell
...
for (i = 1; i<10; i++) {
token = strtok(NULL, “ “);
if (token == NULL)
break;

arguments[i] = token;
}
arguments[i] = NULL;
...
• Continues to delimit the command

• if strtok gets NULL as its first parameter, it starts to delimit from the
position saved in its static variable

command token

e c h o \0 h e l l o \0 q u a s i \0 s h e l l \0 0 …

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

arguments[0 arguments[3]
1 st arguments[1] 2 nd arguments[2] 3 rd
]
loop loop loop
19
Very simple pseudo code of the shell
...
for (i = 1; i<10; i++) {
token = strtok(NULL, “ “);
if (token == NULL)
break;

arguments[i] = token;
}
arguments[i] = NULL;
...
• Saves NULL at the last element of the array arguments

• For specifying the array is ended there (like string)


0 1 2 3 4 5 6 7 8 9

argument
s
NULL

e c h o \0 h e l l o \0 q u a s i \0 s h e l l \0 0 …

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
arguments[0] arguments[1] arguments[2] arguments[3]
20
Very simple pseudo code of the shell

pid = fork();
if (pid != 0)
wait(NULL);
else
execvp(arugments[0], arguments);

• Creates the child process

• The child process starts executing code from inside of fork()

• The return value of the fork() is different between the parent process and

the child process


• Parent process gets process id of the child process made by fork()
• Child process gets 0

21
Very simple pseudo code of the shell
pid = fork();
if (pid != 0)
wait(NULL);
else
execvp(arugments[0], arguments);
• Parent process waits until the child process exits

• It gets no exit status because it passes NULL for 1st parameter


pid = fork();
if (pid != 0)
wait(NULL);
else
execvp(arguments[0], arguments);

• Child process executes the program the command requests

• Inside the execvp(), the child process starts to execute code from main()
function of the program that corresponds to arguments[0]

• execvp() does not return unless execvp() fails

22
Assignment

• Add below functionalities int i, pid;


char *token, command[2000], *arguments[10];
• Make the shell execute command
fgets(command, sizeof(command), stdin);
command[strlen(command)-1] = 0;
multiple times (use loop)
token = strtok(command, “ “);
• Make the shell get exited when if (token == NULL) {exit(-1);}
the user types “exit” arguments[0] = token;
for (i = 1; i<10; i++) {
• Add appropriate error handling token = strtok(NULL, “ “);
if (token == NULL)
• Check the fgets() return value break;
arguments[i] = token;
• What if execvp() returns }
arguments[i] = NULL;
• Name your file “studentID_name.c”
pid = fork();
and submit it to KLMS (no if (pid != 0){
wait(NULL);
} else {
screenshot or JPG file allowed) execvp(arguments[0], arguments);
}

23
24

You might also like