Reputation: 13
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);
}
Upvotes: 1
Views: 2856
Reputation: 754390
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.
Upvotes: 3