home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 488.lha / csh_v5.0 / src / csh500src.lzh / sub.c < prev   
C/C++ Source or Header  |  1991-02-23  |  21KB  |  1,079 lines

  1.  
  2. /*
  3.  * SUB.C
  4.  *
  5.  * (c)1986 Matthew Dillon     9 October 1986
  6.  *
  7.  * Version 2.07M by Steve Drew 10-Sep-87
  8.  * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  9.  * Version 5.00L by Urban Mueller 17-Feb-91
  10.  *
  11.  */
  12.  
  13. #include "shell.h"
  14. #include "proto.h"
  15.  
  16. static void del_history( void );
  17. static int hasspace( char *s );
  18. static int dnext( struct DPTR *dp, char **pname, int *stat);
  19. static char *svfile( char *s1, char *s2, FIB *fib);
  20. static int exall( BPTR lock, char *path );
  21. static void quicksort( char **av, int n );
  22.  
  23.  
  24. #define HM_STR 0              /* various HISTORY retrieval modes */
  25. #define HM_REL 1
  26. #define HM_ABS 2
  27.  
  28. void
  29. seterr( void )
  30. {
  31.     char buf[32], *val;
  32.     int stat=0;
  33.  
  34.     sprintf(buf, "%d", Lastresult);
  35.     set_var(LEVEL_SET, v_lasterr, buf);
  36.     if( val=get_var(LEVEL_SET, v_stat))
  37.         stat = atoi(val);
  38.     if (stat < Lastresult) set_var(LEVEL_SET, v_stat, buf);
  39. }
  40.  
  41. #define ISSPACE(c) ((c)==' ' || (c)==9 || (c)==0xA0)
  42.  
  43. char *
  44. next_word( char *str )
  45. {
  46.     while (*str && ! ISSPACE(*str)) ++str;
  47.     while (*str &&   ISSPACE(*str)) ++str;
  48.     return str;
  49. }
  50.  
  51. static int
  52. hasspace( char *s )
  53. {
  54.     for ( ; *s; s++)
  55.         if (ISSPACE(*s)) return 1;
  56.     return 0;
  57. }
  58.  
  59. char *
  60. compile_av(char **av, int start, int end, char delim, int quote)
  61. {
  62.     char *cstr, *p;
  63.     int len, i;
  64.  
  65.     len = 1;
  66.     for (i = start; i < end; ++i) len += strlen(av[i]) + 3;
  67.     p = cstr = malloc(len);
  68.     *cstr = '\0';
  69.     for (i = start; i < end; ++i) {
  70.         if (debug) fprintf (stderr, "AV[%2d] :%s:\n", i, av[i]);
  71.         if (quote && hasspace(av[i]))
  72.             p += sprintf(p, "\"%s\"", av[i]);
  73.         else
  74.             p += sprintf(p, "%s",     av[i]);
  75.         if (i+1 < end) *p++=delim;
  76.     }
  77.     *p='\0';
  78.     return cstr;
  79. }
  80.  
  81. /*
  82.  * FREE(ptr)   --frees without actually freeing, so the data is still good
  83.  *               immediately after the free.
  84.  */
  85.  
  86.  
  87. void
  88. Free( void *ptr )
  89. {
  90.     static char *old_ptr;
  91.  
  92.     if (old_ptr) free (old_ptr);
  93.     old_ptr = ptr;
  94. }
  95.  
  96. /*
  97.  * Add new string to history (H_head, H_tail, H_len,
  98.  *  S_histlen
  99.  */
  100.  
  101. void
  102. add_history( char *str )
  103. {
  104.     struct HIST *hist;
  105.     char *get;
  106.  
  107.     for( get=str; *get; get++ )
  108.         if( (*get&127)<' ')
  109.             *get=' ';
  110.  
  111.     if (H_head != NULL && !strcmp(H_head->line, str))
  112.         return;
  113.     while (H_len > S_histlen)
  114.         del_history();
  115.     hist = (struct HIST *)malloc (sizeof(struct HIST));
  116.     if (H_head == NULL) {
  117.         H_head = H_tail = hist;
  118.         hist->next = NULL;
  119.     } else {
  120.         hist->next = H_head;
  121.         H_head->prev = hist;
  122.         H_head = hist;
  123.     }
  124.     hist->prev = NULL;
  125.     hist->line = malloc (strlen(str) + 1);
  126.     strcpy (hist->line, str);
  127.     ++H_len;
  128. }
  129.  
  130. static void
  131. del_history()
  132. {
  133.     if (H_tail) {
  134.         --H_len;
  135.         ++H_tail_base;
  136.         free (H_tail->line);
  137.         if (H_tail->prev) {
  138.             H_tail = H_tail->prev;
  139.             free (H_tail->next);
  140.         H_tail->next = NULL;
  141.         } else {
  142.             free (H_tail);
  143.             H_tail = H_head = NULL;
  144.         }
  145.     }
  146. }
  147.  
  148. char *
  149. get_history( char *ptr, int echo )
  150. {
  151.     struct HIST *hist;
  152.     int len;
  153.     int mode = HM_REL;
  154.     int num  = 1;
  155.     char *str;
  156.     char *result = NULL;
  157.  
  158.     if (ptr[1] >= '0' && ptr[1] <= '9') {
  159.         mode = HM_ABS;
  160.         num  = atoi(&ptr[1]);
  161.         goto skip;
  162.     }
  163.     switch (ptr[1]) {
  164.     case '!':
  165.         break;
  166.     case '-':
  167.         num += atoi(&ptr[2]);
  168.         break;
  169.     default:
  170.         mode = HM_STR;
  171.         str  = ptr + 1;
  172.         break;
  173.     }
  174. skip:
  175.     switch (mode) {
  176.     case HM_STR:
  177.         len = strlen(str);
  178.         for (hist = H_head; hist; hist = hist->next) {
  179.             if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
  180.                 result = hist->line;
  181.                 break;
  182.             }
  183.         }
  184.         break;
  185.     case HM_REL:
  186.         for (hist = H_head; hist && num--; hist = hist->next);
  187.         if (hist)
  188.         result = hist->line;
  189.         break;
  190.     case HM_ABS:
  191.         len = H_tail_base;
  192.         for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
  193.         if (hist)
  194.         result = hist->line;
  195.         break;
  196.     }
  197.     if( echo )
  198.         fprintf(stderr, result ? "%s\n" : "History failed\n", result);
  199.     if( !result ) result="";
  200.     return result;
  201. }
  202.  
  203. void
  204. replace_head( char *str )
  205. {
  206.     if (str && strlen(str) && H_head) {
  207.         free (H_head->line);
  208.         H_head->line = malloc (strlen(str)+1);
  209.         strcpy (H_head->line, str);
  210.     }
  211. }
  212.  
  213.  
  214. #if 0
  215. #define CDLEN 20
  216. static int   cd_len=CDLEN, cd_read, cd_write, cd_current;
  217. static char *cd_hist[CDLEN];
  218.  
  219. add_cdhist( char *str )
  220. {
  221.     if( !str )
  222.         return;
  223.     if( cd_hist[cd_write] )
  224.         free(cd_hist[cd_write]);
  225.     cd_hist[cd_write++]=str;
  226.     cd_write%=cd_len;
  227.     cd_current=cd_write;
  228. }
  229.  
  230. char *
  231. back_cdhist( void )
  232. {
  233.     if( cd_current!=cd_write ) cd_current= --cd_current % cd_len;
  234.     return cd_hist[cd_current];
  235. }
  236.  
  237. char *
  238. forw_cdhist( void )
  239. {
  240.     if( cd_current!=cd_read  ) cd_current= ++cd_current % cd_len;
  241.     return cd_hist[cd_current];
  242. }
  243. #endif
  244.  
  245. void
  246. pError(char *str )
  247. {
  248.     int ierr = (long)IoErr();
  249.     ierror(str, ierr);
  250. }
  251.  
  252. ierror( char *str, int err )
  253. {
  254.     struct PERROR *per = Perror;
  255.  
  256.     if (err) {
  257.         for (; per->errstr; ++per) {
  258.             if (per->errnum == err) {
  259.                 fprintf (stderr, "%s%s%s\n",
  260.                 per->errstr,
  261.                 (str) ? ": " : "",
  262.                 (str) ? str : "");
  263.                 return err;
  264.             }
  265.         }
  266.         fprintf (stderr, "Unknown DOS error %d %s\n", err, (str) ? str : "");
  267.     }
  268.     return err;
  269. }
  270.  
  271. /*
  272.  * Disk directory routines
  273.  *
  274.  * dptr = dopen(name, stat)
  275.  *    struct DPTR *dptr;
  276.  *    char *name;
  277.  *    int *stat;
  278.  *
  279.  * dnext(dptr, name, stat)
  280.  *    struct DPTR *dptr;
  281.  *    char **name;
  282.  *    int  *stat;
  283.  *
  284.  * dclose(dptr)                  -may be called with NULL without harm
  285.  *
  286.  * dopen() returns a struct DPTR, or NULL if the given file does not
  287.  * exist.  stat will be set to 1 if the file is a directory.  If the
  288.  * name is "", then the current directory is openned.
  289.  *
  290.  * dnext() returns 1 until there are no more entries.  The **name and
  291.  * *stat are set.  *stat = 1 if the file is a directory.
  292.  *
  293.  * dclose() closes a directory channel.
  294.  *
  295.  */
  296.  
  297. extern long IoError;
  298.  
  299. struct DPTR *
  300. dopen( char *name, int *stat)
  301. {
  302.     struct DPTR *dp;
  303.  
  304.     *stat = 0;
  305.     dp = (struct DPTR *)malloc(sizeof(struct DPTR));
  306.     if (*name == '\0')
  307.         dp->lock = DupLock(Myprocess->pr_CurrentDir);
  308.     else
  309.         dp->lock = Lock (name,ACCESS_READ);
  310.     if (dp->lock == NULL) {
  311.         IoError=IoErr();
  312.         free (dp);
  313.         return NULL;
  314.     }
  315.     dp->fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
  316.     if (!Examine (dp->lock, dp->fib)) {
  317.         pError (name);
  318.         dclose (dp);
  319.         return NULL;
  320.     }
  321.     if (dp->fib->fib_DirEntryType >= 0) *stat = 1;
  322.     return dp;
  323. }
  324.  
  325. static int
  326. dnext( struct DPTR *dp, char **pname, int *stat)
  327. {
  328.     if (dp == NULL) return (0);
  329.         if (ExNext (dp->lock, dp->fib)) {
  330.             *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
  331.             *pname = dp->fib->fib_FileName;
  332.             return 1;
  333.         }
  334.     return 0;
  335. }
  336.  
  337. int
  338. dclose( struct DPTR *dp )
  339. {
  340.     if (dp == NULL)
  341.         return 1;
  342.     if (dp->fib)
  343.         FreeMem (dp->fib,(long)sizeof(*dp->fib));
  344.     if (dp->lock)
  345.         UnLock (dp->lock);
  346.     free (dp);
  347.     return 1;
  348. }
  349.  
  350.  
  351. int
  352. isdir( char *file )
  353. {
  354.     struct DPTR *dp;
  355.     int stat;
  356.  
  357.     stat = 0;
  358.     if (dp = dopen (file, &stat))
  359.         dclose(dp);
  360.     return (stat == 1);
  361. }
  362.  
  363.  
  364. void
  365. free_expand( char **av )
  366. {
  367.     char **get = av;
  368.  
  369.     if (av) {
  370.         while (*get)
  371.         free (*get++-sizeof(struct file_info));
  372.         free (av);
  373.     }
  374. }
  375.  
  376. /*
  377.  * EXPAND(base,pac)
  378.  *    base           - char * (example: "df0:*.c")
  379.  *    pac            - int  *  will be set to # of arguments.
  380.  *
  381.  * 22-May-87 SJD.  Heavily modified to allow recursive wild carding and
  382.  *                 simple directory/file lookups. Returns a pointer to
  383.  *                 an array of pointers that contains the full file spec
  384.  *                 eg. 'df0:c/sear*' would result in : 'df0:C/Search'
  385.  *
  386.  *                 Now no longer necessary to Examine the files a second time
  387.  *                 in do_dir since expand will return the full file info
  388.  *                 appended to the file name. Set by formatfile().
  389.  *                 eg. fullfilename'\0'rwed  NNNNNN NNNN  DD-MMM-YY HH:MM:SS
  390.  *
  391.  *                 Caller must call free_expand when done with the array.
  392.  *
  393.  * base             bname =       ename =
  394.  * ------           -------       -------
  395.  *  "*"               ""            "*"
  396.  *  "!*.info"         ""            "*.info" (wild_exclude set)
  397.  *  "su*d/*"          ""            "*"      (tail set)
  398.  *  "file.*"          ""            "file.*"
  399.  *  "df0:c/*"         "df0:c"       "*"
  400.  *  ""                ""            "*"
  401.  *  "df0:.../*"       "df0:"        "*"      (recur set)
  402.  *  "df0:sub/.../*"   "df0:sub"     "*"      (recur set)
  403.  *
  404.  * ---the above base would be provided by execom.c or do_dir().
  405.  * ---the below base would only be called from do_dir().
  406.  *
  407.  *  "file.c"          "file.c"      ""       if (dp == 0) fail else get file.c
  408.  *  "df0:"            "df0:"        "*"
  409.  *  "file/file"       "file/file"   ""       (dp == 0) so fail
  410.  *  "df0:.../"        "df0:"        "*"      (recur set)
  411.  *
  412.  */
  413.  
  414. int expand_err;
  415.  
  416. char **
  417. expand( char *base, int *pac )
  418. {
  419.     char *ptr;
  420.     char **eav = (char **)malloc(sizeof(char *) * (2));
  421.     short eleft, eac;
  422.     char *name;
  423.     char *bname, *ename, *tail;
  424.     int stat, recur, scr, bl;
  425.     struct DPTR *dp;
  426.  
  427.     expand_err = *pac = recur = eleft = eac = 0;
  428.  
  429.     base = strcpy(malloc(strlen(base)+1), base);
  430.     for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
  431.  
  432.     if (!*ptr)   /* no wild cards */
  433.         --ptr;
  434.     else
  435.         for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
  436.  
  437.     if (ptr < base) {
  438.         bname = strcpy (malloc(1), "");
  439.     } else {
  440.         scr = ptr[1];
  441.         ptr[1] = '\0';
  442.         if (!strcmp(ptr-3,".../")) {
  443.             recur = 1;
  444.             *(ptr-3) = '\0';
  445.         }
  446.         bname = strcpy (malloc(strlen(base)+2), base);
  447.         ptr[1] = scr;
  448.     }
  449.     bl = strlen(bname);
  450.     ename = ++ptr;
  451.     for (; *ptr && *ptr != '/'; ++ptr);
  452.     scr = *ptr;
  453.     *ptr = '\0';
  454.     if (scr) ++ptr;
  455.     tail = ptr;
  456.  
  457.     if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) {
  458.         free (bname);
  459.         free (base);
  460.         free (eav);
  461.         expand_err=1;
  462.         return (NULL);
  463.     }
  464.  
  465.     if (!stat) {                /* eg. 'dir file' */
  466.         char *p,*s;
  467.         for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p;
  468.         if (s != bname) ++s;
  469.         *s ='\0';
  470.         eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib);
  471.         goto done;
  472.     }
  473.     if (!*ename) ename = "*";    /* eg. dir df0: */
  474.     if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */
  475.         bname[bl] = '/';
  476.         bname[++bl] = '\0';
  477.     }
  478.     while ((dnext (dp, &name, &stat)) && !breakcheck()) {
  479.         int match = compare_ok(ename,name,0);
  480.         if (match && !(!recur && *tail)) {
  481.             if (eleft < 2) {
  482.                 char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  483.                 memmove (scrav, eav, (eac + 1) << 2);
  484.                 free (eav);
  485.                 eav = scrav;
  486.                 eleft = 10;
  487.             }
  488.             eav[eac++] = svfile(bname,name,dp->fib);
  489.             --eleft;
  490.         }
  491.         if ((*tail && match) || recur) {
  492.             int alt_ac;
  493.             char *search, **alt_av, **scrav;
  494.             BPTR lock;
  495.  
  496.             if (!stat)           /* expect more dirs, but this not a dir */
  497.                 continue;
  498.             lock = CurrentDir (dp->lock);
  499.             search = malloc(strlen(ename)+strlen(name)+strlen(tail)+6);
  500.             strcpy (search, name);
  501.             strcat (search, "/");
  502.             if (recur) {
  503.                 strcat(search, ".../");
  504.                 strcat(search, ename);
  505.             }
  506.             strcat (search, tail);
  507.             scrav = alt_av = expand (search, &alt_ac);
  508.             free(search);
  509.             CurrentDir (lock);
  510.             if (scrav) {
  511.                 while (*scrav) {
  512.                     int l;
  513.                     if (eleft < 2) {
  514.                         char **scrav = (char **)malloc(sizeof(char *)*(eac+10));
  515.                         memmove ( scrav, eav, (eac + 1) << 2);
  516.                         free (eav);
  517.                         eav = scrav;
  518.                         eleft = 10;
  519.                     }
  520.  
  521.                     l = strlen(*scrav);
  522.                     eav[eac] = malloc(bl+l+1+sizeof(struct file_info));
  523.                     memcpy( eav[eac], *scrav-sizeof(struct file_info),
  524.                     sizeof(struct file_info));
  525.                     eav[eac]+=sizeof(struct file_info);
  526.                     strcpy( eav[eac], bname);
  527.                     strcat( eav[eac], *scrav);
  528.  
  529.                     free (*scrav-sizeof(struct file_info));
  530.                     ++scrav;
  531.                     --eleft, ++eac;
  532.                 }
  533.                 free (alt_av);
  534.             }
  535.         }
  536.     }
  537. done:
  538.     dclose (dp);
  539.     *pac = eac;
  540.     eav[eac] = NULL;
  541.     free (bname);
  542.     free (base);
  543.     if (eac)
  544.         return (eav);
  545.     free (eav);
  546.     return (NULL);
  547. }
  548.  
  549. char *
  550. strupr( char *s )
  551. {
  552.     char *old=s;
  553.     while (*s) *s=toupper(*s), s++;
  554.     return old;
  555. }
  556.  
  557. char *
  558. strlwr( char *s )
  559. {
  560.     char *old=s;
  561.     while (*s) *s=tolower(*s), s++;
  562.     return old;
  563. }
  564.  
  565. /*
  566.  * Compare a wild card name with a normal name
  567.  */
  568.  
  569. int
  570. compare_ok( char *wild, char *name, int casedep)
  571. {
  572.     int queryflag;
  573.     char buf[260], wildbuf[260], *lowname;
  574.  
  575.     if (queryflag=(*wild=='&')) wild++;
  576.     if (*wild=='!') *wild='~';
  577.  
  578.     if (! casedep) {
  579.         strupr(wild);
  580.         strcpy(buf,name);
  581.         strupr(buf);
  582.         lowname=buf;
  583.     } else
  584.         lowname=name;
  585.  
  586.     PreParse(wild, wildbuf);
  587.     if ( ! PatternMatch(wildbuf,lowname)) return 0;
  588.  
  589.     if (queryflag) {
  590.         printf("Select %s%-16s%s [y/n] ? ",o_hilite,name,o_lolite);
  591.         gets(buf);
  592.         return (toupper(*buf)=='Y');
  593.     }
  594.     return 1;
  595. }
  596.  
  597. static char *
  598. svfile( char *s1, char *s2, FIB *fib)
  599. {
  600.     int len=strlen(s1)+strlen(s2)+1;
  601.     char *p = malloc (len+sizeof(struct file_info));
  602.     struct file_info *info;
  603.  
  604.     info=(struct file_info *)p;
  605.     p+=sizeof(struct file_info);
  606.     strcpy(p, s1);
  607.     strcat(p, s2);
  608.     info->flags = fib->fib_Protection;
  609.     if( fib->fib_DirEntryType<0 ) {
  610.         info->size  = fib->fib_Size;
  611.         info->blocks= fib->fib_NumBlocks;
  612.     } else {
  613.         info->size  = -1;
  614.         info->blocks= 0;
  615.     }
  616.     if( fib->fib_Comment[0] )
  617.         info->flags|= 1<<30;
  618.     info->date=fib->fib_Date;
  619.     info->class[0]=1;
  620.     return p;
  621. }
  622.  
  623.  
  624.  
  625. static FILE *out;
  626. static int NumDirs;
  627.  
  628. void
  629. expand_all( char *name, FILE *file )
  630. {
  631.     BPTR lock;
  632.     char path[300];
  633.     FIB  *fib;
  634.  
  635.     out=file;
  636.     printf( " %s\n", name );
  637.     NumDirs=0;
  638.  
  639.     if(fib=AllocMem(sizeof(struct FileInfoBlock),0)) {
  640.         if( lock=Lock( name, ACCESS_READ )) {
  641.             strcpy( path, name );
  642.             exall( lock, path );
  643.             printf( "\n", NumDirs );
  644.         }
  645.         FreeMem(fib,sizeof(struct FileInfoBlock));
  646.     }
  647. }
  648.  
  649. static int
  650. exall( BPTR lock, char *path )
  651. {
  652.     BPTR old, sublock;
  653.     int len;
  654.     struct FileInfoBlock *fib;
  655.  
  656.     old=CurrentDir( lock );
  657.  
  658.     if( !(fib=AllocMem(sizeof(struct FileInfoBlock),0)) )
  659.         return 1;
  660.  
  661.     len=strlen( path );
  662.     Examine( lock, fib );
  663.     while( ExNext( lock, fib ) ) {
  664.         if( fib->fib_DirEntryType>=0 )
  665.             if( sublock=Lock( fib->fib_FileName, ACCESS_READ )) {
  666.                 if( !len || path[len-1]==':' )
  667.                     sprintf(path+len,"%s",  fib->fib_FileName);
  668.                 else 
  669.                     sprintf(path+len,"/%s", fib->fib_FileName);
  670.                 fprintf( out, "%s\n", path );
  671.                 fprintf( stdout, " Directories: %d\015", ++NumDirs );
  672.                 fflush ( stdout );
  673.                 if(exall( sublock, path ))
  674.                     break;
  675.                 path[len]=0;
  676.             }
  677.     }
  678.     FreeMem( fib, sizeof(struct FileInfoBlock));
  679.     CurrentDir( old );
  680.     return dobreak();
  681. }
  682.  
  683.  
  684.  
  685. /* Sort routines */
  686.  
  687. int reverse;
  688.  
  689. int
  690. cmp( char *s1, char *s2)
  691. {
  692.     int r=Strcmp(s1, s2);
  693.     return reverse ? -r : r;
  694. }
  695.  
  696. int
  697. sizecmp( char *s1, char *s2)
  698. {
  699.     int r= ((struct file_info *)(s2-sizeof(struct file_info)))->size -
  700.            ((struct file_info *)(s1-sizeof(struct file_info)))->size;
  701.     return reverse ? -r : r;
  702. }
  703.  
  704. int
  705. datecmp( char *s1, char *s2 )
  706. {
  707.     int r;
  708.     struct DateStamp
  709.       *d1=&((struct file_info *)(s1-sizeof(struct file_info)))->date,
  710.       *d2=&((struct file_info *)(s2-sizeof(struct file_info)))->date;
  711.     if( !(r= d2->ds_Days - d1->ds_Days))
  712.         if( !(r=d2->ds_Minute - d1->ds_Minute ) )
  713.             r=d2->ds_Tick - d1->ds_Tick;
  714.     return reverse ? -r : r;
  715. }
  716.  
  717.  
  718. static void
  719. enterclass( FILEINFO *info )
  720. {
  721.     char *class, *iclass=info->class, *t;
  722.  
  723.     if( *iclass==1 ) {
  724.         if( class=getclass( (char *)(info+1))) {
  725.             strncpy( iclass, class, 11 );
  726.             iclass[11]=0;
  727.             if( t=index(iclass,0xA0))
  728.                 *t=0;
  729.         } else 
  730.             iclass[0]=0;
  731.     }
  732. }
  733.  
  734. int
  735. classcmp( char *s1, char *s2 )
  736. {
  737.     int r;
  738.     FILEINFO *info1=(FILEINFO *)s1-1, *info2=(FILEINFO *)s2-1;
  739.  
  740.     enterclass( info1 );
  741.     enterclass( info2 );
  742.  
  743.     r= Strcmp( info1->class, info2->class );
  744.     if( !r ) r=Strcmp(s1, s2);
  745.     return reverse ? -r : r;
  746. }
  747.  
  748.  
  749. void
  750. QuickSort( char *av[], int n)
  751. {
  752.     DirQuickSort( av, n, cmp, 0 );
  753. }
  754.  
  755. static int (*compare)(char *, char *);
  756.  
  757. void
  758. DirQuickSort( char *av[], int n, int (*func)(char *,char *), int rev)
  759. {
  760.     reverse=rev; compare=func;
  761.     quicksort( av, n-1 );
  762. }
  763.  
  764. static void
  765. quicksort( char **av, int n )
  766. {
  767.     char **i, **j, *x, *t;
  768.  
  769.  
  770.     if( n>0 ) {
  771.         i=av; j=av+n; x=av[ n>>1 ];
  772.         do {
  773.             while( (*compare)(*i,x)<0 ) i++;
  774.             while( (*compare)(x,*j)<0 ) --j;
  775.             if( i<=j )
  776.                 { t=*i; *i=*j; *j=t; i++; j--; }
  777.         } while( i<=j );
  778.  
  779.         if( j-av < av+n-i ) {
  780.             quicksort( av, j-av  );
  781.             quicksort( i , av+n-i);
  782.         } else {
  783.             quicksort( i , av+n-i);
  784.             quicksort( av, j-av  );
  785.         }
  786.     }
  787. }
  788.  
  789.  
  790. int
  791. filesize( char *name )
  792. {
  793.     BPTR lock;
  794.     struct FileInfoBlock *fib;
  795.     int  len=0;
  796.  
  797.     if( lock = Lock (name,ACCESS_READ)) {
  798.         if( fib=(struct FileInfoBlock *)AllocMem(sizeof(*fib),MEMF_PUBLIC)) {
  799.             if (Examine (lock, fib))
  800.                 len=fib->fib_Size;
  801.             FreeMem( fib, sizeof(*fib));
  802.         }
  803.         UnLock(lock);
  804.     }
  805.     return len;
  806. }
  807.  
  808.  
  809. #ifndef MIN
  810. #define MIN(x,y) ((x)<(y)?(x):(y))
  811. #endif
  812.  
  813. char **
  814. and( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
  815. {
  816.     char **av=(char **)malloc(MIN(ac1,ac2)*sizeof(char *) ), *str;
  817.     int i, j, k=0;
  818.  
  819.     for( i=0; i<ac1; i++ )
  820.         for( j=0, str=base ? BaseName(av1[i]) : av1[i]; j<ac2; j++ )
  821.             if( !Strcmp(str, base ? BaseName(av2[j]) : av2[j]))
  822.                 av[k++]=av1[i];
  823.     *ac=k;
  824.     return av;
  825. }
  826.  
  827. char **
  828. without( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
  829. {
  830.     char **av=(char **)malloc(ac1*sizeof(char *) ), *str;
  831.     int i, j, k=0;
  832.  
  833.     for( i=0; i<ac1; i++ ) {
  834.         for( j=0, str=base ? BaseName(av1[i]) : av1[i]; j<ac2; j++ )
  835.             if( !Strcmp(str, base ? BaseName(av2[j]) : av2[j] ) )
  836.                 break;
  837.         if( j==ac2 )
  838.             av[k++]=av1[i];
  839.     }
  840.     *ac=k;
  841.     return av;
  842. }
  843.  
  844. char **
  845. or( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
  846. {
  847.     char **av=(char **)malloc((ac1+ac2)*sizeof(char *) ), *str;
  848.     int i, j, k=0;
  849.  
  850.     for( i=0; i<ac1; i++ )
  851.         av[k++]=av1[i];
  852.  
  853.     for( i=0; i<ac2; i++ ) {
  854.         for( j=0, str=base ? BaseName(av2[i]) : av2[i]; j<ac1; j++ )
  855.             if( !Strcmp(str, base ? BaseName(av1[j]) : av1[j] ) )
  856.                 break;
  857.         if( j==ac1 )
  858.             av[k++]=av2[i];
  859.     }
  860.  
  861.     *ac=k;
  862.     return av;
  863. }
  864.  
  865. void
  866. clear_archive_bit( char *name )
  867. {
  868.     struct DPTR *dp;
  869.     int stat;
  870.  
  871.     if(dp = dopen(name,&stat) ) {
  872.         SetProtection( name, dp->fib->fib_Protection&~FIBF_ARCHIVE);
  873.         dclose( dp );
  874.     }
  875. }
  876.  
  877. char *
  878. itoa( int i )
  879. {
  880.     static char buf[20];
  881.     char *pos=buf+19;
  882.     int count=4, flag=0;
  883.  
  884.     if( i<0 )
  885.         flag=1, i=-i;
  886.  
  887.     do {
  888.         if( !--count )
  889.             count=3, *--pos='\'';
  890.         *--pos= i%10+'0';
  891.     } while( i/=10 );
  892.  
  893.     if( flag )
  894.         *--pos='-';
  895.  
  896.     return pos;
  897. }
  898.  
  899. char *
  900. itok( int i )
  901. {
  902.     static char buf[16], which;
  903.     char *exp=" KMG", *ptr= buf+(which=8-which);
  904.  
  905.     do
  906.         i=(i+512)/1024, exp++;
  907.     while( i>1024 );
  908.     sprintf( ptr,"%d%c",i,*exp);
  909.  
  910.     return ptr;
  911. }
  912.  
  913. char *
  914. next_a0( char *str )
  915. {
  916.     while( *str && *str!=0xA0 && *str!='=' && *str!=',') str++;
  917.     return *str ? str+1 : NULL;
  918. }
  919.  
  920. static int
  921. gethex( char *str, int l )
  922. {
  923.     int i, val=0, n, c;
  924.  
  925.     if( *str=='.' ) return l==2 ? 256 : 0;
  926.  
  927.     for( i=0; i<l || !l; i++ ) {
  928.         c=*str++;
  929.         if     ( c>='0' && c<='9' ) n=c-'0';
  930.         else if( c>='a' && c<='f' ) n=c-'a'+10;
  931.         else if( c>='A' && c<='F' ) n=c-'A'+10;
  932.         else break;;
  933.         val=16*val+n;
  934.     }
  935.     return (l && i!=l) ? -1 : val;
  936. }
  937.  
  938. strwrdcmp( char *str, char *wrd )
  939. {
  940.     int len1=strlen(str);
  941.     char *ind=index(wrd,0xA0);
  942.     if( ind )
  943.         return len1!=ind-wrd || Strncmp(str,wrd,len1);
  944.     else 
  945.         return Strcmp(str,wrd);
  946.  
  947. }
  948.  
  949. int
  950. wrdlen( char *str )
  951. {
  952.     char *old=str;
  953.  
  954.     while( *str && *str!=0xA0 ) str++;
  955.     return str-old;
  956. }
  957.  
  958. char *classfile;
  959.  
  960. char *
  961. getclass(char *file)
  962. {
  963.     CLASS *cl;
  964.     char *class, *str, *arg, *get, *buf;
  965.     int offs, byte, len, fail;
  966.     BPTR fh;
  967.  
  968.     if( classfile ) {
  969.         char buf[80];
  970.         sprintf(buf,"source %s",classfile);
  971.         execute(buf);
  972.         classfile=0;
  973.     }
  974.  
  975.     if( isdir(file) ) return "dir";
  976.  
  977.     if( !(buf=calloc(1024,1))) return NULL;
  978.     if( !(fh=Open(file,MODE_OLDFILE))) return NULL;
  979.     len=Read( fh,buf,1023);
  980.     Close(fh);
  981.  
  982.     for( cl=CRoot; cl; cl=cl->next ) {
  983.         class=cl->name;
  984.         if(!(str=next_a0(cl->name))) continue;
  985.         while( str ) {
  986.             if(!(arg=next_a0( str ))) goto nextclass;
  987.             switch( *str ) {
  988.             case 's':
  989.                 if( (offs=strlen(file)-wrdlen(arg))<0 ) break;
  990.                 if( !strwrdcmp(file+offs,arg)) goto found;
  991.                 break;
  992.             case 'n':
  993.                 if( !strwrdcmp(BaseName(file),arg) ) goto found;
  994.                 break;
  995.             case 'd':
  996.                 goto found;
  997.             case 'o':
  998.                 offs=gethex(arg,0);
  999.                 if( !(arg=index(arg,','))) goto nextclass;
  1000.                 if( offs>len-10 ) break;
  1001.                 for( get=buf+offs, ++arg; (byte=gethex(arg,2))>=0; arg+=2 )
  1002.                     if( *get++!=byte && byte!=256 )
  1003.                         goto nexttry;
  1004.                 goto found;
  1005.             case 'c':
  1006.                 if( !len )
  1007.                     goto nexttry;
  1008.                 for( get=buf, fail=0; get<buf+len; get++ )
  1009.                     if( *get<9 || *get>13 && *get<32 || *get>127  )
  1010.                         fail++;
  1011.                 if( fail*8>len )
  1012.                     goto nexttry;
  1013.                 goto found;
  1014.             case 'a':
  1015.                 goto nextclass;
  1016.             default:
  1017.                 goto nextclass;
  1018.             }
  1019. nexttry:    str=next_a0(arg);
  1020.         }
  1021. nextclass: ;
  1022.     }
  1023.  
  1024.     free(buf);
  1025.     return NULL;
  1026.  
  1027. found:
  1028.     free(buf);
  1029.     return class;
  1030. }
  1031.  
  1032. char *
  1033. getaction( char *class, char *action )
  1034. {
  1035.     CLASS *cl;
  1036.     char *cur, *ind;
  1037.     int len;
  1038.  
  1039.     for( len=0; class[len] && class[len]!=0xA0; len++ ) ;
  1040.     for( cl=CRoot; cl; cl=cl->next ) {
  1041.         if( strncmp( cur=cl->name,class,len+1 ))
  1042.             continue;
  1043.         do
  1044.             cur=index( cur,0xA0 );
  1045.         while( cur && *++cur!='a');
  1046.  
  1047.         if( cur && (cur=index( ++cur,0xA0 ))) {
  1048.             do {
  1049.                 if( !(ind=index( ++cur,'=' )))
  1050.                     return NULL;
  1051.                 len=ind-cur;
  1052.                 if( len==strlen(action) && !strncmp(action,cur,len))
  1053.                     return ++ind;
  1054.             } while( cur=index(cur,0xA0) );
  1055.         }
  1056.     }
  1057.     return NULL;
  1058. }
  1059.  
  1060. int
  1061. doaction( char *file, char *action, char *args )
  1062. {
  1063.     char *class, *com, *c, *copy;
  1064.  
  1065.     if( !(class=getclass(file)))
  1066.         return 10;
  1067.     if( !(com=getaction(class,action)))
  1068.         return 11;
  1069.     if( c=index(com,0xA0) )
  1070.         *c=0;
  1071.     copy=malloc( strlen(com)+strlen(file)+strlen(args)+5 );
  1072.     sprintf(copy,"%s %s %s",com,file,args);
  1073.     execute(copy);
  1074.     free(copy);
  1075.     if( c )
  1076.         *c=0xA0;
  1077.     return 0;
  1078. }
  1079.