The CGI app then responds with a generated HTML document. As a general rule, with Unix webservers, the webserver forks and executes the CGI app, and the CGI app writes the HTML code on standard output. The webserver captures the standard output of the app, and sends it over the TCP/IP channel to the user's browser. This is the case in almost all CGI apps under Unix.
Additionally, the user can send special fields of data to the CGI app in the request, such as a User ID, Part Number, etc. These fields are URL-Encoded(making the characters legal for use in an URL) and transmitted to the server. Precisely how they are transmitted depends upon the Request Method used. CGIRef supports the two most common methods, GET and POST.
Well, we need programs for math questions and math answers. So, let's call the programs mathq.c and matha.c. Let's start with mathq.c , which will select two random numbers and challenge the user to add them and input a correct sum.
#define MAX_Q_NUM 100 /* Do not define to be 0 - program will fail*/
int main(void)
{
int N1,N2;
srand(time(0));
N1=(rand()%MAX_Q_NUM)+1;
N2=(rand()%MAX_Q_NUM)+1;
printf("Content-type: text/html%c%c",10,10);
printf("<! DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2
Final//EN\">%c",10);
printf("<HTML>%c",10);
printf("<HEAD>%c",10);
printf("<TITLE>Sample Math Question</TITLE>%c",10);
printf("</HEAD>%c",10);
printf("<BODY>%c",10);
printf("<H1>A Sample Math Question</H1>%c",10);
printf("<HR>%c",10);
printf("<FORM ACTION=\"/cgi-bin/matha.cgi\" METHOD=\"POST\">");
printf("<INPUT TYPE=\"Hidden\" NAME=\"N1\" VALUE=\"%d\" SIZE=0></TD></TR>%c",N1,10);
printf("<INPUT TYPE=\"Hidden\" NAME=\"N2\" VALUE=\"%d\" SIZE=0></TD></TR>%c",N2,10);
printf("<TABLE>%c",10);
printf("<TR><TD>First Number</TD><TD ALIGN=\"RIGHT\">%d</TD></TR>%c",N1,10);
printf("<TR><TD>Second Number</TD><TD ALIGN=\"RIGHT\">%d</TD></TR>%c",N2,10);
printf("<TR><TD>Enter the sum</TD><TD ALIGN=\"RIGHT\">");
printf("<INPUT TYPE=\"text\" NAME=\"A\" SIZE=8></TD></TR>%c",10);
printf("</TABLE>%c",10);
printf("<INPUT TYPE=\"submit\"><INPUT TYPE=\"reset\">%c",10);
printf("</FORM>%c",10);
printf("</BODY>%c",10);
printf("</HTML>%c",10);
return(0);
}
Now here is the program to interpret it:
char *FieldName_Answer = "A";
char *FieldName_N1 = "N1";
char *FieldName_N2 = "N2";
int ValidateFields(void);
int main(int argc, char *argv[])
{
unsigned TheirAnswer=0;
unsigned N1;
unsigned N2;
printf("Content-Type: text/html%c%c",10,10);
printf("<! DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2
Final//EN\">%c",10);
printf("<HEAD>%c",10);
printf("<TITLE>Quiz results</TITLE>%c",10);
printf("</HEAD>%c",10);
printf("<BODY>%c",10);
printf("<H1>Quiz Results</H1>%c",10);
printf("<HR>%c",10);
if(!cgiInit())
{
if(!ValidateFields())
{
if(strlen(cgiGetField(FieldName_Answer)))
{
TheirAnswer=atoi(cgiGetField(FieldName_Answer));
N1
=atoi(cgiGetField(FieldName_N1 ));
N2
=atoi(cgiGetField(FieldName_N2 ));
if(TheirAnswer==N1+N2)
printf("<B>Correct!</B>
You answered: %d%c",TheirAnswer,10);
else
{
if(TheirAnswer==0)
printf("Zero
or non-numeric response: %s%c",cgiGetField(FieldName_Answer),10);
else
printf("Incorrect!
Try again!%c",10);
}
}
else
printf("Error: You left the answer field
blank!%c",10);
}
else
printf("Error: Required field(s) invalid or not
present!%c",10);
}
else
printf("Error: Cannot initialize CGI environment!%c",10);
printf("<HR>%c",10);
printf("Thank you for taking our quiz%c",10);
printf("</BODY>%c",10);
return(0);
}
int ValidateFields(void)
{
int rv=-1;
if(cgiFieldPresent(FieldName_Answer))
if(cgiFieldPresent(FieldName_N1))
if(cgiFieldPresent(FieldName_N1))
rv=0;
return(rv);
}
Basically the program works as follows: First, we call the cgiInit library routine, to initialize the the CGIRef library and read in the query. Then, we call ValidateFields() to make sure the user typed in the right stuff. If not, they get an error message. Then, we obtain character pointers to the passed variables, by calling cgiGetField with the name of the field we want to get. The string values stored in these variables are converted to integers, then added and checked.
Wait! What's all this with the %c and so forth? Why not just put a "\n" at the end of the line? Because some implementations of printf() do an fflush() system call when they see a "\n" in the format string. Well, that's normally OK, but when we're working over a network socket, an fflush() will trigger a packet being sent. If we are outputting a 5-character line, that will trigger the sending of a packet with a data payload only 5 bytes long...very inefficient, as practically any Unix machine will trigger a send when the buffer fills up to the MTU size. Don't use "\n" with printf()s in CGI apps. Be lazy and let the system decide when to send packets.
NOTE: Stop for a second, look at this program and notice how no matter what happens, the user gets something back. Always design your CGI apps this way. Nothing is more frustrating than to hit the "Submit" button and get nothing back and have no idea what was done wrong.
Finally, we do a horizontal rule, and thank the user.
OK, so you've seen the basics! Now go to it!