// C Program to design a shell in Linux #include #include #include #include #include #include #include #include #include #define MAXCOM 1000 // max number of letters to be supported #define MAXLIST 100 // max number of commands to be supported // Clearing the shell using escape sequences #define clear() printf("\033[H\033[J") // Function to take input int takeInput(char* str) { char* buf; buf = readline("\n$ "); if (strlen(buf) != 0) { add_history(buf); strcpy(str, buf); return 0; } else { return 1; } } // Function where the system command is executed void execArgs(char** parsed) { // Forking a child pid_t pid = fork(); if (pid == -1) { printf("\nFailed forking child.."); return; } else if (pid == 0) { if (execvp(parsed[0], parsed) < 0) { printf("\nsh: command not found: \%s", parsed[0]); } exit(0); } else { // waiting for child to terminate wait(NULL); return; } } // Function where the piped system commands is executed void execArgsPiped(char** parsed, char** parsedpipe) { // 0 is read end, 1 is write end int pipefd[2]; pid_t p1, p2; if (pipe(pipefd) < 0) { printf("\nPipe could not be initialized"); return; } p1 = fork(); if (p1 < 0) { printf("\nCould not fork"); return; } if (p1 == 0) { // Child 1 executing.. // It only needs to write at the write end close(pipefd[0]); dup2(pipefd[1], STDOUT_FILENO); close(pipefd[1]); if (execvp(parsed[0], parsed) < 0) { printf("\nsh: command not found: \%s", parsed[0], parsedpipe[0]); exit(0); } } else { // Parent executing p2 = fork(); if (p2 < 0) { printf("\nCould not fork"); return; } // Child 2 executing.. // It only needs to read at the read end if (p2 == 0) { close(pipefd[1]); dup2(pipefd[0], STDIN_FILENO); close(pipefd[0]); if (execvp(parsedpipe[0], parsedpipe) < 0) { printf("\nsh: command not found: \%s", parsedpipe[0]); exit(0); } } else { // parent executing, waiting for two children wait(NULL); wait(NULL); } } } // Function to execute builtin commands int ownCmdHandler(char** parsed) { int NoOfOwnCmds = 2, i, switchOwnArg = 0; char* ListOfOwnCmds[NoOfOwnCmds]; char* username; ListOfOwnCmds[0] = "exit"; ListOfOwnCmds[1] = "cd"; for (i = 0; i < NoOfOwnCmds; i++) { if (strcmp(parsed[0], ListOfOwnCmds[i]) == 0) { switchOwnArg = i + 1; break; } } switch (switchOwnArg) { case 1: exit(0); case 2: if(parsed[1]){ chdir(parsed[1]); return 1; } else { char *home = getenv("HOME"); chdir(home); return 1; } default: break; } return 0; } // function for finding pipe int parsePipe(char* str, char** strpiped) { int i; for (i = 0; i < 2; i++) { strpiped[i] = strsep(&str, "|"); if (strpiped[i] == NULL) break; } if (strpiped[1] == NULL) return 0; // returns zero if no pipe is found. else { return 1; } } // function for parsing command words void parseSpace(char* str, char** parsed) { int i; for (i = 0; i < MAXLIST; i++) { parsed[i] = strsep(&str, " "); if (parsed[i] == NULL) break; if (strlen(parsed[i]) == 0) i--; } } int processString(char* str, char** parsed, char** parsedpipe) { char* strpiped[2]; int piped = 0; piped = parsePipe(str, strpiped); if (piped) { parseSpace(strpiped[0], parsed); parseSpace(strpiped[1], parsedpipe); } else { parseSpace(str, parsed); } if (ownCmdHandler(parsed)) return 0; else return 1 + piped; } int main() { char inputString[MAXCOM], *parsedArgs[MAXLIST]; char* parsedArgsPiped[MAXLIST]; int execFlag = 0; while (1) { // take input if (takeInput(inputString)) continue; // process execFlag = processString(inputString, parsedArgs, parsedArgsPiped); // execflag returns zero if there is no command // or it is a builtin command, // 1 if it is a simple command // 2 if it is including a pipe. // execute if (execFlag == 1) execArgs(parsedArgs); if (execFlag == 2) execArgsPiped(parsedArgs, parsedArgsPiped); } return 0; }