home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / oct93 / cli_util / dirs.lha / Dirs / English / dirs.c < prev    next >
C/C++ Source or Header  |  1993-08-23  |  16KB  |  658 lines

  1. // dirs written by Harald Pehl
  2. // Last change 28-Aug-93, 18:35:16
  3. // Version 1.00
  4. // compiled with MaxonC++
  5.  
  6.  
  7. // Includes
  8. #include <pragma/exec_lib.h>
  9. #include <pragma/dos_lib.h>
  10. #include <dos/dosextens.h>
  11. #include <dos/datetime.h>
  12. #include <exec/memory.h>
  13. #include <dos/dos.h>
  14. #include <stream.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <ctype.h>
  18. #include <stdio.h>
  19.  
  20.  
  21. // Functions
  22. void close_all (const char *, const int);
  23. char *itoa (int);
  24. void strrfil (char *, char *, const char, int);
  25. void strlfil (char *, char *, const char, int);
  26. BOOL readdir (char *);
  27. void usage ();
  28.  
  29.  
  30.  
  31. // Options for ReadArgs
  32. char *template = "ARGS/M,C=CLI/S,S=SINCE/K,U=UPTO/K,AS=ALPHASORT/S,"\
  33.                  "-AS=-ALPHASORT/S,SS=SIZESORT/S,-SS=-SIZESORT/S,"\
  34.                  "DS=DATESORT/S,-DS=-DATESORT/S,Q=QUICK/S,DO=DIRSONLY/S,"\
  35.                  "FO=FILESONLY/S,FF=FILESFIRST/S,SH=SHOWHIDDEN/S,NH=NOHEAD/S,"\
  36.                  "NI=NOINFO/S,NS=NOSIZE/S,NP=NOPROTECT/S,ND=NODATE/S,"\
  37.                  "NC=NOCOMMENT/S,V=VAR/K,HEADFORM/K,?=HELP/S";
  38.  
  39. struct Def
  40. {
  41.    char **argv;
  42.    long cli;
  43.    char *since;
  44.    char *upto;
  45.    long alphasort;
  46.    long alphasortdown;
  47.    long sizesort;
  48.    long sizesortdown;
  49.    long datesort;
  50.    long datesortdown;
  51.    long quick;
  52.    long dirsonly;
  53.    long filesonly;
  54.    long filesfirst;
  55.    long showhidden;
  56.    long nohead;
  57.    long noinfo;
  58.    long nosize;
  59.    long noprotect;
  60.    long nodate;
  61.    long nocomment;
  62.    char *var;
  63.    char *headform;
  64.    long help;
  65. } args = {NULL,  FALSE, FALSE, FALSE, NULL,  NULL,  FALSE, FALSE,
  66.           FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
  67.           FALSE, FALSE, FALSE, FALSE, FALSE, NULL,  "  <»--«>  ", FALSE};
  68.  
  69.  
  70.  
  71. struct RDArgs *rda = NULL;
  72. struct FileInfoBlock *fib = NULL;
  73. BOOL sincedate = TRUE, uptodate = TRUE;
  74. struct DateTime *dat = NULL, *since = NULL, *upto = NULL;
  75. char strdate[LEN_DATSTRING], strtime[LEN_DATSTRING], *pat = NULL;
  76.  
  77.  
  78. // Class, in which one file or directory is stored
  79. class Entry
  80. {
  81.    Entry *prev, *next;
  82.    BOOL dir;
  83.    long size, days, mins;
  84.    char name[108], outstr[116];
  85.    
  86.    Entry ();
  87.    int compare (const Entry *) const;
  88.    friend class Lst;
  89. };
  90.  
  91.  
  92. Entry::Entry ()
  93. {
  94.    char *s = outstr;
  95.    
  96.    prev = next = NULL;
  97.    dir  = fib->fib_DirEntryType > 0 ? TRUE : FALSE;
  98.    size = fib->fib_Size;
  99.    days = fib->fib_Date.ds_Days;
  100.    mins = fib->fib_Date.ds_Minute;
  101.    strcpy (name, fib->fib_FileName);
  102.    memset (s, 0, 116);
  103.    if (args.quick)      // Now fill outstr with datas according to parameters
  104.    {
  105.       strcpy (outstr, name);
  106.       return;
  107.    }
  108.    strlfil (s, name, ' ', 25);
  109.    s += 24;
  110.    if (!args.nosize)
  111.    {
  112.       if (dir)
  113.       {
  114.          strncpy (s, "  (dir)   ", 11);
  115.          s += 10;
  116.       }
  117.       else
  118.       {
  119.          strrfil (s, itoa (size), ' ', 7);
  120.          strcat (s, "    "); 
  121.          s += 10;
  122.       }
  123.    }
  124.    if (!args.noprotect)
  125.    {
  126.       int i, j;
  127.       char p[] = "hsparwed";
  128.       
  129.       for (i = 128, j = 0 ; i >= 16 ; i >>= 1, j++, s++)
  130.          if (fib->fib_Protection & i)
  131.             *s = p[j];
  132.          else
  133.             *s = '-';
  134.       for (i = 8, j = 4 ; i >= 1 ; i >>= 1, j++, s++)
  135.          if (fib->fib_Protection & i)
  136.             *s = '-';
  137.          else
  138.             *s = p[j];
  139.       strcat (s, "    ");
  140.       s += 3;
  141.    }
  142.    if (!args.nodate)
  143.    {
  144.       dat->dat_Stamp = fib->fib_Date;
  145.       if (DateToStr (dat))
  146.       {
  147.          strlfil (s, dat->dat_StrDate, ' ', 11);
  148.          s += 10;
  149.          strlfil (s, dat->dat_StrTime, ' ', 12);
  150.          s += 11;
  151.       }
  152.    }
  153.    if (!args.nocomment)
  154.    {
  155.       if (*fib->fib_Comment != '\0')
  156.       {
  157.          strcat (s, "\n    ");
  158.          s += 4;
  159.          strncat (s, fib->fib_Comment, 40);
  160.       }
  161.    }
  162. }
  163.  
  164.  
  165. int Entry::compare (const Entry *that) const
  166. {
  167.    if (args.alphasort || args.alphasortdown)
  168.       return stricmp (name, that->name);
  169.    else if (args.sizesort || args.sizesortdown)
  170.       return size - that->size;
  171.    else if (args.datesort || args.datesortdown)
  172.       return (days - that->days) ? (days - that->days) : (mins - that->mins);
  173.       // If the difference of the two dates is 0, then give back the difference
  174.       // of the two times
  175.    else return -1;
  176. }
  177.  
  178.  
  179. // Class, in which the entries are stored
  180. class Lst
  181. {
  182.    Entry *first, *last;
  183.    
  184.    public:
  185.    int count, bytes;
  186.    
  187.    Lst ();
  188.    ~Lst ();
  189.    void insert ();
  190.    void ausgabe () const;
  191.    BOOL empty () const;
  192. };
  193.  
  194.  
  195. Lst::Lst ()
  196. {
  197.    count = bytes = 0;
  198.    first = last = NULL;
  199. }
  200.  
  201.  
  202. Lst::~Lst ()
  203. {
  204.    Entry *e = first;
  205.    
  206.    while (e)
  207.    {
  208.       Entry *hilf = e;
  209.       e = e->next;
  210.       delete hilf;
  211.    }
  212. }
  213.  
  214.  
  215. void Lst::insert ()
  216. {
  217.    BOOL sort = FALSE;
  218.    Entry *pos = first, *neu = NULL;
  219.    
  220.    if (pat)             // Is there a pattern?
  221.       if (MatchPatternNoCase (pat, fib->fib_FileName) == NULL)
  222.          return;
  223.    if (args.since)      // Is there a since-option
  224.    {
  225.       if (sincedate)
  226.       {
  227.          if (fib->fib_Date.ds_Days < since->dat_Stamp.ds_Days)
  228.             return;
  229.       }
  230.       else
  231.       {
  232.          if (fib->fib_Date.ds_Minute < since->dat_Stamp.ds_Minute)
  233.             return;
  234.       }
  235.    }
  236.    if (args.upto)       // Is ther a upto-option
  237.    {
  238.       if (uptodate)
  239.       {
  240.          if (fib->fib_Date.ds_Days > upto->dat_Stamp.ds_Days)
  241.             return;
  242.       }
  243.       else
  244.       {
  245.          if (fib->fib_Date.ds_Minute > upto->dat_Stamp.ds_Minute)
  246.             return;
  247.       }
  248.    }
  249.    if (fib->fib_DirEntryType < 0)   // Is the entry a file
  250.    {                                // and defined the user
  251.       if (args.dirsonly)            // dirsonly...
  252.          return;
  253.       if (args.noinfo && strstr (fib->fib_FileName, ".info"))
  254.          return;
  255.    }
  256.    else
  257.    {
  258.       if (args.filesonly)           // ...or visa versa ?
  259.          return;
  260.    }
  261.    if (!args.showhidden)            // Is the 'h'-flag set
  262.       if (fib->fib_Protection & FIBF_HIDDEN)
  263.          return;
  264.    neu = new Entry ();
  265.    if (neu == NULL)
  266.    {
  267.       cout << "\nNo memory!!\n\n";
  268.       return;
  269.    }
  270.    
  271.    // if neccesary, sort the entries 
  272.    if (args.alphasort || args.sizesort || args.datesort)
  273.    {
  274.       while (pos && neu->compare (pos) > 0)
  275.          pos = pos->next;
  276.       sort = TRUE;
  277.    }
  278.    else if (args.alphasortdown || args.sizesortdown || args.datesortdown)
  279.    {
  280.       while (pos && neu->compare (pos) < 0)
  281.          pos = pos->next;
  282.       sort = TRUE;
  283.    }
  284.    if (sort)
  285.    {
  286.       if (pos == NULL)
  287.       {
  288.          Entry *alt = last;
  289.  
  290.          if (alt != NULL)
  291.          {
  292.             alt->next = neu;
  293.             neu->prev = alt;
  294.             last = neu;
  295.          }
  296.          else
  297.          {
  298.             first = neu;
  299.             last = neu;
  300.          }
  301.       }
  302.       else
  303.       {
  304.          if (pos->prev == NULL)
  305.          {
  306.             pos->prev = neu;
  307.             neu->next = pos;
  308.             first = neu;
  309.          }
  310.          else
  311.          {
  312.             Entry *vor = pos->prev;
  313.             
  314.             vor->next = neu;
  315.             neu->prev = vor;
  316.             neu->next = pos;
  317.             pos->prev = neu;
  318.          }
  319.       }
  320.    }
  321.    else
  322.    {
  323.       Entry *alt = last;
  324.    
  325.       if (alt)
  326.       {
  327.          alt->next = neu;
  328.          neu->prev = alt;
  329.          last = neu;
  330.       }
  331.       else
  332.       {
  333.          first = neu;
  334.          last = neu;
  335.       }
  336.    }
  337.    count++;
  338.    if (!neu->dir)
  339.       bytes += neu->size;
  340.    return;
  341. }
  342.  
  343.  
  344. void Lst::ausgabe () const
  345. {
  346.    for (Entry *e = first ; e ; e = e->next)
  347.       cout << "   " << e->outstr << "\n";
  348. }
  349.  
  350.  
  351. BOOL Lst::empty () const
  352. {
  353.    return first || last ? FALSE : TRUE;
  354. }
  355.  
  356.  
  357.  
  358. void close_all (const char *why, const int how)
  359. {
  360.    if (why)    cout << why << "\n\n";
  361.    if (pat)    delete [] pat;
  362.    if (fib)    FreeDosObject (DOS_FIB, (APTR)fib);
  363.    if (upto)   FreeVec ((APTR)upto);
  364.    if (since)  FreeVec ((APTR)since);
  365.    if (dat)    FreeVec ((APTR)dat);
  366.    if (rda)    FreeArgs (rda);
  367.    exit (how);
  368. }
  369.  
  370.  
  371. char *itoa (int zahl)
  372. {
  373.    static char res[10];
  374.    char c, *dest = res;
  375.    int maxpot = 1000000, flag = 0;
  376.    
  377.    while (maxpot >= 1)
  378.    {
  379.       c = zahl / maxpot + '0';
  380.       if ((c != '0') || (maxpot == 1) || flag)
  381.       {
  382.          flag = 1;
  383.          *dest++ = c;
  384.       }
  385.       zahl %= maxpot;
  386.       maxpot /= 10;
  387.    }
  388.    *dest = '\0';
  389.    return res;
  390. }
  391.  
  392. // Fill a string with characters. Start from right
  393. void strrfil (char *s, char *t, const char c, int n)
  394. {
  395.    int len = strlen (t);
  396.    
  397.    while (n-- > len)
  398.       *s++ = c;
  399.    while (*s++ = *t++)
  400.       ;
  401. }
  402.  
  403. // Fill a string with characters. Start from left
  404. void strlfil (char *s, char *t, const char c, int n)
  405. {
  406.    while ((n-- > 0) && (*s++ = *t++))
  407.       ;
  408.    s--;
  409.    while (n-- > 0)
  410.       *s++ = c;
  411. }
  412.  
  413.  
  414. BOOL readdir (char *name)
  415. {
  416.    BOOL file = FALSE;
  417.    BPTR lock = NULL, l = NULL;
  418.    Lst *dl = new Lst, *fl = new Lst;   // Create two lists, one for
  419.                                        // Directoriess and one for files
  420.    if (lock = Lock (name, ACCESS_READ))
  421.    {
  422.       Examine (lock, fib);
  423.       if (fib->fib_DirEntryType < 0)
  424.       {
  425.          file = TRUE;
  426.          fl->insert ();
  427.       }
  428.       else
  429.       {
  430.          while (ExNext (lock, fib) == DOSTRUE)
  431.          {
  432.             if (fib->fib_DirEntryType < 0)
  433.                fl->insert ();
  434.             else
  435.                dl->insert ();
  436.          }
  437.       }
  438.       if ((!fl->empty ()) || (!dl->empty ()))   // is there something in the lists?
  439.       {
  440.          if (!args.nohead)
  441.          {
  442.             cout << '\n';
  443.             if (!file)
  444.             {
  445.                if (*name)
  446.                   cout << "Directory: \x9b""1m" << name << "\x9b""0m\n\n";
  447.                else
  448.                   cout << "Current Directory:\n\n";
  449.             }
  450.          }
  451.          if (args.filesfirst)
  452.          {
  453.             fl->ausgabe ();
  454.             dl->ausgabe ();
  455.          }
  456.          else
  457.          {
  458.             dl->ausgabe ();
  459.             fl->ausgabe ();
  460.          }
  461.          if (!args.nohead)
  462.          {
  463.             cout << "\n";
  464.             if (dl->count)
  465.                cout << dl->count << " Director" << (dl->count==1 ? "y" : "ies");
  466.             if (fl->count)
  467.             {
  468.                if (dl->count)
  469.                   cout << args.headform;
  470.                cout << fl->count << " File" << (fl->count==1 ? "" : "s")
  471.                     << args.headform << fl->bytes << " bytes used";
  472.             }
  473.             cout << "\n\n";
  474.          }
  475.       }
  476.       delete dl;
  477.       delete fl;
  478.       UnLock (lock);
  479.       return TRUE;
  480.    }
  481.    return FALSE;
  482. }
  483.  
  484.  
  485. void usage ()
  486. {
  487.    cout << "\x9b""32;40m\x9b""1mDirs © by  Harald Pehl in 1993\n";
  488.    cout << "\x9b""31;40mOptions:\x9b""0m " << template << "\n\n";
  489.    cout << "The value in brackets is the default-value for the argument\n";
  490.    cout << "ARGS         = Directory(ies) which are displayed\n"
  491.            "CLI          = Read arguments ONLY via CLI        (FALSE)\n"
  492.            "SINCE        = Files since a date                 (empty)\n"
  493.            "UPTO         = Files upto a date                  (empty)\n"
  494.            "(-)ALPHASORT = Sort by name  A-Z                  (unsorted)\n"
  495.            "(-)SIZESORT  = Sort by size 10,20,30...           (unsorted)\n"
  496.            "(-)DATESORT  = Sort by date 1.1.78-today          (unsorted)\n"
  497.            "QUICK        = Display only the name              (FALSE)\n"
  498.            "DIRSONLY     = Display only directories           (FALSE)\n"
  499.            "FILESONLY    = Display only files                 (FALSE)\n"
  500.            "FILESFIRST   = Display files before directories   (FALSE)\n"
  501.            "SHOWHIDDEN   = Display hidden files               (FALSE)\n"
  502.            "NOHEAD       = No statusbar                       (FALSE)\n"
  503.            "NOINFO       = Don\'t display .info - Files       (FALSE)\n"
  504.            "NOSIZE       = Don\'t display the size            (FALSE)\n"
  505.            "NOPROTECT    = Don\'t display the protection-bits (FALSE)\n"
  506.            "NODATE       = Don\'t display the date            (FALSE)\n"
  507.            "NOCOMMENT    = Don\'t display the comment         (FALSE)\n"
  508.            "VAR          = Variable which will be read in     (FALSE)\n"
  509.            "HEADFORM     = String in the statusbar            (<»--«>)\n\n";
  510.    close_all (NULL, 0);
  511. }
  512.  
  513.  
  514. void main (int argc, char **argv)
  515. {
  516.    BPTR lock = NULL;
  517.    char name[108], str[256], var[108];
  518.    
  519.    rda = ReadArgs (template, (LONG *)&args, NULL);
  520.    if (args.help)
  521.       usage ();
  522.    if (!args.cli)       // Read in an ENV-variable
  523.    {
  524.       if (args.var)
  525.       {
  526.          if (strstr (args.var, "ENV:"))
  527.             strcpy (var, args.var);
  528.          else
  529.          {
  530.             strcpy (var, "ENV:\0");
  531.             strcat (var, args.var);
  532.          }
  533.       }
  534.       else
  535.          strcpy (var, "ENV:DIRCMD\0");
  536.       if (GetVar (var, str, 256, 0) != -1)
  537.       {
  538.          struct RDArgs *env = NULL;
  539.    
  540.          if (env = (struct RDArgs *)AllocDosObject (DOS_RDARGS, NULL))
  541.          {
  542.             env->RDA_Source.CS_Buffer = str;
  543.             env->RDA_Source.CS_Length = strlen (str);
  544.             env->RDA_Source.CS_CurChr = 0;
  545.             env->RDA_DAList  = NULL;
  546.             env->RDA_Buffer  = NULL;
  547.             env->RDA_BufSiz  = 0;
  548.             env->RDA_ExtHelp = NULL;
  549.             env->RDA_Flags   = 0;
  550.             rda = ReadArgs (template, (LONG *)&args, env);
  551.             FreeDosObject (DOS_RDARGS, (APTR)env);
  552.          }
  553.       }
  554.    }
  555.    if (args.quick)
  556.       args.nohead = args.nosize = args.noprotect = args.nodate = args.nocomment = TRUE;
  557.    // Allocate memory and define structs, if neccesary
  558.    if (!args.nodate)
  559.    {
  560.       if (! (dat = (struct DateTime *)AllocVec (sizeof (struct DateTime), MEMF_CLEAR)))
  561.          close_all ("Kein Speicherplatz mehr", 10);
  562.       dat->dat_Stamp.ds_Days   = 0;
  563.       dat->dat_Stamp.ds_Minute = 0;
  564.       dat->dat_Stamp.ds_Tick   = 0;
  565.       dat->dat_Format  = FORMAT_DOS;
  566.       dat->dat_Flags   = DTF_SUBST;
  567.       dat->dat_StrDay  = NULL;
  568.       dat->dat_StrDate = strdate;
  569.       dat->dat_StrTime = strtime;
  570.    }
  571.    if (args.since)
  572.    {
  573.       if (! (since = (struct DateTime *)AllocVec (sizeof (struct DateTime), MEMF_CLEAR)))
  574.          close_all ("Kein Speicherplatz mehr", 10);
  575.       since->dat_Stamp.ds_Days   = 0;
  576.       since->dat_Stamp.ds_Minute = 0;
  577.       since->dat_Stamp.ds_Tick   = 0;
  578.       since->dat_Format = FORMAT_DOS;
  579.       since->dat_Flags  = DTF_SUBST;
  580.       since->dat_StrDay = NULL;
  581.       if (strchr (args.since, ':'))
  582.       {
  583.          sincedate = FALSE;
  584.          since->dat_StrDate = NULL;
  585.          since->dat_StrTime = args.since;
  586.       }
  587.       else
  588.       {
  589.          since->dat_StrDate = args.since;
  590.          since->dat_StrTime = NULL;
  591.       }
  592.       StrToDate (since);
  593.    }
  594.    if (args.upto)
  595.    {
  596.       if (! (upto = (struct DateTime *)AllocVec (sizeof (struct DateTime), MEMF_CLEAR)))
  597.          close_all ("Kein Speicherplatz mehr", 10);
  598.       upto->dat_Stamp.ds_Days   = 0;
  599.       upto->dat_Stamp.ds_Minute = 0;
  600.       upto->dat_Stamp.ds_Tick   = 0;
  601.       upto->dat_Format = FORMAT_DOS;
  602.       upto->dat_Flags  = DTF_SUBST;
  603.       upto->dat_StrDay = NULL;
  604.       if (strchr (args.since, ':'))
  605.       {
  606.          uptodate = FALSE;
  607.          upto->dat_StrDate = NULL;
  608.          upto->dat_StrTime = args.upto;
  609.       }
  610.       else
  611.       {
  612.          upto->dat_StrDate = args.upto;
  613.          upto->dat_StrTime = NULL;
  614.       }
  615.       StrToDate (upto);
  616.    }
  617.    if (! (fib = (struct FileInfoBlock *)AllocDosObject (DOS_FIB, NULL)))
  618.       close_all ("Kein Speicherplatz mehr", 10);
  619.    argv = args.argv;    // Copy dirs and files to argv
  620.    if (*argv == NULL)
  621.    {
  622.       GetCurrentDirName (name, 108);
  623.       readdir (name);
  624.    }
  625.    else
  626.    {
  627.       do
  628.       {
  629.          if (strstr (*argv, "#?") || strchr (*argv, '?'))
  630.          {
  631.             char *s = *argv;
  632.             int len = strlen (*argv) * 3;
  633.             
  634.             pat = new char [len];
  635.             *argv = FilePart (*argv);
  636.             if (s != *argv)
  637.             {
  638.                strncpy (name, s, *argv-s);
  639.                name[*argv-s] = '\0';
  640.             }
  641.             else
  642.                GetCurrentDirName (name, 108);
  643.             ParsePatternNoCase (*argv, pat, len);
  644.             lock = Lock (name, ACCESS_READ);
  645.          }
  646.          else
  647.             strcpy (name, *argv);
  648.          if (!readdir (name))
  649.             cout << "\nFile/Directory not found: \'" << name << "\' !!\n\n";
  650.          argv++;
  651.          delete [] pat;
  652.          pat = NULL;
  653.       } while (*argv);
  654.    }  
  655.    close_all (NULL, 0);
  656. }
  657.  
  658.