diff --git a/src/Makefile b/src/Makefile
index 55bf2ddf25f03a8335f536465d052e37d9e64921..c1073d9dd7d1220bdcb02c6dfc315e0b94c55cc9 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -4,8 +4,10 @@
 all:
 	@make -C cokebank all
 	@make -C server all
+	@make -C client all
 
 clean:
 	@make -C cokebank clean
 	@make -C server clean
+	@make -C client clean
 
diff --git a/src/client/main.c b/src/client/main.c
index c82d12d793f1bad6334452d23df3f3b0139d5b8f..ed7d1a22bbcf5fda3975fabf7548bb57174ea909 100644
--- a/src/client/main.c
+++ b/src/client/main.c
@@ -24,6 +24,8 @@
 #include <arpa/inet.h>
 #include <openssl/sha.h>	// SHA1
 
+#define	USE_NCURSES_INTERFACE	0
+
 // === TYPES ===
 typedef struct sItem {
 	char	*Ident;
@@ -159,11 +161,8 @@ int main(int argc, char *argv[])
 	}
 	
 	// and choose what to dispense
-	// TODO: ncurses interface (with separation between item classes)
-	// - Hmm... that would require standardising the item ID to be <class>:<index>
-	// Oh, why not :)
 	
-	#if 1
+	#if USE_NCURSES_INTERFACE
 	i = ShowNCursesUI();
 	#else
 	
@@ -224,7 +223,7 @@ int main(int argc, char *argv[])
 			printf("Item failed to dispense, is the slot empty?\n");
 			break;
 		default:
-			printf("Unknown response code %i\n", responseCode);
+			printf("Unknown response code %i ('%s')\n", responseCode, buffer);
 			break;
 		}
 	}
@@ -257,6 +256,9 @@ void ShowItemAt(int Row, int Col, int Width, int Index)
  */
 int ShowNCursesUI(void)
 {
+	// TODO: ncurses interface (with separation between item classes)
+	// - Hmm... that would require standardising the item ID to be <class>:<index>
+	// Oh, why not :)
 	 int	ch;
 	 int	i, times;
 	 int	xBase, yBase;
@@ -512,7 +514,6 @@ void Authenticate(int Socket)
 		// TODO: Get Salt
 		// Expected format: 100 SALT <something> ...
 		// OR             : 100 User Set
-		printf("string = '%s'\n", buf);
 		RunRegex(&gSaltRegex, buf, 4, matches, "Malformed server response");
 		if( atoi(buf) != 100 ) {
 			exit(-1);	// ERROR
@@ -521,7 +522,7 @@ void Authenticate(int Socket)
 			// Set salt
 			memcpy( salt, buf + matches[3].rm_so, matches[3].rm_eo - matches[3].rm_so );
 			salt[ matches[3].rm_eo - matches[3].rm_so ] = 0;
-			printf("Salt: '%s'\n", salt);
+//			printf("Salt: '%s'\n", salt);
 		}
 		
 		fflush(stdout);
@@ -542,7 +543,7 @@ void Authenticate(int Socket)
 				h[ 0], h[ 1], h[ 2], h[ 3], h[ 4], h[ 5], h[ 6], h[ 7], h[ 8], h[ 9],
 				h[10], h[11], h[12], h[13], h[14], h[15], h[16], h[17], h[18], h[19]
 				);
-			printf("Final hash: '%s'\n", buf);
+//			printf("Final hash: '%s'\n", buf);
 			fflush(stdout);	// Debug
 		}
 		
diff --git a/src/cokebank_basic/main.c b/src/cokebank_basic/main.c
index 62d49b85d1d7e313b76905c6cb9dafec74943e3f..ae111d4d88ecd2e226f6c118705247fc5771ecde 100644
--- a/src/cokebank_basic/main.c
+++ b/src/cokebank_basic/main.c
@@ -14,8 +14,6 @@
 #include <openssl/sha.h>
 #include "common.h"
 
-#define HACK_TPG_NOAUTH	1
-
 // === IMPORTS ===
 extern int	Bank_GetMinAllowedBalance(int ID);
 extern int	Bank_GetUserBalance(int ID);
diff --git a/src/server/common.h b/src/server/common.h
index f2eea0cdb066b4cca63a024b834cf2f47b24cce7..0d97ad5f968e465f579757a773b3a5db140d1eb2 100644
--- a/src/server/common.h
+++ b/src/server/common.h
@@ -9,6 +9,8 @@
 #ifndef _COMMON_H_
 #define _COMMON_H_
 
+#include <regex.h>
+
 // === CONSTANTS ===
 #define	DEFAULT_CONFIG_FILE	"/etc/opendispense/main.cfg"
 #define	DEFAULT_ITEM_FILE	"/etc/opendispense/items.cfg"
@@ -62,6 +64,11 @@ extern int	giNumHandlers;
 extern int	giDebugLevel;
 
 // === FUNCTIONS ===
+// --- Helpers --
+extern void	CompileRegex(regex_t *Regex, const char *Pattern, int Flags);
+extern int	RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage);
+
+// --- Dispense ---
 extern int	DispenseItem(int User, tItem *Item);
 
 // --- Logging ---
diff --git a/src/server/handler_coke.c b/src/server/handler_coke.c
index 978e3f5fe538d00c3dba7bb5ed973decdf82eded..3ab46c59d189f7c9279b33748cd8b39afa514097 100644
--- a/src/server/handler_coke.c
+++ b/src/server/handler_coke.c
@@ -41,7 +41,7 @@ int Coke_InitHandler()
 	if( giCoke_SerialFD == -1 ) {
 		fprintf(stderr, "ERROR: Unable to open coke serial port ('%s')\n", gsCoke_SerialPort);
 	}
-	regcomp(&gCoke_StatusRegex, "^slot\\s+(\\d)\\s+([^:]+):([a-zA-Z]+)\\s*", REG_EXTENDED);
+	CompileRegex(&gCoke_StatusRegex, "^slot\\s+(\\d)\\s+([^:]+):([a-zA-Z]+)\\s*", REG_EXTENDED);
 	return 0;
 }
 
@@ -49,17 +49,27 @@ int Coke_CanDispense(int User, int Item)
 {
 	char	tmp[32], *status;
 	regmatch_t	matches[4];
+	 int	ret;
 
 	// Sanity please
-	if( Item < 0 || Item > 6 )	return -1;
+	if( Item < 0 || Item > 6 )	return -1;	// -EYOURBAD
 	
 	// Ask the coke machine
 	sprintf(tmp, "s%i\n", Item);
 	write(giCoke_SerialFD, tmp, 2);
 
 	// Read the response
-	read(giCoke_SerialFD, tmp, sizeof(tmp)-1);
-	regexec(&gCoke_StatusRegex, tmp, sizeof(matches)/sizeof(matches[0]), matches, 0);
+	tmp[0] = '\0';
+	ret = read(giCoke_SerialFD, tmp, sizeof(tmp)-1);
+	//printf("ret = %i\n", ret);
+	if( ret <= 0 ) {
+		fprintf(stderr, "Coke machine is not being chatty (read = %i)\n", ret);
+		return -1;
+	}
+	ret = RunRegex(&gCoke_StatusRegex, tmp, sizeof(matches)/sizeof(matches[0]), matches, "Bad Response");
+	if( ret ) {
+		return -1;
+	}
 
 	tmp[ matches[3].rm_eo ] = '\0';
 	status = &tmp[ matches[3].rm_so ];
diff --git a/src/server/main.c b/src/server/main.c
index 80183ba3638f117b5ae398e7b33e58aad3a15a59..ac6dd27f61bc754945cfe66c4239a169d7e738fe 100644
--- a/src/server/main.c
+++ b/src/server/main.c
@@ -89,3 +89,33 @@ int main(int argc, char *argv[])
 	return 0;
 }
 
+int RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage)
+{
+	 int	ret;
+	
+	ret = regexec(regex, string, nMatches, matches, 0);
+	if( ret ) {
+		size_t  len = regerror(ret, regex, NULL, 0);
+		char    errorStr[len];
+		regerror(ret, regex, errorStr, len);
+		printf("string = '%s'\n", string);
+		fprintf(stderr, "%s\n%s", errorMessage, errorStr);
+		exit(-1);
+	}
+	
+	return ret;
+}
+
+void CompileRegex(regex_t *regex, const char *pattern, int flags)
+{
+	 int	ret = regcomp(regex, pattern, flags);
+	if( ret ) {
+		size_t	len = regerror(ret, regex, NULL, 0);
+		char    errorStr[len];
+		regerror(ret, regex, errorStr, len);
+		fprintf(stderr, "Regex compilation failed - %s\n", errorStr);
+		exit(-1);
+	}
+}
+
+
diff --git a/src/server/server.c b/src/server/server.c
index 5d375ee7130719d7ef42a0555cd1c56ce43ab343..e0fcafa64b2511173f37de18229901842690af14 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -16,11 +16,15 @@
 #include <unistd.h>
 #include <string.h>
 
+// HACKS
+#define HACK_TPG_NOAUTH	1
+
+// Statistics
 #define MAX_CONNECTION_QUEUE	5
 #define INPUT_BUFFER_SIZE	256
 
-#define HASH_TYPE	SHA512
-#define HASH_LENGTH	64
+#define HASH_TYPE	SHA1
+#define HASH_LENGTH	20
 
 #define MSG_STR_TOO_LONG	"499 Command too long (limit "EXPSTR(INPUT_BUFFER_SIZE)")\n"
 
@@ -40,6 +44,7 @@ typedef struct sClient
 
 // === PROTOTYPES ===
 void	Server_Start(void);
+void	Server_Cleanup(void);
 void	Server_HandleClient(int Socket, int bTrusted);
 char	*Server_ParseClientCommand(tClient *Client, char *CommandString);
 // --- Commands ---
@@ -69,6 +74,7 @@ struct sClientCommand {
 	{"DISPENSE", Server_Cmd_DISPENSE}
 };
 #define NUM_COMMANDS	(sizeof(gaServer_Commands)/sizeof(gaServer_Commands[0]))
+ int	giServer_Socket;
 
 // === CODE ===
 /**
@@ -76,12 +82,14 @@ struct sClientCommand {
  */
 void Server_Start(void)
 {
-	 int	server_socket, client_socket;
+	 int	client_socket;
 	struct sockaddr_in	server_addr, client_addr;
 
+	atexit(Server_Cleanup);
+
 	// Create Server
-	server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-	if( server_socket < 0 ) {
+	giServer_Socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if( giServer_Socket < 0 ) {
 		fprintf(stderr, "ERROR: Unable to create server socket\n");
 		return ;
 	}
@@ -93,14 +101,16 @@ void Server_Start(void)
 	server_addr.sin_port = htons(giServer_Port);	// Port
 
 	// Bind
-	if( bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0 ) {
+	if( bind(giServer_Socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0 ) {
 		fprintf(stderr, "ERROR: Unable to bind to 0.0.0.0:%i\n", giServer_Port);
+		perror("Binding");
 		return ;
 	}
 	
 	// Listen
-	if( listen(server_socket, MAX_CONNECTION_QUEUE) < 0 ) {
+	if( listen(giServer_Socket, MAX_CONNECTION_QUEUE) < 0 ) {
 		fprintf(stderr, "ERROR: Unable to listen to socket\n");
+		perror("Listen");
 		return ;
 	}
 	
@@ -111,7 +121,7 @@ void Server_Start(void)
 		uint	len = sizeof(client_addr);
 		 int	bTrusted = 0;
 		
-		client_socket = accept(server_socket, (struct sockaddr *) &client_addr, &len);
+		client_socket = accept(giServer_Socket, (struct sockaddr *) &client_addr, &len);
 		if(client_socket < 0) {
 			fprintf(stderr, "ERROR: Unable to accept client connection\n");
 			return ;
@@ -148,6 +158,12 @@ void Server_Start(void)
 	}
 }
 
+void Server_Cleanup(void)
+{
+	printf("Close(%i)\n", giServer_Socket);
+	close(giServer_Socket);
+}
+
 /**
  * \brief Reads from a client socket and parses the command strings
  * \param Socket	Client socket number/handle