From 0a44510413b543f10026804056d7dc6870cb1922 Mon Sep 17 00:00:00 2001
From: Christoph Steup <christoph.steup@student.uni-magdeburg.de>
Date: Mon, 24 Jan 2011 17:24:00 +0100
Subject: [PATCH] OOStuBs Task6


diff --git a/Makefile b/Makefile
index f56ed0d..5da69cf 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ CXXFLAGS=
 LDFLAGS=-O0
 ASMFLAGS=-g
 
-OBJECT_IGNORE= task1.o task2.o task3.o task4.o task5.o
+OBJECT_IGNORE= task1.o task2.o task3.o task4.o task5.o task6.o string.o
 
 INCPATHS=
 LDPATHS=
diff --git a/include/device/keyboard.h b/include/device/keyboard.h
index 0f8997f..c19f581 100644
--- a/include/device/keyboard.h
+++ b/include/device/keyboard.h
@@ -11,12 +11,14 @@
 
 #include "machine/keyctrl.h"
 #include "guard/gate.h"
- 
+#include "machine/key.h"
+
 /** \brief %Keyboard driver with interrupt support
  *
- * This class is a subclass of Gate and implements the interrupt routine used 
- * for the keyboard.
- */
+ * This class is a subclass of Gate and implements the interrupt routine used
+ * for the keyboard. It also contains a semaphore based one elementary key
+ * buffer to store pressed keys.
+ **/
 class Keyboard : public Keyboard_Controller, public Gate  {
 private:
 	/** \brief storage for fetched keys
@@ -47,7 +49,15 @@ public:
    *
    * \todo write implementation
    **/
-  virtual void epilogue();        
+  virtual void epilogue();
+
+  /** \brief get the next Key or block current Thread
+   *
+   * \todo write implementation
+   *
+   * \return the next Key, that was pressed on the keyboard
+   **/
+  Key getkey();
 };
 
 #endif
diff --git a/include/meeting/semaphore.h b/include/meeting/semaphore.h
new file mode 100644
index 0000000..b5bf74b
--- /dev/null
+++ b/include/meeting/semaphore.h
@@ -0,0 +1,60 @@
+#ifndef __semaphore_header__
+#define __semaphore_header__
+
+#include "meeting/semaphore.h"
+#include "meeting/waitingroom.h"
+
+/**\brief Counting semaphore representation
+ *
+ * This class represents a counting semaphore. It is initialized with a certain
+ * value and provides operations to aquire and release ressources. If all
+ * ressources are aquired any additional aquiring will block the currently
+ * active Customer until ressources are released.
+ **/
+class Semaphore : public Waitingroom
+{
+	private:
+		/** \brief internal representation of the semaphore counter
+		 *
+		 * \todo write declaration
+		 **/
+
+	public:
+		/**\brief Construct a new semaphore with initial value
+		 *
+		 * \todo write implementation
+		 *
+		 * \param value initial value of the semaphore
+		 **/
+		Semaphore(unsigned int value);
+
+		/**\brief virtual destructor to wake up blocked Customers**/
+		virtual ~Semaphore(){}
+
+		/**\brief aquire a ressource from this semaphore
+		 *
+		 * This method can block if no more free ressources are available.  The
+		 * currently active Customer will be suspended until a ressource is
+		 * freed by the signal() or v() call.
+		 *
+		 * \todo write implementation
+		 **/
+		void p();
+
+		/**\brief release a ressource from this semaphore
+		 *
+		 * This method readies a Customer if there is one currently waiting for
+		 * this semaphore.
+		 *
+		 * \todo write implementation
+		 **/
+		void v();
+
+		/**\copydoc p()**/
+		void wait(){p();}
+
+		/**\copydoc v()**/
+		void signal(){v();}
+};
+
+#endif
diff --git a/include/meeting/waitingroom.h b/include/meeting/waitingroom.h
new file mode 100644
index 0000000..387b914
--- /dev/null
+++ b/include/meeting/waitingroom.h
@@ -0,0 +1,33 @@
+#ifndef __waitingroom_header__
+#define __waitingroom_header__
+
+#include "object/queue.h"
+#include "thread/customer.h"
+
+/**\brief Base class of all waiting rooms
+ *
+ * Every class implementing a ressource on which access blocking is possible
+ * should inherit from this class.  This class contains the necessary
+ * functionality to kill currently blocked Customers and to wake up all
+ * Customers on destruction of the ressource.
+ **/
+class Waitingroom : public Queue { public:
+
+		/**\brief virtual destructor
+		 *
+		 * Wake up all the currently blocked Customers of this %Waitingroom.
+		 *
+		 * \todo write implementation
+		 **/
+		virtual ~Waitingroom();
+
+		/**\brief remove a customer from the blocked queue
+		 *
+		 * \todo write implementation
+		 *
+		 * \param that the Customer to be removed
+		 **/
+		virtual void remove(Customer& that);
+};
+
+#endif
diff --git a/include/object/string.h b/include/object/string.h
new file mode 100644
index 0000000..2d5d62d
--- /dev/null
+++ b/include/object/string.h
@@ -0,0 +1,117 @@
+#ifndef __string_header__
+#define __string_header__
+
+#include "object/o_stream.h"
+
+class StringBase{
+public:
+	enum ReturnValues{
+		smaller,
+		equal,
+		bigger
+	};
+protected:
+	static ReturnValues cmpFunc(const char* b1, unsigned char b1Length, const char *b2, unsigned char b2Length=0);
+
+	static short appendChar(char* b1, unsigned char index, unsigned char maxLength, char c);
+
+	static short appendFunc(char* b1, unsigned char b1Size, const char *b2, unsigned char b2Length=0);
+
+public:
+	static unsigned int strlen(const char* string);
+};
+
+class StaticString : public StringBase
+{
+	private:
+		char* buffer;
+		unsigned short index;
+
+	public:
+		const unsigned int maxLength;
+
+		StaticString(char* buffer, unsigned char maxLength) : buffer(buffer), index(0), maxLength(maxLength){}
+
+		StaticString& operator=(const char* string){
+			index=appendFunc(buffer, maxLength, string);
+			return *this;
+		}
+
+		unsigned char length() const{
+			return index;
+		};
+
+
+		StaticString& operator+=(const char* b){
+			index+=appendFunc(&buffer[index], maxLength-index, b);
+			return *this;
+		}
+
+		StaticString& operator+=(StaticString& b){
+			index+=appendFunc(&buffer[index], maxLength-index, b.buffer, b.index);
+			return *this;
+		}
+
+		StaticString& operator+=(char c){
+			index+=appendChar(buffer, index, maxLength, c);
+			return *this;
+		}
+
+		bool operator==(const char* b) const{
+			return (equal==cmpFunc(buffer, index, b));
+		}
+
+		bool operator<(const char* b) const{
+			return (smaller==cmpFunc(buffer, index, b));
+		}
+
+		bool operator>(const char* b) const{
+			return (bigger==cmpFunc(buffer, index, b));
+		}
+
+		bool operator<=(const char* b) const{
+			ReturnValues ret=cmpFunc(buffer, index, b);
+			return (ret==equal||ret==smaller);
+		}
+
+		bool operator>=(const char* b) const{
+			ReturnValues ret=cmpFunc(buffer, index, b);
+			return (ret==equal||ret==bigger);
+		}
+
+		bool operator==(const StaticString& b) const{
+			return (equal==cmpFunc(buffer, index, b.buffer, b.index));
+		}
+
+		bool operator<(const StaticString& b) const{
+			return (equal==cmpFunc(buffer, index, b.buffer, b.index));
+		}
+
+		bool operator>(const StaticString& b) const{
+			return (equal==cmpFunc(buffer, index, b.buffer, b.index));
+		}
+
+		bool operator<=(const StaticString& b) const{
+			ReturnValues ret=cmpFunc(buffer, index, b.buffer, b.index);
+			return (ret==equal||ret==smaller);
+		}
+
+		bool operator>=(const StaticString& b) const{
+			ReturnValues ret=cmpFunc(buffer, index, b.buffer, b.index);
+			return (ret==equal||ret==bigger);
+		}
+
+		char operator[](unsigned char i) const{
+			return buffer[i];
+		}
+
+		char& operator[](unsigned char i){
+			return buffer[i];
+		}
+
+		short find(const char* string, unsigned short start=0);
+};
+
+O_Stream& operator<<(O_Stream& out, const StaticString& s);
+
+#endif
diff --git a/include/syscall/guarded_keyboard.h b/include/syscall/guarded_keyboard.h
new file mode 100644
index 0000000..a510e3d
--- /dev/null
+++ b/include/syscall/guarded_keyboard.h
@@ -0,0 +1,38 @@
+#ifndef __guarded_keyboard__
+#define __guarded_keyboard__
+
+#include "device/keyboard.h"
+#include "guard/secure.h"
+#include "machine/multiboot.h"
+
+/** \brief Extended Keyboard Driver
+ *
+ * This class provides a secure Interface to the Keyboard Driver, that provides
+ * keys to the Userspace Application.
+ *
+ **/
+class Guarded_Keyboard : protected Keyboard{
+public:
+	/** \brief get a new Key from the keyboard
+	 *
+	 * If there are no new keys, the method will block the currently active
+	 * Customer until one is available.
+	 *
+	 * \todo write implementation
+	 *
+	 * \return the next key, the user has hit
+	 **/
+	Key getkey(){
+	}
+
+	/** \brief register the Keyboard for interrupt handling
+	 *
+	 * This method should only be called by kernel.
+	 *
+	 * \todo write implementation
+	 **/
+	void plugin(){
+	}
+};
+
+#endif
diff --git a/include/syscall/guarded_scheduler.h b/include/syscall/guarded_scheduler.h
index 40144ea..1edd4c0 100644
--- a/include/syscall/guarded_scheduler.h
+++ b/include/syscall/guarded_scheduler.h
@@ -10,15 +10,15 @@
 #define __guarded_scheduler_include__
 
 #include "syscall/thread.h"
-#include "thread/scheduler.h"
+#include "thread/organizer.h"
 
-/** \brief Scheduler guarded by Secure
+/** \brief User interface to the Scheduler. 
  *
- * This Scheduler is interrupt safe and therefore needed to cope with
- * preemptive switching of Threads.  Since now the multitasking is preemptiv
- * Threads instead of Coroutines are handled.
+ * The defined methods are guarded but otherwise directly mapped to the methods 
+ * of the superclasses Organizer respective Scheduler. 
+ * Also Threads and Customers are handled instead of Entrants.
  **/
-class Guarded_Scheduler : public Scheduler{
+class Guarded_Scheduler : protected Organizer{
 public:
   /** \brief Start the scheduling by starting the first thread
    *
@@ -26,7 +26,9 @@ public:
    *
    * \todo write implementation
    **/ 
-  void schedule();
+  void schedule(){
+
+  }
   
   /** \brief Insert the specified thread into the ready queue
    *
@@ -34,15 +36,19 @@ public:
    *
    * \param that reference to the thread to be inserted
    **/
-  void ready(Thread& that);
+  void ready(Thread& that){
 
+  }
+  
   /** \brief Remove the currently active thread from the queue
    *
    * If there are no more threads, wait for new threads to arive.
    *
    * \todo write implementation
    **/
-  void exit();
+  void exit(){
+
+  }
 
   /** \brief Remove the specified thread from the queue of processes.
    *
@@ -51,8 +57,10 @@ public:
    * \todo write implementation
    *
    * \param that reference of the thread to be killed.
-   */
-  void kill(Thread* that);
+   **/
+  void kill(Thread* that){
+
+  }
 
   /** \brief Use the scheduling algorithm to get the next thread and
    * resume with that thread.
@@ -60,6 +68,14 @@ public:
    * \todo write implementation
    **/
   void resume();
+
+  /** \brief get the currently active Thread
+   *
+   * \return the current Thread
+   **/
+  Thread* active() const{
+	return static_cast<Thread*>(Organizer::active());
+  }
 };
 
 #endif
diff --git a/include/syscall/thread.h b/include/syscall/thread.h
index 77b5fd7..6c9ee0e 100644
--- a/include/syscall/thread.h
+++ b/include/syscall/thread.h
@@ -9,22 +9,22 @@
 #ifndef __thread_include__
 #define __thread_include__
 
-#include "thread/entrant.h"
+#include "thread/customer.h"
 
 /** \brief Threads are preemptible multitasking entities
  *
- * Every %Thread contain exactly one line of execution, due to their preemptiveness all operations concerning them must be called Secure
- *
-**/
-class Thread : public Entrant{
+ * Every %Thread contain exactly one line of execution, due to their
+ * preemptiveness all operations concerning them must be called Secure
+ **/
+class Thread : protected Customer{
 public:
   /** \brief Default constructor
    *
-   * Delegates initialization to the underlying Entrant object
+   * Delegates initialization to the underlying Customer object
    *
    * \param tos pointer to the stack used by this thread
-   */
-  Thread(void* tos) : Entrant(tos){}
+   **/
+  Thread(void* tos) : Customer(tos){}
 
    /** \brief triggers a context switch
    *
@@ -44,10 +44,10 @@ public:
 
   /** \brief real function of the %Thread,
    *
-   * since every thread does something differenct this method has to be
+   * since every thread does something different this method has to be
    * implemented by a subclass of Thread (e.g. Application).
    **/
-  virtual void action() = 0;   
+  virtual void action() = 0;
 };
 
 #endif
diff --git a/include/thread/customer.h b/include/thread/customer.h
new file mode 100644
index 0000000..3fe9368
--- /dev/null
+++ b/include/thread/customer.h
@@ -0,0 +1,51 @@
+#ifndef __customer_header__
+#define __customer_header__
+
+#include "thread/entrant.h"
+
+/* Forward declaration to avoid circular dependancies**/
+class Waitingroom;
+
+/**\brief Extension of a Thread
+ *
+ * This extension of Thread can be put in a blocking state, where operating is suspended until a certain condition is met.
+ **/
+class Customer : public Entrant
+{
+	private:
+		/**\brief Waitingroom, the customer is currently waiting in
+		 *
+		 * if the Customer is not waiting, this field should contain NULL
+		 **/
+		Waitingroom* room;
+
+	public:
+		/**\brief Constructor passing top of stack pointer
+		 *
+		 * \param tos the top of stack, the Customer should use
+		 **/
+		Customer(void* tos) : Entrant(tos), room(0){}
+
+	private:
+		/**\brief set the Waitingroom the %Customer is waiting in
+		 *
+		 * \param room the Waitingroom to wait in
+		 **/
+		void waiting_in(Waitingroom *room){
+			this->room=room;
+		}
+	
+	public:
+		/**\brief get the Waitingroom the %Customer is waiting in
+		 *
+		 * \return the actual Waitingroom
+		 **/
+		Waitingroom* waiting_in() const{
+			return room;
+		}
+
+	/* friend declaration to access the room variable from the organizer */
+	friend class Organizer;
+};
+
+#endif
diff --git a/include/thread/organizer.h b/include/thread/organizer.h
new file mode 100644
index 0000000..7bab148
--- /dev/null
+++ b/include/thread/organizer.h
@@ -0,0 +1,56 @@
+#ifndef __organizer_header__
+#define __organizer_header__
+
+#include "thread/scheduler.h"
+#include "thread/customer.h"
+#include "meeting/waitingroom.h"
+
+/**\brief Organization of waiting Customers
+ *
+ * This class handles the blocking and the wakeup of Customers.
+ **/
+class Organizer : public Scheduler
+{
+public:
+	/**\brief blocks the currently active Customer
+	 *
+	 * The Customer will be put in the supplied Waitingroom to wait for a
+	 * condition dependant on the Waitingroom
+	 *
+	 * \todo write implementation
+	 *
+	 * \param waitingroom the waitingroom to wait in
+	 **/
+	void block(Waitingroom& waitingroom);
+
+	/**\brief wakes the supplied Customer up
+	 *
+	 * The supplied Customer will be put to the end of the ready queue of the scheduler.
+	 *
+	 * \todo write implementation
+	 *
+	 * \param customer The Customer to be woken up
+	 **/
+	void wakeup(Customer& customer);
+
+	/**\brief kill a Customer
+	 *
+	 * This method removes the supplied Customer from either the ready queue or
+	 * the waitingroom queue he is currently waiting in.
+	 *
+	 * \todo write implementation
+	 *
+	 * \param that The Customer to kill
+	 **/
+	void kill(Customer& that);
+
+	/**\brief return the currently active Customer
+	 *
+	 * \return the currently active Customer
+	 **/
+    Customer* active() const{
+		return static_cast<Customer*>(Scheduler::active());
+    }
+};
+
+#endif
diff --git a/include/user/task6.h b/include/user/task6.h
new file mode 100644
index 0000000..94ef7ad
--- /dev/null
+++ b/include/user/task6.h
@@ -0,0 +1,52 @@
+#ifndef __task6_header__
+#define __task6_header__
+
+#include "user/task5.h"
+#include "object/string.h"
+
+class Task6 : public Task5{
+
+enum Parameters
+{
+	cmdX = 0,
+	cmdY = 20
+};
+
+class Cmd : public Application{
+	enum Parameters{
+		bufferSize=128,
+		appNum=3
+	};
+
+	unsigned short x,y;
+	char *buffer;
+	StaticString inputBuffer;
+	Application* apps[3];
+	const char* appNames[3];
+	bool running[3];
+	
+	void clearBuffer();
+	void parseBuffer();
+	void putChar(char c);
+	void startApp(unsigned int i);
+	void stopApp(unsigned int i);
+
+public:
+	Cmd(void* tos, unsigned short x, unsigned short y,
+		Application& app0, const char* app0Name,
+		Application& app1, const char* app1Name,
+		Application& app2, const char* app2Name);
+	virtual void action();
+};
+
+Cmd cmd;
+
+static unsigned int space;
+static unsigned char cmdStack[stackSize];
+
+public:
+	Task6();
+	virtual void action();
+};
+
+#endif
diff --git a/src/main.cc b/src/main.cc
index a313663..02a2ac1 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -9,7 +9,7 @@
 /* INCLUDES */
 
 #include "machine/multiboot.h"
-//#include "user/task5.h"
+//#include "user/task6.h"
 
 /* GLOBAL OBJECTS */
 
@@ -24,7 +24,7 @@ extern "C" void kernel(uint32_t magic, const Multiboot_Info* addr);
  * This is the entry point of the operating system.  If this function returns
  * all interrupts will be disabled and the cpu will be halted.
  *
- * \todo uncomment Task5
+ * \todo uncomment Task6
  *
  * \param magic bootloader magic value
  * \param addr address of multiboot info structure
@@ -32,7 +32,7 @@ extern "C" void kernel(uint32_t magic, const Multiboot_Info* addr);
 
 void kernel(uint32_t magic, const Multiboot_Info* addr){
 
-//Task5 task;
+//Task6 task;
 
 //scheduler.ready(task);
 
diff --git a/src/meeting/semaphore.cc b/src/meeting/semaphore.cc
new file mode 100644
index 0000000..c239b87
--- /dev/null
+++ b/src/meeting/semaphore.cc
@@ -0,0 +1 @@
+#include "meeting/semaphore.h"
diff --git a/src/meeting/waitingroom.cc b/src/meeting/waitingroom.cc
new file mode 100644
index 0000000..5cadc62
--- /dev/null
+++ b/src/meeting/waitingroom.cc
@@ -0,0 +1 @@
+#include "meeting/waitingroom.h"
diff --git a/src/object/string.cc b/src/object/string.cc
new file mode 100644
index 0000000..0913013
--- /dev/null
+++ b/src/object/string.cc
@@ -0,0 +1,78 @@
+#include "object/string.h"
+
+/*not yet tested*/
+StringBase::ReturnValues StringBase::cmpFunc(const char* b1, unsigned char b1Length, const char *b2, unsigned char b2Length){
+	while(b1Length&&b2Length)
+	{
+		if(*b1<*b2)
+			return smaller;
+		if(*b1>*b2)
+			return bigger;
+		b1Length--;
+		b2Length--;
+		b1++;
+		b2++;
+	}
+
+	if(b1Length)
+		return bigger;
+	if(b2Length)
+		return smaller;
+
+	return equal;
+}
+
+short StringBase::appendChar(char* b1, unsigned char index, unsigned char maxLength, char c){
+	if(c=='\b'&&index>0)
+		return -1;
+	if(c=='\b'&&index==0)
+		return 0;
+	if(index==maxLength)
+		return 0;
+	b1[index]=c;
+	return 1;
+}
+
+/* not yet tested */
+short StringBase::appendFunc(char* b1, unsigned char b1Size, const char *b2, unsigned char b2Length){
+	short appended=0;
+
+	while(b2Length && b1Size>appended)
+	{
+		appended+=appendChar(b1, appended, b1Size, *b2);
+
+		b2++;
+		b2Length--;
+	}
+
+	return appended;
+}
+
+short StaticString::find(const char *string, unsigned short indexA){
+	unsigned short pos=0;
+	unsigned short indexB=0;
+	for(;indexA<index;indexA++)
+	{
+		if(buffer[indexA]==string[indexB])
+			indexB++;
+		else
+			pos++;
+		if(string[indexB]=='\0')
+			return pos;
+	}
+	return -1;
+}
+
+unsigned int StringBase::strlen(const char* string)
+{
+	unsigned int i=0;
+	while(string[i]!='\0')
+		i++;
+	return i;
+}
+
+O_Stream& operator<<(O_Stream& out, const StaticString& s){
+	for(unsigned char i=0;i<s.length();i++)
+		out << s[i];
+	return out;
+}
diff --git a/src/thread/organizer.cc b/src/thread/organizer.cc
new file mode 100644
index 0000000..7b53366
--- /dev/null
+++ b/src/thread/organizer.cc
@@ -0,0 +1 @@
+#include "thread/organizer.h"
diff --git a/src/user/task6.cc b/src/user/task6.cc
new file mode 100644
index 0000000..7617546
--- /dev/null
+++ b/src/user/task6.cc
@@ -0,0 +1,177 @@
+#include "user/task6.h"
+#include "device/cgastr.h"
+#include "syscall/guarded_scheduler.h"
+#include "syscall/guarded_keyboard.h"
+
+extern CGA_Stream kout;
+extern Guarded_Scheduler scheduler;
+extern Guarded_Keyboard keyboard;
+
+unsigned char Task6::cmdStack[];
+
+Task6::Cmd::Cmd(void* tos,
+				unsigned short x,
+				unsigned short y,
+				Application& app0,
+				const char* app0Name,
+				Application& app1,
+				const char* app1Name,
+				Application& app2,
+				const char* app2Name) 
+				: Application(tos), inputBuffer(buffer, bufferSize){
+	this->x=x;
+	this->y=y;
+	this->apps[0]=&app0;
+	this->apps[1]=&app1;
+	this->apps[2]=&app2;
+	this->appNames[0]=app0Name;
+	this->appNames[1]=app1Name;
+	this->appNames[2]=app2Name;
+	for(unsigned int i=0;i<appNum;i++)
+		this->running[i]=false;
+}
+
+void Task6::Cmd::clearBuffer(){
+	Secure s;
+	kout.flush();
+	kout.setpos(x,y);
+	for(unsigned int i=0;i<inputBuffer.length();i++)
+		kout << ' ';
+	kout.flush();
+	kout.setpos(x,y);
+	inputBuffer="";
+}
+
+void Task6::Cmd::parseBuffer(){
+	
+	unsigned int i;
+	short pos;
+
+	{
+		Secure s;
+		kout.setpos(0,y+2);
+		for(unsigned int i=0;i<80;i++)
+			kout << ' ';
+		kout.flush();
+	}
+
+	if(inputBuffer.find("tasks")>=0)
+	{
+		Secure s;
+		kout.setpos(0,y+2);
+		kout << "Available tasks: ";
+		for(unsigned short i=0;i<appNum;i++)
+			kout << appNames[i] << ' ';
+		kout.flush();
+		return;
+	}
+
+	if((pos=inputBuffer.find("start"))>=0)
+	{
+		for(i=0;i<appNum;i++)
+			if(inputBuffer.find(appNames[i], pos+6)>=0)
+			{
+				if(!running[i])
+				{
+					scheduler.ready(*apps[i]);
+					running[i]=true;
+				}
+				else
+				{
+					Secure s;
+					kout.setpos(0,y+2);
+					kout << "Task already running!";
+					kout.flush();
+				}
+				return;
+			}
+	}
+
+	if((pos=inputBuffer.find("stop"))>=0)
+	{
+		for(i=0;i<appNum;i++)
+			if(inputBuffer.find(appNames[i], pos+5)>=0)
+			{
+				if(running[i])
+				{
+					scheduler.kill(*apps[i]);
+					running[i]=false;
+				}
+				else
+				{
+					Secure s;
+					kout.setpos(0,y+2);
+					kout << "Task not running!";
+					kout.flush();
+				}
+				return;
+			}
+	}
+
+	Secure s;
+	kout.setpos(0,y+2);
+	kout << "commands: start stop tasks";
+	kout.flush();
+
+}
+
+void Task6::Cmd::startApp(unsigned int i){
+	if(!running[i])
+		scheduler.ready(*apps[i]);
+}
+
+void Task6::Cmd::stopApp(unsigned int i){
+	if(running[i])
+		scheduler.kill(*apps[i]);
+}
+
+void Task6::Cmd::putChar(char c){
+	inputBuffer+=c;
+
+	Secure s;
+	kout.flush();
+	kout.setpos(x,y);
+	kout << inputBuffer;
+	if(c=='\b')
+		kout << ' ';
+	kout.flush();
+}
+
+void Task6::Cmd::action(){
+	{
+	Secure s;
+	kout.flush();
+	kout.setpos(x, y);
+	kout << "oostubs:$ ";
+	kout.flush();
+	kout.getpos(x,y);
+	for(unsigned int i=0;i<bufferSize;i++)
+		kout << ' ';
+	kout.flush();
+	kout.setpos(x, y);
+	}
+	while(true)
+	{
+		char c=keyboard.getkey().ascii();
+		if(c=='\n')
+		{
+			parseBuffer();
+			clearBuffer();
+		}
+		else
+			putChar(c);
+	}
+}
+
+Task6::Task6() : Task5(), cmd(cmdStack+stackSize, cmdX, cmdY,
+							  counter1, "counter1",
+							  counter2, "counter2",
+							  rotCursor, "rotatingCursor"){
+	kout.clear();
+	kout.setpos(31,1);
+	kout << "OOStuBs - Task 6" << endl << endl;
+}
+
+void Task6::action(){
+	scheduler.ready(cmd);
+}
-- 
1.7.3.4

