简体   繁体   中英

execvp() ls no such file or directory

I am writing a shell emulator where if the user types "lsh ls" I would run the command ls and ignore the "lsh" that was input by the user. So I am using the readline library to get the input, and then parsing the line. Then I am using fork() and execvp() to run the ls command. However, When I type lsh ls I get the following output:

lsh: ls: No such file or directory

Here is my code. I think it's treating ls as a file to search, but I don't get why it is doing this.

int main(){
  pid_t id;
  char* line;
  char **args;
  while(1){
    line = readline("shell: > ");
    if(strcmp(line,"exit") == 0){
        break;
    }
    args = parse(line);
    if(strcmp(args[0],"lsh") == 0){
        id = fork();
        if (id == 0){
            if(execvp(args[1],args) < 0){
                perro("no such command");
            }
        }
        if(id > 0){
            printf("I am the parent process, id %d\n",getppid());
        }
    }   
    free(line);
  }
}

Here is the function which parses the line.

#define LSH_TOK_BUFSIZE 64
#define LSH_TOK_DELIM " \t\r\n\a"
char **parse(char *line){
   int bufsize = LSH_TOK_BUFSIZE, position = 0;
   char **tokens = malloc(bufsize * sizeof(char*));
   char *token;
   if (!tokens) {
    fprintf(stderr, "lsh: allocation error\n");
        exit(EXIT_FAILURE);
   }

  token = strtok(line, " \n");
  while (token != NULL) {
    tokens[position] = token;
    position++;

  if (position >= bufsize) {
    bufsize += LSH_TOK_BUFSIZE;
    tokens = realloc(tokens, bufsize * sizeof(char*));
  if (!tokens) {
    fprintf(stderr, "lsh: allocation error\n");
    exit(EXIT_FAILURE);
  }
  }

  token = strtok(NULL, LSH_TOK_DELIM);
  }
  tokens[position] = NULL;
  return tokens;
  free(tokens);
}

The error message you see is coming from ls , not lsh .

You have, in effect:

char *args[] = { "lsh", "ls", 0 };

execvp(args[1], args);

This means that you attempt to execute ls , and do so successfully, but you tell ls that it is called lsh because argv[0] is set to lsh and request that it list the file ls in the current directory. So, when ls attempts to find the file, it fails, and reports the error using the command name you gave it, lsh .

You could try this (the output shown was obtained on macOS Sierra):

$ cp /bin/ls xx97
$ ./xx97 23-ish
xx97: 23-ish: No such file or directory
$ rm xx97

You need to use:

execvp(argv[1], &argv[1]);

Then you'll invoke ls in an orthodox manner.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM