Overview
Writing in the C language, implement a very basic shell, called smash. In this project, we will work on processing strings and using the appropriate system calls.
Build System setup
Before we can start writing code we need to get our build system all setup. This will involve writing a very simple makefile. You should leverage your Makefile project for this part of the assignment!
Write a Makefile that provides the three targets listed below
all - The default rule. Builds your project.
smash - Builds your smash shell. Initially only one file smash.c
Make sure to use macros!
clean - Cleans your build directory and deletes any generated files.
Implement basic string processing
Start your program by reading from standard in and splitting the input string on spaces. To test your program echo the result to standard out.
We will leverage the strtok standard library call for this part of the assignment. Below is a basic example (modified from cplusplus.com):
1: char line[] ="ls -l -a";
2: char* token = strtok(line," ");
3: int i=0;
4: while (token != NULL){
5: printf ("%d %s\n",i++,token);
6: token = strtok (NULL, " ");
7: }
0 ls 1 -l 2 -a
We will also leverage the fgets standard library call to read input from standard-in.
1: #define MAXLINE 4096
2:
3: char buff[MAXLINE];
4: while (fgets(buff, MAXLINE, stdin) != NULL) {
5: buff[strlen(buff) - 1] = '\0'; /* replace newline with null */
6: }
7: printf("%s\n",buff);
Smash built-in commands
Once you have your program reading from standard in you will add in a few basic commands and call your first system call! A shell will typically farm out 99% of the work to other programs. There are some things such as cd and exit that are built into the shell. We will be implementing a few built in commands before we start to fork/exec.
The Exit command
Your shell should exit when the user types in exit. You will need to use strcmp to compare the string literal "exit" with the user input.
The cd command
When a user types cd some/directory you will need to use the Linux system call chdir to change the directory of the current process (your smash process) to the given directory. If the user inputs an invalid directory, you need to output the string error: some/directory does not exist. Your shell will replace some/directory with the string the user input.
In order to determine if the chdir() command worked you will need to use the getcwd system call to get the current working directory after the cddir() command. Print the result to ensure that your directory did change. NOTE: Read the documentation for getcwd very carefully! You do NOT need to use malloc for this part of the project we are going to leverage a GNU extension to the POSIX.1-2001 standard that allows us to avoid malloc.
Your should print an error under the following conditions:
chdir() returned non-zero
getcwd() returned an unknown result
If the user enters any other command your shell should print the tokens in the format specified below. The $ is your smash prompt and will be hard coded for this part of the assignment. NOTE: Make sure and print the $ to stderr NOT stdout (use fprintf for this).
Example output
bash_shell>./smash $exit bash_shell>./smash $ls -l -a [0] ls [1] -l [2] -a $cd /home /home $cd /asdfasdf error: /asdfasdf does not exist $exit bash_shell>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <ctype.h>
//This method looks up the input command against the lookup
for
//validity purposes
bool FunctionLookUp(char *argv, char *Lookup[])
{
bool match = false;
for(int i = 0; i < 10; i++){
if(*Lookup[i] == *argv){
match =
true;
break;}
}
return match;
}
void parse(char *line, char **argv)
{
while (*line != '\0')
{ /* if not the end of line
....... */
while (*line
== ' ' || *line == '\t' || *line == '\n')
*line++ = '\0'; /* replace white spaces
with 0 */
*argv++ =
line; /* save
the argument position */
while (*line
!= '\0' && *line != ' ' &&
*line != '\t' && *line != '\n')
line++;
/* skip the argument until ... */
}
*argv =
'\0';
/* mark the end of argument list */
}
bool CheckForwardSlash(char temp[], int size)
{
bool present = false
for(int i = 0; i < size;
i++){
if(temp[i]
== '/'){
present = true;
break;
}
}
return present;
}
void execute(char **argv)
{
pid_t pid;
int status;
if ((pid = fork()) < 0)
{ /* fork a child
process
*/
printf("***
ERROR: forking child process failed\n");
exit(1);
}
else if (pid == 0)
{ /* for the
child process:
*/
if
(execvp(*argv, argv) < 0) { /* execute
the command */
printf("*** ERROR: exec failed\n");
exit(1);
}
}
else
{
/* for the parent: */
while
(wait(&status) != pid) /*
wait for completion */
;
}
}
void main(void)
{
char
line[1024];
// The input
line
char
*argv[3];
// An array of pointers to the tokens (the tokens were parsed
// from
the input line)
bool check1, check2 = false;
//A look-up table that contains some of the valid
commands
char *LookUp[11] = {"emacs", "kill", "bye", "jobs",
"fg", "chmod", "cd", "help", "cat", "cp"};
while (1)
{
// repeating....
printf("tish
>>
");
// the
prompt
gets(line);
// read in the command line
printf("\n");
parse(line,
argv);
// parse the line
if
(strcmp(argv[0], "bye") == 0) // exit if the user
enters bye
{exit(0);}
//Input
Validation//
///////////////////
//If the
input is just a white space character, continue with the next
iteration of the loop
if
(isspace(argv[0]))
continue; //If it is some sort of a white-space
character,
//skip the
current iteration of the while loop
//Call a
function that checks for the validity of the input command
check2 =
FunctionLookUp(argv, LookUp);
if(check2 ==
false){
fprintf("Invalid Command\n");
continue;
}
//Test
argv[0] for invalid internal commands. Check for Letters and
Negative numbers.
if(strcmp(argv[0], "kill") == 0){
if(isaplha(argv[1]) || atoi(argv[1]) < 0){
fprintf("Invald PID entered");
fprintf("Enter a positive numeric number");
continue;
}
}
int size =
sizeof(argv[1]) + 1;
char
temp[size];
strcpy(temp,agrv[1]);
check1 =
CheckForwardSlash(temp, size);
//If true is returned by the
CheckForwardSlash method, skip the rest of the while loop
if(check1 ==
true){
printf("Invalid
file format\n");
printf("Avoid
Forward Slashes in your file name\n");
continue;
}
//Input
Validation Ends//
///////////////*********************//////////////////
//Signals to catch the Ctrl-C
and Ctrl/ combination
signal(SIGINT,
SIG_IGN);
//The instructions
said to ignore the SIGINT signal
signal(SIGTERM,
SIG_DFL);
//SIGTERM signal must be caught.
execute(argv);
//Finally, execute the command
}
}
c program for shell
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef _WIN32
#include <windows.h>
#define chdir _chdir
#else
#include <unistd.h>
#endif
#define MAX_LENGTH 1024
#define DELIMS " \t\r\n"
int main(int argc, char *argv[]) {
char *cmd;
char line[MAX_LENGTH];
while (1) {
printf("$ ");
if (!fgets(line, MAX_LENGTH, stdin)) break;
// Parse and execute command
if ((cmd = strtok(line, DELIMS))) {
// Clear errors
errno = 0;
if (strcmp(cmd, "cd") == 0)
{
char *arg = strtok(0,
DELIMS);
if (!arg)
fprintf(stderr, "cd missing argument.\n");
else chdir(arg);
} else if (strcmp(cmd, "exit") ==
0) {
break;
} else system(line);
if (errno) perror("Command
failed");
}
}
return 0;
}
Overview Writing in the C language, implement a very basic shell, called smash. In this project,...
Project 1: Implementing a Shell 1 Overview In this individual project you will have to design and implement a simple shell command interpreter called mysh. The basic function of a shell is to accept lines of text as input and execute programs in response. The shell must be able to execute built-in commands in a process different from the one executing mysh. 2 Requirements When first started, your shell should initialize any necessary data structures and then enter a loop...
You
are required to develop a simple Linux shell in C language
“shell.c".
The shell has to perform the following requirements: - - The
shell prompt is “"myshell>".
- Run commands either from current directory or from “/bin"
directory using the "exec" system call.
- Support output redirection like "command> filename" using
"dup" system call. Note: save the output of the comment in the
(filename).
- Implement the “history shell command to list the last ten
commands entered so far....
Creating a Shell Interface Using Java This project consists of modifying a Java program so that it serves as a shell interface that accepts user commands and then executes each command in a separate process external to the Java virtual machine. Overview A shell interface provides the user with a prompt, after which the user enters the next command. The example below illustrates the prompt jsh> and the user’s next command: cat Prog.java. This command displays the file Prog.java on...
For part one of this assignment, write a program (parse.c) that contains a function to parse a single line of input and and prints out the individual tokens. Part 1 - Single Line Parser For part one of this assignment, you will need to learn how to do some parsing (or more accurately--lexing a line, you do not have to check for correctness). You have previously done some parsing with the cycle count tool perhaps using functions such as strcmp....
This project consists of designing a C program to serve as a shell interface that accepts user commands and then executes each command in a separate process. A shell interface gives the user a prompt, after which the next command is entered. The example below illustrates the prompt cse222> and the user’s next command: cat prog.c. cse222> cat prog.c One technique for implementing a shell interface is to have the parent process first read what the user enters on the...
Update the program in the bottom using C++ to fit the requirements specified in the assignment. Description For this assignment, you will be writing a single program that enters a loop in which each iteration prompts the user for two, single-line inputs. If the text of either one of the inputs is “quit”, the program should immediately exit. If “quit” is not found, each of these lines of input will be treated as a command line to be executed. These...
Edit the code (shell.c) given to do the tasks asked! will rate
for correct answer! Also, include a screen shot of the output and
terminal window of each command you used. Read carefully to do this
task please.
shell.c code given below.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
int main()
{
int PID;
char lineGot[256];
char *cmd;
while (1){
printf("cmd: ");
fgets(lineGot, 256, stdin); // Get a string from user (includes \n)
cmd = strtok(lineGot, "\n");...
In this hands-on project, you compile and install a program from source code. On your Fedora Linux virtual machine, switch to a graphical terminal (tty1) by pressingCtrl+Alt+F1 and log in to the GNOME desktop using the user name of user1 and the password of LNXrocks!. Open the Firefox Web browser and download the source code tarball for rdesktop 1.8.2 (rdesktop-1.8.2.tar.gz) from www.rdesktop.org. Save the source code tarball to the default location (/home/user1/Downloads) and log out of the GNOME desktop when...
Objective : Write a C Shell script which copies all files(*.java and *.class) from your home directory to a new one, and Analyze the new directory information such as number of files, user permissions, and disk usage. Sample Output: << CS Directory Analysis >> Date: ============================================================ Current Directory: /home/tomss New Directory Created : /home/tomss/pgm01 File information Total Number of files : 22 files Directory files: 0 files Plain text files: 10 files File have read permissions: 3 files File have...
One can incidentally terminate sushi by pressing Ctrl+C (Ctrl+Break, Command+dot) or a similar combination of keys that sends SIGNIT to the shell. Function prevent_interruption() sets up a signal handler that intercepts SIGINT and displays message “Type exit to exit the shell” on stderr. The name of the handler is refuse_to_die(), its skeleton and the skeleton of prevent_interruption() are provided in sushi.c. Hint: use system call sigaction() to set up the handler. As a result, when you attempt to interrupt the...