In: Computer Science
Building a Command Line Interpreter (myshell)
1.Goal of this programming assignment
The primary goal of this assignment is to understand and gain some familiarity with
the system call interface in Unix Environment. In this assignment you will be
implementing your own command line interpreter like a Unix shell program.
YOU ARE NOT IMPLEMENTING COMMANDS!
YOUR program should just
FORK off programs and EXECUTE them.
2.
Requirements
(1)
Programming language: You have to use either C or C++ to develop your program.
(2)
Running Environment: Your program should be compiled at
CSEGRIDand be able tobe tested without errors.
3.
The implementation details
(1)
Backgrounds: The command line interpreter, called a shell, is an application program
that gets commands from a keyboard and uses the system call interfaces to invoke OS
functions.
(2)
Your shell should support followings:
(a)
Support exit or stop
your shell command
a)
Example(s): exit
(b)
Support commands with no arguments
.
a)
Examples: “ls”, “pwd”, “whoami” and “hostname”
(c)
Support commands with arguments:
a)
Examples: “ls –l”, “ls –fx”, “ps –aux” ,“date –u”, “cd directory”, etc.
(d)
A command, with or without arguments, whose output is redirected to a file
a)
Examples: ls > foo, ls -Fx > foob
(e)
A command, with or without arguments, whose input is redirected from a file
a)
Examples: sort < testfile
(f)
Supporting a sequence of programs that communicate through a pipe.
a)
Examples: ls | wc
(g)
Display error messages if the typed command has errors or can’t be found
2
4.
Hint
Your shell should isolate itself from program failures by creating a child process to
execute each command specified by the user. For example, the “tar cvf cli5678 program1”
command is executed by a child of the process executing the shell, myshell.
% tar cvf cli5678 program1
You might consider the following functions to build myshell:
(1)
Printing a prompt – when myshell is begun, it display its own string as its own prompt.
For example, “myshell> ”.
(2)
Getting command line –
To get a command line, the shell performs a blocking read
operation so that the process that executes the shell will be blocked until the user types
a command line in response to the prompt. When the user enters the command, the
comm
and line string should be returned to the myshell.
(3)
Parsing the command: Take the user command and divide it into command and
arguments as well as checking errors.
(4)
Finding the file – The shell provides a set of “environment variables” for each user
such as “PATH”. The PATH environment variable is an ordered list of absolute
pathnames that specifies where the shell should search for command files.
(5)
Create a child process and launch the command –
Once the command and arguments
are prepared, create a child process to execute the command with its arguments and
wait until the command is completed.
Someone help to solve this Operating Systems problem?
PROGRAM:
CODE:
int main(int argc, char **argv)
{
lsh_loop();
return EXIT_SUCCESS;
}
void lsh_loop(void)
{
char *lines;
char **args;
int status;
do {
printf("> ");
lines = lsh_read_lines();
args = lsh_split_lines(lines);
status = lsh_execute(args);
free(lines);
free(args);
} while (status);
}
#define LSH_RL_BUFF_SIZE 1024
char *lsh_read_lines(void)
{
int Buff_Size = LSH_RL_BUFF_SIZE;
int pos = 0;
char *buff = malloc(sizeof(char) * Buff_Size);
int c;
if (!buff) {
fprintf(stderr, "lsh: allocation error\n");
exit(EXIT_FAILURE);
}
while (1) {
c = getchar();
if (c == EOF || c == '\n') {
buff[pos] = '\0';
return buff;
} else {
buff[pos] = c;
}
pos++;
if (pos >= Buff_Size) {
Buff_Size += LSH_RL_BUFF_SIZE;
buff = realloc(buff, Buff_Size);
if (!buff) {
fprintf(stderr, "lsh: allocation error\n");
exit(EXIT_FAILURE);
}
}
}
}
char *read_lines_lsh(void)
{
char *lines = NULL;
ssize_t Buff_Size = 0;
getlines(&lines, &Buff_Size, stdin);
return lines;
}
#define BUFF_SIZE_TOKEN_LSH 64
#define DELIM_TOKEN_LSH " \t\r\n\a"
char **lsh_split_lines(char *lines)
{
int Buff_Size = BUFF_SIZE_TOKEN_LSH, pos = 0;
char **tokens = malloc(Buff_Size * sizeof(char*));
char *token;
if (!tokens) {
fprintf(stderr, "lsh: allocation error\n");
exit(EXIT_FAILURE);
}
token = strtok(lines, DELIM_TOKEN_LSH);
while (token != NULL) {
tokens[pos] = token;
pos++;
if (pos >= Buff_Size) {
Buff_Size += BUFF_SIZE_TOKEN_LSH;
tokens = realloc(tokens, Buff_Size * sizeof(char*));
if (!tokens) {
fprintf(stderr, "lsh: allocation error\n");
exit(EXIT_FAILURE);
}
}
token = strtok(NULL, DELIM_TOKEN_LSH);
}
tokens[pos] = NULL;
return tokens;
}
int launch_LSH(char **args)
{
pid_t pid, wpid;
int status;
pid = fork();
if (pid == 0) {
if (execvp(args[0], args) == -1) {
perror("lsh");
}
exit(EXIT_FAILURE);
} else if (pid < 0) {
perror("lsh");
} else {
do {
wpid = waitpid(pid, &status, WUNTRACED);
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
return 1;
}
int lsh_cd(char **args);
int lsh_help(char **args);
int lsh_exit(char **args);
char *bullitin_str[] = {
"cd",
"help",
"exit"
};
int (*builtin_func[]) (char **) = {
&lsh_cd,
&lsh_help,
&lsh_exit
};
int lsh_num_builtins() {
return sizeof(bullitin_str) / sizeof(char *);
}
int lsh_cd(char **args)
{
if (args[1] == NULL) {
fprintf(stderr, "lsh: expected argument to \"cd\"\n");
} else {
if (chdir(args[1]) != 0) {
perror("lsh");
}
}
return 1;
}
int lsh_help(char **args)
{
int i;
printf("Stephen Brennan's LSH\n");
printf("Type program names and arguments, and hit enter.\n");
printf("The following are built in:\n");
for (i = 0; i < lsh_num_builtins(); i++) {
printf(" %s\n", bullitin_str[i]);
}
printf("Use the man command for information on other
programs.\n");
return 1;
}
int lsh_exit(char **args)
{
return 0;
}
int lsh_execute(char **args)
{
int i;
if (args[0] == NULL) {
return 1;
}
for (i = 0; i < lsh_num_builtins(); i++) {
if (strcmp(args[0], bullitin_str[i]) == 0) {
return (*builtin_func[i])(args);
}
}
return launch_LSH(args);
}
#include <sys/wait.h>
waitpid() and associated macros
#include <unistd.h>
chdir()
fork()
exec()
pid_t
#include <stdlib.h>
malloc()
realloc()
free()
exit()
execvp()
EXIT_SUCCESS, EXIT_FAILURE
#include <stdio.h>
fprintf()
printf()
stderr
getchar()
perror()
#include <string.h>
strcmp()
strtok()