Wayne Hong
Wayne Hong

Reputation: 119

Writing a shell - how to execute commands

I'm trying to write a shell that will eventually take advantage of concurrency. Right now I've got a working shell parser but I'm having trouble figuring out how to execute commands. I've looked a bit at exec (execvp etc.) and it looks promising but I have some questions.

Can exec handle file input/output redirection? Can I set up pipes using exec?

I'm also wondering about subshells. What should subshells return; the exit status of its last statement? Can subshells be a part of a pipe?

These might seem like really dumb questions but please bear with my inexperience.

Upvotes: 0

Views: 524

Answers (2)

Adam Mihalcin
Adam Mihalcin

Reputation: 14458

The standard technique for a shell is to use fork-exec. In this model, to execute an application the shell uses fork to create a new process that is a copy of itself, and then uses one of the exec variants to replace its own code, data, etc. with the information specified by an executable file on disk.

The nice thing about this model is that the shell can do a little extra work with file descriptors (which are not thrown away by exec) before it changes out its address space. So to implement redirection, it changes out the file descriptors 0, 1, and 2 (stdin, stdout, and stderr, respectively) to point to another open file, instead of console I/O. You use dup2 to change out the meaning of one of these file descriptors, and then exec to start the new process.

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 754090

Can exec handle file input/output redirection?

No, you do that with open() and dup() or dup2() (and close()).

Can I set up pipes using exec?

No, you do that with pipe(), dup() or dup2() and lots of close() calls.

I'm also wondering about subshells. What should subshells return, the exit status of its last statement?

That's the normal convention, yes.

Can subshells be a part of a pipe?

Yes. In a normal shell, you can write something like:

(cd /some/where; find . -name '*.png') | sed 's/xyz/prq/' > mapped.namelist

If you want to get scared, you could investigate posix_spawn() and its support functions. Search for 'spawn' at the POSIX 2008 site, and be prepared to be scared. I think it is actually easier to do the mapping work ad hoc than to codify it using posix_spawn() and its supporters.

Upvotes: 1

Related Questions