home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / multtsk / cpmult / demo / finder.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-04-07  |  12.6 KB  |  383 lines

  1. {//////////////////////////////////////////////////////////////////////////////
  2. ///                                                                         ///
  3. ///              Turbo-Pascal Multi-Tasking Subsystem V2.10                 ///
  4. ///                    Demonstration der Unit MtPipe                        ///
  5. ///                                                                         ///
  6. ///             (c) Christian Philipps Software-Technik, Moers              ///
  7. ///                            im April 1990                                ///
  8. ///                                                                         ///
  9. ///                Dieses System erfordert Turbo-Pascal V5.x                ///
  10. ///                sowie das Multi-Tasking Subsystem V2.10                  ///
  11. ///                                                                         ///
  12. ///////////////////////////////////////////////////////////////////////////////
  13. ///                                                                         ///
  14. ///  Das Programm Finder durchsucht eine oder mehrere Platten anhand einer  ///
  15. ///  oder mehrerer Suchmuster, die als Befehlszeilenparameter übergeben     ///
  16. ///  werden.                                                                ///
  17. ///  Je Suchmuster wird eine separate Task gestartet, so daß die einzel-    ///
  18. ///  nen Suchabläufe parallel laufen.                                       ///
  19. ///  Es sind maximal 10 Suchmuster auf der Befehlszeile angebbar.           ///
  20. ///  Nach jeweils einem Bildschirminhalt, wartet Finder auf einen Tasten-   ///
  21. ///  druck. Während dieser Zeit, laufen jedoch die Hintergrundprozesse,     ///
  22. ///  die die Platten durchsuchen weiter, sofern die Pipe noch nicht voll-   ///
  23. ///  ständig gefüllt ist.                                                   ///
  24. ///                                                                         ///
  25. //////////////////////////////////////////////////////////////////////////////}
  26.  
  27. {$I-,R-,S-,D-,F-,V-,B-,N-,L- }
  28.  
  29. PROGRAM Finder;
  30.  
  31. { Autor: Christian Philipps
  32.          Düsseldorfer Str. 316
  33.  
  34.          4130 Moers 1
  35.  
  36.  Stand:  Sep. 1989
  37. }
  38.  
  39. USES Dos, Crt, CpMulti, CpMisc, MtPipe;
  40.  
  41. TYPE  FileType       = (Directory, NonDirectory);
  42.       FMaskType      = String[12];
  43.       ErrorType      = (ErrCreateSem, ErrAssignPipe,
  44.                         ErrRemoveSem, ErrCreateTask,
  45.                         ErrRewrite,   ErrReset);
  46.       ParmType       = RECORD
  47.                          Ready     : Pointer;
  48.                          Path      : String;
  49.                          Mask      : FMaskType;
  50.                        END;
  51.       ParmPtr        = ^ParmType;
  52.  
  53. CONST FinderStackSize = 8000;
  54.       PipeSize        = 10000;
  55.       MaxFinders      = 10;
  56.  
  57. VAR   MainPipe       : TEXT;
  58.       DispSem        : Pointer;
  59.       FindSem        : Pointer;
  60.  
  61. {-----------------------------------------------------------------------------}
  62.  
  63. PROCEDURE SafeFindFirst(Path:String; Attr:Word; VAR S:SearchRec);
  64.  
  65. BEGIN {SafeFindFirst}
  66.   SemWait(FindSem);
  67.   FindFirst(Path,Attr,S);
  68.   SemSignal(FindSem);
  69. END;  {SafeFindFirst}
  70.  
  71. {-----------------------------------------------------------------------------}
  72.  
  73. PROCEDURE SafeFindNext(VAR S:SearchRec);
  74.  
  75. BEGIN {SafeFindNext}
  76.   SemWait(FindSem);
  77.   FindNext(S);
  78.   SemSignal(FindSem);
  79. END;  {SafeFindNext}
  80.  
  81. {-----------------------------------------------------------------------------}
  82.  
  83. PROCEDURE FinderError(Err:ErrorType);
  84.  
  85. BEGIN {FinderError}
  86.   Write(^G'Finder: ');
  87.   CASE Err OF
  88.     ErrCreateSem:  Writeln('Fehler bei CreateSem');
  89.     ErrRemoveSem:  Writeln('Fehler bei RemoveSem');
  90.     ErrCreateTask: Writeln('Fehler bei CreateTask');
  91.     ErrAssignPipe: Writeln('Fehler bei AssignPipe');
  92.     ErrRewrite:    Writeln('Fehler bei Rewrite Pipe');
  93.     ErrReset:      Writeln('Fehler bei Reset Pipe');
  94.   ELSE
  95.     Writeln('Unbekannter Fehler (',Byte(Err),')!');
  96.   END;
  97.   Halt(1);
  98. END;  {FinderError}
  99.  
  100. {-----------------------------------------------------------------------------}
  101.  
  102. PROCEDURE Display(Typ:FileType; FName:String; VAR Pipe:TEXT);
  103.  
  104. { Ausgabe von Statusmeldungen über eine Pipe.
  105.   Die Nachricht besteht aus 3 zusammengehörigen Teilen, wodurch die
  106.   gesamte Ausgabe zu einer "atomic action" wird. Durch die Semaphoren-
  107.   Operationen zu Beginn und am Ende der Prozedur wird sichergestellt,
  108.   daß stets alle 3 Teile einer Nachricht zusammenhängend hintereinander
  109.   ausgegeben werden.
  110. }
  111.  
  112. BEGIN {Display}
  113.   SemWait(DispSem);
  114.   IF Typ = Directory
  115.      THEN Write(Pipe,'D ')
  116.      ELSE Write(Pipe,'F ');
  117.   WriteLn(Pipe,GetPID,' ',Fname);
  118.   SemSignal(DispSem);
  119. END;  {Display}
  120.  
  121. {-----------------------------------------------------------------------------}
  122.  
  123. PROCEDURE ScanFiles(Path:String; FileMask:FMaskType; VAR Pipe:TEXT);
  124.  
  125. { Durchsuchen eines Verzeichnisses }
  126.  
  127. VAR  S : SearchRec;
  128.  
  129. BEGIN
  130.   SafeFindFirst(Path+FileMask,$27,S);
  131.   WHILE DosError=0 DO
  132.   BEGIN
  133.     Display(NonDirectory,Path+S.Name,Pipe);
  134.     SafeFindNext(S);
  135.   END;
  136. END;
  137.  
  138. {-----------------------------------------------------------------------------}
  139.  
  140. PROCEDURE ScanDirs(Path:String; FileMask:FMaskType; VAR Pipe:TEXT);
  141.  
  142. { Rekursives Durchsuchen eines Verzeichnisbaumes }
  143.  
  144. VAR  S : SearchRec;
  145.  
  146. BEGIN
  147.   SafeFindFirst(Path+'*.*',$10,S);
  148.   WHILE DosError=0 DO
  149.   BEGIN
  150.     IF (S.Name[1] <> '.') AND (S.Attr = $10)
  151.        THEN BEGIN
  152.               Display(Directory,Path+S.Name,Pipe);
  153.               ScanFiles(Path+S.Name+'\',FileMask,Pipe);
  154.               ScanDirs(Path+S.Name+'\',FileMask,Pipe);
  155.             END;
  156.     SafeFindNext(S);
  157.   END;
  158. END;
  159.  
  160. {-----------------------------------------------------------------------------}
  161.  
  162. {$F+}
  163. PROCEDURE FindTask(P:Pointer);
  164.  
  165. { Dies ist der Taskrumpf der Finder-Tasks.
  166.   Jede Task eröffnet einen eigenen Kommunikationskanal zur Pipe "Finder".
  167.   Alsdann durchsucht sie rekursiv die Platte anhand des angegebenen
  168.   Suchmusters. Die Statusmeldungen werden mittels der Prozedur "Display"
  169.   an das Hauptprogramm (via Pipe) weitergeleitet.
  170.  
  171.   Nach erfolgreichem Abschluß der Arbeit schließt die Task ihre Seite der
  172.   Pipe wieder und beendet sich. Haben sich alle Finder-Tasks, d. h. alle
  173.   schreibenden Prozesse beendet (und somit die Pipe geschlossen), wird
  174.   das Hauptprogramm, welches die Leseseite der Pipe bildet, einen
  175.   Zugriffsfehler gemeldet bekommen, sobald es versucht, eine weitere Nachricht
  176.   aus der vollständig entleerten Pipe zu lesen.
  177. }
  178.  
  179. VAR  Parms: ParmPtr absolute P;
  180.      Pipe : TEXT;
  181.      Path : String;
  182.      Mask : FMaskType;
  183.  
  184. BEGIN {FindTask}
  185.   IF Not AssignPipe(Pipe,'Finder',0,0,NoWait)
  186.      THEN FinderError(ErrAssignPipe);
  187.   Rewrite(Pipe);
  188.   IF IoResult <> 0
  189.      THEN FinderError(ErrRewrite);
  190.   Path := Parms^.Path;
  191.   Mask := Parms^.Mask;
  192.   SemSignal(Parms^.Ready);
  193.   ScanFiles(Path,Mask,Pipe);
  194.   ScanDirs(Path,Mask,Pipe);
  195.   Display(Directory,'--- Fertig! ---',Pipe);
  196.   Close(Pipe);
  197. END;  {FindTask}
  198. {$F-}
  199.  
  200. {-----------------------------------------------------------------------------}
  201.  
  202. FUNCTION StartFinder:Byte;
  203.  
  204. { Für jeden Befehlszeilenparameter wird ein separater Prozeß gestartet.
  205.   Die Prozedur FindTask bildet den Taskrumpf für ALLE diese Prozesse.
  206.   StartFinder erzeugt außerdem eine Semaphore, die für die Synchronisation
  207.   des Zugriffs auf die Prozedur "Display" erforderlich ist.
  208.   StartFinder liefert als Funktionswert die Nummer der ersten gestarteten
  209.   Task. Dieser Wert wird für die Berechnung der Ausgabepositionen inner-
  210.   halb von "ProcessOutput" benötigt.
  211. }
  212.  
  213. VAR  N     : Byte;
  214.      P     : Byte;
  215.      Parms : ParmType;
  216.      T     : TaskNoType;
  217.  
  218. BEGIN {StartFinder}
  219.   IF CreateSem(DispSem) <> Sem_OK
  220.      THEN FinderError(ErrCreateSem);
  221.  
  222.   IF CreateSem(FindSem) <> Sem_OK
  223.      THEN FinderError(ErrCreateSem);
  224.  
  225.   IF CreateSem(Parms.Ready) <> Sem_OK
  226.      THEN FinderError(ErrCreateSem);
  227.   FOR N := 1 TO Min(ParamCount,MaxFinders) DO
  228.   WITH Parms DO
  229.   BEGIN
  230.     Path := ParamStr(n);
  231.     P    := Byte(Path[0]);
  232.     WHILE (P > 0) AND (Path[P] <> '\') AND (Path[P] <> ':') DO
  233.       Dec(P);
  234.     IF P = 0
  235.        THEN BEGIN
  236.               Mask := Path;
  237.               Path := '\';
  238.             END
  239.        ELSE BEGIN
  240.               Mask := Copy(Path,P+1,255);
  241.               Delete(Path,P+1,255);
  242.               IF Path[P] = ':'
  243.                  THEN Path := Path+'\';
  244.             END;
  245.     SemClear(Ready);
  246.     T := CreateTask(FindTask,@Parms,Pri_User,FinderStackSize);
  247.     IF T < 0
  248.        THEN FinderError(ErrCreateTask);
  249.     IF N = 1                                    {melde Nummer der 1. Task}
  250.        THEN StartFinder := T;
  251.     SemWait(Ready);
  252.   END;
  253.   IF RemoveSem(Parms.Ready) <> Sem_OK
  254.      THEN FinderError(ErrRemoveSem);
  255. END;  {StartFinder}
  256.  
  257. {-----------------------------------------------------------------------------}
  258.  
  259. PROCEDURE ProcessOutput(BaseNo:TaskNoType; NoOfTasks:Byte);
  260.  
  261. { Diese Prozedur ließt die Nachrichten, die ihr über die Pipe zugeleitet
  262.   werden aus und zeigt sie am Bildschirm an.
  263.   Jede Nachricht besteht aus 3 Bestandteilen.
  264.   1. Ein Kennbuchstabe; Tpy der Nachricht (D)irectory (F)ile
  265.   2. Die Nummer der Task, die die Nachricht abgesandt hat
  266.   3. Ein Pfadname
  267.   Die einzelnen Bestandteile sind durch jeweils eine Leerstelle voneinander
  268.   getrennt. (siehe auch Prozdur "Display")
  269.  
  270.   In einer Schleife wird der gesamte Inhalt der Pipe gelesen, bis durch
  271.   einen Fehler beim Lesen des Kennbuchstabens angezeigt wird, daß die
  272.   Finder-Tasks alle bereits die Pipe auf ihrer Seite geschlossen haben, d. h.
  273.   keine Daten mehr liefern werden.
  274. }
  275.  
  276. VAR  N    : Byte;
  277.      BotL : Byte;
  278.      Typ  : Char;
  279.      Task : Byte;
  280.      Path : String;
  281.      Hits : Word;
  282.      Sep  : String[80];
  283.      C    : Char;
  284.      Ende : Boolean;
  285.  
  286. BEGIN {ProcessOutput}
  287.   Hits  := 0;
  288.   Ende  := False;
  289.  
  290.   ClrScr;
  291.   TextColor(0);
  292.   TextBackground(7);
  293.   GotoXY(1,1);
  294.   ClrEol;
  295.   GotoXY(17,1);
  296.   Write('>> Finder V1.00 (c) Ch. Philipps im April 1990<<');
  297.   TextColor(7);
  298.   TextBackground(0);
  299.  
  300.   BotL := 25-NoOfTasks-1;
  301.   FillChar(Sep,sizeof(Sep),'-');
  302.   Sep[0] := #80;
  303.   GotoXY(1,BotL+1);
  304.   Write(Sep);
  305.   Reset(MainPipe);
  306.   IF IoResult <> 0
  307.      THEN FinderError(ErrReset);
  308.   Read(MainPipe,Typ);
  309.   Read(MainPipe,Task);
  310.   ReadLn(MainPipe,Path);
  311.   Ende := IOResult <> 0;
  312.   WHILE NOT Ende DO
  313.   BEGIN
  314.     IF Typ = 'D'
  315.        THEN BEGIN
  316.               GotoXY(1,BotL+2+Task-BaseNo);
  317.               ClrEol;
  318.             END
  319.        ELSE BEGIN
  320.               Inc(Hits);
  321.               IF (Hits MOD BotL) = 0
  322.                  THEN BEGIN
  323.                         GotoXY(20,BotL+1);
  324.                         Write(' Weiter mit Return - Abbruch mit ESC! ');
  325.                         REPEAT
  326.                           WHILE NOT Keypressed DO
  327.                             Sleep(1);
  328.                           C := ReadKey;
  329.                         UNTIL C IN [#27,#13];
  330.                         IF C = #27
  331.                            THEN Halt(1);
  332.                         GotoXY(1,BotL+1);
  333.                         Write(Sep);
  334.                       END;
  335.               GotoXY(1,2);
  336.               DelLine;
  337.               GotoXY(1,BotL);
  338.               InsLine;
  339.             END;
  340.     Write(Task:2,': ',Copy(Path,1,75));
  341.     Read(MainPipe,Typ);
  342.     Ende := IOResult <> 0;
  343.     IF NOT Ende
  344.        THEN BEGIN
  345.               Read(MainPipe,Task);
  346.               ReadLn(MainPipe,Path);
  347.             END;
  348.     END;
  349.   Close(MainPipe);
  350.   GotoXY(20,BotL+1);
  351.   Write(' ',Hits,' Treffer - Weiter mit jeder Taste! ');
  352.   IF ReadKey = #0 THEN;
  353. END;  {ProcessOutput}
  354.  
  355. {-----------------------------------------------------------------------------}
  356.  
  357. BEGIN {Main}
  358.   IF ParamCount < 1
  359.      THEN BEGIN
  360.             Writeln('Finder V1.00 / Ch. Philipps / Sep. 1989');
  361.             Writeln('> Finder Suchmuster [...]');
  362.             Writeln;
  363.             Writeln('Finder durchsucht die Platte nach den angegebenen');
  364.             Writeln('Mustern. Enthält ein Suchmuster keine Pfad, so wird');
  365.             Writeln('die gesamte Platte durchsucht!');
  366.             Writeln('Maximal ',MaxFinders,' Suchmuster können auf der Befehlszeile');
  367.             Writeln('angegeben werden.');
  368.             Writeln;
  369.             Writeln('Beispiel: Finder C:*.sys D:*.sys');
  370.             Writeln('Funktion: Durchsuche die Platten C und D beginnend mit');
  371.             Writeln('          dem Root-Directory nach Dateien, deren Exten-');
  372.             Writeln('          sion .SYS lautet.');
  373.             Halt(1);
  374.           END;
  375.  
  376.   SpeedUp(3);
  377.   TimeSlice(1,5);
  378.   SetPri(Pri_User+1);
  379.   IF Not AssignPipe(MainPipe,'Finder',PipeSize,0,NoWait)
  380.      THEN FinderError(ErrAssignPipe);
  381.   ProcessOutput(StartFinder,Min(ParamCount,MaxFinders));
  382. END.  {Main}
  383.