3

You don't have to go through the complete code from the beginning. The problem is in the execl(..) statement inside main. Code is --

#include <cstdio>
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <vector>

#define li long int

using namespace std;


char TypedCommandInTerminal[1001];
vector <string> ValidCommands,TypedCommand;


void ShowTerminal()
{
    cout<<"User:$ ";
    gets(TypedCommandInTerminal);
}


void PushCommands()
{
    ValidCommands.push_back("mkdir");
}


void GetCommandIntoVector()
{
    TypedCommand.clear();

    char *p = strtok(TypedCommandInTerminal," ");

    while(p)
    {
        TypedCommand.push_back(p);
        p = strtok(NULL," ");
    }
}

bool MatchCommand(string Command)
{
    li i;

    for(i=0;i<ValidCommands.size();i++)
    {
        if(ValidCommands[i].compare(Command)==0)
        {
            return true;
        }
    }
    return false;
}



int main()
{
    int status;
    string StoredCommand;

    PushCommands();
    while(true)
    {
        ShowTerminal();
        if(fork()!=0)
        {
            waitpid(-1,&status,0);
        }
        else
        {
            GetCommandIntoVector();
            if(MatchCommand(TypedCommand[0]))
            {
                StoredCommand = "mkdir";
                if(StoredCommand.compare(TypedCommand[0])==0)
                {
                    execl("/bin/mkdir","mkdir",TypedCommand[1],NULL);/*ERROR*/
                }
            }
            else
            {
                cout<<"Command Not Available\n";
                return -1;
            }
        }
    }
    return 0;
}

I am trying to design a simple terminal using c++ in linux. What I am trying to do here is -- taking this command in console as input - "mkdir ab" . Then I managed to tokenize this string and kept "mkdir" in TypedCommand[0] and "ab" in TypedCommand[1]. Problem is when I write "TypedCommand[1]" inside execl compiler gives an error--"cannot pass objects of non-trivially-copyable type....." I removed TypedCommand[1] and manually wrote "ab" in place of it. The code ran and created a folder named "ab" in the execution directory. So looks like execl is working fine.

I need to pass the second string saved in TypedCommand[1] inside execl in some way...what is wrong here ?

Pavel
  • 138
  • 2
  • 4
  • 16
  • 1
    `execl` doesn't and cannot work with `string` objects. It works with raw pointers to `char`. As for what to change to get it working, see [this question](http://stackoverflow.com/questions/347949/convert-stdstring-to-const-char-or-char). –  Aug 24 '14 at 13:22
  • @hvd This is not a duplicate of http://stackoverflow.com/questions/347949/convert-stdstring-to-const-char-or-char . That question is solely about how to convert a `std::string` to `const char *` this question is about passing a non-trivial object to a function taking variable arguments. While the solutions are the same they are two completely different questions. I'm sure this there is a duplicate of this question but that is not it. – Captain Obvlious Aug 24 '14 at 13:28
  • @CaptainObvlious There's been a lot of disagreement in the past over whether closing as a duplicate should be done when the other *question* is the same, or when the other question's *answers* also answer this one. I closed it because that question's answers also answer this one, but now that you brought it up, I have looked for relevant questions on Meta, agree with you, and have re-opened this question. –  Aug 24 '14 at 13:43

1 Answers1

9

You're passing a std::string object as a optional argument to a function (execl accepts a variable number of arguments). std::string has non-trivial constructors, destructor, etc. and cannot be used this way. In this case you want to pass a pointer to a string anyway so change

execl("/bin/mkdir","mkdir",TypedCommand[1],NULL);

to

execl("/bin/mkdir","mkdir",TypedCommand[1].c_str(),NULL);
Captain Obvlious
  • 19,754
  • 5
  • 44
  • 74