Search code examples
cshellexecvp

Shell in C - how to read and execute user input?


My assignment is to write a very simple shell in C. I don't have many sources given and I have just started learning C, I have used only scanf() and printf() and coded simple functions. I only know it supposed to be written with fork() and different exec(). I spent a lot of time analyzing other shells, but I don't understand the structure of programs and some functions, like:

  1. parsing, why do we need parsing? If I know I won't use arguments in commands, I would like only to compare input with my own functions like help() or date() and execute them.
  2. reading user input. Using the fgets() and then strcmp()?
  3. executing, how does it works? How execvp() knows that the user input is a command(function) in my main or program in my program folder?

Solution

  • First, let me say this sounds like a daunting task for a person just learning C, unless it's very carefully restricted. It does not make sense for you to need to analyze other shells. I'd advise you talk to a teaching assistant about the scope of the assignment, and what you're expected to do given your experience.

    To answer your questions, though:

    why do we need parsing?

    Parsing is (in this context) taking a sequence of characters and producing a data structure which your proagram can work on. Now, this could be a rather simple structure if there are not supposed to be any arguments, no multiple commands per line etc. However, you at least have to make sure that the user has indeed not used arguments, not written down an invalid command line, closed their open parentheses and so on.

    If I know I won't use arguments in commands

    The program is not written for the perfect user whose behavior you can predict. You must accommodate any user, who may insert just about anything; you'll need to notice this case and report an error.

    reading user input. Using the fgets() and then strcmp()?

    Remember that fgets() may not get through the entire line - if the line is longer than your buffer length minus 1. But perhaps you are guaranteed a line length limit? Or are allowed to fail on overly long lines?

    Also, it might be the case that the user is allowed to use extra white-space as part of the line, in which case strcmp() might not give you want you want.

    executing, how does it works? How execvp() knows that the user input is a command(function) in my main or program in my program folder?

    Have a look at the man page for execvp() (and friends). Basically, what happens when you call execvp() is that the binary at a specified location gets run, and its command-line is what you pass as the second argument of execvp(). Suppose you run

    execvp("/path/to/foo", "/path/to/foo", "bar");
    

    so, the program at /path/to/foo is run. Like any program, its argv[0] is the path to itself. Its argc will be 2 and its argv[1] will be "bar". Its working directory (and user and group id) will be the current directory, and user and group id, of the process which ran the execvp(), so - not necessarily /path/to/foo.

    Continuing the previous example, you could do:

    chdir("/path/to");
    execvp("foo", "foo", "bar");
    

    at which time foo would run with argv[0] being foo.