## Example of Bubble Sort Algorithm

Example of Bubble Sort algorithm

NOTIFICATION: These examples are provided for educational purposes. Using this code is under your own responsibility and risk. The code is given ‘as is’. I do not take responsibilities of how they are used.

bubblesort.c:

```/**
* Framework for the sorting programs.
* Modified by: Alejandro G. Carlstein
* Program Number: 1
* Description: This code will implement an insertion sort algorithm
*              which will follow the following steps:
*              1. Copy item at current position
*              2. Shift previous position item to current position
*                 while item (in previous positions) is greater than
*                 the item copied and there are previous items
to compare with the key item
*              3. Insert copied item in the previous position in which
*                 the previous item is found to be
*                 smaller than the copied item
*
*/
#include <stdio.h>
#define MAX_SIZE 1000000
int data[MAX_SIZE];
int n;

int main()
{
int i;
int j;
int key_item;

/* Read in the data */
n = 0;
while (scanf('%d', &data[n]) == 1)
++n;

/* Sort the numbers low to high */
for (i = 1; i < n; i++){

key_item = data[i];

for (j = i; (j > 0) && (data[j - 1] > key_item); j--){

data[j] = data[j - 1];

}//end for

data[j] = key_item;

}//end for

/* Print out the data */
for (i = 0; i < n; ++i)
printf('%d\n', data[i]);
}```

If you encounter any problems or errors, please let me know by providing an example of the code, input, output, and an explanation. Thanks.

## File Transfer Client and Server using Vigenere Cipher

[Disclaimer: This code is provided for educational purposes, you are responsible of how you use this code and this code is provided ‘as is’. Meaning that I do not take responsibility of  any harm that this code may or not produce]

The following is an example of a client and server that let you transfer a file from the client to the server by encrypting and then decrypting the packages using Vigenere Cipher.

Test file content example:

Note: This program is designed only to send files that are alphabetic in lower case, without spaces, and  only one line.

`abcdefghijklmnopqrstuvwxyzaabcdefghijklmnopqrstuvwxyzaabcdefghijklmnopqrstuvwxyza`

Makefile:

As a good policy, always add your name, short description, and any other information that could help a user that doesn’t know as you the content of your code and its behaviour.

Note: In the server, there must be a subdirectory named cli_serv in which ssh and scp can access after loading.

﻿﻿﻿

```#########################################################################
# Author: Alejandro G. Carlstein Ramos Mejia
# Description: Client/Server File Transfer using Vergene Cipher
#
#
# make <= compile all files
# make build <= compile all files
# make all <= clean and compile all files
# make ssh <= Connect to server and go to folder cli_serv
# make upload <= Upload files on SRC_FILES list to server
# make uploadssh <= Upload files on SRC_FILES list to server and connect to server
# make submit <= Tar files on SRC_FILES list
# make zipsubmit <= Tar files on SRC_FILES list and gzip them
# make clean <= Clean all executable and *.o files
# make debug_server <= Debug server using dbg
# make debug_client <= Debug client using dbg
# make ldebug_server <= Debug for leaks on server
# make ldebug_client <= Debug for leaks on client
##########################################################################

##########################################################################
# Variables
##########################################################################

# PROJECT is the name used when preparing for sumit/
# The tar and/or zip file will be using this name
PROJECT = server_client_vergene

# SRC_FILES are list of files in the project.
# This list is used when uploading files to the server.
# Also, this list is used when tar/zipped for submit
SRC_FILES = \
cli.c \
serv.c\
default.h \
default.c \
text.txt\
Makefile \
README

# OpenSSH SSH client (remote login program)
SSH = ssh

# secure copy (remote file copy program)
# SCP is used for uploading files to the server in secure mode
SCP = scp

# FOLDER_SERVER is the folder that SSH and SCP will try to access after login
FOLDER_SERVER = server_client_vergene

# SSH_SERVER is the hostname of the server
SSH_SERVER = bingsuns2.cc.binghamton.edu

# SSH_OPTION
# -t opens a pseudo-tty with in the current session.
# This flag is required to execute the commands on SSH_CD_FOLDER
SSH_OPTION = -t

# SSH_CD_FOLDER executes cd
# Then change the prompt to show the number of bash in the server
SSH_CD_FOLDER = 'cd \$(FOLDER_SERVER); bash; echo \$PS1'

# CC indicates which compiler is going to be used
CC = gcc

# Files required for compiling the server
CODE_SERVER_FILE = serv.c default.c

# Files required for compiling the client
CODE_CLIENT_FILE = cli.c default.c

# Name of the executable file for the server
EXEC_SERVER_FILE = serv

# Name for the executable file for the client
EXEC_CLIENT_FILE = cli

# Flags for the compiler
# -g indicate to provide debuggin information
# -Wall activates the warnings.
# -lm indicate the compiler to add basic mathematics libraries
CFLAGS = -g -Wall -lm

# COMPILE is the combination of the compiler with the flags
COMPILE = \$(CC) \$(CFLAGS)

# MFLAGS are flags that require to be added at the end
MFLAGS =

# USERNAME is used later when required to do an upload followed with ssh
USERNAME =

# Detect if the computer is SunOS to add flags needed for compiling
UNAME := \$(shell uname)
ifeq (\$(UNAME), SunOS)
MFLAGS := -lsocket -lnsl
endif

##########################################################################
# 'make' options
##########################################################################

# Clean all files and compile client and server
all: clean compile_server compile_client

# Just build server and client
build: compile_server compile_client

# Compile server
compile_server: \$(CODE_SERVER_FILE)
\$(CC) \$(CFLAGS) -o \$(EXEC_SERVER_FILE) \$(CODE_SERVER_FILE) \$(MFLAGS)

# Compile client
compile_client: \$(CODE_CLIENT_FILE)
\$(CC) \$(CFLAGS) -o \$(EXEC_CLIENT_FILE) \$(CODE_CLIENT_FILE) \$(MFLAGS)

# Debug server
debug_server:
gdb \$(EXEC_SERVER_FILE)

# Debug client
debug_client:
gdb \$(EXEC_CLIENT_FILE)

# Leak debug server
ldebug_server:
valgrind --leak-check=full --show-reachable=yes -v \$(EXEC_SERVER_FILE)

# Leak debug client
ldebug_client:
valgrind --leak-check=full --show-reachable=yes -v \$(EXEC_CLIENT_FILE)

# Upload files and connect to server
uploadssh:
@echo -n 'Upload and connect to \$(SSH_SERVER)- USERNAME: ';\
read user_name;\
\$(SCP) \$(SRC_FILES) \$\$user_name@\$(SSH_SERVER):./\$(FOLDER_SERVER);\
\$(SSH) \$(SSH_OPTION) \$\$user_name@\$(SSH_SERVER) \$(SSH_CD_FOLDER);\

# Upload files to server
upload:
@echo -n 'Upload to \$(SSH_SERVER)- USERNAME: ';\
read user_name;\
\$(SCP) \$(SRC_FILES) \$\$user_name@\$(SSH_SERVER):./\$(FOLDER_SERVER);\

# Connect to server
ssh:
@echo -n 'Connect to \$(SSH_SERVER)- USERNAME: ';\
read user_name;\
\$(SSH) \$(SSH_OPTION) \$\$user_name@\$(SSH_SERVER) \$(SSH_CD_FOLDER);\

# Makes a archive containing all the project source files for submission.
submit:	\$(SRC_FILES)
tar -cvf \$(PROJECT).tar \$(SRC_FILES)

# Makes a archive containing all the project source files for submission
# and zip them
zipsubmit:	\$(SRC_FILES)
tar cvfz \$(PROJECT).tar.gz \$(SRC_FILES)

# Clean files
.PHONY: clean
clean:
rm -f *~ *.o \$(EXEC_SERVER_FILE) \$(EXEC_CLIENT_FILE)```

Default file is required for both the server and the client. It holds the libraries and definitions shared by both programs.

Default.h file:

```/**
* Author: Alejandro G. Carlstein
* Description: File Transfer Client/Server
*/

#ifndef ACARLS_DEFAULT_H
#define ACARLS_DEFAULT_H

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>

/* Required for linux */
#include <string.h>

/* Required for SunOS */
#include <strings.h>

#include <ctype.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>

#define DEFAULT_PORT 					8414
#define DATA_PACKET_SIZE 			1024
#define NUM_BYTES							8
#define ENCRYPTION_KEY		    'security'
#define CHAR_KEY_A						97
#define CHAR_PLAIN_A					97
#define CHAR_CIPHER_A					65

#define DBG_LV0 0
#define DBG_LV1 0
#define DBG_LV2 0
#define DBG_LV3 0

#define TRUE									1
#define FALSE									0

#define QUIT_TRUE							0
#define QUIT_FALSE						1

#define CODE_FAIL							'0FAIL'
#define CODE_OK								'1OK'

#define CODE_HELLO						'100HELLO'
#define CODE_WELCOME 					'101WELCOME'
#define CODE_REQ_SERVER_NAME 	'102REQ_SERVER_NAME'

#define CODE_MSG 							'200MSG'

#define CODE_DATA							'300DATA'
#define CODE_EOF							'301EOF'
#define CODE_PUT						  '302PUT'
#define CODE_REQUEST_FILENAME	'303REQ_FILENAME'
#define CODE_REQUEST_ENCRYPT  '304REQ_ENCRYPT'
#define CODE_ENCRYPT					'305ENCRYPT'
#define CODE_REQUEST_FILE     '306REQUEST_FILE'

#define CODE_CMD							'400CMD'
#define CODE_LS								'401LS'

#define CODE_ERROR            '500ERROR'
#define CODE_ERROR_LS					'501ERROR_LS'
#define CODE_ERROR_CREAT_FILE '502ERROR_CREAT_FILE'

#define CODE_EXIT							'600EXIT'

#define MSG_ERR_WRONG_PROTOCOL  'Wrong protocol!'
#define MSG_ERROR_CREAT_FILE 		'Couldn't create file'
#define MSG_PORT_NUMBER_ONLY 		'Need port number only! \n%s <Port Number>'
#define MSG_ERR_COULDNT_SOCKET  'Couldn't obtain socket - %d'
#define MSG_ERR_COULDNT_CONNECT 'Couldn't connect!'
#define MSG_ERR_SENDING_DATA 		'Couldn't send data!'
#define MSG_ERR_RECEIVING_DATA	'Couln't recieve data!'
#define MSG_ERR_CONNECTION_FAIL 'Connection failed.'
#define MSG_ERR_NO_DIR_STREAM 	'Could not obtain the directory stream'

void debug(int debugLevel, char *fmt, ...);
void errorDoExit(char *fmt, ...);

#endif```

Default.c:

```/**
* Author: Alejandro G. Carlstein
* Description: File Transfer Client/Server
*/

#include 'default.h'

void debug(int debugLevel, char *fmt, ...){
if (debugLevel == 1){
va_list argp;
fprintf(stdout, '[DBG] ');
va_start(argp, fmt);
vfprintf(stdout, fmt, argp);
va_end(argp);
fprintf(stdout, '\n');
}
}

void errorDoExit(char *fmt, ...){
va_list argp;
fprintf(stderr, '[Error] ');
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
if (errno){
fprintf(stderr, '=> %s\n', strerror(errno));
}else{
fprintf(stderr, '\n');
}
exit(1);
}```

The following is the code for the server.
serv.c:

```/**
* Assignment: 1
* Course: CS458
* Author: Alejandro G. Carlstein
* Description: FTP Server
*/

#include 'default.h'

/*max. length queue of pending connections may grow. */
#define MAX_BACKLOG							5
#define SETSOCKOPT_VAL  				1

#define MSG_SERVER_NAME 				'Server Name: ACARLSTEIN Server Version 1.0'
#define MSG_WAIT_CLIENT					'Waiting client...\n'
#define MSG_WAIT_CLIENT_ON_PORT	'\nTCPServer Waiting for client on port %d\n'

#define MSG_ERR_NO_SOCKET_OPT		'Couldn't set and/or get socket options'
#define MSG_ERR_UNABLE_BIND    	'Unable to bind'
#define MSG_ERR_UNABLE_LISTEN  	'Unable to Listen'
#define MSG_ERR_CANT_SEND_LIST  'Can't send server list\n'

struct Connection{
int sock;
int bytes_recieved;
int port_number;
int socket_descriptor;
char send_data[DATA_PACKET_SIZE];
char recv_data[DATA_PACKET_SIZE];
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
};

void setUpConnection(struct Connection *new_connection,
int port_number);
int menuDriver(struct Connection *new_connection);
void sendData(struct Connection *new_connection,
const char* data);
int recieveData(struct Connection *new_connection);
void handShake(struct Connection* new_connection);
void sendListDirectoryContents(struct Connection* new_connection);
int receiveFileFromClient(struct Connection* new_connection);
int strdecrypt(const char* str_in,
char* str_out);

/**
* MAIN
*/
int main(int argc, char *argv[]){
debug(DBG_LV0, 'argc: %d', argc);

short DO_QUIT_PROGRAM;
int i;
int port_number;
socklen_t sin_size = sizeof(struct sockaddr_in);
struct Connection connection;

for(i = 0; DBG_LV1 && i < argc; ++i)
debug(DBG_LV1, 'argv[%d]: %s', i, argv[i]);

if (argc > 2)	errorDoExit(MSG_PORT_NUMBER_ONLY, argv[0]);

port_number = (argc == 2) ? atoi(argv[1]) : DEFAULT_PORT;

DO_QUIT_PROGRAM = QUIT_FALSE;
while(DO_QUIT_PROGRAM){

fflush(stdout);

setUpConnection(&connection, port_number);

printf(MSG_WAIT_CLIENT_ON_PORT, port_number);

connection.socket_descriptor = accept(connection.sock,
(struct sockaddr *)&connection.client_addr,
&sin_size);

if (connection.socket_descriptor  == -1)
errorDoExit(MSG_ERR_COULDNT_CONNECT);

handShake(&connection);

menuDriver(&connection);

close(connection.sock);

}

return 0;
}

/**
* Menu driver waiting for instructions
*/
int menuDriver(struct Connection *new_connection){

short DO_QUIT_CONNECTION;
int bytes_received = 1;

DO_QUIT_CONNECTION = QUIT_FALSE;
while (DO_QUIT_CONNECTION){

if(bytes_received == 0){
DO_QUIT_CONNECTION = QUIT_TRUE;
}else{

printf(MSG_WAIT_CLIENT);

bytes_received = recieveData(new_connection);
if (strcmp(new_connection->recv_data, CODE_LS) == 0){
sendListDirectoryContents(new_connection);
}else
if (strcmp(new_connection->recv_data, CODE_PUT) == 0){
bytes_received = receiveFileFromClient(new_connection);
}else{
close(new_connection->sock);
fprintf(stderr, MSG_ERR_WRONG_PROTOCOL ' - PUT\n');
DO_QUIT_CONNECTION = QUIT_TRUE;
}
}
}
return 0;
}

/**
* Set up connection with the client
*/
void setUpConnection(struct Connection *new_connection,
int port_number){
debug(DBG_LV0, 'setUpConnection(port_number: %d)', port_number);

int opt_val = SETSOCKOPT_VAL;
new_connection->port_number = port_number;

if ((new_connection->sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
errorDoExit(MSG_ERR_COULDNT_SOCKET, new_connection->sock);

if (setsockopt(new_connection->sock, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(int)) == -1)
errorDoExit(MSG_ERR_NO_SOCKET_OPT);

debug(DBG_LV1, 'Got socket!');

new_connection->server_addr.sin_family = AF_INET;
debug(DBG_LV1,'sin_family');

new_connection->server_addr.sin_port = htons(port_number);
debug(DBG_LV1,'sin_port');

new_connection->server_addr.sin_addr.s_addr = INADDR_ANY;
debug(DBG_LV1, 'sin_addr');

bzero(&(new_connection->server_addr.sin_zero), NUM_BYTES);
debug(DBG_LV1,'sin_zero');

// bind a name to a socket
if (bind(new_connection->sock,
(struct sockaddr *)&new_connection->server_addr,
sizeof(struct sockaddr)) == -1){
close(new_connection->sock);
errorDoExit(MSG_ERR_UNABLE_BIND);
}

// Listen for connection on the socket
if (listen(new_connection->sock, MAX_BACKLOG) == -1){
close(new_connection->sock);
errorDoExit(MSG_ERR_UNABLE_LISTEN);
}
debug(DBG_LV1, 'Listening...');

}

/**
* Send data to client
*/
void sendData(struct Connection *new_connection,
const char* data){
debug(DBG_LV0, 'sendData(data: %s)', data);

int data_length;

bzero(new_connection->send_data, DATA_PACKET_SIZE);
strcpy(new_connection->send_data, data);
data_length = strlen(new_connection->send_data);

debug(DBG_LV1, 'new_connection->send_data: %s',
new_connection->send_data);

if (send(new_connection->socket_descriptor,
new_connection->send_data,
data_length, 0) != data_length){
close(new_connection->sock);
fprintf(stderr, MSG_ERR_SENDING_DATA '\n');
}
}

/**
* Receive data from client
*/
int recieveData(struct Connection *new_connection){
debug(DBG_LV0, 'recieveData()');

bzero(new_connection->recv_data, DATA_PACKET_SIZE);
int bytes_recieved = recv(new_connection->socket_descriptor,
new_connection->recv_data,
DATA_PACKET_SIZE,
0);

debug(DBG_LV1, 'Check bytes received');

if(bytes_recieved < 1){

close(new_connection->sock);

if(bytes_recieved == 0){
fprintf(stderr, MSG_ERR_CONNECTION_FAIL '\n');
}else{
fprintf(stderr,MSG_ERR_RECEIVING_DATA '\n');
}

}else{

debug(DBG_LV1, 'Received: %s', new_connection->recv_data);

new_connection->bytes_recieved = bytes_recieved;
new_connection->recv_data[bytes_recieved] = '\0';
}

return bytes_recieved;
}

/**
* Hand shake with client to test own protocol
*/
void handShake(struct Connection* new_connection){
debug(DBG_LV0, 'handShake()');

printf('Connection from (%s , %d)...\n',
inet_ntoa(new_connection->client_addr.sin_addr),
ntohs(new_connection->client_addr.sin_port));

debug(DBG_LV1,' If client say HELLO, Greed client with WELCOME');
recieveData(new_connection);
if (strcmp(new_connection->recv_data, CODE_HELLO) == 0){
debug(DBG_LV1, 'Client handshake with server');
sendData(new_connection, CODE_WELCOME);
}else{
close(new_connection->sock);
fprintf(stderr, MSG_ERR_WRONG_PROTOCOL ' - HELLO/WELCOME \n');
}

debug(DBG_LV0,'If client ask for server name send server name to client');
recieveData(new_connection);
if (strcmp(new_connection->recv_data, CODE_REQ_SERVER_NAME) == 0){
debug(DBG_LV1, 'Client asking for server name');
sendData(new_connection, MSG_SERVER_NAME);
}else{
close(new_connection->sock);
fprintf(stderr, MSG_ERR_WRONG_PROTOCOL ' - SERVER NAME\n');
}
}

/**
* Send list of directory contents to client
*/
void sendListDirectoryContents(struct Connection* new_connection){
debug(DBG_LV0, 'void displayLocalListDirectoryContents()');
int bytes_received;
struct dirent *dirent_struct_ptr;
DIR *directory_stream_ptr;

if ((directory_stream_ptr = opendir('./')) != NULL){

while ((dirent_struct_ptr = readdir(directory_stream_ptr))){
sendData(new_connection, dirent_struct_ptr->d_name);

bytes_received = recieveData(new_connection);
if (strcmp(new_connection->recv_data, CODE_OK) != 0){
fprintf(stderr, MSG_ERR_CANT_SEND_LIST);
}
}
sendData(new_connection, CODE_EOF);

}else{
sendData(new_connection, CODE_ERROR_LS);
errorDoExit(MSG_ERR_NO_DIR_STREAM);
}

}

/**
* Receive encrypted file from client
*/
int receiveFileFromClient(struct Connection* new_connection){
debug(DBG_LV0, 'void receiveFileFromClient(is_encrypted: %s)');

int bytes_received;

char filename[DATA_PACKET_SIZE];
char filename_se[DATA_PACKET_SIZE];
char filename_sd[DATA_PACKET_SIZE];
char str_unencrypted[DATA_PACKET_SIZE];
FILE *fp_se, *fp_sd;

/* Request filename */
debug(DBG_LV1, 'Request filename from client');
sendData(new_connection, CODE_REQUEST_FILENAME);

/* receive filename */
bytes_received = recieveData(new_connection);
strcpy(filename, new_connection->recv_data);
sprintf(filename_se, '%s_se', filename);
sprintf(filename_sd, '%s_sd', filename);

debug(DBG_LV1, 'filename: %s', filename);
debug(DBG_LV1, 'filename_se: %s', filename_se);
debug(DBG_LV1, 'filename_sd: %s', filename_sd);

fp_se = fopen(filename_se, 'w');
fp_sd = fopen(filename_sd, 'w');
debug(DBG_LV1, 'Files open');

if (fp_se == NULL || fp_sd == NULL){
debug(DBG_LV1, 'Error, closing files');
fclose(fp_se);
fclose(fp_sd);
errorDoExit(MSG_ERROR_CREAT_FILE);
}else{

debug(DBG_LV1, 'Download file...');
/* Send code request file */
sendData(new_connection, CODE_REQUEST_FILE);

bytes_received = recieveData(new_connection);

/* while loop until eof */
while (strcmp(new_connection->recv_data, CODE_EOF) != 0){

debug(DBG_LV1, 'Saving: %s', new_connection->recv_data);
/* save encrypted package */
fprintf(fp_se, '%s', new_connection->recv_data);

/* Decencrypt package */
bzero(str_unencrypted, DATA_PACKET_SIZE);
strdecrypt(new_connection->recv_data, str_unencrypted);
debug(DBG_LV1, 'Decrypt: %s\n', new_connection->recv_data);

/* Save unecrypted package */
debug(DBG_LV1, 'DECRYPT: %s', str_unencrypted);

fprintf(fp_sd, '%s', str_unencrypted);

debug(DBG_LV1, 'Sending OK...');
/*send ok */
sendData(new_connection, CODE_OK);
bytes_received = recieveData(new_connection);
}

}

fclose(fp_se);
fclose(fp_sd);
return 0;
}

/**
* Decrypt string
*/
int strdecrypt(const char* str_in,
char* str_out){
debug(DBG_LV0, 'strdencrypt(str_in: %s)', str_in);

int i, j;
int i_cipher, i_key, i_temp;
char str_key[DATA_PACKET_SIZE];
strcpy(str_key, ENCRYPTION_KEY);
char char_temp;
for (i = 0, j = 0; i < strlen(str_in); ++i, ++j){

i_cipher = str_in[i] - CHAR_CIPHER_A;
i_key = str_key[j] - CHAR_KEY_A;
i_temp = i_cipher - i_key;

debug(DBG_LV1, 'Ci([%c]%d): %d, Ki([%c]%d): %d, Ci - Ki: %d',
str_in[i], i, i_cipher, str_key[j], j, i_key, i_temp);

if (i_temp > -1){
//COMMON KNOWN DECRYPT ALGORIGHTM
i_temp = ((i_temp) % 26);
}else{
//DECRYPT ALGORITHM FOR UNCOMMON CASES WHERE I_TEMP IS NEGATIVE
i_temp = ((i_temp + 26) % 26);
}

char_temp = i_temp + CHAR_PLAIN_A;
if (isalpha(char_temp)){
str_out[i] = char_temp;
}else{
str_out[i] = '\0';
}

if ( (j + 1) >= strlen(str_key)) j = -1;
}

return 0;
}```

The following is the code for the client.

cli.c

```/**
* Assignment: 1
* Course: CS458
* Author: Alejandro G. Carlstein
* Description: Transfer Encrypted File Client
*/

#include 'default.h'

#define DEFAULT_HOST 									'localhost'
#define EXIT_PROGRAM 									0
#define DONT_EXIT_PROGRAM 						1

#define CMD_QUIT											'quit'
#define CMD_HELP											'help'
#define CMD_LS												'ls'
#define CMD_LLS												'lls'
#define CMD_LPWD											'lpwd'
#define CMD_PUT												'put'

#define MSG_DISPLAY_MENU 							'User help:\n'\
'help - Display help option\n'\
'lls  - Display local directory list contents\n'\
'lpwd - Display local current directory\n'\
'put  - Transfer local file to server\n'\
'  put <file to transfer>\n'\
'quit - Quit program\n'

#define MSG_ERROR_UNKNOWN_COMMAND			'[X] Command not recognized: %s\n'
#define MSG_ERROR_GETTING_HOSTNAME 		'Couln't get hostname!'
#define MSG_ERROR_SERVER_DISCONNECTED 'Server disconnected...\n'

enum TOKENS{
TOKEN_COMMAND,
TOKEN_FILENAME,
MAX_TOKENS
};

struct Connection{
int sock;
int bytes_received;
int port_number;
char send_data[DATA_PACKET_SIZE];
char recv_data[DATA_PACKET_SIZE];
struct hostent *host;
struct sockaddr_in server_addr;
};

void getConnection(struct Connection *new_connection,
char *hostname,
int port_number);
void menuDriver(struct Connection *new_connection);
int receiveData(struct Connection *new_connection);
int sendData(struct Connection* new_connection, const char* data);
void handShake(struct Connection* new_connection);
void promptUser(char* tokens[]);
void displayHelp(void);
void displayLocalListDirectoryContents(void);
void printNameCurrentDirectory(void);
void receiveListDirectoryContents(struct Connection *new_connection);
void putFileOnServer(struct Connection *new_connection,
const char* filename);
int strencrypt(const char* str_in,
char* str_out);
/**
* MAIN
*/
int main(int argc, char* argv[]){
debug(DBG_LV0, 'argc: %d', argc);

int i;
int port_number = (argc >= 3 ) ? atoi(argv[2]) : DEFAULT_PORT;
char* host_name = (argc >= 2) ? argv[1] : DEFAULT_HOST;

struct Connection connection;

for(i = 0; i < argc; ++i)
debug(DBG_LV0, 'argv[%d]: %s', i, argv[i]);

if (argc > 3)
errorDoExit(MSG_PORT_NUMBER_ONLY, argv[0]);

debug(DBG_LV1, 'host: %s', host_name);

getConnection(&connection, host_name, port_number);

handShake(&connection);

menuDriver(&connection);

return 0;

}

/**
* Driver menu
*/
void menuDriver(struct Connection *new_connection){
debug(DBG_LV0, 'menuDriver()');

short doExit = DONT_EXIT_PROGRAM;
int i;
char* tokens[MAX_TOKENS] = {NULL, NULL};
char command[DATA_PACKET_SIZE];
char filename[DATA_PACKET_SIZE];

while(doExit){

promptUser(tokens);

for (i = 0; DBG_LV1 && i < MAX_TOKENS; ++i)
debug(DBG_LV1, 'TOKEN[%d]: %s', i, tokens[i]);

/* Must copy string to work on SunOS */
if (tokens[TOKEN_COMMAND] != NULL){
strcpy(command, tokens[TOKEN_COMMAND]);
debug(DBG_LV1, '[Command: %s]', command);
}

if (tokens[TOKEN_FILENAME] != NULL){
strcpy(filename, tokens[TOKEN_FILENAME]);
debug(DBG_LV1, '[Filename: %s]', filename);
}

/* MENU */

if (strcmp(command, CMD_QUIT) == 0){
debug(DBG_LV1, 'COMMAND> %s: ', CMD_QUIT);
close(new_connection->sock);
printf('Bye Bye\n');
doExit = EXIT_PROGRAM;

}else
if (strcmp(command, 'help') == 0){
debug(DBG_LV1, 'COMMAND> %s ', CMD_HELP);
displayHelp();

}else
if (strcmp(command, CMD_LLS) == 0){
debug(DBG_LV1, 'COMMAND> %s ', CMD_LLS);
displayLocalListDirectoryContents();

}else
if (strcmp(command, CMD_LLS) == 0){
debug(DBG_LV1, 'COMMAND> %s ', CMD_LLS);
displayLocalListDirectoryContents();

}else
if (strcmp(command, CMD_LS) == 0){
debug(DBG_LV1, 'COMMAND> %s ', CMD_LS);
receiveListDirectoryContents(new_connection);

}else
if (strcmp(command, CMD_LPWD) == 0){
debug(DBG_LV1, 'COMMAND> %s ', CMD_LPWD);
printNameCurrentDirectory();

}else
if (strcmp(command, CMD_PUT) == 0){
debug(DBG_LV1, 'COMMAND> %s ', CMD_PUT);
putFileOnServer(new_connection, filename);

}else{
printf(MSG_ERROR_UNKNOWN_COMMAND, command);
}

}

}

/**
* Obtain connection with server
*/
void getConnection(struct Connection *new_connection,
char *hostname,
int port_number){
debug(DBG_LV0, 'getConnection(hostname: %s, port_number: %d)', hostname, port_number);

if ((new_connection->host = gethostbyname(hostname)) == NULL)
errorDoExit(MSG_ERROR_GETTING_HOSTNAME);

new_connection->port_number = port_number;

if ((new_connection->sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
errorDoExit(MSG_ERR_COULDNT_SOCKET, new_connection->sock);

debug(DBG_LV1, 'Got socket!');

new_connection->server_addr.sin_family = AF_INET;
debug(DBG_LV1,'sin_family');

new_connection->server_addr.sin_port = htons(port_number);
debug(DBG_LV1,'sin_port');

new_connection->server_addr.sin_addr = *((struct in_addr *)new_connection->host->h_addr);
debug(DBG_LV1, 'sin_addr');

// bzero() is used only for setting the values to zero
bzero(&(new_connection->server_addr.sin_zero), NUM_BYTES);
debug(DBG_LV1,'sin_zero');

if (connect(new_connection->sock,
(struct sockaddr *)&new_connection->server_addr,
sizeof(struct sockaddr)) == -1)
errorDoExit(MSG_ERR_COULDNT_CONNECT);

debug(DBG_LV1, 'Got connection!');
}

/**
* Receive data
* @Return: Number of bytes received
*/
int receiveData(struct Connection *new_connection){
debug(DBG_LV0, 'receiveData()');

bzero(new_connection->recv_data, DATA_PACKET_SIZE);
int bytes_received = recv(new_connection->sock,
new_connection->recv_data,
DATA_PACKET_SIZE,
0);

if(bytes_received < 1){
close(new_connection->sock);
if(bytes_received == 0){
close(new_connection->sock);
printf(MSG_ERROR_SERVER_DISCONNECTED);
errorDoExit(MSG_ERR_CONNECTION_FAIL);

}else{
errorDoExit(MSG_ERR_RECEIVING_DATA);
}
}

debug(DBG_LV1, 'Received (%d): %s',
strlen(new_connection->recv_data), new_connection->recv_data);

new_connection->bytes_received = bytes_received;
new_connection->recv_data[bytes_received] = '\0';

return bytes_received;
}

/**
* Send data
* @Return: Number of bytes sended
*/
int sendData(struct Connection* new_connection,
const char* data){
debug(DBG_LV0, 'sendData(%s)', data);
int data_length;

bzero(new_connection->send_data, DATA_PACKET_SIZE);
strcpy(new_connection->send_data, data);
data_length = strlen(new_connection->send_data);

if (send(new_connection->sock, new_connection->send_data,
data_length, 0) != data_length){
close(new_connection->sock);
errorDoExit(MSG_ERR_SENDING_DATA);
}

return data_length;
}

/**
* Hand shake with the server to verify own protocol
*/
void handShake(struct Connection* new_connection){
debug(DBG_LV0, 'handShake()');

debug(DBG_LV1, 'Sending HELLO message...');
sendData(new_connection, CODE_HELLO);

debug(DBG_LV1, 'Getting WELCOME message...');
receiveData(new_connection);

if (strcmp(new_connection->recv_data, CODE_WELCOME) > -1){
debug(DBG_LV1, 'Got WELCOME!');

debug(DBG_LV1, 'Request server name');
sendData(new_connection, CODE_REQ_SERVER_NAME);

receiveData(new_connection);
printf('Server Name: %s\n', new_connection->recv_data);
}else{
errorDoExit(MSG_ERR_WRONG_PROTOCOL);
}
}

/**
* Prompt user for input
*/
void promptUser(char* tokens[]){
char str_input[DATA_PACKET_SIZE];
char *p;
int i;

printf('\nftp> ');
fgets(str_input, DATA_PACKET_SIZE, stdin);

p = strtok(str_input, ' \n');
for (i = 0; p != NULL; (p = strtok(NULL, ' \n')), i++)
tokens[i] = p;
}

/**
* Display help message
*/
void displayHelp(void){
debug(DBG_LV0, 'displayHelp()');
printf(MSG_DISPLAY_MENU);
}

/**
* Display local list directory contents
*/
void displayLocalListDirectoryContents(void){
debug(DBG_LV0, 'void displayLocalListDirectoryContents()');

struct dirent *dirent_struct_ptr;
DIR *directory_stream_ptr;

if ((directory_stream_ptr = opendir('./')) != NULL){
printNameCurrentDirectory();

while ((dirent_struct_ptr = readdir(directory_stream_ptr))){
printf(' %s\n',dirent_struct_ptr->d_name);
}
}else{
errorDoExit(MSG_ERR_NO_DIR_STREAM);
}

}

/**
* Print the name of the current directory
*/
void printNameCurrentDirectory(void){
debug(DBG_LV0, 'void printNameCurrentDirectory()');

long size;
char *buf;
char *ptr;
size = pathconf('.', _PC_PATH_MAX);
if ((buf = (char *)malloc((size_t)size)) != NULL){
ptr = getcwd(buf, (size_t)size);
}else{
errorDoExit('Could not obtain the current directory');
}
printf('Current Directory: %s\n', ptr);
}

/**
* Receive the list of directory contents from the server
*/
void receiveListDirectoryContents(struct Connection *new_connection){
debug(DBG_LV0, 'receiveListDirectoryContents()');

sendData(new_connection, CODE_LS);

receiveData(new_connection);
while (strcmp(new_connection->recv_data, CODE_EOF) != 0){

if (strcmp(new_connection->recv_data, CODE_ERROR_LS) == 0){
fprintf(stderr, 'Couldn't read list directory contents!\n');
break;
}else{
printf('%s\n', new_connection->recv_data);
sendData(new_connection, CODE_OK);
}
receiveData(new_connection);
}

}

/**
* Put an encrypted file on the server
*/
void putFileOnServer(struct Connection *new_connection,
const char* filename){
debug(DBG_LV0, 'void putFileOnServer(filename: %s)', filename);

char str_filename[DATA_PACKET_SIZE];
char filename_ce[DATA_PACKET_SIZE];
char str_in_file[DATA_PACKET_SIZE];
char str_in_file_encrypt[DATA_PACKET_SIZE];
FILE *fp, *fp_ce;

strcpy(str_filename, filename);

debug(DBG_LV1, 'str_filename: %s', str_filename);

sprintf(filename_ce, '%s_ce', str_filename);

debug(DBG_LV1, 'filename_ce: %s', filename_ce);

debug(DBG_LV1, 'OPEN FILE TO READ');
fp = fopen(str_filename, 'r');

debug(DBG_LV1, 'OPEN FILE TO WRITE');
fp_ce = fopen(filename_ce, 'w');

if (fp == NULL || fp_ce == NULL){
fclose(fp_ce);
fclose(fp);
errorDoExit('Couldn't open file');
}else{

/* Send PUT code to server */
sendData(new_connection, CODE_PUT);

debug(DBG_LV0, 'Waiting for CODE_REQUEST_FILENAME');
/* Receive filename request form server */
receiveData(new_connection);
if (strcmp(new_connection->recv_data, CODE_REQUEST_FILENAME) == 0){

debug(DBG_LV0, 'Send filename');
/* Send filename to server */
sendData(new_connection, str_filename);

/* Receive request to send file */
receiveData(new_connection);
if (strcmp(new_connection->recv_data, CODE_REQUEST_FILE) == 0){
printf('Sending file: %s.\n', filename);
/* Encrypt file */
while(fgets(str_in_file, DATA_PACKET_SIZE, fp) != NULL){
debug(DBG_LV2, 'Reading (Len: %d): %s', strlen(str_in_file), str_in_file);

/* encrypt package */
strencrypt(str_in_file, str_in_file_encrypt);

/* Save it in <filename>_ce */
fprintf(fp_ce, '%s', str_in_file_encrypt);

/* send packages */
sendData(new_connection, str_in_file_encrypt);

/* Waiting for ok */
receiveData(new_connection);
if (strcmp(new_connection->recv_data, CODE_OK) == 0){
printf('OK');
}else{
errorDoExit('Wrong protocol - Waiting OK');
}

}
sendData(new_connection, CODE_EOF);

}else{
errorDoExit('Wrong protocol - Waiting request for file ');
}

}else{
errorDoExit('Wrong protocol - Waiting for request of filename');
}

}

fclose(fp);
fclose(fp_ce);

}

/**
* Encrypt the string using key
* @Return: Number of bytes encrypted
*/
int strencrypt(const char* str_in,
char* str_out){
debug(DBG_LV0, 'strencrypt(str_in: %s)', str_in);

int i, j;
int i_plain, i_key;

char str_key[DATA_PACKET_SIZE];

strcpy(str_key, ENCRYPTION_KEY);

for (i = 0, j = 0; i < strlen(str_in) - 1; ++i, ++j){

i_plain = (unsigned int)str_in[i] - CHAR_PLAIN_A;
i_key = (unsigned int)str_key[j] - CHAR_KEY_A;

str_out[i] = (char)((i_plain + i_key) % 26 + CHAR_CIPHER_A);

debug(DBG_LV1, '(str_out: %d) [%c:%d] = (str_in:%d)[%c:%d], (key:%d)[%c:%d]',
i, str_out[i], (int)str_out[i],
i, str_in[i], (int) str_in[i],
j, str_key[j], (int)str_key[j]);

if ( (j + 1) >= strlen(str_key)) j = -1;
}

return strlen(str_in);
}```

When I wrote the code, I was following certain guidelines. As you may think the code could be written better. I agree.

In case you have any questions about the code please post them. I will try to answer you as soon as possible.

## Algorithms Examples in ANSI C

Here are some examples of Algorithm written in ANSI C.
Even do they are written in ANSI C, I would advice to compile them in Linux as I did. If you encounter any problems or errors, please let me know by providing an example of the code, input, output, and an explanation. Thanks.
NOTIFICATION: These examples are provided for educational purposes. Using this code is under your own responsibility and risk. I do not take responsibilities of how they are used.