home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / dtx9101 / utils / xdel / xdel.c next >
Encoding:
C/C++ Source or Header  |  1991-10-01  |  32.1 KB  |  967 lines

  1. /*********************************************************/
  2. /*                     XDEL.C                            */
  3. /*                   Version 1.21                        */
  4. /*      (C) 1991 Hubert Hopf & DMV-Verlag                */
  5. /*  Erweiterte DOS-Löschfunktionen äquivalent zu XCOPY   */                   
  6. /*********************************************************/
  7.  
  8.  
  9. #include <dir.h>
  10. #include <dos.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <conio.h>
  15. #include <ctype.h>
  16. #include <stdarg.h>
  17.  
  18. /* Definitionen */
  19.  
  20. #define M_REP           0x0002  /* Meldung in Report */
  21. #define M_PRT           0x0001  /* Meldung nach stdout */
  22.  
  23. /* Definitionen für Meldungen (Messages) */
  24.  
  25. #define MSG_DD          0       /* delete directory     */
  26. #define MSG_DF          1       /* delete file          */
  27. #define MSG_UD          2       /* up-directory         */
  28. #define MSG_SD          3       /* sub-directory        */
  29. #define MSG_DRO         4       /* direct. is read only */
  30. #define MSG_FRO         5       /* file is read only    */
  31. #define MSG_EUD         6       /* error chg. up-dir    */
  32. #define MSG_ESD         7       /* error chg. sub-dir   */
  33. #define MSG_FROND       8       /* rd. only-file not del*/
  34. #define MSG_FLM         9       /* files last message   */
  35. #define MSG_DLM         10      /* dir. last message    */
  36. #define MSG_FER         11      /* error open report    */
  37. #define MSG_NOD         12      /* not deleted          */
  38. #define MSG_NF          13      /* no files or dirs     */
  39. #define MSG_BRK         14      /* break with escape    */
  40. #define MSG_FNOF        15      /* filenames overflow   */
  41.  
  42. #define Error(text)     { printf("\n%s\n\n",text); exit(1); }
  43.  
  44.  
  45. /* Hilfetexte zu den verschiedenen Optionen */
  46.  
  47. /* Hilfe zur Option /h (Hilfe) */
  48. char *hhelp[] =
  49. {
  50.   "Die Option /hx gibt eine ausführliche Hilfe zu der "
  51.   "angegebenen Option aus.\n",
  52.   "Beispiel: XDEL /hs   gibt eine ausführliche Hilfe "
  53.   "zu der Option /s \n",
  54.   "                     (Unterverz. löschen) aus.\n",
  55.   "Es sind sonst keine Aktionen möglich, XDEL bricht "
  56.   "nach der Ausgabe der\n",
  57.   "Hilfe ab, es können aber mehrere /h-Optionen "
  58.   "hintereinander angegeben werden.\n",
  59.   "Beispiel: XDEL /hs /ha /hnm ... \n",
  60.   "                     XDEL gibt dann Hilfen zu allen "
  61.   "angegebenen Optionen.\n",
  62.   NULL
  63. };
  64.  
  65. /* Hilfe zur Option /a bzw. /na (Abfrage) */
  66. char *ahelp[] =
  67. {
  68.   "Die Optionen /a bzw. /na schalten die "
  69.   "Sicherheitsabfragen an oder aus\n",
  70.   "(in drei Stufen).\n",
  71.   "Diese Abfragen müssen mit 'j' oder 'J' für Ja bzw. 'y' "
  72.   "oder 'Y' für Yes\n",
  73.   "bestätigt werden, wenn die abgefragte Datei bzw. das "
  74.   "Verzeichnis gelöscht\n",
  75.   "werden soll, oder mit jedem anderen beliebigen Zeichen,"
  76.   " wenn die Datei oder\n",
  77.   "das Verzeichnis nicht gelöscht werden soll.\n",
  78.   "Standard: (ohne /a bzw. /na) Es wird vor der Löschung "
  79.   "von Verzeichnissen\n",
  80.   "          oder schreibgeschützten Dateien eine "
  81.   "Sicherheitsabfrage \n",
  82.   "          durchgeführt.\n",
  83.   "/a        Es wird bei jeder Datei oder bei jedem "
  84.   "Verzeichnis abgefragt.\n",
  85.   "/na       Es wird nicht abgefragt, auch nicht bei "
  86.   "Verzeichnissen.\n",
  87.   "          Ausnahme: schreibgeschützte Dateien werden "
  88.   "auch hier vor der\n",
  89.   "          Löschung abgefragt.\n",
  90.   NULL
  91. };
  92.  
  93. /* Hilfe zur Option /r (Report) */
  94. char *rhelp[] =
  95. {
  96.   "Die Option /r[File] startet einen Report (Protokoll) "
  97.   "über alle Lösch-\n",
  98.   "vorgänge und schreibt sie auf die Standardausgabe bzw. "
  99.   "wenn eine Datei\n",
  100.   "angegeben wurde in diese Datei. \n",
  101.   "Dieses Protokoll beinhaltet außer den normalen Angaben "
  102.   "und Meldungen\n",
  103.   "Meldungen über Name und Größe jeder gelöschten Datei.\n",
  104.   "Beispiel: XDEL /rLOESCH.REP *.*   schreibt alle "
  105.   "Informationen in die\n",
  106.   "                                  Datei LOESCH.REP.\n",
  107.   "Achtung !!!  Die Report-Datei darf nicht dem Suchmuster"
  108.   " entsprechen,\n",
  109.   "             da sie sonst auch gelöscht wird. Abhilfe: "
  110.   "Die Report-Datei\n",
  111.   "             über Pfad-Angabe in ein anderes "
  112.   "Verzeichnis legen.\n",
  113.   "             Beispiel: XDEL /rC:\\REPORTS\\LOESCH.REP "
  114.   "*.*\n",
  115.   NULL
  116. };
  117.  
  118. /* Hilfe zur Option /s (Subdirectories, Unterverz.) */
  119. char *shelp[] =
  120. {
  121.   "Die Option /s erlaubt es, Unterverzeichnisse eines "
  122.   "angegebenen \n",
  123.   "Verzeichnisses mit dem kompletten Inhalt zu löschen.\n",
  124.   "Achtung !! Die Wirkung ist wie ein DEL *.* in diesem "
  125.   "Verzeichnis\n",
  126.   "und anschließendem RMDIR des Verzeichnisses. \n",
  127.   "Je nach Option /(n)a wird vorher eine "
  128.   "Sicherheitsabfrage \n",
  129.   "durchgeführt (siehe dort).\n",
  130.   "Verweis auf Option /m: Löschen bestimmter Dateien in "
  131.   "allen \n",
  132.   "                       Unterverzeichnissen.\n",
  133.   NULL
  134. };
  135.  
  136. /* Hilfe zur Option /nm (No message, keine Meldungen) */
  137. char *nhelp[] =
  138. {
  139.   "Die Option /nm[x] erlaubt es, den Löschvorgang ohne "
  140.   "Meldungen und\n",
  141.   "Sicherheitsabfragen zu durchlaufen. Es kann dabei "
  142.   "eine Standard-\n",
  143.   "Antwort für die Sicherheitsabfragen vorgegeben "
  144.   "werden.\n",
  145.   "Wird keine Standard-Antwort vorgegeben, ist 'Nein' "
  146.   "der Standard,\n",
  147.   "d.h. es wird bei Abfragen nicht gelöscht.\n",
  148.   "Beispiel: XDEL /nm *.*  Löscht alle Dateien ohne "
  149.   "Meldungen,\n",
  150.   "                        Wird eine Sicherheitsabfrage "
  151.   "ausgegeben\n",
  152.   "                        (z. B. bei schreibgeschützten "
  153.   "Dateien), \n",
  154.   "                        so wird diese Datei nicht "
  155.   "gelöscht.\n",
  156.   "                        entspricht XDEL /nmn *.*\n",
  157.   "          XDEL /nmj *.* Wie oben, jedoch werden jetzt "
  158.   "die Dateien,\n",
  159.   "                        bei denen eine Abfrage erfolgt,"
  160.   " auch gelöscht.\n",
  161.   "          XDEL /s /nmj *.* Löscht alle Dateien und "
  162.   "Unterverzeichnisse\n",
  163.   "                        ohne (!!) vorherige Abfrage.\n",
  164.   "FATAL !!: XDEL /s /nmj C:\\*.*  Löscht die ganze "
  165.   "Festplatte ohne Abfrage.\n",
  166.   "Deshalb: Vorsicht beim Umgang mit dieser Option, nur "
  167.   "dann einsetzen, wenn\n",
  168.   "         es auch wirklich nötig ist, und man sicher "
  169.   "ist, daß nichts \n",
  170.   "         Falsches gelöscht wird.\n",
  171.   "Diese Option ist vor allem für den Betrieb in BATCH-"
  172.   "Dateien gedacht.\n",
  173.   NULL
  174. };
  175.  
  176. /* Hilfe zur Option /m (Matchcode, passende Files) */
  177. char *mhelp[] =
  178. {
  179.   "Die Option /m bewirkt, daß sämtliche Unterverzeichnisse"
  180.   " nach passenden\n",
  181.   "Dateien durchsucht und diese gelöscht werden. Dabei "
  182.   "werden gleichnamige\n",
  183.   "Unterverzeichnisse nicht gelöscht.\n",
  184.   "Beispiel: XDEL /m *.bak  Löscht alle Dateien, die als "
  185.   "Endung .BAK haben\n",
  186.   "                         im aktuellen und allen "
  187.   "Unterverzeichnissen.\n",
  188.   "Die Option /s (Unterverzeichnisse mit Inhalt löschen) "
  189.   "hat bei aktivierter\n",
  190.   "/m-Option keine Wirkung.\n",
  191.   NULL
  192. };
  193.  
  194. /* Hilfe zur Option /i (Info) */
  195. char *ihelp[] =
  196. {
  197.   "Die Option /i bewirkt die Ausgabe von ausführlicher "
  198.   "Information während\n",
  199.   "des Löschvorganges. Die Informationen werden auf den "
  200.   "Bildschirm ausgegeben.\n",
  201.   "Der Umfang der Informationen entspricht den mit /r in "
  202.   "eine Report-Datei\n",
  203.   "ausgegebene Information.\n",
  204.   NULL
  205. };
  206.  
  207. /* Hilfe zur Option /d ((not) delete) */
  208. char *dhelp[] =
  209. {
  210.   "Die Option /d bewirkt, daß die im Pfad angegebenen "
  211.   "Dateien gesucht\n",
  212.   "werden und (je nach Option /i) auch Meldungen "
  213.   "ausgegeben werden,\n",
  214.   "aber die Dateien werden nicht tatsächlich gelöscht.\n",
  215.   "Diese Option kann dazu dienen, alle Dateien oder "
  216.   "Verzeichnisse, die \n",
  217.   "auf das angegebene Suchmuster im Pfad passen würden, "
  218.   "zu suchen.\n",
  219.   "Die Wirkung ist ähnlich einem FIND-Befehl.\n",
  220.   NULL
  221. };
  222.  
  223. /* Hilfe zur Option /e (Exclude, Ausschließlich) */
  224. char *ehelp[] =
  225. {
  226.   "Die Option /e bewirkt, daß alle Dateien, die nach "
  227.   "dieser Option aufgeführt\n",
  228.   "sind, vom Löschvorgang ausgeschlossen sind. \n",
  229.   "Beispiel: XDEL prog.* /e *.exe *.com Löscht im "
  230.   "aktuellen Verzeichnis alle\n",
  231.   "                                     Dateien, die "
  232.   "mit PROG beginnen, außer\n",
  233.   "                                     PROG.COM und "
  234.   "PROG.EXE.\n",
  235.   "          XDEL /e *.exe *.com        Löscht im "
  236.   "aktuellen Verzeichnis alle\n",
  237.   "                                     Dateien, außer "
  238.   "COM- oder EXE-Dateien.\n",
  239.   "Beim Aufruf von XDEL ist die Reihenfolge der "
  240.   "angegebenen Dateien zu\n",
  241.   "beachten, da alle vor /e angegebenen Dateien gelöscht "
  242.   "und alle nach /e \n",
  243.   "angegebenen Dateien vom Löschvorgang ausgeschlossen "
  244.   "werden. \n",
  245.   "Wird die Angabe der Dateien vor /e weggelassen, so "
  246.   "werden alle (*.*) Dateien\n",
  247.   "angenommen (siehe zweites Beispiel oben).\n",
  248.   "Die Angabe der Exclude-Dateien sollte ohne Pfadangabe "
  249.   "erfolgen, da sonst kein \n",
  250.   "korrekter Vergleich erfolgen kann.\n",
  251.   NULL
  252. };
  253.  
  254. /* Meldungen, die mit mess() aufgerufen werden */
  255.  
  256. char *msg[] =
  257. {
  258.   "Verzeichnis %-15s gelöscht\n",
  259.   "Datei       %-15s mit %8ld Bytes gelöscht\n",
  260.   "Pfad:       ..   <---\n",
  261.   "Pfad:  ---> %-15s\n",
  262.   "Verzeichnis %-15s ist schreibgeschützt !\n",
  263.   "Datei       %-15s war schreibgeschützt !\n",
  264.   "Fehler beim Wechsel in Vaterverzeichnis !! \n"
  265.   "Abbruch !!!\n",
  266.   "Fehler beim Wechsel in Verzeichnis %s !! \n"
  267.   "Abbruch !!!\n",
  268.   "Datei       %-15s ist schreibgeschützt und "
  269.   "wurde nicht gelöscht !\n",
  270.   "%d Dateien mit insgesamt %ld Bytes gelöscht !\n",
  271.   "%d Verzeichnisse gelöscht !\n",
  272.   "Konnte Report-Datei %s nicht öffnen, \n"
  273.   "Report-Ausgabe erfolgt auf die Standard-Ausgabe !\n",
  274.   "Angezeigte Dateien und Verzeichnisse wurden nicht (!) "
  275.   "gelöscht\n",
  276.   "Keine Datei oder Verzeichnis gefunden !\n",
  277.   "Löschvorgang wurde durch ESC abgebrochen !\n",
  278.   "Zu viele Filenamen als Parameter angegeben (max. 16)!\n"
  279. };
  280.  
  281. FILE *output = stdout;  /* File-Pointer für Report-File  */
  282. int argcnt = 0, eargcnt = 0, subdirs = 0, subcount = 0;
  283. int message = 1, reports = 0, help = 0, matchdel = 0;
  284. int exclude = 0, nodel = 0, info = 0, ask = 1, endxdel = 0;
  285. int anzf = 0, anzd = 0;
  286. int answer = 'n';     /* Standard-Antwort bei Abfragen */
  287. long bytes = 0L;
  288.  
  289. /* char-Pointer (Strings) für Filenamen und Pfade */
  290. char *name, repfile[MAXPATH];
  291. char drive[MAXDRIVE], dir[MAXDIR], files[MAXFILE];
  292. char ext[MAXEXT], fullpath[MAXPATH], oldpath[MAXPATH];
  293. char aktpath[MAXPATH], *argums[16], *eargums[16];
  294.  
  295. int  splitflags;        /* Flags für fnsplit()           */
  296.  
  297. /* Attribute der zu suchenden Files und Directories      */
  298. int  fattrib = FA_RDONLY | FA_HIDDEN | FA_DIREC;
  299.  
  300.  
  301. /*********************************************************/
  302. /*                                                       */
  303. /*  Funktion: void PrtHlp(char *htxt[])                  */
  304. /*                                                       */
  305. /*  Beschr. : Diese Funktion gibt die Hilfetexte für die */
  306. /*            verschiedenen Optionen aus. Nach der Aus-  */
  307. /*            gabe wartet die Fkt. auf einen Tastendruck.*/
  308. /*                                                       */
  309. /*  Übergabe: char *htxt[]                               */
  310. /*            Array mit char-Pointern, die die Hilfetexte*/
  311. /*            enthalten. Das Ende des Arrays wird durch  */
  312. /*            einen NULL-Pointer gekennzeichnet.         */
  313. /*                                                       */
  314. /*********************************************************/
  315.  
  316. void PrtHlp(char *htxt[])
  317. {
  318.   int i;
  319.   printf("\n");
  320.   for (i = 0; htxt[i] != NULL; i ++) printf(htxt[i]);
  321.   printf("\nWeiter mit beliebiger Taste\n\n");
  322.   getch();
  323. }
  324.  
  325.  
  326. /*********************************************************/
  327. /*                                                       */
  328. /*  Funktion: void mess(int mode, char *msg, ...)        */
  329. /*                                                       */
  330. /*  Beschr. : Diese Funktion gibt eine Meldung auf den   */
  331. /*            Bildschirm oder in eine Datei (Report) aus.*/
  332. /*            Die Meldungen werden i.d.R. mit Hilfe der  */
  333. /*            msg-Texte übergeben.                       */
  334. /*                                                       */
  335. /*  Übergabe: int mode                                   */
  336. /*            Gibt an, wohin die Meldung ausgegeben      */
  337. /*            werden soll.                               */
  338. /*            mode = M_REP Ausgabe in Report             */
  339. /*            mode = M_PRT Ausgabe in stdout             */
  340. /*            Die Modi können auch OR-verknüpft werden.  */
  341. /*                                                       */
  342. /*            char *msg                                  */
  343. /*            Auszugebende Nachricht mit Formatangaben   */
  344. /*            wie bei printf().                          */
  345. /*                                                       */
  346. /*            ...                                        */
  347. /*            Variable Paramterliste wie bei printf(), um*/
  348. /*            für Formatangaben in msg Werte zu liefern. */
  349. /*                                                       */
  350. /*********************************************************/
  351.  
  352. void mess(int mode, char *msg,...)
  353. {
  354.   va_list argptr;
  355.   char buffer[128];
  356.  
  357.   /* Variable Parameterliste auswerten */
  358.   va_start(argptr,msg);
  359.   vsprintf(buffer,msg,argptr);
  360.   va_end(argptr);
  361.  
  362.   /* Nachricht auf Bildschirm oder in Report ausgeben */
  363.   if ((message && (mode & M_PRT)) || info) printf(buffer);
  364.   if (reports && (mode & M_REP)) fprintf(output,buffer);
  365. }
  366.  
  367.  
  368. /*********************************************************/
  369. /*                                                       */
  370. /*  Funktion: int delfiles(struct ffblk *fblk)           */
  371. /*                                                       */
  372. /*  Beschr. : Diese Funktion löscht Files oder Direct.   */
  373. /*            mit Hilfe der DOS-Funktion 3Ah (Direct.)   */
  374. /*            bzw. 41h (Files). Nach dem Löschvorgang    */
  375. /*            wird die Anzahl der gelöschten Files bzw.  */
  376. /*            Directories hochgezählt und die gelöschten */
  377. /*            Bytes addiert.                             */
  378. /*                                                       */
  379. /*  Übergabe: struct ffblk *fblk                         */
  380. /*            Struktur von DOS, die von den DOS-Funktion */
  381. /*            findfirst() und findnext() geliefert wird. */
  382. /*            Diese Struktur beinhaltet auch den File-   */
  383. /*            namen und die Fileattribute.               */
  384. /*                                                       */
  385. /*********************************************************/
  386.  
  387. int delfiles(struct ffblk *fblk)
  388. {
  389.   union  REGS  r;
  390.   struct SREGS s;
  391.  
  392.   /* Löschen eingeschaltet (nicht aktive Option /d) */
  393.   /* dann löschen.                                  */
  394.   if (nodel == 0)
  395.   {
  396.     if (fblk->ff_attrib & FA_DIREC) r.h.ah = 0x3A;
  397.     else                            r.h.ah = 0x41;
  398.     s.ds   = _DS;  /* direkt Datensegment zuweisen    */
  399.     r.x.dx = FP_OFF(&fblk->ff_name);
  400.     intdosx(&r,&r,&s);
  401.     if (r.x.cflag) return(r.x.ax);  /* Fehler ? */
  402.   }
  403.   /* Anzahl erhöhen und Meldung ausgeben */
  404.   if (fblk->ff_attrib & FA_DIREC)
  405.   {
  406.     anzd ++;
  407.     mess(M_REP,msg[MSG_DD],fblk->ff_name);
  408.   }
  409.   else
  410.   {
  411.     anzf ++;
  412.     bytes += (long)fblk->ff_fsize;
  413.     mess(M_REP,msg[MSG_DF],fblk->ff_name,fblk->ff_fsize);
  414.   }
  415.   return(0);
  416. }
  417.  
  418. /*********************************************************/
  419. /*                                                       */
  420. /*  Funktion: void xdelhelp(void)                        */
  421. /*                                                       */
  422. /*  Beschr. : Gibt eine Kurzinformation über den         */
  423. /*            Aufruf und die Parameter von XDEL.         */
  424. /*                                                       */
  425. /*********************************************************/
  426.  
  427. void xdelhelp(void)
  428. {
  429.   printf("\nAufruf: XDEL [/hx /a /na /nmx /s /m /i /d /r["
  430.      "File]] File [File ...] /e Files ...\n");
  431.   printf("          /hxx = Ausführliche Hilfe zu der ansc"
  432.      "hließend angegebenen Option\n");
  433.   printf("          /a   = Mit Abfrage (Dateien und Verze"
  434.      "ichnisse)\n");
  435.   printf("          /na  = keine Abfrage \n");
  436.   printf("                 Standard: Abfrage nur bei Verz"
  437.      "eichnissen\n");
  438.   printf("                           und schreibgeschützt"
  439.      "en Dateien\n");
  440.   printf("          /nmx = Keine Nachrichten\n");
  441.   printf("             x = Standard-Antwort bei Sicherhei"
  442.      "tsabfragen\n");
  443.   printf("             x = 'j' Bei Abfrage löschen\n");
  444.   printf("             x = 'n' Bei Abfr. nicht löschen\n");
  445.   printf("          /s   = Auch Unterverzeichnisse lösche"
  446.      "n (mit komplettem Inhalt)\n");
  447.   printf("          /m   = bestimmte Dateien im aktuellen"
  448.      " und allen Unterverzeichnissen\n");
  449.   printf("                 löschen. Verzeichnisse werden "
  450.      "nicht gelöscht !\n");
  451.   printf("          /i   = Voll-Info nach Beendigung\n");
  452.   printf("          /e   = Es werden alle Dateien außer d"
  453.      "ie angegebenen gelöscht\n");
  454.   printf("          /d   = nicht löschen, nur anzeigen ! "
  455.      "\n");
  456.   printf("          /r[file] = Report auf Bildschirm oder"
  457.      " in Datei\n");
  458.   printf("      Filename auch mit Wildcards (Jokerzeichen"
  459.      ") möglich\n");
  460.   printf("      Abbruch des Löschvorganges mit ESC möglic"
  461.      "h\n\n");
  462.   exit(1);
  463. }
  464.  
  465. /*********************************************************/
  466. /*                                                       */
  467. /*  Funktion: int setattribute(char *name)               */
  468. /*                                                       */
  469. /*  Beschr. : Löscht das Read-Only-Attribut des übergeb- */
  470. /*            enen Files. DOS-Fkt INT 21h, Fkt 43h       */
  471. /*                                                       */
  472. /*  Übergabe: char *name                                 */
  473. /*        Name des Files, dessen RO-Attribut             */
  474. /*        gelöscht werden soll.                          */
  475. /*                                                       */
  476. /*  Rückgabe: Fehlercode des Interrupt-Aufrufes          */
  477. /*                                                       */
  478. /*********************************************************/
  479.  
  480. int setattribute(char *name)
  481. {
  482.   union  REGS  r;
  483.   struct SREGS s;
  484.   char  *pfad;
  485.   int    ret;
  486.  
  487.   pfad = (char *)malloc(128);
  488.  
  489.   /* Zuerst kompletten Filenamen mit Pfadangabe */
  490.   strcpy(pfad," :\\");
  491.   pfad[0] = 'A' + getdisk();
  492.   getcurdir(0,pfad+3);
  493.   strcat(pfad,"\\");
  494.   strcat(pfad,name);
  495.  
  496.   r.x.ax = 0x4300;
  497.   s.ds   = _DS;
  498.   r.x.dx = FP_OFF(pfad);
  499.   intdosx(&r,&r,&s);    /* Attribute holen */
  500.   ret = r.x.ax;
  501.   if (r.x.cflag)        /* Fehler ? */
  502.   {
  503.     free(pfad);
  504.     return(ret);        /* Dann beenden */
  505.   }
  506.   r.x.cx &= 0xFFFE;     /* sonst RO-Attribut löschen */
  507.   r.x.ax =  0x4301;
  508.   intdosx(&r,&r,&s);
  509.   if (r.x.cflag) ret = r.x.ax;
  510.   else           ret = 0;
  511.   free(pfad);
  512.   return(ret);
  513. }
  514.  
  515. /*********************************************************/
  516. /*                                                       */
  517. /*  Funktion: int askdel(char *name, int mode)           */
  518. /*                                                       */
  519. /*  Beschr. : Fragt nach, ob ein File oder Directory     */
  520. /*            gelöscht werden soll.                      */
  521. /*                                                       */
  522. /*  Übergabe: char *name                                 */
  523. /*            Name des Files oder Directories, das       */
  524. /*            gelöscht werden soll.                      */
  525. /*                                                       */
  526. /*            int mode                                   */
  527. /*            mode = 0 Es handelt sich um ein Directory  */
  528. /*            mode = 1 Es handelt sich um ein File       */
  529. /*                                                       */
  530. /*  Rückgabe: 0  Abfrage wurde mit Nein beantwortet      */
  531. /*            1  Abfrage wurde mit Ja beantwortet        */
  532. /*                                                       */
  533. /*********************************************************/
  534.  
  535. int askdel(char *name, int mode)
  536. {
  537.   int cc;
  538.  
  539.   if (message == 1) /* Es soll gefragt werden */
  540.   {
  541.     if (ask == 2 || (ask == 1 && mode == 0))
  542.     {
  543.       if (mode) printf("Datei %s löschen (J/N) ",name);
  544.       else printf("Verzeichnis %s löschen (J/N) ",name);
  545.  
  546.       cc = tolower(getch());
  547.       printf("%c\n",cc);
  548.       if (cc == 'j' || cc == 'y') return(1);
  549.       else return(0);
  550.     }
  551.   }
  552.   /* Es soll nicht gefragt werden: Gibt Wahr zurück,    */
  553.   /* wenn die Standard-Antwort (aus Option /nm) Ja ist. */
  554.   else return(answer == 'j');
  555.  
  556.   return(1); /* wird nie erreicht, für Compilerwarnung */
  557. }
  558.  
  559. /*********************************************************/
  560. /*                                                       */
  561. /*  Funktion: int checkexclude(char *name)               */
  562. /*                                                       */
  563. /*  Beschr. : Prüft, ob das angegebene File vom Lösch-   */
  564. /*            vorgang ausgeschlossen sein soll (Opt. /e).*/
  565. /*            Der Name sollte ohne Pfadangabe sein, da   */
  566. /*            jedes Directory überprüft wird.            */
  567. /*                                                       */
  568. /*  Übergabe: char *name                                 */
  569. /*            Filename, der überprüft werden soll.       */
  570. /*                                                       */
  571. /*  Rückgabe: 1 wenn File ausgeschl. wird, sonst 0.      */
  572. /*                                                       */
  573. /*********************************************************/
  574.  
  575. int checkexclude(char *name)
  576. {
  577.   int    i;
  578.   int    ret;
  579.   struct ffblk eblk;
  580.  
  581.   if (exclude) /* Option eingeschaltet ? */
  582.   {
  583.     strupr(name);
  584.  
  585.     for (i = 0; i < eargcnt; i ++)
  586.     {
  587.       ret = findfirst(eargums[i],&eblk,fattrib);
  588.       while (ret == 0) /* Exclude-File gefunden ? */
  589.       {
  590.     /* stimmt überein ? */
  591.     if (strcmp(eblk.ff_name,name) == 0) return(1);
  592.     ret = findnext(&eblk); /* Weitersuchen */
  593.       }
  594.     }
  595.   }
  596.   return(0); /* hat nicht übereingestimmt */
  597. }
  598.  
  599. /*********************************************************/
  600. /*                                                       */
  601. /*  Funktion: int delfunkt(char *name)                   */
  602. /*                                                       */
  603. /*  Beschr. : Löscht alle Dateien und evtl. Verzeichnisse*/
  604. /*            die auf name passen.                       */
  605. /*                                                       */
  606. /*  Übergabe: char *name                                 */
  607. /*            File- oder Directoryname (auch Wildcards), */
  608. /*            der gelöscht werden soll.                  */
  609. /*                                                       */
  610. /*********************************************************/
  611.  
  612. int delfunkt(char *name)
  613. {
  614.   int    ret = 0;
  615.   int    cc;
  616.   struct ffblk fblk;
  617.  
  618.   ret = findfirst(name,&fblk,fattrib);
  619.   if (ret == 0)
  620.   {
  621.     do
  622.     {
  623.       if (kbhit())
  624.     if (getch() == 27) { endxdel = 1; break; }
  625.       if (ret != 0)
  626.       {
  627.     if (chdir("..") == 0)
  628.     {
  629.       mess(M_REP,msg[MSG_UD]);
  630.       subcount --;
  631.       break;
  632.     }
  633.     else
  634.     {
  635.       mess(M_REP,msg[MSG_EUD]);
  636.       Error("Fehler beim Wechsel in Vaterverzeichnis ! \n");
  637.     }
  638.       }
  639.       else
  640.       {
  641.     if ((fblk.ff_attrib & FA_DIREC) && subdirs &&
  642.          (strncmp(fblk.ff_name,".",1) != 0))
  643.     {
  644.       if ((fblk.ff_attrib & FA_RDONLY) != 0)
  645.         mess(M_REP,msg[MSG_DRO],fblk.ff_name);
  646.       else
  647.       {
  648.         if (askdel(fblk.ff_name,0))
  649.         {
  650.           if (chdir(fblk.ff_name) == 0)
  651.           {
  652.         mess(M_REP,msg[MSG_SD],fblk.ff_name);
  653.         subcount ++;
  654.         delfunkt("*.*");
  655.         if (endxdel) break;
  656.         delfiles(&fblk);
  657.           }
  658.           else
  659.           {
  660.         mess(M_REP,msg[MSG_ESD],fblk.ff_name);
  661.         Error("Fehler beim Wechsel in nächstes Verzeichnis !");
  662.           }
  663.         }
  664.       }
  665.     }
  666.     else
  667.     {
  668.       if ((fblk.ff_attrib & FA_DIREC) == 0 &&
  669.           (!checkexclude(fblk.ff_name)))
  670.       {
  671.         if ((fblk.ff_attrib & FA_RDONLY) != 0)
  672.         {
  673.           if (message)
  674.           {
  675.         printf("Datei %s ist schreibgeschützt ! "
  676.                "  Trotzdem löschen (J/N) ? ",
  677.             fblk.ff_name);
  678.         printf("%c\n",cc = tolower(getch()));
  679.           }
  680.           else cc = answer;
  681.           if (cc == 'j' || cc == 'y')
  682.           {
  683.         setattribute(fblk.ff_name);
  684.         if (delfiles(&fblk) == 0)
  685.           mess(M_REP,msg[MSG_FRO],fblk.ff_name);
  686.           }
  687.           else
  688.         mess(M_REP,msg[MSG_FROND],fblk.ff_name);
  689.         }
  690.         else
  691.           if (askdel(fblk.ff_name,1)) delfiles(&fblk);
  692.       }
  693.     }
  694.       }
  695.     }
  696.     while (((ret = findnext(&fblk)) == 0 || (subcount && subdirs)) &&
  697.         !endxdel);
  698.   }
  699.   else
  700.     if (!matchdel) mess(M_REP | M_PRT,msg[MSG_NF]);
  701.   return (0);
  702. }
  703.  
  704. /*********************************************************/
  705. /*                                                       */
  706. /*  Funktion: int delmatches(char *name)                 */
  707. /*                                                       */
  708. /*  Beschr. : Löscht alle Files, die auf name passen.    */
  709. /*            Löscht auch alle passenden Files in Unter- */
  710. /*            verzeichnissen, aber nicht d. Verz. selbst.*/
  711. /*                                                       */
  712. /*  Übergabe: char *name                                 */
  713. /*            Filename (auch Wildcards) der gelöscht     */
  714. /*            werden soll.                               */
  715. /*                                                       */
  716. /*********************************************************/
  717.  
  718. int delmatches(char *name)
  719. {
  720.   int    ret = 0;
  721.   struct ffblk mblk;
  722.  
  723.   subdirs = 0; /* In delfunkt() keine Unterverz. suchen */
  724.  
  725.   delfunkt(name); /* Zuerst alle passenden Files löschen */
  726.  
  727.   /* dann alle Unterverzeichnisse durchsuchen */
  728.   ret = findfirst("*.*",&mblk,FA_DIREC);
  729.   do
  730.   {
  731.     if (ret != 0)
  732.     {
  733.       if (!subcount) break;
  734.       if (chdir("..") == 0)
  735.       {
  736.     mess(M_REP,msg[MSG_UD]);
  737.     subcount --;
  738.     break;
  739.       }
  740.       else
  741.       {
  742.     mess(M_REP,msg[MSG_EUD]);
  743.     Error("Fehler beim Wechsel in Vaterverzeichnis ! \n");
  744.       }
  745.     }
  746.     else
  747.     {
  748.       if ((mblk.ff_attrib & FA_DIREC) && /* Directory ? */
  749.       (strncmp(mblk.ff_name,".",1) != 0))
  750.       {
  751.     if (chdir(mblk.ff_name) == 0)  /* dann wechseln */
  752.     {
  753.       mess(M_REP,msg[MSG_SD],mblk.ff_name);
  754.       subcount ++;
  755.       delmatches(name);
  756.       if (endxdel) break;
  757.     }
  758.     else
  759.     {
  760.       mess(M_REP,msg[MSG_ESD],mblk.ff_name);
  761.       Error("Fehler beim Wechsel in "\
  762.         "nächstes Verzeichnis !");
  763.     }
  764.       }
  765.     }
  766.   }
  767.   while ((ret = findnext(&mblk)) == 0 || subcount);
  768.   return(0);
  769. }
  770.  
  771. /*********************************************************/
  772. /*                                                       */
  773. /*  Funktion: int main(int argc, char *argv[])           */
  774. /*                                                       */
  775. /*  Beschr. : Hauptfunktion, liest Parameter ein und     */
  776. /*            ruft je nach Option /m delfunkt() oder     */
  777. /*            delmatches() auf. Gibt abschließende       */
  778. /*            Meldungen aus.                             */
  779. /*                                                       */
  780. /*  Übergabe: int argc, char *argv[]                     */
  781. /*            Anzahl und Text der übergebenen Parameter  */
  782. /*            Optionen und Filenamen                     */
  783. /*                                                       */
  784. /*  Rückgabe: 0 wenn erfolgreich                         */
  785. /*            ESC (27) bei Abbruch mit ESC               */
  786. /*                                                       */
  787. /*********************************************************/
  788.  
  789. int main(int argc, char *argv[])
  790. {
  791.   int i;
  792.   char hc;
  793.   name = NULL;
  794.  
  795.   printf("XDEL V. 1.21 (C) 1991 H. Hopf & DMV-Verlag\n");
  796.   if (argc < 2) xdelhelp(); /* keine Parameter */
  797.   
  798.  
  799.   for (i = 1; i < argc; i ++) /* Param. einlesen */
  800.   {
  801.     if (strncmp(argv[i],"/",1) == 0) /* Par. od. File */
  802.     {
  803.       strlwr(argv[i]);
  804.       if (strncmp(argv[i],"/nm",3) == 0)
  805.       {
  806.     message = 0;
  807.     if (strlen(argv[i]) > 3)
  808.     {
  809.       answer = argv[i][3]; /* Antwort für /nm setzen */
  810.       if (answer != 'j' && answer != 'y') answer = 'n';
  811.     }
  812.       }
  813.       if (strncmp(argv[i],"/s",2)  == 0) subdirs = 1;
  814.       if (strncmp(argv[i],"/m",2)  == 0) matchdel = 1;
  815.       if (strncmp(argv[i],"/i",2)  == 0) info = 1;
  816.       if (strncmp(argv[i],"/a",2)  == 0) ask = 2;
  817.       if (strncmp(argv[i],"/na",3) == 0) ask = 0;
  818.       if (strncmp(argv[i],"/d",2)  == 0) nodel = 1;
  819.       if (strncmp(argv[i],"/e",2)  == 0) exclude = 1;
  820.       if ((strncmp(argv[i],"/h",2) == 0) ||
  821.       (strncmp(argv[i],"/?",2) == 0))
  822.       {
  823.     help = 1; hc = 'h'; /* Hilfe-Option gesetzt */
  824.     if (strlen(argv[i])>2)
  825.     {
  826.       if (strchr("samiedrn",argv[i][2]) != NULL)
  827.         hc = argv[i][2];
  828.       if (argv[i][2] == 'n')
  829.         if (strlen(argv[i]) > 3 && argv[i][3] == 'a')
  830.           hc = 'a';
  831.     }
  832.     switch (hc) /* entsprechende Hilfe aufrufen */
  833.     {
  834.       case 'a' : PrtHlp(ahelp); break;
  835.       case 's' : PrtHlp(shelp); break;
  836.       case 'm' : PrtHlp(mhelp); break;
  837.       case 'i' : PrtHlp(ihelp); break;
  838.       case 'e' : PrtHlp(ehelp); break;
  839.       case 'd' : PrtHlp(dhelp); break;
  840.       case 'r' : PrtHlp(rhelp); break;
  841.       case 'n' : PrtHlp(nhelp); break;
  842.       case 'h' : PrtHlp(hhelp); break;
  843.     }
  844.       }
  845.       if (strncmp(argv[i],"/r",2) == 0) /* Report in File*/
  846.       {
  847.     reports = 1;
  848.     if (strlen(argv[i]) > 2)
  849.     {
  850.       strcpy(repfile,&argv[i][2]);
  851.       if ((output = fopen(repfile,"w")) == NULL)
  852.       {
  853.         output = stdout; /* in File ging nicht, ->   */
  854.         mess(M_PRT,msg[MSG_FER]); /* Rep. auf stdout */
  855.       }
  856.     }
  857.       }
  858.     }
  859.     else
  860.     {
  861.       if (exclude) /* Auszuschließende Files */
  862.       {
  863.     if (eargcnt < 16)
  864.     {
  865.       if ((eargums[eargcnt] =
  866.           (char *)malloc(strlen(argv[i])+2)) != NULL)
  867.         strcpy(eargums[eargcnt++],argv[i]);
  868.       else Error("Kein Speicherplatz mehr !");
  869.     }
  870.     else
  871.     {
  872.       mess(M_REP | M_PRT,msg[MSG_FNOF]); exit(1);
  873.     }
  874.       }
  875.       else /* zu löschende Files */
  876.       {
  877.     if (argcnt < 16)
  878.     {
  879.       if ((argums[argcnt] =
  880.           (char *)malloc(strlen(argv[i])+2)) != NULL)
  881.         strcpy(argums[argcnt++],argv[i]);
  882.       else Error("Kein Speicherplatz mehr !");
  883.     }
  884.     else
  885.     {
  886.       mess(M_REP | M_PRT,msg[MSG_FNOF]); exit(1);
  887.     }
  888.       }
  889.     }
  890.   }
  891.   if (help) /* Nach Hilfen Löschen abbrechen */
  892.     Error("Hilfen wurden ausgegeben, " \
  893.       "kein Löschvorgang gestartet !");
  894.  
  895.   if (argcnt == 0 && eargcnt > 0)
  896.   {
  897.     argums[argcnt] = (char *)malloc(5);
  898.     strcpy(argums[argcnt++],"*.*");
  899.   }
  900.   getcwd(oldpath,MAXPATH); /* alten Pfad merken */
  901.  
  902.   for (i = 0; i < argcnt; i ++)
  903.   {
  904.     if ((name=(char *)malloc(strlen(argums[i])+2)) != NULL)
  905.       strcpy(name,argums[i]);
  906.     else Error("Kein Speicherplatz mehr !");
  907.     if (name == NULL)
  908.       Error("Kein Dateiname oder Verzeichnis angegeben !");
  909.  
  910.     splitflags = fnsplit(name,drive,dir,files,ext);
  911.     if (splitflags & DRIVE) strcpy(fullpath,drive);
  912.     else strncpy(fullpath,oldpath,2);
  913.     fullpath[2] = '\0'; strcpy(aktpath,"\\");
  914.     getcurdir(toupper(fullpath[0]) - '@',aktpath+1);
  915.     if (!(splitflags & DIRECTORY)) strcat(fullpath,aktpath);
  916.     else
  917.     {
  918.       if (dir[0] != '\\')
  919.       {
  920.     strcat(fullpath,aktpath);
  921.     strcat(fullpath,"\\");
  922.     strcat(fullpath,dir);
  923.       }
  924.       else strcat(fullpath,&dir[1]);
  925.     }
  926.     if ((fullpath[strlen(fullpath)-1] == '\\') &&
  927.     (strlen(fullpath) > 3))
  928.       fullpath[strlen(fullpath)-1] = '\0';
  929.  
  930.     if (chdir(fullpath) != 0 ) /* Pfad wechseln */
  931.     {
  932.       if (anzf > 0)
  933.     mess(M_REP | M_PRT,msg[MSG_FLM],anzf,bytes);
  934.       if (subdirs && anzd > 0)
  935.     mess(M_REP | M_PRT,msg[MSG_DLM],anzd);
  936.       if (nodel && (anzd > 0 || anzf > 0))
  937.     mess(M_REP | M_PRT, msg[MSG_NOD]);
  938.       Error("Konnte angegebenen Pfad nicht finden");
  939.     }
  940.     strcpy(name,files);
  941.     strcat(name,ext);
  942.     setdisk(toupper(fullpath[0])-'A');
  943.  
  944.     /* Löschfunktion aufrufen */
  945.     if (matchdel)
  946.     {
  947.       delmatches(name);
  948.       if (anzf == 0) mess(M_REP | M_PRT,msg[MSG_NF]);
  949.     }
  950.     else delfunkt(name);
  951.  
  952.     chdir(aktpath);
  953.     chdir(oldpath);
  954.     setdisk(toupper(oldpath[0])-'A');
  955.     free(name);
  956.     if (endxdel) break;
  957.   }
  958.   /* Abschlußmeldungen ausgeben */
  959.   if (endxdel) mess(M_PRT,msg[MSG_BRK]);
  960.   mess(M_REP | M_PRT,msg[MSG_FLM],anzf,bytes);
  961.   if (subdirs) mess(M_REP | M_PRT,msg[MSG_DLM],anzd);
  962.   if (nodel == 1) mess(M_REP | M_PRT, msg[MSG_NOD]);
  963.   if (output != stdout) fclose(output);
  964.   if (endxdel) return(27);
  965.   return(0);
  966. }
  967.