Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

You may have noticed that 3000shell does not support the internal command cd. Implement a simplified version of cd. - The current directory should be

You may have noticed that 3000shell does not support the internal command cd. Implement a simplified version of cd. - The current directory should be changed to what follows cd, e.g., cd / enters the root directory, cd .. goes back to the parent directory, and cd /var/log enters /var/log. - Verify your implementation using the command ls to list files in the current directory. - cd with no argument should enter the home directory of the user. - To get full marks, your prompt must reflect the current directory changed by cd. For example: student@compxxxx:/var$ cd student@compxxxx:/home/student$ cd / student@compxxxx:/$ - Note: simplified is in the sense that our cd does not support everything a regular cd does, e.g., you are not required to support options like -L, or shorthand like - (previous directory) and ~. Hint: you may need two functions setenv() and chdir() (and other functions depending on your way of implementing it).

shell.c

#include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #define BUFFER_SIZE 1<<16 #define ARR_SIZE 1<<16 #define COMM_SIZE 32 const char *proc_prefix = "/proc"; void parse_args(char *buffer, char** args, size_t args_size, size_t *nargs) { char *buf_args[args_size]; /* You need C99 */ char **cp, *wbuf; size_t i, j; wbuf=buffer; buf_args[0]=buffer; args[0] =buffer; for(cp=buf_args; (*cp=strsep(&wbuf, " \t")) != NULL ;){ if ((*cp != NULL) && (++cp >= &buf_args[args_size])) break; } for (j=i=0; buf_args[i]!=NULL; i++){ if (strlen(buf_args[i]) > 0) args[j++]=buf_args[i]; } *nargs=j; args[j]=NULL; } /* this is kind of like getenv() */ char *find_env(char *envvar, char *notfound, char *envp[]) { const int MAXPATTERN = 128; int i, p; char c; char pattern[MAXPATTERN]; char *value = NULL; p = 0; while ((c = envvar[p])) { pattern[p] = c; p++; if (p == (MAXPATTERN - 2)) { break; } } pattern[p] = '='; p++; pattern[p] = '\0'; i = 0; while (envp[i] != NULL) { if (strncmp(pattern, envp[i], p) == 0) { value = envp[i] + p; } i++; } if (value == NULL) { return notfound; } else { return value; } } void find_binary(char *name, char *path, char *fn, int fn_size) { char *n, *p; int r, stat_return; struct stat file_status; if (name[0] == '.' || name[0] == '/') { strncpy(fn, name, fn_size); return; } p = path; while (*p != '\0') { r = 0; while (*p != '\0' && *p != ':' && r < fn_size - 1) { fn[r] = *p; r++; p++; } fn[r] = '/'; r++; n = name; while (*n != '\0' && r < fn_size) { fn[r] = *n; n++; r++; } fn[r] = '\0'; stat_return = stat(fn, &file_status); if (stat_return == 0) { return; } if (*p != '\0') { p++; } } } void setup_comm_fn(char *pidstr, char *comm_fn) { char *c; strcpy(comm_fn, proc_prefix); c = comm_fn + strlen(comm_fn); *c = '/'; c++; strcpy(c, pidstr); c = c + strlen(pidstr); strcpy(c, "/comm"); } void plist() { DIR *proc; struct dirent *e; int result; char comm[COMM_SIZE]; /* seems to just need 16 */ char comm_fn[512]; int fd, i, n; proc = opendir(proc_prefix); if (proc == NULL) { fprintf(stderr, "ERROR: Couldn't open /proc. "); } for (e = readdir(proc); e != NULL; e = readdir(proc)) { if (isdigit(e->d_name[0])) { setup_comm_fn(e->d_name, comm_fn); fd = open(comm_fn, O_RDONLY); if (fd > -1) { n = read(fd, comm, COMM_SIZE); close(fd); for (i=0; i < n; i++) { if (comm[i] == ' ') { comm[i] = '\0'; break; } } printf("%s: %s ", e->d_name, comm); } else { printf("%s ", e->d_name); } } } result = closedir(proc); if (result) { fprintf(stderr, "ERROR: Couldn't close /proc. "); } } void signal_handler(int the_signal) { int pid, status; if (the_signal == SIGHUP) { fprintf(stderr, "Received SIGHUP. "); return; } if (the_signal != SIGCHLD) { fprintf(stderr, "Child handler called for signal %d?! ", the_signal); return; } pid = wait(&status); if (pid == -1) { /* nothing to wait for */ return; } if (WIFEXITED(status)) { fprintf(stderr, " Process %d exited with status %d. ", pid, WEXITSTATUS(status)); } else { fprintf(stderr, " Process %d aborted. ", pid); } } void run_program(char *args[], int background, char *stdout_fn, char *path, char *envp[]) { pid_t pid; int fd, *ret_status = NULL; char bin_fn[BUFFER_SIZE]; pid = fork(); if (pid) { if (background) { fprintf(stderr, "Process %d running in the background. ", pid); } else { pid = wait(ret_status); } } else { find_binary(args[0], path, bin_fn, BUFFER_SIZE); if (stdout_fn != NULL) { fd = creat(stdout_fn, 0666); dup2(fd, 1); close(fd); } if (execve(bin_fn, args, envp)) { puts(strerror(errno)); exit(127); } } } void prompt_loop(char *username, char *path, char *envp[]) { char buffer[BUFFER_SIZE]; char *args[ARR_SIZE]; int background; size_t nargs; char *s; int i, j; char *stdout_fn; while(1){ printf("%s $ ", username); s = fgets(buffer, BUFFER_SIZE, stdin); if (s == NULL) { /* we reached EOF */ printf(" "); exit(0); } parse_args(buffer, args, ARR_SIZE, &nargs); if (nargs==0) continue; if (!strcmp(args[0], "exit")) { exit(0); } if (!strcmp(args[0], "plist")) { plist(); continue; } background = 0; if (strcmp(args[nargs-1], "&") == 0) { background = 1; nargs--; args[nargs] = NULL; } stdout_fn = NULL; for (i = 1; i < nargs; i++) { if (args[i][0] == '>') { stdout_fn = args[i]; stdout_fn++; printf("Set stdout to %s ", stdout_fn); for (j = i; j < nargs - 1; j++) { args[j] = args[j+1]; } nargs--; args[nargs] = NULL; break; } } run_program(args, background, stdout_fn, path, envp); } } int main(int argc, char *argv[], char *envp[]) { struct sigaction signal_handler_struct; char *username; char *default_username = "UNKNOWN"; char *path; char *default_path = "/usr/bin:/bin"; memset (&signal_handler_struct, 0, sizeof(signal_handler_struct)); signal_handler_struct.sa_handler = signal_handler; signal_handler_struct.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &signal_handler_struct, NULL)) { fprintf(stderr, "Couldn't register SIGCHLD handler. "); } if (sigaction(SIGHUP, &signal_handler_struct, NULL)) { fprintf(stderr, "Couldn't register SIGHUP handler. "); } username = find_env("USER", default_username, envp); path = find_env("PATH", default_path, envp); prompt_loop(username, path, envp); return 0; }

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image_2

Step: 3

blur-text-image_3

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Database Systems A Practical Approach To Design Implementation And Management

Authors: THOMAS CONNOLLY

6th Edition

9353438918, 978-9353438913

More Books

Students also viewed these Databases questions

Question

=+5. Review the six categories of 50 strategies.

Answered: 1 week ago

Question

4. Evaluation is ongoing and used to improve the system.

Answered: 1 week ago

Question

6. Effectively perform the managers role in career management.

Answered: 1 week ago