Having written my own shell in C, how do I run Unix executables?

In one of my courses, we write our own shell (mostly from scratch).

We have already worked on writing a lexer and a parser to split the input into nice β€œcommand” structures that are easier to handle. Similarly, I have a read_command() function that will read one command at a time and find out what type of command (pipe / and / or / simple / etc.).

Now I'm trying to write a function execute_command(struct command cmd) , which actually takes a command and runs it. I am struggling to even start writing this feature.

Say I just get very simple cat foo.txt as a command. My command structure will divide it neatly, so I have a set of words with two words in it.

Now I want to run the cat executable with the argument foo.txt . I understand that I have to use the $PATH variable to try to find the executable and then run it with this argument.

I am struggling with a few important questions:

  • How am I really looking for a cat ? Remember that this program uses C. What functions can I use to search directories? How can I use PATH for this?
  • When I find the cat , how can I run it with foo.txt as a parameter? How can this be done in C?
+6
source share
2 answers

The man pages themselves or a simple search on any of these Google features will lead to many examples to help you.

+11
source

You split the command line into separate lines (command name, arguments), and you store them at the zero end of the array of character pointers. Then you fork and pass the command name and command + arguments to execvp() , if only it is verboten. In the end, you have to worry about channel redirection and I / O reassignment, but the basic idea remains the same.

 char *args[MAXARGS]; args[0] = "cat"; args[1] = "foo.txt"; args[2] = 0; if ((pid = fork()) == 0) { execvp(args[0], args); ...print error... exit(1); /* execvp() does not return unless there an error */ } else if (pid < 0) ...fork failed... else ...wait for child to finish - or start other commands, or ... 

You can dynamically allocate args in a real shell. This is one step harder if you must provide a custom environment for the executable. Basically, you will collect a copy of the environment, and then after forking set the global environment to a new value, but if the new environment contains a new value for PATH, it will affect the search for the command using execvp() . Because of this, you can write your own version of execvp() . If so, take a sheet from the BSD book (MacOS X); there is an execvp() function:

  int execvP(const char *file, const char *search_path, char *const argv[]); 

which allows you to specify the search path to use, even if you fixed the environment. The most fundamental call is execve() ; this is used by execvp() backstage (possibly through execv() ).

+4
source

Source: https://habr.com/ru/post/906521/


All Articles