This C program is used a CGI backend by the forms demonstrations in the encyclopaedia.
The program is compiled using the following command on
scitsc
cc -o expr1.cgi expr1.c -lncsa
#include <stdio.h>
#include <ncsa.h>
#include <stdlib.h>
#define NENT 15
struct entry entries[NENT];
main()
{
int i,m;
char *cl = getenv("QUERY_STRING");
printf("Content-Type: text/plain\n\n");
for(i=0; cl[0] && i<NENT; i++)
{
getword(entries[i].val,cl,'&');
plustospace(entries[i].val);
unescape_url(entries[i].val);
getword(entries[i].name,entries[i].val,'=');
}
m = i;
for(i=0;i<m;i++) printf("Item %d Name = %s Value = %s\n",
i,entries[i].name,entries[i].val);
}
The program shown above uses various routines that came with the scitsc NCSA WWW server, they are not particularly efficient. Here is some simple C code (it took me about 20 minutes) that decodes a CGI query string and stores the results. It could do with some refinement but you may find it useful as a starting point for developing your own programs.
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
struct entry
{
char *name;
char *value;
};
void un_escape(char *);
main()
{
int i,m;
int pcts=0;
char *cp;
char **cfp;
struct entry *entries;
char *cl = getenv("QUERY_STRING");
printf("Content-Type: text/plain\n\n");
cp =cl;
/* first scan query string for ampersands which separate
name=value pairs - count gives number of items */
while(*cp) if(*cp++ == '&') pcts++;
pcts++;
/* get enough space to store the information - the text
strings stay in the environment variable QUERY_STRING */
cfp = (char **)calloc(pcts,sizeof(char *));
/* now split the environment variable into separate strings */
cfp[0] = cp = cl;
i = 1;
while(*cp)
{
if(*cp == '&')
{
*cp = '\0';
cfp[i++] = cp+1;
}
cp++;
}
/* print obtained values - if you uncomment out this bit of code
for(i=0;i<pcts;i++) printf("%d %s\n",i,cfp[i]);
*/
/* allocate enough space to hold the actual struct entry items */
entries = (struct entry *)calloc(pcts,sizeof(struct entry));
/* now look for the = symbols that separate the names and
values within each string - store the pointers in the
struct entry items */
for(i=0;i<pcts;i++)
{
cp = strchr(cfp[i],'=');
if(cp == NULL) printf("Error in %d\n",i);
*cp = '\0';
entries[i].name = cfp[i];
entries[i].value = cp+1;
}
/* more optional printing
for(i=0;i<pcts;i++)
{
printf("%d name = %s value = %s\n",i,entries[i].name,
entries[i].value);
}
*/
/* now to undo the http escaping conventions */
for(i=0;i<pcts;i++)
un_escape(entries[i].value);
/* and yet more optional printing
for(i=0;i<pcts;i++)
{
printf("%d name = %s value = %s\n",i,entries[i].name,
entries[i].value);
}
*/
}
void un_escape(char *s)
{
/* in-place http unescaping - two things to do
1. replace pluses by spaces
2. deal with %XX escapes
*/
char *s1; /* destination */
int v1,v2;
int i;
s1 = s;
while(*s)
{
if(*s == '+') *s1=' '; /* plus -> space */
else if(*s == '%') /* an %XX escape ?? */
{
for(i=1;i<=2;i++) /* two hex digits MUST follow */
{
if(!isdigit(*(s+i))) /* special crude stuff for A-F */
{
*(s+i) = tolower(*(s+i));
*(s+i) = *(s+i)-'a' + '9' + 1;
}
}
v1 = 16*(*(s+1)-'0') + *(s+2)-'0';
*s1 = v1;
s+=2;
}
else *s1 = *s;
s++;
s1++;
}
*s1 = '\0';
return;
}