home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1989 / 03 / praxis / virtest.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1988-12-16  |  14.6 KB  |  436 lines

  1. (* ------------------------------------------------------ *)
  2. (*                    VIRTEST.PAS                         *)
  3. (*  Das Programm überprüft Disketten und die Festplatte   *)
  4. (*  auf Veränderungen und versucht, Beschädigungen zu     *)
  5. (*  reparieren.                                           *)
  6. (*        (c) 1989 Andreas Schuster & TOOLBOX             *)
  7. (* ------------------------------------------------------ *)
  8. PROGRAM VirTest;
  9.  
  10. USES Dos,Crt;
  11.  
  12. CONST
  13.   DefaultName = 'VIRTEST.DTA';   (* Vorgabe Referenzdatei *)
  14.   LogName     = 'VIRTEST.LOG';   (* Name Protokolldatei   *)
  15.   Titel       = 'VirTest   ';
  16.   CopyRight   = '(c) 1989 A. Schuster & TOOLBOX';
  17.   Version     = 'Version 2.1   ';
  18.  
  19. TYPE
  20.   String12 = STRING[12];
  21.   String8  = STRING[8];
  22.   String3  = STRING[3];
  23.   Zeiger   = ^Liste;
  24.   Liste    = RECORD
  25.                Name : String12;
  26.                Next : Zeiger;
  27.              END;
  28.   SaveRec  = RECORD
  29.                Kopf : ARRAY[1..16] OF BYTE;
  30.                Attr : BYTE;
  31.                Time : LONGINT;
  32.                Size : LONGINT;
  33.                Name : String8;
  34.                Ext  : String3;
  35.                Path : STRING[64];
  36.              END;
  37.  
  38. VAR
  39.   Datei      : String12;
  40.   Anzahl     : WORD;          (* gefundene Programme      *)
  41.   Dir        : STRING[64];    (* durchsuchtes Directory   *)
  42.   Puffer,                     (* Puffer für Programmdaten *)
  43.   RefRec     : SaveRec;       (* Referenzdaten            *)
  44.   RefFile    : FILE OF SaveRec;
  45.   Prot       : TEXT;          (* Protokolldatei           *)
  46.   TestFile   : FILE OF BYTE;  (* zu testendes Programm    *)
  47.   Init       : BOOLEAN;       (* bei TRUE Daten holen,    *)
  48.                               (* bei FALSE vergl.         *)
  49.   Kommando,                   (* Option /I oder /T        *)
  50.   OptionName,                 (* Name und                 *)
  51.   OptionPfad : STRING;        (* Pfad der Datendatei      *)
  52.   Warnungen,                  (* Anzahl der Vorwarnungen  *)
  53.   Viren      : WORD;          (* Anzahl der Virenmeldungen*)
  54.   Error,                      (* Fehler in Datei gefunden *)
  55.   KopfErr,                    (* erste 16 Bytes geändert! *)
  56.   ExtErr,                     (* Extension geändert !     *)
  57.   TypErr,                     (* Extension paßt nicht zu  *)
  58.                               (* Dateityp !               *)
  59.   SizeErr,                    (* Dateigröße verändert !   *)
  60.   TimeErr,                    (* Zeiteintrag verändert !  *)
  61.   AttribErr  : BOOLEAN;       (* Attribut geändert        *)
  62.  
  63.  
  64.   FUNCTION Min(a, b : LONGINT) : LONGINT;
  65.   BEGIN
  66.     IF a < b THEN min := a ELSE Min := b;
  67.   END;
  68.  
  69.  
  70.   FUNCTION ZielGruppe(NameExt : String12) : BOOLEAN;
  71.   VAR                                       (* Programm ? *)
  72.     Ext : STRING[4];
  73.   BEGIN
  74.     Ext := Copy(NameExt, Pos('.', NameExt),4);
  75.     IF Ext = '.COM' THEN ZielGruppe := TRUE
  76.     ELSE
  77.       IF Ext = '.EXE' THEN ZielGruppe := TRUE
  78.       ELSE
  79.         IF Ext = '.SYS' THEN ZielGruppe := TRUE
  80.         ELSE
  81.           IF Ext = '.VIR' THEN ZielGruppe := TRUE
  82.           ELSE ZielGruppe:=FALSE;
  83.   END;
  84.  
  85.  
  86.   FUNCTION GetName(NameExt: String12): String8;
  87.                                  (* Datei-Name separieren *)
  88.   BEGIN
  89.     GetName := Copy(NameExt, 1, Pos('.', NameExt) - 1);
  90.   END;
  91.  
  92.  
  93.   FUNCTION GetExt(NameExt : String12) : String3;
  94.                                   (* Datei-Typ separieren *)
  95.   BEGIN
  96.     GetExt := Copy(NameExt, Pos('.', NameExt) + 1, 3);
  97.   END;
  98.  
  99.  
  100.   PROCEDURE ChangeExt(Name           : String8;
  101.                       ExtAlt, ExtNeu : String3);
  102.   VAR
  103.     RenameFile : FILE OF BYTE;
  104.     AlterName,
  105.     NeuerName  : String12;
  106.   BEGIN
  107.     AlterName := Name + '.' + ExtAlt;
  108.     NeuerName := Name + '.' + ExtNeu;
  109.     Assign(RenameFile, AlterName);
  110.     Rename(RenameFile, NeuerName);
  111.   END;
  112.  
  113.  
  114.   PROCEDURE DateiSuche;          (* Directory durchsuchen *)
  115.   VAR
  116.     Anfang, Neu, Aktuell : Zeiger;
  117.     Eintrag              : SearchRec;
  118.     Fehler               : BOOLEAN;
  119.     Datum                : DateTime;
  120.     Dir                  : STRING[64];
  121.  
  122.  
  123.     PROCEDURE DateiDaten;
  124.                         (* Daten des akt. Programms holen *)
  125.     VAR
  126.       i : BYTE;
  127.     BEGIN
  128.       Assign(TestFile, Eintrag.Name);
  129.     IF (Eintrag.Attr AND ReadOnly) <>0 THEN
  130.                                  (* Schreibschutz umgehen *)
  131.       SetFAttr(TestFile, $00);
  132.     Reset(TestFile);
  133.     IF Eintrag.Size > 0 THEN BEGIN
  134.       FOR i := 1 TO Min(16, Eintrag.Size) DO  (* 16 Bytes *)
  135.         Read(TestFile, Puffer.Kopf[i]);       (* lesen,   *)
  136.       IF (Eintrag.Size < 16) THEN
  137.                                  (* wenn Programm kürzer, *)
  138.         FOR i:=Eintrag.Size TO 16 DO
  139.                                  (* mit $00 auffüllen     *)
  140.           Puffer.Kopf[i] := $00;
  141.     END ELSE
  142.       FillChar(Puffer.Kopf[1], 16, $00);
  143.       Close(TestFile);
  144.       IF (Eintrag.Attr AND ReadOnly) <> 0 THEN
  145.                              (* bei Schreibschutz altes   *)
  146.       SetFAttr(TestFile, Eintrag.Attr);
  147.                              (* Attribut wiederherstellen *)
  148.       Puffer.Attr := Eintrag.Attr;
  149.                              (* Daten des Programms in    *)
  150.       Puffer.Time := Eintrag.Time;
  151.                              (* den Puffer laden ...      *)
  152.       Puffer.Size := Eintrag.Size;
  153.       Puffer.Name := GetName(Eintrag.Name);
  154.       Puffer.Ext  := GetExt(Eintrag.Name);
  155.       Puffer.Path := Dir;
  156.       IF Init THEN Write(RefFile, Puffer);
  157.                              (* ... und sichern           *)
  158.     END;
  159.  
  160.  
  161.     FUNCTION KopfFehler: BOOLEAN;
  162.                    (* Veränderung i. d. ersten 16 Bytes ? *)
  163.     VAR
  164.       i: BYTE;
  165.     BEGIN
  166.       KopfFehler := TRUE;
  167.       FOR i := 1 TO 16 DO
  168.         IF Puffer.Kopf[i] <> RefRec.Kopf[i] THEN Exit;
  169.       KopfFehler := FALSE;
  170.     END;
  171.  
  172.  
  173.     PROCEDURE Meldung;
  174.                    (* Bericht in Protokolldatei schreiben *)
  175.     BEGIN
  176.       WriteLn(Prot, Dir);
  177.       WriteLn(Prot, ' ', Eintrag.Name);
  178.       IF KopfErr THEN BEGIN
  179.         WriteLn(Prot, '   V I R E N B E F A L L  !');
  180.         WriteLn(Prot, '   Im Dateikopf wurden Veränderun',
  181.                       'gen festgestellt;');
  182.         WriteLn(Prot, '   Sie sollten dieses Programm ',
  183.                       'nicht mehr verwenden !');
  184.         WriteLn(Prot, '   Die Datei wurde in *.VIR ',
  185.                       'umbenannt.');
  186.       END;
  187.       IF ExtErr THEN BEGIN
  188.         WriteLn(Prot, '   WARNUNG : Extension geändert');
  189.         WriteLn(Prot, '   Wenn Sie die Extension nicht ',
  190.                       'geändert haben, deutet');
  191.         WriteLn(Prot, '   dies auf einen Virus hin.');
  192.       END;
  193.       IF TypErr THEN BEGIN
  194.         WriteLn(Prot, '   WARNUNG : Falscher Dateityp');
  195.         WriteLn(Prot, '   Die Datei trägt die Endung .COM,',
  196.                       ' ihr Aufbau ent-');
  197.         WriteLn(Prot, '   spricht dem Typ .EXE. Dies ',
  198.                       'deutet auf Viren hin.');
  199.         WriteLn(Prot, '   Die Datei wurde in *.EXE ',
  200.                       'umbenannt.');
  201.       END;
  202.       IF SizeErr THEN BEGIN
  203.         WriteLn(Prot, '   WARNUNG : Die Größe der Datei ',
  204.                       'hat sich geändert');
  205.         WriteLn(Prot, '   Haben Sie das Programm neu ',
  206.                       'compiliert oder installiert ?');
  207.         WriteLn(Prot, '   Sonst kann dies auf Viren ',
  208.                       'hindeuten.');
  209.       END;
  210.       IF TimeErr THEN BEGIN
  211.         WriteLn(Prot, '   WARNUNG : Das Datei-Datum hat ',
  212.                       'sich geändert');
  213.         WriteLn(Prot, '   Haben Sie das Programm neu ',
  214.                       'compiliert oder installiert ?');
  215.         WriteLn(Prot, '   Sonst kann dies auf Viren ',
  216.                       'hindeuten.');
  217.       END;
  218.       IF AttribErr THEN
  219.         WriteLn(Prot, '   HINWEIS : Dateiattribut ',
  220.                       'verändert !');
  221.     END;
  222.  
  223.  
  224.     PROCEDURE FindeFehler;
  225.                                   (* aktuelle Daten mit   *)
  226.     CONST                         (* Referenz vergleichen *)
  227.       Abbruch : BOOLEAN = FALSE;
  228.     BEGIN
  229.       Error     := FALSE;         (* Flags initialisieren *)
  230.       KopfErr   := FALSE;
  231.       ExtErr    := FALSE;
  232.       TypErr    := FALSE;
  233.       SizeErr   := FALSE;
  234.       TimeErr   := FALSE;
  235.       AttribErr := FALSE;
  236.     IF (Puffer.Path <> RefRec.Path) OR
  237.        (Puffer.Name <> RefRec.Name) THEN BEGIN
  238.       WriteLn(Prot);
  239.       WriteLn(Prot, '   Im Pfad oder Dateinamen wurden ',
  240.                     'Veränderungen');
  241.       WriteLn(Prot, '   festgestellt. VirTest muß neu ',
  242.                     'initialisiert');
  243.       WriteLn(Prot, '   werden.');
  244.       WriteLn(Prot, '   Erwartet : ', RefRec.Path, '\',
  245.                     RefRec.Name + '.' + RefRec.Ext);
  246.       WriteLn(Prot, '   Gefunden : ', Puffer.Path, '\',
  247.                     Puffer.Name + '.' + Puffer.Ext);
  248.       Close(Prot);
  249.       Close(RefFile);
  250.       GotoXY(1,5);
  251.       WriteLn('Programm abgebrochen - bitte lesen Sie ',
  252.                LogName);
  253.       WriteLn;
  254.       ChDir(OptionPfad);
  255.       Halt(1);
  256.     END;
  257.     IF KopfFehler AND (Puffer.Ext<>'VIR') THEN BEGIN
  258.                     (* Veränderung i.d. ersten 16 Bytes ? *)
  259.       Error   := TRUE;
  260.       KopfErr := TRUE;
  261.       Viren := Viren + 1;            (* Hinweis auf Virus *)
  262.       ChangeExt(Puffer.Name, Puffer.Ext, 'VIR');
  263.                                      (* Datei umbenennen  *)
  264.       Abbruch := TRUE;
  265.       Exit;
  266.     END;
  267.     IF (Puffer.Ext <> RefRec.Ext) AND
  268.        (Puffer.Ext <> 'VIR') THEN BEGIN
  269.       IF (Chr(Puffer.Kopf[1]) + Chr(Puffer.Kopf[2]) = 'MZ')
  270.                                           (* EXE-Header ? *)
  271.          AND (Puffer.Ext='COM') THEN BEGIN
  272.                         (* Extension und Typ inkonsistent *)
  273.         Error  := TRUE;
  274.         TypErr := TRUE; (* Typenfehler schwerwiegender    *)
  275.         ExtErr := FALSE;(* als Extensionsfehler           *)
  276.         Viren  := Viren + 1;
  277.         ChangeExt(Puffer.Name, Puffer.Ext, 'EXE');
  278.                                     (* Fehler korrigieren *)
  279.         Abbruch := TRUE;
  280.       END;
  281.     END;
  282.     IF NOT Abbruch THEN BEGIN
  283.       IF Puffer.Size <> RefRec.Size THEN SizeErr := TRUE;
  284.       IF (Puffer.Time <> RefRec.Time)
  285.          AND (NOT SizeErr) THEN TimeErr := TRUE;
  286.       IF Puffer.Attr <> RefRec.Attr THEN AttribErr := TRUE;
  287.       IF ExtErr OR SizeErr OR TimeErr OR
  288.          AttribErr THEN BEGIN
  289.         Error := TRUE;
  290.         Warnungen := Warnungen + 1;
  291.       END;
  292.     END;
  293.   END;
  294.  
  295.  
  296.   PROCEDURE DateiTest;             (* Programm überprüfen *)
  297.   BEGIN
  298.     Read(RefFile, RefRec);
  299.     DateiDaten;
  300.     FindeFehler;
  301.     IF Error THEN Meldung;
  302.              (* wenn Fehler gefunden, Protokoll schreiben *)
  303.   END;
  304.  
  305.  
  306. BEGIN  (* DateiSuche *)
  307.   FindFirst('*.*', AnyFile, Eintrag);
  308.   GetDir(0,Dir);               (* Pfad merken             *)
  309.   WHILE DosError=0 DO BEGIN
  310.     IF ZielGruppe(Eintrag.Name) THEN BEGIN
  311.       GotoXY(1,5); DelLine;
  312.       WriteLn('Bearbeitet : ', Eintrag.Name);
  313.       IF Init THEN DateiDaten  (* Referenzdaten erstellen *)
  314.               ELSE DateiTest;  (* Programm testen         *)
  315.       Anzahl := Anzahl + 1;
  316.     END;
  317.     FindNext(Eintrag);
  318.   END;
  319.   Anfang  := NIL;              (* Anfang der Unterver-    *)
  320.   Aktuell := NIL;              (* zeichnisliste           *)
  321.   FindFirst('*.*', Directory, Eintrag);
  322.   WHILE DosError = 0 DO BEGIN
  323.     IF Eintrag.Attr = Directory THEN BEGIN
  324.       New(Neu);                (* in Liste aufnehmen ...  *)
  325.       Neu^.Name := Eintrag.Name;
  326.       Neu^.Next := NIL;
  327.       IF Anfang = NIL THEN Anfang := Neu
  328.                       ELSE Aktuell^.Next := Neu;
  329.       Aktuell := Neu;
  330.     END;
  331.     FindNext(Eintrag);         (* und weitersuchen        *)
  332.   END;
  333.   Aktuell := Anfang;
  334.   WHILE Aktuell <> NIL DO BEGIN
  335.     IF (Aktuell^.Name <> '..') AND
  336.        (Aktuell^.Name <> '.') THEN BEGIN
  337.       ChDir(Aktuell^.Name);    (* ins nächste Verzeichnis *)
  338.       DateiSuche;              (* Programme suchen        *)
  339.       ChDir('..');             (* und zurück              *)
  340.     END;
  341.     Aktuell := Aktuell^.Next;
  342.   END;
  343. END;
  344.  
  345.  
  346. PROCEDURE Initialisierung;     (* Referenzdatei erstellen *)
  347. BEGIN
  348.   GetDir(0, Dir);              (* Ausgangspunkt merken    *)
  349.   ChDir(OptionPfad);
  350.   GotoXY(1, 4);
  351.   WriteLn('Platte/Diskette initialisieren');
  352.   Init := TRUE;
  353.   Assign(RefFile, OptionName);
  354.   Rewrite(RefFile);            (* Datei anlegen           *)
  355.   Anzahl := 0;
  356.   ChDir('\');                  (* ins Hauptverzeichnis    *)
  357.   DateiSuche;                  (* nach Programmen suchen  *)
  358.   GotoXY(1, 5);
  359.   DelLine;
  360.   WriteLn('Gesamt gefunden : ', Anzahl, ' Datei(en)');
  361.   ChDir(Dir);
  362.   Close(RefFile);
  363. END;
  364.  
  365.  
  366. PROCEDURE Test;
  367. BEGIN
  368.   Warnungen := 0;
  369.   Viren := 0;
  370.   GetDir(0, Dir);
  371.   GotoXY(1, 4);
  372.   WriteLn('Platte/Diskette testen');
  373.   Init := FALSE;
  374.   ChDir(OptionPfad);
  375.   Assign(RefFile, OptionName); Reset(RefFile);
  376.   Assign(Prot, LogName)      ; Rewrite(Prot);
  377.   Anzahl := 0;
  378.   ChDir('\');
  379.   DateiSuche;
  380.   Close(RefFile);
  381.   WriteLn(Prot);
  382.   Write(Prot, 'Report : ', Warnungen:3, ' Warnung(en)   ');
  383.   WriteLn(Prot, Viren:3, ' Virenmeldung(en)');
  384.   Close(Prot);
  385.   GotoXY(1, 5);
  386.   Write('VirTest Report : ',Warnungen:3);
  387.   WriteLn(' Warnung(en)  ', Viren:3, ' Virenmeldung(en)');
  388.   IF Warnungen + Viren > 0 THEN BEGIN
  389.     WriteLn('Bitte lesen Sie die Logdatei ', LogName);
  390.     ChDir(OptionPfad);
  391.     IF Viren > 0 THEN Halt(20) ELSE
  392.                             (* Infornation für ERRORLEVEL *)
  393.       IF Warnungen > 0 THEN Halt(10)
  394.                             (* bzw. DosExitCode           *)
  395.   END;
  396.   ChDir(Dir);
  397.   Halt(5);                  (* 20=Viren; 10=Warnung; 5=OK *)
  398. END;
  399.  
  400.  
  401. PROCEDURE HilfsText;  (* Syntax ausgeben *)
  402. BEGIN
  403.   WriteLn('Syntax : VIRTEST /I [d:\pfad] [dateiname]  ',
  404.           'Initialisierung');
  405.   WriteLn('                 /T [d:\pfad] [dateiname]  ',
  406.           'Test');
  407.   WriteLn;
  408.   WriteLn;
  409.   Halt(1);
  410. END;
  411.  
  412.  
  413. BEGIN  (* Hauptprogramm *)
  414.   ClrScr;
  415.   WriteLn(Titel, Version, CopyRight);
  416.   IF ParamCount < 1 THEN HilfsText;
  417.   Kommando   := ParamStr(1);
  418.   OptionPfad := ParamStr(2);
  419.   OptionName := ParamStr(3);
  420.   IF Kommando = '?' THEN HilfsText;
  421.   IF (Pos('\', OptionPfad) = 0) AND
  422.      (Pos(':', OptionPfad) = 0) THEN BEGIN
  423.     OptionName := OptionPfad;
  424.     GetDir(0, OptionPfad);
  425.   END;
  426.   IF OptionName = '' THEN OptionName := DefaultName;
  427.   IF Pos(':', OptionPfad) = Length(OptionPfad) THEN
  428.     OptionPfad := OptionPfad + '\';
  429.   IF (Kommando = '/I') OR (Kommando='/i') THEN
  430.     Initialisierung
  431.   ELSE
  432.     IF (Kommando = '/T') OR (Kommando = '/t') THEN Test
  433.                                              ELSE HilfsText;
  434. END.
  435. (* ------------------------------------------------------ *)
  436. (*                 Ende von VIRTEST.PAS                   *)