Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Practice UNIX system calls by writing a custom shell interpreter in C/C++. Quest

ID: 3604831 • Letter: P

Question

Practice UNIX system calls by writing a custom shell interpreter in C/C++.

Question 1) Implement a shell, and provide the source codes.

Your shell should prompt the user for a command. The command prompt must be "AB>" where A is the first letter of your first name and B is the first letter of your last name.

The shell executes a command, if it is an external command, by fork(2)-ing the main process and having the child execute the command using a function of
the exec(3) family. The parent should use a function of the wait(2) family to wait for the completion of the child process before continuing.

If the command is a built-in, the shell execute it without using fork(2) and exec(3).

The shell must be able to handle internal commands cd, help, exit and an additional built-in command of your choice.

If the user enters the command exit, the main process should not call fork(2) and instead just exit the program successfully.

Question 2) Add an ability to handle the history internal command, and provide the source codes.

The history command will print the list of the commands executed by user or message indicating the history is empty. Practice the command for better understanding before designing a solution.

The shell needs to keep every command in a data structure in the same order of execution. For this purpose, you may want to implement a simple singly linked list.

!!: This command will execute the last command the user executed. This command should not be added to the history list.

!n: This command tells the shell to execute the n-th command in the history. If no such command exists it should display an error. This command should not be added to the history list. You may find the function atoi(3) helpful in parsing this command.

Explanation / Answer

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <dirent.h>

#define MAX_CMD_LEN 128

#define HISTORY_COUNT 10

int user_history(char *hist[], int current)

{

int i = current;

int hist_num = 1;

do {

if (hist[i])

{

printf("%4d %s ", hist_num, hist[i]);

hist_num++;

}

i = (i + 1) % HISTORY_COUNT;

} while (i != current);

return 0;

}

int clear_user_history(char *hist[])

{

int i;

for (i = 0; i < HISTORY_COUNT; i++)

{

free(hist[i]);

hist[i] = NULL;

}

return 0;

}

int cd(char *pth)

{

char path[MAX_CMD_LEN];

strcpy(path,pth);

char cwd[MAX_CMD_LEN];

getcwd(cwd,sizeof(cwd));

strcat(cwd,"/");

strcat(cwd,path);

printf("cd location before chdir is : %s ", path);

int ret = chdir(path);  

if(ret!=0)

printf("Error: Could not change to the directory ");

else

system("pwd");

return 0;

}

int hasPrefix(char const *p, char const *q)

{

int i = 0;

for(i = 0;q[i];i++)

{

if(p[i] != q[i])

return -1;

}

return 0;

}

void run_ls_command()

{

char *curr_dir = NULL;

DIR *dp = NULL;

struct dirent *dptr = NULL;

unsigned int count = 0;

  

curr_dir = getenv("PWD");

if(NULL == curr_dir)

{

printf(" ERROR : Could not get the working directory ");

return;

}

  

dp = opendir((const char*)curr_dir);

if(NULL == dp)

{

printf(" ERROR : Could not open the working directory ");

}

  

printf(" ");

for(count = 0; NULL != (dptr = readdir(dp)); count++)

{

// Check if the name of the file/folder begins with '.'

// If yes, then do not display it.

if(dptr->d_name[0] != '.')

printf("%s ",dptr->d_name);

}

printf(" ");

}

int main()

{

char cmd[MAX_CMD_LEN];

char *hist[HISTORY_COUNT];

char buf[1000];

int i, current = 0;

for (i = 0; i < HISTORY_COUNT; i++)

hist[i] = NULL;

char *tok;

tok = strtok (cmd," ");

  

while (1)

{

bzero(cmd, MAX_CMD_LEN);

printf("user@shell> ");

fgets(cmd, MAX_CMD_LEN, stdin);

  

if (cmd[strlen(cmd) - 1] == ' ')

{

cmd[strlen(cmd) - 1] = '';

}

if(hasPrefix(cmd,"cd") == 0)

{

tok = strchr(cmd,' ');

if(tok)

{

char *tempTok = tok + 1;

tok = tempTok;

char *locationOfNewLine = strchr(tok, ' ');

if(locationOfNewLine)

{

*locationOfNewLine = '';

}

printf("cd location is : %s ", tok);

cd(tok);

}

else

{

system("pwd");

}

  

}

free(hist[current]);

hist[current] = strdup(cmd);

current = (current + 1) % HISTORY_COUNT;

if (strcmp(cmd, "history") == 0)

user_history(hist, current);

else if (strcmp(cmd, "hc") == 0)

clear_user_history(hist);

else if (strcmp(cmd, "exit") == 0)

exit(0);

else if (strcmp(cmd,"pwd") == 0)

{

char *path = getcwd(buf, 100);

printf("%s ", path);

}

else if(strcmp(cmd,"ls") == 0)

run_ls_command();

}

clear_user_history(hist);

return 0;

}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote