Touch ups --#-- URL encoding is handled here in a simplistic way. You may want to expand on this by encoding other characters (such as <, > © and others).

char *urlEncode(char *s, char *param) { char *c; strcpy(s, param); c = s; while (*c != '\0') { if (*c == ' ') *c = '+'; c++; } return s; }
Now, we need to form all of the request headers from beginning to end:

char *formRequest() { char *post; int len; char cLen[32]; char *protocol = "POST "; char *request; int i; post = formContent(); len = strlen(post); sprintf(cLen, "%d", len); len = 0; len += strlen(protocol); len += strlen(action) + 1; len += strlen(headerStuff); len += strlen(cLen) + 6; len += strlen(post); if ((request = (char *)malloc(len)) == NULL) die("Out of memory!"); strcpy(request, protocol); strcat(request, action); strcat(request, " "); strcat(request, headerStuff); strcat(request, cLen); strcat(request, "\r\n\r\n"); strcat(request, post); strcat(request, "\r\n"); free(post); return request; }
It should be apparent why we formed the name/value pair request string in a separate function -- we need to measure it by itself and tack the result onto the end of the Content-length header. This is to notify the server of how much body is about to come so the connection will stay open.

Remember, too, that char *post was created by a malloc in the function formContent(), so we need to free it. Likewise, the caller will have to free the return from this function as well.