Skip to content
Snippets Groups Projects
Commit 83d83d5a authored by yanjung2's avatar yanjung2
Browse files

initial commit

parents
No related branches found
No related tags found
No related merge requests found
Pipeline #180106 failed
shell.c 0 → 100644
/**
* Shell Lab
* CS 241 - Fall 2018
*/
#include "format.h"
#include "shell.h"
#include "vector.h"
#include "sstring.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <limits.h>
#include <getopt.h>
#include <sys/wait.h>
#include <signal.h>
typedef struct process {
char *command;
char *status;
pid_t pid;
} process;
static vector* processes;
void insert_history(vector* history, char* path_h) {
FILE* f = fopen(path_h, "r");
size_t size = 0;
if (!f) {
print_history_file_error();
return;
}
else {
char *buffer = NULL;
while (getline(&buffer, &size, f) != -1) {
int length = strlen(buffer);
if (buffer[length-1] == '\n') {
buffer[length-1] = '\0';
}
vector_push_back(history, buffer);
}
free(buffer);
}
fclose(f);
}
void write_history(vector* history, char* path_h) {
FILE* f = fopen(path_h, "w+");
for (size_t i = 0; i < vector_size(history); i++) {
fprintf(f, "%s\n", vector_get(history,i));;
}
fclose(f);
}
int handle_command(char* line, vector* history, vector* processes) {
sstring* sstr = cstr_to_sstring((const char*)line);
vector* vec = sstring_split(sstr, ' ');
int result = 0;
if (strcmp(vector_get(vec, 0), "cd") == 0) {
if (vector_size(vec) == 1) {
print_no_directory("");
}
else {
if (chdir(vector_get(vec, 1))==-1) {
print_no_directory(vector_get(vec, 1));
}
else {
result = 1;
}
}
}
else if (strcmp(vector_get(vec, 0), "!history") == 0) {
for (size_t i = 0; i < vector_size(history); i++) {
print_history_line(i, vector_get(history, i));
}
}
else if (((char*)vector_get(vec, 0))[0] == '!') {
if (vector_size(history) == 0) {
print_no_history_match();
}
else if (vector_size(vec) == 1 && strcmp(vector_get(vec, 0), "!") == 0) {
print_command(vector_get(history, vector_size(history)-1));
if(handle_command(vector_get(history, vector_size(history)-1), history, processes)) {
char* last = vector_get(history, vector_size(history)-1);
vector_push_back(history, last);
}
}
else {
int idx = -1;
for (size_t i = 0; i < vector_size(history); i++) {
char target[strlen(line)];
strncpy(target, vector_get(history, vector_size(history)-i-1), strlen(line)-1);
if (strcmp(target, line+1) == 0) {
idx = vector_size(history)-i-1;
break;
}
}
if (idx == -1) {
print_no_history_match();
}
else {
print_command(vector_get(history, idx));
if(handle_command(vector_get(history, idx), history, processes)) {
char* last = vector_get(history, idx);
vector_push_back(history, last);
}
}
}
}
else if (((char*)vector_get(vec, 0))[0] == '#') {
int idx = atoi(line+1);
if ((unsigned long)idx > vector_size(history)-1 || idx < 0) {
print_invalid_index();
}
else {
print_command(vector_get(history, idx));
if(handle_command(vector_get(history, idx), history, processes)) {
char* last = vector_get(history, idx);
vector_push_back(history, last);
}
}
}
else if (strcmp(vector_get(vec, 0), "ps") == 0) {
for (size_t i = 0; i < vector_size(processes); i++) {
process* p = vector_get(processes, i);
print_process_info(p->status, p->pid, p->command);
}
result = 1;
}
else if (strcmp(vector_get(vec, 0), "kill") == 0) {
if (vector_size(vec) != 2) {
print_invalid_command(line);
}
else {
pid_t found = 0;
process* p;
for (size_t i = 0; i < vector_size(processes); i++) {
p = vector_get(processes, i);
if (p->pid == atoi(vector_get(vec, 1))) {
found = p->pid;
kill(found, SIGTERM);
print_killed_process(p->pid, p->command);
result = 1;
break;
}
}
if (found == 0) {
print_no_process_found(atoi(vector_get(vec,1)));
}
}
}
else if (strcmp(vector_get(vec, 0), "stop") == 0) {
if (vector_size(vec) != 2) {
print_invalid_command(line);
}
else {
pid_t found = 0;
process* p;
for (size_t i = 0; i < vector_size(processes); i++) {
p = vector_get(processes, i);
if (p->pid == atoi(vector_get(vec, 1))) {
found = p->pid;
p->status = STATUS_STOPPED;
kill(found, SIGTSTP);
print_stopped_process(p->pid, p->command);
result = 1;
break;
}
}
if (found == 0) {
print_no_process_found(atoi(vector_get(vec,1)));
}
}
}
else if (strcmp(vector_get(vec, 0), "cont") == 0) {
if (vector_size(vec) != 2) {
print_invalid_command(line);
}
else {
pid_t found = 0;
process* p;
for (size_t i = 0; i < vector_size(processes); i++) {
p = vector_get(processes, i);
if (p->pid == atoi(vector_get(vec, 1))) {
found = p->pid;
p->status = STATUS_RUNNING;
kill(found, SIGCONT);
result = 1;
break;
}
}
if (found == 0) {
print_no_process_found(atoi(vector_get(vec,1)));
}
}
}
else if (line[strlen(line)-1] == '&') {
fflush(stdout);
char newline[strlen(line)];
strcpy(newline, line);
newline[strlen(newline)-1] = '\0';
sstring* new_sstr = cstr_to_sstring((const char*)newline);
vector* new_vec = sstring_split(new_sstr, ' ');
char** com = (char**)malloc(sizeof(char*)*(vector_size(new_vec)+1));
pid_t child = fork();
if (child == -1) {
print_fork_failed();
exit(1);
}
else if (child == 0) {
for (size_t i = 0; i < vector_size(new_vec); i++) {
com[i] = vector_get(new_vec, i);
}
print_command_executed(getpid());
execvp(com[0], com);
print_exec_failed(newline);
exit(1);
}
else {
if (setpgid(child, getpid()) == -1) {
print_setpgid_failed();
for (size_t i = 0; i < vector_size(processes); i++) {
process* p = vector_get(processes, i);
if (i>=1) {
int status;
waitpid(p->pid, &status, 0);
free(p->command);
}
free(p);
}
vector_destroy(new_vec);
sstring_destroy(new_sstr);
free(com);
sstring_destroy(sstr);
vector_destroy(vec);
vector_destroy(processes);
vector_destroy(history);
exit(1);
}
process* bg = malloc(sizeof(process));
bg->pid = child;
bg->status = STATUS_RUNNING;
bg->command = strdup(line);
vector_push_back(processes, bg);
result = 1;
}
vector_destroy(new_vec);
sstring_destroy(new_sstr);
free(com);
}
else {
fflush(stdout);
char** com = (char**)malloc(sizeof(char*)*(vector_size(vec)+1));
pid_t child = fork();
if (child == -1) {
print_fork_failed();
exit(1);
}
else if (child == 0) {
for (size_t i = 0; i < vector_size(vec); i++) {
com[i] = vector_get(vec, i);
}
print_command_executed(getpid());
execvp(com[0], com);
print_exec_failed(line);
exit(1);
}
else {
int status = 0;
waitpid(child, &status, 0);
if (status != 0) {
print_wait_failed();
}
else {
result = 1;
}
}
free(com);
}
sstring_destroy(sstr);
vector_destroy(vec);
if (result == 1)
return 1;
else
return 0;
}
int seperator_idx(char* line) {
char* temp = line;
int idx = 0;
while(*temp) {
if (*temp == ';') {
return idx;
}
temp++;
idx++;
}
return 0;
}
int and_index(char* line) {
char* temp = line;
int idx = 0;
while(*temp) {
if (*temp == '&') {
if (idx+1 < (int)strlen(line))
return idx;
}
temp++;
idx++;
}
return 0;
}
int or_index(char* line) {
char* temp = line;
int idx = 0;
while(*temp) {
if (*temp == '|') {
return idx;
}
temp++;
idx++;
}
return 0;
}
void handle_file(vector* history, char* path_f, vector* processes) {
FILE* f = fopen(path_f, "r");
if (!f) {
print_script_file_error();
return;
}
pid_t pid_sh = getpid();
char* buffer = NULL;
size_t size = 0;
char cwd[PATH_MAX + 1];
while(getline(&buffer, &size, f) != -1) {
int length = strlen(buffer);
if (buffer[length-1] == '\n') {
buffer[length-1] = '\0';
}
getcwd(cwd, sizeof(cwd));
print_prompt(cwd, pid_sh);
print_command((const char*)buffer);
if (strlen(buffer)==0) {
continue;
}
sstring* str = cstr_to_sstring(buffer);
int idx = seperator_idx(buffer);
if (idx > 0) {
char* com1 = sstring_slice(str, 0, idx);
char* com2 = sstring_slice(str, idx+2, strlen(buffer));
handle_command(com1, history, processes);
handle_command(com2, history, processes);
free(com1);
free(com2);
vector_push_back(history, buffer);
sstring_destroy(str);
continue;
}
idx = and_index(buffer);
if (idx > 0) {
char* a = sstring_slice(str, 0, idx);
char* b = sstring_slice(str, idx+3, strlen(buffer));
if (handle_command(a, history, processes) > 0) {
handle_command(b, history, processes);
}
free(a);
free(b);
vector_push_back(history, buffer);
sstring_destroy(str);
continue;
}
idx = or_index(buffer);
if (idx > 0) {
char* c = sstring_slice(str, 0, idx);
char* d = sstring_slice(str, idx+3, strlen(buffer));
if (handle_command(c, history, processes) == 0) {
handle_command(d, history, processes);
}
free(c);
free(d);
vector_push_back(history, buffer);
sstring_destroy(str);
continue;
}
int result = handle_command(buffer, history, processes);
if (result == 1) {
vector_push_back(history, buffer);
}
sstring_destroy(str);
}
free(buffer);
fclose(f);
}
void sig_chld(int signal) {
if (vector_size(processes) > 1) {
pid_t pid;
int status;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
for (size_t i = 1; i < vector_size(processes); i++) {
process* p = vector_get(processes, i);
if (p->pid == pid) {
free(p->command);
free(p);
vector_erase(processes, i);
break;
}
}
}
}
}
void sig_int(int signal) {
while(vector_size(processes) > 1) {
process* p = vector_get(processes, 1);
kill(p->pid, SIGTERM);
}
}
int shell(int argc, char *argv[]) {
// TODO: This is the entry point for your shell.
if (argc > 5 || argc == 4 || argc == 2) {
print_usage();
exit(1);
}
if (argc == 3 && strcmp(argv[1],"-h") != 0 && strcmp(argv[1],"-f") != 0) {
print_usage();
exit(1);
}
processes = shallow_vector_create();
process* p_sh = malloc(sizeof(process));
p_sh->command = "./shell";
p_sh->status = STATUS_RUNNING;
p_sh->pid = getpid();
vector_push_back(processes, p_sh);
vector* history = string_vector_create();
signal(SIGINT, sig_int);
signal(SIGCHLD, sig_chld);
if (argc == 3 && strcmp(argv[1],"-f") == 0) {
char* path_f = get_full_path((char*)argv[2]);
handle_file(history, path_f, processes);
free(path_f);
}
else if (argc == 5) {
if (strcmp(argv[1],"-h") == 0 && strcmp(argv[3],"-f") == 0) {
char* path_h = get_full_path((char*)argv[2]);
insert_history(history, path_h);
free(path_h);
char* path_f = get_full_path((char*)argv[4]);
handle_file(history, path_f, processes);
free(path_f);
}
else if (strcmp(argv[1],"-f") == 0 && strcmp(argv[3],"-h") == 0) {
char* path_h = get_full_path((char*)argv[4]);
insert_history(history, path_h);
free(path_h);
char* path_f = get_full_path((char*)argv[2]);
handle_file(history, path_f, processes);
free(path_f);
}
else {
print_usage();
vector_destroy(processes);
vector_destroy(history);
exit(1);
}
}
else {
if (argc == 3) {
char* path_h = get_full_path((char*)argv[2]);
insert_history(history, path_h);
free(path_h);
}
size_t size = 0;
char* buffer = NULL;
char cwd[PATH_MAX + 1];
pid_t pid_sh = getpid();
getcwd(cwd, sizeof(cwd));
print_prompt(cwd, pid_sh);
while(getline(&buffer, &size, stdin) != -1) {
int length = strlen(buffer);
if (buffer[length-1] == '\n') {
buffer[length-1] = '\0';
}
if (strlen(buffer)==0) {
getcwd(cwd, sizeof(cwd));
print_prompt(cwd, pid_sh);
continue;
}
if (strcmp(buffer, "exit") == 0) {
break;
}
sstring* str = cstr_to_sstring(buffer);
int idx = seperator_idx(buffer);
if (idx > 0) {
char* com1 = sstring_slice(str, 0, idx);
char* com2 = sstring_slice(str, idx+2, strlen(buffer));
handle_command(com1, history, processes);
handle_command(com2, history, processes);
free(com1);
free(com2);
vector_push_back(history, buffer);
sstring_destroy(str);
getcwd(cwd, sizeof(cwd));
print_prompt(cwd, pid_sh);
continue;
}
idx = and_index(buffer);
if (idx > 0) {
char* a = sstring_slice(str, 0, idx);
char* b = sstring_slice(str, idx+3, strlen(buffer));
if (handle_command(a, history, processes) > 0) {
handle_command(b, history, processes);
}
free(a);
free(b);
vector_push_back(history, buffer);
sstring_destroy(str);
getcwd(cwd, sizeof(cwd));
print_prompt(cwd, pid_sh);
continue;
}
idx = or_index(buffer);
if (idx > 0) {
char* c = sstring_slice(str, 0, idx);
char* d = sstring_slice(str, idx+3, strlen(buffer));
if (handle_command(c, history, processes) == 0) {
handle_command(d, history, processes);
}
free(c);
free(d);
vector_push_back(history, buffer);
sstring_destroy(str);
getcwd(cwd, sizeof(cwd));
print_prompt(cwd, pid_sh);
continue;
}
int result = handle_command(buffer, history, processes);
if (result == 1) {
vector_push_back(history, buffer);
}
getcwd(cwd, sizeof(cwd));
print_prompt(cwd, pid_sh);
sstring_destroy(str);
}
free(buffer);
}
while(vector_size(processes) > 1) {
process* p = vector_get(processes, 1);
kill(p->pid, SIGTERM);
}
process* p = vector_get(processes, 0);
free(p);
if (argc == 3) {
if (strcmp(argv[1],"-h") == 0) {
char* pa = get_full_path((char*)argv[2]);
write_history(history, pa);
free(pa);
}
}
if (argc == 5) {
if (strcmp(argv[3],"-h") == 0) {
char* pa = get_full_path((char*)argv[4]);
write_history(history, pa);
free(pa);
}
}
vector_destroy(processes);
vector_destroy(history);
return 0;
}
shell.h 0 → 100644
/**
* Shell Lab
* CS 241 - Fall 2018
*/
/**
* this file exists so that we can provide a main method which does a variety of
* handy things.
*
* DO NOT EDIT THIS FILE!
*/
// entry point for student code
int shell(int argc, char **argv);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment