/********************************************************************/
/* Beispiel fur ein CGI-Programm in der Sprache C                   */
/********************************************************************/
/* CGI = Common Gateway Interface                                   */
/********************************************************************/
/* CGI-Programme werden auf einem Web-Server ausgeführt             */
/* sie erzeugen dynamische Webseiten - oft auf Grundlage von Daten, */
/* die über ein  Web-Formular bereitgestellt werden                 */
/* ein CGI-Programm schreibt "normales" HTML in die Standardausgabe */
/********************************************************************/
/* ein CGI-Programm muss auf Webserver Plattform übersetzt werden   */
/* der Name des ausführbaren File muss auf  .cgi enden              */
/*   cc  rechner_cgi.c -o rechner.cgi                               */
/********************************************************************/
/* bei method="get" in der Formulardefinition werden die Daten des  */
/*                  ausgefüllten Formulars in der Umgebungsvariable */
/*                  QUERY_STRING bereitgestellt ( "post" in stdin)  */
/* Beispiel:        QUERY_STRING="9999.9999&op=9&op2=9999.999"      */
/********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>

/************************************/
/* Funktion error() zeigt Fehler an */
/************************************/

int fehler=0;
void error(fm)
char *fm;
{
     printf("<center><h2><p>Fehler: %s\n</h2></center>", fm);
     fehler=1;
}

/*******************************************************************/
/* Funktion print_header() gibt die "Kopfsätze" der HTML-Seite aus */
/*******************************************************************/

char header0[]="Content-type: text/html\n\n";
char header1[]="<HTML>\n<HEAD>\n<TITLE>CGI Rechner</TITLE></HEAD>\n";
char header2[]="<BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\"> \n";
char header3[]="<FONT FACE=\"Arial,Helvetica\"> \n";
char header4[]="<center><h1>\"Supercomputer\"</h1></center><p> \n";
void print_header()
{
  printf(header0);
  printf(header1);
  printf(header2);
  printf(header3);
  printf(header4);
}

/*******************************************************************/
/* Funktion print_footer() gibt "Schlusssätze"  der HTML-Seite aus */
/*******************************************************************/

char footer1[] = "</FONT>\n </BODY>\n </HTML>\n";
void print_footer()
{
  printf(footer1);
}

/********************************************************************/
/* Funktion syntax() prüft, ob ein String fz nur Bestandteile einer */
/* Gleitkommazahl enthält                                           */
/* j ist die Nr. des Operanden für evtl. Fehlermeldungen            */
/********************************************************************/

void syntax(fz,j)
char *fz;
int j;
{
  int i;
  char fehlstr[50];

  i=0;
  while(fz[i] != '\0') {
    if(fz[i]>='0' && fz[i]<='9' || fz[i]=='.' || fz[i]=='-')
     i++;
    else {
     sprintf(fehlstr,"%d. Operand %s ist keine Gleitkommazahl!",j,fz);
     error(fehlstr);
     return;
    }
  }
}

main ()
{
   int x;
   double op1, op2, erg;
   char zkop1[512], zkop2[512], query[512], *poi, rechenop, opz;

   print_header();

   if(getenv("QUERY_STRING") == NULL) {
     /* das sollte eigentlich nicht vorkommen */
     error("QUERY_STRING nicht definiert");
     print_footer();
     exit(1);
   }
   strncpy(query,getenv("QUERY_STRING"),512);
   if(query[0]=='\0') {
     error("Im rufenden Dokument bei Formulardefinition method!=get");
     print_footer();
     exit(1);
   }
   if((poi=strstr(query,"op1=")) != NULL) {
     strcpy(zkop1,poi+4); /* zkop1=9999.99999&op=9&op2=99999.99999 */
     x=0;
     while(zkop1[x] != '&' && zkop1[x] != '\0') x++;
     zkop1[x]='\0';
     syntax(zkop1,1);
     op1=atof(zkop1);
   } else {
     /* wenn CGI als URL oder aus falschem Formular gerufen wird */
     error("op1 nicht angegeben");
   }
   if((poi=strstr(query,"op2=")) != NULL) {
     strcpy(zkop2,poi+4);
     x=0;
     while(zkop2[x] != '&' && zkop2[x] != '\0') x++;
     zkop2[x]='\0';
     syntax(zkop2,2);
     op2=atof(zkop2);
   } else {
     error("op2 nicht angegeben");
   }
   if((poi=strstr(query,"op=")) != NULL) {
     rechenop=*(poi+3);
   } else {
     error("op nicht angegeben");
   }
   switch (rechenop) {
     case '1': erg=op1+op2;
               opz='+';
               break;
     case '2': erg=op1-op2;
               opz='-';
               break;
     case '3': erg=op1*op2;
               opz='*';
               break;
     case '4': if(op2 == 0) error("Division durch Null");
               erg=op1/op2;
               opz='/';
               break;
     default: error("Falsches Operationszeichen");
   }
   if(fehler != 0) {
       print_footer();
       exit(1);
   }
   printf("<center>\n<h2>");
   printf("%s %c %s = %f\n", zkop1, opz, zkop2, erg);
   printf("</h2></center>\n");
   print_footer();
}
