Ik moet een eenvoudige shell in C ontwikkelen met systeemaanroepen fork()/execvp(). Tot dusverre neemt mijn code een commando op, splitst het op met behulp van strtok in een array argv en dan roep ik fork om een kind te maken en het commando uit te voeren. Ik werk hieraan in ubuntu, waar de meeste opdrachten in de /bin/-map staan, dus ik voeg de programmanaam toe (bijvoorbeeld /bin/ls) en gebruik die voor het eerste arg van execvp en dan geef ik het de argv-array . Mijn programma werkt als ik het commando “ls” typ, maar als ik andere commando’s of zelfs “ls -l” probeer, krijg ik een “ls: ongeldige optie”. Ik weet niet zeker wat ik hier verkeerd doe.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_LEN 1024
int main(){
char line[BUFFER_LEN]; //get command line
char* argv[100]; //user command
char* path= "/bin/"; //set path at bin
char progpath[20]; //full file path
int argc; //arg count
while(1){
printf("My shell>> "); //print shell prompt
if(!fgets(line, BUFFER_LEN, stdin)){ //get command and put it in line
break; //if user hits CTRL+D break
}
if(strcmp(line, "exit\n")==0){ //check if command is exit
break;
}
char *token; //split command into separate strings
token = strtok(line," ");
int i=0;
while(token!=NULL){
argv[i]=token;
token = strtok(NULL," ");
i++;
}
argv[i]=NULL; //set last value to NULL for execvp
argc=i; //get arg count
for(i=0; i<argc; i++){
printf("%s\n", argv[i]); //print command/args
}
strcpy(progpath, path); //copy /bin/ to file path
strcat(progpath, argv[0]); //add program to path
for(i=0; i<strlen(progpath); i++){ //delete newline
if(progpath[i]=='\n'){
progpath[i]='\0';
}
}
int pid= fork(); //fork child
if(pid==0){ //Child
execvp(progpath,argv);
fprintf(stderr, "Child process could not do execvp\n");
}else{ //Parent
wait(NULL);
printf("Child exited\n");
}
}
}
Antwoord 1, autoriteit 100%
De ongeldige optie is omdat fgets()
de '\n'
behoudt wanneer je op enter drukt, probeer dit
if(!fgets(line, BUFFER_LEN, stdin))
break;
size_t length = strlen(line);
if (line[length - 1] == '\n')
line[length - 1] = '\0';
wanneer u ls -l
probeert aan te roepen, geeft u "-l\n"
door als optie, vandaar het bericht.
Je zult moeten veranderen
strcmp(line, "exit\n")
naar
strcmp(line, "exit")
Antwoord 2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#define BUFFER_LEN 1024
int main(){
char user_input[BUFFER_LEN]; //get command line
char* argv[120]; //user command
int argc ; //argument count
char* path= "/bin/"; //set path at bin
char file_path[50];//full file path
while(1){
printf("Simple Shell>> "); // Greeting shell during startup
if(!fgets(user_input,BUFFER_LEN, stdin)){
break; //break if the command length exceed the defined BUFFER_LEN
}
size_t length = strlen(user_input);
if(length == 0){
break;
}
if (user_input[length - 1] == '\n'){
user_input[length - 1] = '\0'; // replace last char by '\0' if it is new line char
}
//split command using spaces
char *token;
token = strtok(user_input," ");
int argc=0;
if(token == NULL){
continue;
}
while(token!=NULL){
argv[argc]=token;
token = strtok(NULL," ");
argc++;
}
argv[argc]=NULL;
strcpy(file_path, path); //Assign path to file_path
strcat(file_path, argv[0]); //conctanate command and file path
if (access(file_path,F_OK)==0){ //check the command is available in /bin
pid_t pid, wpid;
int status;
pid = fork();
if (pid == 0) { //child process
if (execvp(file_path,argv) == -1) {
perror("Child proccess end");
}
exit(EXIT_FAILURE);
}
else if (pid > 0) { // parent process
wpid = waitpid(pid, &status, WUNTRACED);
while (!WIFEXITED(status) && !WIFSIGNALED(status)){
wpid = waitpid(pid, &status, WUNTRACED);
}
}
else {
perror("Fork Failed"); //process id can not be null
}
}
else {
printf("Command is not available in the bin\n"); //Command is not available in the bin
}
}
}