1

I'm real lost here. Building a Linux shell, working on processing external commands. I'm trying to create a new process then execute the commands. Very new to exec(), fork(), pipe() and dup(), but I'm sure I need them somewhere.

Basically my question is: what's the best way to pass arguments into exec? I know there's many options, but if I have a string vector that contains "ls -l" how do I pass that into execute? Should I re-parse it into "ls" and "-l"?

I already have fork() creating a child process, but I don't know how to run exec().

On a somewhat related note, what should I put in the waitpid part of fork()

                pid_t pid;
                int status;
                pid = fork();
                if (pid < 0)
                {
                    cout << "Fork failed." << endl;
                }
                else if (pid == 0)
                {

                    execv("/bin/sh", (VECTOR OF COMMANDS?));
                    _exit (EXIT_FAILURE);
                }
                else
                {
                    if (waitpid (pid, &status, 0) == pid)
                    {
                        cout << "huh?" << endl;
                    }
                    else
                    {
                        cout << "Error." << endl;
                    }
                }

The next hurdle is piping, but I'll cross that bridge when I get there.

EDIT:

For what it's worth, here's the parsing and calling that I'm having trouble with. The lines with "**" after seem to be the ones giving me problems

    const char *args [1024];

string::iterator it5;
size_t pos5;

for (it5=origCstr.begin(); it5 < origCstr.end(); it5++)
{
    string::iterator it2;
    pos5 = origCstr.find(' ');
    if (pos5 == string::npos)
    {
        tmpChar = origCstr.c_str();
        args[argCount] = tmpChar;
        argCount++;
        break;
    }
    it2 = it5 + pos5;
        tmpCstr = origCstr.substr(0, pos5);
    tmpChar = tmpCstr.c_str();
    args[argCount] = tmpChar;
    origCstr.erase(it5, it2+1);
    argCount++;
}
    tmpChar = origCstr.c_str();
args[argCount] = tmpChar;
argCount++;

    pid_t pid;
int status;
pid = fork();
if (pid < 0)
{
    cout << "Fork failed." << endl;
}
else if (pid == 0)
{

        execv("/bin/", args); ****
        _exit (EXIT_FAILURE);
}
else
{
    if (waitpid (pid, &status, 0) == pid)
    {
        cout << "huh?" << endl;
    }
    else
    {
        cout << "Error." << endl;
    }
}
twsmale
  • 139
  • 1
  • 5
  • 14
  • The errors are: invalid converstion from 'const char**' to 'char* const*' initializing argument 2 of 'int execv(const char*, char* const*)' – twsmale Jun 03 '12 at 04:14

1 Answers1

1

You will want to call 'execv' so that you can make a char*[] containing the options. "ls" and "-l" each get their own slot in the array.

You'll have to cast away const, or use a char `char const*[]' array and then cast away the const on that to pass it to execv. In general, the declarations for these system calls are mildly unfriendly to C++.

See a stack overflow question on this subject.

There's a reasonable tutorial at http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html.

Roughly speaking:

char * exec_args[1024];
int arg_count = 0;
std::vector<std::string> theArgs;

exec_args[arg_count++] = "/bin/whatever"; // leave command in argv[0]
for (int x = 0; x < theArgs.size(); x++) {
   exec_args[arg_count++] = strdup(theArgs[x].c_str());
}
exec_args[arg_count++] = 0; // tell it when to stop!

execv("/bin/whatever", exec_args);
Community
  • 1
  • 1
bmargulies
  • 97,814
  • 39
  • 186
  • 310
  • Okay, that was my thought. So here's the rookie question: now I'm having trouble passing them into the char array because they're being parsed as strings. As I'm re-parsing, this is the call I'm using to pass each one through. args[argCount] = tmpCstr.c_str(); The above gives me the "invalid conversion const char* to char*" error – twsmale Jun 03 '12 at 03:12
  • Never mind. Got that straightened out. Now I have an array of "ls" and "-l". How do I pass that in? Also, what size for the char* array? – twsmale Jun 03 '12 at 03:51
  • I had seen both of those documents before, however, neither answer my question at all. Because I'm initializing the array from a user input and not static, it's not helpful. PLEASE PLEASE, I desperately need help/examples – twsmale Jun 03 '12 at 17:48
  • Making SERIOUS progress, thanks so much @bmargulies. Any idea how to treat the '&' character as an input? Everything just keeps skipping over it – twsmale Jun 03 '12 at 18:57
  • I have no idea what this part is about. Perhaps a new question would be appropriate? I don't know how you are reading, what you are reading, or what's missing. – bmargulies Jun 03 '12 at 19:31
  • `exec_args[arg_count++] = "/bin/whatever";` looks like it's not valid C++ (the RHS is a *const* char array). – Kerrek SB Sep 17 '13 at 20:47