0

I am implementing a shell by using C++ as my coding language.

Basically I define a char *argv[128] for storing the command by strtok the space.

So if I input ls -a -l > test.txt it will turn to

ls
-a
-l
>
test.txt

What I want to do is to separate the '>' symbol so I can continue implement the redirection and pipe function.

Well I want to define a vector to store the ls-a-l and test.txt and let the program do the redirection function.

How can I do that?

Howe Chen
  • 143
  • 2
  • 12
  • 2
    What do you mean by "separate"? It's already separate in your list. – Mat Apr 28 '15 at 05:37
  • @Mat Well I want to define a vector to store the ls-a-l and test.txt and let the program do the redirection function. – Howe Chen Apr 28 '15 at 05:39
  • 2
    You want `argv` to be of `std::vector` type, not `char*argv[128]`. You are asking how to parse and tokenize a line. And you need lexical conventions (how would you input an argument containing a space)! – Basile Starynkevitch Apr 28 '15 at 05:39
  • what do u mean by let the program do the redirection ? – smali Apr 28 '15 at 05:42
  • 1
    Which program is going to do the redirection? `ls` won't; it always writes to standard output. It is up to your shell to make sure that the output of `ls` goes to the file you want it to go to rather than the terminal. There's nothing to stop you, and probably some good, in revising the argument list so that I/O redirections are recognized and stored separately from actual command arguments. – Jonathan Leffler Apr 28 '15 at 05:43
  • 1
    Also, any fixed length argument list you're likely to devise is too short. You need to be prepared to handle hundreds, even thousands, of arguments. – Jonathan Leffler Apr 28 '15 at 05:44
  • @ali786 I want the shell I built to do the redirection and pipe jobs. – Howe Chen Apr 28 '15 at 05:44
  • @JonathanLeffler Well this is just a project of my course.. The max length of command is 256 so for now I just set the length as 128. – Howe Chen Apr 28 '15 at 05:45
  • @HoweChen: you are wrong; the command `ls *` could expand to `/bin/ls` invoked with many thousands of arguments. – Basile Starynkevitch Apr 28 '15 at 06:23
  • @BasileStarynkevitch You are right but this project limited the length to 256 – Howe Chen Apr 28 '15 at 06:35

2 Answers2

0

You should define lexical conventions for your shell. For instance in POSIX shells you can pass an argument with a space by e.g. quoting it or escaping it with a backslash, like in
ls > 'file name with spaces' which get the output of ls into a single file named file name with spaces

If coding in C++, you should use genuine C++ features. So you would read the line into a std::string using std::getline. Then you should tokenize that string, i.e. transform it into a sequence of tokens. Some tokens are special (so > is not the same as the quoted '>' etc...). So define a class Token and implement a parser which gives a std::vector<Token> from a line (of type std::string) that you have previously read.

Of course you'll need to know some syscalls, so read e.g. Advanced Linux Programming. For instance, cd has to be a shell builtin which calls chdir(2). Redirections need to use dup2(2) and open(2). Pipes need to use pipe(2) etc....

BTW, you should look into the source code of free software shells (and use strace to find out what they do). Most are coded in C (e.g. GNU bash, or sash), but fish is coded in C++.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
-1

If you would like to separate lexical symbols you should define lexical conventions. You can use flex++ to generate parser for you.

If you want to do redirection in your shell, try method dup2() You can find similar Q&A here.

Community
  • 1
  • 1
M.L.
  • 728
  • 4
  • 12