Skip to content

Commit

Permalink
Finished A2
Browse files Browse the repository at this point in the history
  • Loading branch information
sterrio committed Oct 7, 2021
1 parent 8bc985e commit 6e67664
Show file tree
Hide file tree
Showing 4 changed files with 417 additions and 0 deletions.
97 changes: 97 additions & 0 deletions CSCI3120 - Operating Systems/A2/A2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Stephen Terrio B00755443

// Base taken from Assignement 2 PDF -
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#include "linked_list.h"

// CITED RESOURCES: LinkedList.c with its respective header has been taken from previous work done in the class: Systems Programming
// It is only used for the history command.

#define MAX_LINE 80 /* max command length */

// MAIN -
int main (void){
/* flag for program execution vs termination */
int should_run = 1;
LinkedList* history = llist_initialize(sizeof(char*),"string");
LinkedList* ids = llist_initialize(sizeof(int*),"integer");

while(should_run == 1) {
printf("CSCI3120>");
fflush(stdout);

/* Reading user input, refrencing back to my solution of A1... */
char input[250];
// getting input until new line & discarding, adding to history list & checking special commands
scanf("%[^\n]%*c", input);

if(!strcmp("!!",input)){
if(history->size == 0){printf("No command in history!\n");continue;}
strcpy(input,llist_get(history, 0));
printf("CSCI3120>%s\n", input);

}else if(input[0] == '!'){
int index = input[1] - '0';
if(index > history->size){printf("Such a command is NOT in history!\n"); continue;}
strcpy(input,llist_get(history,index - 1));
printf("CSCI3120>%s\n", input);
}
if(strcmp("history",input)){llist_add_first(history, input);}
char *split = strtok(input, " ");
// 41 tokens at most, 39 buffer tokens
char *arrayofchars[80];
int counter = 0;
// looping till there can be no more splits
while(split != NULL){
arrayofchars[counter] = split;
split = strtok(NULL, " ");
counter = counter + 1;
}

// checking for exit command
if(!strcmp("exit",arrayofchars[0])){should_run = 0;}

// handling for history command
if(!strcmp("history",arrayofchars[0])){
if(history->size == 0){printf("No command in history!\n"); continue;}
printf("ID PID Command\n");
for(int i = 0; i < history->size && i < 10; i++){
int tempID = (*(int *)llist_get(ids,i));
printf("%d %d %s\n", i+1, tempID, llist_get(history,i));
}
continue;
}
// Keeping track of function stats in case of error
int execpStatus;
int waitStatus;
/* Fork to a child process */
pid_t child;
child = fork();
// saving to be used later in history
void *id = &child;
llist_add_first(ids, id);

// should not be non-negative unless an error occured, referencing class notes pdf
if(child < 0){
printf("An error occured Forking");
return 1;
}
/*Child Process Running Correctly*/
else if(child == 0 && should_run != 0){
execpStatus = execvp(arrayofchars[0], arrayofchars);
if(execpStatus == -1){
// an error has occured
printf("Invalid command!");
exit(1);
}
}
/* Parent Process */
else {
wait(&waitStatus);
}
}
}
7 changes: 7 additions & 0 deletions CSCI3120 - Operating Systems/A2/ReadMe.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
TO COMPILE:
open terminal and find folder containing .c and .h files
cd into it and execute this command in terminal once reaching directory

gcc A2.c linked_list.c -o a2

once compiled, run command ./a2 to execute program
278 changes: 278 additions & 0 deletions CSCI3120 - Operating Systems/A2/linked_list.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
#include "linked_list.h"
#include <stdlib.h>
#include <string.h>

LinkedList* llist_initialize(int typeSize, char* typeName)
{
// Create a linked list struct.
LinkedList* llist = malloc(sizeof(*llist));

// If the linked list can't have memory allocated, return NULL.
if(llist == NULL)
return NULL;

// Initialize all of the linked list fields.
llist->first = NULL;
llist->last = NULL;
llist->size = 0;
llist->itemSize = typeSize;
llist->type = malloc(strlen(typeName));
strcpy(llist->type, typeName);

// Return the empty linked list.
return llist;
}

bool llist_add_at(LinkedList* llist, int index, void* element)
{
// If the list or element are null, return false.
if(llist == NULL || element == NULL)
return false;

// If the index doesn't fit in the bounds of the
// list, we can return false.
if(index < 0 || index > llist->size)
return false;

// Create a new node and populate its data.
Node *node = malloc(sizeof(*node));
node->data = malloc(llist->itemSize);
memcpy(node->data, element, llist->itemSize);

// If we haven't added any nodes yet, we need to
// ensure both the first and last are updated.
if(llist->size == 0)
{
llist->first = node;
llist->last = node;
node->next = NULL;
node->prev = NULL;
}
// If we are adding on the front of the list,
// we only need to deal with the first pointer.
else if(index == 0)
{
node->next = llist->first;
node->prev = NULL;
llist->first->prev = node;
llist->first = node;
}
// If we are adding on the end of the list,
// we only need to deal with the last pointer.
else if(index == llist->size)
{
node->next = NULL;
node->prev = llist->last;
llist->last->next = node;
llist->last = node;
}
// If we get here, we are inserting somewhere
// in the middle of the list.
else
{
// Create a temporary traversal node.
Node *temp = llist->first;

// Iterate until we get to the node to be removed.
for(int i=0; i < index; i++)
temp = temp->next;

// Set the new node's previous to the current node's previous.
node->prev = temp->prev;

// Set the new node's next to the current node.
node->next = temp;

// Set the previous node to point to the new one.
temp->prev->next = node;

// Set the current node to point to the new one.
temp->prev = node;
}

// Increase the size of the linked list by 1.
llist->size++;
return true;
}

bool llist_add_first(LinkedList* llist, void* element)
{
// We can simply call/return "add_at". It will check for NULL.
return llist_add_at(llist, 0, element);
}

bool llist_add_last(LinkedList* llist, void* element)
{
// We need to check if llist is null before we
// use llist->size, otherwise we'll seg fault.
if(llist == NULL)
return false;

// Return the value of "add_at" on the list size.
return llist_add_at(llist, llist->size, element);
}

void* llist_get(LinkedList* llist, int index)
{
// If the list is null, we return null.
if(llist == NULL)
return NULL;

// If the index isn't in the list right now, return null.
if(index < 0 || index >= llist->size)
return NULL;

// Create a temporary node variable and store the first node.
Node *temp = llist->first;

// Iterate through the list until we find the element.
for(int i=0; i < index; i++)
temp = temp->next;

// Return a pointer to the element.
return temp->data;
}

int llist_index_of(LinkedList* llist, void* element)
{
// If the list is null or the element is null, we return -1.
if(llist == NULL || element == NULL)
return -1;

// Create a temporary node variable and store the first node.
Node *temp = llist->first;

// Iterate through the list until we find the element.
for(int i=0; i < llist->size; i++)
{
// Compare the element to the stored data of this node.
// If the data matches the element, return the index.
if(memcmp(temp->data, element, llist->itemSize) == 0)
return i;

// Move to the next list node.
temp = temp->next;
}

// If we get here, the list didn't have the element. Return -1.
return -1;
}

void* llist_remove(LinkedList* llist, int index)
{
// If the list is null, return null.
if(llist == NULL)
return NULL;

// If the index is out of bounds, return null.
if(index < 0 || index >= llist->size)
return NULL;

// Create a temporary node.
Node *temp = llist->first;

// Iterate until we get to the node to be removed.
for(int i=0; i < index; i++)
temp = temp->next;

// Adjust the pointers of adjacent nodes and linked list:
// 1) If the list only has one node, we simply set the
// linked list's first and last pointers to NULL.
// 2) If we are removing the first node, we only have to
// adjust the next node's pointers and update the
// linked list's first node pointer.
// 3) If we are removing the last node, we only have to
// adjust the previous node's pointers and update the
// linked list's last node pointer.
// 4) Otherwise we adjust the next and prev nodes to make
// sure they point to each other.
if(llist->size == 1)
{
llist->first = NULL;
llist->last = NULL;
}
else if(index == 0)
{
llist->first = temp->next;
llist->first->prev = NULL;
}
else if(index == llist->size-1)
{
llist->last = temp->prev;
llist->last->next = NULL;
}
else
{
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
}

// Reduce the size of the linked list by 1.
llist->size--;

// Save the data from the node.
void* data = temp->data;

// Free the node.
free(temp);

// Return the removed node. It is up to the owner to free it.
return data;
}

void* llist_remove_first(LinkedList* llist)
{
// We can call "remove" on the first index.
return llist_remove(llist, 0);
}

void* llist_remove_last(LinkedList* llist)
{
// If llist is null, we can't use the the
// llist->size member without a seg fault.
if(llist == NULL)
return false;

// We can call "remove" on the last index.
return llist_remove(llist, llist->size-1);
}

bool llist_destroy(LinkedList* llist)
{
// If the list is null, we can't destroy it. Return false.
if(llist == NULL)
return false;

// If there are nodes available in the list, free them.
if(llist->size > 0)
{
// Create a temporary node for holding nodes.
Node *current = llist->first;
Node *next = NULL;

// Iterate through all of the nodes.
for(int i=0; i < llist->size; i++)
{
// Store a pointer to the next node.
next = current->next;

// Free this node's data.
free(current->data);

// Free this node.
free(current);

// We move to the next node.
current = next;
}
}

// Free the necessary linked list fields.
free(llist->type);

// Free the linked list.
free(llist);

// We destroyed the list. Return true.
return true;
}
Loading

0 comments on commit 6e67664

Please sign in to comment.