home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d107 / csh.lha / Csh / sub.c < prev   
C/C++ Source or Header  |  1987-10-31  |  13KB  |  621 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.  *
  9.  */
  10.  
  11. #include "shell.h"
  12.  
  13. #define HM_STR 0          /* various HISTORY retrieval modes */
  14. #define HM_REL 1
  15. #define HM_ABS 2
  16.  
  17. /* extern struct FileLock *Clock; */
  18. seterr()
  19. {
  20.    char buf[32];
  21.    int stat;
  22.  
  23.    sprintf(buf, "%d", Lastresult);
  24.    set_var(LEVEL_SET, V_LASTERR, buf);
  25.    stat = atoi(get_var(LEVEL_SET, V_STAT));
  26.    if (stat < Lastresult)
  27.       stat = Lastresult;
  28.    sprintf(buf, "%d", stat);
  29.    set_var(LEVEL_SET, V_STAT, buf);
  30. }
  31.  
  32.  
  33. char *
  34. next_word(str)
  35. register char *str;
  36. {
  37.    while (*str    &&  *str != ' '     &&  *str != 9 && (unsigned char)*str != 0xA0)
  38.       ++str;
  39.    while (*str    && (*str == ' ' || *str == 9 || (unsigned char)*str == 0xA0))
  40.       ++str;
  41.    return (str);
  42. }
  43.  
  44. char *
  45. compile_av(av, start, end, delim)
  46. char **av;
  47. unsigned char delim;
  48. {
  49.    char *cstr;
  50.    int i, len;
  51.  
  52.    len = 0;
  53.    for (i = start; i < end; ++i)
  54.       len += strlen(av[i]) + 1;
  55.    cstr = malloc(len + 1);
  56.    *cstr = '\0';
  57.       for (i = start; i < end; ++i) {
  58.       if (debug) {
  59.      fprintf (stderr, "AV[%2d] :%s:\n", i, av[i]);
  60.       }
  61.       strcat (cstr, av[i]);
  62.       if (i + 1 < end)
  63.          strncat(cstr, &delim, 1);
  64.    }
  65.    return (cstr);
  66. }
  67.  
  68.  
  69. /*
  70.  * FREE(ptr)   --frees without actually freeing, so the data is still good
  71.  *         immediately after the free.
  72.  */
  73.  
  74.  
  75. Free(ptr)
  76. char *ptr;
  77. {
  78.    static char *old_ptr;
  79.  
  80.    if (old_ptr)
  81.       free (old_ptr);
  82.    old_ptr = ptr;
  83. }
  84.  
  85. /*
  86.  * Add new string to history (H_head, H_tail, H_len,
  87.  *  S_histlen
  88.  */
  89.  
  90. add_history(str)
  91. char *str;
  92. {
  93.    register struct HIST *hist;
  94.  
  95.    if (H_head != NULL && strcmp(H_head->line, str) == 0)
  96.        return(0);
  97.    while (H_len > S_histlen)
  98.       del_history();
  99.    hist = (struct HIST *)malloc (sizeof(struct HIST));
  100.    if (H_head == NULL) {
  101.       H_head = H_tail = hist;
  102.       hist->next = NULL;
  103.    } else {
  104.       hist->next = H_head;
  105.       H_head->prev = hist;
  106.       H_head = hist;
  107.    }
  108.    hist->prev = NULL;
  109.    hist->line = malloc (strlen(str) + 1);
  110.    strcpy (hist->line, str);
  111.    ++H_len;
  112. }
  113.  
  114. del_history()
  115. {
  116.    if (H_tail) {
  117.       --H_len;
  118.       ++H_tail_base;
  119.       free (H_tail->line);
  120.       if (H_tail->prev) {
  121.      H_tail = H_tail->prev;
  122.      free (H_tail->next);
  123.      H_tail->next = NULL;
  124.       } else {
  125.      free (H_tail);
  126.      H_tail = H_head = NULL;
  127.       }
  128.    }
  129. }
  130.  
  131. char *
  132. get_history(ptr)
  133. char *ptr;
  134. {
  135.    register struct HIST *hist;
  136.    register int len;
  137.    int mode = HM_REL;
  138.    int num  = 1;
  139.    char *str;
  140.    char *result = NULL;
  141.  
  142.    if (ptr[1] >= '0' && ptr[1] <= '9') {
  143.       mode = HM_ABS;
  144.       num  = atoi(&ptr[1]);
  145.       goto skip;
  146.    }
  147.    switch (ptr[1]) {
  148.    case '!':
  149.       break;
  150.    case '-':
  151.       num += atoi(&ptr[2]);
  152.       break;
  153.    default:
  154.       mode = HM_STR;
  155.       str  = ptr + 1;
  156.       break;
  157.    }
  158. skip:
  159.    switch (mode) {
  160.    case HM_STR:
  161.       len = strlen(str);
  162.       for (hist = H_head; hist; hist = hist->next) {
  163.      if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
  164.         result = hist->line;
  165.         break;
  166.      }
  167.       }
  168.       break;
  169.    case HM_REL:
  170.       for (hist = H_head; hist && num--; hist = hist->next);
  171.       if (hist)
  172.      result = hist->line;
  173.       break;
  174.    case HM_ABS:
  175.       len = H_tail_base;
  176.       for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
  177.       if (hist)
  178.      result = hist->line;
  179.       break;
  180.    }
  181.    if (result) {
  182.       fprintf(stderr,"%s\n",result);
  183.       return(result);
  184.    }
  185.    printf("History failed\n");
  186.    return ("");
  187. }
  188.  
  189. replace_head(str)
  190. char *str;
  191. {
  192.    if (str == NULL)
  193.       str = "";
  194.    if (H_head) {
  195.       free (H_head->line);
  196.       H_head->line = malloc (strlen(str)+1);
  197.       strcpy (H_head->line, str);
  198.    }
  199. }
  200.  
  201.  
  202. pError(str)
  203. char *str;
  204. {
  205.    int ierr = (long)IoErr();
  206.    ierror(str, ierr);
  207. }
  208.  
  209. ierror(str, err)
  210. register char *str;
  211. {
  212.    register struct PERROR *per = Perror;
  213.  
  214.    if (err) {
  215.       for (; per->errstr; ++per) {
  216.      if (per->errnum == err) {
  217.         fprintf (stderr, "%s%s%s\n",
  218.           per->errstr,
  219.           (str) ? ": " : "",
  220.           (str) ? str : "");
  221.         return ((short)err);
  222.      }
  223.       }
  224.       fprintf (stderr, "Unknown DOS error %d %s\n", err, (str) ? str : "");
  225.    }
  226.    return ((short)err);
  227. }
  228.  
  229. /*
  230.  * Disk directory routines
  231.  *
  232.  * dptr = dopen(name, stat)
  233.  *    struct DPTR *dptr;
  234.  *    char *name;
  235.  *    int *stat;
  236.  *
  237.  * dnext(dptr, name, stat)
  238.  *    struct DPTR *dptr;
  239.  *    char **name;
  240.  *    int  *stat;
  241.  *
  242.  * dclose(dptr)             -may be called with NULL without harm
  243.  *
  244.  * dopen() returns a struct DPTR, or NULL if the given file does not
  245.  * exist.  stat will be set to 1 if the file is a directory.  If the
  246.  * name is "", then the current directory is openned.
  247.  *
  248.  * dnext() returns 1 until there are no more entries.  The **name and
  249.  * *stat are set.  *stat = 1 if the file is a directory.
  250.  *
  251.  * dclose() closes a directory channel.
  252.  *
  253.  */
  254.  
  255. struct DPTR *
  256. dopen(name, stat)
  257. char *name;
  258. int *stat;
  259. {
  260.    struct DPTR *dp;
  261.  
  262.    *stat = 0;
  263.    dp = (struct DPTR *)malloc(sizeof(struct DPTR));
  264.    if (*name == '\0')
  265.       dp->lock = (struct FileLock *)DupLock ((struct FileLock *)Myprocess->pr_CurrentDir);
  266.    else
  267.       dp->lock = (struct FileLock *)Lock (name, ACCESS_READ);
  268.    if (dp->lock == NULL) {
  269.       free (dp);
  270.       return (NULL);
  271.    }
  272.    dp->fib = (struct FileInfoBlock *)
  273.      AllocMem((long)sizeof(struct FileInfoBlock), MEMF_PUBLIC);
  274.    if (!Examine (dp->lock, dp->fib)) {
  275.       pError (name);
  276.       dclose (dp);
  277.       return (NULL);
  278.    }
  279.    if (dp->fib->fib_DirEntryType >= 0)
  280.       *stat = 1;
  281.    return (dp);
  282. }
  283.  
  284. dnext(dp, pname, stat)
  285. struct DPTR *dp;
  286. char **pname;
  287. int *stat;
  288. {
  289.    if (dp == NULL)
  290.       return (0);
  291.    if (ExNext (dp->lock, dp->fib)) {
  292.       *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
  293.       *pname = dp->fib->fib_FileName;
  294.       return (1);
  295.    }
  296.    return (0);
  297. }
  298.  
  299.  
  300. dclose(dp)
  301. struct DPTR *dp;
  302. {
  303.    if (dp == NULL)
  304.       return (1);
  305.    if (dp->fib)
  306.       FreeMem (dp->fib,(long)sizeof(*dp->fib));
  307.    if (dp->lock)
  308.       UnLock (dp->lock);
  309.    free (dp);
  310.    return (1);
  311. }
  312.  
  313.  
  314. isdir(file)
  315. char *file;
  316. {
  317.    register struct DPTR *dp;
  318.    int stat;
  319.  
  320.    stat = 0;
  321.    if (dp = dopen (file, &stat))
  322.       dclose(dp);
  323.    return (stat == 1);
  324. }
  325.  
  326.  
  327. free_expand(av)
  328. register char **av;
  329. {
  330.    char **base = av;
  331.  
  332.    if (av) {
  333.       while (*av) {
  334.      free (*av);
  335.      ++av;
  336.       }
  337.       free (base);
  338.    }
  339. }
  340.  
  341. /*
  342.  * EXPAND(base,pac)
  343.  *    base         - char * (example: "df0:*.c")
  344.  *    pac         - int  *  will be set to # of arguments.
  345.  *
  346.  * 22-May-87 SJD.  Heavily modified to allow recursive wild carding and
  347.  *           simple directory/file lookups. Returns a pointer to
  348.  *           an array of pointers that contains the full file spec
  349.  *           eg. 'df0:c/sear*' would result in : 'df0:C/Search'
  350.  *
  351.  *           Now no longer necessary to Examine the files a second time
  352.  *           in do_dir since expand will return the full file info
  353.  *           appended to the file name. Set by formatfile().
  354.  *           eg. fullfilename'\0'rwed  NNNNNN NNNN  DD-MMM-YY HH:MM:SS
  355.  *
  356.  *           Caller must call free_expand when done with the array.
  357.  *
  358.  * base            bname =      ename =
  359.  * ------        -------      -------
  360.  *  "*"              ""        "*"
  361.  *  "!*.info"          ""        "*.info" (wild_exclude set)
  362.  *  "su*d/*"          ""        "*"         (tail set)
  363.  *  "file.*"          ""        "file.*"
  364.  *  "df0:c/*"          "df0:c"        "*"
  365.  *  ""              ""        "*"
  366.  *  "df0:.../*"          "df0:"        "*"         (recur set)
  367.  *  "df0:sub/.../*"   "df0:sub"        "*"         (recur set)
  368.  *
  369.  * ---the above base would be provided by execom.c or do_dir().
  370.  * ---the below base would only be called from do_dir().
  371.  *
  372.  *  "file.c"          "file.c"        ""         if (dp == 0) fail else get file.c
  373.  *  "df0:"          "df0:"        "*"
  374.  *  "file/file"          "file/file"   ""         (dp == 0) so fail
  375.  *  "df0:.../"          "df0:"        "*"         (recur set)
  376.  *
  377.  */
  378.  
  379.  
  380. char **
  381. expand(base, pac)
  382. char *base;
  383. int *pac;
  384. {
  385.    register char *ptr;
  386.    char **eav = (char **)malloc(sizeof(char *) * (2));
  387.    short eleft, eac;
  388.    char *name;
  389.    char *svfile();
  390.    char *bname, *ename, *tail;
  391.    int stat, recur, scr,wild_exclude,bl;
  392.    register struct DPTR *dp;
  393.  
  394.    *pac = recur = eleft = eac = wild_exclude = 0;
  395.  
  396.    base = strcpy(malloc(strlen(base)+1), base);
  397.    for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
  398.  
  399.    if (!*ptr)    /* no wild cards */
  400.       --ptr;
  401.    else
  402.       for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
  403.  
  404.    if (ptr < base) {
  405.       bname = strcpy (malloc(1), "");
  406.    } else {
  407.       scr = ptr[1];
  408.       ptr[1] = '\0';
  409.       if (!strcmp(ptr-3,".../")) {
  410.      recur = 1;
  411.      *(ptr-3) = '\0';
  412.       }
  413.       bname = strcpy (malloc(strlen(base)+2), base);
  414.       ptr[1] = scr;
  415.    }
  416.    bl = strlen(bname);
  417.    ename = ++ptr;
  418.    for (; *ptr && *ptr != '/'; ++ptr);
  419.    scr = *ptr;
  420.    *ptr = '\0';
  421.    if (scr) ++ptr;
  422.    tail = ptr;
  423.    if (*ename == '!') wild_exclude = 1;
  424.  
  425.    if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) {
  426.       free (bname);
  427.       free (base);
  428.       free (eav);
  429.       return (NULL);
  430.    }
  431.  
  432.    if (!stat) {               /* eg. 'dir file' */
  433.       char *p,*s;
  434.       for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p;
  435.       if (s != bname) ++s;
  436.       *s ='\0';
  437.       eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib);
  438.       goto done;
  439.    }
  440.    if (!*ename) ename = "*";    /* eg. dir df0: */
  441.    if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */
  442.       bname[bl] = '/';
  443.       bname[++bl] = '\0';
  444.    }
  445.    while ((dnext (dp, &name, &stat)) && !breakcheck()) {
  446.     int match = compare_ok(ename+wild_exclude,name);
  447.  
  448.       if (wild_exclude) match ^= 1;
  449.       if (match && !(!recur && *tail)) {
  450.      if (eleft < 2) {
  451.            char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  452.            movmem (eav, scrav, (eac + 1) << 2);
  453.            free (eav);
  454.            eav = scrav;
  455.            eleft = 10;
  456.      }
  457.      eav[eac++] = svfile(bname,name,dp->fib);
  458.      --eleft;
  459.       }
  460.       if ((*tail && match) || recur) {
  461.      int alt_ac;
  462.      char *search, **alt_av, **scrav;
  463.      struct FileLock *lock;
  464.  
  465.      if (!stat)          /* expect more dirs, but this not a dir */
  466.         continue;
  467.      lock = (struct FileLock *)CurrentDir (dp->lock);
  468.      search = malloc(strlen(ename)+strlen(name)+strlen(tail)+5);
  469.      strcpy (search, name);
  470.      strcat (search, "/");
  471.      if (recur) {
  472.         strcat(search, ".../");
  473.         strcat(search, ename);
  474.      }
  475.      strcat (search, tail);
  476.      scrav = alt_av = expand (search, &alt_ac);
  477.      /* free(search); */
  478.      CurrentDir (lock);
  479.      if (scrav) {
  480.         while (*scrav) {
  481.            int l;
  482.            if (eleft < 2) {
  483.           char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  484.           movmem (eav, scrav, (eac + 1) << 2);
  485.           free (eav);
  486.           eav = scrav;
  487.           eleft = 10;
  488.            }
  489.  
  490.            l = strlen(*scrav);
  491.            scrav[0][l] = ' ';
  492.            eav[eac] = malloc(bl+l+40);
  493.            strcpy(eav[eac], bname);
  494.            strcat(eav[eac], *scrav);
  495.            eav[eac][l+bl] = '\0';
  496.  
  497.            free (*scrav);
  498.            ++scrav;
  499.            --eleft, ++eac;
  500.         }
  501.         free (alt_av);
  502.      }
  503.       }
  504.    }
  505. done:
  506.    dclose (dp);
  507.    *pac = eac;
  508.    eav[eac] = NULL;
  509.    free (bname);
  510.    free (base);
  511.    if (eac) {
  512.       return (eav);
  513.    }
  514.    free (eav);
  515.    return (NULL);
  516. }
  517.  
  518. /*
  519.  * Compare a wild card name with a normal name
  520.  */
  521.  
  522. #define MAXB   8
  523.  
  524. compare_ok(wild, name)
  525. char *wild, *name;
  526. {
  527.    register char *w = wild;
  528.    register char *n = name;
  529.    char *back[MAXB][2];
  530.    register char s1, s2;
  531.    int    bi = 0;
  532.  
  533.    while (*n || *w) {
  534.       switch (*w) {
  535.       case '*':
  536.      if (bi == MAXB) {
  537.         printf(stderr,"Too many levels of '*'\n");
  538.         return (0);
  539.      }
  540.      back[bi][0] = w;
  541.      back[bi][1] = n;
  542.      ++bi;
  543.      ++w;
  544.      continue;
  545. goback:
  546.      --bi;
  547.      while (bi >= 0 && *back[bi][1] == '\0')
  548.         --bi;
  549.      if (bi < 0)
  550.         return (0);
  551.      w = back[bi][0] + 1;
  552.      n = ++back[bi][1];
  553.      ++bi;
  554.      continue;
  555.       case '?':
  556.      if (!*n) {
  557.         if (bi)
  558.            goto goback;
  559.         return (0);
  560.      }
  561.      break;
  562.       default:
  563.      s1 = (*n >= 'A' && *n <= 'Z') ? *n - 'A' + 'a' : *n;
  564.      s2 = (*w >= 'A' && *w <= 'Z') ? *w - 'A' + 'a' : *w;
  565.      if (s1 != s2) {
  566.         if (bi)
  567.            goto goback;
  568.         return (0);
  569.      }
  570.      break;
  571.       }
  572.       if (*n)  ++n;
  573.       if (*w)  ++w;
  574.    }
  575.    return (1);
  576. }
  577.  
  578.  
  579. char *
  580. svfile(s1,s2,fib)
  581. char *s1,*s2;
  582. struct FileInfoBlock *fib;
  583. {
  584.    char *p;
  585.    p = malloc (strlen(s1)+strlen(s2)+40);
  586.    strcpy(p, s1);
  587.    strcat(p, s2);
  588.    formatfile(p,fib);
  589.    return(p);
  590. }
  591.  
  592. /* will have either of these formats:
  593.  *
  594.  *    fullfilename'\0'arwed   <Dir>       DD-MMM-YY HH:MM:SS\n'\0'
  595.  *    fullfilename'\0'arwed  NNNNNN NNNN  DD-MMM-YY HH:MM:SS\n'\0'
  596.  *              01234567890123456789012345678901234567 8 9
  597.  *
  598.  */
  599. formatfile(str,fib)
  600. char *str;
  601. register struct FileInfoBlock *fib;
  602. {
  603.    char *dates();
  604.  
  605.    while(*str++);
  606.  
  607.          
  608.    *str++ = (fib->fib_Protection & FIBF_ARCHIVE)     ? 'a' : ' ';
  609.    *str++ = (fib->fib_Protection & FIBF_READ)        ? '-' : 'r';
  610.    *str++ = (fib->fib_Protection & FIBF_WRITE)        ? '-' : 'w';
  611.    *str++ = (fib->fib_Protection & FIBF_EXECUTE)    ? '-' : 'e';
  612.    *str++ = (fib->fib_Protection & FIBF_DELETE)        ? '-' : 'd';
  613.    
  614.    if (fib->fib_DirEntryType < 0) {
  615.       sprintf(str,"  %6ld %4ld  ", (long)fib->fib_Size, (long)fib->fib_NumBlocks);
  616.    }
  617.    else
  618.       strcpy(str,"   <Dir>       ");
  619.    strcat(str,dates(&fib->fib_Date));
  620. }
  621.