diff --git a/src/passbook.c b/src/passbook.c
index fb04ba8cf7930eb43d75e61d521806466210c40f..e0bc21577b28a911c8fc4b96ed3bccf40a9bd428 100644
--- a/src/passbook.c
+++ b/src/passbook.c
@@ -3,14 +3,15 @@
 #include <stdlib.h>
 #include <assert.h>
 
-const char INSTRUCTION_LOGIN[] = "login";
+#include "debug.h"
 
-const char INSTRUCTION_ADD[] = "add";
+const char INSTRUCTION_PUT[] = "put";
 
-const char INSTRUCTION_REMOVE[] = "remove";
+const char INSTRUCTION_REMOVE[] = "rem";
 
-const char INSTRUCTION_LOOKUP[] = "lookup";
+const char INSTRUCTION_GET[] = "get";
 
+const char INSTRUCTION_MPW[] = "mpw";
 
 typedef struct {
   char * username;
@@ -135,6 +136,97 @@ static node_t * rem(node_t *p, const char *url){
   return start; // not found
 }
 
+const char WHITESPACE[] = " \t\r\n";
+
+
+/* tokenise a string, splitting on characters in WHITESPACE, up to
+ * a maxium of toksLen tokens, each of whose start addresses is put into
+ * toks and each of which is NUL-terminated in str.
+ * returns number of tokens found */
+unsigned int tokenise(char *str, char * toks[], unsigned int toksLen){
+  unsigned numToks = 0;
+  while (numToks < toksLen){
+    /* strip leading whitespace */     
+    size_t start = strspn(str,WHITESPACE);
+    debug_printf("start: %lu\n",start);
+    if (str[start] != '\0'){
+      toks[numToks] = &(str[start]);    
+      debug_printf("Token %u starts here: --begintok--%s--end--\n",numToks,toks[numToks]);
+    
+      /* compute the length of the token */
+      const size_t tokLen = strcspn(toks[numToks],WHITESPACE);
+      if (tokLen > 0){
+        toks[numToks][tokLen] = '\0';
+        debug_printf("Found token %d: --begintok--%s--endtok--\n",numToks,toks[numToks]);
+        str = &(toks[numToks][tokLen+1]);
+        numToks++;
+      }else{
+        debug_printf("tokLen was: %lu\n",tokLen);
+        return numToks;
+      }
+    }else{
+      return numToks;
+    }
+  }
+  return numToks;
+}
+
+#define MAX_LINE_LENGTH  1022
+
+/* two extra chars in each line: the newline '\n' and NUL '\0' */
+#define INSTRUCTION_LENGTH (MAX_LINE_LENGTH+2)
+
+char inst[INSTRUCTION_LENGTH];
+
+static int execute(void){
+  assert(0 && "not implemented yet");
+  return 0;
+}
+
+static int run(void){
+  debug_printf("Attempting to read program. max line length: %d\n",MAX_LINE_LENGTH);
+
+  FILE *f = stdin;
+  assert(f != NULL);
+  
+  int instructionCount = 0;
+  while (1){
+    char * res = fgets(inst,MAX_LINE_LENGTH+2,f);
+    if (res == NULL){
+      if (feof(f)){
+        /* end of file */
+        fclose(f);
+        return instructionCount;
+      }else{
+        debug_printf("Error while reading, having read %d lines\n",instructionCount);
+        fclose(f);
+        return -1;
+      }
+    }
+    if (inst[MAX_LINE_LENGTH] != '\0'){
+      if (!(inst[MAX_LINE_LENGTH] == '\n' && inst[MAX_LINE_LENGTH+1] == '\0')){
+        debug_printf("Line %d exceeds maximum length (%d)\n",instructionCount+1,MAX_LINE_LENGTH);
+        debug_printf("(Expected at array index %d to find NUL but found '%c' (%d))\n",MAX_LINE_LENGTH,inst[MAX_LINE_LENGTH],inst[MAX_LINE_LENGTH]);
+        fclose(f);
+        return -1;
+      }
+    }else{
+      /* inst[MAX_LINE_LENGTH] == '\0', so
+         strlen is guaranteed to be <= MAX_LINE_LENGTH
+         Check if it has a newline and add it if it needs it */
+      size_t len = strlen(inst);
+      if (len > 0){
+        if (inst[len-1] != '\n'){
+          inst[len] = '\n';
+          inst[len+1] = '\0';
+        }
+      }
+    }
+    instructionCount++;
+  }
+  execute();
+}
+
 
 int main(void){
   cred_t cred1, cred2;
@@ -150,6 +242,8 @@ int main(void){
   assert(p == lookup(p,"http://meh.com"));
   assert(strcmp(lookup(p,"http://blah.com")->cred.username,cred1.username) == 0);
   p = put(p,"http://blah.com",cred2);
-  assert(strcmp(lookup(p,"http://blah.com")->cred.username,cred2.username) == 0);  
+  assert(strcmp(lookup(p,"http://blah.com")->cred.username,cred2.username) == 0);
+
+  run();
   return 0;
 }