home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / shell / csh550src.lha / sub.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-02  |  28.3 KB  |  1,519 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.  
  15. static void del_history( void );
  16. static int dnext( DPTR *dp, char **pname, int *stat);
  17. static char *svfile( char *s1, char *s2, FIB *fib);
  18. static void quicksort( char **av, int n );
  19.  
  20. void
  21. seterr( int err )
  22. {
  23.     static int LastErr;
  24.     char buf[32], *val;
  25.     int  stat=0;
  26.  
  27.     Lastresult=err;
  28.  
  29.     if( LastErr!=err ) {
  30.         LastErr=err;
  31.         sprintf(buf, "%d", err);
  32.         set_var(LEVEL_SET, v_lasterr, buf);
  33.  
  34.         if( val=get_var(LEVEL_SET, v_stat))
  35.             stat = atoi(val);
  36.         if (stat < Lastresult) set_var(LEVEL_SET, v_stat, buf);
  37.     }
  38. }
  39.  
  40. char *
  41. next_word( char *str )
  42. {
  43.     while (*str && ! ISSPACE(*str)) ++str;
  44.     while (*str &&   ISSPACE(*str)) ++str;
  45.     return str;
  46. }
  47.  
  48. /*
  49.  * FREE(ptr)   --frees without actually freeing, so the data is still good
  50.  *               immediately after the free.
  51.  */
  52.  
  53.  
  54. void
  55. Free( void *ptr )
  56. {
  57.     static char *old_ptr;
  58.  
  59.     if (old_ptr) free (old_ptr);
  60.     old_ptr = ptr;
  61. }
  62.  
  63. /*
  64.  * Add new string to history (H_head, H_tail, H_len,
  65.  *  S_histlen
  66.  */
  67.  
  68. void
  69. add_history( char *str )
  70. {
  71.     HIST *hist;
  72.     char *get;
  73.  
  74.     for( get=str; *get; get++ )
  75.         if( (*get&127)<' ')
  76.             *get=' ';
  77.  
  78.     if (H_head != NULL && !strcmp(H_head->line, str))
  79.         return;
  80.     while (H_len > S_histlen)
  81.         del_history();
  82.     hist = (HIST *)salloc (sizeof(HIST));
  83.     if (H_head == NULL) {
  84.         H_head = H_tail = hist;
  85.         hist->next = NULL;
  86.     } else {
  87.         hist->next = H_head;
  88.         H_head->prev = hist;
  89.         H_head = hist;
  90.     }
  91.     hist->prev = NULL;
  92.     hist->line = salloc (strlen(str) + 1);
  93.     strcpy (hist->line, str);
  94.     ++H_len;
  95.     H_num= H_tail_base+ H_len;
  96. }
  97.  
  98. static void
  99. del_history()
  100. {
  101.     if (H_tail) {
  102.         --H_len;
  103.         ++H_tail_base;
  104.         free (H_tail->line);
  105.         if (H_tail->prev) {
  106.             H_tail = H_tail->prev;
  107.             free (H_tail->next);
  108.         H_tail->next = NULL;
  109.         } else {
  110.             free (H_tail);
  111.             H_tail = H_head = NULL;
  112.         }
  113.     }
  114. }
  115.  
  116. char *
  117. get_history( char *ptr )
  118. {
  119.     int   hnum=find_history( ptr+1, 1 );
  120.     HIST *hist;
  121.  
  122.     for( hist=H_head; hist && hnum--; hist=hist->next) ;
  123.     if( !hist ) {
  124.         fprintf(stderr,"History failed\n");
  125.         return "";
  126.     }
  127.     fprintf(stderr, "%s\n", hist->line );
  128.     return hist->line;
  129. }
  130.  
  131.  
  132. int
  133. find_history( char *ptr, int min )
  134. {
  135.     HIST *hist;
  136.     int  len, num;
  137.  
  138.     if     ( *ptr=='!' )
  139.         return 1;
  140.     else if( *ptr=='-' )
  141.         return atoi(ptr+1);
  142.     else if (*ptr >= '0' && *ptr <= '9')
  143.         return H_len-(atoi(ptr)-H_tail_base)-1;
  144.  
  145.     len = strlen(ptr);
  146.     for (hist=H_head,num=0; hist; hist=hist->next, num++)
  147.         if ( !strnicmp(hist->line, ptr, len) && num>=min)
  148.             return num;
  149.     return -1;
  150. }
  151.  
  152. void
  153. replace_head( char *str )
  154. {
  155.     if (str && strlen(str) && H_head) {
  156.         free (H_head->line);
  157.         H_head->line = salloc (strlen(str)+1);
  158.         strcpy (H_head->line, str);
  159.     }
  160. }
  161.  
  162.  
  163. void
  164. pError(char *str )
  165. {
  166.     int ierr = (long)IoErr();
  167.     ierror(str, ierr);
  168. }
  169.  
  170. ierror( char *str, int err )
  171. {
  172.     PERROR *per = Perror;
  173.     char msgbuf[256];
  174.  
  175.     setioerror(err);
  176.  
  177.     if (err) {
  178.         if(err<500 && Fault(err,str,msgbuf,255)) {
  179.             fprintf(stderr,"%s\n",msgbuf);
  180.             return err;
  181.         }
  182.         else {
  183.             for (; per->errstr; ++per) {
  184.                 if (per->errnum == err) {
  185.                     fprintf (stderr, "%s%s%s\n",
  186.                     per->errstr,
  187.                     (str) ? ": " : "",
  188.                     (str) ? str : "");
  189.                     return err;
  190.                 }
  191.             }
  192.         }
  193.         fprintf (stderr, "Unknown DOS error %d: %s\n", err, (str) ? str : "");
  194.     }
  195.     return err;
  196. }
  197.  
  198. void
  199. setioerror( int err )
  200. {
  201.     static int LastIoError = -1;
  202.     char buf[20];
  203.  
  204.     IoError=err;
  205.     if( IoError<0 ) IoError=0;
  206.     if( LastIoError!=IoError) {
  207.         LastIoError=IoError;
  208.         sprintf(buf, "%d", IoError);
  209.         set_var(LEVEL_SET, v_ioerr, buf);
  210.     }
  211. }
  212.  
  213. char *
  214. ioerror(int num)
  215. {
  216.     PERROR *per = Perror;
  217.  
  218.     for ( ; per->errstr; ++per)
  219.         if (per->errnum == num)
  220.             return per->errstr;
  221.     return NULL;
  222. }
  223.  
  224. /*
  225.  * Disk directory routines
  226.  *
  227.  * dptr = dopen(name, stat)
  228.  *    DPTR *dptr;
  229.  *    char *name;
  230.  *    int *stat;
  231.  *
  232.  * dnext(dptr, name, stat)
  233.  *    DPTR *dptr;
  234.  *    char **name;
  235.  *    int  *stat;
  236.  *
  237.  * dclose(dptr)                  -may be called with NULL without harm
  238.  *
  239.  * dopen() returns a struct DPTR, or NULL if the given file does not
  240.  * exist.  stat will be set to 1 if the file is a directory.  If the
  241.  * name is "", then the current directory is openned.
  242.  *
  243.  * dnext() returns 1 until there are no more entries.  The **name and
  244.  * *stat are set.  *stat != 0 if the file is a directory.
  245.  *
  246.  * dclose() closes a directory channel.
  247.  *
  248.  */
  249.  
  250. DPTR *
  251. dopen( char *name, int *stat)
  252. {
  253.     DPTR *dp;
  254.  
  255.     IoError=0;
  256.     *stat = 0;
  257.     dp = (DPTR *)salloc(sizeof(DPTR));
  258.     if (*name == '\0')
  259.         dp->lock = DupLock(Myprocess->pr_CurrentDir);
  260.     else
  261.         dp->lock = Lock (name,ACCESS_READ);
  262.     if (dp->lock == NULL) {
  263.         IoError=IoErr();
  264.         free (dp);
  265.         return NULL;
  266.     }
  267.     dp->fib = (FIB *)SAllocMem((long)sizeof(FIB), MEMF_PUBLIC);
  268.     if (!Examine (dp->lock, dp->fib)) {
  269.         pError (name);
  270.         dclose (dp);
  271.         return NULL;
  272.     }
  273.     if (dp->fib->fib_DirEntryType >= 0) *stat = 1;
  274.  
  275. #ifdef MA_AMK
  276.     {
  277.     char *c;
  278.     if (c=strchr(name,':')) {
  279.         if (dp->dname = strdup(name))
  280.             dp->dvp = GetDeviceProc(dp->dname,NULL);
  281.         else
  282.             dp->dvp = NULL;
  283.     }
  284.     else {
  285.         dp->dname = NULL;
  286.         dp->dvp   = NULL;
  287.     }
  288.     }
  289. #endif
  290.  
  291.     return dp;
  292. }
  293.  
  294. static int
  295. dnext( DPTR *dp, char **pname, int *stat)
  296. {
  297.     if (dp == NULL) return (0);
  298.  
  299.     if (ExNext (dp->lock, dp->fib)) {
  300.         *stat = 0;
  301.         if( dp->fib->fib_DirEntryType >= 0)
  302.             *stat= dp->fib->fib_DirEntryType!=ST_USERDIR ? 2 : 1;
  303.         *pname = dp->fib->fib_FileName;
  304.         return 1;
  305.     }
  306.  
  307. #ifdef MA_AMK
  308.     {
  309.     BOOL ma_done = FALSE;
  310.     if (IoErr()==ERROR_NO_MORE_ENTRIES) {
  311.         while (!ma_done && dp->dvp && (dp->dvp->dvp_Flags&DVPF_ASSIGN)) {
  312.             dp->dvp = GetDeviceProc(dp->dname,dp->dvp);
  313.             if (dp->dvp && dp->dvp->dvp_Lock) {
  314.                 char buf[256];
  315.                 BPTR new_lock,old_lock;
  316.                 char *add = strchr(dp->dname,':')+1;
  317.                 if (NameFromLock(dp->dvp->dvp_Lock,buf,255)) {
  318.                     AddPart(buf,add,255);
  319.                     printf("½%s╗\n",buf);
  320.  
  321.                     if (new_lock=Lock(buf,ACCESS_READ)) {
  322.                         if (Examine(new_lock,dp->fib)) {
  323.                             if (dp->lock) UnLock(dp->lock);
  324.                             dp->lock = new_lock;
  325.                             if (dp->fib->fib_DirEntryType >= 0) *stat = 1;
  326.                             *pname = dp->fib->fib_FileName;
  327.                             return 1;
  328.                             ma_done = TRUE;
  329.                         }
  330.                     }
  331.                 }
  332.                 else {
  333.                     fprintf(stderr,"csh.dnext: NameFromLock() failed\n");
  334.                 }
  335.             }
  336.         }
  337.     }
  338.     }
  339. #endif
  340.  
  341.     return 0;
  342. }
  343.  
  344. int
  345. dclose( DPTR *dp )
  346. {
  347.     if (dp == NULL)
  348.         return 1;
  349.     if (dp->fib)
  350.         FreeMem (dp->fib,(long)sizeof(*dp->fib));
  351.     if (dp->lock)
  352.         UnLock (dp->lock);
  353. #ifdef MA_AMK
  354.     if (dp->dvp)
  355.         FreeDeviceProc(dp->dvp);
  356. #endif
  357.     free (dp);
  358.     return 1;
  359. }
  360.  
  361.  
  362. int
  363. isdir( char *file )
  364. {
  365.     DPTR *dp;
  366.     int stat;
  367.  
  368.     stat = 0;
  369.     if (dp = dopen (file, &stat))
  370.         dclose(dp);
  371.     return (stat!=0);
  372. }
  373.  
  374.  
  375. void
  376. free_expand( char **av )
  377. {
  378.     char **get = av;
  379.  
  380.     if (av) {
  381.         while (*get)
  382.         free (*get++-sizeof(FILEINFO));
  383.         free (av);
  384.     }
  385. }
  386.  
  387. /*
  388.  * EXPAND(base,pac)
  389.  *    base           - char * (example: "df0:*.c")
  390.  *    pac            - int  *  will be set to # of arguments.
  391.  *
  392.  * 22-May-87 SJD.  Heavily modified to allow recursive wild carding and
  393.  *                 simple directory/file lookups. Returns a pointer to
  394.  *                 an array of pointers that contains the full file spec
  395.  *                 eg. 'df0:c/sear*' would result in : 'df0:C/Search'
  396.  *
  397.  *                 Now no longer necessary to Examine the files a second time
  398.  *                 in do_dir since expand will return the full file info
  399.  *                 appended to the file name. Set by formatfile().
  400.  *
  401.  *                 Caller must call free_expand when done with the array.
  402.  *
  403.  * base             bname =       ename =
  404.  * ------           -------       -------
  405.  *  "*"               ""            "*"
  406.  *  "!*.info"         ""            "*.info" (wild_exclude set)
  407.  *  "su*d/*"          ""            "*"      (tail set)
  408.  *  "file.*"          ""            "file.*"
  409.  *  "df0:c/*"         "df0:c"       "*"
  410.  *  ""                ""            "*"
  411.  *  "df0:.../*"       "df0:"        "*"      (recur set)
  412.  *  "df0:sub/.../*"   "df0:sub"     "*"      (recur set)
  413.  *
  414.  * ---the above base would be provided by execom.c or do_dir().
  415.  * ---the below base would only be called from do_dir().
  416.  *
  417.  *  "file.c"          "file.c"      ""       if (dp == 0) fail else get file.c
  418.  *  "df0:"            "df0:"        "*"
  419.  *  "file/file"       "file/file"   ""       if (dp == 0) fail
  420.  *  "df0:.../"        "df0:"        "*"      (recur set)
  421.  *
  422.  */
  423.  
  424. char **
  425. expand( char *base, int *pac )
  426. {
  427.     char *ptr;
  428.     char **eav = (char **)salloc(sizeof(char *) * (2));
  429.     short eleft, eac;
  430.     char *name;
  431.     char *bname, *ename, *tail;
  432.     int  stat, recur, scr, bl;
  433.     DPTR *dp;
  434.     PATTERN *pat;
  435.  
  436.     IoError = *pac = recur = eleft = eac = 0;
  437.  
  438.     /* kprintf("Analyzing: %s\n",base); */
  439.  
  440.     base = strcpy(salloc(strlen(base)+1), base);
  441. #if 1
  442.     /*for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);*/
  443.     for (ptr = base; *ptr && *ptr != '?' && *ptr != '*' && *ptr != '[' && *ptr != ']'; ++ptr);
  444. #else
  445.     /* AMK: experimental DOS pattern detection */
  446.     /*printf("trying to expand... %s\n",base);*/
  447.     for (ptr=base; *ptr && *ptr != '?' && *ptr!='*' && *ptr!='!' &&
  448.                    *ptr != '(' && *ptr!=')' &&
  449.                    *ptr != '|' && *ptr!='%' &&
  450.                    *ptr != '~' && *ptr!='#' &&
  451.                    *ptr != '[' && *ptr!=']';
  452.          ++ptr);
  453. #endif
  454.  
  455.     if (!*ptr)   /* no wild cards */
  456.         --ptr;
  457.     else
  458.         for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
  459.  
  460.     if (ptr < base) {
  461.         bname = strcpy (salloc(1), "");
  462.     } else {
  463.         scr = ptr[1];
  464.         ptr[1] = '\0';
  465.         if (!strcmp(ptr-3,".../")) {
  466.             recur = 1;
  467.             *(ptr-3) = '\0';
  468.         }
  469.         bname = strcpy (salloc(strlen(base)+2), base);
  470.         ptr[1] = scr;
  471.     }
  472.     bl = strlen(bname);
  473.     ename = ++ptr;
  474.     for (; *ptr && *ptr != '/'; ++ptr);
  475.     scr = *ptr;
  476.     *ptr = '\0';
  477.     if (scr) ++ptr;
  478.     tail = ptr;
  479.  
  480.     if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) {
  481.         free (bname);
  482.         free (base);
  483.         free (eav);
  484.         return NULL;
  485.     }
  486.  
  487.     if (!stat) {                /* eg. 'dir file' */
  488.         char *p,*s;
  489.         for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p;
  490.         if (*s=='/' || *s==':') s++;
  491.         *s=0;
  492.         eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib);
  493.         goto done;
  494.     }
  495.     if (!*ename) ename = "*";    /* eg. dir df0: */
  496.     if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */
  497.         bname[bl] = '/';
  498.         bname[++bl] = '\0';
  499.     }
  500.  
  501. #if 0
  502.     if (stat) {
  503.         kprintf("isdir: %s, examining: %s\n",bname,ename);
  504.     }
  505. #endif
  506.  
  507.     pat= compare_preparse( ename, 0 );
  508.     while ((dnext (dp, &name, &stat)) && !breakcheck()) {
  509.         int match = compare_ok( pat, name);
  510.         if (match && (recur || !*tail)) {
  511.             if (eleft < 2) {
  512.                 char **scrav = (char **)salloc(sizeof(char *) * (eac + 10));
  513.                 memmove (scrav, eav, (eac + 1) << 2);
  514.                 free (eav);
  515.                 eav = scrav;
  516.                 eleft = 10;
  517.             }
  518.             eav[eac++] = svfile(bname,name,dp->fib);
  519.             --eleft;
  520.         }
  521.         if ((*tail && match) || recur) {
  522.             int alt_ac;
  523.             char *search, **alt_av, **scrav;
  524.             BPTR lock;
  525.  
  526.             if (stat!=1)           /* expect more dirs, but this not a dir */
  527.                 continue;
  528.             lock = CurrentDir (dp->lock);
  529.             search = salloc(strlen(ename)+strlen(name)+strlen(tail)+6);
  530.             strcpy (search, name);
  531.             strcat (search, "/");
  532.             if (recur) {
  533.                 strcat(search, ".../");
  534.                 strcat(search, ename);
  535.             }
  536.             strcat (search, tail);
  537.             /*
  538.              *  expand() will crash in endless recursion
  539.              *  if you do a .../* and a directory name
  540.              *  contains a pattern character
  541.              *
  542.              *  possible solution (hack!) :
  543.              *  convert all pattern characters to some
  544.              *  "harmless" characters and change them
  545.              *  back later. It's obvious that this sucks
  546.              *  if a directory contains exactly that
  547.              *  escape character :-(
  548.              */
  549.             scrav = alt_av = expand (search, &alt_ac);
  550.             free(search);
  551.             CurrentDir (lock);
  552.             if (scrav) {
  553.                 while (*scrav) {
  554.                     int l;
  555.                     if (eleft < 2) {
  556.                         char **scrav = (char **)salloc(sizeof(char *)*(eac+10));
  557.                         memmove ( scrav, eav, (eac + 1) << 2);
  558.                         free (eav);
  559.                         eav = scrav;
  560.                         eleft = 10;
  561.                     }
  562.  
  563.                     l = strlen(*scrav);
  564.                     eav[eac] = salloc(bl+l+1+sizeof(FILEINFO));
  565.                     memcpy( eav[eac], *scrav-sizeof(FILEINFO),sizeof(FILEINFO));
  566.                     eav[eac]+=sizeof(FILEINFO);
  567.                     strcpy( eav[eac], bname);
  568.                     strcat( eav[eac], *scrav);
  569.  
  570.                     free (*scrav-sizeof(FILEINFO));
  571.                     ++scrav;
  572.                     --eleft, ++eac;
  573.                 }
  574.                 free (alt_av);
  575.             }
  576.         }
  577.     }
  578.     compare_free( pat );
  579. done:
  580.     dclose (dp);
  581.     *pac = eac;
  582.     eav[eac] = NULL;
  583.     free (bname);
  584.     free (base);
  585.  
  586.     if (eac) {
  587.         int i, j, len;
  588.  
  589.         QuickSort( eav, eac );
  590.         for( i=0; i<eac-1; i++ ) {
  591.             len=strlen(eav[i]);
  592.  
  593.             for( j=i+1; j<eac && !strnicmp(eav[i],eav[j],len); j++ )
  594.                 if( !stricmp(eav[j]+len,".info")) {
  595.                     ((FILEINFO*)eav[i]-1)->flags |= INFO_INFO;
  596.                     break;
  597.                 }
  598.         }
  599.         return eav;
  600.     }
  601.  
  602.     free (eav);
  603.     return NULL;
  604. }
  605.  
  606.  
  607.  
  608. char *strdel(char *s,int from,int len)
  609. {
  610.     while( s[from] ) {
  611.         s[from] = s[from+len];
  612.         ++from;
  613.     }
  614.     return(s);
  615. }
  616.  
  617.  
  618.  
  619. char *
  620. strupr( char *s )
  621. {
  622.     char *old=s;
  623.     while (*s) *s=toupper(*s), s++;
  624.     return old;
  625. }
  626.  
  627. char *
  628. strlwr( char *s )
  629. {
  630.     char *old=s;
  631.     while (*s) *s=tolower(*s), s++;
  632.     return old;
  633. }
  634.  
  635.  
  636.  
  637. /*
  638.  * Compare a wild card name with a normal name
  639.  */
  640.  
  641. extern void *PatternBase;
  642.  
  643. PATTERN *
  644. compare_preparse( char *wild, int casedep )
  645. {
  646. /*    struct pattern *pat=salloc(256);*/
  647.     struct pattern *pat;
  648.     char *my_wild = wild;
  649.  
  650.     pat = salloc(sizeof(struct pattern) + strlen(wild)*2 + 3);
  651.     /* this is not exact ('lil bit too much) but better readable */
  652.  
  653.     pat->casedep=casedep;
  654.     if (pat->queryflag=(*wild=='&')) wild++;
  655.  
  656.     my_wild = salloc(strlen(wild)+3);
  657.     strcpy(my_wild,wild);
  658.     if (*my_wild=='!') *my_wild='~';
  659.     if (!casedep) strlwr(my_wild);
  660.     if (*my_wild=='~') {
  661.         strins(my_wild+1,"(");
  662.         strcat(my_wild,")");
  663.     }
  664.  
  665.     DOSBase->dl_Root->rn_Flags |= RNF_WILDSTAR;
  666.     if (PatternBase) {
  667.         if ((pat->patptr=AllocPattern( my_wild, 0 ))<0) {
  668.             free(pat);
  669.             free(my_wild);
  670.             return NULL;
  671.         }
  672.     }
  673.     else {
  674.         if ((ParsePattern(my_wild,pat->pattern,strlen(wild)*2+2)<0)) {
  675.             free(pat);
  676.             free(my_wild);
  677.             return NULL;
  678.         }
  679.     }
  680.  
  681.     free(my_wild);
  682.     return pat;
  683. }
  684.  
  685. int
  686. compare_ok( PATTERN *pat, char *name )
  687. {
  688.     char *lowname=name;
  689.  
  690.     if (!pat)
  691.         return 0;
  692.  
  693.     if (!pat->casedep) {
  694.         if (lowname=strdup(name))
  695.             strlwr(lowname);
  696.         else
  697.             return 0;
  698.     }
  699.  
  700.     DOSBase->dl_Root->rn_Flags |= RNF_WILDSTAR;
  701.     if (PatternBase) {
  702.         if (MatchThePattern(pat->patptr,lowname)!=1) {
  703.             if (lowname!=name) free(lowname);
  704.             return 0;
  705.         }
  706.     } else {
  707.         if (!MatchPattern(pat->pattern,lowname)) {
  708.             if (lowname!=name) free(lowname);
  709.             return 0;
  710.         }
  711.     }
  712.  
  713.     if (lowname!=name)
  714.         free(lowname);
  715.  
  716.     if (pat->queryflag) {
  717.         char buf[260];
  718.         printf("Select %s%-16s%s [y/n] ? ",o_hilite,name,o_lolite);
  719.         gets(buf);
  720.         return (toupper(*buf)=='Y');
  721.     }
  722.  
  723.     return 1;
  724. }
  725.  
  726. void
  727. compare_free( PATTERN *pat )
  728. {
  729.     if( !pat )
  730.         return;
  731.     if( PatternBase )
  732.         FreePattern(pat->patptr);
  733.     free( pat );
  734. }
  735.  
  736. #if 0
  737. int
  738. compare_strings( char *pattern, char *str, int casedep )
  739. {
  740.     PATTERN *pat=compare_preparse( pattern, casedep );
  741.     int ret=compare_ok(pat,str);
  742.     compare_free(pat);
  743.     return ret;
  744. }
  745. #endif
  746.  
  747. static char *
  748. svfile( char *s1, char *s2, FIB *fib)
  749. {
  750.     FILEINFO *info=salloc(sizeof(FILEINFO)+strlen(s1)+strlen(s2)+1);
  751.     char     *p = (char *)(info+1);
  752.  
  753.     strcpy(p, s1);
  754.     strcat(p, s2);
  755.     info->flags = fib->fib_Protection | (*fib->fib_Comment ? INFO_COMMENT : 0);
  756.     info->type  = fib->fib_DirEntryType;
  757.     info->size  = (fib->fib_DirEntryType<0 || fib->fib_DirEntryType==ST_SOFTLINK) ? fib->fib_Size      : -1;
  758.     info->blocks= (fib->fib_DirEntryType<0 || fib->fib_DirEntryType==ST_SOFTLINK) ? fib->fib_NumBlocks :  0;
  759.     info->date  = fib->fib_Date;
  760.     info->uid   = fib->fib_OwnerUID;
  761.     info->gid   = fib->fib_OwnerGID;
  762.     info->class[0]=1;
  763.     return p;
  764. }
  765.  
  766. static char   *FullPath;
  767. static FIB    *PrevFile;
  768. static int   (*Action)(long, char *, char *);
  769. static long    Mask;
  770. static int     Queued=0;
  771.  
  772. static int
  773. passinfo( FIB *fib )
  774. {
  775.     char   *p = (char *)(PrevFile+1);
  776.     int    oldlen, ret=0;
  777.  
  778.     if( Queued ) {
  779.         oldlen=strlen(FullPath);
  780.         /* AMK: don't know the exact length... used dummy 256L */
  781.         AddPart( FullPath, p, 256L );
  782.         ret=(*Action)( Mask, p, FullPath );
  783.         FullPath[oldlen]=0;
  784.         Queued=0;
  785.     }
  786.  
  787.     if( fib ) {
  788.         *PrevFile= *fib;
  789.         strcpy( p, fib->fib_FileName);
  790.         Queued=1;
  791.     }
  792.  
  793.     return ret;
  794. }
  795.  
  796.  
  797. static int
  798. nu_recurse( char *name )
  799. {
  800.     BPTR lock, cwd;
  801.     FIB  *fib  =(FIB *)SAllocMem(sizeof(FIB),MEMF_PUBLIC);
  802.     int  oldlen=strlen( FullPath ), ret=0;
  803.  
  804.     /* AMK: don't know the length... used dummy 256L */
  805.     AddPart( FullPath, name, 256L );
  806.  
  807.     if (lock=Lock(name,ACCESS_READ)) {
  808.         if( Mask & SCAN_DIRENTRY )
  809.             (*Action)( SCAN_DIRENTRY, name, FullPath );
  810.  
  811.         cwd =CurrentDir(lock);
  812.         if (Examine(lock, fib)) {
  813.             while (ExNext(lock, fib) && !breakcheck()) {
  814.                 if (fib->fib_DirEntryType==ST_USERDIR) {
  815.                     if ( Mask & SCAN_RECURSE ) {
  816.                         if(!ret && !(ret=passinfo( NULL )))
  817.                             ret=nu_recurse(fib->fib_FileName);
  818.                     }
  819.                     if ( Mask & SCAN_DIR     )
  820.                         if( !ret )
  821.                             ret=passinfo( fib );
  822.                 } else if( fib->fib_DirEntryType<0 && Mask & SCAN_FILE )
  823.                     if( !ret )
  824.                         ret=passinfo( fib );
  825.             }
  826.             if( breakcheck() )
  827.                 ret=5;
  828.  
  829.             if( !ret )
  830.                 passinfo( NULL );
  831.  
  832.         }
  833.         UnLock(CurrentDir(cwd));
  834.  
  835.         if( Mask & SCAN_DIREND )
  836.             (*Action)( SCAN_DIREND, name, FullPath );
  837.     } else
  838.         pError(name);
  839.  
  840.     FullPath[oldlen]=0;
  841.     FreeMem(fib, sizeof(FIB));
  842.     return ret;
  843. }
  844.  
  845. int
  846. newrecurse(int mask, char *name, int (*action)FUNCARG(long,char *,char *))
  847. {
  848.     int ret;
  849.  
  850.     FullPath = salloc( 512 );
  851.     PrevFile = salloc( sizeof(FIB)+108+1 );
  852.     Action   = action;
  853.     Mask     = mask;
  854.     Queued   = 0;
  855.     *FullPath= 0;
  856.  
  857.     ret=nu_recurse( name );
  858.  
  859.     free( PrevFile );
  860.     free( FullPath );
  861.  
  862.     return ret;
  863. }
  864.  
  865.  
  866. /* Sort routines */
  867.  
  868. static int reverse, factor;
  869.  
  870. int
  871. cmp( FILEINFO *s1, FILEINFO *s2)
  872. {
  873.     return stricmp( (char *)(s1+1), (char *)(s2+1) );
  874. }
  875.  
  876. int
  877. cmp_case( FILEINFO *s1, FILEINFO *s2)
  878. {
  879.     return strcmp( (char *)(s1+1), (char *)(s2+1) );
  880. }
  881.  
  882. int
  883. sizecmp( FILEINFO *s1, FILEINFO *s2)
  884. {
  885.     return s2->size - s1->size;
  886. }
  887.  
  888. int
  889. datecmp_csh( FILEINFO *s1, FILEINFO *s2 )
  890. {
  891.     int r;
  892.     struct DateStamp *d1 = &s1->date, *d2 = &s2->date;
  893.     if( !(r= d2->ds_Days - d1->ds_Days))
  894.         if( !(r=d2->ds_Minute - d1->ds_Minute ) )
  895.             r=d2->ds_Tick - d1->ds_Tick;
  896.     return r;
  897. }
  898.  
  899.  
  900. int
  901. numcmp( FILEINFO *s1, FILEINFO *s2 )
  902. {
  903.     return atoi((char *)(s1+1))-atoi((char *)(s2+1));
  904. }
  905.  
  906. static void
  907. enterclass( FILEINFO *info )
  908. {
  909.     char *class, *iclass=info->class, *t;
  910.  
  911.     if( *iclass==1 ) {
  912.         if( class=getclass( (char *)(info+1))) {
  913.             strncpy( iclass, class, 11 );
  914.             iclass[11]=0;
  915.             if( t=index(iclass,0xA0))
  916.                 *t=0;
  917.         } else 
  918.             iclass[0]=0;
  919.     }
  920. }
  921.  
  922. int
  923. classcmp( FILEINFO *info1, FILEINFO *info2 )
  924. {
  925.     int r;
  926.  
  927.     enterclass( info1 );
  928.     enterclass( info2 );
  929.  
  930.     r= stricmp( info1->class, info2->class );
  931.     if( !r ) r=stricmp((char *)(info1+1),(char *)(info2+1));
  932.     return r;
  933. }
  934.  
  935.  
  936. void
  937. QuickSort( char *av[], int n)
  938. {
  939.     reverse=factor=0;
  940.     DirQuickSort( av, n, cmp, 0, 0 );
  941. }
  942.  
  943. static int (*compare)(FILEINFO *, FILEINFO *);
  944.  
  945. static int
  946. docompare(char *s1,char *s2)
  947. {
  948.     FILEINFO *i1=(FILEINFO *)s1-1, *i2=(FILEINFO *)s2-1;
  949.     int r=(*compare)( i1,i2 );
  950.  
  951.     if( reverse ) r = -r;
  952.     if( factor )  r+= factor*((i2->size<0) - (i1->size<0));
  953.     return r;
  954. }
  955.  
  956. #define QSORT
  957.  
  958. void
  959. DirQuickSort( char *av[], int n, int (*func)(FILEINFO *,FILEINFO *), int rev, int fac)
  960. {
  961.     reverse=rev; compare=func; factor=fac;
  962.  
  963.     quicksort( av, n-1 );
  964. }
  965.  
  966. static void
  967. quicksort( char **av, int n )
  968. {
  969.     char **i, **j, *x, *t;
  970.  
  971.  
  972.     if( n>0 ) {
  973.         i=av; j=av+n; x=av[ n>>1 ];
  974.         do {
  975.             while( docompare(*i,x)<0 ) i++;
  976.             while( docompare(x,*j)<0 ) --j;
  977.             if( i<=j )
  978.                 { t = *i; *i = *j; *j=t; i++; j--; }
  979.         } while( i<=j );
  980.  
  981.         if( j-av < av+n-i ) {
  982.             quicksort( av, j-av  );
  983.             quicksort( i , av+n-i);
  984.         } else {
  985.             quicksort( i , av+n-i);
  986.             quicksort( av, j-av  );
  987.         }
  988.     }
  989. }
  990.  
  991. int
  992. filesize( char *name )
  993. {
  994.     BPTR lock;
  995.     struct FileInfoBlock *fib;
  996.     int  len=0;
  997.  
  998.     if( lock = Lock (name,ACCESS_READ)) {
  999.         if( fib=(struct FileInfoBlock *)AllocMem(sizeof(*fib),MEMF_PUBLIC)) {
  1000.             if (Examine (lock, fib))
  1001.                 len=fib->fib_Size;
  1002.             FreeMem( fib, sizeof(*fib));
  1003.         }
  1004.         UnLock(lock);
  1005.     }
  1006.     return len;
  1007. }
  1008.  
  1009.  
  1010. #ifndef MIN
  1011. #define MIN(x,y) ((x)<(y)?(x):(y))
  1012. #endif
  1013.  
  1014. char **
  1015. and( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
  1016. {
  1017.     char **av=(char **)salloc(MIN(ac1,ac2)*sizeof(char *) ), *str;
  1018.     int i, j, k=0;
  1019.  
  1020.     for( i=0; i<ac1; i++ )
  1021.         for( j=0, str=base ? (char*)FilePart(av1[i]) : av1[i]; j<ac2; j++ )
  1022.             if( !stricmp(str, base ? (char*)FilePart(av2[j]) : av2[j]))
  1023.                 av[k++]=av1[i];
  1024.     *ac=k;
  1025.     return av;
  1026. }
  1027.  
  1028. char **
  1029. without( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
  1030. {
  1031.     char **av=(char **)salloc(ac1*sizeof(char *) ), *str;
  1032.     int i, j, k=0;
  1033.  
  1034.     for( i=0; i<ac1; i++ ) {
  1035.         for( j=0, str=base ? (char*)FilePart(av1[i]) : av1[i]; j<ac2; j++ )
  1036.             if( !stricmp(str, base ? (char*)FilePart(av2[j]) : av2[j] ) )
  1037.                 break;
  1038.         if( j==ac2 )
  1039.             av[k++]=av1[i];
  1040.     }
  1041.     *ac=k;
  1042.     return av;
  1043. }
  1044.  
  1045. char **
  1046. or( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
  1047. {
  1048.     char **av=(char **)salloc((ac1+ac2)*sizeof(char *) ), *str;
  1049.     int i, j, k=0;
  1050.  
  1051.     for( i=0; i<ac1; i++ )
  1052.         av[k++]=av1[i];
  1053.  
  1054.     for( i=0; i<ac2; i++ ) {
  1055.         for( j=0, str=base ? (char*)FilePart(av2[i]) : av2[i]; j<ac1; j++ )
  1056.             if( !stricmp(str, base ? (char*)FilePart(av1[j]) : av1[j] ) )
  1057.                 break;
  1058.         if( j==ac1 )
  1059.             av[k++]=av2[i];
  1060.     }
  1061.  
  1062.     *ac=k;
  1063.     return av;
  1064. }
  1065.  
  1066. void
  1067. clear_archive_bit( char *name )
  1068. {
  1069.     DPTR *dp;
  1070.     int  stat;
  1071.  
  1072.     if(dp = dopen(name,&stat) ) {
  1073.         setProtection( name, dp->fib->fib_Protection&~FIBF_ARCHIVE);
  1074.         dclose( dp );
  1075.     }
  1076. }
  1077.  
  1078. char *
  1079. itoa( int i )
  1080. {
  1081.     static char buf[20];
  1082.     char *pos=buf+19;
  1083.     int count=4, flag=0;
  1084.  
  1085.     if( i<0 )
  1086.         flag=1, i = -i;
  1087.  
  1088.     do {
  1089.         if( !--count )
  1090.             count=3, *--pos=',';
  1091.         *--pos= i%10+'0';
  1092.     } while( i/=10 );
  1093.  
  1094.     if( flag )
  1095.         *--pos='-';
  1096.  
  1097.     return pos;
  1098. }
  1099.  
  1100. char *
  1101. itok( int i )
  1102. {
  1103. #if 0
  1104.     static char buf[16], which;
  1105.     char *exp=" KMG", *ptr= buf+(which=8-which);
  1106. #endif
  1107.     /* now three buffers instead of two as needed for do_info() */
  1108.     static char buf[24], which;
  1109.     char *exp=" kMG", *ptr= buf+(8*(which=(which+1)%3));
  1110.     int res,m=1024;
  1111.  
  1112. /* AMK: don't cripple small numbers */
  1113.     if (i<1000) {
  1114.         sprintf(ptr,"%d",i);
  1115.         return ptr;
  1116.     }
  1117.  
  1118. /* AMK: allow four places for kilobytes */
  1119.     if ((res=(i+512)/1024)<10000) {
  1120.         sprintf(ptr,"%dk",res);
  1121.         return ptr;
  1122.     }
  1123. /* AMK: because of HD floppies with 1760K (not 2MB :-) */
  1124.  
  1125.     do {
  1126.         /* res=(i+512)/m; */
  1127.         res=(i+(m/2))/m;
  1128.         m*=1024;
  1129.         ++exp;
  1130.     }
  1131.     while (res>999);
  1132.  
  1133.     if (res==0)
  1134.         res=1;
  1135.  
  1136.     sprintf(ptr,"%d%c",res,*exp);
  1137.  
  1138.     return ptr;
  1139. }
  1140.  
  1141. char *
  1142. next_a0( char *str )
  1143. {
  1144.     while( *str && (UBYTE)*str!=0xA0 && *str!='=' && *str!=',') str++;
  1145.     if( *str )
  1146.         return str+1;
  1147.     return NULL;
  1148. }
  1149.  
  1150. static int
  1151. gethex( char *str, int l )
  1152. {
  1153.     int i, val=0, n, c;
  1154.  
  1155.     if( *str=='.' ) return l==2 ? 256 : 0;
  1156.  
  1157.     for( i=0; i<l || !l; i++ ) {
  1158.         c = *str++;
  1159.         if     ( c>='0' && c<='9' ) n=c-'0';
  1160.         else if( c>='a' && c<='f' ) n=c-'a'+10;
  1161.         else if( c>='A' && c<='F' ) n=c-'A'+10;
  1162.         else break;;
  1163.         val=16*val+n;
  1164.     }
  1165.     return (l && i!=l) ? -1 : val;
  1166. }
  1167.  
  1168. strwrdcmp( char *str, char *wrd )
  1169. {
  1170.     PATTERN *pat;
  1171.     int ret;
  1172.     char *ind=index(wrd,0xA0);
  1173.  
  1174.     if( ind ) *ind=0;
  1175.     pat=compare_preparse( wrd,0 );
  1176.     ret=compare_ok(pat,str);
  1177.     compare_free( pat );
  1178.     if( ind ) *ind=0xA0;
  1179.     return !ret;
  1180. }
  1181.  
  1182. int
  1183. wrdlen( char *str )
  1184. {
  1185.     char *old=str;
  1186.  
  1187.     while( *str && (UBYTE)*str!=0xA0 ) str++;
  1188.     return str-old;
  1189. }
  1190.  
  1191. char *
  1192. getclass(char *file)
  1193. {
  1194.     CLASS *cl;
  1195.     char *class, *str, *arg, *get, *buf;
  1196.     int offs, byte, len, fail;
  1197.     BPTR fh;
  1198.  
  1199.     if( isdir(file) ) return "dir";
  1200.  
  1201.     if( !(buf=calloc(1024,1))) return NULL;
  1202.     if( !(fh=Open(file,MODE_OLDFILE))) return NULL;
  1203.     len=Read( fh,buf,1023);
  1204.     Close(fh);
  1205.  
  1206.     for( cl=CRoot; cl; cl=cl->next ) {
  1207.         class=cl->name;
  1208.         if(!(str=next_a0(cl->name))) continue;
  1209.         while( str ) {
  1210.             if(!(arg=next_a0( str ))) goto nextclass;
  1211.             switch( *str ) {
  1212.             case 's':
  1213.                 if( (offs=strlen(file)-wrdlen(arg))<0 ) break;
  1214.                 if( !strwrdcmp(file+offs,arg)) goto found;
  1215.                 break;
  1216.             case 'n':
  1217.                 if( !strwrdcmp(FilePart(file),arg) ) goto found;
  1218.                 break;
  1219.             case 'd':
  1220.                 goto found;
  1221.             case 'o':
  1222.                 offs=gethex(arg,0);
  1223.                 if( !(arg=index(arg,','))) goto nextclass;
  1224.                 if( offs>len-10 ) break;
  1225.                 for( get=buf+offs, ++arg; (byte=gethex(arg,2))>=0; arg+=2 )
  1226.                     if( (UBYTE)*get++!=byte && byte!=256 )
  1227.                         goto nexttry;
  1228.                 goto found;
  1229.             case 'c':
  1230.                 if( !len )
  1231.                     break;
  1232.                 for( get=buf, fail=0; get<buf+len; get++ )
  1233.                     if( *get<9 || *get>13 && *get<32 || *get>127  )
  1234.                         fail++;
  1235.                 if( fail*8>len )
  1236.                     break;
  1237.                 goto found;
  1238.             case 'i':
  1239.                 break;
  1240.             case 'a':
  1241.                 goto nextclass;
  1242.             default:
  1243.                 goto nextclass;
  1244.             }
  1245. nexttry:    str=next_a0(arg);
  1246.         }
  1247. nextclass: ;
  1248.     }
  1249.  
  1250.     free(buf);
  1251.     return NULL;
  1252.  
  1253. found:
  1254.     free(buf);
  1255.     return (char *)class;
  1256. }
  1257.  
  1258. char *
  1259. superclass( char *subclass )
  1260. {
  1261.     CLASS *cl;
  1262.     char *cur;
  1263.     int len;
  1264.  
  1265.     for( len=0; subclass[len] && (UBYTE)subclass[len]!=0xA0; len++ ) ;
  1266.     for( cl=CRoot; cl; cl=cl->next ) {
  1267.         if( strncmp( cur=cl->name,subclass,len ))
  1268.             continue;
  1269.         do
  1270.             cur=index( cur,0xA0 );
  1271.         while( cur && *++cur!='i');
  1272.  
  1273.         if( cur && (cur=index(cur,'=')))
  1274.             return ++cur;
  1275.     }
  1276.     return NULL;
  1277. }
  1278.  
  1279. char *
  1280. getaction( char *class, char *action )
  1281. {
  1282.     CLASS *cl;
  1283.     char *cur, *ind;
  1284.     int len;
  1285.  
  1286.     for( len=0; class[len] && (UBYTE)class[len]!=0xA0; len++ ) ;
  1287.     for( cl=CRoot; cl; cl=cl->next ) {
  1288.         if( strncmp( cur=cl->name,class,len ) || !issep(cur[len]))
  1289.             continue;
  1290.         do
  1291.             cur=index( cur,0xA0 );
  1292.         while( cur && *++cur!='a');
  1293.  
  1294.         if( cur && (cur=index( ++cur,0xA0 ))) {
  1295.             do {
  1296.                 if( !(ind=index( ++cur,'=' )))
  1297.                     return NULL;
  1298.                 len=ind-cur;
  1299.                 if( len==strlen(action) && !strncmp(action,cur,len))
  1300.                     return ++ind;
  1301.             } while( cur=index(cur,0xA0) );
  1302.         }
  1303.     }
  1304.     return NULL;
  1305. }
  1306.  
  1307. int
  1308. doaction( char *file, char *action, char *args )
  1309. {
  1310.     char *class, *com, *c, *copy;
  1311.     int ret, spc=hasspace(file), i=0;
  1312.  
  1313.     if( !(class=getclass(file)))
  1314.         return exists(file) ? 10 : 9;
  1315.  
  1316.     do
  1317.         if( com=getaction(class,action))
  1318.             break;
  1319.     while( (class=superclass( class )) && ++i<4 );
  1320.     if( !class )
  1321.         return 11;
  1322.     if( c=index(com,0xA0) )
  1323.         *c=0;
  1324.     copy=salloc( strlen(com)+strlen(file)+strlen(args)+7 );
  1325.     sprintf(copy,spc?"%s \"%s\" %s":"%s %s %s", com, file, args);
  1326.     ret=execute(copy);
  1327.     free(copy);
  1328.     if( c )
  1329.         *c=0xA0;
  1330.     return ret ? 12 : 0;
  1331. }
  1332.  
  1333. void *
  1334. salloc( int len )
  1335. {
  1336.     void *ret;
  1337.  
  1338.     if( !len ) len++;
  1339.  
  1340.     if( !(ret=malloc(len))) {
  1341.         fprintf(stderr,"Out of memory -- exiting\n");
  1342.         main_exit( 20 );
  1343.     }
  1344.     return ret;
  1345. }
  1346.  
  1347. void *
  1348. SAllocMem( long size, long req  )
  1349. {
  1350.     void *ret;
  1351.  
  1352.     if( !(ret=AllocMem(size,req))) {
  1353.         fprintf(stderr,"Out of memory -- exiting\n");
  1354.         main_exit( 20 );
  1355.     }
  1356.     return ret;
  1357. }
  1358.  
  1359.  
  1360.  
  1361. int
  1362. issep( char s )
  1363. {
  1364.     return !s || ISSPACE(s) || s=='/' || s==';' || s=='|' || s=='&';
  1365. }
  1366.  
  1367.  
  1368. char *
  1369. filemap( char *buf, int last )
  1370. {
  1371.     char *s=buf, *d, *lcd;
  1372.     int  len;
  1373.  
  1374.     if( last && *s=='~' && issep(s[1])) {
  1375.         if (!(lcd=get_var(LEVEL_SET,v_lcd)))
  1376.             return buf;
  1377.         len= strlen(lcd);
  1378.         memmove( s+len, s+1, strlen(s)+1);
  1379.         memcpy( s, lcd, strlen(lcd));
  1380.         if( s[len]!='/' )
  1381.             return buf;
  1382.         s+=len+1;
  1383.     }
  1384.     d=s;
  1385.     for( ;; ) {
  1386.         if( s[0]=='.' && issep(s[1]) ) {
  1387. #if 0
  1388.             char AmkBuf[256];
  1389.             strcpy(AmkBuf,get_var(LEVEL_SET, v_cwd));
  1390.             AddPart(AmkBuf,(s[1]==0)?s+1:s+2,255);
  1391.             printf(". = %s\n",AmkBuf);
  1392. #endif
  1393.             s+=1+(s[1]!=0);
  1394.         }
  1395.         else if( s[0]=='.' && s[1]=='.' && issep(s[2]))
  1396.             *d++='/', s+=2+(s[2]!=0);
  1397.         else
  1398.             break;
  1399.     }
  1400.     while( *d++ = *s++ ) ;
  1401.  
  1402.     return buf;
  1403. }
  1404.  
  1405.  
  1406. char *
  1407. safegets( char *buf, FILE *in )
  1408. {
  1409.     char *t;
  1410.  
  1411.     if( dobreak() )
  1412.         return NULL;
  1413.  
  1414.     if( !fgets(buf,249,in) )
  1415.         return NULL;
  1416.  
  1417.     if( t=index(buf,'\n' ))
  1418.         *t=0;
  1419.  
  1420.     return buf;
  1421. }
  1422.  
  1423.  
  1424.  
  1425. /* ------------------------ string array handling -------------------------- */
  1426.  
  1427. /*
  1428.  *  First call:  pass "*array=NULL" and "*len=0" !!
  1429.  */
  1430.  
  1431. #define AL_BLOCKSIZE 20
  1432.  
  1433. BOOL add_array_list(char ***array, long *len, char *str)
  1434. {
  1435.     char **new_array = *array;
  1436.     long i = *len;
  1437.     BOOL success=FALSE;
  1438.  
  1439.     if (i%AL_BLOCKSIZE == 0) {
  1440.         if (new_array = malloc((i+AL_BLOCKSIZE) * sizeof(char *))) {
  1441.             memcpy(new_array,*array,i * sizeof(char *));
  1442.             free(*array);            /* free old array */
  1443.             *array = new_array;        /* set new array */
  1444.         }
  1445.         else
  1446.             return(success);
  1447.     }
  1448.  
  1449.     if (new_array[i] = strdup(str)) {
  1450.         *len = ++i;                /* update length */
  1451.         success = TRUE;
  1452.     }
  1453.  
  1454.     return(success);
  1455. }
  1456.  
  1457. void free_array_list(char **array, long len)
  1458. {
  1459.     long i;
  1460.     if (len>0) {
  1461.         for (i=0; i<len; i++)
  1462.             free(array[i]);
  1463.         free(array);
  1464.     }
  1465. }
  1466.  
  1467. /* ------------------------ string array handling -------------------------- */
  1468.  
  1469.  
  1470.  
  1471. #ifndef ACTION_SET_OWNER
  1472. #define ACTION_SET_OWNER 1036
  1473. #endif
  1474.  
  1475. BOOL SetOwner37(UBYTE *name, LONG uidgid)
  1476. {
  1477.     struct DevProc *devproc = NULL;
  1478.     BPTR lock;
  1479.     char null[] = "\0\0\0\0";    /* longword aligned null-byte */
  1480.     BOOL Res = FALSE;
  1481.  
  1482.     while(devproc = GetDeviceProc(name, devproc))
  1483.     {
  1484.         if (lock = Lock(name, SHARED_LOCK))
  1485.         {
  1486.             Res = DoPkt(devproc->dvp_Port,
  1487.                 ACTION_SET_OWNER,
  1488.                 NULL, lock, MKBADDR(null+3), uidgid, NULL);
  1489.             UnLock(lock);
  1490.             break;
  1491.         }
  1492.         else if (IoErr() != ERROR_OBJECT_NOT_FOUND)
  1493.             break;
  1494.     }
  1495.     if (devproc)
  1496.         FreeDeviceProc(devproc);
  1497.     else
  1498.         if (IoErr() == ERROR_NO_MORE_ENTRIES)
  1499.             SetIoErr(ERROR_OBJECT_NOT_FOUND);
  1500.     return Res;
  1501. }
  1502.  
  1503.  
  1504.  
  1505. long setProtection( char *name, long mask )
  1506. {
  1507.     long rc;
  1508. #ifdef MULTIUSER_SUPPORT
  1509.     if (muBase)
  1510.         rc = (long)muSetProtection( name, mask );
  1511.     else
  1512.         rc = (long)SetProtection( name, mask );
  1513. #else
  1514.     rc = (long)SetProtection( name, mask );
  1515. #endif
  1516.     return(rc);
  1517. }
  1518.  
  1519.