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

initial commit

parents
Branches master
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