-1

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?
einpoklum
  • 118,144
  • 57
  • 340
  • 684
L.krez
  • 31
  • 5
  • 4
    Break it down into smaller parts, and learn each small part one by one. For example, what does `fork` do? What does it return? How does it work? What are parent and child processes? Experiment with `fork` and processes, until you get how it works. Then when you know about `fork` then move on to the next part. And so on. Before you know it you will have enough knowledge about each small part, that it becomes a simple puzzle and all you have to do it put the pieces together. And [here's some very related reading](https://ericlippert.com/2014/03/21/find-a-simpler-problem/) about that subject. – Some programmer dude Jan 05 '19 at 13:41
  • exec takes a list of arguments. Parsing is what converts your command string to that list. – stark Jan 05 '19 at 13:43
  • 1
    Suggestion: avoid scanf. You will spend a lot of time debugging arcane issues of the format string and not learn anything useful. Use `fread` and `fgetc` family of functions for your input. Learning to use these will be far more useful. – William Pursell Jan 05 '19 at 14:58

1 Answers1

2

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.

einpoklum
  • 118,144
  • 57
  • 340
  • 684