Part Ⅲ–Built-in commands
Just as we have mentioned in part Ⅱ,the exec
family of functions can’t perform built-in commands like cd
.
It’s like
The reason for this is that cd
is not a system command like ls
or pwd
.We need to write and invoke functions to realize commands such as cd
.
Imagine that if cd
were a system command,the workflow would be like this:
- the user sends the input
cd /
- the shell forks the current process and executes the function(s) corresponding to
cd
- After a successful invocation,the child’s lifecycle ends and it exits.The control is returned to the parent process.
- The current working directory of parent has not changed,since the command was executed in the child.As a result,though the
cd
command is successfully carried out,the produce is not we desired.
Therefore,to successfully realize it,we have to implement it on our own.We also need to inspect if the command we input is cd
(or maybe other built-in commands).If it is,we will not fork
the process and move on to wait for the next input.
Nevertheless,pwd
and echo
are built-in commands too.Why we can successfully execute built-in commands like them but not cd
?
Because cd
changes the current directory but pwd
and echo
do not.The following explanation is given by chatGPT.
the built-in cd command changes the current working directory of the shell process, rather than launching a new process.
When a shell built-in command is executed, it is handled directly by the shell itself, without invoking a new process. In other words, the shell executes the built-in command directly in its own process, rather than creating a new process to execute the command.
The execvp() function, on the other hand, is used to create a new process and execute a new program within that process. When execvp() is called, it loads the specified executable file into the new process's memory and starts executing it.
So, since cd is a shell built-in command that changes the current working directory of the shell process itself, it cannot be implemented using execvp(), which is used to execute a new program in a new process. Instead, the cd command must be implemented as a shell built-in command.
Ops,the /usr/bin/pwd
and shell built-in pwd
are different.The pwd
and echo
we execute above are exactly not built-in commands but system call like /usr/bin/pwd
and /usr/bin/echo
.And actually in the majority of shell like bash,sh and zsh,pwd
and echo
are built-in commands.So which commands are shell built-in commands?List of Bourne shell built-in commands
cd
Fortunately,there is a chdir
function available for us to inplement cd
straightforward.It accepts the path as an argument and returns 0 upon a success and -1 upon a failure.
We define our function like this:
int cd(char *path) {
return chdir(path);
}
And add a check in our main
function:
while(1) {
input = readline("mysh> ");//with "mysh> " to be a prompt,the function reads a line of input.
command = split_input(input);
if(!command[0]) {//empty commands
free(input);
free(command);
continue;
}
if(strcmp(command[0], "cd") == 0) {
if (cd(command[1] < 0)) {
perror(command[1]);
}
continue;;
}
...
Test it.