Wednesday, 27 July 2011

Keyboard Woes and Obsessions

So, in a prior post I extolled my employers to stop being cheap asses and to invest in decent equipment for my lightening fast keyboard fingers to work on.  Well, my calls for a working keyboard were answered, however, my prayers for a decent keyboard were not really met... In fact I'm so befuddled with the outcome I'm not sure whether what I have now is an improvement.

Let me explain, I had a Dell, with horrible rubber dome keys.  I had one of these at home up until we got a puppy earlier this year and it was a god send when he ate mine, so imagine my excitement when at work my left shift and control keys were getting a bit stiff and unreliable.

Now, I reckon I type at about 85-92 words per minute, I am a programmer, and I can touch type for most of the time.  I generally work in bursts of typing, hitting the keys hard and repeatedly until a function or subroutine is complete and needs reviewing, or until my fingers physically tire; and tire they do on having to bottom out every key stroke.  Now I type so much that I soon rub the keys on the keyboard smooth.  I've done this to around five keyboard at my current employer, I've had five keyboard in just short of 8 years (excluding new ones with new machines - then I've had 11 keyboards)... but five just wearing out and becoming unreliable.

I estimate the replacement keyboard I receive to cost the company around twelve pounds.  Its not the cheapest piece of shit as I had envisaged in a prior post and looking it up on Amazon they go for £12.51.  Its still rubber dome equipped, its stand feet are too short - meaning I have it propped up on some cardboard - and it is so lightly constructed as I type is bounces around (it has no rubber feet as other keyboards generally do, so it skitters around on the hard desk surface).

So, putting these tree facts together:

  • Professional level typing
  • Wears out keyboards in around 11 months
  • Replacements disturb the work area being hard to handle
You'd think I had a pretty interesting argument for better investment in better equipment.  After all it is said that once you have your computer to work on the best thing to do is spend luxuriously to ensure you can use it correctly, and the keyboard is the primary interaction point for me; and so I strongly believe that I should be able to actively redress the situation with a vested interest in increasing my typing speed and hence work throughput.

Nope.  I just get the £12.51 hunk of plastic.  I point out that five of these things at that price is nearing £60, the price of one professional grade keyboard with mechanical switches.... I point out that the rich stay rich by buying one expensive piece of kit and it working for a long time, and the poor stay poor by buying a cheap piece of kit and having to continually buy more and more replacement pieces of cheap kit to replace them as they break down.  But my philosophy is falling on deaf ears.

Maybe its the economic down turn... not so much that they're being cheap, but that they literally can't afford a decent keyboard for me... or anyone else... I doubt it, but its possible.  More plausible however is that simply a decent keyboard is not seen as important.

On the personal side of my keyboard woes things are still not brilliant, I'm using a "Microsoft Wireless 1000".  It it perhaps the second worst keyboard I've ever owned.  Even after typing this little stretch of blog post (which, go look at it, ain't that much) is hurting my fingers, as I'm constantly in a strange stretching feeling between my third and index fingers - of both hands - also the function keys are a "secondary function" the function keys only being active when you have a "function" key toggle set down and they're small (only half the size of a regular key) which is a problem for a programmer trying to use the Function keys for debugging all the time.

I still miss the old Apple Aluminium keyboard I had, but I'm never going to buy another one because the build and materials quality is so poor for its price.  I worked out it cost about £25 a year, for that I can have three complete sets of these Microsoft keyboards in that same time span...

Wait a moment.. I just struck myself with the obvious tactic being employed by my employer... yes you heard me, I can get three sets of cheap shit crap keyboards for the price of one better keyboard layout...

So, why would I want one decent keyboard?  Because now I'm on the trail of mechanical keyboards.

Mechanicals live longer, they have (hopefully) better build quality than the Apple membrane keyboard, and they sound lovely compared to rubber dome keyboards.

Argh, I'm rambling... I'm just after a decent keyboard.  I think one of the problems I have is that the mechanicals I'm looking at are expensive, they're never on show anywhere for you to try, and their price makes "risking" getting the wrong one too much of a risk.

Monday, 25 July 2011

Chrome Getting Flakey

Is it just me, or is Chrome getting really flaky?  I mean, I've had a fantastic experience with the browser until about the last fortnight, where upon all copies (on my main desktop, my laptop, my office PC and my two Linux boxes) have just gotten a bit temperamental.

Sometimes tabs refuse to browse to any site.  Whereupon a cross check with Firefox shows the site instantly.  Sometimes the chrome browser reports that plug-in (for example Flash player) is missing, but I've already got flash open in another tab.

And when I have multiple copies open, doing multiple downloads I'll suddenly have all downloads stop.

I'm wondering if this is personal revenge by Google as I read, and reviewed, Doug Edwards book "I'm feeling Lucky". hehe.

Sunday, 24 July 2011

Stripping Victorian Plaster

So, I've spent a very very un-technological weekend, actually the second in a row... We've been stripping the house out for a complete redecoration... this might sound dramatic, but we're going back to the bare brick... and this house was built when Queen Victoria still had 20 years left to live.

I've dug out the hearth, three layers deep, took off fake pine wooden beams someone added in a weird Union Flag motif, I've stripped layers of artex, modern plaster, plaster from the 1960's and then right back to lime plaster of the late 1800's.

Add to that door frames which were growing when America was only 100 years old... Soot & coal dust fragments its been a nightmare.

For some unknown reason the people who lived here over the ages have liked wall paper with vertical wood grain pattern, green velour wall paper, more vertical wood patterns, plain plaster, painted yellow, then painted green, finally the wood beams and betwixt these they stuck a ton of plaster into which they swirled their fingers... And they added fake points to all the doors... gah.  Terrible.

Friday, 22 July 2011

Technology Employers Cheap on Technology

I have a basic problem at work at the moment, my PC hardware I'm using as my main development box is starting to show its age.  Compared to other machines in the company its a pretty swish bit of kit (Core 2 Duo 2.0ghz, 6GB RAM, nVidia 8400GS) but when you compare it with my actual own personal development machine (Core i7 950 3.0ghz, 16gb RAM, nVidia 4800 GTX) it looks a little measly.

And I thought back through time to late 1997 when I got my first technical job... we always had machines a step behind the technology curve.  And it struck me as a utter false economy then, and it strikes me as it now.

I sit at work waiting for between 3 and 12 minutes for system wide builds to complete (I've been spending lots of time recently improving the optimization of my hard drives to speed up searches and file access) but he raw grunt of the machine is simply starting to flag.  3 minute build times for the stuff we do now 24 months ago (when the machine was bought for me) was excellent... but now, well I come home and can do much more complex builds in less and less time... 20 seconds for the same build... and I'm running like 4 virtual machines at the same time (on my 8 true cores).

At work, I'm struggling to run 1 virtual machine and a couple of copies of Visual Studio... I'd be far more productive with a much better machine.  And it'd only cost a grand!  You consider how much they pay me, increase my productivity by as little as 5% in a day and they're getting close to saving paying me to sit staring at a progress bar idle waiting for that same amount of time...

But the problem doesn't just stop where the hardware specification is, it continues... they insist, instead of implementing decent codes of practice and education of the less IT minded to prevent virus infections and people falling for cons they load the machines down with stupid (and unfit for purpose) virus scanners.

My employers use McAfee, and its an utter joke, we actually got slammed by a virus not too long ago (all my machines were clean I hasten to add) but the virus scanner we have in place; as ordered by the corporate overloads; didn't pick it up!

Then the IT department also get on with loading our machines down with yet more junkware... there's one they have running which reports all installed software to them, an audit trail of installed software as it were... this thing sits detecting every executable and DLL on the machine and reporting it back over the network to the IT department... Every time I perform a build it generates approximately 1,800 executable and DLL files... so I'm taking a hit on the hard drive to access the file, then the compiler is being scanned by the "On Access Scanner" then I'm getting hit as the compiler outputs the object file.  Next the linker gets "On Access Scanned" and the output executable object file is then scanned, toe tied and tissue typed.... All when there should be one scan access, or preferably none!

Gah, shit shit shit.

Saturday, 16 July 2011

Oh its all so touchy feely

I've just gotten around to watching the BBC programme "Classroom Secrets", and oh my god, these are primary school pupils if the kids at my school (Eastglade Junior - 1984-1989) had acted like this there would have been hell to pay.  Mr Allison, Mr Donnelly or Mr Dexter would have been down on you like a tonne of bricks sorting such bad behaviour.

Kids getting up to go for a drink... or sharpen a pencil... or go through draws... you could not do that in my day! In fact, I don't remember hydration being a major issue at school we didn't ever go thirsty, but we were not allowed to just up and go get a drink from our chair.

My memories are all of being told to stay where you were, unless you asked for permission to move... And I had some of the loveliest teachers at that time.

There was this regimented scheme, not to oppress you as an individual, but to make sure you covered the information you had to, to make sure that the teacher who was alone in the classroom had the confidence to know you were all safe.

But I'm looking at this programme, at these children and I can't believe what I'm seeing... teachers getting support workers left right and centre, all the staff (or nearly all) being female, its all so woolly, all so touchy feely... 

And I just heard the head teacher calling a child by a nick name "You alright Betty Spaghetti"... my head teacher would never ever have called you by your nick name.

If this is the school system my children will be going into I'm seriously thinking about home schooling them.

Friday, 8 July 2011

Chrome Tabs Not Browsing

So, I'm having a few recurrant problems with Chrome.  After browsing for a while (and there seems to be no set pattern to this) suddenly I'll right click and "open in new tab" a link, but it'll come up as a blank new tab.  No actual HTTP retrieval seems to go off.

I've had this before and resorted to removing Chrome from my machine and reinstalling it, however, it seems to be getting more and more frequent, and alarmingly so.  Its happens on two different Vista machines, a Kubuntu virtual machine (running in VMWare Player) and on a Ubuntu machine.

All were running stock download and installs of Chrome from Google, there were no plug-ins - except maybe flash - but I was not using video at the time.  And suddenly I can open no links in new tabs... we're not even talking a lot of tabs, just one or two and kaput no more browsing.


The weird thing is though that in any tab already open, showing a page/content, I can still left click to move into and out of hyper links to new pages, and they still load.

I've  had this problem whilst typing into google.com, yahoo mail, msn, this very blogger site (which is a google site underneith) and also whilst using amazon, play and the BBC.  There really is no pattern to when it goes, but once its gone I have to close all open instances of Chrome, all of them, even pages supposedly on other pages in other copies... and I have to open a whole new fresh copy of the browser.

The version of Chrome I've experienced this in is 1.2.0.742.112.

Ironically, I've just tried to report this bug through the Chromium project site... and not been able to.... so I'm going to file it with a fresh install of Firefox in a moment.

Monday, 4 July 2011

C++ based CGI with Apache on Win32 & Linux

Update: Hello new viewers, this post has recently started to receive 100's of page views a day, shooting it up my post rankings... And I don't know why, after all these years, why is it suddenly so popular... Let me know in the comments below! (And don't forget the tip jar is just on the top right there! hehe)

So, today I'm going to go through a really long winded explanation of how to set up C++ based CGI under Apache server on both Debian based Linux (Ubuntu) and Windows.

Before I go too far though let us just sort something out, CGI stands for "Common Gateway Interface" it is simply a set of definitions for data parsing and redirecting the standard input and standard output streams to your application. Your CGI application can be written in ANY language you want.  It can be PHP, Perl, C, C++, Visual Basic, C#, Python... Literally any programming language which is able to create a console application can be used to make a CGI application. Many sources on the Internet (like this one http://www.javascriptkit.com/howto/phpcgi.shtml) simply muddle up what CGI is, with it being a specific language. CGI is not a language it is actually an Application Programming Interface (API); it might even be thought of as a protocol rather than an API; to define how we use our cin and cout streams to render dynamic web page content.

So, moving on, we need a web server to host our applications, what we will do is code our applications in one location, build them and then copy them to the CGI folder of our web server. Then use a browser pointing to our server to make it run our application for us.

If you didn't spot it, I just mentioned the largest draw-back of CGI. Every time someone visits your CGI application page a new copy of the application is loaded from disk into the server and executed. If your CGI application is slow, or relies on a shared file, or some other item delays it, then you will noticeably slow your handling of web pages. There are ways around this, such as FastCGI, or with languages like Perl and PHP the scripts are not applications, instead they are interpreted (making them slower) but once they have been compiled (or precompiled once) those scripts can be kept in the server memory negating the need to load and reload each time someone accesses them. However, having lots of such scripts in server ram increases the server resource foot print (it needs more server memory to run effectively) quite dramatically.

Our target platform will be Apache2, on a very low power machine, single CPU, single core, 512mb of ram. Our operating systems will be Ubuntu Server, Kubuntu Desktop and Windows Vista 32bit Home Premium. (Any flavour of windows will work the exact same way - we're going to configure Apache, not Windows), and our goal is to run on as small a memory foot print as possible, with as few interpreters and sub-libraries working on our behalf.

Set up HTTP Apache Server under Windows

So, lets get on with setting up Apache... First lets get hold of the Apache HTTP server from http://httpd.apache.org/. We're going to concentrate on Apache 2.2.19, which is the current (at time of writing) stable release.

Under Windows you'll need to download httpd-2.2.19-win32-x86-no_ssl.msi from http://httpd.apache.org/download.cgi#apache22, then install the server by double clicking the msi where ever you have saved it to.

You can set the server up however you wish, however, for this example I selected to install my server as "localhost:8080" only so that I had to manually run the server and could browse to "http://localhost:8080" to see the "It Works!" Screen. So go a head and install, start the server



If you want to throw your own HTML pages onto your server you now simply browse to the folder apache installed to (by default this is under C:\Program Files\Apache Software Foundation\Apache2) and you can drop HTML or HTM files into the "htdocs" subfolder.

Note: You can copy files into the Windows Apache Subfolder and have them be served up without needing to restart the server.

Setup HTTP Apache Server under Linux

You should have your Linux machine installed with Ubuntu, server or desktop, or Kubuntu it makes no difference, you simply need to be able to open a command prompt (terminal window) and use the apt-get command.

So, first things first, lets install apache. In your prompt type:

sudo apt-get install apache2

Allow this comment to complete by providing your root password, and you should then be able to browse to your server IP, or the local host IP, and see the "It Works!" Page, just as we did under windows.

Again you can copy, or create, files in the folder /var/www to have them hosted by the server, so you could create /var/www/hello.html with a big "HELLO" text in the center of the page, however, just creating the file under Linux is not enough, you must perform a server restart each time you add a file (or after you have added a bunch of files).

To do this type:

sudo /etc/init.d/apache2 restart

Provide your root password and the server will restart and now you'll be able to browse to "http://127.0.0.1/hello.html" and see your big centered HELLO (swap 127.0.0.1 with your server/linux box IP if you're viewing from a different machine).

Adding CGI

By default both platforms have configuration to point to a cgi-bin directory, it is from this directory we will be running our example code (you can change the folder later), under windows you'll find the cgi-bin in the location of the apache executable you installed, so by default this is in "C:\program files\apache software foundation\apache2\cgi-bin". You can copy your CGI programs into there anytime you wish, once you have copied the file across, make sure you rename the extension "cgi", so you might build "cgidemo.exe", when you copy it rename it to "cgidemo.cgi".

On Linux this default location is /usr/lib/cgi-bin. So copy files into there you will need to use the root user comment to copy, for example, to copy a file called "cgidemo" from your home directory (where your username is ralph) to the cgi-bin you would have to use the command line:

sudo cp /home/ralph/cgidemo /usr/lib/cgi-bin/cgidemo.cgi

This copies the file, but also renames the file just as we would under windows.

Script Alias and Handlers

So, why do we rename our exe or file to .cgi? Well, this is to facilitate our adding a handler type to the Apache configuration. A handler basically tells the Apache software to associate a given file extension with an internal module. So we need to associate the .cgi extension with the cgi-script type.

Under windows you do this by using the start menu, seeking out where Apache installed in your programs list and using "Configure Apache" and the "Edit the Apache httpd.conf Configuration File" option. This will open notepad editing the sever configuration.

You need to look for the "ScriptAlias" for the /cgi-bin/ so use find to get to the line which starts "ScriptAlias /cgi-bin/" it will include another folder which is the actual folder on your hard drive where the cgi files will be stored. You can change that path later, but for now simply remove the # from the front, this will enable the Script Alias against that directory.

So mine reads:

ScriptAlias /cgi-bin/ "C:/Program Files/Apache Software Foundation/Apache2.2/cgi-bin/"

The next thing we need do is to find the actual configuration for this directory, the directory configuration tells the server what can and cannot be accessed or executed from this folder, so now find the Directory section for the alias given:

<Directory "C:/Program Files/Apache Software Foundation/ Apache2.2/cgi-bin/">

And you need to set some options and add a handler for cgi-scripts to the .cgi extension, this looks just like this:

<Directory "C:/Program Files/Apache Software Foundation/ Apache2.2/cgi-bin/">
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
    AddHandler cgi-script cgi
</Directory>

So, I have enabled cgi to execute from this directory, and told the handler to use any file ending "cgi" as a cgi-script.

Under Linux this is a lot simpler, you simply need to use the command line to edit the same file, which is in a slightly different location. So from the command prompt you will need to run the command:

sudo nano /etc/apache2/sites-available/default

This is the same configuration file as under Windows, it looks different, but it takes the same input, if you look now for the same <Directory specified as under windows, you should find the /usr/lib/cgi-bin folder thus:

<Directory "/usr/lib/cgi-bin">

Now set the directory to be the same:

<Directory "/usr/lib/cgi-bin">
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
    AddHandler cgi-script cgi
</Directory>

However, unlike windows you need to add the script alias yourself, so I have added mine just like this:

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
    AddHandler cgi-script cgi
</Directory>

If you save this file and then restart the apache server any cgi files you have in cgi-bin can now be accessed.
Alias Explained
So, I hope its obvious now that the alias you set is used to map a local folder on your hard drive to a URL on your server, so if you have an alias of /cgi-bin/ pointing to a folder you access if from a browser as "http://YOUR IP/cgi-bin/"
If you added an alias of "/nothing/" then you could get to contents in that folder as "Http://YOURIP/nothing" in your browser.
Now to Code
So, our next task is to create some code which we can actually run as our CGI. So, in Visual Studio I create a new C++ application which is an empty Console Application. In Code Blocks on Linux I create an empty project.
To both I add a "main.cpp" file and I put the exact same code in both:
#include <iostream>
#include <string>

using namespace std;

const string c_ContentHeader = "Content-type: text/html\n\n";

int main (int argc, char* argv[])
{
 cout << c_ContentHeader;
 cout << "Hello From CGI" << endl;

 return 0;
}

Pretty simple application. Both windows and linux (gcc) will build this without even blinking, so go a head and build it up, and copy the output executable to your cgi folder.... so my output is called "hellocgi.exe" on windows and just "hellocgi" on Linux.
I copy and rename it to our cgi folders "C:\apachepath\cgi-bin\hellocgi.cgi" on windows and "sudo cp /home/ralph/cgidemo/bin/Debug/hellocgi /usr/lib/cgi-bin/hellocgi.cgi"
On Linux I restart apache "sudo /etc/init.d/apache2 restart".
And now I browse to the server as "http://127.0.0.1:8080/cgi-bin/hellocgi.cgi" on windows, and I browse to "http://127.0.0.1/cgi-bin/hellocgi.cgi" on Linux. And voila I see my "Hello From CGI".
Now, lets take this code apart, if you miss out sending the "Content-type" string first you will get a server side error in your browser, this error looks like this:
To then spot that we missed the content header, then we need to view the error.log within our apache logs folder and we can see the line:
[Mon Jul 04 11:32:16 2011] [error] [client 127.0.0.1] malformed header from script. Bad header=Hello From CGI: CGI.cgi

Oh, "bad header" and yes.. I had the code looking like this:

#include <iostream>
#include <string>

using namespace std;

const string c_ContentHeader = "Content-type: text/html\n\n";

int main (int argc, char* argv[])
{
 //cout << c_ContentHeader;  -- Commented out
 cout << "Hello From CGI" << endl;

 return 0;
}

So, what have we learned from all this?
  • To point an Apache alias at a directory.
  • To configure this directory to allow CGI execution.
  • To add a handler for the cgi-script type to a defined file extension.
  • To copy our C++ compiled/built output to the cgi-bin folder we've aliased.
  • To restart the server.
  • To run the executable.
Rendering HTML
From our C++ application we can now render any HTML we want, we could load this from templates on disk, or simply stream it out from the code
 cout << c_ContentHeader;
 cout << "<html>";
 cout << "<body>";
 cout << "<lcenter>Hello World from the CGI app, but with HTML</center>";
 cout << "</body>";
 cout << "</html>";

This is using the C++ IOStream library, however we can use the old C style output of "printf".

printf ("%s", c_ContentHeader.c_str());
 printf ("<html>");
 printf ("<body>");
 printf ("<center>Hello World from the CGI app, but with HTML</center>");
 printf ("</body>");
 printf ("</html>");

You could therefore load a template from disk, for example a file containing:
<html>
<body>
<center><%=String%></center>
</body>
</html>

And in our program we can replace &qupt;<%=String%>" with some other value... This kind of script usage might ring bells with ASP developers, as it is exactly the kind of syntax used to output a value from an ASP application... Maybe you could write your own dynamic content server...
We could simplify processing of templates loaded with the use of the C style calls, for example, this template:
<html>
<body>
<center>%s</center>
</body>
</html>

Loaded as a single string this could then be rendered with a value in place of %s with a single call to printf:
printf (template.c_str(), "HELLO WORLD");
Will result in the Hello world string being presented center of the page from the template.
You can get as complex as you wish here.
Receiving Input
So, if we now are happy with outputting HTML from our CGI application we will need to work out how to receive input. For example, if we had our browser come to our CGI page from a form post, then that page might look like this:
<html>
<body>

<form name="TestForm" action="http://127.0.0.1:8080/cgi-bin/contentLength.cgi" method="POST">

 <input type=text name="TextField1" value="Hello World">

 <input type=submit name="submit" value="Click To Submit">

</form>

</body>
</html>

So, we see the form has an input field and a submit field, and it points to our CGI page... this is a new CGI page, the code for which looks like this:
#include <iostream>
#include <string>

using namespace std;


const string c_ContentHeader = "Content-type: text/html\n\n";


    // ---- CONTENT LENGTH ----

    ///<Summary>
    /// The content length environment variable
    /// name
    ///</Summary>
    const string c_ContentLengthVariableName = "CONTENT_LENGTH";

    ///<Summary>
    /// Function to return the current requests
    /// content length
    ///</Summary>
    const int GetContentLength()
    {
        int l_result = 0;
        char* l_ContentLengthVariable = getenv(c_ContentLengthVariableName.c_str());
        if ( l_ContentLengthVariable != NULL )
        {
            l_result = atoi(l_ContentLengthVariable);
        }
        return l_result;

    }

    // ---- END CONTENT LENGTH ----


int main (int argc, char* argv[])
{
 cout <<c_ContentHeader;
 
 cout <<"The content Length is: " << GetContentLength() << endl;


 return 0;
}

This code shows you a new function to get the content length, this used the "getenv" call, get env returns a set of environment variables, for a CGI program like ours the environment variables are all items set up by the Apache server before it started our application.
So, if you build this code and copy it into place as "contentLength.cgi" save the HTML shown to your /htdocs or /var/www folder and restart your server. Then you can browse your server to the HTML page, click submit and send that data to the CGI.
The "<input" items in the form are then sent to the CGI script, becoming its input.
You should see by default the number of bytes sent to your CGI script. If you go back and change the text in the input field, you will see a different content length being shown by your CGI program.
So where does this input come from? Well, it comes from the standard input stream, is you perform a cin, or read console, or Console.ReadLine or whatever you want, then you will receive your input. We already know how many bytes to read, so lets see how to do this...

    // ---- GET CONTENT ----

    ///<Summary>
    /// Function to return the content
    ///</Summary>
    const list<string> GetContent()
    {
        list<string> l_result;

        // Now seek the content
        int l_ContentLength = GetContentLength();
        if ( l_ContentLength > 0 )
        {
            try
            {
                // Allocate a buffer for the information
                auto_ptr<char> l_Buffer (new char[l_ContentLength]);

                // Read the content sent into the buffer
                int l_bytesRead = fread (l_Buffer.get(), sizeof(char), l_ContentLength, stdin);

                // Check the data length
                if ( l_bytesRead == l_ContentLength )
                {                                        
                    // Convert the buffer to a string
                    stringstream l_stream (l_Buffer.get());

                    // Push the content as a string into the buffer
                    while ( !l_stream.eof() )
                    {
                        string l_item;
                        l_stream >>: l_item;

                        l_result.push_back(l_item);
                    }
                }
            }
            catch (bad_alloc l_badAllocationException)
            {
                // TODO handle bad alloc
            }
        }

        return l_result;
    }

    // ---- END GET CONTENT ----
 
So, what is this doing? Well, its allocating a buffer of the content length we know we have, its then reading this buffer from the stdin stream. I'm then choosing to squirt it into a string stream and pushing each line into the result list.
Putting it all together my whole code base now looks like this:
#include <iostream>
#include <string>
#include <list>
#include <sstream>
#include <memory>

using namespace std;


const string c_ContentHeader = "Content-type: text/html\n\n";

    // ---- CONTENT LENGTH ----

    ///<Summary>
    /// The content length environment variable
    /// name
    ///</Summary>
    const string c_ContentLengthVariableName = "CONTENT_LENGTH";

    ///<Summary>
    /// Function to return the current requests
    /// content length
    ///</Summary>
    const int GetContentLength()
    {
        int l_result = 0;
        char* l_ContentLengthVariable = getenv(c_ContentLengthVariableName.c_str());
        if ( l_ContentLengthVariable != NULL )
        {
            l_result = atoi(l_ContentLengthVariable);
        }
        return l_result;

    }

    // ---- END CONTENT LENGTH ----


    // ---- GET CONTENT ----

    ///<Summary>
    /// Function to return the content
    ///</Summary>
    const list<string> GetContent()
    {
        list<string> l_result;

        // Now seek the content
        int l_ContentLength = GetContentLength();
        if ( l_ContentLength > 0 )
        {
            try
            {
                // Allocate a buffer for the information
                auto_ptr<char> l_Buffer (new char[l_ContentLength]);

                // Read the content sent into the buffer
                int l_bytesRead = fread (l_Buffer.get(), sizeof(char), l_ContentLength, stdin);

                // Check the data length
                if ( l_bytesRead == l_ContentLength )
                {                                        
                    // Convert the buffer to a string
                    stringstream l_stream (l_Buffer.get());

                    // Push the content as a string into the buffer
                    while ( !l_stream.eof() )
                    {
                        string l_item;
                        l_stream >> l_item;

                        l_result.push_back(l_item);
                    }
                }
            }
            catch (bad_alloc l_badAllocationException)
            {
                // TODO handle bad alloc
            }
        }

        return l_result;
    }

    // ---- END GET CONTENT ----


int main (int argc, char* argv[])
{
 cout << c_ContentHeader;
 cout << "<html><body>" << endl;
 cout << "The content Length is: " << GetContentLength() << "<br>" << endl;

 cout << "The Content is: <br><pre>" << endl;

 list<string> theContent = GetContent();
 for (list<string>::const_iterator itr = theContent.begin();
  itr != theContent.end();
  itr++)
 {
  cout << (*itr) << endl;
 }

 cout << "</pre><hr></body></html>" << endl;

 return 0;
}

And I've built this and names it "contentExample.cgi" in my cgi-bin.
I've also edited the HTML form to submit to this new CGI application:
<html>
<body>

<form name="TestForm" action="http://127.0.0.1:8080/cgi-bin/contentExample.cgi" method="POST">

 <input type=text name="TextField1" value="Hello World">

 <input type=submit name="submit" value="Click To Submit">

</form>

</body>
</html>

Now when I perform the post we get an output from our CGI for the form being submitted. And viola, there is our input.
Conclusion
I'm not going to go into processing the input, nor am I going to point you in the direction of libraries to perform these item yourself. It is a much better learning experience to process all the commands yourself, possibly write your own library, so you understand the underlying CGI protocol environment variables and pitfalls.
This becomes invaluable in understanding the API.
Here you will find a list of all the CGI environment variables you can ask for via "getenv": http://www.perlfect.com/articles/cgi_env.shtml
All the code given is completely interchangeable between windows and linux.
If you have any problems with this (very basic) introduction, drop me a line.