mirror of
https://github.com/caperren/school_archives.git
synced 2025-11-09 21:51:15 +00:00
Added work from my other class repositories before deletion
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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(¤t_time_raw);
|
||||
time_as_struct = localtime(¤t_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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
make clean
|
||||
make build
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
@@ -0,0 +1 @@
|
||||
THE RED GOOSE FLIES AT MIDNIGHT STOP
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
IN THE BEGINNING
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
$*!(#*djs8301these-are-all-bad-characters
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user