Minishell
InKwan [email protected]
Topics Unix System calls
waitpid() pipe() dup2()
C function calls strtok() strcmp()
Minishell Software Enginnering tip Evolutionary & Iterative
Unix System calls waitpid()
For out purpose: waitpid(pid, 0, 0); Blocking wait for a child until it
terminates For Project 1, every child is waited
until they all terminate
Unix System calls Ex
#include <unistd.h>
main()
{
int pid;
if ((pid = fork()) ==0) {
print("This is the child\n");
// execvp() can be here.
}
else {
waitpid(pid, 0, 0); // wait until the child terminates
printf("This is the parent\n");
}
}
Unix System calls pipe()
Creates pipes dup2()
Duplicates an open file descriptor Next slides will show how they
work pipe() and dup2() should be used to
implement ‘|’ operator in the shell
File Descriptor/Table/i-node
fd 0fd 1fd 2fd 3fd 4
Descriptor table[one table per process]
Open file table [shared by all processes]
i-node table[shared by all processes]
File pos
refcnt==1
...
File pos
Refcnt==1
...
stderrstdout
stdin File access
...
File size
File type
File access
...
File size
File type
File A (terminal)
File B (disk)
pipe() Call int pfd[2]; pipe(pfd);
fd 0fd 1fd 2fd 3fd 4
Descriptor table(one table
per process)
Open file table (shared by
all processes)
i-node table(shared by
all processes)
File pos
Refcnt==1...
File pos
Refcnt==1
...
File access
...
File size
File type
Pipe 0
Pipe 1
pfd[1] pfd[0]
After the First fork()
fd 0fd 1fd 2fd 3fd 4
Descriptor tables Open file table i-node table
File pos
refcnt==2
...
File pos
refcnt==2
...
Parent's table
fd 0fd 1fd 2fd 3fd 4
Child's table
File access
...
File size
File type
Pipe 0
Pipe1
fork();
pfd[1]pfd[0]
pfd[1]pfd[0]
File access
...
File size
File type
Child dup2()
fd 0fd 1fd 2fd 3fd 4
Descriptor tables Open file table i-node table
File pos
refcnt=2
...
File pos
refcnt=2
...
Parent's table
fd 0fd 1fd 2fd 3fd 4
Child 1's table
File access
...
File size
File type
File access
...
File size
File type
Pipe 0
Pipe1
dup2(pdf[1], STDOUT_FILENO); // in forked child // STDOUT_FILENO == 1 close(pdf[1]);
Finally after Two fork()s, dup2()s, and close()s
fd 0fd 1fd 2fd 3fd 4
File pos
refcnt==1
...
File pos
refcnt==1
...
Child 1's table
fd 0fd 1fd 2fd 3fd 4
Child 2's table
File access
...
File size
File type
pipe 0
pipe 1
fd 0fd 1fd 2fd 3fd 4
Parent's table
stdoutstdin
stdoutstdin
C Function Calls strtok()
Stg type variables are strings terminating with zero (0)
typedef of Stg in arabildr.h and stgbildr.h should be factored out into main.h
strtok() can be used to generate a parsed argument to execvp()
Takes two arguments The first argument is a string to be parsed The second argument is a string of
delimiters
C Function Calls strtok()
The string in the first argument is altered after strtok() call
The first argument should be in write-able memory
For exmaple, Stg cmd = “Hello, World”; may not work
Initialized strings can be placed in BSS region (read-only)
C Function Calls strtok()
// Stg cmd has “Hello,I am here”
Arabildr ar_bildr = arabildr_init();
Stg tok = strtok(cmd, " ,"); // tok has “Hello”
arabildr_append(arr_bildr, tok);
tok = Stg strtok(NULL, " ,"); // tok has “I”
arabildr_append(arr_bildr, tok);
tok = Stg strtok(NULL, " ,"); // tok has “am”
arabildr_append(arr_bildr, tok);
tok = Stg strtok(NULL, " ,"); // tok has “here”
arabildr_append(arr_bildr, tok);
tok = Stg strtok(NULL, " ,"); // tok == NULL; The end
AraOfStgs cmd_array = arabildr_array(arr_bildr);
“Hello”“I”
“am”“Here”
0
cmd_array[0]
cmd_array[4]
C Function Calls strcmp()
Compares two zero terminated strings If they are exact match, returns 0 Else returns nonzero
C Function Calls strcmp()
Arabildr ar_bildr = arabildr_init();
arabildr_append(arr_bildr, “exit”);
AraOfStgs cmd_array = arabildr_array(arr_bildr); ;
// cmd_array[0] is assigned to “exit”
int match = strcmp(cmd_array[0], “exit”);
printf(“match %d\n”, match);
Minishell SE tip 1st step
Read user input & display : getchar() 2nd step
Parse the input : strtok() 3rd step
Run the program : fork(), exec(), waitpid(), strcmp()
4th step Run the piped programs : pipe(), dup2()
Minishell SE tip 1st step
While(1) { Read a user key stoke using getchar() Use Stgbildr APIs to accumulate the user
input Display the input when ‘\n’ is
encountered Destroy the Stgbildr object
}
Minishell SE tip 2nd step
While(1) { Get the user input Parse the input using strtok()
Use Arabildr APIs Display Arabildr objects
AraOfStgs type variable is useful in displaying
}
Minishell SE tip 3rd step
While(1) { Get the user input Parse the input Use strcmp() to “exit”, “logout” or “quit” ; if yes
then exit(); Run the non-piped program
fork() Parent: waitpid() for the child Child: execvp() using AraOfStgs type argument
Destroy objects }
Minishell SE tip 4th step
While(1) { Get the user input Parse the input strcmp() to “exit” Check if ‘|’ exist in the input If yes run the piped programs
Two children are created; pipe() and dup2() are helpful for ‘|’
strtok(), pipe(), dup2(), 2*fork(), 2*execvp(), 2*waitpid() Else run the non-piped program
strtok(), fork(), execvp(), waitpid() Destroy objects
}
Further Information Advanced Programming in the UNIX
Environment, Addison-Wesley, 1992, ISBN: 0-201-56317-7
Design of the UNIX Operating System, Prentice Hall, 1986, ISBN: 0132017997
Top Related