Begutachtung von Source

Hi.

Leider hab ich jetzt (über Weihnachten) nicht gerade viel Zeit, aber wie wäre es denn wenn du erstmal nur den Header einliest und den Rest erstmal einfach in die Datei schreibst. Wenn clamscan drüber gerutscht ist kannst du ja immer noch die Datei in die Standardausgabe schreiben - so sparst du dir die Allozierung des Speichers.

Evtl. hast du ja procmail falsch eingestellt, denn normalerweise wartet das Teil zumindest solange bis das Programm erfolgreich ausgeführt wurde?!

Gruß
 
ProcMail ist so eingestellt, dass es wartet bis das Programm fertig ist. Aber ich denke, dass es da trotzdem noch einen TimeOut gibt falls das betreffende Programm z.B. wegen Buffer Overflow oder sowas verreckt.
Ich hab es gestern bevor ich gegangen bin nochmal angeschmissen und time hat mir folgende Info geliefert:
time hat gesagt.:
real 553m41.648s
user 527m6.417s
sys 0m7.400s
Aber offensichtlich ist es nicht durchgelaufen sondern hat nach Ablauf dieser knapp 10 Stunden diese Fehlermeldung produziert:
LibClamAV Error: cli_untar: only standard TAR files are currently supported
Segmentation fault

Kann doch irgendwie nicht sein, dass nur TAR supported ist. Und wenn ich den Eicar-Test-String in ein .tar.gz packe dann erkennt er denn ja auch.

Du meinst also, dass ich nur den Header in eine Variable schreibe, damit ich dort meinen Header einfuegen kann, der Rest wandert gleich in die Datei und nach dem Scan lese ich die Datei wieder aus gebe sich nach STDOUT aus?

Und dass Du ueber Weihnachten keine Zeit und Lust hast Dich hier andauernd mit meinem Problem zu befassen ist klar und verstaendlich, erwarte ich auch garnicht.
Ich selbst werde heute und morgen etwas Zeit haben und mich mal weiter drum kuemmern. Jegliche Fortschritte werde ich hier kundtun.

Auf jeden Fall nochmals vielen Dank und ein frohes Fest.

Nachtrag:
Im Moment macht mir mein Ansatz um auf den doppelten Zeilenumbruch zu pruefen noch ein paar Probleme.
Folgenden Code hab ich zum testen mal genutzt:
Code:
data=malloc(16);
data[0]=(char)NULL;
strncpy(data,"Hallo Welt",10);
printf("%s\r\n",data); //Hallo Welt
printf("%s\r\n",data+strlen(data)-4); //Welt
if (data+strlen(data)-4=="Welt")
{
 printf("1\r\n"); //wird nicht ausgegeben
}
free(data);
Eigentlich sollte doch if (data+strlen(data)-4=="Welt") dies zutreffen, oder?
Immerhin hab ich zuvor genau diesen Sub-String ausgegeben und dabei "Welt" erhalten. Aber warum ist das nun nicht =="Welt"?

Nachtrag 2:
Okay, Kommande zurueck. Ich hab das gleiche jetzt mit strcmp() probiert und dies fuehrt zum Erfolg.

Nachtrag 3:
Es scheint als haette mein Rewrite ordentlich was gebracht. Fuer die selbe eMail (mit der selben Fehlermeldung im Anschluss :rolleyes: ) werden jetzt keine 10 Stunden sondern nur noch knapp 1 Minute benoetigt. Es scheint also, dass es wohl an den ganzen Reallozierungen gelegen hat.

Ich hab es jetzt doch nicht so gemacht, dass ich erstmal den Header in eine Variable und den Rest in eine Datei schreibe sondern ich schreibe alles gleich in die Datei. Scanne diese und lese sie dann wieder aus. Und vor der Ausgabe schiebe ich halt noch meinen Header ein.
Der Grund dafuer ist einfach: Wenn ich den Header nicht mit in die Datei geschrieben habe wurde der Virus nicht erkannt.

Hier die letzte Fassung des alten, langsamen Codes:
Code:
ret=cl_loaddbdir(cl_retdbdir(),&node,&signo);
if (ret)
	{
		return EXIT_FAILURE;
	}
ret=cl_build(node);
if (ret)
	{
		cl_free(node);
		return EXIT_FAILURE;
	}
memsize=initialmemsize;
data=malloc(memsize);
if (data==NULL)
	{
		cl_free(node);
		return EXIT_FAILURE;
	}
data[0]=(char)NULL;
memcount=0;
while ((scanf("%c",&input)!=EOF) && (data!=NULL))
	{
		memcount++;
		if (memcount>=memsize)
			{
				memsize+=initialmemsize;
				data=realloc(data,memsize);
			}
		if (data!=NULL)
			{
				strncat(data,input,1);
			}
	}
if (data==NULL)
	{
		cl_free(node);
		return EXIT_FAILURE;
	}
scantmpfile=tmpfile();
if (scantmpfile==NULL)
	{
		printf("%s",data);
		cl_free(node);
		free(data);
		return EXIT_FAILURE;
	}
fwrite(data,sizeof(char),strlen(data),scantmpfile);
fflush(scantmpfile);
ret=cl_scandesc(fileno(scantmpfile),&virname,NULL,node,NULL,CL_SCAN_STDOPT);
fclose(scantmpfile);
part1=strstr(data,"Subject:");
if (part1==NULL)
	{
		printf("%s",data);
		cl_free(node);
		free(data);
		return EXIT_FAILURE;
	}
part2=strstr(part1,"\n");
email=malloc(strlen(data)+512);
if (email==NULL)
	{
		printf("%s",data);
		cl_free(node);
		free(data);
		return EXIT_FAILURE;
	}
email[0]=(char)NULL;
strncpy(email,data,strlen(data)-strlen(part2)+2);
email[strlen(data)-strlen(part2)+1]=(char)NULL;
free(data);
if (ret==CL_VIRUS)
	{
		strcat(email,"X-Virus-Status: Yes\r\n");
		strcat(email,"X-Virus-Checker: Scanned by mailscan ");
		strcat(email,mailscanversion);
		strcat(email," (Virus found: ");
		strcat(email,virname);
		strcat(email,")\r\n");
	}
else if (ret==CL_CLEAN)
	{
		strcat(email,"X-Virus-Status: No\r\n");
		strcat(email,"X-Virus-Checker: Scanned by mailscan ");
		strcat(email,mailscanversion);
		strcat(email," (No virus found)\r\n");
	}
else
	{
		strcat(email,"X-Virus-Status: Error\r\n");
		strcat(email,"X-Virus-Checker: Scanned by mailscan ");
		strcat(email,mailscanversion);
		strcat(email," (Scan error: ");
		strcat(email,cl_strerror(ret));
		strcat(email,")\r\n");
	}
strcat(email,part2+1);
printf("%s",email);
cl_free(node);
free(email);
return EXIT_SUCCESS;
Und hier die aktuelle, unheimlich beschleunigte Version:
Code:
ret=cl_loaddbdir(cl_retdbdir(),&node,&signo);
if (ret)
	{
		return EXIT_FAILURE;
	}
ret=cl_build(node);
if (ret)
	{
		cl_free(node);
		return EXIT_FAILURE;
	}
scantmpfile=tmpfile();
if (scantmpfile==NULL)
	{
		cl_free(node);
		return EXIT_FAILURE;
	}
while (scanf("%c",&input)!=EOF)
	{
		fwrite(input,sizeof(char),1,scantmpfile);
	}
memsize=ftell(scantmpfile);
fflush(scantmpfile);
ret=cl_scandesc(fileno(scantmpfile),&virname,NULL,node,NULL,CL_SCAN_STDOPT);
data=malloc(memsize);
if (data==NULL)
	{
		cl_free(node);
		fclose(scantmpfile);
		return EXIT_FAILURE;
	}
data[0]=(char)NULL;
rewind(scantmpfile);
fread(data,sizeof(char),memsize,scantmpfile);
fclose(scantmpfile);
part1=strstr(data,"Subject:");
if (part1==NULL)
	{
		cl_free(node);
		free(data);
		return EXIT_FAILURE;
	}
part2=strstr(part1,"\n");
email=malloc(memsize+512);
if (email==NULL)
	{
		cl_free(node);
		free(data);
		return EXIT_FAILURE;
	}
email[0]=(char)NULL;
strncpy(email,data,strlen(data)-strlen(part2)+1);
free(data);
if (ret==CL_VIRUS)
	{
		strcat(email,"X-Virus-Status: Yes\r\n");
		strcat(email,"X-Virus-Checker: Scanned by mailscan ");
		strcat(email,mailscanversion);
		strcat(email," (Virus found: ");
		strcat(email,virname);
		strcat(email,")\r\n");
	}
else if (ret==CL_CLEAN)
	{
		strcat(email,"X-Virus-Status: No\r\n");
		strcat(email,"X-Virus-Checker: Scanned by mailscan ");
		strcat(email,mailscanversion);
		strcat(email," (No virus found)\r\n");
	}
else
	{
		strcat(email,"X-Virus-Status: Error\r\n");
		strcat(email,"X-Virus-Checker: Scanned by mailscan ");
		strcat(email,mailscanversion);
		strcat(email," (Scan error: ");
		strcat(email,cl_strerror(ret));
		strcat(email,")\r\n");
	}
strcat(email,part2+1);
printf("%s",email);
free(email);
return EXIT_SUCCESS;
 
Eigentlich sollte doch if (data+strlen(data)-4=="Welt") dies zutreffen, oder?
Immerhin hab ich zuvor genau diesen Sub-String ausgegeben und dabei "Welt" erhalten. Aber warum ist das nun nicht =="Welt"?

Nachtrag 2:
Okay, Kommande zurueck. Ich hab das gleiche jetzt mit strcmp() probiert und dies fuehrt zum Erfolg.

Du vergleichst da zwei Referenzen die auf zwei verschiedene String Objekte
zeigen, die koennen nicht gleich sein. Deswegen kann da nur strcmp
funktionieren....

Code:
("Welt" == "Welt") == false


Gruß

RedWing
 
Ich hab halt in den letzten Jahren zu viel mit PHP gearbeitet, da verlernt man schon ein wenig von dem was so in C abgeht.
Aber ich werde mich auf jeden Fall jetzt wieder intensiver mit C beschaeftigen, kann auf jeden Fall nie schaden. :)
 
So, ueber das Weihnachtsfest und die letzten beiden Tage hab ich noch was am Code geschraubt.
Meine 6MB grosse Testmail braucht jetzt nicht mehr knapp 5 Stunden um verarbeitet zu werden, sondern nur noch 20-50 Sekunden (ja nach Last auf dem Rechner).

Weiterhin habe ich auch so gut wie moeglich versucht die Vorschlaege einzubauen. So findet nun zum Beispiel strncat() regen Gebrauch und auch die wesentlich bessere TempFile-Verwaltung mittels tmpfile() funktioniert wunderbar.
Ein paar Probleme hatten mir unerwartete Zeichen an String-Enden gemacht. Das lag wohl daran das ich zuvor strncpy() genutzt hab und dann die Strings unterminiert waren.
Auch am Anfang von Strings hatte ich zum Teil merkwuerdige Zeichen, diese konnte ich aber durch Code wie diesen nach dem allozieren entfernen.
Code:
if (strlen(data)>0)
	{
		data[0]=(char)NULL;
	}
Und zwischendurch gab es noch das Problem, dass ich den Pointer part1 nicht wieder mit free() deallozieren konnte, aber auch das konnte ich dann loesen. Wer haette gedacht, dass es daran liegt, dass der String ein Zeichen zu kurz ist? ;)
Der zu Beginn angesprochene Optimismus ist auch aus dem Script verschwunden und es sollte im Grunde so gut wie jeder moegliche Fehler entsprechend behandelt werden.

Bevor ich nun die Versionsnummer von 0.9 auf 1.0 erhebe wollte ich den Code noch einmal in vollem Umfang posten und werde natuerlich selbst auch noch testen ob der Code noch irgendwie aus den Schuhen zu hauen ist.

Code:
/***************************************************************************
 *   Copyright (C) 2005 by Dennis Wronka                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

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

const char mailscanversion[4]="0.9";
int ret;
unsigned int signo;
unsigned long memsize;
struct cl_node *node;
struct cl_limits limits;
const char *virname;
char input[1];
char *data,*email,*part1,*part2;
FILE *scantmpfile;

int main(int argc, char *argv[])
{
	ret=cl_loaddbdir(cl_retdbdir(),&node,&signo);
	if (ret)
		{
			return EXIT_FAILURE;
		}
	ret=cl_build(node);
	if (ret)
		{
			cl_free(node);
			return EXIT_FAILURE;
		}
	scantmpfile=tmpfile();
	if (scantmpfile==NULL)
		{
			cl_free(node);
			return EXIT_FAILURE;
		}
	while (scanf("%c",&input)!=EOF)
		{
			fwrite(input,sizeof(char),1,scantmpfile);
		}
	memsize=ftell(scantmpfile);
	fflush(scantmpfile);
	memset(&limits,0,sizeof(struct cl_limits));
	limits.maxfiles=1000000;
	limits.maxfilesize=10*1048576;
	limits.maxreclevel=100;
	limits.maxratio=500;
	limits.archivememlim=0;
	ret=cl_scandesc(fileno(scantmpfile),&virname,NULL,node,&limits,CL_SCAN_STDOPT | CL_SCAN_BLOCKMAX);
	data=malloc(memsize+1);
	if (data==NULL)
		{
			fclose(scantmpfile);
			cl_free(node);
			return EXIT_FAILURE;
		}
	if (strlen(data)>0)
		{
			data[0]=(char)NULL;
		}
	rewind(scantmpfile);
	fread(data,sizeof(char),memsize,scantmpfile);
	data[memsize]=(char)NULL;
	fclose(scantmpfile);
	if (strstr(data,"Subject:")==NULL)
		{
			free(data);
			cl_free(node);
			return EXIT_FAILURE;
		}
	part1=malloc(strlen(strstr(data,"Subject:"))+1);
	if (part1==NULL)
		{
			free(data);
			cl_free(node);
			return EXIT_FAILURE;
		}
	if (strlen(part1)>0)
		{
			part1[0]=(char)NULL;
		}
	strncat(part1,strstr(data,"Subject:"),strlen(strstr(data,"Subject:")));
	if (strstr(part1,"\n")==NULL)
		{
			free(part1);
			free(data);
			cl_free(node);
			return EXIT_FAILURE;
		}
	part2=malloc(strlen(strstr(part1,"\n"))+1);
	if (part2==NULL)
		{
			free(part1);
			free(data);
			cl_free(node);
			return EXIT_FAILURE;
		}
	if (strlen(part2)>0)
		{
			part2[0]=(char)NULL;
		}
	strncat(part2,strstr(part1,"\n"),strlen(strstr(part1,"\n")));
	free(part1);
	email=malloc(memsize+1024);
	if (email==NULL)
		{
			free(part2);
			free(data);
			cl_free(node);
			return EXIT_FAILURE;
		}
	if (strlen(email)>0)
		{
			email[0]=(char)NULL;
		}
	strncat(email,data,strlen(data)-strlen(part2+1));
	free(data);
	if (ret==CL_VIRUS)
		{
			strcat(email,"X-Virus-Status: Yes\r\n");
			strcat(email,"X-Virus-Checker: Scanned by mailscan ");
			strcat(email,mailscanversion);
			strcat(email," (Virus found: ");
			strcat(email,virname);
			strcat(email,")\r\n");
		}
	else if (ret==CL_CLEAN)
		{
			strcat(email,"X-Virus-Status: No\r\n");
			strcat(email,"X-Virus-Checker: Scanned by mailscan ");
			strcat(email,mailscanversion);
			strcat(email," (No virus found)\r\n");
		}
	else
		{
			strcat(email,"X-Virus-Status: Error\r\n");
			strcat(email,"X-Virus-Checker: Scanned by mailscan ");
			strcat(email,mailscanversion);
			strcat(email," (Scan error: ");
			strcat(email,cl_strerror(ret));
			strcat(email,")\r\n");
		}
	strncat(email,part2+1,strlen(part2+1));
	free(part2);
	printf("%s",email);
	free(email);
	return EXIT_SUCCESS;
}
 
Hi.

Ich hab mir deinen Sourcecode nun nochmal angeschaut und finde das sieht nun wirklich recht gut aus.

Ich habe allerdings mal schnell verschiedene Methoden zum Einlesen von einem Stream getestet weil du gefragt hattest welche Methode besser ist - scanf("%c", &c) oder i = getchar()

Eigentlich ist mir das schon klar gewesen, aber ich hab's trotzdem selber nochmal getestet nur um sicher zu sein, das es auch wirklich stimmt was ich gehört hatte und was ich mir überlegt habe.

Natürlich ist es erstens sowieso etwas ungünstig immer nur zeichenweise zu lesen - deshalb hat man sich ja irgendwann mal die gepufferte Ein-/Ausgabe ausgedacht weil es sonst wirklich viel zu lange dauert.

Dann ist es natürlich so, das beim scanf immer noch der Formatstring geparst werden muß - und das für jedes einzelne Zeichen. Das erzeugt dann auch einen ganz schönen Overhead. Allerdings kann man den Effekt mildern indem man die Anzahl der Zeichen zum Einlesen angibt.

Ich habe eine 100MB große Testdatei genommen und folgende Methoden getestet:

1) zeichenweise einlesen: fscanf(f, "%c", &c)

2) zeichenweise einlesen: i = getc(f)

3) blockweise einlesen, Puffergröße 1024 Byte: fscanf(f, "%1024c", buffer)

4) blockweise Daten einlesen, Puffergröße 1024 Byte:fread(buffer, sizeof(buffer[0]), sizeof(buffer), f)

Die Zeit hab ich einfach ein paarmal mit time in der Shell gestoppt.

1) real 0m24.218s; user 0m24.066s; sys 0m0.152s

2) real 0m3.546s; user 0m3.452s; sys 0m0.096s

3) real 0m1.154s; user 0m1.024s; sys 0m0.132s

4) real 0m0.180s; user 0m0.112s; sys 0m0.068s

Das heißt also Methode 4 ist so ungefähr um den Faktor 135 schneller als die langsamste Variante mit scanf.

Dann würde ich dir empfehlen nicht die ganze Datei in den Speicher zu lesen, sondern auch einfach mit fread blockweise einlesen und auf stdout auszugeben. Eine Pipe unter Linux hat sowieso nur einen 4KByte Puffer und gerade bei größeren Mails wenn die Ausgabe blockiert ist, belegt dein Programm dann unnötig viel Speicher.

Viel Speicher verschwendest du auch beim Kopieren der ganzen Email um ein paar Zeilen einzufügen - ich meine du liest erstmal die komplette Mail in den Speicher, machst dann praktisch eine Kopie (die paar Header, die da wegfallen...) und dann noch eine; wenn also die Mail 10 MiB groß ist belegst du erstmal ganze 30MiB. Ich weiß nicht ob ich mir dein Programm installieren würde... ;)

Ich würde einfach nach dem Viruscheck die Datei solange einlesen bis der Body der Mail anfängt und dann die zusätzlichen Header einfügen und einfach weiter die Datei ausgeben. (muß eine Mail denn eigentlich eine Subject Zeile haben? Wenn ja, könntest du das natürlich auch beim Einlesen prüfen und könntest dir den Viruscheck sparen, da du ja sowieso abbrichst wenn keine Subject Zeile vorhanden ist.

Übrigens solltest an den Stellen wo du einen String in einen anderen kopieren willst nicht strncat verwenden sondern strncpy. Du willst die beiden Strings ja schließlich nicht konkatenieren sondern einfach den einen überschreiben (da steht ja sowieso nix drin). So brauchst du die Strings auch noch dem allozieren nicht gleich nullterminieren weil der Inhalt sowieso gelöscht wird.


Gruß
 
Wow, nochmal vielen Dank fuer Deine Muehe.

Ich werd mich gleich mal dransetzen und versuchen Deine Vorschlaege umzusetzen.
Natuerlich ist das nicht gerade speicherfreundlich wie ich die Mail rumkopiere, aber ich dachte mir dabei erstmal, dass eine eMail in der Regel eh nicht sehr gross ist (in der Regel ja < 10MB) und dann gebe ich ja jede Variable wieder frei sobald sie nicht mehr benoetigt wird.
Natuerlich ist das keine gute Ausrede, und ich werd auch weiter versuchen den Code zu verbessern.

Eine Frage haette ich da auch noch, Du hast Dich ja nun bereits intensiv damit auseinandergesetzt wie ich die Datei am besten einlesen koennte, aber wie kann ich am effektivsten von STDIN einlesen?

Ich hatte ja zuletzt ein wenig mit Valgrind rumgespielt und festgestellt, dass in der hier geposteten Version am Ende noch knapp 8MB Daten erreichbar sind. Das lag daran, dass ich am Ende des Codes vergessen hab mit cl_free(node); die Virendatenbank wieder freizugeben. Nachdem ich dies nun eingearbeitet hab, bleiben noch 663 Bytes erreichbar, aber daran schein ich nichts aendern zu koennen da diese wohl von irgendwo innerhalb cl_scandesc() zu kommen scheinen.
Valgrind hat gesagt.:
==4036== 24 bytes in 3 blocks are still reachable in loss record 1 of 3
==4036== at 0x401A901: calloc (vg_replace_malloc.c:279)
==4036== by 0x404BD7E: cli_calloc (others.c:334)
==4036== by 0x4061BEB: tableCreate (table.c:38)
==4036== by 0x405CA6C: initialiseTables (mbox.c:2789)
==4036== by 0x4059981: cli_parse_mbox (mbox.c:778)
==4036== by 0x4052DD9: cli_scanmail (scanners.c:1335)
==4036== by 0x40534BF: cli_magic_scandesc (scanners.c:1439)
==4036== by 0x4053601: cl_scandesc (scanners.c:1563)
==4036== by 0x8048AAF: main (mailscan.c:72)
==4036==
==4036==
==4036== 291 bytes in 29 blocks are still reachable in loss record 2 of 3
==4036== at 0x4019647: malloc (vg_replace_malloc.c:149)
==4036== by 0x410529F: strdup (in /lib/libc-2.3.2.so)
==4036== by 0x4061CF5: tableInsert (table.c:87)
==4036== by 0x405CAE2: initialiseTables (mbox.c:2803)
==4036== by 0x4059981: cli_parse_mbox (mbox.c:778)
==4036== by 0x4052DD9: cli_scanmail (scanners.c:1335)
==4036== by 0x40534BF: cli_magic_scandesc (scanners.c:1439)
==4036== by 0x4053601: cl_scandesc (scanners.c:1563)
==4036== by 0x8048AAF: main (mailscan.c:72)
==4036==
==4036==
==4036== 348 bytes in 29 blocks are still reachable in loss record 3 of 3
==4036== at 0x4019647: malloc (vg_replace_malloc.c:149)
==4036== by 0x404BCF6: cli_malloc (others.c:314)
==4036== by 0x4061D1F: tableInsert (table.c:80)
==4036== by 0x405CAE2: initialiseTables (mbox.c:2803)
==4036== by 0x4059981: cli_parse_mbox (mbox.c:778)
==4036== by 0x4052DD9: cli_scanmail (scanners.c:1335)
==4036== by 0x40534BF: cli_magic_scandesc (scanners.c:1439)
==4036== by 0x4053601: cl_scandesc (scanners.c:1563)
==4036== by 0x8048AAF: main (mailscan.c:72)

Da Du erwaehnst, dass Du nicht weisst ob Du Dir mein Programm installieren wuerdest wollte ich noch was zur Entstehung loswerden. Ich weiss zwar nicht ob ich das schon getan hab, aber egal.
Der Grund warum ich ueberhaupt auf die Idee gekommen bin selbst diesen Mail-Scanner zu schreiben war, dass ich auf der Arbeit KlamMail dazu genutzt hab um von ProcMail Mails zum Scannen zu erhalten. KlamMail startet aber bei jedem Aufruf clamd, beendet dieses aber nicht. Das fuehrt dazu, dass nur die ersten paar Mails gescannt werden und mir der Speicher mit dem clamd zugemuellt wird. Das ganze ist also quasi ein spontan entstandenes Projekt fuer die Arbeit. Aber natuerlich hatte ich auch im Hinterkopf, das ganze, wenn es denn mal einigermassen vernuenftig laeuft, der Oeffentlichkeit zu praesentieren und zu hoffen, dass es vielleicht nuetzlich ist.
Ich selbst koennte mir durchaus vorstellen meinem heimischen KMail demnaechst zu verklickern nicht mehr KlamMail sondern meinen kleinen Scanner zu nutzen.

So, ich werd mich dann mal ein wenig an die Arbeit machen.
Falls man sich in diesem Jahr nicht mehr lesen sollte wuensche ich Dir einen guten Rutsch.
 
Hi. Frohes neues Jahr!

Dennis Wronka hat gesagt.:
Eine Frage haette ich da auch noch, Du hast Dich ja nun bereits intensiv damit auseinandergesetzt wie ich die Datei am besten einlesen koennte, aber wie kann ich am effektivsten von STDIN einlesen?
Das hab ich gerade nochmal ausgetestet. Dazu hab ich ein Programm geschrieben welches 100 MB an Daten (in 1024 Byte Blöcken) mit fwrite auf die Standardausgabe schreibt. Das Programm selbst braucht ca. 0.150s zur Ausführung um diese Daten nach /dev/null zu schreiben.

Dann hab ich die Testprogramme dahingehend abgeändert das sie von der Standardeingabe lesen:

1) scanf("%c", &c)
2) i = getchar()
3) scanf("%1024c", &buffer)
4) fread(buffer, sizeof(buffer[0]), sizeof(buffer), stdin)

An der Reihenfolge ändert sich freilich nichts.

1) real 0m21.978s; user 0m21.793s; sys 0m0.184
2) real 0m4.248s; user 0m4.064s; sys 0m0.184s
3) real 0m1.208s; user 0m0.976s; sys 0m0.232s
4) real 0m0.457s; user 0m0.268s; sys 0m0.192s

Die schnellste (beste) Methode ist also jedenfalls die Variante mit fread.

Gruß
 
//offtopic
lol da fehlt mir wohl noch Grundlagenwissen :)
Du hast natürlich recht...

Kannst du mir dann auch noch den Unterschied erklären zwischen:

Code:
        char* a = "Welt";
        char* b = "Welt";
        //und
        char s[] = "Welt";
        char t[] = "Welt";

Aber ich denke ich weiß schon. b und a zeigen wahrsch auf das Wort "Welt" im Codesegment, s und t zeigen auf real existierenden Speicher im Stacksegment
und s == t würde dann demnach false ergeben (wenn das definiert ist?).

Das würde auch erklären wieso dann
Code:
a[4] = 's';
in die Hose geht...

Gruß

RedWing
 

Neue Beiträge

Zurück