home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 455.lha / finddisk_v3.1 / fd2src / fd2.c < prev    next >
C/C++ Source or Header  |  1990-12-10  |  21KB  |  1,168 lines

  1.  
  2. /*                            FindDisk2.2
  3.  
  4.      Author      : Ross MacGregor
  5.      Date        : 27/10/88
  6.      Last Update : 5/03/90
  7.      Comments    : This is a public domain program.
  8.  
  9.  
  10.      DiskList stored in compacted form:
  11.  
  12.      below: { unskrunched } => { skrunched }
  13.             [] is a byte of memory
  14.  
  15.      * compacts strings of spaces
  16.          { [$20] [$20] [$20] [$20] [$20] } => { [SKRUNCHAR] [SKRUNOFFS 5] }
  17.          { [$20] [$20] } => { [$20] [$20] }
  18.  
  19.      * the STARTSTR is compacted
  20.          { STARTSTR } => { [STARTCHAR] }
  21.  
  22. */
  23.  
  24. /*#include <functions.h>*/
  25. #include <exec/types.h>
  26. #include <exec/nodes.h>
  27. #include <exec/lists.h>
  28. #include <exec/libraries.h>
  29. #include <exec/ports.h>
  30. #include <exec/interrupts.h>
  31. #include <exec/io.h>
  32. #include <exec/memory.h>
  33. #include <libraries/dos.h>
  34. #include <libraries/dosextens.h>
  35.  
  36. /* lattice will want smaller strings - sorry, do it yourself */
  37.  
  38. #define HELPTEXT1  "\nFindDisk2.2 :\n\
  39. FD -l             ; Loads DiskList to ram:\n\
  40. FD -s             ; Saves DiskList back to disk (first doing an update)\n\
  41. FD -d  [path]     ; Saves dir listing to ram:TempDL\n\
  42. FD -a  [path]     ; Saves listing with all sub-directories included\n\
  43. FD -u             ; Updates the DiskList with TempDL\n\
  44. FD -n             ; Creates a new (empty) DiskList\n"
  45.  
  46. #define HELPTEXT2  "FD -r  diskname   ; Removes directory from DiskList matching 'diskname'\n\
  47. FD text1 [textn]  ; Lists disk dir with a line containing text1 to textn\n\
  48.   FD text           ; Case insensitive scan for text\n\
  49.   FD !text          ; Case sensitive scan for for text\n"
  50.  
  51. #define HELPTEXT3 "\nEnvironment Variables: (= default setting)\n\
  52.   DLDISK  =  FindDisk:Disklist (Disk storage location/name)\n\
  53.   DLTEMP  =  ram:DiskList (Ram storage location/name)\n\
  54.   DLDRIVE =  df0: (Captures dir of this drive)\n\n"
  55.  
  56.  
  57. #define CP_BUFF 1024L    /* Buffer size for the file copy function */
  58.  
  59. /* This indicates the start line of a dir listing, and
  60.    it MUST have the name of the disk on the same line.  */
  61.  
  62. #define STARTSTR  "Directory of "
  63.  
  64.  
  65. /* Special character used to compact the spaces in DiskList */
  66. #define SKRUNCHAR 1
  67. #define SKRUNOFFS 10
  68.  
  69. /* Special characters used to replace the STARTSTR */
  70. #define STARTCHAR  2
  71.  
  72. /* Lines in the stored dir listing array */
  73. #define NUMLINES 25
  74.  
  75. /* Max length of the lines read in */
  76. #define LINELEN  170
  77. #define MAXBUF   LINELEN+1
  78.  
  79. struct FileHandle *fdl, *ftmp;
  80. struct FileHandle *confh;
  81.  
  82. char *tempdl="ram:TempDL";
  83.  
  84. char *dltemp="ram:DiskList", *dldisk="FindDisk:DiskList";
  85. char *sdir_pat="df0:";
  86.  
  87. #define MAXPATHLEN 80
  88.  
  89. char *dlpath;
  90. char buffer[LINELEN];
  91.  
  92. /* global main arguments */
  93. int glargc;
  94. char **glargv;
  95.  
  96. /* function error indicator */
  97. int fcnerr;
  98.  
  99. char *outofmem="Out of Memory Error.\n";
  100. char *cutoff=" - - (no more lines available) - -\n";
  101.  
  102. /*------------ dynamic structure for coping DL to memory -------------*/
  103.  
  104. /* Blocks of memory for storing the disklist */
  105. #define BUFBLKS 20
  106. #define BLKSIZE 10000
  107.  
  108. char *bufferblock[BUFBLKS],*bufptr=NULL;
  109. int bufcount=-1, chrcount=BLKSIZE+1;
  110. void init_bufblks(), free_bufblks();
  111.  
  112.  
  113.  
  114. /*------------ dynamic structure for listing the volume names --------*/
  115. /*                   used in recursive do_ls call also                */
  116.  
  117. struct disk
  118. {
  119.   char name[LINELEN];
  120.   struct disk *next;
  121. };
  122. struct disk *firstdisk,*diskptr;
  123.  
  124. #define INIT_DISKNAMES firstdisk=diskptr=NULL
  125. #define FREE_DISKNAMES free_disknames()
  126.  
  127. void free_disknames();
  128.  
  129. /*----------------------------------------------------------------------*/
  130.  
  131. char *strstr(), *strtoupper(), *getstr();
  132. void putstr();
  133. char *skrunch(), *getenv();
  134. void unskrunch(), get_dlpath();
  135. struct FileHandle *opendl(), *opentmp();
  136.  
  137. char *strchr(), *malloc();
  138. extern struct FileHandle *Open();
  139.  
  140.  
  141. void finddisk();
  142. /* finddisk uses this */
  143. char dirlist[NUMLINES][LINELEN];
  144.  
  145. int update(), remove(), loaddl(), savedl(), sdir(), newdl();
  146.  
  147. void update_free(), ls_free(), remove_free();
  148.  
  149.  
  150. void main(argc,argv)
  151.   int argc;
  152.   char *argv[];
  153. {
  154.  
  155.   glargv=argv;
  156.   glargc=argc;
  157.  
  158.   if( (confh=Output())==NULL )
  159.     exit(1);
  160.  
  161.   if( argc==1)
  162.   {
  163.     putstr(HELPTEXT1);
  164.     putstr(HELPTEXT2);
  165.     putstr(HELPTEXT3);
  166.     exit(0);
  167.   }
  168.  
  169.   dldisk=getenv("env:dldisk",dldisk);
  170.   dltemp=getenv("env:dltemp",dltemp);
  171.   sdir_pat=getenv("env:dldrive",sdir_pat);
  172.   get_dlpath();
  173.  
  174.   if( *argv[1]=='-' )
  175.   {
  176.     switch( *(argv[1]+1) )
  177.     {
  178.        case 'd':  if( sdir(0) )
  179.                     putstr("SaveDir failed!\n");
  180.                   break;
  181.  
  182.        case 'a':  if( sdir(1) )
  183.                     putstr("SaveDir failed!\n");
  184.                   break;
  185.  
  186.        case 's':  if( savedl() )
  187.                     putstr("SaveDL failed!\n");
  188.                   break;
  189.  
  190.        case 'l':  if( loaddl() )
  191.                     putstr("LoadDL failed!\n");
  192.                   break;
  193.  
  194.        case 'u':  if( update() )
  195.                     putstr("Update failed!\n");
  196.                   break;
  197.  
  198.        case 'r':  if( remove() )
  199.                     putstr("Remove failed!\n");
  200.                   break;
  201.  
  202.        case 'n':  if( newdl() )
  203.                     putstr("Empty DiskList created (Save if in RAM).\n");
  204.                   break;
  205.  
  206.        default :  putstr("Unknown Option.\n");
  207.     }
  208.   }
  209.   else finddisk();
  210.  
  211. }
  212.  
  213.  
  214. char *getenv(fullpath,var)
  215.   char *fullpath, *var;
  216. {
  217.   struct FileLock *lock,*Lock();
  218.   struct FileHandle *fh;
  219.   char *buffer;
  220.   int  len;
  221.  
  222.   if( lock=Lock(fullpath,(long)ACCESS_READ) )
  223.   {
  224.     UnLock(lock);
  225.     if( !(fh=Open(fullpath,(long)MODE_OLDFILE)) )
  226.       return var;
  227.     if( !(buffer=(char *)malloc(MAXPATHLEN+1)) )
  228.     {
  229.       putstr(outofmem);
  230.       Close(fh);
  231.       return var;
  232.     }
  233.     len=Read(fh,buffer,(long)MAXPATHLEN);
  234.     Close(fh);
  235.     *(buffer+len)='\0';
  236.     return buffer;
  237.   }
  238.   return var;
  239. }
  240.  
  241. void finddisk()
  242. {
  243.   int  kase=0, thisone=0, line=0;
  244.   int i;
  245.   char *p;
  246.  
  247.   if( !(fdl=opendl((long)MODE_OLDFILE)) )
  248.     return;
  249.  
  250.   /* Converts non-case sensitive keywords to upper case */
  251.   for(i=1; i<glargc; i++)
  252.     if( *glargv[i]!='!' )
  253.       strtoupper(glargv[i]);
  254.  
  255.   /* get line of DiskList */
  256.   while( getstr(buffer,fdl) !=NULL )
  257.   {
  258.  
  259.     /* first checks for a startchar of a dirlist */
  260.     if( strchr(buffer,(char)STARTCHAR) )
  261.     {
  262.        if( thisone )
  263.        {
  264.           /* print the directory */
  265.           line--;
  266.           for(i=0; i<line; i++)
  267.             unskrunch(dirlist[i]);
  268.  
  269.           /* if at the end of the dirlist array- prints 'cut off' */
  270.           if( line==NUMLINES-1 )
  271.             putstr(cutoff);
  272.  
  273.           thisone=0;
  274.         }
  275.  
  276.         line=1;
  277.     }
  278.  
  279.  
  280.     if( line )
  281.     {
  282.        /* Copies the line in buffer to the stored dirlist */
  283.        strncpy(dirlist[line-1],buffer,MAXBUF);
  284.  
  285.        if( ++line > NUMLINES )
  286.          line--;
  287.  
  288.        /* Checks for given keywords */
  289.        if( thisone==0 )
  290.          for(i=1; i<glargc; i++)
  291.          {
  292.            if( *glargv[i]=='!' )
  293.            {
  294.              p=glargv[i]+1;
  295.              kase=1;
  296.            }
  297.            else
  298.            {
  299.              p=glargv[i];
  300.              kase=0;
  301.            }
  302.  
  303.            if( strstr(buffer,p,kase) )
  304.              thisone=1;
  305.            else
  306.            {
  307.              thisone=0;
  308.              break;
  309.            }
  310.          }
  311.  
  312.     }/* if(line) */
  313.  
  314.   } /* while( get next buffer) */
  315.  
  316.   if( thisone )
  317.   {
  318.         line--;
  319.         for(i=0; i<line; i++)
  320.           unskrunch(dirlist[i]);
  321.  
  322.         /* if at the end of the dirlist array- prints 'cut off' */
  323.         if( line==NUMLINES-1 )
  324.           putstr(cutoff);
  325.   }
  326.  
  327.   Close(fdl);
  328. }
  329.  
  330.  
  331. #define update_cleanup(x)  { update_free(); return x; }
  332.  
  333. update()
  334. {
  335.   int  i;
  336.  
  337.   if( !(fdl=opendl((long)MODE_OLDFILE)) )
  338.     return 1;
  339.  
  340.   if( !(ftmp=opentmp((long)MODE_OLDFILE)) )
  341.   {
  342.     Close(fdl);
  343.     return 0;
  344.   }
  345.  
  346.   INIT_DISKNAMES;
  347.   init_bufblks();
  348.  
  349.   /* finds the disks names in TempDL */
  350.   while( getstr(buffer,ftmp) !=NULL )
  351.   {
  352.       if( strstr(buffer,STARTSTR,1) )
  353.       {
  354.          skrunch(buffer);
  355.          if( storename(buffer) )
  356.            update_cleanup(3)
  357.       }
  358.   }
  359.   if( fcnerr )
  360.     update_cleanup(10)
  361.  
  362.   if( storedl() )
  363.     update_cleanup(4)
  364.  
  365.   Seek(ftmp,0L,(long)OFFSET_BEGINNING);
  366.  
  367.   /* store TempDL in memory */
  368.   while( getstr(buffer,ftmp) !=NULL )
  369.     if( store( skrunch(buffer) ) )
  370.       update_cleanup(5)
  371.   if( fcnerr )
  372.     update_cleanup(6);
  373.  
  374.   Close(fdl);
  375.   if( !(fdl=opendl((long)MODE_NEWFILE)) )
  376.   {
  377.     Close(ftmp);
  378.     FREE_DISKNAMES;
  379.     free_bufblks();
  380.     return 7;
  381.   }
  382.  
  383.   /* write the in memory disklist to the one in ram: */
  384.   for(i=0; i<=bufcount; i++)
  385.     if( fputstr(bufferblock[i],fdl) )
  386.       update_cleanup(8)
  387.  
  388.   Close(ftmp);
  389.   if( !(ftmp=opentmp((long)MODE_NEWFILE)) )
  390.     update_cleanup(9)
  391.  
  392.   update_free();
  393.   return 0;
  394. }
  395.  
  396. void update_free()
  397. {
  398.   Close(fdl);
  399.   Close(ftmp);
  400.   FREE_DISKNAMES;
  401.   free_bufblks();
  402. }
  403.  
  404.  
  405. #define remove_cleanup(x)  { remove_free(); return x; }
  406.  
  407. remove()
  408. {
  409.   int i;
  410.  
  411.   if( !(fdl=opendl((long)MODE_OLDFILE)) )
  412.     return 2;
  413.  
  414.   INIT_DISKNAMES;
  415.   init_bufblks();
  416.  
  417.   /* finds the disk name in DiskList */
  418.   while( getstr(buffer,fdl) !=NULL )
  419.   {
  420.       if( strstr(buffer,glargv[2],1) )
  421.       {
  422.          if( storename(buffer) )
  423.            remove_cleanup(3)
  424.       }
  425.   }
  426.   if( fcnerr )
  427.     remove_cleanup(4);
  428.  
  429.   Seek(fdl,0L,(long)OFFSET_BEGINNING);
  430.  
  431.   if( storedl() )
  432.     remove_cleanup(5)
  433.  
  434.   Close(fdl);
  435.   if( !(fdl=opendl((long)MODE_NEWFILE)) )
  436.   {
  437.     FREE_DISKNAMES;
  438.     free_bufblks();
  439.     return 6;
  440.   }
  441.  
  442.   /* write the in memory disklist to the one in ram: */
  443.   for(i=0; i<=bufcount; i++)
  444.     if( fputstr(bufferblock[i],fdl) )
  445.       remove_cleanup(7)
  446.  
  447.   remove_free();
  448.   return 0;
  449. }
  450.  
  451.  
  452. void remove_free()
  453. {
  454.   Close(fdl);
  455.   FREE_DISKNAMES;
  456.   free_bufblks();
  457. }
  458.  
  459.  
  460.  
  461. /* loads the DiskList into memory but leaves out the directories in the
  462.    diskname list, pointed to by firstdisk */
  463. storedl()
  464. {
  465.   int storeit=1;  /* saving this directory */
  466.  
  467.   /* doesn't store directories that are in the temp file */
  468.   while( getstr(buffer,fdl) !=NULL )
  469.   {
  470.       if( strchr(buffer,(char)STARTCHAR) )
  471.       {
  472.          storeit=1;
  473.          diskptr=firstdisk;
  474.          while(diskptr)
  475.          {
  476.            if( strstr(buffer,diskptr->name,1) )
  477.            {
  478.              storeit=0;
  479.              break;
  480.            }
  481.            diskptr=diskptr->next;
  482.          }
  483.       }
  484.  
  485.       if(storeit)
  486.        if( store(buffer) )
  487.          return 1;
  488.   }
  489.  
  490.   return fcnerr;
  491. }
  492.  
  493.  
  494.  
  495. /* Saves the name of a disk in a linked list structure */
  496. storename(buffer)
  497.  char *buffer;
  498. {
  499.   if( diskptr==NULL )
  500.   {
  501.     if( (firstdisk=(struct disk *)malloc(sizeof(struct disk)) )==NULL)
  502.     {
  503.       putstr(outofmem);
  504.       return 1;
  505.     }
  506.     diskptr=firstdisk;
  507.     strncpy(diskptr->name,buffer,MAXBUF);
  508.     diskptr->next=NULL;
  509.   }
  510.   else
  511.   {
  512.     if( (diskptr->next=(struct disk *)malloc(sizeof(struct disk)) )==NULL)
  513.     {
  514.       putstr(outofmem);
  515.       return 2;
  516.     }
  517.     diskptr=diskptr->next;
  518.     strncpy(diskptr->name,buffer,MAXBUF);
  519.     diskptr->next=NULL;
  520.   }
  521.  
  522.   return 0;
  523. }
  524.  
  525. void free_disknames()
  526. {
  527.   struct disk *p;
  528.  
  529.   while(firstdisk)
  530.   {
  531.     p=firstdisk->next;
  532.     free(firstdisk);
  533.     firstdisk=p;
  534.   }
  535. }
  536.  
  537.  
  538. /* prints line to stdout unskrunched */
  539. /* format  [BYTE]=>   [SKRUNCHAR] [# of spaces ]   */
  540.  
  541. void unskrunch(line)
  542.   char *line;
  543. {
  544.   char output[LINELEN], *p;
  545.   int i;
  546.  
  547.   p=output;
  548.   while(*line)
  549.   {
  550.     switch((int)*line)
  551.     {
  552.       case SKRUNCHAR : line++;
  553.                        for(i=SKRUNOFFS; i<(int)*line; i++)
  554.                          *(p++)=' ';
  555.                        break;
  556.  
  557.       case STARTCHAR : strncpy(p,STARTSTR,MAXBUF);
  558.                        p+=strlen(STARTSTR);
  559.                        break;
  560.  
  561.       default : *(p++)=*line;
  562.     }
  563.  
  564.     line++;
  565.   }
  566.   *p='\0';
  567.   putstr(output);
  568. }
  569.  
  570.  
  571. char *skrunch(line)
  572.   char *line;
  573. {
  574.   char skbuf[LINELEN],*p;
  575.   int  spaces=0;
  576.  
  577.   /* first tokenizes the STARTSTR/XnSTR if in line */
  578.  
  579.   tokenize(line,STARTSTR,STARTCHAR);
  580.  
  581.   /* this is the compaction of >2 spaces */
  582.   p=skbuf;
  583.   while( *line )
  584.   {
  585.     if( *line==' ' )
  586.       spaces++;
  587.     else
  588.     {
  589.       if( spaces )
  590.         if( spaces>2 )
  591.         {
  592.           *(p++)=(char)SKRUNCHAR;
  593.           *(p++)=(char)(spaces+SKRUNOFFS);
  594.           spaces=0;
  595.         }
  596.         else
  597.         {
  598.           *(p++)=' ';
  599.           if( spaces>1 ) *(p++)=' ';
  600.           spaces=0;
  601.         }
  602.  
  603.       *p=*line;
  604.       p++;
  605.     }
  606.     line++;
  607.   }
  608.   *p='\0';
  609.   strncpy(buffer,skbuf,MAXBUF);
  610.   return buffer;
  611. }
  612.  
  613.  
  614. /* will tokenize first occurance of STR in LINE */
  615. tokenize(line,str,chr)
  616.   char *line,*str;
  617.   int  chr;
  618. {
  619.   char *p,*q;
  620.  
  621.   if( p=strstr(line,str,1) )
  622.   {
  623.     q=p+strlen(str);
  624.     *p=(char)chr;
  625.     strncpy(p+1,q,MAXBUF);
  626.     return 1;
  627.   }
  628.   return 0;
  629. }
  630.  
  631.  
  632.  
  633. /* Uses:  chrcount bufcount bufferblock[] bufptr */
  634. /* stores line to memory */
  635. store(buffer)
  636.   char *buffer;
  637. {
  638.   int i;
  639.  
  640.   i=strlen(buffer);
  641.   chrcount+=i;
  642.   if( chrcount>=BLKSIZE )
  643.   {
  644.     *bufptr='\0';
  645.     chrcount=i;
  646.     if( (++bufcount)>=BUFBLKS )
  647.     {
  648.       putstr("Error: DiskList too large (Increase buffer size in source).\n");
  649.       return 1;
  650.     }
  651.  
  652.     if( (bufferblock[bufcount]=(char *)malloc(BLKSIZE) )==NULL)
  653.     {
  654.        putstr(outofmem);
  655.        return 2;
  656.     }
  657.  
  658.     bufptr=bufferblock[bufcount];
  659.   }
  660.  
  661.   strncpy(bufptr,buffer,MAXBUF);
  662.   bufptr+=i;
  663.  
  664.   return 0;
  665. }
  666.  
  667. void init_bufblks()
  668. {
  669.   bufptr=NULL;
  670.   bufcount=-1;
  671.   chrcount=BLKSIZE+1;
  672. }
  673.  
  674. void free_bufblks()
  675. {
  676.   int i;
  677.  
  678.   for(i=1; i<=bufcount; i++)
  679.     free(bufferblock[i]);
  680. }
  681.  
  682.  
  683. /*   OK, this is not quite a true strstr() with case switch.
  684.      The sub string must be in upper case if kase=0 (?!sorry)    */
  685.  
  686. char *strstr(str,sub,kase)
  687.   char *str,*sub;
  688.   int  kase;
  689. {
  690.   int length;
  691.  
  692.   length=strlen(sub);
  693.  
  694.   if( kase )
  695.     str=strchr(str,*sub);
  696.   else
  697.     str=strchr(strtoupper(str),*sub);
  698.  
  699.   while( str )
  700.   {
  701.     if( strncmp(str,sub,length) )
  702.       str++;
  703.     else
  704.       return str;
  705.  
  706.     str=strchr(str,*sub);
  707.   }
  708.  
  709.   return NULL;
  710. }
  711.  
  712. char *strtoupper(s)
  713.   char *s;
  714. {
  715.     register char *p = s;
  716.  
  717.     while(*p)
  718.     {
  719.        *p = toupper(*p);
  720.        p++;
  721.     }
  722.     return(s);
  723. }
  724.  
  725. void get_dlpath()
  726. {
  727.   struct FileLock *lock,*Lock();
  728.  
  729.   if( lock=Lock(dltemp,(long)ACCESS_READ) )
  730.   {
  731.     dlpath=dltemp;
  732.     UnLock(lock);
  733.   }
  734.   else
  735.     dlpath=dldisk;
  736. }
  737.  
  738. struct FileHandle *opendl(mode)
  739.   long mode;
  740. {
  741.   struct FileHandle *fdl;
  742.  
  743.   if( (fdl=Open(dlpath,mode))==NULL)
  744.   {
  745.     putstr("Error: Could not open DiskList\n");
  746.     return 0;
  747.   }
  748.   return fdl;
  749. }
  750.  
  751.  
  752. #define MODE_APPEND 1000L
  753.  
  754. struct FileHandle *opentmp(mode)
  755.   long mode;
  756. {
  757.   struct FileHandle *ftmp;
  758.   struct FileLock *lock,*Lock();
  759.   int    seek=0;
  760.  
  761.   if( mode==MODE_APPEND)
  762.   {
  763.     if( lock=Lock(tempdl,(long)ACCESS_READ) )
  764.     {
  765.       UnLock(lock);
  766.       mode=(long)MODE_OLDFILE;
  767.       seek=1;
  768.     }
  769.     else
  770.       mode=(long)MODE_NEWFILE;
  771.   }
  772.  
  773.   if( (ftmp=Open(tempdl,mode))==NULL)
  774.   {
  775.     putstr("Error: Could not open RAM:TempDL\n");
  776.     return 0;
  777.   }
  778.  
  779.   if( seek )
  780.     Seek(ftmp,0L,(long)OFFSET_END);
  781.  
  782.   return ftmp;
  783. }
  784.  
  785.  
  786. sdir(recur)
  787.   int recur;
  788. {
  789.   char *p;
  790.  
  791.  
  792.   if( glargc>2 )
  793.     p=glargv[2];
  794.   else
  795.     p=sdir_pat;
  796.  
  797.   if( !(ftmp=opentmp(MODE_APPEND)) )
  798.     return 1;
  799.  
  800.   if( do_ls(p,ftmp,recur) )
  801.   {
  802.     Close(ftmp);
  803.     return 2;
  804.   }
  805.   Close(ftmp);
  806.   return 0;
  807. }
  808.  
  809.  
  810. #define ls_cleanup(x) { ls_free(lock,f_info); return x; }
  811.  
  812. do_ls(pat,fh,recur)
  813.   char *pat;
  814.   struct FileHandle *fh;
  815.   int recur;
  816. {
  817.   struct FileLock *lock=NULL, *Lock();
  818.   struct FileInfoBlock *f_info;
  819.  
  820.   char *s, *tempstr;
  821.   int  slen, isadir, col, patchg=0, firstrun=1;
  822.   char *spaces1, *spaces2;
  823.   struct disk *nextdir;
  824.   char basename[80], tempname[80];
  825.  
  826.  
  827.   /* strings of 18 & 36 spaces for formatting output */
  828.   /*       012345678901234567                        */
  829.   spaces1="                  ";
  830.   /*       0123456789012345678901234567890123456     */
  831.   spaces2="                                     ";
  832.  
  833.   INIT_DISKNAMES;
  834.   nextdir=NULL;
  835.  
  836.   strncpy(tempname,"/",2);
  837.   tempstr=tempname+1;
  838.  
  839.   if((f_info=(struct FileInfoBlock *)
  840.      AllocMem((long)sizeof(struct FileInfoBlock),0L))==0)
  841.   {
  842.     putstr(outofmem);
  843.     FREE_DISKNAMES;
  844.     return 1;
  845.   }
  846.  
  847.   do
  848.   {
  849.     if( firstdisk )
  850.     {
  851.  
  852.       while( *(nextdir->name)=='/' )
  853.       {
  854.         strncpy(basename,(nextdir->name)+1,79);
  855.         strncpy(basename+strlen(basename),"/",2);
  856.         nextdir=nextdir->next;
  857.         if( !nextdir )
  858.           ls_cleanup(0)
  859.       }
  860.       strncpy(tempname+1,basename,78);
  861.       slen=strlen(tempname);
  862.       strncpy(tempname+slen,nextdir->name,79-slen);
  863.       if( storename(tempname) )
  864.         ls_cleanup(1);
  865.       pat=tempname+1;
  866.     }
  867.  
  868.     do
  869.     {
  870.       if( firstrun )
  871.       {
  872.         if(patchg==1)
  873.         {
  874.           patchg=2;
  875.           strncpy(tempstr,f_info->fib_FileName,78);
  876.           slen=strlen(tempstr);
  877.           tempstr[slen]=':';
  878.           strncpy(tempstr+slen+1,s+4,78-slen);
  879.           pat=tempstr;
  880.         }
  881.         else if( strchr(pat,':')<strchr(pat,'\0')-1 )
  882.         {
  883.           patchg=2;
  884.           if( !(strncmp(pat,"df0:",4) && strncmp(pat,"df1:",4)) )
  885.           {
  886.             patchg=1;
  887.             strncpy(tempstr,pat,4);
  888.             *(tempstr+4)='\0';
  889.             s=pat;
  890.             pat=tempstr;
  891.           }
  892.         }
  893.       }
  894.  
  895.       if((lock=Lock(pat,(long)ACCESS_READ))==0)
  896.         ls_cleanup(2)
  897.  
  898.       if((Examine(lock,f_info))==0)
  899.         ls_cleanup(3)
  900.     }
  901.     while( patchg==1 );
  902.     firstrun=0;
  903.  
  904.     if( fputstr(STARTSTR,fh) )
  905.       ls_cleanup(4)
  906.     if( firstdisk )
  907.     {
  908.       fputstr(tempname+1,fh);
  909.       fputstr ("\n",fh);
  910.     }
  911.     else
  912.     {
  913.       if( patchg )
  914.       {
  915.         patchg=0;
  916.         if( fputstr(pat,fh) )
  917.           ls_cleanup(5)
  918.         fputstr ("\n",fh);
  919.         strcpy(basename,pat,79);
  920.         slen=strlen(basename);
  921.         basename[slen++]='/';
  922.         basename[slen]='\0';
  923.  
  924.       }
  925.       else
  926.       {
  927.         if( fputstr(f_info->fib_FileName,fh) )
  928.           ls_cleanup(6)
  929.         fputstr (":\n",fh);
  930.         strncpy(basename,f_info->fib_FileName,78);
  931.         slen=strlen(basename);
  932.         basename[slen++]=':';
  933.         basename[slen]='\0';
  934.       }
  935.     }
  936.     col=0;
  937.  
  938.     while( (ExNext(lock,f_info))!=0)
  939.     {
  940.       s=f_info->fib_FileName;
  941.       slen=strlen(s);
  942.       isadir= (f_info->fib_DirEntryType>0);
  943.  
  944.       if((col == 3) && slen >18) {
  945.            fputstr("\n",fh);
  946.            col = 0;
  947.       }
  948.  
  949.       if (isadir)
  950.         fputstr ("\033[33m ",fh);
  951.       else
  952.         fputstr (" ",fh);
  953.  
  954.       if (slen >18) {
  955.          if( fputstr(s,fh) )
  956.            ls_cleanup(7)
  957.          col += 2;
  958.          if( fputstr(spaces2+slen,fh) )
  959.            ls_cleanup(8)
  960.       }
  961.       else {
  962.          if( fputstr(s,fh) )
  963.            ls_cleanup(9)
  964.          if( fputstr(spaces1+slen,fh) )
  965.            ls_cleanup(10)
  966.          col++;
  967.       }
  968.  
  969.       if( isadir && recur )
  970.         if(storename(s))
  971.           ls_cleanup(1);
  972.  
  973.       if (isadir)
  974.         fputstr("\033[0m",fh);
  975.  
  976.       if (col > 3) {
  977.          fputstr("\n",fh);
  978.          col = 0;
  979.       }
  980.  
  981.     }
  982.     fputstr("\n",fh);
  983.     if( col )
  984.       fputstr("\n",fh);
  985.  
  986.     UnLock(lock);
  987.     lock=NULL;
  988.  
  989.     if( nextdir )
  990.       nextdir=nextdir->next;
  991.     else
  992.       nextdir=firstdisk;
  993.   }
  994.   while( nextdir );
  995.  
  996.   ls_free(lock,f_info);
  997.   return 0;
  998. }
  999.  
  1000. void ls_free(lock,f_info)
  1001.   struct FileLock *lock;
  1002.   struct FileInfoBlock *f_info;
  1003.  
  1004. {
  1005.   if( lock )
  1006.     UnLock(lock);
  1007.   FreeMem(f_info,(long)sizeof(struct FileInfoBlock));
  1008.   FREE_DISKNAMES;
  1009. }
  1010.  
  1011. void putstr(str)
  1012.   char *str;
  1013. {
  1014.     Write(confh,str,(long)strlen(str));
  1015. }
  1016.  
  1017.  
  1018. fputstr(str,fh)
  1019.   char *str;
  1020.   struct FileHandle *fh;
  1021. {
  1022.    long len;
  1023.    len=(long)strlen(str);
  1024.    if( Write(fh,str,len)==len)
  1025.      return 0;
  1026.    return 1;
  1027. }
  1028.  
  1029. /* must be used in the WHILE( GETSTR()!=NULL) fashion */
  1030. char *getstr(line,f)
  1031.   char *line;
  1032.   struct FileHandle *f;
  1033. {
  1034.   static char *buffer, *bufptr;
  1035.   static int  last_read;
  1036.   int len, n=MAXBUF;
  1037.   char temp, *p, empty='\0';
  1038.  
  1039.   if( !buffer )
  1040.   {
  1041.     if( (buffer=(char *)AllocMem((long)CP_BUFF+1,0L))==0)
  1042.     {
  1043.        putstr(outofmem);
  1044.        fcnerr=1;
  1045.        return (char *)0;
  1046.     }
  1047.     bufptr=∅
  1048.   }
  1049.  
  1050.   while(1)
  1051.     if( p=strchr(bufptr,'\n') )
  1052.     {
  1053.       temp=*(++p);
  1054.       *p='\0';
  1055.       strncpy(line,bufptr,n);
  1056.       *p=temp;
  1057.       bufptr=p;
  1058.       return line;
  1059.     }
  1060.     else
  1061.     {
  1062.       strncpy(line,bufptr,n);
  1063.       len=strlen(line);
  1064.       n-=len;
  1065.       line+=len;
  1066.  
  1067.       if( last_read )
  1068.       {
  1069.         FreeMem(buffer,CP_BUFF);
  1070.         buffer=0;
  1071.         last_read=0;
  1072.         return (char *)0;
  1073.       }
  1074.       else
  1075.         if( (len=Read(f,buffer,CP_BUFF)) <1 )
  1076.           last_read=1;
  1077.         else
  1078.         {
  1079.           last_read= len!=CP_BUFF;
  1080.           bufptr=buffer;
  1081.           *(buffer+len)='\0';
  1082.         }
  1083.     }
  1084. }
  1085.  
  1086. savedl()
  1087. {
  1088.   if( update() )
  1089.     return 1;
  1090.  
  1091.   if( strcmp(dlpath,dldisk) )
  1092.   {
  1093.     if( copy(dlpath,dldisk) )
  1094.       return 1;
  1095.     DeleteFile(dlpath);
  1096.     DeleteFile(tempdl);
  1097.   }
  1098.   return 0;
  1099. }
  1100.  
  1101. loaddl()
  1102. {
  1103.   if( strcmp(dltemp,dlpath) )
  1104.     if( copy(dlpath,dltemp) )
  1105.       return 1;
  1106.   return 0;
  1107. }
  1108.  
  1109. newdl()
  1110. {
  1111.   struct FileHandle *fh;
  1112.  
  1113.   putstr("Are you sure? ");
  1114.   Read(confh,buffer,LINELEN);
  1115.  
  1116.   if( *buffer=='y' )
  1117.   {
  1118.     if( fh=Open(dlpath,(long)MODE_NEWFILE) )
  1119.     {
  1120.       Close(fh);
  1121.       return 0;
  1122.     }
  1123.     return 1;
  1124.   }
  1125.   return 0;
  1126. }
  1127.  
  1128. copy(src,dest)
  1129.   char *src,*dest;
  1130. {
  1131.   struct FileHandle *sfh,*dfh;
  1132.   char *buffer;
  1133.   int  len;
  1134.  
  1135.   if((sfh=Open(src,(long)MODE_OLDFILE))==0)
  1136.     return 1;
  1137.  
  1138.   if((dfh=Open(dest,(long)MODE_NEWFILE))==0)
  1139.   {
  1140.     Close(sfh);
  1141.     return 2;
  1142.   }
  1143.   if( (buffer=(char *)AllocMem(CP_BUFF,0L))==0)
  1144.   {
  1145.     Close(sfh);
  1146.     Close(dfh);
  1147.     putstr(outofmem);
  1148.     return 3;
  1149.   }
  1150.  
  1151.   do
  1152.   {
  1153.     len=Read(sfh,buffer,CP_BUFF);
  1154.     Write(dfh,buffer,(long)len);
  1155.   }
  1156.   while( len!=0 );
  1157.  
  1158.   FreeMem(buffer,CP_BUFF);
  1159.  
  1160.   Close(sfh);
  1161.   Close(dfh);
  1162.   return 0;
  1163. }
  1164.  
  1165.  
  1166.  
  1167.  
  1168.