×
Samples Blogs Make Payment About Us Reviews 4.9/5 Order Now

Shell Creation Assignment Solution in Linux

July 11, 2024
Dr. Alice Davies
Dr. Alice
🇺🇸 United States
Operating System
Dr. Alice Davies, an alumna of Massachusetts Institute of Technology, United States, brings 15 years of experience to Operating System assignments. With a Ph.D. from MIT, her expertise ensures tailored solutions for student success.
Key Topics
  • New Shell Creation
Tip of the day
When working on OCaml assignments, make use of pattern matching to simplify your code. It provides a clean and efficient way to handle different cases, especially for recursive functions and data structures like lists and trees. This can reduce complexity and improve readability.
News
Universities worldwide are seeing a surge in programming enrollment, as coding becomes an essential skill across disciplines. To meet growing academic pressures, more students are seeking online help for programming assignments and coursework.

New Shell Creation

Question:

Construct a new Linux shell. Your shell will be called msh (Merrimack Shell).

Solution:

#include < stdio.h> #include < unistd.h> #include < sys times.h=""> #include < time.h> #include < dirent.h> #include < stdio.h> #include < string.h> #include < unistd.h> #include < stdlib.h> #include < ctype.h> #include < sys wait.h=""> #include < sys types.h=""> #include < sys wait.h=""> #include < fcntl.h> #include < stdbool.h> #include < time.h> #include < sys time.h=""> #include < sys stat.h=""> #define MAX_LINE 80 /* The maximum length command */ #define ANSI_COLOR_RESET "\x1b[0m" #define ANSI_COLOR_YELLOW "\x1b[33m" #define ANSI_COLOR_GREEN "\x1b[92m" #define ANSI_COLOR_BLUE "\x1b[94m" #define pipenow (alternate ? _file : file) #define futurepipe (alternate ? file : _file) #define READ 0 #define WRITE 1 #define CHILD 0 #define ERROR -1 #define PARENT default #define previouspipe futurepipe typedef enum { begining, center, ending, pipebool } pipestruct; /***************************** * We will use 2 pipes and * * alternate between them * * for to acheive many pipes * *****************************/ typedef int pipe_io[2]; char **completecmd, **futurecmd, **cmd; char input_file[512], output_file[512], error_file[512]; size_t i, semicolons, next, pipes; bool cmdline, background, alternate; int infile, outfile, errfile; pipe_io file, _file; pid_t pid; void executeWithPipes(char* cmds); void fillPipes(); void startWithPipe(pipestruct pipetype); void redirect(); void redirect_in(size_t index); void redirect_out(size_t index); void redirect_err(size_t index); void start(char** cmd, pipestruct pipetype); void clear(char** cmd); void fillPipes() { size_t i, j; pipestruct pipetype = begining; alternate = false; for (i = 0; cmd[i] != NULL; i++) if (!strcmp(cmd[i], "|")) { clear(&cmd[i]); while (true) { // run a pipe than decrease one from the sum if (pipe(pipenow) != ERROR) { startWithPipe(pipetype); pipes--; if (*cmd == NULL) return; for (j = 0; cmd[j] != NULL; j++) if (!strcmp(cmd[j], "|")) clear(&cmd[j]); ; //if it's the last pipe if (!(pipes > 0)) { startWithPipe(ending); return; } alternate = alternate ? false : true; } else perror("pipe()"); pipetype = center; } }; } void startWithPipe(pipestruct pipetype) { while (*cmd != NULL) { start(cmd, pipetype); // free all old commands for (i = 0; i < next; i++) if (cmd != NULL) clear(&cmd[i]); ; cmd = &cmd[next]; // if there is more pipes if (pipes > 0) break; } } int child_pid = 0; int killall=0; time_t startinternal; int timedout = 0; int timedoutsec = 0; void start(char** cmd, pipestruct pipetype) { void (*getfuturecmd)() = redirect; /* fork a child process*/ switch (pid = fork()) { case ERROR: perror("fork()"); break; case CHILD: if (*cmd == NULL) exit(EXIT_SUCCESS); switch (pipetype) { /* if it's the first element in pipes */ case begining: dup2(pipenow[WRITE], STDOUT_FILENO); break; /* if it's the middle element in pipes */ case center: dup2(previouspipe[READ], STDIN_FILENO); dup2(pipenow[WRITE], STDOUT_FILENO); break; /* if it's the last element in pipes */ case ending: dup2(pipenow[READ], STDIN_FILENO); default: break; } redirect(); execvp(*cmd, cmd); perror(*cmd); _exit(EXIT_FAILURE); /* if it's the parent process decide wether to wait based on & */ PARENT: child_pid = pid; switch (pipetype) { case begining: close(pipenow[WRITE]); break; case center: close(previouspipe[READ]); close(pipenow[WRITE]); break; case ending: close(pipenow[READ]); default: break; } if (!background) { if (timedout == 1) { alarm(timedoutsec); int state; waitpid(pid, &state, 0); printf("(%ld) WIFEXITED: %d\n", time(0), WIFEXITED(state)); } else while (wait(NULL) > 0) ; } getfuturecmd(); } } void redirect() { size_t i; for (i = 0; cmd[i] != NULL; i++) { if (!strcmp(cmd[i], "<")) redirect_in(i++); else if (!strcmp(cmd[i], ">")) redirect_out(i++); else if (!strcmp(cmd[i], "2>")) redirect_err(i++); } if (pipes > 0) i++; next = i; } void redirect_in(size_t i) { if (pid == CHILD) { clear(&cmd[i]); strcpy(input_file, cmd[++i]); clear(&cmd[i]); infile = open(input_file, O_RDONLY); if (infile != ERROR) { dup2(infile, STDIN_FILENO); close(infile); } else { perror(input_file); exit(EXIT_SUCCESS); } } } void redirect_out(size_t i) { if (pid == CHILD) { clear(&cmd[i]); strcpy(output_file, cmd[++i]); clear(&cmd[i]); outfile = open(output_file, O_RDWR | O_CREAT, 0777); if (outfile != ERROR) { dup2(outfile, STDOUT_FILENO); close(outfile); } else { perror(output_file); exit(EXIT_SUCCESS); } } } void redirect_err(size_t i) { if (pid == CHILD) { clear(&cmd[i]); strcpy(error_file, cmd[++i]); clear(&cmd[i]); errfile = open(error_file, O_RDWR | O_CREAT, 0777); if (errfile != ERROR) { dup2(errfile, STDERR_FILENO); close(errfile); } else { perror(error_file); exit(EXIT_SUCCESS); } } } void executeWithPipes(char* cmds) { size_t max = 1024; char* token; i = 0; semicolons = 0; completecmd = malloc(sizeof(char*) * max); token = strtok(cmds, " "); while (token != NULL) { if (!strcmp(token, ";")) { completecmd[i] = NULL; semicolons++; } else { completecmd[i] = malloc(sizeof(char) * (strlen(token) + 1)); strcpy(completecmd[i], token); } token = strtok(NULL, " "); if (i == max) completecmd = realloc(completecmd, max *= 2); i++; } completecmd[i] = NULL; if (!strcmp(completecmd[--i], "&")) { background = true; clear(&completecmd[i]); } else background = false; cmd = completecmd; size_t i; while (true) { pipes = 0; for (i = 0; cmd[i] != NULL; i++) if (!strcmp(cmd[i], "|")) pipes++; ; if (pipes > 0) fillPipes(); else startWithPipe(pipebool); if (semicolons > 0) { cmd = &cmd[1]; semicolons--; } else break; } free(completecmd); } void clear(char** cmd) { free(*cmd); *cmd = NULL; } char** splitstring(char* strs, int* n_spaces) { char** res = NULL; *n_spaces = 0; char* str = (char*)malloc(strlen(strs) + 1); strcpy(str, strs); char* p = strtok(str, " "); /* split string and append tokens to 'res' */ while (p) { *n_spaces = *n_spaces + 1; res = (char**)realloc(res, sizeof(char*) * (*n_spaces)); if (res == NULL) exit(-1); /* memory allocation failed */ res[*n_spaces - 1] = p; p = strtok(NULL, " "); } /* realloc one extra element for the last NULL */ res = (char**)realloc(res, sizeof(char*) * (*n_spaces + 1)); res[*n_spaces] = 0; return res; } void process_terminated(pid_t child_pid) { printf("\n\nterminated\n\n"); } static char* util_cat(char* dest, char* end, const char* str) { while (dest < end && *str) *dest++ = *str++; return dest; } size_t join_str(char* out_string, size_t out_bufsz, const char* delim, char** chararr) { char* ptr = out_string; char* strend = out_string + out_bufsz; while (ptr < strend && *chararr) { ptr = util_cat(ptr, strend, *chararr); chararr++; if (*chararr) ptr = util_cat(ptr, strend, delim); } return ptr - out_string; } time_t timepast24h; time_t timenow; time_t startime; time_t endtime; void printDate(time_t t) { char date[16]; strftime(date, 16, "%d-%m-%y %H:%M", localtime(&t)); printf("Date : %s\n", date); } void printDateraw(time_t t) { char date[36]; strftime(date, 26, "%d-%m-%y " ANSI_COLOR_GREEN " %H:%M " ANSI_COLOR_RESET, localtime(&t)); printf("%s", date); } void printDateraw1(time_t t) { char date[36]; strftime(date, 26, "%d-%m-%y %H:%M ", localtime(&t)); printf("%s", date); } void printHour(time_t t) { char date[16]; strftime(date, 16, "%H:%M", localtime(&t)); printf("Date : %s", date); } int n = 0; void mtime_cmd(char* basePath, const int root, time_t starttime1, time_t endtime1, int iprint) { if (timedout==1 && time(NULL) > startinternal + timedout) return; int i; char path[1000]; struct dirent* dp; DIR* dir = opendir(basePath); if (!dir) return; while ((dp = readdir(dir)) != NULL) { if (timedout==1 && time(NULL) > startinternal + timedout) return; if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0) { struct stat attr; char path1[1000]; strcpy(path1, basePath); strcat(path1, "/"); strcat(path1, dp->d_name); stat(path1, &attr); struct tm* ts = localtime(&attr.st_mtime); if (attr.st_mtime > starttime1 && attr.st_mtime <= endtime1) { printf(ANSI_COLOR_BLUE); if (iprint == 1) printf(" "); if (iprint == 1) printDateraw1(mktime(ts)); if (iprint == 1) printf(" --> %s/%s", basePath, dp->d_name); if (iprint == 1) printf("\n"); printf(ANSI_COLOR_RESET); for (i = 0; i < root; i++) { /*if (i%2 == 0 || i == 0) printf("│"); else printf(" ");*/ } //printf("├─%s\n", dp->d_name); n++; } strcpy(path, basePath); strcat(path, "/"); strcat(path, dp->d_name); mtime_cmd(path, root + 2, starttime1, endtime1, iprint); } } closedir(dir); } int main() { int i, j; int sizeCmd = 0; int measure = 0; char cmd[MAX_LINE / 2 + 1]; /* command line arguments */ int should_run = 1, towait = 1; /* flag to determine when to exit program */ char s[256]; int internalcmd = 0; /*******************/ char** history = NULL; int sz_history = 0; /*******************/ while (should_run) { internalcmd = 0; timedout = 0; measure = 0; printf(ANSI_COLOR_GREEN); printf("\nmsh> "); printf(ANSI_COLOR_RESET); int ret = scanf(" %[^\n]s", cmd); //CTRL+D if (ret == EOF) return 0; if (strcmp(cmd, "!!") == 0) { if (sz_history > 0) { strcpy(cmd, history[sz_history - 1]); //history[ sz_history-1] = NULL; printf(ANSI_COLOR_BLUE); printf("\n%s\n", cmd); printf(ANSI_COLOR_RESET); } else { printf("\nNo commands in history.\n"); internalcmd = 1; } }else if(cmd[0]=='!') { cmd[0]='0'; int n=atoi(cmd); if (sz_history >= n) { strcpy(cmd, history[sz_history - n]); //history[ sz_history-1] = NULL; printf(ANSI_COLOR_BLUE); printf("\n%s\n", cmd); printf(ANSI_COLOR_RESET); } else { printf("\nNo commands in history.\n"); internalcmd = 1; } } else { sz_history = sz_history + 1; history = (char**)realloc(history, sizeof(char*) * (sz_history + 1)); char* str = (char*)malloc(strlen(cmd) + 1); strcpy(str, cmd); history[sz_history - 1] = str; history[sz_history] = 0; } redo: killall=0; internalcmd = 0; char** res = splitstring(cmd, &sizeCmd); if (strcmp(res[0], "exit") == 0 || strcmp(res[0], "quit") == 0) { should_run = 0; internalcmd = 1; } printf(ANSI_COLOR_BLUE); if (strcmp(res[0], "pwd") == 0) { printf("%s\n", getcwd(s, 100)); internalcmd = 1; } printf(ANSI_COLOR_RESET); if (strcmp(res[0], "cd") == 0) { if (sizeCmd > 1 && strlen(res[1]) > 0) chdir(res[1]); internalcmd = 1; } towait = 1; if (sizeCmd > 0 && strlen(res[sizeCmd - 1]) > 0) { char c = res[sizeCmd - 1][strlen(res[sizeCmd - 1]) - 1]; if (c == '&') { towait = 0; res[sizeCmd - 1][strlen(res[sizeCmd - 1]) - 1] = 0; } } if (strlen(res[sizeCmd - 1]) == 0) res[sizeCmd - 1] = 0; printf(ANSI_COLOR_RESET); if (internalcmd == 0) { struct tms times_start, times_end; clock_t times_start_retval, times_end_retval; if ((times_start_retval = times(×_start)) == -1) { perror("starting times"); return -1; } struct timeval start, end; gettimeofday(&start, NULL); clock_t t; t = clock(); /************************/ if (timedout == 1) { char path1[1000] = ""; for (j = 2; j < sizeCmd; j++) { strcat(path1, res[j]); strcat(path1, " "); } executeWithPipes(path1); } else if (measure == 1) { char path1[1000] = ""; for (j = 1; j < sizeCmd; j++) { strcat(path1, res[j]); strcat(path1, " "); } executeWithPipes(path1); } else executeWithPipes(cmd); /************************/ t = clock() - t; gettimeofday(&end, NULL); double time_taken = (1000 * (double)t) / CLOCKS_PER_SEC; long seconds = (end.tv_sec - start.tv_sec); long micros = ((seconds * 1000000) + end.tv_usec) - (start.tv_usec); if ((times_end_retval = times(×_end)) == -1) { perror("ending timer"); return -1; } if (measure == 1) { printf("\nCPU Time elpased is %f milliseconds \n", time_taken); printf("Wall Time elpased is %f milliseconds ", (double)micros / 1000); printf("\nSystem Time elpased is %f milliseconds ", (double)times_end.tms_cstime - times_start.tms_cstime / CLOCKS_PER_SEC); } } free(res); fflush(stdout); } return 0; }

Related Samples

Explore our free operating system assignment samples showcasing comprehensive solutions and insights into various OS concepts. Ideal for understanding practical implementations and enhancing your learning experience.