Is is possible to implement internal shell command (shell builtin) by only using the exec() functions?

Viewed 162

I want to implement some Linux commands by only using the exec() family of functions. When I use external commands such as "ls", "whoami", it runs well. However, I can't run internal commands (shell builtins) such as "export". Is there any other way to run those commands? And also, why can system() implement those internal commands even though it uses execl() function?

1 Answers

The Linux implementation of system does indeed use execl, but it uses it to run a shell, not to directly invoke the utility. man system is quite explicit:

The system() library function uses fork(2) to create a child process that executes the shell command specified in command using execl(3) as follows:

   execl("/bin/sh", "sh", "-c", command, (char *) 0);

So system runs an instance of the standard shell (/bin/sh), passing it two command-line parameters: -c and the argument to system. Shells are expected to interpret the command-line flag -c as requesting the the shell execute the following argument as a shell command. The shell will certainly be able to execute its own builtins from a -c argument in the same way that it executes them if you type them interactively.

However, although you can execute a cd or export command with system, you will find that it is utterly pointless because it works on the execution environment of the shell invoked by system. That shell will terminate as soon as it finishes executing the command it has been asked to execute, so any changes to its execution environment will immediately vanish.

So that's not very useful if you are trying to write a shell. You will want cd to actually change working directories and export to modify your shell's environment variables. So, just like the system shell, you'll have to implement your own builtins. As the word "builtin" implies, these commands are interpreted directly by the shell itself, rather than being passed to some external utility to implement.

For these particular commands, you'll probably want to investigate the standard library functions setenv(3) (to modify environment variables) and chdir(2) (to change the current working directory).

Related