FinalProject 1
FinalProject 1
OPERATING SYSTEM
Final Project – Homework
~~~*~~~
PROBLEM 1
Implement Section 3: Creating a History Feature
Solution:
For this solution we need to create an array to store the user’s command and when the
user types input as “!!” the command will be executed again.
We must declare the history variable and create a function to add the user commands
to the above array. For details, the user inputs the commands as a string value, so we
need to use the strcpy function to pass the command value to the array history. To
know the situation in this array we also need to write the function to give the signal if
the array did not have any value on itself.
Code:
//---------------------------------
// Author: Đặng Thành Đạt
// Student ID: 21521928
//---------------------------------
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
char history[HISTORY_SIZE][MAXLINE];
while (should_run) {
printf("21521928>");
fflush(stdout);
if (strcmp(args, "exit") == 0) {
should_run = 0;
} else if (strcmp(args, "!!") == 0) {
if (history[0][0] == '\0') {
printf("No commands in history.\n");
} else {
printf("%s\n", history[0]);
addToHistory(history[0]);
pid_t pid = fork();
if (pid == 0) {
char *token;
char *tokens[MAXLINE / 2 + 1];
int i = 0;
execvp(tokens[0], tokens);
fprintf(stderr, "Exec failed\n");
return 1;
}
if (pid > 0) {
wait(NULL);
}
}
} else {
addToHistory(args);
pid_t pid = fork();
if (pid == 0) {
char *token;
char *tokens[MAXLINE / 2 + 1];
int i = 0;
token = strtok(args, " ");
while (token != NULL) {
tokens[i++] = token;
token = strtok(NULL, " ");
}
tokens[i] = NULL;
execvp(tokens[0], tokens);
fprintf(stderr, "Exec failed\n");
return 1;
}
if (pid > 0) {
wait(NULL);
}
}
}
return 0;
}
Explanation:
Step 1: Declaring the array variable and creating the function to add a new
command:
Explain:
I declare that variable – char variables and a function that takes responsibility for
adding new commands to the commands history in the array. It will replace the
commands' position by one unit to make a free space for the new command and then
copy the new command to the first row of the array, then, the array with the most
recent command will be updated.
Step 2: Handling when the user types input as the “!!” symbol.
Explain:
When the type inputs as “!!” symbol, if the array is empty It will be displayed as
“There is no command in history”. Unless the array is empty it will execute the latest
command in the array by the “axecvp” function.
Testing:
Explain:
At the results when I input “!!”, the screen displays “There is no command in history”,
which means there are not any commands to execute.
When I type “echo ThanhDat” the program will execute the command and store the
command in the array.
When an invalid command is input into a shell, it is not executed but is retained in the
command history. Subsequently, if the user enters '!!,' the shell will execute the last
command from the history, including any previously entered invalid commands."
When I type “ls” It is going to do the same thing with “echo ThanhDat”.
Video demo: https://drive.google.com/drive/u/0/folders/1IFthYyl-
3cM3ZMztCnkP1Ht3INopIlSu
PROBLEM 2
Implement Section 4: Redirecting Input and Output
char history[HISTORY_SIZE][MAXLINE];
int main(void) {
char args[MAXLINE / 2 + 1];
int should_run = 1;
while (should_run) {
printf("21521928>");
fflush(stdout);
if (strcmp(args, "exit") == 0) {
should_run = 0;
} else if (strcmp(args, "!!") == 0) {
if (history[0][0] == '\0') {
printf("No commands in history.\n");
} else {
printf("%s\n", history[0]);
addToHistory(history[0]);
char *token;
char *tokens[MAXLINE / 2 + 1];
int i = 0;
if (redirectOutput) {
int fd = open(tokens[i - 1], O_WRONLY | O_CREAT | O_TRUNC,
0644);
if (fd == -1) {
perror("open");
return 1;
}
dup2(fd, STDOUT_FILENO);
close(fd);
}
execvp(tokens[0], tokens);
fprintf(stderr, "Exec failed\n");
return 1;
}
if (pid > 0) {
wait(NULL);
}
}
} else {
addToHistory(args);
char *token;
char *tokens[MAXLINE / 2 + 1];
int i = 0;
token = strtok(args, " ");
while (token != NULL) {
tokens[i++] = token;
token = strtok(NULL, " ");
}
tokens[i] = NULL;
int redirectInput = 0;
int redirectOutput = 0;
for (int j = 0; tokens[j] != NULL; ++j) {
if (strcmp(tokens[j], ">") == 0) {
redirectOutput = 1;
tokens[j] = NULL;
break;
} else if (strcmp(tokens[j], "<") == 0) {
redirectInput = 1;
tokens[j] = NULL;
break;
}
}
pid_t pid = fork();
if (pid == 0) {
if (redirectInput) {
int fd = open(tokens[i - 1], O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
dup2(fd, STDIN_FILENO);
close(fd);
}
if (redirectOutput) {
int fd = open(tokens[i - 1], O_WRONLY | O_CREAT | O_TRUNC,
0644);
if (fd == -1) {
perror("open");
return 1;
}
dup2(fd, STDOUT_FILENO);
close(fd);
}
execvp(tokens[0], tokens);
fprintf(stderr, "Exec failed\n");
return 1;
}
if (pid > 0) {
wait(NULL);
}
}
}
return 0;
}
Explanation:
Two flags, redirect_input and redirect_output, serve to signal the necessity of input or
output redirection.
Input file
Explain:
When entering the command "ls > out.txt," it creates a file named "out.txt" and stores
the output of the "ls" command in this file. Similarly, if an "in.txt" file is created with
text content and the command "cat < in.txt" is used, it prints the text values from the
"in.txt" file. When a list of integers is placed in "in.txt," and the command "sort <
in.txt" is executed, the values in the file are sorted, and the sorted list of integers is
printed. Using the command "!!" subsequently prints the last entered command along
with its output.
However, if a non-command such as "wertyufgh" is entered, the system responds with
"Exec failed," signaling that the input is not a valid command. This message indicates
that the attempted execution of the given input failed, typically because the command
is not recognized or executable.
In summary, the described commands showcase the functionality of input and output
redirection, command repetition with "!!," and the indication of execution failure for
invalid commands.
Video demo: https://drive.google.com/drive/u/0/folders/1IFthYyl-
3cM3ZMztCnkP1Ht3INopIlSu
./END