I am writing a program to implement a simple shell in C but when I execute the program at the end when I type exit it does not exit.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.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
size_t length = strlen(line);
if (line[length - 1] == 'n')
line[length - 1] = '';
break; //if user hits CTRL+D break
}
if (strcmp(line, "exit") == 0) { //check if command is exit
exit(0);
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("%sn", 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] = '';
}
}
int pid = fork(); //fork child
if (pid == 0) { //Child
execvp(progpath, argv);
fprintf(stderr, "Child process could not do execvpn");
} else { //Parent
wait(NULL);
printf("Child exitedn");
}
}
}
I am executing in on cygwin hence a.exe is generated.
execution of program
$ ./a.exe My shell>> ls ls a.exe p3.4.cpp p3.6.cpp p3.6.cpp~ p3.7.cpp p3.7.cpp~ p3.cpp shell.c shell.c~ test.txt Child exited My shell>> cat test.txt cat.txt Child process could not do execvp My shell>> exit exit Child process could not do execvp My shell>> exit() exit() Child process could not do execvp My shell>> exit exit Child process could not do execvp My shell>> exit exit
Here you can see in the above output the program is not able to exit when I am typing an exit on the command prompt. What is the mistake I am doing in above program?
Advertisement
Answer
You probably mixed removing the new line with the handling of CTRL-D. Your code
if (!fgets(line, BUFFER_LEN, stdin)) { //get command and put it in line
size_t length = strlen(line);
if (line[length - 1] == 'n')
line[length - 1] = '';
break; //if user hits CTRL+D break
}
removed the new line only if fgets fails, e.g. end of file has been reached.
Also, line[length-1] will yield undefined behaviour if length==0.
I’d replace the logic:
if (!fgets(line, BUFFER_LEN, stdin)) { //get command and put it in line
break; //if user hits CTRL+D break
} else {
line[strcspn(line, "n")] = '';
}