-1

I am writing a simple shell program in C++. When I pass my arguments into execvp, in particular, for the ls command, I receive a ls: cannot access H��p����: Protocol error. A similar error occurs for other commands as well.

My strategy is the parse the input into a vector<vector<char> and then convert it into a char **.

Here is the conversion code below:

//input is parsed from command-line above
vector< vector<char> > args_vector;

string s;
stringstream ss(input);

while(getline(ss, s, ' ')){
    vector<char> cv(s.begin(), s.end());
    cv.push_back('\0');
    args_vector.push_back(cv);
}

char *args[args_vector.size() + 1];

for(int i = 0; i < args_vector.size(); i++){
    char *arg = &args_vector[i][0];   
    args[i] = arg;
}

args[args_vector.size() + 1] = NULL;

Then I pass args into execvp in the following code below:

pid_t child_pid
int status;
child_pid = fork();

if (child_pid == 0) {
    execvp(args[0], args);
    cout << "Error: execution of command failed";
}
else {
    pid_t pid;
    do {
        pid = wait(&status);
    } while (pid != child_pid);
}

I am compiling the code with clang++ and on a Debian 8 VM on Mac OS X. Does anyone have idea whats going?

Riddhesh Sanghvi
  • 1,218
  • 1
  • 12
  • 22
iknowhtml
  • 17
  • 7
  • You do know that the normal input operator `>>` separates on space, and when reading strings discards leading space? Which means your tokenizing loop can be simply `while (ss >> s) { ... }`. – Some programmer dude Sep 24 '15 at 12:49
  • Also, you write out of bounds of the `args` array (and note that [variable-length arrays](https://en.wikipedia.org/wiki/Variable-length_array) are not part of C++). And I don't see the reason for the nested vector in the first place, just use a vector of `std::string`, and then a vector of `const char*`, and don't let the first vector of `std::string` go out of bounds (which is probably your problem)! Convert to a vector of `const char*` only when actually needed, i.e. just before the `exec` call. – Some programmer dude Sep 24 '15 at 12:52
  • Hi, thanks for the quick response! I use the nested vectors because I do not know the length of my arguments or the the length of each individual arguement and do not want to deal with the overhead of handling variable length arrays. With that put into consideration, is it still a sub-optimal solution? – iknowhtml Sep 24 '15 at 13:03
  • Also, I am not sure what you mean by letting my vector go out of bounds. I'm assuming you mean that I am putting my more elements in the vector than is allocated for it in memory, but I'm confused as to what the issue is with that since it's vector. – iknowhtml Sep 24 '15 at 13:05

1 Answers1

0

To elaborate on my guess for your problem: I guess that the tokenizing (the first snippet of code) is in a separate function, and it then returns which makes the vector of vectors of characters you have be destructed, so the pointers you save in the args array will no longer be valid. This leads to undefined behavior, and you are pretty lucky the program doesn't actually crash (which is a common symptom of undefined behavior).

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • I have printed out the elements in args after the while loop and they are what I expect them to be. For ls, I run the following code snippet `cout << args[0][0]< – iknowhtml Sep 24 '15 at 13:11
  • The problem turned to be the issue you pointed out. I initilized `char *args[]` outside of the `while` loop and it now works properly. Thank you so much for the help! – iknowhtml Sep 24 '15 at 13:22