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")] = ''; }