2

Hello I need to run a program using execvp() the thing is that im getting a sting as argument and i cant seem to match the syntax of the command to work properly here is the code:

int executeUserCommand(char *command, int runInBackground) {
    pid_t pid;
    int status;
    pid = fork();
    if (pid == 0) {
        //child process
        execvp(command, &command);
        exit(1);
    } else {
       //perent
       if (!runInBackground) {
           waitpid(pid, &status, 0);
           return WEXITSTATUS(status);
       }
    }
    return 0;
}

and i am using executeUserCommand("./test 1 2 3", 0) the thing is that the program is running but without the arguments.. what is the problem and how i solve it?

EDIT: i have added two fuctions to help me with the spliting and its still not working.

char *getCommand(char *commandAndArguments) {
    char command[256];
    memset(command,0,MAX_LENGTH_OF_LINE);
    sscanf(commandAndArguments,"%s ", command);
    //strncpy(command, commandAndArguments, command - commandAndArguments);
    return command;
}

void commandToArrguments(char *stringToSplit) {
  const char *p = stringToSplit;
  int n, len;
  int i = 0;
  for (n = 0; n < MAX_NUMBER_OF_COMMANDS; n++) {
    for (len=0; len < MAX_LENGTH_OF_LINE-1; len++) {
      if (p[0] == '\0') {
        break;
      }
      if (p[0] == ' ') {
        p += 1;
        break;
      }

      commandArgumnets[n][len] = *p;
      p++;
    }
    commandArgumnets[n][len] = '\0';
  }
}

int executeUserCommand(char *command, int runInBackground) {
pid_t pid;
int status;
pid = fork();
char *commandToExecute = getCommand(command);
if (pid == 0) {
    //child process
    execvp(commandToExecute, commandArgumnets);
    exit(1);
} else {
    //perent
    if (!runInBackground) {
        waitpid(pid, &status, 0);
        return WEXITSTATUS(status);
    }
}
return 0;

}

commandArgumnets is defined as global and still not working

tubu13
  • 924
  • 2
  • 17
  • 34

2 Answers2

8

The execvp call expects arguments to be separated out in an array. You're providing only a single argument, which tells the OS to run a program called ./test 1 2 3 instead of running ./test with the parameters ./test, 1, 2, and 3 (yes, the 0th parameter should be the executable).

So you need to construct an array of strings by splitting your command into separate arguments (perhaps splitting along all spaces, perhaps taking quotes into consideration). How you do that is up to you. Each string in your array should be just one argument without spaces.

Like this:

char* args[5];
args[0]="./test";
args[1]="1";
args[2]="2";
args[3]="3";
args[4]=NULL;

execvp(args[0],args);
tylerl
  • 30,197
  • 13
  • 80
  • 113
0

Here is another example similar to your function: (From Here)

Notice how argv is set up in main()..., then passed to execute() . Notice also the prototype used to pass argv ... char **
Use a similar argument type (i.e. array of strings) in your version.

void  execute(char **argv)
{
     pid_t  pid;
     int    status;

     if ((pid = fork()) < 0) {     /* fork a child process           */
          printf("*** ERROR: forking child process failed\n");
          exit(1);
     }
     else if (pid == 0) {          /* for the child process:         */
          if (execvp(*argv, argv) < 0) {     /* execute the command  */
               printf("*** ERROR: exec failed\n");
               exit(1);
          }
     }
     else {                                  /* for the parent:      */
          while (wait(&status) != pid)       /* wait for completion  */
               ;
     }
}

void  main(void)
{
     char  line[1024];             /* the input line                 */
     char  *argv[64];              /* the command line argument      */

     while (1) {                   /* repeat until done ....         */
          printf("Shell -> ");     /*   display a prompt             */
          gets(line);              /*   read in the command line     */
          printf("\n");
          parse(line, argv);       /*   parse the line               */
          if (strcmp(argv[0], "exit") == 0)  /* is it an "exit"?     */
               exit(0);            /*   exit if it is                */
          execute(argv);           /* otherwise, execute the command */
     }
}
ryyker
  • 22,849
  • 3
  • 43
  • 87