Reputation: 45
I am trying to make a simple shell running any command from PATH, lets say ls or pwd du gedit etc. I am having trouble with exec.I require that if i enter space nothing happens and if i type exit it terminates.Any help is appreciated
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <string.h>
#define BUFFER 1024
int main() {
char line[BUFFER];
char* args[100];
char* path = "";
char program[20];
while(1){
printf("$ ");
if(!fgets(line, BUFFER, stdin))
break;
size_t length = strlen(line);
if (line[length - 1] == '\n')
line[length - 1] = '\0';
if(strcmp(line, "exit")==0) break;
strcpy(program,path);
strcat(program,line);
int pid= fork(); //fork child
if(pid==0){ //Child
execlp(program,line,(char *)NULL);
}else{ //Parent
wait(NULL);
}
}
}
Upvotes: 2
Views: 10502
Reputation: 121387
You have 2 fgets()
call. Remove the first one fgets(line, BUFFER, stdin);
.
fgets()
will read in the newline if there's space in buffer. You need to remove it because when you input exit
, you'll actually input exit\n
and there's no command as /bin/exit\n
.
The below code demonstrates removing newline character:
if(!fgets(line, BUFFER, stdin))
break;
char *p = strchr(line, '\n');
if (p) *p = 0;
execl
. You need to pass the arguments: execl(program, line, (char *)NULL);
Notice the cast of last argument of NULL
. In case, NULL
is defined as 0
then the cast becomes necessary because execl
is a variadic function.A modified example using execvp
:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <string.h>
#define BUFFER 1024
int main(void) {
char line[BUFFER];
while(1) {
printf("$ ");
if(!fgets(line, BUFFER, stdin)) break;
char *p = strchr(line, '\n');
if (p) *p = 0;
if(strcmp(line, "exit")==0) break;
char *args[] = {line, (char*)0};
int pid= fork(); //fork child
if(pid==0) { //Child
execvp(line, args);
perror("exec");
exit(1);
} else { //Parent
wait(NULL);
}
}
return 0;
}
Upvotes: 2
Reputation: 5591
Hi See my correction below and see my comment as well.
int main() {
char line[BUFFER];
char* args[100];
char* path = "/bin/";
char program[20];
char command[50];
while(1){
printf("$ ");
if(!fgets(line, BUFFER, stdin))
break;
memset(command,0,sizeof(command));
if(strncmp(line, "exit", (strlen(line)-1))==0) break;
strncpy(command,line,(strlen(line)-1));
strcpy(program, path);
strcat(program,command);
int pid= fork(); //fork child
if(pid==0){ //Child
execl(program,command,NULL);
exit(0);// you must exit from the child because now you are inside while loop of child. Otherwise you have to type exit twice to exit from the application. Because your while loop also became the part of every child and from the child again it will call fork and create a child again
}else{
wait(NULL);
}
}
}
Also to support all command execution see the function execl
how you need to pass the parameters in it. Accordingly you need to split your command and create the parameter list properly for execl
.
Upvotes: 1