calc.c
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "cgihelp.h"
#define ERR_NO_VALUE (1)
#define ERR_BAD_VALUE (2)
#define ERR_ZERO_DIVIDE (3)
#define ERR_BAD_OPERATOR (4)
int main() {
int a, b, result, error = 0;
char *num1, *num2, *op, *endptr = NULL;
printf("Content-Type: text/html\n\n");
printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\">\n\n");
printf("<HTML>\n\n");
printf("<HEAD>\n");
printf(" <TITLE>CGI Calculator</TITLE>\n");
printf("</HEAD>\n\n");
printf("<BODY>\n\n");
printf("<H1>CGI Calculator</H1>\n\n");
if ( InitInput(100) ) {
printf("<P>ERROR: Problem getting input</P>\n\n");
}
else {
printf("<P>Last result: ");
num1 = GetValue("number1");
num2 = GetValue("number2");
op = GetValue("operator");
if ( !num1 && !num2 && !op )
printf("No previous calculation.</P>\n\n");
else {
if ( !num1 )
error = ERR_NO_VALUE;
else {
a = strtol(num1, &endptr, 0);
if ( *endptr )
error = ERR_BAD_VALUE;
}
if ( !num2 )
error = ERR_NO_VALUE;
else {
b = strtol(num2, &endptr, 0);
if ( *endptr )
error = ERR_BAD_VALUE;
}
if ( !op )
error = ERR_NO_VALUE;
else {
if ( !strcmp(op, "plus") )
result = a + b;
else if ( !strcmp(op, "minus") )
result = a - b;
else if ( !strcmp(op, "multiplied by") )
result = a * b;
else if ( !strcmp(op, "divided by") )
if ( b )
result = a / b;
else
error = ERR_ZERO_DIVIDE;
else if ( !strcmp(op, "to the power of") )
result = pow(a, b);
else
error = ERR_BAD_OPERATOR;
}
switch ( error ) {
case ERR_NO_VALUE:
printf("Error - one or more values are missing.</P>\n\n");
break;
case ERR_BAD_VALUE:
printf("Error - one or more values was invalid.</P>\n\n");
break;
case ERR_ZERO_DIVIDE:
printf("Error - can't divide by zero.</P>\n\n");
break;
case ERR_BAD_OPERATOR:
printf("Error - invalid operator.</P>\n\n");
break;
default:
printf("%d %s %d = %d</P>\n\n", a, op, b, result);
break;
}
}
printf("<BR><HR><BR>\n\n");
printf("<FORM ACTION=\"/cgi-bin/calc\" METHOD=\"GET\">\n");
printf("<TABLE BORDER=\"1\" CELLPADDING=\"10\">\n");
printf(" <TR>\n");
printf(" <TH>First number</TH>\n");
printf(" <TH>Operator</TH>\n");
printf(" <TH>Second number</TH>\n");
printf(" </TR>\n\n");
printf(" <TR>\n");
printf(" <TD><INPUT TYPE=\"text\" NAME=\"number1\" SIZE=\"8\"></TD>\n");
printf(" <TD><SELECT NAME=\"operator\">\n");
printf(" <OPTION>plus</OPTION>\n");
printf(" <OPTION>minus</OPTION>\n");
printf(" <OPTION>multiplied by</OPTION>\n");
printf(" <OPTION>divided by</OPTION>\n");
printf(" <OPTION>to the power of</OPTION>\n");
printf(" </SELECT></TD>\n");
printf(" <TD><INPUT TYPE=\"text\" NAME=\"number2\" SIZE=\"8\"></TD>\n");
printf(" </TR>\n\n");
printf(" <TR>\n");
printf(" <TD COLSPAN=\"3\"><CENTER>");
printf("<INPUT TYPE=\"submit\" VALUE=\"Calculate!\">");
printf("</CENTER></TD>\n");
printf(" </TR>\n");
printf("</TABLE>\n");
printf("</FORM>\n\n");
printf("</BODY>\n\n</HTML>\n");
}
FreeCGI();
return EXIT_SUCCESS;
}
cgihelp.h
#ifndef PG_CGIHELP
#define PG_CGIHELP
#define ERR_BADREQUEST (1)
#define ERR_BADMALLOC (2)
int InitInput (int maxbuffer);
char * GetValue (char *key);
char * GetIndexedValue(int index);
char * GetIndexedKey (int index);
void FreeCGI ();
#endif
cgihelp.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "cgihelp.h"
void cleanurl(char *str);
typedef struct varlist {
char *key;
char *value;
struct varlist *next;
} varlist;
varlist* varstart;
int InitInput(int maxbuffer) {
varlist *var;
char *input;
if ( !(input = malloc(sizeof(char) * maxbuffer)) )
return ERR_BADMALLOC;
memset(input, '\0', sizeof(char) * maxbuffer);
if ( !strcmp(getenv("REQUEST_METHOD"), "GET") )
strncpy(input, getenv("QUERY_STRING"), maxbuffer - 1);
else if ( !strcmp(getenv("REQUEST_METHOD"), "POST") )
fgets(input, maxbuffer, stdin);
else
return ERR_BADREQUEST;
if ( ! (varstart = malloc(sizeof(varlist)) ) )
return ERR_BADMALLOC;
var = varstart;
if ( (input = strtok(input, "=")) ) {
while ( var ) {
if ( !(var->key = malloc(sizeof(char) * strlen(input))) )
return ERR_BADMALLOC;
strcpy(var->key, input);
cleanurl(var->key);
input = strtok(NULL, "&");
if ( !(var->value = malloc(sizeof(char) * strlen(input))) )
return ERR_BADMALLOC;
strcpy(var->value, input);
cleanurl(var->value);
if ( (input = strtok(NULL, "=")) ) {
if ( !(var->next = malloc(sizeof(varlist))) )
return ERR_BADMALLOC;
}
else {
var->next = NULL;
}
var = var->next;
}
}
else {
free(varstart);
varstart = NULL;
}
free(input);
return 0;
}
char * GetValue(char *key) {
varlist *var = varstart;
while ( var ) {
if ( !strcmp(key, var->key) )
return var->value;
var = var->next;
}
return NULL;
}
char * GetIndexedKey(int index) {
int n;
varlist *var = varstart;
for ( n = 1; n < index; ++n )
if ( var->next == NULL )
return NULL;
else
var = var->next;
return var->key;
}
char * GetIndexedValue(int index) {
int n;
varlist *var = varstart;
for ( n = 1; n < index; ++n )
if ( var->next == NULL )
return NULL;
else
var = var->next;
return var->value;
}
void FreeCGI() {
varlist *var = varstart;
while ( var ) {
free(var->key);
free(var->value);
var = var->next;
free(varstart);
varstart = var;
}
}
void cleanurl(char *str) {
char asciinum[3] = {0};
int i = 0, c;
while ( str[i] ) {
if ( str[i] == '+' )
str[i] = ' ';
else if ( str[i] == '%' ) {
asciinum[0] = str[i+1];
asciinum[1] = str[i+2];
str[i] = strtol(asciinum, NULL, 16);
c = i+1;
do {
str[c] = str[c+2];
} while ( str[2+(c++)] );
}
++i;
}
}
Please send all comments, suggestions, bug reports etc to mail@paulgriffiths.net