/************************************************************************/
/*																		*/
/*		CATRONDO.C														*/
/*																		*/
/*		Rundschreibengenerator fr CAT									*/
/*																		*/
/*		Matthias Strmer (C)1993										*/
/*																		*/
/*		**********************************************************		*/
/*																		*/
/*		1.0		13.8.93		ms@ka2	erste Release						*/
/*		1.1		26.8.93		ms@ka2	Erweiterung um Verteilerliste		*/
/*		1.2		30.8.93		ms@ka2	Returncode fr CAT					*/
/*				 8.9.93		ms@ka2	Bugfix fr TOS 2.06 und gr”žer		*/
/*																		*/
/************************************************************************/
/*		Tabsize:	4													*/

/* -------------------------------------------------------------------- */
/*		Headerdateien einbinden.										*/
/* -------------------------------------------------------------------- */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <aes.h>
#include <tos.h>

#include "catrondo.h"

/* -------------------------------------------------------------------- */
/*		int main ( int argc, const char *argv[] );						*/
/*																		*/
/*		Kernstck des Programms.										*/
/*																		*/
/*		->	argc			Anzahl der Argumente.						*/
/*			argv			Argumente.									*/
/*			1. Parameter:	Quelltext.									*/
/*			2. Parameter:	Zieltext.									*/
/*																		*/
/*		<-	fehler			Exit-Wert.									*/
/* -------------------------------------------------------------------- */

int main ( void )
{
 RUNDINFO	rund;
 MEMBLK		rundinfopuffer, msginfopuffer;
 MSGINFO	*msg;
 int		fehler = 0;
 BOOLEAN	heureka = FALSE;

 fehler = datei_laden( rundinfodatei, &rundinfopuffer );
 fehler_auswerten( rundinfodatei, fehler );
 if ( fehler == 0 )
	{
	fehler = rundinfo_auswerten( &rundinfopuffer, &rund );
	fehler_auswerten( rundinfodatei, fehler );
	Mfree( rundinfopuffer.start );
	if ( (fehler == 0) && (Fsfirst( rund.msginfodatei, 0 ) == 0) )
	/*    kein Fehler  und  MSGINFO.DAT gefunden */
		{
		do	{
			fehler = datei_laden( rund.msginfodatei, &msginfopuffer );
			fehler_auswerten( rund.msginfodatei, fehler );
			if ( fehler == 0 )
				{
				rund.hoechste_nummer = hoechste_nummer( &msginfopuffer );
				fehler = rundschreiben_suchen( &msginfopuffer, &rund, &msg );
				if ( fehler == 0 )
					{
					heureka = TRUE;
					fehler = rundschreiben( &rund, msg );
					}
				Mfree( msginfopuffer.start );
				}
			} while ( fehler == 0 );
		}
	}
 if ( !heureka )
	fehler_auswerten( rund.msginfodatei, 1 ); /* Nichts zu tun */
 else if ( fehler == 1 )
	fehler = 0;

 if ( fehler == 0 )
	fehler = 0x4713;		/* CAT.INF einlesen	*/

 return ( fehler );
}																/* main */


/* -------------------------------------------------------------------- */
/*		int rundschreiben_suchen ( MEMBLK *msginfopuffer,				*/
/*									RUNDINFO *rund, MSGINFO ** msg );	*/
/*																		*/
/*		Sucht die Nummer des ersten Rundschreibens.						*/
/*																		*/
/*		->	msginfopuffer	MSGINFO.DAT im Speicher.					*/
/*			rund			Rundschreiben-Infos.						*/
/*			msg				Eintrag in der MSGINFO.DAT.					*/
/*																		*/
/*		<-	fehler			Laufzeitfehler.								*/
/* -------------------------------------------------------------------- */

int rundschreiben_suchen ( MEMBLK *msginfopuffer, RUNDINFO *rund, MSGINFO **msg )
{
 char		*ende, *pos, merk;
 char		headerdatei[256];
 int		fehler = 0;
 MEMBLK		headerpuffer;
 
 rund->rund_nummer = 0;
 ende = msginfopuffer->start + msginfopuffer->laenge;
 *msg = (MSGINFO *)(msginfopuffer->start + 8);
 do {
	name_zusammensetzen( headerdatei, rund, (*msg)->nummer, ".HDR" );
	fehler = datei_laden( headerdatei, &headerpuffer );
	fehler_auswerten( headerdatei, fehler );
	if ( fehler == 0 )
		{
		merk = *(headerpuffer.start + headerpuffer.laenge - 1);	/* Zeichen zwischenpuffern	*/
		*(headerpuffer.start + headerpuffer.laenge -1) = EOS;	/* um EOS setzen zu k”nnen.	*/
		pos = strstr( headerpuffer.start, rund->intro );		/* Nach dem Ende sollte man	*/
		*(headerpuffer.start + headerpuffer.laenge -1) = merk;	/* ja nicht schreiben.		*/
		if ( pos != NULL )
			{
			rund->rund_nummer = (*msg)->nummer;
			memcpy( rund->rund_name, (char*)((size_t)(pos)+strlen(rund->intro)+1), 32 );
			rund->rund_name[31] = EOS;
			pos = memchr( rund->rund_name, 0x0D, 32 );
			if ( pos != NULL )
				*pos = EOS;
			strcpy( rund->rund_datei, rund->database );
			strcat( rund->rund_datei, "\\" );
			strcat( rund->rund_datei, rund->rund_name );
			strcat( rund->rund_datei, ".INF" );
			}
		}
	Mfree( headerpuffer.start );
	(*msg)++;
	} while ( ((char*)*msg < ende) && (fehler == 0) && (rund->rund_nummer == 0));

 (*msg)--;	/* wieder rcksetzen, um sp„ter darauf zugreifen zu k”nnen	*/

 if ( (fehler == 0) && (rund->rund_nummer == 0) )
	fehler = 1;

 return ( fehler );
}												/* rundschreiben_suchen	*/


/* -------------------------------------------------------------------- */
/*		int rundschreiben ( RUNDINFO *rund, MSGINFO *msg );				*/
/*																		*/
/*		Das eigentliche Rundschreiben.									*/
/*																		*/
/*		->	rund			Infos aus CATRONDO.INF.						*/
/*			msg				Teil aus MSGINFO.DAT im Speicher.			*/
/*																		*/
/*		<-	fehler			Laufzeitfehler.								*/
/* -------------------------------------------------------------------- */

int rundschreiben ( RUNDINFO *rund, MSGINFO *msg )
{
 int		fehler = 0;
 MEMBLK		adresspuffer, headerpuffer, mailpuffer;
 char		*naechste_adresse, adresse[256], headerdatei[256], maildatei[256];

 fehler = datei_laden( rund->rund_datei, &adresspuffer );
 fehler_auswerten( rund->rund_datei, fehler );
 if ( fehler == 0 )
	{
	fehler = plattenplatz_pruefen( &adresspuffer, rund );
	if ( fehler == 0 )
		{
		name_zusammensetzen( headerdatei, rund, rund->rund_nummer, ".HDR" );
		fehler = datei_laden( headerdatei, &headerpuffer );
		fehler_auswerten( headerdatei, fehler );
		if ( fehler == 0 )
			{
			naechste_adresse = adresse_holen( adresspuffer.start, adresse, adresspuffer.start+adresspuffer.laenge, rund );
			fehler = neuen_header_schreiben( &headerpuffer, rund, rund->rund_nummer, adresse );
			}
		if ( fehler == 0 )
			{
			name_zusammensetzen( maildatei, rund, rund->rund_nummer, ".TXT" );
			fehler = datei_laden( maildatei, &mailpuffer );
			fehler_auswerten( maildatei, fehler );
			if ( fehler == 0 )
				{
				verteiler_suchen( rund, &mailpuffer );
				if ( (*(rund->gruss) != EOS) || rund->verteiler )
					fehler = message_kopieren( &mailpuffer, rund, rund->rund_nummer, adresse, &adresspuffer );
				while ( (naechste_adresse != NULL) && (fehler == 0) )
					{
					naechste_adresse = adresse_holen( naechste_adresse, adresse, adresspuffer.start+adresspuffer.laenge, rund );
					(rund->hoechste_nummer)++;
					fehler = neuen_header_schreiben( &headerpuffer, rund, rund->hoechste_nummer, adresse );
					if ( fehler == 0 )
						{
						fehler = message_kopieren( &mailpuffer, rund, rund->hoechste_nummer, adresse, &adresspuffer );
						if ( fehler == 0 )
							fehler = msginfo_erweitern( rund, msg );
						}
					}
				}
			Mfree( mailpuffer.start );
			}
		Mfree( headerpuffer.start );
		}
	Mfree( adresspuffer.start );
	}

 return ( fehler );
}													/* rundschreiben	*/


/* -------------------------------------------------------------------- */
/*		void verteiler_suchen ( RUNDINFO *rund, MEMBLK *mail )			*/
/*																		*/
/*		Soll der Verteiler an die Message angeh„ngt werden?				*/
/*																		*/
/*		->	mail			Hier steht die Ursprungsmail).				*/
/*																		*/
/*		<-	rund->verteiler	Verteiler soll angeh„ngt werden oder nicht.	*/
/* -------------------------------------------------------------------- */

void verteiler_suchen ( RUNDINFO *rund, MEMBLK *mail )
{
 char	*ende;

 rund->verteiler = FALSE;

 ende = mail->start + mail->laenge - 1;
 while ( (*ende == '\n') || (*ende == '\r') )
	ende--;
 if ( strncmp( ende-9, "Verteiler:", 10 ) == 0 )
	rund->verteiler = TRUE;
}													/* verteiler_suchen	*/


/* -------------------------------------------------------------------- */
/*		char *adresse_holen ( char *start, char *adresse, char *ende,	*/
/*								RUNDINFO *rund );						*/
/*																		*/
/*		Adresse aus der Liste holen.									*/
/*																		*/
/*		->	start			Ab hier suchen.								*/
/*			ende			Bis hier suchen.							*/
/*			rund			Infos...									*/
/*																		*/
/*		<-	adresse			Adresse aus der Liste.						*/
/*							N„chster Anfang, NULL, wenn Ende.			*/
/* -------------------------------------------------------------------- */

char *adresse_holen ( char *start, char *adresse, char *ende, RUNDINFO *rund )
{
 char	*pos;
 long	laenge;
 char	selbstreferenz[100], rdatei[32];

 /* zun„chst der Check, ob die Adresse auf die eigene Rundschreibenliste*/
 /* zeigt, d.h. eine direkte Endlosschleife wird vermieden.				*/
 strcpy( selbstreferenz, rund->intro );	
 strcat( selbstreferenz, " " );
 d_get_dateiname( rund->rund_datei, rdatei );
 pos = strchr( rdatei, '.' );
 if ( pos != NULL )
	*pos = EOS;
 strcat( selbstreferenz, rdatei );
 laenge = (long)(ende-start);
 pos = memchr( start, 0x0d, laenge );
 if ( pos != NULL )						/* -> Zeilenende */
	{
	*pos = EOS;
	strcpy( adresse, start );
	pos += 2;
	if ( ende-pos < 4 )		/* kurz vor Ende kann nichts	*/
		pos = NULL;			/* sinnvolles mehr da stehen.	*/
	}
 else if ( ende-start > 3 )	/* es gibt kein Zeilenende, d.h.*/
	{						/* danach ist Schluž.			*/
	strncpy( adresse, start, laenge );
	*(adresse+laenge) = EOS;
	}

 /* Bei Selbstreferenz die n„chste Adresse holen.			*/
 if ( (pos != NULL) && (strcmp( selbstreferenz, adresse )==0) )
	pos = adresse_holen( pos, adresse, ende, rund );

 return ( pos );
}													/* adresse_holen	*/


/* -------------------------------------------------------------------- */
/*		int neue_header_schreiben ( MEMBLK *puffer, int nummer,			*/
/*					RUNDINFO *rund, char *adresse );					*/
/*																		*/
/*		Neue Headerdatei schreiben.										*/
/*																		*/
/*		->	puffer			Alter Header.								*/
/*			rund			Infos...									*/
/*			nummer			neue Nummer.								*/
/*			adresse			Neue Adresse.								*/
/*																		*/
/*		<-					Laufzeitfehler.								*/
/* -------------------------------------------------------------------- */

int neuen_header_schreiben ( MEMBLK *puffer, RUNDINFO *rund, int nummer, char *adresse )
{
 int	dhandle;
 int	fehler = 0;
 long	erg, len;
 char	headerdatei[256], *pos;

 name_zusammensetzen( headerdatei, rund, nummer, ".HDR" );
 dhandle = (int)Fcreate( headerdatei, 0 );
 if ( dhandle <= 0 )
	fehler = dhandle;
 if ( fehler == 0 )
	{
	/* 1. Zeile separieren */
	pos = memchr( puffer->start, 0x0d, puffer->laenge );
	if ( pos!= NULL )
		pos += 2;
	else
		fehler = 2;	/* Fehlerhafter Header */
	/* 1. Zeile schreiben */
	if ( fehler == 0 )
		{
		len = pos-puffer->start;
		erg = Fwrite( dhandle, len, puffer->start );
		if ( erg != len )
			fehler = -10;
		}
	/* Adresse schreiben */
	if ( fehler == 0 )
		{
		strcat( adresse, "\r\n" );
		len = strlen(adresse);
		erg = Fwrite( dhandle, len, adresse );
		if ( erg != len )
			fehler = -10;
		}
	/* 2. Zeile berlesen */
	pos = memchr( pos, 0x0d, puffer->laenge-(long)pos+(long)puffer->start );
	if ( pos!= NULL )
		pos += 2;
	else
		fehler = 2;	/* Fehlerhafter Header */
	/* Rest schreiben */
	if ( fehler == 0 )
		{
		len = puffer->laenge-(long)pos+(long)puffer->start;
		erg = Fwrite( dhandle, len, pos );
		if ( erg != len )
			fehler = -10;
		}
	Fclose( dhandle );
	}
 fehler_auswerten( headerdatei, fehler );

 return ( fehler );
}											/* neuen_header_schreiben	*/


/* -------------------------------------------------------------------- */
/*		int msginfo_erweitern ( MEMBLK *msginfopuffer, RUNDINFO *rund,	*/
/*								MSGINFO *msg );							*/
/*																		*/
/*		MSGINFO.DAT erweitern.											*/
/*																		*/
/*		->	msginfopuffer	MSGINFO.DAT im Speicher.					*/
/*			rund			Infos...									*/
/*			msg				Anzuh„ngendes Struct.						*/
/*																		*/
/*		<-					Laufzeitfehler.								*/
/* -------------------------------------------------------------------- */

int msginfo_erweitern ( RUNDINFO *rund, MSGINFO *msg )
{
 int	fehler = 0, dhandle;
 long	erg, len;
 char	tempdatei[256];
 MEMBLK	msginfodat;

 fehler = datei_laden( rund->msginfodatei, &msginfodat );
 fehler_auswerten( rund->msginfodatei, fehler );
 if ( fehler == 0 )
	{
	strcpy( tempdatei, rund->msginfodatei );
	d_set_extension( tempdatei, "$$$" );
	dhandle = (int)Fcreate( tempdatei, 0 );
	if ( dhandle <= 0 )
		fehler = dhandle;
	}
 /* Anfang schreiben */
 if ( fehler == 0 )
	{
	erg = Fwrite( dhandle, msginfodat.laenge, msginfodat.start );
	if ( erg != msginfodat.laenge )
		fehler = -10;
	}
 /* 1 Struct anh„ngen */
 if ( fehler == 0 )
	{
	msg->nummer = rund->hoechste_nummer;
	len = sizeof( *msg );
	erg = Fwrite( dhandle, len, msg );
	if ( erg != len )
		fehler = -10;
	}
 Fclose( dhandle );
 fehler_auswerten( tempdatei, fehler );
 /* alte MSGINFO.DAT l”schen und Tempor„rdatei Umbenennen	*/
 if ( fehler == 0 )
	{
	fehler = (int)Fdelete( rund->msginfodatei );
	if ( fehler != 0 )
		{
		fehler = 3;
		fehler_auswerten( rund->msginfodatei, fehler );
		}
	else
		{
		fehler = Frename( 0, tempdatei, rund->msginfodatei );
		if ( fehler != 0 )
			{
			fehler = 4;
			fehler_auswerten( tempdatei, fehler );
			}
		}
	}

 return ( fehler );
}												/* msginfo_erweitern	*/


/* -------------------------------------------------------------------- */
/*		int message_kopieren ( MEMBLK *puffer, RUNDINFO *rund,			*/
/*					int nummer, char *adresse, MEMBLK *adresspuffer );	*/
/*																		*/
/*		Message kopieren (Text).										*/
/*																		*/
/*		->	puffer			Kopierpuffer (am Stck).					*/
/*			rund			Infos...									*/
/*			nummer			neue Nummer.								*/
/*			adresse			Zieladresse.								*/
/*																		*/
/*		<-					Laufzeitfehler.								*/
/* -------------------------------------------------------------------- */

int message_kopieren ( MEMBLK *puffer, RUNDINFO *rund, int nummer, char *adresse, MEMBLK *adresspuffer )
{
 int	dhandle;
 int	fehler = 0;
 long	erg, len;
 char	maildatei[256], grusszeile[100], vorname[100], *pos;

 name_zusammensetzen( maildatei, rund, nummer, ".TXT" );
 dhandle = (int)Fcreate( maildatei, 0 );
 if ( dhandle <= 0 )
	fehler = dhandle;
 if ( fehler == 0 )
	{
	if ( *(rund->gruss) != EOS )	/* Gruž vorhanden	*/
		{
		/* Vornamen ermitteln	*/
		strcpy( vorname, adresse );
		pos = strpbrk( vorname, " _.@!%$&?=" );
		if ( pos != NULL )
			*pos = EOS;
		/* Gružzeile aufbauen	*/
		strcpy( grusszeile, rund->gruss );
		strcat( grusszeile, " " );
		strcat( grusszeile, vorname );
		strcat( grusszeile, "!\r\n\r\n" );
		if ( strcmp( vorname, rund->intro ) != EOS )
			{
			len = strlen( grusszeile );
			erg = Fwrite( dhandle, len, grusszeile );
			if ( erg != len )
				fehler = -10;
			}
		}
	if ( fehler == 0 )
		{
		erg = Fwrite( dhandle, puffer->laenge, puffer->start );
		if ( erg != puffer->laenge )
			fehler = -10;
		}
	if ( (fehler == 0) && (rund->verteiler) )
		{
		erg = Fwrite( dhandle, adresspuffer->laenge, adresspuffer->start );
		if ( erg != adresspuffer->laenge )
			fehler = -10;
		}

	Fclose( dhandle );
	}
 fehler_auswerten( maildatei, fehler );

 return ( fehler );
}													/* message_kopieren	*/


/* -------------------------------------------------------------------- */
/*		int hoechste_nummer ( MEMBLK *msginfopuffer );					*/
/*																		*/
/*		Liefert die gr”žte verwendete Messagenummer.					*/
/*																		*/
/*		->	msginfopuffer	MSGINFO.DAT im Speicher.					*/
/*																		*/
/*		<-	nummer			Nummer der Message.							*/
/* -------------------------------------------------------------------- */

int hoechste_nummer ( MEMBLK *msginfopuffer )
{
 char		*ende;
 MSGINFO	*msg;
 int		nummer = 0;

 ende = msginfopuffer->start + msginfopuffer->laenge;
 msg = (MSGINFO *)(msginfopuffer->start + 8);
 do {
	if ( msg->nummer > nummer )
		nummer = msg->nummer;
	msg++;
	} while ( (char*)msg < ende );

 return ( nummer );
}													/* hoechste_nummer	*/


/* -------------------------------------------------------------------- */
/*		void name_zusammensetzen ( char *headerdatei, RUNDINFO *rund,	*/
/*								int nummer, const char *extension );	*/
/*																		*/
/*		Name der Messagedatei zusammensetzen.							*/
/*																		*/
/*		->	rund			Infos: Pfad, etc.							*/
/*			nummer			Nummer der Message.							*/
/*			extension		Header oder Text.							*/
/*																		*/
/*		<-	headerdatei		Name der Headerdatei.						*/
/* -------------------------------------------------------------------- */

void name_zusammensetzen ( char *headerdatei, RUNDINFO *rund, int nummer, const char *extension )
{
 char	num[8] = "0000";

 strcpy( headerdatei, rund->messages );
 strcat( headerdatei, "\\MSG" );

 if ( nummer > 99 )
	itoa( nummer, num, 10 );
 else if ( nummer > 9 )
	itoa( nummer, num+1, 10 );
 else
	itoa( nummer, num+2, 10 );

 strcat( headerdatei, num );
 strcat( headerdatei, extension );
}											/* header_zusammensetzen	*/


/* -------------------------------------------------------------------- */
/*		int plattenplatz_pruefen ( MEMBLK *adresspuffer,				*/
/*									RUNDINFO *rund );					*/
/*																		*/
/*		Prft, ob gengend Platz auf der Platte ist.					*/
/*																		*/
/*		->	adresspuffer	RUND.INF im Speicher.						*/
/*			rund			Rundschreiben-Infos.						*/
/*																		*/
/*		<-	fehler			Laufzeitfehler.	(2: Plattenplatz)			*/
/* -------------------------------------------------------------------- */

int plattenplatz_pruefen ( MEMBLK *adresspuffer, RUNDINFO *rund )
{
 char			*pos, *ende, *cr;
 int			anzahl = 0, lw, fehler = 0;
 unsigned long	platzbedarf, frei;
 DISKINFO		di;

 pos = adresspuffer->start;
 ende = adresspuffer->start + adresspuffer->laenge;
 do {
	anzahl++;
	cr = memchr( pos, 0x0D, ende-pos );
	if ( cr != NULL )
		pos = cr+1;
	} while ( cr != NULL );
 platzbedarf = (long)anzahl << 14; /* 16kB pro Message */
 d_get_laufwerk( rund->database, &lw );
 Dfree( &di, lw );
 frei = di.b_free * di.b_secsiz * di.b_clsiz;
 if ( frei < platzbedarf )
	fehler = 5;
 fehler_auswerten( rund->rund_datei, fehler );

 return ( fehler );
}												/* plattenplatz_pruefen	*/


/* -------------------------------------------------------------------- */
/*		int rundinfo_auswerten ( MEMBLK *puffer, RUNDINFO *rund );		*/
/*																		*/
/*		Infodatei von CATRONDO auswerten.								*/
/*																		*/
/*		->	puffer			In diesem Puffer steht CATRONDO.INF.		*/
/*																		*/
/*		<-	rund			In dieses Struct sollen die Daten.			*/
/* -------------------------------------------------------------------- */

int rundinfo_auswerten ( MEMBLK *puffer, RUNDINFO *rund )
{
 BOOLEAN	ok = TRUE;
 char		*pos, *ende;
 char		testdat[256];
 int		fehler = 0;

 pos = puffer->start;
 ende = puffer->start + puffer->laenge;

 ok = zeile_lesen( &pos, ende, rund->database );
 if ( ok )
	ok = zeile_lesen( &pos, ende, rund->messages );
 if ( ok )
	ok = zeile_lesen( &pos, ende, rund->intro );
 if ( ok )
	ok = zeile_lesen( &pos, ende, rund->gruss );
 if ( ok )
	{
	strcpy( rund->msginfodatei, rund->messages );
	strcat( rund->msginfodatei, "\\MSGINFO.DAT" );
	strcpy( testdat, rund->database );
	strcat( testdat, "\\PRIVATE.DAT" );
	if ( ( Fsfirst( rund->msginfodatei, 0 ) != 0 ) ||
		 ( Fsfirst( testdat, 0 ) != 0 ) )
		ok = FALSE;
	}
 if ( !ok )
	fehler = 6;

 return ( fehler );
}												/* rundinfo_auswerten	*/


/* -------------------------------------------------------------------- */
/*		BOOLEAN zeile_lesen ( char **pos, char *ende, char *var );		*/
/*																		*/
/*		Zeile aus CATRONDO.INF auslesen.								*/
/*																		*/
/*		->	ende			Endmarker von CATRONDO.INF.					*/
/*																		*/
/*		<>	pos				Leseposition innerhalb von CATRONDO.INF.	*/
/*																		*/
/*		<-	var				Stringvariable.								*/
/*							Erfolgreiches Auslesen oder nicht.			*/
/* -------------------------------------------------------------------- */

BOOLEAN zeile_lesen ( char **pos, char *ende, char *var )
{
 char		*cr;
 BOOLEAN	ok = TRUE;

 *var = EOS;
 if ( *pos >= ende )
	ok = FALSE;
 else
	{
	cr = memchr( *pos, 0x0D, ende-(*pos) );
	if ( cr == NULL )
		{
		strncpy( var, *pos, ende-(*pos) );
		*(ende - (*pos) + var) = EOS;
		}
	else
		{
		*cr = EOS;
		strcpy( var, *pos );
		(*pos) = cr+2;
		if ( (*pos) >= ende )
			*pos = ende;
		}
	}

 return ( ok );
}														/* zeile_lesen	*/


/* -------------------------------------------------------------------- */
/*		void fehler_auswerten ( char *dateiname, int fehler );			*/
/*																		*/
/*		Fehlerausgabe.													*/
/*																		*/
/*		->	dateiname		Name der Datei.								*/
/*			fehler			GEMDOS-Fehlernummer.						*/
/*																		*/
/*		<-					Nichts.										*/
/* -------------------------------------------------------------------- */

void fehler_auswerten ( char *dateiname, int fehler )
{
 char fehlertext[200], fehlernr[10], fdatei[64];

 if ( fehler != 0 )
	{
	strcpy( fehlertext, "[1][ CATRONDO:| " );
	switch ( fehler )
		{
		case 1:
			strcat( fehlertext, "Nichts zu tun!" ); break;
		case 5:
			strcat( fehlertext, "Zu wenig Platz auf dem| Speichermedium!" ); break;
		default:
			d_get_dateiname( dateiname, fdatei );
			fdatei[30] = EOS; /* Um der Alertbox keine Schwierigkeiten zu machen...*/
			strcat( fehlertext, "Fehler in Datei| " );
			strcat( fehlertext, fdatei );
			strcat( fehlertext, "| " );
			switch ( fehler )
				{
				case 2:
					strcat( fehlertext, "Fehlerhafte Headerdatei!" ); break;
				case 3:
					strcat( fehlertext, "Fehler beim L”schen!" ); break;
				case 4:
					strcat( fehlertext, "Fehler beim Umbenennen!" ); break;
				case 6:
					strcat( fehlertext, "Fehlerhafte Eintragungen!" ); break;
				case -10:
					strcat( fehlertext, "Schreibfehler!" ); break;
				case -11:
					strcat( fehlertext, "Lesefehler!" ); break;
				case -13:
					strcat( fehlertext, "Das Speichermedium ist| schreibgeschtzt!" ); break;
				case -33:
					strcat( fehlertext, "Datei nicht gefunden!" ); break;
				case -34:
					strcat( fehlertext, "Ordner nicht gefunden!" ); break;
				case -35:
					strcat( fehlertext, "Zu viele Dateien ge”ffnet!" ); break;
				case -36:
					strcat( fehlertext, "Zugriff nicht erlaubt!" ); break;
				case -39:
					strcat( fehlertext, "Nicht gengend Speicher| vorhanden !" ); break;
				case -49:
					strcat( fehlertext, "Es k”nnen keine Dateien| mehr ge”ffnet werden!" ); break;
				default:
					itoa( fehler, fehlernr, 10 );
					strcat( fehlertext, "GEMDOS-Fehler Nr. " );
					strcat( fehlertext, fehlernr );
					break;
				}
		}
	strcat( fehlertext, "][  . . .  ]" );
	form_alert( 1, fehlertext );
	}
}													/* fehler_auswerten	*/


/* -------------------------------------------------------------------- */
/*		int datei_laden ( const char *dateiname, MEMBLK *dateipuffer );	*/
/*																		*/
/*		Datei in einen eigenen Puffer laden.							*/
/*																		*/
/*		->	dateiname		Name der Datei.								*/
/*																		*/
/*		<-	dateipuffer		Puffer der Datei.							*/
/*							Aufgetretener Fehler = GEMDOS-Fehlernummer.	*/
/* -------------------------------------------------------------------- */

int datei_laden ( const char *dateiname, MEMBLK *dateipuffer )
{
 unsigned long	erg;
 long			mem_frei;
 int			dhandle;
 int			fehler = 0;

 dateipuffer->start = NULL;
 dateipuffer->laenge = 0;

 fehler = Fsfirst( dateiname, 0 );
 if ( fehler == 0 )
	{
	dateipuffer->laenge = Fgetdta()->d_length;
	mem_frei = (long)Malloc( -1 );
	if ( mem_frei < dateipuffer->laenge )
		fehler = -39;
	else
		{
		dateipuffer->start = Malloc( dateipuffer->laenge );
		if ( dateipuffer->start == 0 )
			fehler = -39;
		else
			{
			dhandle = (int)Fopen( dateiname, FO_READ );
			if ( dhandle <= 0 )
				fehler = dhandle;
			else
				{
				erg = Fread( dhandle, dateipuffer->laenge, dateipuffer->start );
				Fclose( dhandle);
				if ( erg != dateipuffer->laenge )
					fehler = -11;
				}
			if ( fehler != 0 )
				{
				Mfree( dateipuffer->start );
				dateipuffer->start = NULL;
				dateipuffer->laenge = 0;
				}
			}
		}
	}

 return ( fehler );
}														/* datei_laden	*/


/* -------------------------------------------------------------------- */
/*		int d_get_laufwerk ( const char *pfad, int *drv );				*/
/*																		*/
/*		Ermittelt Laufwerk; wenn in der Pfadangabe keine				*/
/*		Laufwerksangabe ist, wird das aktuelle Laufwerk zurckgegeben.	*/
/*																		*/
/*		->	pfad 				Vollst„ndiger Pfadname. 				*/
/*																		*/
/*		<-	drv					Laufwerk (1:A, 2:B, ...). 				*/
/*								Wenn aktuelles Laufwerk, dann ist der	*/
/*								Rckgabewert 1, sonst 0.				*/
/* -------------------------------------------------------------------- */

int d_get_laufwerk ( const char *pfad, int *drv )
{
 int	ret = 0;

 if ( (pfad[0]>='A') && (pfad[0]<='Z') && (pfad[1]==':') )
	*drv = pfad[0] - 'A' + 1;
  else
   {
	*drv = Dgetdrv() + 1;
	ret = 1;
   }

 return ( ret );
}													/* d_get_laufwerk() */


/* -------------------------------------------------------------------- */
/*		int d_get_pfadname ( const char *vollstaendiger_pfad,			*/
/*							 char *pfad, BOOLEAN lw );					*/
/*																		*/
/*		Ermittelt Pfad aus der Angabe eines vollst„ndigen Pfades;		*/
/*		Wenn der vollst„ndige Pfad leer ist, wird der aktuelle Pfad		*/
/*		des aktuellen Laufwerks zurckgegeben.							*/
/*																		*/
/*		->	vollstaendiger_pfad	Vollst„ndiger Pfadname. 				*/
/*			lw					Pfadname soll Laufwerk enthalten,		*/
/*								falls vorhanden.						*/
/*																		*/
/*		<-	pfad 				Pfadname. 								*/
/*								Wenn aktueller Pfad, dann ist der		*/
/*								Rckgabewert 1, sonst 0, im Fehlerfall	*/
/*								beim akt. Pfad die Fehlernummer.		*/
/* -------------------------------------------------------------------- */

int d_get_pfadname ( const char *vollstaendiger_pfad, char *pfad, BOOLEAN lw )
{
 int		ret = 0;
 char		*pfadanfang, *pfadende, v_pfad[STPATHLEN+1];

 strcpy( v_pfad, vollstaendiger_pfad );
 if ( v_pfad[0] == EOS )
   {
	ret = Dgetdrv();
	if ( ret >= 0 )
	   {
		if ( lw )
		   {
			v_pfad[0] = ret+65;
			v_pfad[1] = ':';
			v_pfad[2] = EOS;
			ret = Dgetpath( v_pfad+2, ret+1 );
		   }
		 else
			ret = Dgetpath( pfad, ret+1 );
		if ( ret == 0 )
		   {
			ret = 1;
			if ( lw )
				strcpy( pfad, v_pfad );
		   }
	   }
   }
  else		/* v_pfad nicht leer */
   {
	if ( ( v_pfad[0] >= 'A' ) &&			/* am Anfang steht	*/
		 ( v_pfad[0] <= 'Z' ) &&			/* das Laufwerk		*/
		 ( v_pfad[1] == ':' ) )
	   {
		if ( v_pfad[2] != '\\' )			/* falls kein \		*/
		   {								/* Fehler			*/
			pfad[0] = ':';					/* korrigieren		*/
			pfad[1] = EOS;
			strcpy( pfad+2, v_pfad+2 );
			strcpy( v_pfad+2, pfad );
		   }
		if ( lw )
			pfadanfang = v_pfad;
		 else
			pfadanfang = &v_pfad[2];
	   }
	 else					/* Laufwerk stand nicht am Anfang	*/
	   {
		pfadanfang = v_pfad;
		if ( lw )			/* soll aber da sein	*/
		   {
			ret = Dgetdrv();
			if ( ret >= 0 )
			   {
				pfad[0] = ret+65;
				pfad[1] = ':';
				if ( v_pfad[0] == '\\' )
				   {
					pfad[2] = EOS;
					strcpy( pfad+2, v_pfad );
				   }
				 else
				   {
					pfad[2] = '\\';
					pfad[3] = EOS;
					strcpy( pfad+3, v_pfad );
				   }
				strcpy( v_pfad, pfad );
				pfadanfang = v_pfad;
			   }			/* ret <0	*/
		   }				/* not lw	*/
	   }

	if ( ret >= 0 )
	   {
		pfadende = strrchr( pfadanfang, '\\' );
		if ( pfadende == 0 )
			pfad[0] = EOS;
		 else
		   {
			strncpy( pfad, pfadanfang, pfadende - pfadanfang + 1);
			pfad[pfadende-pfadanfang+1] = EOS;
		   }
	   }
	 else
		pfad[0] = EOS;
   }

 if ( ret < 0 )
   {
	pfad[0] = EOS;
   }

 return ( ret );
}													/* d_get_pfadname() */


/* -------------------------------------------------------------------- */
/*		void d_get_dateiname ( const char *pfad, char *datei );			*/
/*																		*/
/*		Extrahiert den Dateinamen aus einem Pfad.						*/
/*																		*/
/*		->	pfad 				Vollst„ndiger Pfadname. 				*/
/*																		*/
/*		<>	datei				Dateiname. 								*/
/* -------------------------------------------------------------------- */

void d_get_dateiname ( const char *pfad, char *datei )
{
 char 	*pos, *dateianfang, temp[STPATHLEN+1];

 strcpy( temp, pfad );
 pos = strrchr( temp, '\\' );
 if ( pos == NULL )
	dateianfang = temp;
  else
	dateianfang = pos + 1;
 strcpy( datei, dateianfang );
}												   /* d_get_dateiname() */


/* -------------------------------------------------------------------- */
/*		void d_get_extension ( const char *datei, char *ext );			*/
/*																		*/
/*		Extrahiert die Extension aus einem Pfad.						*/
/*																		*/
/*		->	datei				Datei- oder Pfadname. 					*/
/*																		*/
/*		<-	ext					Extension.								*/
/* -------------------------------------------------------------------- */

void d_get_extension ( const char *datei, char *ext )
{
 char	*pos_punkt, *pos_slash;

 pos_punkt = strrchr( datei, '.' );
 pos_slash = strrchr( datei, '\\' );
 if ( (pos_punkt != NULL) && (pos_slash != NULL) )
   {
	if ( pos_punkt < pos_slash )
		ext[0] = EOS;
	 else
		strcpy( ext, pos_punkt + 1 );
   }
 else if ( pos_punkt == NULL )
	ext[0] = EOS;
  else
	strcpy( ext, pos_punkt + 1 );
}												   /* d_get_extension() */


/* -------------------------------------------------------------------- */
/*		void d_set_extension ( char *datei, const char *ext );			*/
/*																		*/
/*		Extension einer Datei setzen.									*/
/*																		*/
/*		->	ext 				zu setzende Extension. 					*/
/*																		*/
/*		<>	datei				Dateiname. 								*/
/* -------------------------------------------------------------------- */

void d_set_extension ( char *datei, const char *ext )
{
 char	*pos, 		/* absolute Position eines Zeichens in einem String */
		punkt[2]; 	/* "."												*/

 pos = strrchr( datei, '.' );
 if ( pos != NULL )
   {
	pos += 1;
	strcpy( pos, ext );
   }
  else
   {
	strcpy( punkt, "." );
	strcat( datei, punkt );
	strcat( datei, ext );
   }
}												   /* d_set_extension() */


/* -------------------------------------------------------------------- */
/*		void dateiname ( char *dest, int drv,	const char *s1,			*/
/*												const char *s2 );		*/
/*																		*/
/*		Konkatoniere Pfadnamen und Dateinamen. 							*/
/*																		*/
/*		->	drv 				Laufwerk.								*/
/*			s1					Pfadname.								*/
/*			s2					Dateiname. 								*/
/*																		*/
/*		<>	dest				Zielstring.								*/
/* -------------------------------------------------------------------- */

void dateiname ( char *dest, int drv, const char *s1, const char *s2 )
{
 char	bs[2] = "\\",						/* BACKSPACE				*/
		temp[STPATHLEN+1];					/* Zwischenspeicher 		*/

 strcpy( temp, dest );

 if ( drv > 0 ) 							/* drv = 1 -> Laufwerk A	*/
   {
	temp[0] = drv + 'A' - 1;				/* Laufwerk 1 -> A			*/
	temp[1] = ':';							/*				 :			*/
	temp[2] = EOS;
   }
  else										/* drv = 0 -> kein Laufwerk */
	temp[0] = EOS;

 if ( s1[0] == EOS)
   {
	if ( drv > 0 )
		strcat( temp, bs );
   }
  else										/* Pfad != ""				*/
   {
	if ( ( drv > 0 ) && ( s1[0] != '\\' ) )
		strcat( temp, bs );
	strcat( temp, s1 );
	if ( temp[strlen( temp)-1] != '\\' )	/* falls Pfad nicht mit \ 	*/
		strcat( temp, bs );					/* endet, \ anh„ngen		*/
   }

 if ( s2[0] != EOS )						/* Datei != ""				*/
	strcat( temp, s2 );

 strcpy( dest, temp );
}														 /* dateiname() */

/************************************************************************/
/*		E n d e		CATRONDO.C											*/
/************************************************************************/
