0
pid_t childPid = fork ();
if (childPid == (pid_t) 0)//zero success
{
    const char *path = "/usr/local/mysql/bin/mysql";
    //doesn't work
    //char * const parmList[] = {"--user=root", "test_db", NULL};
    //does work
    char * const parmList[] = {"", "--user=root", "test_db", NULL};
    execv(path, parmList);
    printf("ERROR:\tFork failed.\n");   
}
else if (childPid < (pid_t) 0)// -1 failure
{
    /* The fork failed. */
    printf("ERROR:\tFork failed.\n");   
    return EXIT_FAILURE;
}
else
{
    while (true) {
        //stay alive
        sleep(1);
    }
}
printf("done");
exit(0);

I am having trouble importing a sql dump by using execv. You can see I wasn't able to login using the first paramList but the second one worked just fine. Anyways, if I add to the param list:

char * const parmList[] = {"", "--user=root", "test_db", "<", "/Users/joelsaltzman/Desktop/dump.sql", NULL};

The output shows the mysql help for the command line args like I typed something wrong. Does anybody know how to get this to work?

joels
  • 7,249
  • 11
  • 53
  • 94

3 Answers3

3

The first paramList is incorrect, because the first element should be the filename of the program you are going to execute:

The argument argv is an array of character pointers to null-terminated strings. The application shall ensure that the last member of this array is a null pointer. These strings shall constitute the argument list available to the new process image. The value in argv[0] should point to a filename that is associated with the process being started by one of the exec functions.

The input redirection with < does not work because this is not a feature of the kernel (which you invoke using execv), but of usual Unix shells. The system library call is what you are looking for. (It also just uses a call from the exec-family, but calls a shell with your command, which will then support <.)

Be sure to read the manpage system(3) and think about input validation if you are going to pass it a string that could be influenced by a malicious user.

fnl
  • 2,209
  • 19
  • 17
  • It is legitimate (but _very_ weird) to tell the `mysql` program it is called `--user=root`, but that won't be treated as an option argument by the program. It is also legitimate (but _rather_ weird) not to tell the program what it is called by supplying an empty string. This might matter if the program looks at its name to decide what it is supposed to do. This can happen if a program is designed to behave differently depending on the name it is invoked under. (Consider `cc` and `gcc`, which are links to the same executable; `c89` and `c99` are simple scripts rather than links to `gcc`.) – Jonathan Leffler Feb 11 '12 at 20:19
2

The second one works better, because the first parameter should be the command name. Therefore, MySQL starts reading from the second parameter. You should use the command name (the path), not an empty string, but it normally doesn't matter.

You can't use redirection with execv, because this is a shell feature, and execv doesn't run the shell. You can execute /bin/sh, with parameters that tell it to run mysql, or you can use dup2 to change stdin to whatever you want.

ugoren
  • 16,023
  • 3
  • 35
  • 65
1

Use popen() instead to start mysql, and then write the contents of the sql file into the process yourself.

Erik Ekman
  • 2,051
  • 12
  • 13