1

I have to write a program that will start a new program called demo.cpp using execvp when user inputs certain commands. User will enter input in the format

bg demo word int1 int2 (ignore the word relevance of the word bg, I store it in a string called command in my code).

This is the code :

int main(){

char *argv[5];
argv[0] = new char[10];
argv[1] = new char[10];
argv[2] = new char[10];
argv[3] = new char[10];
argv[4] = nullptr;


string command;
pid_t PID;

cin>>command; //store the string 'bg'

cin>>argv[0]>>argv[1]>>argv[2]>>argv[3];

PID = fork();

if(PID<0){
    perror("Fork failed!"); 
}

else if(PID==0){

    if(execvp("./demo.cpp",argv)<0)
          printf("Failed");
    }

 wait(0);

 return 0;
 }

Every time the code prints "Failed". The only thing I can think is that maybe there's an error in the format of arguments passed to execvp. This code and demo.cpp are stored in the same folder.

Sim
  • 27
  • 4
  • 2
    What is `./demo.cpp`? Is it a C++ source file? You cannot execute a C++ source file. – mch Feb 13 '17 at 09:51
  • Search for similar problems on SO, check this question for example http://stackoverflow.com/questions/14301407/how-does-execvp-run-a-command – Laza Feb 13 '17 at 09:52
  • @mch : I am being stupid! Of course you can't execvp the C++ source file. – Martin Bonner supports Monica Feb 13 '17 at 10:03
  • @mch Oh so you mean I have to give the name of the executable file? But the youtube tutorials I have seen simply write the .cpp address. – Sim Feb 13 '17 at 10:12
  • @mch Yes I changed the argument to the name of the executable file and it works now! Thank you – Sim Feb 13 '17 at 10:19

1 Answers1

2

You have two problems: Firstly execvp needs the supplied argument list to be null-terminated. You need

    char *argv[5];  // Not 4.

    ...  // input as before

    argv[4] = nullptr;

Incidentally, personally I would change this to:

    std::array<std::string,4> arguments;
    std::cin>>arguments[0]>>arguments[1]>>arguments[2]>>arguments[3];
    char *argv[5];
    for (size_t i = 0; i<4; i++) {
       argv[i] = const_cast<char*>(arguments[i].c_str());
    }
    argv[4] = nullptr;

The point is to do the input into std::string, and then get the char pointer afterwards. This avoids any risk of buffer overflow. (On the other hand, the const_cast is not very nice - but I am pretty sure it is actually safe.)

Secondly, you cannot pass exec* the name of a C++ source file! You have to build the executable (probably calling it demo), and then exec that:

    if(execvp("./demo",argv)<0)

(You also need to make sure that the current directory is the directory containing the executable.)

  • I tried the first suggestion and it still fails, though I have edited the code in the question to incorporate your suggestion – Sim Feb 13 '17 at 09:59
  • You are right, the error was that I was passing the source file! Why don't tutorials mention this detail! – Sim Feb 13 '17 at 10:20