Added work from my other class repositories before deletion

This commit is contained in:
2017-11-29 10:28:24 -08:00
parent cb0b5f4d25
commit 5ea24c81b5
198 changed files with 739603 additions and 0 deletions

View File

@@ -0,0 +1,301 @@
#!/bin/bash
#
# Program 1
#
# To create a test run of your program put this file and your stats
# program, which must be named "stats", together in a directory. Then run
# this command, which will take perhaps 15 seconds:
#
# % p1gradingscript > p1results
#
# Your whole program must be contained in the single file named "stats".
#
LS=/bin/ls
RM=rm
PS=/bin/ps
TESTDIR=assign1.test.$$
STATS=./stats
if test -d $TESTDIR
then
echo Please rename or remove $TESTDIR
exit 1
fi
mkdir $TESTDIR 2>&1
cp stats $TESTDIR 2>&1
cd $TESTDIR 2>&1
chmod +x stats 2>&1
echo --------------------------------------------------------------------------
echo Creating file1 file2 file3 file4 file5
echo
cat > file1 <<EOF
93 93 93 93 93 93 93 93 100
73 84 95 83 72 86 80 97 100
85 0 82 75 88 79 80 81 100
85 0 87 73 88 79 80 71 100
80 81 83 63 100 85 63 68 100
53 57 61 53 70 61 73 50 100
55 54 41 63 63 45 33 41 100
53 55 43 44 63 75 35 21 100
100 100 100 100 100 100 100 100 100
EOF
cat > file2 <<EOF
97 95 93 91
86 80 97 99
61 73 50 100
95 94 93 92
EOF
cat > file3 <<EOF
17
EOF
cat > file4 <<EOF
EOF
i=0
while [ $i -lt 50000 ]
do
echo "$i `expr $i \* 2`"
i=`expr $i + 100`
done > file5
echo
$LS -l 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo File 1 Statistics by Rows: 1 point per correct number: 18
echo
$STATS -rows file1 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo Check for Temporary Files: 5 points if no temp files
echo
$LS 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo File 1 Statistics by Cols: 1 point per correct number: 18
echo
$STATS -cols file1 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo Check for Temporary Files: 5 points if no temp files
echo
$LS 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo File 2 Statistics by Rows: 1 point per correct number: 8
echo
$STATS -rows file2 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo File 2 Statistics by Cols: 1 point per correct number: 8
echo
$STATS -cols file2 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo File 3 Statistics by Rows: 1 point per correct number: 2
echo
$STATS -rows file3 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo File 3 Statistics by Cols: 1 point per correct number: 2
echo
$STATS -cols file3 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo File 4 Statistics by Rows: lose 3 points if response not something like FILE IS EMPTY
echo
$STATS -rows file4 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo File 4 Statistics by Cols: lose 3 points if response not something like FILE IS EMPTY
echo
$STATS -cols file4 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo File 5 Statistics by Cols: 1 point per number: 4
echo
$STATS -cols file5 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo Check for Temporary Files: 5 points if no temp files
echo
$LS 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo Good Syntax
echo
echo Standard Input on Rows: 2 points for exit value 0, 1 point for no error text
$STATS -rows < file2 2> err.out
echo Exit Value: $?
echo Error Message:
cat err.out
echo
echo Standard Input on Cols: 2 points for exit value 0, 1 point for no error text
$STATS -cols < file2 2> err.out
echo Exit Value: $?
echo Error Message:
cat err.out
echo
echo Option -cols: 2 points for exit value 0, 1 point for no error text
$STATS -cols file2 2> err.out
echo Exit Value: $?
echo Error Message:
cat err.out
echo
echo Option -rrrrrr: 2 points for exit value 0, 1 point for no error text
$STATS -rrrrrr file2 2> err.out
echo Exit Value: $?
echo Error Message:
cat err.out
echo
echo Option -cccccc: 3 points for exit value 0
$STATS -cccccc file2 2> err.out
echo Exit Value: $?
echo Error Message:
cat err.out
echo
echo Option -r: 3 points for exit value 0
$STATS -r file2 2> err.out
echo Exit Value: $?
echo Error Message:
cat err.out
echo
echo
echo --------------------------------------------------------------------------
echo Bad Syntax
echo
echo Too Few Arguments: 1 point for usage text, 2 points for exit value 1
$STATS 2> err.out
echo Exit Value: $?
echo Error Message:
cat err.out
echo
echo Too Many Arguments: 1 point for usage text, 2 points for exit value 1
$STATS -r file1 file2 2> err.out
echo Exit Value: $?
echo Error Message:
cat err.out
echo
echo Wrong Format: 1 point for usage text, 2 points for exit value 1
$STATS file1 file2 2> err.out
echo Exit Value: $?
echo Error Message:
cat err.out
echo
echo Bad Option: 1 point for usage text, 2 points for exit value 1
$STATS -x file1 2> err.out
echo Exit Value: $?
echo Error Message:
cat err.out
echo
echo
echo --------------------------------------------------------------------------
echo File Not Readable: 2 points for error msg, 2 points for program halting
echo
chmod 000 file3 2>&1
echo
$STATS -r file3 2> err.out
echo Exit Value: $?
echo Error Message:
cat err.out
echo
$RM -f err.out 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo Check for Temporary Files: 5 points for no temp files
echo
$LS 2>&1
echo
echo
echo --------------------------------------------------------------------------
echo Simultaneous Runs
echo
$STATS -rows < file1 > simrun1.out 2>&1 &
PID1=$!
$STATS -rows < file1 > simrun2.out 2>&1 &
PID2=$!
$STATS -rows < file1 > simrun3.out 2>&1 &
PID3=$!
sleep 2
echo
echo Before Finishing
$LS 2>&1
echo
while ($PS | egrep "^ *($PID1)|($PID2)|($PID3)" > /dev/null)
do
echo waiting...
sleep 5
done
echo
echo Run 1 Output: 5 points for succesful run 1
cat simrun1.out 2>&1
echo
echo Run 2 Output: 5 points for succesful run 2
cat simrun2.out 2>&1
echo
echo Run 3 Output: 5 points for succesful run 3
cat simrun3.out 2>&1
echo
$RM -f simrun[123].out 2>&1
echo
echo After Finishing: 5 points if no temp file
$LS 2>&1
echo
echo
echo Trap Signals
echo
$STATS -rows < file5 > /dev/null &
PID=$!
sleep 2
echo
echo Before Kill
$LS 2>&1
echo
$PS
echo
kill $PID
sleep 5
echo
echo After Kill: 8 points if no temp files
$LS 2>&1
echo
$PS
echo
echo
cd ..
$RM -rf $TESTDIR 2>&1

View File

@@ -0,0 +1,32 @@
stats {-rows|-cols} [input_file]
DONE: Numbers are separated by tabs, lines by newlines
DONE: Check for the correct number of arguments, failure to standard error
DONE: Check whether file is readable, or exists, stderr if not
DONE: -rows and -cols should work for anything that starts with its character eg. -rad would do rows
Stats output to stdout
Exit value for errors should be 1
You can assume each row will be less than 1000 bytes long, unix limits this, but unlimited numbers of rows
DONE: If using temp files, make sure they include process id's in name to allow for simultaneous runs. Remove files when done.
DONE: Use the trap command to catch interrupt, hangup, and terminate signals to remove temp files if terminates unexpectedly
Values and results must be whole numbers, round like normal, 7.5 to 8, 7.4 to 7
DONE: Calculations must be done with expr or commandline tools. No other languages
DONE: For median, sort values and take the middle value. If even, take the larger of the middle two values.
DONE: Must be in a single file.
DONE: You can return an error if there is no input file
HINTS

View File

@@ -0,0 +1,35 @@
% cat test_file
1 1 1 1 1
9 3 4 5 5
6 7 8 9 7
3 6 8 9 1
3 4 2 1 4
6 4 4 7 7
% stats -rows test_file
Average Median
1 1
5 5
7 7
5 6
3 3
6 6
% cat test_file | stats c
Averages:
5 4 5 5 4
Medians:
6 4 4 7 5
% echo $?
0
% stats
Usage: stats {-rows|-cols} [file]
% stats -r test_file nya-nya-nya
Usage: stats {-rows|-cols} [file]
% stats -both test_file
Usage: stats {-rows|-cols} [file]
% chmod -r test_file
% stats -columns test_file
stats: cannot read test_file
% stats -columns no_such_file
stats: cannot read no_such_file
% echo $?
1

View File

@@ -0,0 +1,235 @@
#!/bin/bash
########## Programmer Info ############
# Name: Corwin Perren
# OSU ID: 931759527
# Assignment: Assignment 1 - stats
# Filename: stats
########## Global Variables ############
# Used for transposing the axis on a two dimensional array
awk_transpose='{
for ( i=1; i <= NF; i++ )
row[i] = row[i]((row[i])?" ":"")$i
}
END{
for ( x = 1; x <= length(row) ; x++ )
print row[x]
}'
# Used to properly round the floating point values
awk_proper_rounding='
{printf("%d\n",$1 + 0.5)}
'
# Stores the PID used to name and delete temp files
master_pid=$!
########## Functions ###########
# Error function for when user input is wrong
show_usage_error ()
{
echo "Usage: stats {-rows|-cols} [file]" >&2
exit 1
}
# Error function for when a user feeds in an empty file
show_empty_file_error ()
{
echo "stats: Input empty. Please provide valid input." >&2
exit 1
}
# Error function for when the file doesn't exist or can't be accessed
show_invalid_file_error ()
{
echo "stats: Cannot read file. Please verify file exists or check permissions." >&2
exit 1
}
# Function to delete temporary files
remove_temp_if_exist ()
{
rm -f ${master_pid}"_"transposed
rm -f ${master_pid}"_"temp
}
# Function to handle file cleanup and returning an error when an interrupt happens
handle_unexpected_termination_error ()
{
remove_temp_if_exist
echo "CTRL+C received. Exiting." >&2
exit 1
}
#####################################################
#####################################################
########## "stats" script "main"-ish code ###########
# Handle unexpected termination
trap handle_unexpected_termination_error INT HUP TERM
# Determine if we're getting data from stdin or a file, error if neither
if [ $# -eq 0 ] || [ $# -gt 2 ]; then
show_usage_error
elif [ $# -eq 1 ]; then
is_stdin=1
elif [ $# -eq 2 ]; then
is_stdin=0
fi
# Determine if we're doing statistics based on columns or rows, error if neither
if [[ $1 == -r* ]]; then
is_rows=1
elif [[ $1 == -c* ]]; then
is_rows=0
else
show_usage_error
fi
# If the input is a file, make sure we can open it and that it exists
if [ ${is_stdin} -eq 0 ]; then
if [ ! -e $2 ] || [ ! -r $2 ] || [ ! -f $2 ]; then
show_invalid_file_error
fi
fi
# If stats should be on columns, transpose the table so the columns are the new rows and rows are the new columns
# This will make it so the same stats math can be used to generate the correct data
# If the data is coming from stdin and needs to be columns, it makes a temp file, stores the data in it, and then
# transposes it just as if it were a file being fed in as an argument
# If the flags here are anything but a standard in piping with rows, it opens the file with a file descriptor for access
# This also handles showing an error if the input from stdin with -cols is empty
if [ ${is_rows} -eq 0 ] && [ ${is_stdin} -eq 0 ]; then
cat $2 | awk "${awk_transpose}" > ${master_pid}"_"transposed
exec 3<> ${master_pid}"_"transposed
elif [ ${is_rows} -eq 0 ] && [ ${is_stdin} -eq 1 ]; then
line_count=0
while read current_line
do
echo -e ${current_line} >> ${master_pid}"_"temp
((line_count = line_count + 1))
done
if [ ${line_count} -eq 0 ]; then
show_empty_file_error
fi
cat ${master_pid}"_"temp | awk "${awk_transpose}" > ${master_pid}"_"transposed
exec 3<> ${master_pid}"_"transposed
is_stdin=0
elif [ ${is_rows} -eq 1 ] && [ ${is_stdin} -eq 0 ]; then
exec 3<> $2
fi
# Now we perform the stats math operations on the data
line_count=0
declare -a averages
declare -a medians
while [ 1 ];
do
# We read in the current line
if [ ${is_stdin} -eq 1 ]; then
read current_line
else
read -u 3 current_line
fi
# Here we get the result code from read, which tells us if there's data left
read_result=$?
# If there was no data, and we haven't looped yet, the file is empty and we error
# Otherwise, it means we've reached the end of the file and it's time to leave the loop
if [ ${read_result} -eq 1 ] && [ ${line_count} -eq 0 ]; then
show_empty_file_error
elif [ ${read_result} -eq 1 ]; then
break
fi
# Initialize variables for doing the calculations
sum=0
count=0
avg=0
newline="\n"
numbers_string=""
# This part does the summing and adds the numbers to a new string so it can be parsed by sort
for word in ${current_line}
do
numbers_string=${numbers_string}${newline}${word}
((sum = word + sum))
((count = count + 1))
done
# Here we use bc and awk to handle the floating point results of division and proper rounding
# The avg then gets added to the average array for display later
avg=$(echo "(${sum}/${count})" | bc -l | awk "${awk_proper_rounding}")
averages[${line_count}]=${avg}
# Now the new string we created is sorted numerically so we can easily find the median
sorted=$(echo -e ${numbers_string} | sort -n)
# Then we find and add the median number to our medians array
i=0
for word in ${sorted}
do
if [ ${i} == $(((count/2))) ]; then
medians[${line_count}]=${word}
break
fi
((i = i + 1))
done
# Here we increment our line count so we can properly handle empty files
((line_count = line_count + 1))
done
# For rows display, we print out the header then one value from averages and count, separated by tabs
if [ ${is_rows} -eq 1 ]; then
echo -e "Average\tMedian"
count=0
for word in ${averages[*]}
do
echo -e "${averages[count]}\t${medians[count]}"
((count = count + 1))
done
# For cols display, we print a header, then all the contents of average, another header, and the contents of median
# Takes a little more work to print this one and not have extra tabs left over
else
echo -e "Averages:"
first=1
for word in ${averages[*]}
do
if [ ${first} -eq 1 ]; then
echo -e -n "${word}"
first=0
else
echo -e -n "\t${word}"
fi
((count = count + 1))
done
echo
echo -e "Medians:"
first=1
for word in ${medians[*]}
do
if [ ${first} -eq 1 ]; then
echo -e -n "${word}"
first=0
else
echo -e -n "\t${word}"
fi
((count = count + 1))
done
echo
fi
# Assuming we make it this far, the trap handler will not have taken care of our temp files, so we do that now
remove_temp_if_exist
# Again, having made it this far the program has completed successfully. Exit with no error.
exit 0

View File

@@ -0,0 +1,128 @@
#
# There exist several targets which are by default empty and which can be
# used for execution of your targets. These targets are usually executed
# before and after some main targets. They are:
#
# .build-pre: called before 'build' target
# .build-post: called after 'build' target
# .clean-pre: called before 'clean' target
# .clean-post: called after 'clean' target
# .clobber-pre: called before 'clobber' target
# .clobber-post: called after 'clobber' target
# .all-pre: called before 'all' target
# .all-post: called after 'all' target
# .help-pre: called before 'help' target
# .help-post: called after 'help' target
#
# Targets beginning with '.' are not intended to be called on their own.
#
# Main targets can be executed directly, and they are:
#
# build build a specific configuration
# clean remove built files from a configuration
# clobber remove all built files
# all build all configurations
# help print help mesage
#
# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
# .help-impl are implemented in nbproject/makefile-impl.mk.
#
# Available make variables:
#
# CND_BASEDIR base directory for relative paths
# CND_DISTDIR default top distribution directory (build artifacts)
# CND_BUILDDIR default top build directory (object files, ...)
# CONF name of current configuration
# CND_PLATFORM_${CONF} platform name (current configuration)
# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration)
# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration)
# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration)
# CND_PACKAGE_DIR_${CONF} directory of package (current configuration)
# CND_PACKAGE_NAME_${CONF} name of package (current configuration)
# CND_PACKAGE_PATH_${CONF} path to package (current configuration)
#
# NOCDDL
# Environment
MKDIR=mkdir
CP=cp
CCADMIN=CCadmin
# build
build: .build-post
.build-pre:
# Add your pre 'build' code here...
.build-post: .build-impl
# Add your post 'build' code here...
# clean
clean: .clean-post
.clean-pre:
# Add your pre 'clean' code here...
.clean-post: .clean-impl
# Add your post 'clean' code here...
# clobber
clobber: .clobber-post
.clobber-pre:
# Add your pre 'clobber' code here...
.clobber-post: .clobber-impl
# Add your post 'clobber' code here...
# all
all: .all-post
.all-pre:
# Add your pre 'all' code here...
.all-post: .all-impl
# Add your post 'all' code here...
# build tests
build-tests: .build-tests-post
.build-tests-pre:
# Add your pre 'build-tests' code here...
.build-tests-post: .build-tests-impl
# Add your post 'build-tests' code here...
# run tests
test: .test-post
.test-pre: build-tests
# Add your pre 'test' code here...
.test-post: .test-impl
# Add your post 'test' code here...
# help
help: .help-post
.help-pre:
# Add your pre 'help' code here...
.help-post: .help-impl
# Add your post 'help' code here...
# include project implementation makefile
include nbproject/Makefile-impl.mk
# include project make variables
include nbproject/Makefile-variables.mk

View File

@@ -0,0 +1,673 @@
/* ///////////////////////////////////////// */
/* ///////// Includes and Defines ////////// */
/* ///////////////////////////////////////// */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <assert.h>
#include <time.h>
/* ///////////////////////////////////// */
/* ///////// Global Variables ////////// */
/* ///////////////////////////////////// */
/* Room variables */
char* room_filenames[] = {
"room_1.txt",
"room_2.txt",
"room_3.txt",
"room_4.txt",
"room_5.txt",
"room_6.txt",
"room_7.txt"
};
char* rooms_directory_base = "perrenc.rooms.";
char rooms_directory_full[255];
char *potential_room_names[10] = {
"Dearborn",
"Graf",
"Rogers",
"Covell",
"Batcheller",
"Kidder",
"Valley Library",
"Memorial Union",
"Gilbert",
"Weniger"
};
unsigned int min_connections = 3;
unsigned int max_connections = 6;
char* current_room_filename;
char path_taken[255][15];
unsigned int num_steps = 0;
/* File access variables */
FILE *file_pointer_main;
FILE *file_pointer_time;
/* Threading variables */
pthread_t time_thread_ID;
bool time_written = false;
char* time_file_name = "currentTime.txt";
pthread_mutex_t time_mutex;
/* State Handling Variables */
bool game_over = false;
bool delete_folder_and_files = true;
/* State Variables */
bool valid_input = false;
bool first_print = true;
/* //////////////////////////////////////// */
/* ///////// Function Prototypes ////////// */
/* //////////////////////////////////////// */
/* Initialization functions */
void program_init(void);
void generate_rooms(void);
/* User Input and Printing Functions */
void print_current_room_and_prompt(void);
void get_user_input_and_process(void);
void print_game_over(void);
/* Room Specific Functions*/
void create_room(char *room_filename, char *room_name, char* room_type);
void add_connection_to_room(char *room_filename, char *room_name_to_add);
unsigned int get_number_of_connections_from_room(char *room_filename);
bool is_room_used(char* room_name);
bool is_end_room(char* room_filename);
void get_room_name(char* room_filename, char* room_name_buffer);
int get_room_index_from_name(char* room_name);
int get_used_indexes(char* room_filename, int* output_list);
/* Threading Functions */
void print_time(void);
/* Threading Functions */
void* get_time(void *arguments);
/* Helper Functions */
FILE *open_file_local_folder(char *file_name, char *mode);
int delete_file_local_folder(char *file_name);
/* ///////////////////////// */
/* ///////// Main ////////// */
/* ///////////////////////// */
int main(int argc, char** argv) {
program_init();
generate_rooms();
while(!game_over){
print_current_room_and_prompt();
while(!valid_input){
get_user_input_and_process();
}
valid_input = false;
}
print_game_over();
return (EXIT_SUCCESS);
}
/* ///////////////////////////////////////////// */
/* ///////// Initialization Functions ////////// */
/* ///////////////////////////////////////////// */
void program_init(void){
char pid_buffer[20];
memset(pid_buffer, '\0', 20);
/* Initialize our mutex */
assert(pthread_mutex_init(&time_mutex, NULL) == 0);
/* Make the rooms directory string we'll be using */
memset(rooms_directory_full, '\0', 255);
sprintf(pid_buffer, "%d", getpid());
strcat(rooms_directory_full, rooms_directory_base);
strcat(rooms_directory_full, pid_buffer);
/* Create the directory now that we have the string */
mkdir(rooms_directory_full, 0770);
/* Select the start room as the start point */
current_room_filename = room_filenames[0];
}
void generate_rooms(void){
time_t t;
bool start_used = false;
bool end_used = false;
char num_rooms = sizeof(room_filenames) / sizeof(room_filenames[0]);
srand((unsigned) time(&t));
/* Generate base rooms with room name and room type */
int i;
for(i = 0 ; i < num_rooms ; i++){
/* Get a random room name */
int random_num_name = rand() % 10;
char* current_room_name = potential_room_names[random_num_name];
/* If that name is already used, generate a unique one */
while(is_room_used(current_room_name)){
random_num_name = rand() % 10;
current_room_name = potential_room_names[random_num_name];
}
/* Make the start room if it hasn't been made yet */
if(!start_used){
create_room(room_filenames[i], current_room_name, "START_ROOM");
start_used = true;
/* Make the end room if it hasn't been made yet */
}else if(!end_used){
create_room(room_filenames[i], current_room_name, "END_ROOM");
end_used = true;
/* Make the middle rooms, if the start and ends rooms are made */
}else{
create_room(room_filenames[i], current_room_name, "MID_ROOM");
}
}
/* Generate the room connections for each room */
for(i = 0 ; i < num_rooms ; i++){
char buffer[255];
int used_rooms[6];
/* Initialize used rooms array with invalid numbers */
int l;
for(l = 0 ; l < 6 ; l++){
used_rooms[l] = -1;
}
/* Get random number between min and max connections */
int num_connections = (rand() % 4) + min_connections - \
get_number_of_connections_from_room(room_filenames[i]);
/* Generate the connections for an individual room */
int j;
for(j = 0 ; j < num_connections ; j++){
int room_to_add;
bool unused_found = false;
/* Generate connections, making sure they're not itself or other
rooms that have already been used */
while(!unused_found){
room_to_add = rand() % 7;
/* Skip if room is itself */
if(room_to_add == i){
continue;
}
/* Make sure that we're not adding a room that's already a
connection */
bool already_exists = false;
get_used_indexes(room_filenames[i], used_rooms);
int k;
for(k = 0 ; k < 6 ; k++){
if(used_rooms[k] == room_to_add){
already_exists = true;
break;
}
}
/* Make sure the connecting room can handle the reverse
connection */
if(get_number_of_connections_from_room(\
room_filenames[room_to_add]) == max_connections){
already_exists = true;
}
/* If all is good, set flag to exit loop */
if(!already_exists){
unused_found = true;
}
}
/* Once a connection has been deemed valid, add forward and
backwards connections */
memset(buffer, '\0', 255);
get_room_name(room_filenames[room_to_add], buffer);
add_connection_to_room(room_filenames[i], buffer);
memset(buffer, '\0', 255);
get_room_name(room_filenames[i], buffer);
add_connection_to_room(room_filenames[room_to_add], buffer);
}
}
}
/* //////////////////////////////////////////////// */
/* ///////// User Input and Printing Functions //// */
/* //////////////////////////////////////////////// */
void print_current_room_and_prompt(void){
char current_line[255];
char print_buffer[255];
char* tokenized;
memset(current_line, '\0', 255);
memset(print_buffer, '\0', 255);
file_pointer_main = open_file_local_folder(current_room_filename, "r");
/* Print location header */
if(first_print){
printf("CURRENT LOCATION: ");
first_print = false;
}else{
printf("\nCURRENT LOCATION: ");
}
/* Strip out and print current room name */
fgets(current_line, 255, file_pointer_main);
tokenized = strtok(current_line, ":");
tokenized = strtok(NULL, " \n");
bool first_entry = true;
while(tokenized != NULL){
if(first_entry){
first_entry = false;
}else{
printf(" ");
}
printf("%s", tokenized);
tokenized = strtok(NULL, " \n");
}
/* Print possible connections header */
printf("\nPOSSIBLE CONNECTIONS: ");
/* Loop through connections and print names with separators */
bool printing_connections = true;
bool printed_first_connection = false;
while(printing_connections){
fgets(current_line, 255, file_pointer_main);
tokenized = strtok(current_line, " ");
if(strcmp(tokenized, "CONNECTION") != 0){
printing_connections = false;
break;
}
if(printed_first_connection){
printf(", ");
}else{
printed_first_connection = true;
}
tokenized = strtok(NULL, ":");
tokenized = strtok(NULL, " \n");
bool first_entry = true;
while(tokenized != NULL){
if(first_entry){
first_entry = false;
}else{
printf(" ");
}
printf("%s", tokenized);
tokenized = strtok(NULL, " \n");
}
}
printf(".");
fclose(file_pointer_main);
}
void get_user_input_and_process(void){
char buffer[255];
memset(buffer, '\0', 255);
/* Print where to header */
printf("\nWHERE TO? >");
/* Read in newline terminated string from user, and strip out the newline*/
fgets(buffer, 255, stdin);
buffer[strlen(buffer)-1] = '\0';
/* Check input to determine if valid and what it should do*/
int room_index = get_room_index_from_name(buffer);
if(room_index != -1){
/* Room change is valid, change room and log */
strcpy(path_taken[num_steps], buffer);
num_steps++;
current_room_filename = room_filenames[room_index];
valid_input = true;
}else if(strcmp(buffer, "time") == 0){
/* Request was to print time, do so */
print_time();
}else{
/* Bad input was entered, print input error message */
printf("\nHUH? I DON'T UNDERSTAND THAT ROOM. TRY AGAIN.\n");
valid_input = true;
}
/* Set game over flag to the result of whether we're in the end room */
game_over = is_end_room(current_room_filename);
}
void print_game_over(void){
/* Print game over header */
printf("\nYOU HAVE FOUND THE END ROOM. CONGRATULATIONS!");
printf("\nYOU TOOK %u STEPS. YOUR PATH TO VICTORY WAS:", num_steps);
/* Print path taken to game over*/
int i;
for(i = 0 ; i < num_steps ; i++){
printf("\n%s", path_taken[i]);
}
printf("\n");
}
/* ////////////////////////////////////// */
/* ///////// Room Specific Functions //// */
/* ////////////////////////////////////// */
void create_room(char *room_filename, char *room_name, char* room_type){
file_pointer_main = open_file_local_folder(room_filename, "w");
assert(file_pointer_main != NULL);
/* Print line for the room name */
fputs("ROOM NAME: ", file_pointer_main);
fputs(room_name, file_pointer_main);
fputs("\n", file_pointer_main);
/* Print line for the room type */
fputs("ROOM TYPE: ", file_pointer_main);
fputs(room_type, file_pointer_main);
fclose(file_pointer_main);
}
void add_connection_to_room(char *room_filename, char *room_name_to_add){
char output_string_buffer[255];
char room_type_save_buffer[255];
unsigned int newline_count = 0;
unsigned int line_to_insert_at = 0;
long insertion_position = 0;
memset(output_string_buffer, '\0', 255);
memset(room_type_save_buffer, '\0', 255);
/* Determine where the new connection line will sit */
line_to_insert_at = get_number_of_connections_from_room(room_filename);
/* Add one to skip room name line */
line_to_insert_at++;
file_pointer_main = open_file_local_folder(room_filename, "r+");
/* Count out way to where we insert the new connection */
while(newline_count != line_to_insert_at){
if(fgetc(file_pointer_main) == '\n'){
newline_count++;
}
}
/* Save insertion position and make backup of line that will be wiped out */
insertion_position = ftell(file_pointer_main);
fgets(room_type_save_buffer, 255, file_pointer_main);
fseek(file_pointer_main, insertion_position, SEEK_SET);
/* Save new connection line and add the saved one after it */
sprintf(output_string_buffer, "CONNECTION %u: %s\n", line_to_insert_at, \
room_name_to_add);
fputs(output_string_buffer, file_pointer_main);
fputs(room_type_save_buffer, file_pointer_main);
fclose(file_pointer_main);
}
unsigned int get_number_of_connections_from_room(char *room_filename){
char current_line[255];
char* tokenized;
unsigned int number_of_rooms = 0;
memset(current_line, '\0', 255);
file_pointer_main = open_file_local_folder(room_filename, "r");
/* Loop through the lines and count the number of connections we have */
while(fgets(current_line, 255, file_pointer_main) != NULL){
tokenized = strtok(current_line, " ");
if(strcmp("CONNECTION", tokenized) == 0){
number_of_rooms++;
}
}
fclose(file_pointer_main);
return number_of_rooms;
}
bool is_room_used(char* room_name){
char num_rooms = sizeof(room_filenames) / sizeof(room_filenames[0]);
char room_name_buffer[255];
/* Loop through all files and strcmp to see if it's been used already */
int i;
for(i = 0 ; i < num_rooms ; i++){
memset(room_name_buffer, '\0', 255);
get_room_name(room_filenames[i], room_name_buffer);
/* printf("Comparing %s to %s\n", room_name, room_name_buffer); */
if(strcmp(room_name_buffer, room_name) == 0){
return true;
}
}
return false;
}
bool is_end_room(char* room_filename){
char current_line[255];
char* tokenized;
memset(current_line, '\0', 255);
file_pointer_main = open_file_local_folder(room_filename, "r");
/* Run through file until room type, check if room is end room*/
while(fgets(current_line, 255, file_pointer_main) != NULL){
tokenized = strtok(current_line, ":");
if(strcmp("ROOM TYPE", tokenized) == 0){
tokenized = strtok(NULL, " \n");
if(strcmp(tokenized, "END_ROOM") == 0){
fclose(file_pointer_main);
return true;
}
}
}
fclose(file_pointer_main);
return false;
}
void get_room_name(char* room_filename, char* room_name_buffer){
char current_line[255];
char* tokenized;
memset(current_line, '\0', 255);
file_pointer_main = open_file_local_folder(room_filename, "r");
/* Return immediately if file does not yet exist */
if(file_pointer_main == NULL){
strcpy(room_name_buffer, "___NOT_A_ROOM_NAME____");
return;
}
/* Run through file and get room name with special handling for spaces */
while(fgets(current_line, 255, file_pointer_main) != NULL){
/*strcpy(current_line_backup, current_line);*/
tokenized = strtok(current_line, ":");
bool first_entry = true;
if(strcmp("ROOM NAME", tokenized) == 0){
tokenized = strtok(NULL, " \n");
while(tokenized != NULL){
if(first_entry){
first_entry = false;
}else{
strcat(room_name_buffer, " ");
}
strcat(room_name_buffer, tokenized);
tokenized = strtok(NULL, " \n");
}
break;
}
}
fclose(file_pointer_main);
}
int get_room_index_from_name(char* room_name){
char num_rooms = sizeof(room_filenames) / sizeof(room_filenames[0]);
char room_name_buffer[255];
/* Loop through files until the room name is found, return index*/
int i;
for(i = 0 ; i < num_rooms ; i++){
memset(room_name_buffer, '\0', 255);
get_room_name(room_filenames[i], room_name_buffer);
if(strcmp(room_name_buffer, room_name) == 0){
return i;
}
}
return -1;
}
int get_used_indexes(char* room_filename, int* output_list){
char current_line[255];
char used_names[6][15];
char* tokenized;
int return_index = 0;
memset(current_line, '\0', 255);
file_pointer_main = open_file_local_folder(room_filename, "r");
/* Loop through and get names of all connections in file */
while(fgets(current_line, 255, file_pointer_main) != NULL){
tokenized = strtok(current_line, " ");
if(strcmp("CONNECTION", tokenized) == 0){
tokenized = strtok(NULL, ":");
tokenized = strtok(NULL, " \n");
bool first_entry = true;
while(tokenized != NULL){
if(first_entry){
first_entry = false;
}else{
strcat(used_names[return_index], " ");
}
strcat(used_names[return_index], tokenized);
tokenized = strtok(NULL, " \n");
}
return_index++;
}
}
fclose(file_pointer_main);
/* Get indices from names, and return */
int i;
for(i = 0 ; i < return_index ; i++){
output_list[i] = get_room_index_from_name(used_names[i]);
}
return return_index;
}
/* /////////////////////////////////// */
/* ///////// Time Functions ////////// */
/* /////////////////////////////////// */
void print_time(void){
/* Make and run the thread. Join to block until the other thread is done. */
assert(pthread_create(&time_thread_ID, NULL, get_time, NULL) == 0);
assert(pthread_join(time_thread_ID, NULL) == 0);
/* Lock and get a copy of whether time was written. Set original to false. */
pthread_mutex_lock(&time_mutex);
bool time_was_written = time_written;
time_written = false;
pthread_mutex_unlock(&time_mutex);
/* Make sure that the time was written, otherwise massive error... */
assert(time_was_written);
/* Open file with time information and print it. */
file_pointer_main = open_file_local_folder(time_file_name, "r");
assert(file_pointer_main != NULL);
printf("\n");
char c = fgetc(file_pointer_main);
while(c != EOF){
printf("%c", c);
c = fgetc(file_pointer_main);
}
printf("\n");
fclose(file_pointer_main);
/* Delete this temporary file */
delete_file_local_folder(time_file_name);
}
/* //////////////////////////////////////// */
/* ///////// Threading Functions ////////// */
/* //////////////////////////////////////// */
void* get_time(void *arguments){
time_t current_time_raw;
struct tm *time_as_struct;
char buffer_size = 50;
char buffer[buffer_size];
memset(buffer, '\0', buffer_size);
/* Get current time */
time(&current_time_raw);
time_as_struct = localtime(&current_time_raw);
/* Format per specification */
strftime(buffer, buffer_size, "%-l:%M%P, %A, %B %-e, %Y", time_as_struct);
/* Write formatted time to file */
file_pointer_time = open_file_local_folder(time_file_name, "w");
fprintf(file_pointer_time, "%s", buffer);
fclose(file_pointer_time);
/* Lock, update, and unlock mutex variable */
pthread_mutex_lock(&time_mutex);
time_written = true;
pthread_mutex_unlock(&time_mutex);
return NULL;
}
/* ///////////////////////////////////// */
/* ///////// Helper Functions ////////// */
/* ///////////////////////////////////// */
FILE *open_file_local_folder(char *file_name, char *mode){
/* Makes common concatenation of file with full path easier */
char full_path[255];
memset(full_path, '\0', 255);
strcat(full_path, rooms_directory_full);
strcat(full_path, "/");
strcat(full_path, file_name);
return fopen(full_path, mode);
}
int delete_file_local_folder(char *file_name){
/* Easy delete that handles concatenation for time file */
char full_path[255];
memset(full_path, '\0', 255);
strcat(full_path, rooms_directory_full);
strcat(full_path, "/");
strcat(full_path, file_name);
return remove(full_path);
}

View File

@@ -0,0 +1,8 @@
all: build
clean:
rm -f smallsh
build:
dos2unix smallsh.c > /dev/null 2>&1
gcc smallsh.c -o smallsh -std=c99

View File

@@ -0,0 +1,6 @@
To compile, run the below command in the folder with smallsh.c and the makefile.
make clean build
This will remove the existing compiled binary, if it exists, and then
recompile the source into a new binary executable.

View File

@@ -0,0 +1,386 @@
/////////////////////////////
////////// SMALLSH //////////
/////// Corwin Perren ///////
/////////////////////////////
//////////////////////////////////////////
////////// Includes and Defines //////////
//////////////////////////////////////////
//Includes
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <stdbool.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
//Defines
#define INPUT_LENGTH_MAX 2048
#define INPUT_ARGS_MAX 513 //Includes one extra for the program itself
#define BACKGROUND_WAIT_COUNT 100000
/////////////////////////////////////////
////////// Function Prototypes //////////
/////////////////////////////////////////
void interrupt_signal_handler(int signal_number);
void terminate_signal_handler(int signal_number);
void check_background_processes(int* status);
bool is_blank_input_string(char* input_string);
int split_input_to_array(char* input_string, char** output_array);
void clean_newline(char* input_string);
void clean_array(char** to_clean);
bool check_if_run_in_background(char** arguments_array, int* args_count);
bool check_if_output_redirect(char** arguments_array, int* args_count, \
char* output_filename);
bool check_if_input_redirect(char** arguments_array, int* args_count, \
char* input_filename);
void clean_extra_args(char** arguments_array, int args_count);
//////////////////////////
////////// Main //////////
//////////////////////////
int main() {
////////// SMALLSH Management Variables //////////
char user_input_string[INPUT_LENGTH_MAX];
int input_arg_count = 0;
char** user_input_array = malloc(INPUT_ARGS_MAX * sizeof(char*));
static int smallsh_status = 0;
//Assign initial pointers to NULL so cleaning functions are happy
//This is for user_input_array
for(int i = 0 ; i < INPUT_ARGS_MAX ; i++){
user_input_array[i] = NULL;
}
////////// SMALLSH Process Spawn Variables //////////
bool spawn_in_background = false;
bool redirect_output = false;
bool redirect_input = false;
char output_filename[INPUT_LENGTH_MAX];
char input_filename[INPUT_LENGTH_MAX];
int spawn_id = 0;
////////// SMALLSH Initialization //////////
//Assign signal handlers
signal(SIGINT, interrupt_signal_handler);
signal(SIGTERM, terminate_signal_handler);
////////// Print welcome screen //////////
printf("----------------------\n");
printf("Welcome to Small Shell\n");
printf("http://caperren.com\n");
printf("----------------------\n");
////////// Main program code //////////
while(1){
//Reset process management variables
spawn_in_background = false;
redirect_output = false;
redirect_input = false;
//Process child processes
check_background_processes(&smallsh_status);
//Print prompt
printf(": ");
fflush(stdout);
//Clear input buffer and read in new command
memset(user_input_string, '\0', INPUT_LENGTH_MAX);
fgets(user_input_string, INPUT_LENGTH_MAX, stdin);
//Check if input is blank
if(is_blank_input_string(user_input_string)){
continue;
}
//Clean off newline
clean_newline(user_input_string);
//Break input string into an array of the arguments
input_arg_count = split_input_to_array(user_input_string, \
user_input_array);
//Check what kind of input we got
if(strcmp(user_input_array[0], "exit") == 0){
//We should clean up malloc'd memory and exit
clean_array(user_input_array);
free(user_input_array);
exit(EXIT_SUCCESS);
}else if(strcmp(user_input_array[0], "status") == 0){
//Print our exit status variable, and continue
printf("exit value %d\n", WEXITSTATUS(smallsh_status));
fflush(stdout);
continue;
}else if(strcmp(user_input_array[0], "cd") == 0){
//Check if we're going to the home directory, or somewhere else
if((user_input_array[1] == NULL) || \
(strcmp(user_input_array[1], "~/") == 0) || \
(strcmp(user_input_array[1], "~") == 0)){
//Change to the user's home directory as requested
chdir(getenv("HOME"));
}else{
//Change to the user's requested directory, error is not
//accessible, or doesn't exist
int chdir_result = chdir(user_input_array[1]);
if(chdir_result == -1){
printf("Cannot change to directory \"%s\"\n", \
user_input_array[1]);
fflush(stdout);
}
}
continue;
}else if(user_input_array[0][0] == '#'){
//We got a comment line, so do nothing and continue
continue;
}
//If we've gotten here, that means the command given is one we're
//going to be spawning using an exec call.
//First check is to see whether it should be foreground or not.
spawn_in_background = check_if_run_in_background(user_input_array, \
&input_arg_count);
//Now check whether or not we need to redirect output
redirect_output = check_if_output_redirect(user_input_array, \
&input_arg_count, \
output_filename);
//Then the same, but for redirection of input from file
redirect_input = check_if_input_redirect(user_input_array, \
&input_arg_count, \
input_filename);
//Clean out these input/output args we don't want passed to our process
clean_extra_args(user_input_array, input_arg_count);
//Time to fork for our new process
spawn_id = fork();
if(spawn_id == 0){
//We're the child process, get ready to execute.
if(spawn_in_background){
//If we're supposed to be in the background, set stdin and
//stdout file descriptors for the process to /dev/null
int null_rw = open("/dev/null", O_RDWR);
int null_read = open("/dev/null", O_RDONLY);
dup2(null_read, 0);
dup2(null_rw, 1);
}
if(redirect_input){
//Even if background, if we redirect input, attempt to open
//file and pass it in
int input_fd = open(input_filename, O_RDONLY, 0644);
if(input_fd < 0){
printf("File %s cannot be accessed.\n", input_filename);
fflush(stdout);
continue;
}
dup2(input_fd, 0);
}
if(redirect_output){
//Even if background, attempt to make output file and redirect
int output_fd = open(output_filename, \
O_WRONLY | O_CREAT | O_TRUNC, 0644);
if(output_fd < 0){
printf("File %s cannot be accessed.\n", input_filename);
fflush(stdout);
continue;
}
dup2(output_fd, 1);
}
//Execute the command, including searching the path variable
execvp(user_input_array[0], user_input_array);
printf("Failed to run program: %s\n", user_input_array[0]);
fflush(stdout);
exit(EXIT_FAILURE);
}else{
//We're the parent
if(spawn_in_background){
//Print the process id, and return to prompt
printf("background pid is %d\n", spawn_id);
fflush(stdout);
}else{
//Wait for the process to die, as this is foreground
spawn_id = waitpid(spawn_id, &smallsh_status, 0);
}
}
}
exit(EXIT_SUCCESS);
}
///////////////////////////////////////////
////////// Function Declarations //////////
///////////////////////////////////////////
void interrupt_signal_handler(int signal_number){
printf("terminated by signal %d\n", signal_number);
signal(SIGINT, interrupt_signal_handler);
}
void terminate_signal_handler(int signal_number){
printf("terminated by signal %d\n", signal_number);
exit(EXIT_FAILURE);
signal(SIGTERM, terminate_signal_handler);
}
void check_background_processes(int* status){
int temp_pid = 0;
int temp_count = 0;
//Loop through a bunch of times and print out child exit statuses
while(temp_count < BACKGROUND_WAIT_COUNT){
temp_pid = waitpid(-1, status, WNOHANG);
if(temp_pid > 0){
if(WIFEXITED(*status)){
printf("process %d exited with exit value %d", temp_pid, \
WEXITSTATUS(*status));
}
if(WIFSIGNALED(*status)){
printf("process %d terminated by signal %d", temp_pid, \
WTERMSIG(*status));
}
printf("\n");
fflush(stdout);
}
temp_count++;
}
}
bool is_blank_input_string(char* input_string){
//This does a simple check as to whether we have no input on a line
int length = strlen(input_string);
char current_char = '\0';
for(int i = 0 ; i < length ; i++){
current_char = input_string[i];
if((current_char != ' ') && (current_char != '\0') && \
(current_char != '\n')){
return false;
}
}
return true;
}
int split_input_to_array(char* input_string, char** output_array){
int args_count = 0;
char* token_result;
//Clean the array first so we don't memory leak
clean_array(output_array);
for(args_count = 0 ; args_count < INPUT_ARGS_MAX ; args_count++){
//Get the current tokenizer result
if(args_count == 0){
token_result = strtok(input_string, " ");
}else{
token_result = strtok(NULL, " ");
}
//Check if we're done parsing input string
if(token_result == NULL){
break;
}
//Allocate space for next string
output_array[args_count] = malloc((strlen(token_result) + 1) * \
sizeof(char));
//Copy the current string into this allocated space
strcpy(output_array[args_count], token_result);
}
return args_count;
}
void clean_newline(char* input_string){
input_string[strlen(input_string) - 1] = '\0';
}
void clean_array(char** to_clean){
for(int i = 0 ; i < INPUT_ARGS_MAX ; i++){
if(to_clean[i] != NULL){
free(to_clean[i]);
to_clean[i] = NULL;
}else{
break;
}
}
}
bool check_if_run_in_background(char** arguments_array, int* args_count){
if(strcmp(arguments_array[*args_count-1], "&") == 0){
*args_count -= 1;
return true;
}else{
return false;
}
}
bool check_if_output_redirect(char** arguments_array, int* args_count, \
char* output_filename){
memset(output_filename, '\0', INPUT_LENGTH_MAX);
//Check for output redirect. If found, copy the filename and lower
//argument count so we don't process it later
for(int i = 0 ; i < *args_count ; i++){
if(strcmp(arguments_array[i], ">") == 0){
strcpy(output_filename, arguments_array[i + 1]);
*args_count -= 2;
return true;
}
}
return false;
}
bool check_if_input_redirect(char** arguments_array, int* args_count, \
char* input_filename){
memset(input_filename, '\0', INPUT_LENGTH_MAX);
//Check for input redirect. If found, copy the filename and lower
//argument count so we don't process it later
for(int i = 0 ; i < *args_count ; i++){
if(strcmp(arguments_array[i], "<") == 0){
strcpy(input_filename, arguments_array[i + 1]);
*args_count -= 2;
return true;
}
}
return false;
}
void clean_extra_args(char** arguments_array, int args_count){
//This clean up the rest on the input line, after our redirects if they
//happened
for(int i = args_count ; i < INPUT_ARGS_MAX ; i++){
if(arguments_array[i] != NULL){
free(arguments_array[i]);
arguments_array[i] = NULL;
}else{
break;
}
}
}

View File

@@ -0,0 +1,3 @@
#!/bin/bash
make clean
make build

View File

@@ -0,0 +1,51 @@
/*
* File: keygen.c
* Author: Corwin Perren
*
* Created on November 29, 2016, 7:27 PM
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define PROGRAM_SUCCESS 0
#define PROGRAM_FAILURE 1
#define ASCII_START 65
int main(int argc, char** argv) {
//Some error handling for bad inputs
if(argc < 2){
fprintf(stderr, "No arguments entered. Please try again.\n");
exit(PROGRAM_FAILURE);
}else if (argc > 2){
fprintf(stderr, "Extra arguments entered. Ignoring all but the "
"first.\n");
}else if(atoi(argv[1]) <= 0){
fprintf(stderr, "Key length too small. Number must be greater than "
"zero.\n");
exit(PROGRAM_FAILURE);
}
time_t t;
srand((unsigned) time(&t));
//Get the number passed in as an argument
int key_length = atoi(argv[1]);
//Loop through and output a new character based on the number generated
for(int i = 0 ; i < key_length ; i++){
int rand_char = rand() % 27;
if(rand_char == 26){
printf(" ");
}else{
printf("%c", (char)(rand_char + ASCII_START));
}
}
//Print the final newline and exit successfully.
printf("\n");
exit(PROGRAM_SUCCESS);
}

View File

@@ -0,0 +1,15 @@
all: build
clean:
rm -f otp_dec
rm -f otp_dec_d
rm -f otp_enc
rm -f otp_enc_d
rm -f keygen
build:
gcc otp_dec.c -o otp_dec -std=c99
gcc otp_dec_d.c -o otp_dec_d -std=c99
gcc otp_enc.c -o otp_enc -std=c99
gcc otp_enc_d.c -o otp_enc_d -std=c99
gcc keygen.c -o keygen -std=c99

View File

@@ -0,0 +1,296 @@
/*
* File: otp_enc.c
* Author: Corwin Perren
*
* Created on November 29, 2016, 7:26 PM
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#define PROGRAM_SUCCESS 0
#define PROGRAM_FAILURE 1
#define PROGRAM_FAILURE_PORT 2
#define PORT_MAX 65535
#define PORT_MIN 0
#define OTP_ENC_IDENT "#"
#define OTP_DEC_IDENT "$"
#define TEXT_DONE "@@"
#define OTP_FAILURE "%"
#define OTP_CONTINUE "&"
#define LETTER_OPTIONS 27
int letter_number_assignment[LETTER_OPTIONS][2] = {
'A', 10,
'B', 11,
'C', 12,
'D', 13,
'E', 14,
'F', 15,
'G', 16,
'H', 17,
'I', 18,
'J', 19,
'K', 20,
'L', 21,
'M', 22,
'N', 23,
'O', 24,
'P', 25,
'Q', 26,
'R', 0,
'S', 1,
'T', 2,
'U', 3,
'V', 4,
'W', 5,
'X', 6,
'Y', 7,
'Z', 8,
' ', 9
};
int get_mapped_num_from_char(char letter);
int main(int argc, char** argv) {
int comms_sfd;
unsigned long int comms_port_number; //0 - 65535
struct hostent *server;
struct sockaddr_in server_address;
FILE *input_file;
FILE *key_file;
//Verify correct number of arguments
if(argc < 4){
fprintf(stderr, "Not enough arguments provided. Exiting...\n");
fprintf(stderr, "Correct usage: "
"%s input_file key_file port\n", argv[0]);
exit(PROGRAM_FAILURE);
}else if(argc > 4){
fprintf(stderr, "Extra arguments entered. Ignoring all but the first "
"three.\n");
}
//Get port number, and make sure it's valid
comms_port_number = atoi(argv[3]);
if((comms_port_number > PORT_MAX) || (comms_port_number < PORT_MIN)){
fprintf(stderr, "Port out of range! Please choose a different port! "
"Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Open the files
input_file = fopen(argv[1], "r");
key_file = fopen(argv[2], "r");
//Make sure they opened successfully
if(input_file == NULL){
fprintf(stderr, "Input file does not exist or cannot be read! "
"Exiting...\n");
exit(PROGRAM_FAILURE);
}else if(key_file == NULL){
fprintf(stderr, "Key file does not exist or cannot be read! "
"Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Read in input file
char* temp_buffer = malloc(sizeof(char) * 1000000);
memset(temp_buffer, '\0', sizeof(char) * 1000000);
fgets(temp_buffer, 1000000, input_file);
char* input_text = malloc(sizeof(char) * (strlen(temp_buffer) + 1));
memset(input_text, '\0', sizeof(char) * (strlen(temp_buffer) + 1));
strcpy(input_text, temp_buffer);
//Remove input file newline
int input_str_len = strlen(input_text);
if(input_text[input_str_len - 1] == '\n'){
input_text[input_str_len - 1] = '\0';
}
//Read in key file
memset(temp_buffer, '\0', sizeof(char) * 1000000);
fgets(temp_buffer, 1000000, key_file);
char* key_text = malloc(sizeof(char) * (strlen(temp_buffer) + 1));
memset(key_text, '\0', sizeof(char) * (strlen(temp_buffer) + 1));
strcpy(key_text, temp_buffer);
//Remove input file newline
input_str_len = strlen(key_text);
if(key_text[input_str_len - 1] == '\n'){
key_text[input_str_len - 1] = '\0';
}
free(temp_buffer);
//Exit as error is input_string is longer than the key
if(strlen(input_text) > strlen(key_text)){
fprintf(stderr, "Key file too small. Please try again with larger "
"file. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Check files for bad characters
for(unsigned long i = 0 ; i < strlen(input_text) ; i ++){
if(get_mapped_num_from_char(input_text[i]) == -1){
fprintf(stderr, "Bad characters in input text. Exiting...\n");
exit(PROGRAM_FAILURE);
}
}
for(unsigned long i = 0 ; i < strlen(key_text) ; i ++){
if(get_mapped_num_from_char(key_text[i]) == -1){
fprintf(stderr, "Bad characters in key text. Exiting...\n");
exit(PROGRAM_FAILURE);
}
}
//Create listening socket, check if created successfully
comms_sfd = socket(AF_INET, SOCK_STREAM, 0);
if(comms_sfd < 0){
fprintf(stderr, "Could not create comms socket! Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Get localhost as server, check if valid
server = gethostbyname("localhost");
if(server == NULL){
fprintf(stderr, "localhost is not a valid host! Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Set up comms parameters for the server we're connecting to.
memset((char *)&server_address, '\0', sizeof(server_address));
server_address.sin_port = htons(comms_port_number);
memcpy(&server_address.sin_addr, server->h_addr_list[0], server->h_length);
server_address.sin_family = AF_INET;
//Make the server connection and verify it didn't fail.
int connect_result = connect(comms_sfd, \
(struct sockaddr *)&server_address, \
sizeof(server_address));
if(connect_result < 0){
fprintf(stderr, "Connection failed! Is the port correct? Exiting...\n");
exit(PROGRAM_FAILURE_PORT);
}
//Set up writing and reading variables
int read_return;
int write_return;
unsigned int concat_index = 0;
char read_buffer[10];
char* concat_buffer = malloc(sizeof(char) * 1000000);
memset(read_buffer, '\0', 1);
memset(concat_buffer, '\0', sizeof(char) * 1000000);
//Write message to tell the daemon what program we are
write_return = write(comms_sfd, OTP_DEC_IDENT TEXT_DONE, 3);
if(write_return < 0){
fprintf(stderr, "Failed to write data. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Read the servers response to our message
while(strstr(concat_buffer, TEXT_DONE) == NULL){
read_return = read(comms_sfd, read_buffer, 1);
if(read_return != -1){
concat_buffer[concat_index] = read_buffer[0];
concat_index++;
}
}
if(strstr(concat_buffer, OTP_CONTINUE TEXT_DONE) != NULL){
//In this case, the response from the server is to continue
//We write the input text to the daemon
write_return = write(comms_sfd, input_text, strlen(input_text));
if(write_return < 0){
fprintf(stderr, "Failed to write data. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Then we write the ending characters
write_return = write(comms_sfd, TEXT_DONE, 2);
if(write_return < 0){
fprintf(stderr, "Failed to write data. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Now we write the key file to the daemon
write_return = write(comms_sfd, key_text, strlen(key_text));
if(write_return < 0){
fprintf(stderr, "Failed to write data. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//And the ending characters again
write_return = write(comms_sfd, TEXT_DONE, 2);
if(write_return < 0){
fprintf(stderr, "Failed to write data. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Reset variables to receive data
concat_index = 0;
memset(read_buffer, '\0', 10);
memset(concat_buffer, '\0', sizeof(char) * 1000000);
//Read in the response from the daemon
while(strstr(concat_buffer, TEXT_DONE) == NULL){
read_return = read(comms_sfd, read_buffer, 1);
if(read_return != -1){
concat_buffer[concat_index] = read_buffer[0];
concat_index++;
}
}
//Null out our marker characters
int input_string_length = strlen(concat_buffer);
concat_buffer[input_string_length-1] = '\0';
concat_buffer[input_string_length-2] = '\0';
//Print out the cleaned up response from the daemon
for(int i = 0 ; i < strlen(concat_buffer) ; i++){
printf("%c", concat_buffer[i]);
}
printf("\n");
}else if(strstr(concat_buffer, OTP_FAILURE TEXT_DONE) != NULL){
//Print an error if we try to connect to the wrong daemon
fprintf(stderr, "OTP_DEC may NOT connect to OTP_ENC_D. Exiting...\n");
exit(PROGRAM_FAILURE);
}else{
//Print an error if we get erroneous data.
fprintf(stderr, "Got bad data. Exiting...\n");
exit(PROGRAM_FAILURE);
}
exit(PROGRAM_SUCCESS);
}
int get_mapped_num_from_char(char letter){
for(int i = 0 ; i < LETTER_OPTIONS ; i++){
if(letter == letter_number_assignment[i][0]){
return letter_number_assignment[i][1];
}
}
return -1;
}

View File

@@ -0,0 +1,309 @@
/*
* File: otp_enc_d.c
* Author: Corwin Perren
*
* Created on November 29, 2016, 7:26 PM
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/wait.h>
#define PROGRAM_SUCCESS 0
#define PROGRAM_FAILURE 1
#define PORT_MAX 65535
#define PORT_MIN 0
#define OTP_ENC_IDENT "#"
#define OTP_DEC_IDENT "$"
#define TEXT_DONE "@@"
#define OTP_FAILURE "%"
#define OTP_CONTINUE "&"
#define LETTER_OPTIONS 27
int letter_number_assignment[LETTER_OPTIONS][2] = {
'A', 10,
'B', 11,
'C', 12,
'D', 13,
'E', 14,
'F', 15,
'G', 16,
'H', 17,
'I', 18,
'J', 19,
'K', 20,
'L', 21,
'M', 22,
'N', 23,
'O', 24,
'P', 25,
'Q', 26,
'R', 0,
'S', 1,
'T', 2,
'U', 3,
'V', 4,
'W', 5,
'X', 6,
'Y', 7,
'Z', 8,
' ', 9
};
int get_mapped_num_from_char(char letter);
char get_mapped_char_from_num(int number);
char encode_character(char letter, char key_letter);
char decode_character(char input_letter, char key_letter);
int main(int argc, char** argv) {
int listen_sfd; //sfd == socked_file_descriptor
int comms_sfd;
unsigned long int listen_port_number; //0 - 65535
socklen_t client_length;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
//Check if we have enough arguments, error and exit if not.
if(argc < 2){
fprintf(stderr, "No port provided! Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Create our listening socket, check if created successfully
listen_sfd = socket(AF_INET, SOCK_STREAM, 0);
if(listen_sfd < 0){
fprintf(stderr, "Could not create listening socket! Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Get port number, and make sure it's valid
listen_port_number = atoi(argv[1]);
if((listen_port_number > PORT_MAX) || (listen_port_number < PORT_MIN)){
fprintf(stderr, "Port out of range! Please choose a different port! "
"Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Set up listening parameters
memset((char *)&server_address, '\0', sizeof(server_address));
server_address.sin_port = htons(listen_port_number);
server_address.sin_addr.s_addr = INADDR_ANY;
server_address.sin_family = AF_INET;
//Bind server to settings set above, let system know we're ready
int bind_result = bind(listen_sfd, (struct sockaddr *)&server_address, \
sizeof(server_address));
if(bind_result < 0){
fprintf(stderr, "Failed to bind listening port! "
"Please choose a different port! Exiting...\n");
exit(PROGRAM_FAILURE);
}
while(1){
//Call waitpid to kill off any zombie processes. Don't let it block.
static int process_status;
waitpid(-1, &process_status, WNOHANG);
//Listen to the port, and allow up to five connections
listen(listen_sfd, 5); //Listen to the port
//Block until a valid connection is made, then accept it.
//Also make sure it's accepted correctly
socklen_t client_length = sizeof(client_address);
comms_sfd = accept(listen_sfd, (struct sockaddr *) &client_address, \
&client_length);
if (comms_sfd < 0){
fprintf(stderr, "Client accept failed. Trying next "
"connection...\n");
}else{
//We've made a valid connection, so spawn off a new process to
//handle it to free up the main thread for accepting a new client.
pid_t spawned_pid;
spawned_pid = fork();
//Only run the child code if it's a child process
if(spawned_pid == 0){
//Initialize read write variables
int read_return;
int write_return;
unsigned int concat_index = 0;
char read_buffer[10];
char* concat_buffer = malloc(sizeof(char) * 1000000);
memset(read_buffer, '\0', 10);
memset(concat_buffer, '\0', sizeof(char) * 1000000);
//Read initial message telling us who the client is
while(strstr(concat_buffer, TEXT_DONE) == NULL){
read_return = read(comms_sfd, read_buffer, 1);
if(read_return != -1){
concat_buffer[concat_index] = read_buffer[0];
concat_index++;
}
}
//Choose a response appropriate for who is communicating
if(strstr(concat_buffer, OTP_DEC_IDENT TEXT_DONE) != NULL){
//In this case, the client/server match and we can continue
//Write a message to the client that we'll continue
write_return = write(comms_sfd, OTP_CONTINUE TEXT_DONE, 3);
if(write_return < 0){
fprintf(stderr, "Failed to alert sender. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Reset variables to receive data
concat_index = 0;
memset(read_buffer, '\0', 10);
memset(concat_buffer, '\0', sizeof(char) * 1000000);
//Read in first input file from client
while(strstr(concat_buffer, TEXT_DONE) == NULL){
read_return = read(comms_sfd, read_buffer, 1);
if(read_return != -1){
concat_buffer[concat_index] = read_buffer[0];
concat_index++;
}
}
//Null out our marker characters
int input_string_length = strlen(concat_buffer);
concat_buffer[input_string_length-1] = '\0';
concat_buffer[input_string_length-2] = '\0';
//Store input text for later use
char* input_text = malloc(sizeof(char) * \
(strlen(concat_buffer) + 1));
memset(input_text, '\0', sizeof(char) * \
(strlen(concat_buffer) + 1));
strcpy(input_text, concat_buffer);
//Reset variables to receive data
concat_index = 0;
memset(read_buffer, '\0', 10);
memset(concat_buffer, '\0', sizeof(char) * 1000000);
//Read in key file from client
while(strstr(concat_buffer, TEXT_DONE) == NULL){
read_return = read(comms_sfd, read_buffer, 1);
if(read_return != -1){
concat_buffer[concat_index] = read_buffer[0];
concat_index++;
}
}
//Null out our marker characters
input_string_length = strlen(concat_buffer);
concat_buffer[input_string_length-1] = '\0';
concat_buffer[input_string_length-2] = '\0';
//Store key file for later
char* key_text = malloc(sizeof(char) * \
(strlen(concat_buffer) + 1));
memset(key_text, '\0', sizeof(char) * \
(strlen(concat_buffer) + 1));
strcpy(key_text, concat_buffer);
free(concat_buffer);
//Write the decrypted data to the client
for(unsigned long int i = 0 ; i < strlen(input_text) ;\
i++){
char new_char = decode_character(input_text[i], \
key_text[i]);
write_return = write(comms_sfd, &new_char, 1);
}
//Write the end of text marker
write_return = write(comms_sfd, TEXT_DONE, 2);
if(write_return < 0){
fprintf(stderr, "Failed to alert sender. Exiting...\n");
exit(PROGRAM_FAILURE);
}
}else if(strstr(concat_buffer, OTP_ENC_IDENT TEXT_DONE) \
!= NULL){
//In this case, client and server don't match
//Write failure message so client exits
write_return = write(comms_sfd, OTP_FAILURE TEXT_DONE, 3);
if(write_return < 0){
fprintf(stderr, "Failed to alert sender. Exiting...\n");
}
exit(PROGRAM_FAILURE);
}else{
//Error and messages for erroneous data
fprintf(stderr, "Got bad data. Alerting sender and "
"exiting...\n");
write_return = write(comms_sfd, OTP_FAILURE TEXT_DONE, 3);
if(write_return < 0){
fprintf(stderr, "Failed to alert sender. Exiting...\n");
}
exit(PROGRAM_FAILURE);
}
//Since this is a child process, once it's done it should die.
exit(PROGRAM_SUCCESS);
}
}
}
close(listen_sfd);
exit(PROGRAM_SUCCESS);
}
int get_mapped_num_from_char(char letter){
for(int i = 0 ; i < LETTER_OPTIONS ; i++){
if(letter == letter_number_assignment[i][0]){
return letter_number_assignment[i][1];
}
}
return -1;
}
char get_mapped_char_from_num(int number){
for(int i = 0 ; i < LETTER_OPTIONS ; i++){
if(number == letter_number_assignment[i][1]){
return letter_number_assignment[i][0];
}
}
return -1;
}
char encode_character(char input_letter, char key_letter){
int letter_mapped = get_mapped_num_from_char(input_letter);
int key_mapped = get_mapped_num_from_char(key_letter);
int summed = (letter_mapped + key_mapped);
if(summed >= LETTER_OPTIONS){
summed -= LETTER_OPTIONS;
}
return get_mapped_char_from_num(summed);
}
char decode_character(char input_letter, char key_letter){
int letter_mapped = get_mapped_num_from_char(input_letter);
int key_mapped = get_mapped_num_from_char(key_letter);
int subbed = (letter_mapped - key_mapped);
if(subbed < 0){
subbed += LETTER_OPTIONS;
}
return get_mapped_char_from_num(subbed);
}

View File

@@ -0,0 +1,294 @@
/*
* File: otp_enc.c
* Author: Corwin Perren
*
* Created on November 29, 2016, 7:26 PM
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#define PROGRAM_SUCCESS 0
#define PROGRAM_FAILURE 1
#define PROGRAM_FAILURE_PORT 2
#define PORT_MAX 65535
#define PORT_MIN 0
#define OTP_ENC_IDENT "#"
#define OTP_DEC_IDENT "$"
#define TEXT_DONE "@@"
#define OTP_FAILURE "%"
#define OTP_CONTINUE "&"
#define LETTER_OPTIONS 27
int letter_number_assignment[LETTER_OPTIONS][2] = {
'A', 10,
'B', 11,
'C', 12,
'D', 13,
'E', 14,
'F', 15,
'G', 16,
'H', 17,
'I', 18,
'J', 19,
'K', 20,
'L', 21,
'M', 22,
'N', 23,
'O', 24,
'P', 25,
'Q', 26,
'R', 0,
'S', 1,
'T', 2,
'U', 3,
'V', 4,
'W', 5,
'X', 6,
'Y', 7,
'Z', 8,
' ', 9
};
int get_mapped_num_from_char(char letter);
int main(int argc, char** argv) {
int comms_sfd;
unsigned long int comms_port_number; //0 - 65535
struct hostent *server;
struct sockaddr_in server_address;
FILE *input_file;
FILE *key_file;
//Verify correct number of arguments
if(argc < 4){
fprintf(stderr, "Not enough arguments provided. Exiting...\n");
fprintf(stderr, "Correct usage: "
"%s input_file key_file port\n", argv[0]);
exit(PROGRAM_FAILURE);
}else if(argc > 4){
fprintf(stderr, "Extra arguments entered. Ignoring all but the first "
"three.\n");
}
//Get port number, and make sure it's valid
comms_port_number = atoi(argv[3]);
if((comms_port_number > PORT_MAX) || (comms_port_number < PORT_MIN)){
fprintf(stderr, "Port out of range! Please choose a different port! "
"Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Open the files
input_file = fopen(argv[1], "r");
key_file = fopen(argv[2], "r");
//Make sure they opened successfully
if(input_file == NULL){
fprintf(stderr, "Input file does not exist or cannot be read! "
"Exiting...\n");
exit(PROGRAM_FAILURE);
}else if(key_file == NULL){
fprintf(stderr, "Key file does not exist or cannot be read! "
"Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Read in input file
char* temp_buffer = malloc(sizeof(char) * 1000000);
memset(temp_buffer, '\0', sizeof(char) * 1000000);
fgets(temp_buffer, 1000000, input_file);
char* input_text = malloc(sizeof(char) * (strlen(temp_buffer) + 1));
memset(input_text, '\0', sizeof(char) * (strlen(temp_buffer) + 1));
strcpy(input_text, temp_buffer);
//Remove input file newline
int input_str_len = strlen(input_text);
if(input_text[input_str_len - 1] == '\n'){
input_text[input_str_len - 1] = '\0';
}
//Read in key file
memset(temp_buffer, '\0', sizeof(char) * 1000000);
fgets(temp_buffer, 1000000, key_file);
char* key_text = malloc(sizeof(char) * (strlen(temp_buffer) + 1));
memset(key_text, '\0', sizeof(char) * (strlen(temp_buffer) + 1));
strcpy(key_text, temp_buffer);
//Remove input file newline
input_str_len = strlen(key_text);
if(key_text[input_str_len - 1] == '\n'){
key_text[input_str_len - 1] = '\0';
}
free(temp_buffer);
//Exit as error is input_string is longer than the key
if(strlen(input_text) > strlen(key_text)){
fprintf(stderr, "Key file too small. Please try again with larger "
"file. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Check files for bad characters
for(unsigned long i = 0 ; i < strlen(input_text) ; i ++){
if(get_mapped_num_from_char(input_text[i]) == -1){
fprintf(stderr, "Bad characters in input text. Exiting...\n");
exit(PROGRAM_FAILURE);
}
}
for(unsigned long i = 0 ; i < strlen(key_text) ; i ++){
if(get_mapped_num_from_char(key_text[i]) == -1){
fprintf(stderr, "Bad characters in key text. Exiting...\n");
exit(PROGRAM_FAILURE);
}
}
//Create listening socket, check if created successfully
comms_sfd = socket(AF_INET, SOCK_STREAM, 0);
if(comms_sfd < 0){
fprintf(stderr, "Could not create comms socket! Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Get localhost as server, check if valid
server = gethostbyname("localhost");
if(server == NULL){
fprintf(stderr, "localhost is not a valid host! Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Set up comms parameters for the server we're connecting to.
memset((char *)&server_address, '\0', sizeof(server_address));
server_address.sin_port = htons(comms_port_number);
memcpy(&server_address.sin_addr, server->h_addr_list[0], server->h_length);
server_address.sin_family = AF_INET;
//Make the server connection and verify it didn't fail.
int connect_result = connect(comms_sfd, \
(struct sockaddr *)&server_address, \
sizeof(server_address));
if(connect_result < 0){
fprintf(stderr, "Connection failed! Is the port correct? Exiting...\n");
exit(PROGRAM_FAILURE_PORT);
}
//Set up writing and reading variables
int read_return;
int write_return;
unsigned int concat_index = 0;
char read_buffer[10];
char* concat_buffer = malloc(sizeof(char) * 1000000);
memset(read_buffer, '\0', 1);
memset(concat_buffer, '\0', sizeof(char) * 1000000);
//Write message to tell the daemon what program we are
write_return = write(comms_sfd, OTP_ENC_IDENT TEXT_DONE, 3);
if(write_return < 0){
fprintf(stderr, "Failed to write data. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Read the servers response to our message
while(strstr(concat_buffer, TEXT_DONE) == NULL){
read_return = read(comms_sfd, read_buffer, 1);
if(read_return != -1){
concat_buffer[concat_index] = read_buffer[0];
concat_index++;
}
}
if(strstr(concat_buffer, OTP_CONTINUE TEXT_DONE) != NULL){
//In this case, the response from the server is to continue
//We write the input text to the daemon
write_return = write(comms_sfd, input_text, strlen(input_text));
if(write_return < 0){
fprintf(stderr, "Failed to write data. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Then we write the ending characters
write_return = write(comms_sfd, TEXT_DONE, 2);
if(write_return < 0){
fprintf(stderr, "Failed to write data. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Now we write the key file to the daemon
write_return = write(comms_sfd, key_text, strlen(key_text));
if(write_return < 0){
fprintf(stderr, "Failed to write data. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//And the ending characters again
write_return = write(comms_sfd, TEXT_DONE, 2);
if(write_return < 0){
fprintf(stderr, "Failed to write data. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Reset variables to receive data
concat_index = 0;
memset(read_buffer, '\0', 10);
memset(concat_buffer, '\0', sizeof(char) * 1000000);
//Read in the response from the daemon
while(strstr(concat_buffer, TEXT_DONE) == NULL){
read_return = read(comms_sfd, read_buffer, 1);
if(read_return != -1){
concat_buffer[concat_index] = read_buffer[0];
concat_index++;
}
}
//Null out our marker characters
int input_string_length = strlen(concat_buffer);
concat_buffer[input_string_length-1] = '\0';
concat_buffer[input_string_length-2] = '\0';
//Print out the cleaned up response from the daemon
for(int i = 0 ; i < strlen(concat_buffer) ; i++){
printf("%c", concat_buffer[i]);
}
printf("\n");
}else if(strstr(concat_buffer, OTP_FAILURE TEXT_DONE) != NULL){
//Print an error if we try to connect to the wrong daemon
fprintf(stderr, "OTP_ENC may NOT connect to OTP_DEC_D. Exiting...\n");
exit(PROGRAM_FAILURE);
}else{
//Print an error if we get erroneous data.
fprintf(stderr, "Got bad data. Exiting...\n");
exit(PROGRAM_FAILURE);
}
exit(PROGRAM_SUCCESS);
}
int get_mapped_num_from_char(char letter){
for(int i = 0 ; i < LETTER_OPTIONS ; i++){
if(letter == letter_number_assignment[i][0]){
return letter_number_assignment[i][1];
}
}
return -1;
}

View File

@@ -0,0 +1,310 @@
/*
* File: otp_enc_d.c
* Author: Corwin Perren
*
* Created on November 29, 2016, 7:26 PM
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/wait.h>
#define PROGRAM_SUCCESS 0
#define PROGRAM_FAILURE 1
#define PORT_MAX 65535
#define PORT_MIN 0
#define OTP_ENC_IDENT "#"
#define OTP_DEC_IDENT "$"
#define TEXT_DONE "@@"
#define OTP_FAILURE "%"
#define OTP_CONTINUE "&"
#define LETTER_OPTIONS 27
int letter_number_assignment[LETTER_OPTIONS][2] = {
'A', 10,
'B', 11,
'C', 12,
'D', 13,
'E', 14,
'F', 15,
'G', 16,
'H', 17,
'I', 18,
'J', 19,
'K', 20,
'L', 21,
'M', 22,
'N', 23,
'O', 24,
'P', 25,
'Q', 26,
'R', 0,
'S', 1,
'T', 2,
'U', 3,
'V', 4,
'W', 5,
'X', 6,
'Y', 7,
'Z', 8,
' ', 9
};
int get_mapped_num_from_char(char letter);
char get_mapped_char_from_num(int number);
char encode_character(char letter, char key_letter);
char decode_character(char input_letter, char key_letter);
int main(int argc, char** argv) {
int listen_sfd; //sfd == socked_file_descriptor
int comms_sfd;
unsigned long int listen_port_number; //0 - 65535
socklen_t client_length;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
//Check if we have enough arguments, error and exit if not.
if(argc < 2){
fprintf(stderr, "No port provided! Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Create our listening socket, check if created successfully
listen_sfd = socket(AF_INET, SOCK_STREAM, 0);
if(listen_sfd < 0){
fprintf(stderr, "Could not create listening socket! Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Get port number, and make sure it's valid
listen_port_number = atoi(argv[1]);
if((listen_port_number > PORT_MAX) || (listen_port_number < PORT_MIN)){
fprintf(stderr, "Port out of range! Please choose a different port! "
"Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Set up listening parameters
memset((char *)&server_address, '\0', sizeof(server_address));
server_address.sin_port = htons(listen_port_number);
server_address.sin_addr.s_addr = INADDR_ANY;
server_address.sin_family = AF_INET;
//Bind server to settings set above, let system know we're ready
int bind_result = bind(listen_sfd, (struct sockaddr *)&server_address, \
sizeof(server_address));
if(bind_result < 0){
fprintf(stderr, "Failed to bind listening port! "
"Please choose a different port! Exiting...\n");
exit(PROGRAM_FAILURE);
}
while(1){
//Call waitpid to kill off any zombie processes. Don't let it block.
static int process_status;
waitpid(-1, &process_status, WNOHANG);
//Listen to the port, and allow up to five connections
listen(listen_sfd, 5); //Listen to the port
//Block until a valid connection is made, then accept it.
//Also make sure it's accepted correctly
socklen_t client_length = sizeof(client_address);
comms_sfd = accept(listen_sfd, (struct sockaddr *) &client_address, \
&client_length);
if (comms_sfd < 0){
fprintf(stderr, "Client accept failed. Trying next "
"connection...\n");
}else{
//We've made a valid connection, so spawn off a new process to
//handle it to free up the main thread for accepting a new client.
pid_t spawned_pid;
spawned_pid = fork();
//Only run the child code if it's a child process
if(spawned_pid == 0){
//Initialize read write variables
int read_return;
int write_return;
unsigned int concat_index = 0;
char read_buffer[10];
char* concat_buffer = malloc(sizeof(char) * 1000000);
memset(read_buffer, '\0', 10);
memset(concat_buffer, '\0', sizeof(char) * 1000000);
//Read initial message telling us who the client is
while(strstr(concat_buffer, TEXT_DONE) == NULL){
read_return = read(comms_sfd, read_buffer, 1);
if(read_return != -1){
concat_buffer[concat_index] = read_buffer[0];
concat_index++;
}
}
//Choose a response appropriate for who is communicating
if(strstr(concat_buffer, OTP_ENC_IDENT TEXT_DONE) != NULL){
//In this case, the client/server match and we can continue
//Write a message to the client that we'll continue
write_return = write(comms_sfd, OTP_CONTINUE TEXT_DONE, 3);
if(write_return < 0){
fprintf(stderr, "Failed to alert sender. Exiting...\n");
exit(PROGRAM_FAILURE);
}
//Reset variables to receive data
concat_index = 0;
memset(read_buffer, '\0', 10);
memset(concat_buffer, '\0', sizeof(char) * 1000000);
//Read in first input file from client
while(strstr(concat_buffer, TEXT_DONE) == NULL){
read_return = read(comms_sfd, read_buffer, 1);
if(read_return != -1){
concat_buffer[concat_index] = read_buffer[0];
concat_index++;
}
}
//Null out our marker characters
int input_string_length = strlen(concat_buffer);
concat_buffer[input_string_length-1] = '\0';
concat_buffer[input_string_length-2] = '\0';
//Store this for later use
char* input_text = malloc(sizeof(char) * \
(strlen(concat_buffer) + 1));
memset(input_text, '\0', sizeof(char) * \
(strlen(concat_buffer) + 1));
strcpy(input_text, concat_buffer);
//Reset variables to receive data
concat_index = 0;
memset(read_buffer, '\0', 10);
memset(concat_buffer, '\0', sizeof(char) * 1000000);
//Read in key file from client
while(strstr(concat_buffer, TEXT_DONE) == NULL){
read_return = read(comms_sfd, read_buffer, 1);
if(read_return != -1){
concat_buffer[concat_index] = read_buffer[0];
concat_index++;
}
}
//Null out our marker characters
input_string_length = strlen(concat_buffer);
concat_buffer[input_string_length-1] = '\0';
concat_buffer[input_string_length-2] = '\0';
//Store key file for later
char* key_text = malloc(sizeof(char) * \
(strlen(concat_buffer) + 1));
memset(key_text, '\0', sizeof(char) * \
(strlen(concat_buffer) + 1));
strcpy(key_text, concat_buffer);
free(concat_buffer);
//Write the encrypted data to the client
for(unsigned long int i = 0 ; i < strlen(input_text) ;\
i++){
char new_char = encode_character(input_text[i], \
key_text[i]);
write_return = write(comms_sfd, &new_char, 1);
}
//Write the end of text marker
write_return = write(comms_sfd, TEXT_DONE, 2);
if(write_return < 0){
fprintf(stderr, "Failed to alert sender. Exiting...\n");
exit(PROGRAM_FAILURE);
}
}else if(strstr(concat_buffer, OTP_DEC_IDENT TEXT_DONE) \
!= NULL){
//In this case, client and server don't match
//Write failure message so client exits
write_return = write(comms_sfd, OTP_FAILURE TEXT_DONE, 3);
if(write_return < 0){
fprintf(stderr, "Failed to alert sender. Exiting...\n");
}
exit(PROGRAM_FAILURE);
}else{
//Error and messages for erroneous data
fprintf(stderr, "Got bad data. Alerting sender and "
"exiting...\n");
write_return = write(comms_sfd, OTP_FAILURE TEXT_DONE, 3);
if(write_return < 0){
fprintf(stderr, "Failed to alert sender. Exiting...\n");
}
exit(PROGRAM_FAILURE);
}
//Since this is a child process, once it's done it should die.
exit(PROGRAM_SUCCESS);
}
}
}
close(listen_sfd);
exit(PROGRAM_SUCCESS);
}
int get_mapped_num_from_char(char letter){
for(int i = 0 ; i < LETTER_OPTIONS ; i++){
if(letter == letter_number_assignment[i][0]){
return letter_number_assignment[i][1];
}
}
return -1;
}
char get_mapped_char_from_num(int number){
for(int i = 0 ; i < LETTER_OPTIONS ; i++){
if(number == letter_number_assignment[i][1]){
return letter_number_assignment[i][0];
}
}
return -1;
}
char encode_character(char input_letter, char key_letter){
int letter_mapped = get_mapped_num_from_char(input_letter);
int key_mapped = get_mapped_num_from_char(key_letter);
int summed = (letter_mapped + key_mapped);
if(summed >= LETTER_OPTIONS){
summed -= LETTER_OPTIONS;
}
return get_mapped_char_from_num(summed);
}
char decode_character(char input_letter, char key_letter){
int letter_mapped = get_mapped_num_from_char(input_letter);
int key_mapped = get_mapped_num_from_char(key_letter);
int subbed = (letter_mapped - key_mapped);
if(subbed < 0){
subbed += LETTER_OPTIONS;
}
return get_mapped_char_from_num(subbed);
}

View File

@@ -0,0 +1,142 @@
#!/bin/bash
# FYI, this command removes file abc if it is empty: [ -s abc ] || rm -f abc
usage="usage: $0 encryptionport decryptionport"
#use the standard version of echo
echo=/bin/echo
#Make sure we have the right number of arguments
if test $# -gt 2 -o $# -lt 2
then
${echo} $usage 1>&2
exit 1
fi
#Clean up any previous runs
${echo} '#Initializing - Cleaning up - ignore Operation Not Permitted errors'
killall -q -u $USER otp_*
rm -f ciphertext*
rm -f plaintext*_*
rm -f key20
rm -f key70000
#Record the ports passed in
encport=$1
decport=$2
#Run the daemons
otp_enc_d $encport &
otp_dec_d $decport &
sleep 5
${echo}
${echo} '#-----------------------------------------'
${echo} '#START OF GRADING SCRIPT'
${echo} '#keygen 20 > key20'
keygen 20 > key20
${echo} "#5 POINTS: key20 must exist"
[ -s key20 ] || rm -f key20
if [ -f key20 ]; then ${echo} 'key20 exists!'; else ${echo} 'key20 DOES NOT EXIST'; fi
${echo}
${echo} "#-----------------------------------------"
${echo} "#5 POINTS: Number of characters in key20, should be 21:"
wc -m key20
${echo}
${echo} "#-----------------------------------------"
${echo} '#keygen 70000 > key70000'
keygen 70000 > key70000
${echo} "#5 POINTS: Number of characters in key70000, should be 70001:"
[ -s key70000 ] || rm -f key70000
wc -m key70000
${echo}
${echo} "#-----------------------------------------"
${echo} '#otp_enc plaintext1 key20 $encport'
${echo} "#10 POINTS: Should return error about too-short key"
otp_enc plaintext1 key20 $encport
${echo}
${echo} "#-----------------------------------------"
${echo} '#otp_enc plaintext1 key70000 $encport'
${echo} "#20 POINTS: Should return encrypted version of plaintext1"
otp_enc plaintext1 key70000 $encport
${echo}
${echo} '#-----------------------------------------'
${echo} '#otp_enc plaintext1 key70000 $encport > ciphertext1'
otp_enc plaintext1 key70000 $encport > ciphertext1
${echo} "#10 POINTS: ciphertext1 must exist"
[ -s ciphertext1 ] || rm -f ciphertext1
if [ -f ciphertext1 ]; then ${echo} 'ciphertext1 exists!'; else ${echo} 'ciphertext1 DOES NOT EXIST'; fi
${echo}
${echo} '#-----------------------------------------'
${echo} '#10 POINTS: ciphertext1 must be same number of chars as source'
${echo} '#wc -m plaintext1'
wc -m plaintext1
${echo} '#Should be same: wc -m ciphertext1'
wc -m ciphertext1
${echo}
${echo} '#-----------------------------------------'
${echo} '#5 POINTS: ciphertext1 should look encrypted'
cat ciphertext1
${echo}
${echo} '#-----------------------------------------'
${echo} '#otp_dec ciphertext1 key70000 $encport'
${echo} '#5 POINTS: Should fail giving error that otp_dec cannot use otp_enc_d'
otp_dec ciphertext1 key70000 $encport
${echo}
${echo} '#-----------------------------------------'
${echo} '#20 POINTS: should return decrypted ciphertext1 that matches source'
${echo} '#cat plaintext1'
cat plaintext1
${echo} '#otp_dec ciphertext1 key70000 $decport'
otp_dec ciphertext1 key70000 $decport
${echo}
${echo} '#-----------------------------------------'
${echo} '#otp_dec ciphertext1 key70000 $decport > plaintext1_a'
otp_dec ciphertext1 key70000 $decport > plaintext1_a
${echo} "#10 POINTS: plaintext1_a must exist"
[ -s plaintext1_a ] || rm -f plaintext1_a
if [ -f plaintext1_a ]; then ${echo} 'plaintext1_a exists!'; else ${echo} 'plaintext1_a DOES NOT EXIST'; fi
${echo}
${echo} '#-----------------------------------------'
${echo} '#cmp plaintext1 plaintext1_a'
${echo} '#5 POINTS: plaintext1 must be the same as plaintext1_a:'
cmp plaintext1 plaintext1_a
${echo} '#echo $? should be == 0, which means the cmp succeeded!'
echo $?
${echo}
${echo} '#-----------------------------------------'
${echo} '#20 POINTS: concurrent test of encryption - look for 4 properly-sized ciphertext# files, or 5 where the 5th is 0 bytes'
${echo} '#5 POINTS: Should be only one error about plaintext5 being bad'
rm -f ciphertext*
rm -f plaintext*_*
otp_enc plaintext1 key70000 $encport > ciphertext1 &
otp_enc plaintext2 key70000 $encport > ciphertext2 &
otp_enc plaintext3 key70000 $encport > ciphertext3 &
otp_enc plaintext4 key70000 $encport > ciphertext4 &
otp_enc plaintext5 key70000 $encport > ciphertext5 &
${echo} 'Ten second sleep, your program must complete in this time'
sleep 10
ls -pla
${echo}
${echo} '#-----------------------------------------'
${echo} '#15 POINTS: concurrent test of decryption - look for 4 plaintext#_a files that match the plaintext# files'
otp_dec ciphertext1 key70000 $decport > plaintext1_a &
otp_dec ciphertext2 key70000 $decport > plaintext2_a &
otp_dec ciphertext3 key70000 $decport > plaintext3_a &
otp_dec ciphertext4 key70000 $decport > plaintext4_a &
${echo} '#Ten second sleep, your program must complete in this time'
sleep 10
ls -pla
#Clean up
${echo}
${echo} '#-----------------------------------------'
${echo} '#Cleaning up - ignore Operation Not Permitted errors'
killall -q -u $USER otp_*
rm -f ciphertext*
rm -f plaintext*_*
rm -f key20
rm -f key70000
${echo}
${echo} '#SCRIPT COMPLETE'

View File

@@ -0,0 +1 @@
THE RED GOOSE FLIES AT MIDNIGHT STOP

View File

@@ -0,0 +1 @@
CAVERNA POWER GRID SPACE CADETS STARSHIP TROOPERS DIXIT DOMINION ARKHAM HORROR MAGIC FALLING BANE ECLIPSE ACQUIRE CORE WORLDS REVOLUTION LORDS OF WATERDEEP MICE AND MYSTICS PATHFINDER ACG MUNCHKIN SMASHUP TWILIGHT STRUGGLE PUERTO RICO SMALL WORLD PANDEMIC SEVEN WONDERS ROBORALLY DIPLOMACY DEADWOOD KILL DOCTOR LUCKY

View File

@@ -0,0 +1 @@
IN THE BEGINNING

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
$*!(#*djs8301these-are-all-bad-characters

View File

@@ -0,0 +1,57 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg) { perror(msg); exit(0); } // Error function used for reporting issues
int main(int argc, char *argv[])
{
int socketFD, portNumber, charsWritten, charsRead;
struct sockaddr_in serverAddress;
struct hostent* serverHostInfo;
char buffer[256];
if (argc < 3) { fprintf(stderr,"USAGE: %s hostname port\n", argv[0]); exit(0); } // Check usage & args
// Set up the server address struct
memset((char*)&serverAddress, '\0', sizeof(serverAddress)); // Clear out the address struct
portNumber = atoi(argv[2]); // Get the port number, convert to an integer from a string
serverAddress.sin_family = AF_INET; // Create a network-capable socket
serverAddress.sin_port = htons(portNumber); // Store the port number
serverHostInfo = gethostbyname(argv[1]); // Convert the machine name into a special form of address
if (serverHostInfo == NULL) { fprintf(stderr, "CLIENT: ERROR, no such host\n"); exit(0); }
memcpy((char*)&serverAddress.sin_addr.s_addr, (char*)serverHostInfo->h_addr, serverHostInfo->h_length); // Copy in the address
// Set up the socket
socketFD = socket(AF_INET, SOCK_STREAM, 0); // Create the socket
if (socketFD < 0) error("CLIENT: ERROR opening socket");
// Connect to server
if (connect(socketFD, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) // Connect socket to address
error("CLIENT: ERROR connecting");
// Get input message from user
printf("CLIENT: Enter text to send to the server, and then hit enter: ");
memset(buffer, '\0', sizeof(buffer)); // Clear out the buffer array
fgets(buffer, sizeof(buffer) - 1, stdin); // Get input from the user, trunc to buffer - 1 chars, leaving \0
buffer[strcspn(buffer, "\n")] = '\0'; // Remove the trailing \n that fgets adds
// Send message to server
charsWritten = send(socketFD, buffer, strlen(buffer), 0); // Write to the server
if (charsWritten < 0) error("CLIENT: ERROR writing to socket");
if (charsWritten < strlen(buffer)) printf("CLIENT: WARNING: Not all data written to socket!\n");
// Get return message from server
memset(buffer, '\0', sizeof(buffer)); // Clear out the buffer again for reuse
charsRead = recv(socketFD, buffer, sizeof(buffer) - 1, 0); // Read data from the socket, leaving \0 at end
if (charsRead < 0) error("CLIENT: ERROR reading from socket");
printf("CLIENT: I received this from the server: \"%s\"\n", buffer);
close(socketFD); // Close the socket
return 0;
}

View File

@@ -0,0 +1,53 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void error(const char *msg) { perror(msg); exit(1); } // Error function used for reporting issues
int main(int argc, char *argv[])
{
int listenSocketFD, establishedConnectionFD, portNumber, charsRead;
socklen_t sizeOfClientInfo;
char buffer[256];
struct sockaddr_in serverAddress, clientAddress;
if (argc < 2) { fprintf(stderr,"USAGE: %s port\n", argv[0]); exit(1); } // Check usage & args
// Set up the address struct for this process (the server)
memset((char *)&serverAddress, '\0', sizeof(serverAddress)); // Clear out the address struct
portNumber = atoi(argv[1]); // Get the port number, convert to an integer from a string
serverAddress.sin_family = AF_INET; // Create a network-capable socket
serverAddress.sin_port = htons(portNumber); // Store the port number
serverAddress.sin_addr.s_addr = INADDR_ANY; // Any address is allowed for connection to this process
// Set up the socket
listenSocketFD = socket(AF_INET, SOCK_STREAM, 0); // Create the socket
if (listenSocketFD < 0) error("ERROR opening socket");
// Enable the socket to begin listening
if (bind(listenSocketFD, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0) // Connect socket to port
error("ERROR on binding");
listen(listenSocketFD, 5); // Flip the socket on - it can now receive up to 5 connections
// Accept a connection, blocking if one is not available until one connects
sizeOfClientInfo = sizeof(clientAddress); // Get the size of the address for the client that will connect
establishedConnectionFD = accept(listenSocketFD, (struct sockaddr *)&clientAddress, &sizeOfClientInfo); // Accept
if (establishedConnectionFD < 0) error("ERROR on accept");
// Get the message from the client and display it
memset(buffer, '\0', 256);
charsRead = recv(establishedConnectionFD, buffer, 255, 0); // Read the client's message from the socket
if (charsRead < 0) error("ERROR reading from socket");
printf("SERVER: I received this from the client: \"%s\"\n", buffer);
// Send a Success message back to the client
charsRead = send(establishedConnectionFD, "I am the server, and I got your message", 39, 0); // Send success back
if (charsRead < 0) error("ERROR writing to socket");
close(establishedConnectionFD); // Close the existing socket which is connected to the client
close(listenSocketFD); // Close the listening socket
return 0;
}

View File

@@ -0,0 +1,56 @@
# Assignment 5 - Python Exploration
# Corwin Perren
import os
import random
ASCII_MIN = ord('a')
ASCII_MAX = ord('z')
NUM_MIN = 1
NUM_MAX = 42
def make_file_with_random_letters(filename):
file = open(filename, "w")
for _ in range(10):
character_decimal = random.randint(ASCII_MIN, ASCII_MAX)
file.write(chr(character_decimal))
file.write('\n')
file.close()
def print_out_file(filename):
file = open(filename, "r")
lines = file.readlines()
for line in lines:
print "File \"" + filename + "\" contains: " + line,
file.close()
if __name__ == "__main__":
current_pid = os.getpid()
filenames = [
str(current_pid) + "_1.txt",
str(current_pid) + "_2.txt",
str(current_pid) + "_3.txt"
]
print "Generating files with names:"
for name in filenames:
make_file_with_random_letters(name)
print name
print "\nContents of files are:"
for name in filenames:
print_out_file(name)
print "\nGenerating two random numbers:"
first_number = random.randint(NUM_MIN, NUM_MAX)
second_number = random.randint(NUM_MIN, NUM_MAX)
print "First number is: " + str(first_number)
print "Second number is: " + str(second_number)
print "Product of the two numbers is: " + str(first_number*second_number)