/*****************************************************************/
/*                                                               */
/* module:   pinnwand.c                                          */
/* project:  pinnwand                                            */
/* version:  1.7                                                 */ 
/* author:   marko meister                                       */
/*              <marko.meister@informatik.uni-weimar.de>         */
/* compiler: cc, mvc++ 4.0                                       */
/* SYSTEM: HP-UX, IRIX, WIN95/NT                                 */
/*                                                               */
/*****************************************************************/
/*                                                               */
/* if you port this software to another system, please send your */
/* report to marko.meister@informatik.uni-weimar.de              */
/*                                                               */
/*****************************************************************/
/* last changes:                                                 */
/* 04.01.2000 (ver 1.7.005)                                      */
/*     Y2K Problem (war eigentlich keines) beseitigt, (bei       */
/*     angaben stand z.B. 1.1.100 - jetzt steht korrekt 1.1.00)  */
/* 11.05.1999                                                    */
/*     DAs Problem mit der Zeitverschiebung bei den              */
/*     UNIX-Varianten wurde beseitigt.                           */
/* 18.05.1998                                                    */
/*     im rc-file werden placeholder nun getestet ob sie mit     */
/*     %PINNWAND_ beginnen                                       */
/*     jetzt geht auch %PINNWAND_VERFALL%                        */
/* 29.04.1998                                                    */
/*     einige Aenderungen wegen UNIX anpassung (1.7.002)         */
/* 18.04.1998                                                    */
/*    jetzt mit build nummern (1.7.001)                          */   
/* 31.03.1998                                                    */
/*    bei URL erkennung werden alle Zeichen die nicht in einem   */
/*    URL stehen duerfen als Trennung benutzt                    */
/* 15.03.1998   (v1.7)                                           */
/*    der ganze Quellcode ist jetzt in einer Datei               */
/* 04.03.1998                                                    */
/*    ported to win95                                            */
/* 09.02.1998                                                    */
/*    fixed some bugs (empty author or subject string)           */
/*    thanx to niels heidenreich for bug-reporting               */
/* 04.11.1997                                                    */ 
/*    fixed some bugs ... thanx to jsd                           */
/* 03.11.1997                                                    */
/*    added some english text                                    */
/* 22.4.1997                                                     */
/*    fixed some bugs (z.B. core dump after running without args)*/
/* 10.4.1997                                                     */
/*    actualized some strings ... (Kosmetik)                     */
/* 13.4.1996                                                     */
/*    changed EOF != ... to (unsigned char) EOF !=               */
/* 26.3.1996                                                     */
/*    changed include to sys/time.h for portability              */
/* apri-mai 1995                                                 */
/*    first release                                              */  
/*****************************************************************/

/*
** 
** 
** Dieses Programm wurde f"ur einen www Server an der Fakult"at
** Informatik der HAB-Weimar -Universit"at-
** geschrieben.
** <p> apr-mai 95 by mm (Marko Meister)
**
** diese software ist -frei- im Sinne der GNU-GPL 
**
*/

const char *string_version               = "Pinnwand v1.7.005";

#define PINN_DOKU_URL "http://www.uni-weimar.de/~meister1/private/papers/pinnwand"

/* includes: */

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

/* is needed for gettimeofday() 
   win95port                    
 */
#ifdef WIN32
#include <sys/timeb.h>
#include <time.h>
#include <direct.h> /* for _getcwd() */
#else
#include <sys/time.h>
#endif


/*  Definitions:  */

/*  for debugging  */
#define PINN_DEBUG             
#undef  PINN_DEBUG             

#define TRUE                        1
#define FALSE                       0

#define LF                          10
#define CR                          13

#define PINN_MAX_FORM_ENTRIES       8

#ifdef WIN32
#define PINN_PATH_DELIMITER         '\\'
#else
#define PINN_PATH_DELIMITER         '/'
#endif



#define PINN_RC_BUFF_SIZE           65000
#define PINN_ENTRY_BUFF_SIZE        8192

#define PINN_TMP_LISTFILENAME       "list.tmp"
#define PINN_TMP_OLDLISTFILENAME    "oldlist.tmp"

/* kritische Fehler (Programm wird beendet) */
#define PINN_FEHLER_001             "CONTENT_LENGHT ist nicht definiert."
#define PINN_FEHLER_002             "Im Formular fehlen wichtige Felder!"
#define PINN_FEHLER_003             "Die im Formular angegebene Ressourcedatei kann nicht geoeffnet werden!"
#define PINN_FEHLER_004             "Die eingestellte Puffer (PINN_RC_BUFF_SIZE) ist kleiner als die Ressourcedatei!" 
#define PINN_FEHLER_005             "In der Ressourcedatei fehlt ein wichtiges Feld!" 
#define PINN_FEHLER_006             "Beim Aufruf von der Kommandozeile musz als Parameter der Name der Ressourcedatei angegeben werden!" 
#define PINN_FEHLER_007             "Die Nachrichtendatei kann nicht angelegt werden!" 
#define PINN_FEHLER_008             "Die interne Indexdatei kann nicht geoeffnet werden!" 
#define PINN_FEHLER_009             "Die Indexdatei kann nicht geoeffnet werden!" 
#define PINN_FEHLER_010             "Die OldIndexdatei kann nicht geoeffnet werden!" 
#define PINN_FEHLER_011             "Die temporaere OldIndex Datei kann nicht geoeffnet werden!" 
#define PINN_FEHLER_012             "Die temporaere Index Datei kann nicht geoeffnet werden!" 
#define PINN_FEHLER_013             "Die eingestellte Puffer (PINN_ENTRY_BUFF_SIZE) ist kleiner als ein Eintrag in der internen Indexdatei!" 
#define PINN_FEHLER_014             "Die interne Indexdatei kann nicht angelegt werden!" 
#define PINN_FEHLER_015             "Nicht genuegend Spüeicherplatz um einen internen Puffer zu allozieren!" 

/* Warnungen (Programm laeuft weiter) */
#define PINN_WARN_001 "Das Formular enthaelt zu viele Felder!"

#define PINN_ERROR(out_string) {\
    if (the_firsterror) {\
        the_firsterror=FALSE;\
        fprintf(stdout,"content-Type: text/plain\n\n");}\
    fprintf(stdout,"%s: Programm wird beendet!\n",string_version);\
    fprintf(stdout,"%s ", out_string);\
    fflush (stdout);}

#define PINN_WARN(out_string) {\
    if (the_firsterror) {\
          the_firsterror=FALSE;\
          fprintf(stdout,"content-Type: text/plain\n\n");}\
          fprintf(stdout,"%s: \n",string_version);\
          fprintf(stdout,"%s ", out_string);\
          fprintf(stdout,"\nVersuche Programm fortzusetzen!\n");\
          fflush (stdout);}

/* Structures: */

typedef struct {
  char* name;
  char* val;
} cgi_entry;

/* globals:   */


char *wochentag[7] ={ "Sonntag",
                      "Montag",
                      "Dienstag",
                      "Mittwoch",
                      "Donnerstag",
                      "Freitag",
                      "Samstag"};

/* globale Namensdefinition.
   So muessen die Felder im Formular heiszen! */

char *input_name[8] ={"rc_filename",
                      "subject",
                      "message",
                      "author",
                      "email",
                      "url",
                      "verfall",
                      "methode"};
/* so muessen die Felder im rc file heiszen */
/* hier die einzeiligen (enden mit CR LF) */
#define PINN_MAX_RC_FIELDS_SHORT  11
char *rc_short_name[PINN_MAX_RC_FIELDS_SHORT] =
{ "MESSAGE_BASE_NAME",
  "EMPTY_URL",
  "OUTPUT_PATH",
  "OUTPUT_PATH_URL",
  "INDEX_FILE_INTERN",
  "INDEX_FILE_INTERN_NEW",
  "INDEX_FILENAME",
  "OLDINDEX_FILENAME",
  "KILL_HTML_IN_INDEX_FILES",
  "INSERT_HREFS_IN_MESSAGES",
  "POST_STRING"};

/* hier die mehrzeiligen (enden mit 2x CR LF (Leerzeile)) */
#define PINN_MAX_RC_FIELDS_LONG   7
#define PINN_MAX_RC_FIELDS        PINN_MAX_RC_FIELDS_SHORT+PINN_MAX_RC_FIELDS_LONG
char *rc_long_name[PINN_MAX_RC_FIELDS_LONG] = 
{ "[MESSAGE_TEMPLATE]",
  "[EMAIL_HINT_TEMPLATE]",
  "[PREVIEW_OK_HINT_TEMPLATE]",
  "[OK_HINT_TEMPLATE]",
  "[ENTRY_TEMPLATE]",
  "[INDEX_TEMPLATE]",
  "[OLDINDEX_TEMPLATE]"};

/* dies ist die Reihenfolge der Felder in rc_fields */

#define PINN_MESSAGE_BASE_NAME        0
#define PINN_EMPTY_URL                1
#define PINN_OUTPUT_PATH              2
#define PINN_OUTPUT_PATH_URL          3
#define PINN_INDEX_FILE_INTERN        4
#define PINN_INDEX_FILE_INTERN_NEW    5
#define PINN_INDEX_FILENAME           6
#define PINN_OLDINDEX_FILENAME        7
#define PINN_KILL_HTML_IN_INDEX_FILES 8
#define PINN_INSERT_HREFS             9
#define PINN_POST_STRING              10

#define PINN_MESSAGE_TEMPLATE         PINN_MAX_RC_FIELDS_SHORT
#define PINN_EMAIL_HINT_TEMPLATE      PINN_MAX_RC_FIELDS_SHORT+1
#define PINN_PREVIEW_OK_HINT_TEMPLATE PINN_MAX_RC_FIELDS_SHORT+2
#define PINN_OK_HINT_TEMPLATE         PINN_MAX_RC_FIELDS_SHORT+3
#define PINN_ENTRY_TEMPLATE           PINN_MAX_RC_FIELDS_SHORT+4
#define PINN_INDEX_TEMPLATE           PINN_MAX_RC_FIELDS_SHORT+5
#define PINN_OLDINDEX_TEMPLATE        PINN_MAX_RC_FIELDS_SHORT+6

int the_firsterror = TRUE;
int the_kill_html =FALSE;
int the_insert_hrefs = FALSE;
int the_kill_long_line = FALSE;
char the_date[256];
char the_filename[256];
long the_current_time_value;

char *input[PINN_MAX_FORM_ENTRIES];
char *rc_fields[PINN_MAX_RC_FIELDS];


/* die placeholder muessen immer mit diesem String beginnen   */
/* ist relevant fuer put_and_substitute                       */
#define PINN_PREFIX         "%PINNWAND_"
#define PINN_SUFFIX         "%"

/* wenn mehr substitutionen gewuenscht werden, dann
   auch put_placeholder_text entsprechend aendern! */
#define S_DATE              "%PINNWAND_DATE%"               
#define S_SUBJECT           "%PINNWAND_SUBJECT%"
#define S_MESSAGE           "%PINNWAND_MESSAGE%"
#define S_AUTHOR            "%PINNWAND_AUTHOR%"
#define S_EMAIL             "%PINNWAND_EMAIL%"
#define S_URL               "%PINNWAND_URL%"   
#define S_REMOTE_HOST       "%PINNWAND_REMOTE_HOST%"
#define S_REMOTE_ADDR       "%PINNWAND_REMOTE_ADDR%"
#define S_VERSION           "%PINNWAND_VERSION%" 
#define S_MESSAGE_FILENAME  "%PINNWAND_MESSAGE_FILENAME%"
#define S_MSG_LIST          "%PINNWAND_MSG_LIST%"
#define S_OLDMSG_LIST       "%PINNWAND_OLDMSG_LIST%"
#define S_INDEX_FILENAME    "%PINNWAND_INDEX_FILENAME%"
#define S_OLDINDEX_FILENAME "%PINNWAND_OLDINDEX_FILENAME%"
#define S_OUTPUT_PATH_URL   "%PINNWAND_OUTPUT_PATH_URL%"
#define S_HINTS             "%PINNWAND_HINTS%"
#define S_DOKU_URL          "%PINNWAND_DOKU_URL%"
#define S_VERFALL           "%PINNWAND_VERFALL%"


/* helper functions: */

void getword(char *word, char *line, char stop) {
  int x = 0,y;

  for(x=0;((line[x]) && (line[x] != stop));x++)
    word[x] = line[x];

  word[x] = '\0';
  if(line[x]) ++x;
  y=0;

  while(line[y++] = line[x++]);
}

char *makeword(char *line, char stop) {
  int x = 0,y;
  char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));

  for(x=0;((line[x]) && (line[x] != stop));x++)
    word[x] = line[x];

  word[x] = '\0';
  if(line[x]) ++x;
  y=0;

  while(line[y++] = line[x++]);
  return word;
}

char *fmakeword(FILE *f, char stop, int *cl) {
  int wsize;
  char *word;
  int ll;

  wsize = 102400;
  ll=0;
  word = (char *) malloc(sizeof(char) * (wsize + 1));

  while(1) {
    word[ll] = (char)fgetc(f);
    if(ll==wsize) {
      word[ll+1] = '\0';
      wsize+=102400;
      word = (char *)realloc(word,sizeof(char)*(wsize+1));
    }
    --(*cl);
    if((word[ll] == stop) || (feof(f)) || (!(*cl))) {
      if(word[ll] != stop) ll++;
      word[ll] = '\0';
      return word;
    }
    ++ll;
  }
}

char x2c(char *what) {
  register char digit;

  digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
  digit *= 16;
  digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
  return(digit);
}

void unescape_url(char *url) {
  register int x,y;

  for(x=0;url[x];x++)
    if(url[x] == '+') url[x] = ' ';
  for(x=0,y=0;url[y];++x,++y) {
    if((url[x] = url[y]) == '%') {
      url[x] = x2c(&url[y+1]);
      y+=2;
    }
  }
  url[x] = '\0';
}


int rind(char *s, char c) {
  register int x;
  for(x=strlen(s) - 1;x != -1; x--)
    if(s[x] == c) return x;
  return -1;
}

int getline(char *s, int n, FILE *f) {
  register int i=0;

  while(1) {
    s[i] = (char)fgetc(f);

    if(s[i] == CR)
      s[i] = fgetc(f);

    if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
      s[i] = '\0';
      return (feof(f) ? 1 : 0);
    }
    ++i;
  }
}

void send_fd(FILE *f, FILE *fd)
{
  int num_chars=0;
  char c;

  while (1) {
    c = fgetc(f);
    if(feof(f))
      return;
    fputc(c,fd);
  }
}

int ind(char *s, char c) {
  register int x;

  for(x=0;s[x];x++)
    if(s[x] == c) return x;

  return -1;
}

void escape_shell_cmd(char *cmd) {
  register int x,y,l;

  l=strlen(cmd);
  for(x=0;cmd[x];x++) {
    if(ind("&;`'\"|*?~<>^()[]{}$\\",cmd[x]) != -1){
      for(y=l+1;y>x;y--)
	cmd[y] = cmd[y-1];
      l++; /* length has been increased */
      cmd[x] = '\\';
      x++; /* skip the character */
    }
  }
}

/* end of helperfunctions */


/* for porting I had to implement strncasecmp: */
int my_strncasecmp(char* s1,const char* s2,size_t l)
{
#ifdef WIN32
  return (_strnicmp(s1,s2,l));
#else
  return (strncasecmp(s1,s2,l));
#endif

}


char *my_getcwd(char *buffer, size_t maxlen)
{
#ifdef WIN32
  return (_getcwd(buffer,maxlen));
#else
  return ((char*) getcwd(buffer,maxlen));
#endif

}


void pinn_exit(int code) 
{
  fprintf(stdout,"Beendigungsgrund: %d\n\n",code);
  fprintf(stdout,"%s\n",string_version);
  fprintf(stdout,"Kommandozeile: pinnwand <ressourcefilename>\n");
  fprintf(stdout,"               ... die Pinnwand wird aktualisiert.\n");
  fprintf(stdout,"pinnwand wird normalerweise als CGI-Programm von einem HTTP-Server\n");
  fprintf(stdout,"ueber ein entsprechendes Formular gestartet.\n");
  fprintf(stdout,"\n");
  fprintf(stdout,"Die Dokumentation dieses Programms findet sich unter \n");
  fprintf(stdout,"%s\n",PINN_DOKU_URL);
  fprintf(stdout,"\n");       
  fprintf(stdout,"| Marko Meister, E-mail: Marko.Meister@medien.uni-weimar.de |\n");
  fprintf(stdout,"|                WWW:    http://www.uni-weimar.de/~meister1 |\n");
  fprintf(stdout,"| 'halleluja, der turm stuerzt ein ... '                    |\n");
  fprintf(stdout,"+------------------------------------------------pinnwand---+\n");
  fprintf(stdout,"\n");

  if (code == -6) {
    fprintf (stdout, "Um fortzufahren, <ENTER> druecken ...");
    fscanf (stdin,"egal");
  }
  exit (code);
  return;
}



/* filename is a pointer to an allocated String 
   base is a Pointer to the String wich contains
   the basename of the file
   offset is a time value in days which is added to the current
   time (needed for automatically expiration)
*/
int create_a_filename(char *name,char *base,int offset)
{
  /* win95 port: */
#ifdef WIN32
  struct _timeb tv;
  _ftime( &tv );
  offset=offset*24*3600; 
  sprintf(name,"%s.%.6d.%.6d.html",base,tv.time+offset,tv.millitm);
  return (0);  
#else
  struct timeval tv;
  struct timezone tz;
  offset=offset*24*3600;   
  gettimeofday(&tv,&tz);
  sprintf(name,"%s.%.6d.%.6d.html",base,tv.tv_sec+offset,tv.tv_usec);
  return (0);  
#endif
}


/* This is a workaround. 
   If someone uses a textarea field for Subject, it can be, that
   there are CR/LFs in the string. If they get to the internal indexfile,
   pinnwand crashes. Therefore I replace the CR/LFs by Spaces. 
   mm, april 1998
*/
char *kill_long_line(char *string)
{
  int i,l;
  char *temp = (char *) calloc ( strlen(string)+5, sizeof (char) );

  if (the_kill_long_line) {
    if (temp==NULL) {
      PINN_ERROR(PINN_FEHLER_015);
      PINN_ERROR("in function: kill_long_line\n");
      pinn_exit (-15);
    }
    l=strlen(string);
    for (i=0; i<l; i++)
      {
	if ((CR == string[i]) ||
	    (LF == string[i]) ) {
	  temp[i]=' ';
	} else
	  temp[i]=string[i];
      }
  } else
    return (string);
  return (temp);
}


/* This function replaces all the < by &lt;
   and > by &gt;
   This function is called for SUBJECT, AUTHOR, etc,
   if KILL_HTML_IN_INDEX_FILES is set to ja in the rc-file
*/
char *kill_html(const char *string)
{
  int i,j,k=0;
  char *temp = (char *) calloc ( 16*strlen(string), sizeof (char) );
  /* --- jaja Ihr boesen buben! ;-) */
  if (temp==NULL) {
    PINN_ERROR(PINN_FEHLER_015);
    PINN_ERROR("in function: kill_html\n");
    pinn_exit (-15);
  }
  for (i=0,j=0; i<strlen(string); i++,j++)
    {
      if ('<' == string[i]) {
	/* Ich weisz, das ist nicht sehr elegant, aber es musz jetzt schnell
	   gehen */
	temp[j]   = '<';
	temp[++j] = 'B';
	temp[++j] = '>';
	temp[++j] = '&';
	temp[++j] = 'l';
	temp[++j] = 't';
	temp[++j] = ';';
	k++;
	continue;
      }
      if ('>' == string[i]) {
	temp[j]   = '&';
	temp[++j] = 'g';
	temp[++j] = 't';
	temp[++j] = ';';
	temp[++j] = '<';
	temp[++j] = '/';
	temp[++j] = 'B';
	temp[++j] = '>';
	k--;
	continue;
      }
      /* was zum teufel soll das jetzt sein: ? */
      if (('&' == string[i]) &&
	  ('m' == string[i+1]) &&
	  ('m' == string[i+2]) &&
	  ( ('<' == string[i+3]) || ('>' == string[i+3])) && 
	  (';' == string[i+4]) ) {
	temp[j]   = string[i+3];
	i+=4;
	continue;
      }
      temp[j] = string[i];
    }
  while ( k!=0) {
    if (k>0) {
      temp[j]   = '&';
      temp[++j] = 'g';
      temp[++j] = 't';
      temp[++j] = ';';
      temp[++j] = '<';
      temp[++j] = '/';
      temp[++j] = 'B';
      temp[++j] = '>';
      k--;
    }
    else {
      temp[j]   = '<';
      temp[++j] = 'B';
      temp[++j] = '>';
      temp[++j] = '&';
      temp[++j] = 'l';
      temp[++j] = 't';
      temp[++j] = ';';
      k++;
    }
  }
  /* don't forget: */
  if (0==j) {
    temp[j++]='?';
  }
  temp[j+1] = '\0';
   
  /*fprintf (stdout,"ergebnis:_%s_\n",temp);*/
  return (temp);
}

/* This function turns all URLs in a Message into valid Links
 */
char *insert_hrefs(const char *string)
{
  int i,j,k=0,merke=0,l,interpretieren=TRUE,len;
  char *temp = (char *) calloc ( 3*strlen(string), sizeof (char) );

  if (temp==NULL) {
    PINN_ERROR(PINN_FEHLER_015);
    PINN_ERROR("in function: insert_hrefs\n");
    pinn_exit (-15);
  }

  len=strlen(string);

  for (i=0,j=0; i<len; i++)
    {
      if ('<' == string[i])
	interpretieren=FALSE;
      if ('>' == string[i])
	interpretieren=TRUE;
       
      if (('h' == string[i]) &&
	  ('t' == string[i+1]) &&
	  ('t' == string[i+2]) &&
	  ('p' == string[i+3]) &&
	  (':' == string[i+4]) &&
	  ('/' == string[i+5]) &&
	  ('/' == string[i+6]) &&
	  (0==k) &&
	  (interpretieren==TRUE))
	{
	  temp[j++] = '<';
	  temp[j++] = 'A';
	  temp[j++] = ' ';
	  temp[j++] = 'H';
	  temp[j++] = 'R';
	  temp[j++] = 'E';
	  temp[j++] = 'F';
	  temp[j++] = '=';
	  temp[j++] = '"';
	  temp[j++] = string[i];
	  merke++;
	  k++;
	  continue;
	}
      /* hier stehen die Zeichen, anhand derer erkannt wird, ob der
	 URL zu ende ist */
      if (((' ' == string[i]) ||
           ('<' == string[i]) ||
           ('>' == string[i]) ||
           ('\\' == string[i]) ||
           ('"' == string[i]) ||
           ('!' == string[i]) ||
           ('\t' == string[i]) ||
           ('\n' == string[i]) ||
           ('\r' == string[i]) ) &&
	  (k==1))
	{
	  temp[j++] = '"';
	  temp[j++] = ' ';
	  temp[j++] = 'T';
	  temp[j++] = 'A';
	  temp[j++] = 'R';
	  temp[j++] = 'G';
	  temp[j++] = 'E';
	  temp[j++] = 'T';
	  temp[j++] = '=';
	  temp[j++] = '"';
	  temp[j++] = '_';
	  temp[j++] = 't';
	  temp[j++] = 'o';
	  temp[j++] = 'p';
	  temp[j++] = '"';
	  temp[j++] = '>';
           
	  for (l=0;l<merke;l++) 
	    temp[j++]   = string[i-merke+l];
	  temp[j++] = '<';
	  temp[j++] = '/';
	  temp[j++] = 'A';
	  temp[j++] = '>';
	  temp[j++] = string[i];
	  k--;
	  merke=0;
	  continue;
	}
      if (k==1)
	merke++;
      temp[j++] = string[i];
    }
  /*fprintf (stdout,"ergebnis:_%s_\n",temp);*/
  if (k==1)
    {
      temp[j++] = '"';
      temp[j++] = '>';
      for (l=0;l<merke;l++) 
	temp[j++]   = string[i-merke+l];
      temp[j++] = '<';
      temp[j++] = '/';
      temp[j++] = 'A';
      temp[j++] = '>';
      temp[j++] = '\0';
    } else
      temp[j++]='\0';

  return (temp);
}

int kill_carriage_returns(char *a_string)
{
  int i;
  int l=strlen(a_string);

  for (i=0; i<l;i++) {
    if (CR == a_string[i]) {
      a_string[i]=' ';
    }
  }
  return(0);
}

int get_input(void)
{
  /* return:  0 -- ok
     -1 -- content_lenght nicht definiert 
     -2 -- zu viele Felder im Formular    
     -3 -- Formularfeldname nicht gefunden */
  int input_length,i,j;
  cgi_entry entries[PINN_MAX_FORM_ENTRIES];

    /* wenn Content_Lenght nicht definiert ist, waeren wir nicht hier sondern bei update!*/
  input_length = atoi (getenv ("CONTENT_LENGTH"));

  for (i = 0; input_length && (!feof (stdin)); i++) {
    if (i<PINN_MAX_FORM_ENTRIES) {
      entries[i].val = fmakeword (stdin,'&',&input_length);
      unescape_url (entries[i].val);
      entries[i].name = makeword (entries[i].val, '='); 
    }
    else {
      PINN_WARN(PINN_WARN_001);
      return (1);
    }
  }

  for (i=0;i<PINN_MAX_FORM_ENTRIES;i++) {
    j=0;
    while (0!= strcmp(input_name[i],entries[j].name)) {
      j++;
      if (j>PINN_MAX_FORM_ENTRIES) {
	PINN_ERROR(PINN_FEHLER_002);
	PINN_ERROR(input_name[i]);
	return (-2);
      }
    }
    input[i]=strdup(entries[j].val);
  }

  return (0);
}
    
int read_rc_file(void) 
{
  FILE *rc_file=NULL;

  char c;
  int i,j;
  char *buffer;
  char *temp1, *temp2;
  int comment=FALSE;

  buffer = malloc(PINN_RC_BUFF_SIZE);
  temp2 = malloc(PINN_RC_BUFF_SIZE);
  i=0;

  if (NULL!=(rc_file=fopen(input[0],"r"))) {
    while( !feof(rc_file))   {
      c=fgetc(rc_file);
      if (!feof(rc_file)) {
	/* Kommentar sind nur die zeilen, mit newline am Anfang! */
	if (0==i) {
	  if (c=='#') {
	    while ((c!='\n') && (!feof(rc_file))) 
	      c=fgetc(rc_file);
	  } else 
	    buffer[i++]=c;
	} else {
	  if ((c=='#') && (buffer[i-1]=='\n')) {
	    while ((c!='\n') && (!feof(rc_file))) 
	      c=fgetc(rc_file);
	  } else 
	    buffer[i++]=c;
	}
      }             
      if (i>=PINN_RC_BUFF_SIZE) {
	PINN_ERROR(PINN_FEHLER_004);
	fclose(rc_file);
	return(-4);
      }
    }
    fclose(rc_file);
    buffer[i]='\0';
  }
  else {
    PINN_ERROR(PINN_FEHLER_003);
    fprintf(stdout,"rc-filename: %s\n",input[0]);
    return(-3);
  }


#ifdef PINN_DEBUG
  fprintf(stdout,"buffer (%d Bytes) is: \n\n%s \n",strlen(buffer), buffer);
  fflush(stdout);
#endif

  /* read short names */
  for (i=0; i<PINN_MAX_RC_FIELDS_SHORT; i++) {
    temp1 =strstr(buffer,rc_short_name[i]);
    if (temp1 == NULL) {
      PINN_ERROR(PINN_FEHLER_005);
      fprintf (stdout,"\n%s fehlt in der rc Datei!\n",rc_short_name[i]);

      return(-5);
    } else {
      while (temp1[0]!='=') 
	temp1++;
      temp1++;
      j=0;
      while (temp1[j]!='\n') {
	temp2[j]=temp1[j];
	j++;
      }
      temp2[j]='\0';

      rc_fields[i] = strdup(temp2);
#ifdef PINN_DEBUG
      fprintf (stdout,"found %s in rc file (%s)\n",rc_short_name[i],rc_fields[i] );
      fflush(stdout);
#endif

    }
  }
  for (i=0; i<PINN_MAX_RC_FIELDS_LONG; i++) {
    temp1 =strstr(buffer,rc_long_name[i]);
    if (temp1 == NULL) {
      PINN_ERROR(PINN_FEHLER_005);
      fprintf (stdout,"\n%s fehlt in der rc Datei!\n",rc_long_name[i]);
      return(-5);
    } else {
      while (temp1[0]!='\n') 
	temp1++;
      temp1++;
      j=0;
      while (!((temp1[j]=='\n')&&(temp1[j+1]=='\n'))) {
	temp2[j]=temp1[j];
	j++;
      }
      temp2[j]='\0';

      rc_fields[i+PINN_MAX_RC_FIELDS_SHORT] = strdup(temp2);
#ifdef PINN_DEBUG
      fprintf (stdout,"found %s in rc file (%s)\n",rc_long_name[i],rc_fields[i+PINN_MAX_RC_FIELDS_SHORT]);
      fflush(stdout);
#endif
    }
  }
  /* replace all newlines in entrytemplate with spaces*/
  for (i=0;i<strlen(rc_fields[PINN_ENTRY_TEMPLATE]);i++)
    if ('\n'==rc_fields[PINN_ENTRY_TEMPLATE][i]) 
      rc_fields[PINN_ENTRY_TEMPLATE][i]=' ';
  return (0);
}

int check_email(void)
{
  if ((0==strcmp(input[4],"")) || 
      (NULL==strchr(input[4],'@'))||
      (NULL==strchr(input[4],'.'))||
      (5>strlen(input[4]))) 
    return (FALSE);
  else 
    return (TRUE);
}



/* Prototyp wird wegen Rekursion benoetigt */

int put_and_subst(FILE *fileptr,char *pinn_templat); 

int put_placeholder_text(FILE *fileptr,char *var_name)
{
  char *temp_buf;
  char name_with_path[1024];
  char c;
  FILE *infile=NULL;
    
  if (0==strcmp(var_name,S_DATE)) {
    fprintf(fileptr,"%s",the_date);        
    return (0);
  }
  if (0==strcmp(var_name,S_DOKU_URL)) {
    fprintf(fileptr,"%s",PINN_DOKU_URL);        
    return (0);
  }
  if (0==strcmp(var_name,S_SUBJECT)) {
    if (the_kill_html) 
      fprintf(fileptr,"%s",kill_long_line(kill_html(input[1])));
    else
      fprintf(fileptr,"%s",kill_long_line(input[1]));
    return (0);
  }
  if (0==strcmp(var_name,S_MESSAGE)) { 
    kill_carriage_returns(input[2]);
    if (the_kill_html) {
      if (the_insert_hrefs)
	fprintf(fileptr,"%s",insert_hrefs(kill_html(input[2])));
      else
	fprintf(fileptr,"%s",kill_html(input[2]));
    }
    else {
      if (the_insert_hrefs)
	fprintf(fileptr,"%s",insert_hrefs(input[2]));
      else
	fprintf(fileptr,"%s",input[2]);
    }
    return (0);
  }
  if (0==strcmp(var_name,S_AUTHOR)) {
    if (the_kill_html)
      fprintf(fileptr,"%s",kill_html(input[3]));
    else
      fprintf(fileptr,"%s",input[3]);
    return (0);
  }
  if (0==strcmp(var_name,S_EMAIL)) {
    if (the_kill_html)
      fprintf(fileptr,"%s",kill_html(input[4]));
    else
      fprintf(fileptr,"%s",input[4]);
    return (0);
  }
  if (0==strcmp(var_name,S_URL)) {
    if (   (0 == strcmp(input[5], rc_fields[PINN_EMPTY_URL]))
	   || (10 > strlen(input[5])) )  {
      if (the_kill_html)
	fprintf(fileptr,"%s",kill_html(input[4]));
      else
	fprintf(fileptr,"mailto:%s",input[4]);
      return (0);
    } 
    else {
      if (the_kill_html)
	fprintf(fileptr,"%s",kill_html(input[5]));
      else 
	fprintf(fileptr,"%s",input[5]);
      return (0);
    }
  }
  if (0==strcmp(var_name,S_INDEX_FILENAME)) {        
    fprintf(fileptr,"%s",rc_fields[PINN_INDEX_FILENAME]);
    return (0);
  }
  if (0==strcmp(var_name,S_OLDINDEX_FILENAME)) {        
    fprintf(fileptr,"%s",rc_fields[PINN_OLDINDEX_FILENAME]);
    return (0);
  }
  if (0==strcmp(var_name,S_OUTPUT_PATH_URL)) {        
    fprintf(fileptr,"%s",rc_fields[PINN_OUTPUT_PATH_URL]);
    return (0);
  }

  if (0==strcmp(var_name,S_MSG_LIST)) {
    strcpy(name_with_path,rc_fields[PINN_OUTPUT_PATH]);
    strcat(name_with_path,PINN_TMP_LISTFILENAME);
    infile=fopen(name_with_path,"r");
    if (NULL==infile) {
      PINN_ERROR(PINN_FEHLER_012);
      return(-12);
    } else {
      while(1) {
	c=fgetc(infile);
	if (feof(infile))
	  break;
	fputc (c,fileptr);
      }
      fclose (infile);
    }
    return (0);
  }

  if (0==strcmp(var_name,S_OLDMSG_LIST)) {
    strcpy(name_with_path,rc_fields[PINN_OUTPUT_PATH]);
    strcat(name_with_path,PINN_TMP_OLDLISTFILENAME);
    infile=fopen(name_with_path,"r");
    if (NULL==infile) {
      PINN_ERROR(PINN_FEHLER_011);
      return(-11);
    } else {
      while(1) {
	c=fgetc(infile);
	if (feof(infile))
	  break;
	fputc (c,fileptr);
      }
      fclose (infile);
    }
    return (0);
  }
  if (0==strcmp(var_name,S_MESSAGE_FILENAME)) {
    fprintf(fileptr,"%s",the_filename);
    return (0);
  }
  if (0==strcmp(var_name,S_REMOTE_ADDR)) {
    if (NULL != (temp_buf=getenv ("REMOTE_ADDR"))) 
      fprintf(fileptr,"%s",temp_buf);
    else    
      fprintf(fileptr,"REMOTE_ADDR nicht definiert");
    return (0);
  }
  if (0==strcmp(var_name,S_REMOTE_HOST)) {
    if (NULL != (temp_buf=getenv ("REMOTE_HOST"))) 
      fprintf(fileptr,"%s",temp_buf);
    else
      fprintf(fileptr,"REMOTE_HOST nicht definiert");
    return (0);
  }
  if (0==strcmp(var_name,S_VERSION)) {
    fprintf(fileptr,"%s",string_version);
    return (0);
  }
  if (0==strcmp(var_name,S_VERFALL)) {
    fprintf(fileptr,"%s",input[6]);
    return (0);
  }
  if (0==strcmp(var_name,S_HINTS)) {
    /* hints wird nur auf stdout geschrieben. */
    if (fileptr == stdout) {
      /* das ist Rekursion ?!! */
      if (FALSE==check_email()) 
	put_and_subst(fileptr,rc_fields[PINN_EMAIL_HINT_TEMPLATE]) ;
      else {
	if (0==strcmp(input[7],rc_fields[PINN_POST_STRING]))
	  put_and_subst(fileptr,rc_fields[PINN_OK_HINT_TEMPLATE]) ;
	else
	  put_and_subst(fileptr,rc_fields[PINN_PREVIEW_OK_HINT_TEMPLATE]) ;
      }
    }
    return (0);
  }
  /* wenn nicht vorhanden, dann den Text einfach ausgeben */
  fprintf(fileptr,"%s",var_name);
  return (0);
}

int put_and_subst(FILE *fileptr,char *pinn_templat) 
{
  char *var_name_buffer =  (char *) calloc(1024, sizeof(char));

  int check_varname=FALSE;
  int i,j;

  j=0;
  for (i=0;i<strlen(pinn_templat);i++) {
    /* 18.5.98: damit nicht jedes % im rc-file zu fehlern fuehrt */
    if (((PINN_PREFIX[0] == pinn_templat[i]) &&
	 (PINN_PREFIX[1] == pinn_templat[i+1]) &&
	 (PINN_PREFIX[2] == pinn_templat[i+2]) &&
	 (PINN_PREFIX[3] == pinn_templat[i+3]) &&
	 (PINN_PREFIX[4] == pinn_templat[i+4]) &&
	 (PINN_PREFIX[5] == pinn_templat[i+5]) &&
	 (PINN_PREFIX[6] == pinn_templat[i+6]) &&
	 (PINN_PREFIX[7] == pinn_templat[i+7]) &&
	 (PINN_PREFIX[8] == pinn_templat[i+8]) &&
	 (FALSE == check_varname)) || 
	((PINN_SUFFIX[0] == pinn_templat[i]) &&
	 (TRUE == check_varname)))
      {
	if (!check_varname) {
	  check_varname=TRUE;
	  var_name_buffer[j++]=pinn_templat[i];
	}
	else {
	  var_name_buffer[j++]=pinn_templat[i];
	  var_name_buffer[j++]='\0';
		
	  put_placeholder_text(fileptr,var_name_buffer);
	  check_varname=FALSE;
	  j=0;
	}
	    
      } else {
	if (check_varname)
	  var_name_buffer[j++]=pinn_templat[i];
	else 
	  fputc(pinn_templat[i],fileptr);
      }
  }
  return (0);
}



int write_output_file(void) 
{
  char name_with_path[1024];
  char name_with_path1[1024];

  char c;

  FILE *output=NULL;
  FILE *input1=NULL;

  /* dateiname generieren */
  create_a_filename(the_filename, rc_fields[PINN_MESSAGE_BASE_NAME],atoi(input[6]));
  strcpy(name_with_path,rc_fields[PINN_OUTPUT_PATH]);
  strcat(name_with_path,the_filename);
               
  /* Datei oeffnen und Nachricht reinschreiben */
  output=fopen(name_with_path,"w+");
  if (NULL==output) {
    PINN_ERROR(PINN_FEHLER_007);
    return(-7);
  }
  put_and_subst(output,rc_fields[PINN_MESSAGE_TEMPLATE]); 
  fclose (output);


  /* schreibe die interne index-datei */
  strcpy(name_with_path,rc_fields[PINN_OUTPUT_PATH]);
  strcat(name_with_path,rc_fields[PINN_INDEX_FILE_INTERN_NEW]);
  output = fopen (name_with_path,"w+");
  if (NULL==output) {
    PINN_ERROR(PINN_FEHLER_008);
    return(-8);
  }
   
  /* new since version 1.6b: 
     in author_string and subject_string is any html-tag killed */ 

  if ((0==my_strncasecmp(rc_fields[PINN_KILL_HTML_IN_INDEX_FILES],"yes",3)) ||
      (0==my_strncasecmp(rc_fields[PINN_KILL_HTML_IN_INDEX_FILES],"ja",3)) ||
      (0==my_strncasecmp(rc_fields[PINN_KILL_HTML_IN_INDEX_FILES],"TRUE",4)) ||
      (0==my_strncasecmp(rc_fields[PINN_KILL_HTML_IN_INDEX_FILES],"wahr",4)) ||
      (0==my_strncasecmp(rc_fields[PINN_KILL_HTML_IN_INDEX_FILES],"1",1))) {
    the_kill_html=TRUE;    
  }
  the_kill_long_line=TRUE;
  put_and_subst(output,rc_fields[PINN_ENTRY_TEMPLATE]); 
  /*ENTRYTEMPLATE sollte in einer Zeile stehen!*/
  fprintf(output,"\n");
  the_kill_long_line=FALSE;
  the_kill_html=FALSE;

  strcpy(name_with_path1,rc_fields[PINN_OUTPUT_PATH]);
  strcat(name_with_path1,rc_fields[PINN_INDEX_FILE_INTERN]);
  input1 = fopen (name_with_path1,"r");
  /* wenn diese Datei nicht da ist wird sie ignoriert! */
  /* dies passiert z.B. bei der ersten Nachricht */
  if (NULL!=input1) {
    while(1) {
      c=fgetc(input1);
      if (feof(input1))
	break;
      fputc (c,output);
    }
    fclose (input1);
  }
  fclose (output);
  remove (name_with_path1);
  rename (name_with_path,name_with_path1);    



  return (0);
}



int set_rc_filename(char *programname,char *rc_filename)
{
  /* programname ist argv[0]
     unter NT (apache httpd) ist dies nur der programname
     deshalb wird auch im current workdirectory gesucht.
       */

  int i;
  char *temp1=NULL,*temp2=NULL;
  FILE *rc_file=NULL;

  /* (1) rc-filename plain oeffnen ... */

#ifdef PINN_DEBUG
  fprintf(stdout,"set rc_filename: suche rc file so wie es kommt: \n");
  fprintf(stdout,"rc_filename = %s\n",rc_filename);
  fflush(stdout);
#endif

  if (NULL!=(rc_file=fopen(rc_filename,"r"))) {
    fclose(rc_file);
    input[0] = strdup(rc_filename);
    return (0);
  }
#ifdef PINN_DEBUG
  fprintf(stdout,"fehlgeschlagen!\n");
  fflush(stdout);
#endif

  /* (2) rc-filename im pfad von argv[0] oeffnen */
    
  temp1 = strdup(programname); 
  temp2 = calloc(strlen(rc_filename)+strlen(temp1), sizeof(char));
    
  for (i=strlen(temp1);i>0;i--) {
    if (temp1[i] != PINN_PATH_DELIMITER) 
      temp1[i] = '\0';
    else i=0;
  }

  sprintf(temp2,"%s%s",temp1,rc_filename);
#ifdef PINN_DEBUG
  fprintf(stdout,"set rc_filename: suche rc file im pfad von argv[0]: \n");
  fprintf(stdout,"programname(argv[0]) = %s\n",programname);
  fprintf(stdout,"rc_filename = %s\n",temp2);
  fflush(stdout);
#endif
    
  if (NULL!=(rc_file=fopen(temp2,"r"))) {
    fclose(rc_file);
    input[0] = strdup(temp2);
    return (0);
  }

  free (temp1);
  free (temp2);
  temp1 = NULL;
  temp2 = NULL;

#ifdef PINN_DEBUG
  fprintf(stdout,"fehlgeschlagen!\n");
  fflush(stdout);
#endif

  /* (3) Das .rc file im current workdir oeffnen */

  temp1 = my_getcwd(temp1,1024);
  temp2 = calloc(strlen(rc_filename)+strlen(temp1)+1,sizeof(char));
  sprintf (temp2,"%s%c%s",temp1,PINN_PATH_DELIMITER,rc_filename);

#ifdef PINN_DEBUG
  fprintf(stdout,"set rc_filename: suche rc file im cwd: \n");
  fprintf(stdout,"my_getcwd() = %s\n",temp1);
  fprintf(stdout,"rc_filename = %s\n",temp2);
  fflush(stdout);
#endif
  if (NULL!=(rc_file=fopen(temp2,"r"))) {
    fclose(rc_file);
    input[0] = strdup(temp2);
    return (0);
  }
  fprintf(stdout,"set rc_filename: rc file not found !\n");

   
  return(0);
}


int update()
{
  /* generiere index.html und oldindex.html */

  char name_with_path[1024];
  char *buf_ptr;
  char c;
  FILE *output=NULL;
  FILE *infile=NULL;
  FILE *old_list=NULL;
  FILE *list=NULL;

  char *entry_buffer = malloc(PINN_ENTRY_BUFF_SIZE);
  char *value_buffer = malloc(PINN_ENTRY_BUFF_SIZE);
  int i,j;
  long value;

    /* index_intern-file oeffnen und zwei temporaere dateien schreiben:
       THE_OLDLIST
       THE_LIST
       */
    
    /* internes Indexfile zum lesen oeffnen */
  strcpy(name_with_path,rc_fields[PINN_OUTPUT_PATH]);
  strcat(name_with_path,rc_fields[PINN_INDEX_FILE_INTERN]);
  infile=fopen(name_with_path,"r");
  if (NULL==infile) {
    if (NULL==(infile=fopen(name_with_path,"w"))) {
      PINN_ERROR(PINN_FEHLER_014);
      return(-14);
    }
    fclose(infile);
    infile=fopen(name_with_path,"r");
    if (NULL==infile) {
      PINN_ERROR(PINN_FEHLER_008);
      return(-8);
    }
  }

  /* old_list zum schreiben oeffnen */
  strcpy(name_with_path,rc_fields[PINN_OUTPUT_PATH]);
  strcat(name_with_path,PINN_TMP_OLDLISTFILENAME);
  if (NULL==(old_list=fopen(name_with_path,"w"))) {
    PINN_ERROR(PINN_FEHLER_011);
    return(-11);
  }
    
  /* list zum schreiben oeffnen */
  strcpy(name_with_path,rc_fields[PINN_OUTPUT_PATH]);
  strcat(name_with_path,PINN_TMP_LISTFILENAME);
  if (NULL==(list=fopen(name_with_path,"w"))) {
    PINN_ERROR(PINN_FEHLER_012);
    return(-12);
  }

  /* internes indexfiele zeilen weise einlesen und in old list bzw list schreiben */
  i=0;
  while( !feof(infile))   {
    c=fgetc(infile);
    if ( !feof(infile))
      entry_buffer[i++]=c;
    if (i>=PINN_ENTRY_BUFF_SIZE) {
      PINN_ERROR(PINN_FEHLER_013);
      fclose(infile);
      return(-13);
    }
    if (c=='\n') {
      entry_buffer[i]='\0';
      /* suche den Teil wo die Zahl steht,
	 und speichere die Zahl in value */
      buf_ptr=strstr(entry_buffer,rc_fields[PINN_MESSAGE_BASE_NAME]);
      buf_ptr+=strlen(rc_fields[PINN_MESSAGE_BASE_NAME])+1;
      j=0;
      while ('.'!=(buf_ptr[j])) {
	value_buffer[j]=buf_ptr[j];
	j++;
      }
      value_buffer[j]='\0';
      value=atoi(value_buffer);
      if (the_current_time_value>=value)
	fprintf(old_list,"%s",entry_buffer);
      else 
	fprintf(list,"%s",entry_buffer);
      i=0;
    }
  }
  fclose(infile);
  fclose(list);
  fclose(old_list);

    /* INDEX Datei generieren */

  strcpy(name_with_path,rc_fields[PINN_OUTPUT_PATH]);
  strcat(name_with_path,rc_fields[PINN_INDEX_FILENAME]);
  output=fopen(name_with_path,"w+");
  if (NULL==output) {
    PINN_ERROR(PINN_FEHLER_009);
    return(-9);
  }
  put_and_subst(output,rc_fields[PINN_INDEX_TEMPLATE]); 
  fclose (output);

  /* OLD_INDEX Datei generieren */

  strcpy(name_with_path,rc_fields[PINN_OUTPUT_PATH]);
  strcat(name_with_path,rc_fields[PINN_OLDINDEX_FILENAME]);
  output=fopen(name_with_path,"w+");
  if (NULL==output) {
    PINN_ERROR(PINN_FEHLER_010);
    return(-7);
  }
  put_and_subst(output,rc_fields[PINN_OLDINDEX_TEMPLATE]); 
  fclose (output);

  /* nicht vergessen: die temporaeren Dateien loeschen! */
  strcpy(name_with_path,rc_fields[PINN_OUTPUT_PATH]);
  strcat(name_with_path,PINN_TMP_OLDLISTFILENAME);
  remove(name_with_path);
  strcpy(name_with_path,rc_fields[PINN_OUTPUT_PATH]);
  strcat(name_with_path,PINN_TMP_LISTFILENAME);
  remove(name_with_path);
    
  return (0);
}


int main(int argc , char** argv)
{
  int test;

  struct tm *splitted;
  time_t the_time;
#ifdef WIN32
  struct _timeb tv;
#else
  struct timeval tv;
  struct timezone tz;
#endif

  /* the__current_time_value: repraesentiert die Sekunden seit 1.1.1970 */
#ifdef WIN32 
  time( &the_time );
  _ftime( &tv );
  the_current_time_value=tv.time;
#else
  the_time = time(NULL);
  gettimeofday(&tv,&tz);
  the_current_time_value=tv.tv_sec;
#endif

  splitted = localtime(&the_time); 

  /* the_date: ein String, in dem das aktuelle Datum steht */
  /* tm_year ist die Anzahl der Jahre seit 1900 hier sollte also wenigstens */
  /* tm_year % 100 stehen. (new since 1.7.005)                              */
  sprintf(the_date,"%s, %d.%d.%02d, %02d:%02d Uhr", wochentag[splitted->tm_wday],
	  splitted->tm_mday,
	  splitted->tm_mon+1,
	  splitted->tm_year % 100,
	  splitted->tm_hour,
	  splitted->tm_min);


  sprintf(the_filename,"no_Filename");
    
#ifdef PINN_DEBUG
  fprintf(stdout,"Content-Type: text/plain\n\n");
  fprintf(stdout,"argv[0]: %s \n", argv[0]);
  fprintf(stdout,"the_date: %s \n",the_date);
  fflush(stdout);
#endif

  /* soll ich nur update fahren? */
  /* dann ist input_lenght nicht definiert */ 
  if (NULL == (getenv ("CONTENT_LENGTH"))) {
    if (argc<2) {
      PINN_ERROR(PINN_FEHLER_006);
      pinn_exit(-6);
    }
    test = set_rc_filename(argv[0],argv[1]);
#ifdef PINN_DEBUG
    fprintf(stdout,"input[0] (rc_filename) = %s\n", input[0]);
    fflush(stdout);
#endif
    if (test < 0) pinn_exit (test);
    test = read_rc_file();
    if (test < 0) pinn_exit (test);
    test = update();
    if (test < 0) pinn_exit (test);
  }    
  else {
#ifdef PINN_DEBUG
    fprintf(stdout,"Programm wurde ueber CGI gerufen, lese Input!\n");
    fflush(stdout);
#endif
        
    test = get_input();
    if (test < 0) pinn_exit (test);

    test = set_rc_filename(argv[0],input[0]);
    if (test < 0) pinn_exit (test);

#ifdef PINN_DEBUG
    fprintf(stdout,"versuche das .rc file (%s) zu oeffnen!\n",input[0]);
    fflush(stdout);
#endif
    test = read_rc_file();
    if (test < 0) pinn_exit (test);

#ifdef PINN_DEBUG
    fprintf(stdout,"jetzt gehts los!\n");
    fflush(stdout);
#endif

    if ((0==my_strncasecmp(rc_fields[PINN_INSERT_HREFS],"yes",3)) ||
	(0==my_strncasecmp(rc_fields[PINN_INSERT_HREFS],"ja",3)) ||
	(0==my_strncasecmp(rc_fields[PINN_INSERT_HREFS],"TRUE",4)) ||
	(0==my_strncasecmp(rc_fields[PINN_INSERT_HREFS],"wahr",4)) ||
	(0==my_strncasecmp(rc_fields[PINN_INSERT_HREFS],"1",1))) 
      the_insert_hrefs=TRUE;
               
    fprintf(stdout,"Content-Type: text/html\n\n");
    test = put_and_subst(stdout,rc_fields[PINN_MESSAGE_TEMPLATE]); 
    if (test < 0) pinn_exit (test);

    /* Datei schreiben! */
    if ((TRUE==check_email()) &&
	(0==strcmp(input[7],rc_fields[PINN_POST_STRING])))
      {         
	test = write_output_file(); 
	if (test < 0) pinn_exit (test);
      }
    test = update(); 
    if (test < 0) pinn_exit (test);
      

#ifdef PINN_DEBUG
    fprintf(stdout,"%s: Programm wird normal beendet.\n ", string_version);
    fflush(stdout);
#endif 
  }
  return (0);
}

