home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 001-099 / ff055.lzh / Csh / comm1.c next >
C/C++ Source or Header  |  1987-03-01  |  24KB  |  1,006 lines

  1. /*
  2.  * COMM1.C
  3.  *
  4.  * Matthew Dillon, August 1986
  5.  *
  6.  * version 2.05M (Manx Version and Additions) by Steve Drew 20-Jan-87
  7.  *
  8.  */
  9.  
  10. #include "shell.h"
  11. typedef struct FileInfoBlock FIB;
  12.  
  13. #define DIR_SHORT 0x01
  14. #define DIR_FILES 0x02
  15. #define DIR_DIRS  0x04
  16. #define DIR_EXCLUDE 0x08
  17.  
  18. #define BPTR_TO_C(strtag, var)  ((struct strtag *)(BADDR( (ULONG) var)))
  19. #define C_TO_BPTR(strtag, var)  ((struct strtag *)(((ULONG)var)>>2))
  20.  
  21. extern char *btocstr();
  22. extern int has_wild;
  23. char cwd[256];
  24. struct FileLock *Clock;
  25.   
  26. do_sleep()
  27. {
  28.    register int i;
  29.  
  30.    if (ac == 2) {
  31.       i = atoi(av[1]);
  32.       while (i > 0) {
  33.          Delay ((long)50*2);
  34.          i -= 2;
  35.          if (CHECKBREAK())
  36.             break;
  37.       }
  38.    }
  39.    return (0);
  40. }
  41.  
  42.  
  43. do_number()
  44. {
  45.    return (0);
  46. }
  47.  
  48. do_cat()
  49. {
  50.    FILE *fopen(), *fi;
  51.    int i;
  52.    char buf[256];
  53.  
  54.    if (ac == 1) {
  55.       while (gets(buf)) {
  56.            if (CHECKBREAK()) break;
  57.          puts(buf);
  58.          }
  59.       clearerr(stdin);
  60.       return (0);
  61.    }
  62.  
  63.    for (i = 1; i < ac; ++i) {
  64.       if ((fi = fopen (av[i], "r")) != 0) {
  65.            while (fgets(buf,256,fi)) {
  66.             fputs(buf,stdout);
  67.             fflush(stdout); 
  68.             if (CHECKBREAK()) {
  69.                breakreset();
  70.                break;
  71.             }
  72.          }
  73.          fclose (fi);
  74.       } else {
  75.          fprintf (stderr, "could not open %s\n", av[i]);
  76.       }
  77.    }
  78.    return (0);
  79. }
  80.  
  81. /* things shared with disp_entry */
  82.  
  83. int   filecount, col; 
  84. long  bytes, blocks;
  85.  
  86. do_dir(garbage, com)
  87. char *garbage;
  88. {
  89.    void           disp_entry();
  90.    struct DPTR          *dp;
  91.    struct InfoData      *info;
  92.    char                 *name;
  93.    int                  i = 0, stat, clen, more;
  94.    char                 options = 0;
  95.    char                 *c;
  96.    char            exclude[40];
  97.    char                 lspec[256];
  98.    char                 volume[40];
  99.    char                 *volname();
  100.    char            *dates();
  101.   
  102.    col = filecount = 0;
  103.    bytes = blocks = 0L;
  104.    
  105.    while((++i < ac) && (av[i][0] == '-')) {
  106.        for (c = av[i]+1; *c ; c++) {
  107.            switch(*c) {
  108.                case 's':
  109.                    options |= DIR_SHORT;
  110.                    break;
  111.                case 'f':
  112.                    options |= DIR_FILES;
  113.                    break;
  114.                case 'd':
  115.                    options |= DIR_DIRS;
  116.                    break;
  117.                case 'e':
  118.                    options |= DIR_EXCLUDE;
  119.                    strcpy(exclude,"*");
  120.                    strcat(exclude,av[++i]);
  121.                    strcat(exclude,"*");
  122.                    break;
  123.                default:
  124.                    break;
  125.            }
  126.        }
  127.    }
  128.    
  129.    if (ac == i) {
  130.       ++ac;
  131.       av[i] = "";
  132.    if (has_wild)
  133.       return(0);
  134.    }
  135.    if (!(options & (DIR_FILES | DIR_DIRS)))  options |= (DIR_FILES | DIR_DIRS);
  136.    
  137.    for (; i < ac; ++i) {
  138.       if (!(dp = dopen (av[i], &stat)))
  139.          continue;
  140.       if (com < 0) {
  141.          info = (struct InfoData *)AllocMem((long)sizeof(struct InfoData), MEMF_PUBLIC);
  142.          if (Info (dp->lock, info)) {
  143.             printf ("Unit:%2ld  Errs:%3ld  Used: %-4ld %3ld%% Free: %-4ld  Volume: %s\n",
  144.                   info->id_UnitNumber,
  145.                   info->id_NumSoftErrors,
  146.                   info->id_NumBlocksUsed,
  147.                   (info->id_NumBlocksUsed * 100)/ info->id_NumBlocks,
  148.                   (info->id_NumBlocks - info->id_NumBlocksUsed),
  149.                   volname(dp->lock,volume));
  150.  
  151.          } else {
  152.             pError (av[i]);
  153.          }
  154.          FreeMem (info,(long) sizeof(*info));
  155.          dclose(dp);
  156.          continue;
  157.          return(0);
  158.       } 
  159.  
  160.      /* start of directory routine */
  161.       
  162.             c = av[i];
  163.             clen = strlen(c);
  164.             if (!stat || has_wild) {    /* if not wild and is a dir don't */
  165.                                          /* extract dir from file name     */
  166.                while (clen && c[clen] != '/' && c[clen] != ':') clen--;
  167.                if (c[clen] == ':' || c[clen] == '/') clen++;
  168.                c[clen] = '\0';
  169.             }
  170.             if (!clen)  c = cwd;
  171.             if (strcmp (c, &lspec) != 0)  {
  172.                strcpy(lspec, c);
  173.                if (col)    printf("\n");
  174.                printf ("Directory of %s\n", lspec);
  175.                fflush(stdout);
  176.                col = 0;
  177.             } 
  178.             more = stat;
  179.             do {
  180.                 if (more && !has_wild) {
  181.                     *lspec = '\0';
  182.                     if (!(more = dnext(dp, &name, &stat)))
  183.                     break;
  184.                 }
  185.                 if (CHECKBREAK()) {
  186.                      i = ac;
  187.                      break;
  188.                 }
  189.                 disp_entry (dp->fib, options,exclude);
  190.       } while(more && !has_wild);     
  191.       dclose(dp); 
  192.     }                /* end for */
  193.    if (col)  printf("\n");    
  194.    if (filecount > 1) {
  195.        blocks += filecount;     /* account for dir blocks */
  196.        printf (" %ld Blocks, %ld Bytes used in %d files\n", blocks, bytes, filecount);
  197.    }
  198.    return (0);
  199. }
  200.  
  201. char *
  202. volname(lock,buf)
  203. struct FileLock *lock;
  204. char *buf;
  205. {
  206.  
  207.         struct    DeviceList    *dl;
  208.         char                    *p;
  209.  
  210.      Forbid();
  211.                 /* Only way I know to get Volume label since InfoData  */
  212.                 /* seems to always have NULL for this string           */
  213.  
  214.         lock = BPTR_TO_C(FileLock, lock);
  215.         dl = BPTR_TO_C(DeviceList, lock->fl_Volume);
  216.         p = btocstr(dl->dl_Name,buf);
  217.  
  218.      Permit();
  219.      return p;
  220. }
  221.  
  222. void
  223. disp_entry(fib, options, exclude)
  224. char options;
  225. char *exclude;
  226. register struct FileInfoBlock *fib;
  227. {
  228.  
  229.    char str[5];
  230.    int italics;
  231.    char s;   
  232.    
  233.    if (!(((options & DIR_FILES) && (fib->fib_DirEntryType < 0)) || 
  234.          ((options & DIR_DIRS)  && (fib->fib_DirEntryType > 0))))
  235.                 return;
  236.  
  237.    if ((options & DIR_EXCLUDE) && (compare_ok(exclude,fib->fib_FileName)))
  238.            return;
  239.                 
  240.  if (!(options & DIR_SHORT)) { 
  241.    str[4] = '\0';
  242.    str[0] = (fib->fib_Protection & FIBF_READ) ? '-' : 'r';
  243.    str[1] = (fib->fib_Protection & FIBF_WRITE) ? '-' : 'w';
  244.    str[2] = (fib->fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
  245.    str[3] = (fib->fib_Protection & FIBF_DELETE) ? '-' : 'd';
  246.  
  247.    printf ("   %-24s  %s  ", fib->fib_FileName, str);
  248.    if (fib->fib_DirEntryType < 0) printf("%6ld %4ld", (long)fib->fib_Size, (long)fib->fib_NumBlocks);
  249.     else printf("   Dir     ");
  250.    printf("  %s", dates(&fib->fib_Date));
  251.    fflush(stdout);
  252.    } 
  253.    else {
  254.    
  255.         if ((col == 3) && strlen(fib->fib_FileName)>18) {
  256.             printf("\n");
  257.             col = 0;
  258.         } 
  259.         if (fib->fib_DirEntryType > 0)  {
  260.             printf ("\033[3m");
  261.             italics = 1;
  262.         }
  263.         if (strlen(fib->fib_FileName)>18) {
  264.             printf(" %-37s",fib->fib_FileName);
  265.             col += 2;
  266.         } 
  267.         else { 
  268.             printf(" %-18s",fib->fib_FileName);
  269.             col++;
  270.         } 
  271.         if (col > 3) {
  272.             printf("\n");
  273.             col = 0;
  274.         }
  275.         if (italics) printf("\033[0m");
  276.    }
  277.    fflush(stdout);
  278.    blocks += fib->fib_NumBlocks;
  279.    bytes  += fib->fib_Size;
  280.    filecount++;
  281.    return;
  282. }
  283.  
  284. /* converts dos date stamp to a time string of form dd-mmm-yy  */
  285.  
  286. char *
  287. dates(dss)
  288. struct DateStamp *dss;
  289. {
  290.    register struct tm tm;
  291.    register long time, t;
  292.    register int i;
  293.    static char timestr[20];
  294.    static char months[12][4] = {
  295.        "Jan","Feb","Mar","Apr","May","Jun",
  296.        "Jul","Aug","Sep","Oct","Nov","Dec"
  297.    };
  298.    static char days[12] = {
  299.        31,28,31,30,31,30,31,31,30,31,30,31
  300.    };
  301.    time = dss->ds_Days * 24 * 60 * 60 + dss->ds_Minute * 60 +
  302.                           dss->ds_Tick/TICKS_PER_SECOND;
  303.    tm.tm_sec = time % 60; time /= 60;
  304.    tm.tm_min = time % 60; time /= 60;
  305.    tm.tm_hour= time % 24; time /= 24;
  306.    tm.tm_wday= time %  7;
  307.    tm.tm_year= 78 + (time/(4*365+1)) * 4; time %= 4 * 365 + 1;
  308.    while (time) {
  309.        t = 365;
  310.        if ((tm.tm_year&3) == 0) t++;
  311.        if (time < t) break;
  312.        time -= t;
  313.        tm.tm_year++;
  314.    }
  315.    tm.tm_yday = ++time;
  316.    for (i=0;i<12;i++) {
  317.        t = days[i];
  318.        if (i == 1 && (tm.tm_year&3) == 0) t++;
  319.        if (time <= t) break;
  320.        time -= t;
  321.    }  
  322.    tm.tm_mon = i;
  323.    tm.tm_mday = time;
  324.    
  325.    sprintf(timestr,"%02d-%s-%2d %02d:%02d:%02d\n",tm.tm_mday,
  326.            months[tm.tm_mon],tm.tm_year,
  327.            tm.tm_hour,tm.tm_min,tm.tm_sec);
  328.    return(timestr);
  329.    
  330. }
  331.  
  332. date()
  333. {
  334.    struct   DateStamp   dss;
  335.    char *s, *dates();
  336.  
  337.    DateStamp(&dss);
  338.    s = dates(&dss);
  339.    printf("%s",s);
  340.    return(0);
  341. }
  342.  
  343. do_quit()
  344. {
  345.    if (Src_stack) {
  346.       Quit = 1;
  347.       return(do_return());
  348.    }
  349.    main_exit (0);
  350. }
  351.  
  352.  
  353. do_echo(str)
  354. char *str;
  355. {
  356.    register char *ptr;
  357.    char nl = 1;
  358.  
  359.    for (ptr = str; *ptr && *ptr != ' '; ++ptr);
  360.    if (*ptr == ' ')
  361.       ++ptr;
  362.    if (av[1] && strcmp (av[1], "-n") == 0) {
  363.       nl = 0;
  364.       ptr += 2;
  365.       if (*ptr == ' ')
  366.          ++ptr;
  367.    }
  368.    printf("%s",ptr);
  369.    fflush(stdout);
  370.    if (nl)
  371.       printf("\n");
  372.    return (0);
  373. }
  374.  
  375. do_source(str)
  376. char *str;
  377. {
  378.    register FILE *fi;
  379.    char buf[256];
  380.  
  381.    if (Src_stack == MAXSRC) {
  382.       printf (stderr,"Too many source levels\n");
  383.       return(-1);
  384.    }
  385.    if ((fi = fopen (av[1], "r")) == 0) {
  386.       fprintf (stderr,"Cannot open %s\n", av[1]);
  387.       return(-1);
  388.    }   
  389.    set_var(LEVEL_SET, V_PASSED, next_word(next_word(str)));
  390.    ++H_stack;
  391.    Src_pos[Src_stack] = 0;
  392.    Src_base[Src_stack] = (long)fi;
  393.    ++Src_stack;
  394.    while (fgets (buf, 256, fi)) {
  395.       buf[strlen(buf)-1] = '\0';
  396.       Src_pos[Src_stack - 1] += 1+strlen(buf);
  397.       if (Verbose)
  398.          fprintf(stderr,"%s\n",buf);
  399.       exec_command (buf);
  400.       if (CHECKBREAK())
  401.          break;
  402.    }
  403.    --H_stack;
  404.    --Src_stack;
  405.    unset_level(LEVEL_LABEL + Src_stack);
  406.    unset_var(LEVEL_SET, V_PASSED);
  407.    fclose (fi);
  408.    return (0);
  409. }
  410.  
  411. /*
  412.  * CD
  413.  *
  414.  * CD(str, -1)      -do pwd and display current cd. if str = NULL don't disp.
  415.  * CD(str, 0)       -do CD operation.
  416.  *
  417.  *    standard operation: breakup path by '/'s and process independantly
  418.  *    x:    -reset cwd base
  419.  *    ..    -remove last cwd element
  420.  *    N     -add N or /N to cwd
  421.  */
  422.  
  423. do_cd(str, com)
  424. char *str;
  425. {
  426.    char sc, *ptr;
  427.    char *name;
  428.  
  429.    if (com < 0) {
  430.       struct FileLock *lock, *newlock;
  431.       FIB *fib;
  432.       int i, len;
  433.  
  434.       fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
  435.       if ((Clock = (struct FileLock *)Myprocess->pr_CurrentDir) == 0) 
  436.           attempt_cd(":"); /* if we just booted 0 = root lock */
  437.       lock = (struct FileLock *)DupLock(Clock);
  438.       cwd[i = 255] = '\0';
  439.       
  440.       while (lock) {
  441.          newlock = (struct FileLock *)ParentDir(lock);
  442.          Examine(lock, fib);
  443.          name = fib->fib_FileName;
  444.          if (*name == '\0')            /* HACK TO FIX RAM: DISK BUG */
  445.             name = "ram";
  446.          len = strlen(name);
  447.          if (newlock) {
  448.             if (i == 255) {
  449.                i -= len;
  450.                bmov(name, cwd + i, len);
  451.             } else {
  452.                i -= len + 1;
  453.                bmov(name, cwd + i, len);
  454.                cwd[i+len] = '/';
  455.             }
  456.          } else {
  457.             i -= len + 1;
  458.             bmov(name, cwd + i, len);
  459.             cwd[i+len] = ':';
  460.          }
  461.          UnLock(lock);
  462.          lock = newlock;
  463.       }
  464.       FreeMem(fib, (long)sizeof(FIB));
  465.       bmov(cwd + i, cwd, 256 - i);
  466.       if (str)
  467.          puts(cwd);
  468.       set_var(LEVEL_SET, V_CWD, cwd);
  469.  
  470.      /* put the current dir name in our CLI task structure */
  471.  
  472.       ptr = (char *)((ULONG)((struct CommandLineInterface *)
  473.           BADDR(Myprocess->pr_CLI))->cli_SetName << 2);
  474.       ptr[0] = strlen(cwd);
  475.       movmem(cwd,ptr+1,(int)ptr[0]);
  476.       return (0);
  477.    }
  478.    str = next_word(str);
  479.    if (*str == '\0')
  480.       puts(cwd);
  481.    str[strlen(str)+1] = '\0';          /* add second \0 on end */
  482.    while (*str) {
  483.       for (ptr = str; *ptr && *ptr != '/' && *ptr != ':'; ++ptr);
  484.       switch (*ptr) {
  485.       case ':':
  486.          sc = ptr[1];
  487.          ptr[1] = '\0';
  488.          if (attempt_cd(str))
  489.             strcpy(cwd, str);
  490.          ptr[1] = sc;
  491.          break;
  492.       case '\0':
  493.       case '/':
  494.          *ptr = '\0';
  495.          if (strcmp(str, "..") == 0 || str == ptr)
  496.             str = "/";
  497.          if (*str && attempt_cd(str)) {
  498.             if (*str == '/') {
  499.                rmlast(cwd);
  500.             } else {
  501.                if (cwd[0] == 0 || cwd[strlen(cwd)-1] != ':')
  502.                   strcat(cwd, "/");
  503.                strcat(cwd, str);
  504.             }
  505.          }
  506.          break;
  507.       }
  508.       str = ptr + 1;
  509.    }
  510.    do_cd(NULL,-1);
  511. }
  512.  
  513. attempt_cd(str)
  514. char *str;
  515. {
  516.    struct FileLock *oldlock, *filelock;
  517.  
  518.    if (filelock = (struct FileLock *)Lock(str, ACCESS_READ)) {
  519.       if (isdir(str)) {
  520.          if (oldlock = (struct FileLock *)CurrentDir(filelock))
  521.             UnLock(oldlock);
  522.          Clock = filelock;
  523.          return (1);
  524.       }
  525.       UnLock(filelock);
  526.       ierror(str, 212);
  527.    } else {
  528.       ierror(str, 205);
  529.    }
  530.    return (0);
  531. }
  532.  
  533.  
  534. /*
  535.  * remove last component. Start at end and work backwards until reach
  536.  * a '/'
  537.  */
  538.  
  539. rmlast(str)
  540. char *str;
  541. {
  542.    char *ptr = str + strlen(str) - 1;
  543.    while (ptr != str && *ptr != '/' && *ptr != ':')
  544.       --ptr;
  545.    if (*ptr != ':')
  546.       ptr[0] = '\0';
  547.    else
  548.       ptr[1] = '\0';
  549. }
  550.  
  551.  
  552. do_mkdir()
  553. {
  554.    register int i;
  555.    register struct FileLock *lock;
  556.  
  557.    for (i = 1; i < ac; ++i) {
  558.       if (lock = (struct FileLock *)CreateDir (av[i])) {
  559.          UnLock (lock);
  560.          continue;
  561.       }
  562.       pError (av[i]);
  563.    }
  564.    return (0);
  565. }
  566.  
  567.  
  568. do_mv()
  569. {
  570.    char dest[256];
  571.    register int i;
  572.    char *str;
  573.  
  574.    --ac;
  575.    if (isdir(av[ac])) {
  576.       for (i = 1; i < ac; ++i) {
  577.          str = av[i] + strlen(av[i]) - 1;
  578.          while (str != av[i] && *str != '/' && *str != ':')
  579.             --str;
  580.          if (str != av[i])
  581.             ++str;
  582.          if (*str == 0) {
  583.             ierror(av[i], 508);
  584.             return (-1);
  585.          }
  586.          strcpy(dest, av[ac]);
  587.          if (dest[strlen(dest)-1] != ':')
  588.             strcat(dest, "/");
  589.          strcat(dest, str);
  590.          if (Rename(av[i], dest) == 0)
  591.             break;
  592.       }
  593.       if (i == ac)
  594.          return (1);
  595.    } else {
  596.       i = 1;
  597.       if (ac != 2) {
  598.          ierror("", 507);
  599.          return (-1);
  600.       }
  601.       if (Rename (av[1], av[2]))
  602.          return (0);
  603.    }
  604.    pError (av[i]);
  605.    return (-1);
  606. }
  607.  
  608. rm_file(file)
  609. char *file;
  610. {
  611.       if (has_wild) printf("  %s...",file);
  612.       fflush(stdout);
  613.       if (!DeleteFile(file))
  614.          pError (file);
  615.       else 
  616.          if (has_wild) printf("Deleted\n");
  617. }
  618.  
  619. do_rm()
  620. {
  621.    register short i, recur;
  622.  
  623.    recur = (strncmp(av[1], "-r", 2)) ? 0 : 1;
  624.  
  625.    for (i = 1 + recur; i < ac; ++i) {
  626.       if (CHECKBREAK()) break;
  627.       if (isdir(av[i]) && recur)
  628.          rmdir(av[i]);
  629.       if (!(recur && av[i][strlen(av[i])-1] == ':')) 
  630.          rm_file(av[i]);
  631.    }
  632.    return (0);
  633. }
  634.  
  635. rmdir(name)
  636. char *name;
  637. {
  638.    register struct FileLock *lock, *cwd;
  639.    register FIB *fib;
  640.    register char *buf;
  641.  
  642.    buf = (char *)AllocMem(256L, MEMF_PUBLIC);
  643.    fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
  644.  
  645.    if (lock = (struct FileLock *)Lock(name, ACCESS_READ)) {
  646.       cwd = (struct FileLock *) CurrentDir(lock);
  647.       if (Examine(lock, fib)) {
  648.          buf[0] = 0;
  649.          while (ExNext(lock, fib)) {
  650.             if (CHECKBREAK()) break;
  651.             if (isdir(fib->fib_FileName))
  652.                rmdir(fib->fib_FileName);
  653.             if (buf[0]) {
  654.                rm_file(buf);
  655.             }
  656.             strcpy(buf, fib->fib_FileName);
  657.          }
  658.          if (buf[0] && !CHECKBREAK()) {
  659.             rm_file(buf);
  660.          }
  661.       }
  662.       UnLock(CurrentDir(cwd));
  663.    } else {
  664.       pError(name);
  665.    }
  666.    FreeMem(fib, (long)sizeof(FIB));
  667.    FreeMem(buf, 256L);
  668. }
  669.  
  670.  
  671.  
  672. do_history()
  673. {
  674.    register struct HIST *hist;
  675.    register int i = H_tail_base;
  676.    register int len = (av[1]) ? strlen(av[1]) : 0;
  677.  
  678.    for (hist = H_tail; hist; hist = hist->prev) {
  679.       if (len == 0 || strncmp(av[1], hist->line, len) == 0) {
  680.          printf ("%3d ", i);
  681.          puts (hist->line);
  682.       }
  683.       ++i;
  684.       if (CHECKBREAK())
  685.          break;
  686.    }
  687.    return (0);
  688. }
  689.  
  690. do_mem()
  691. {
  692.    long cfree, ffree;
  693.    extern long AvailMem();
  694.  
  695.    Forbid();
  696.    cfree = AvailMem (MEMF_CHIP);
  697.    ffree = AvailMem (MEMF_FAST);
  698.    Permit();
  699.  
  700.    if (ffree)       {
  701.    printf ("FAST memory: %ld\n", ffree);  
  702.    printf ("CHIP memory: %ld\n", cfree);   
  703.    }
  704.    printf ("Total  Free: %ld\n", cfree + ffree);
  705.    return(0);
  706. }
  707.  
  708. /*
  709.  * foreach var_name  ( str str str str... str ) commands
  710.  * spacing is important (unfortunetly)
  711.  *
  712.  * ac=0    1 2 3 4 5 6 7
  713.  * foreach i ( a b c ) echo $i
  714.  * foreach i ( *.c )   "echo -n "file ->";echo $i"
  715.  */
  716.  
  717. do_foreach()
  718. {
  719.    register int i, cstart, cend, old;
  720.    register char *cstr, *vname, *ptr, *scr, *args;
  721.  
  722.    cstart = i = (*av[2] == '(') ? 3 : 2;
  723.    while (i < ac) {
  724.       if (*av[i] == ')')
  725.          break;
  726.       ++i;
  727.    }
  728.    if (i == ac) {
  729.       fprintf (stderr,"')' expected\n");
  730.       return (-1);
  731.    }
  732.    ++H_stack;
  733.    cend = i;
  734.    vname = strcpy(malloc(strlen(av[1])+1), av[1]);
  735.    cstr = compile_av (av, cend + 1, ac);
  736.    ptr = args = compile_av (av, cstart, cend);
  737.    while (*ptr) {
  738.       while (*ptr == ' ' || *ptr == 9)
  739.          ++ptr;
  740.       scr = ptr;
  741.       if (*scr == '\0')
  742.          break;
  743.       while (*ptr && *ptr != ' ' && *ptr != 9)
  744.          ++ptr;
  745.       old = *ptr;
  746.       *ptr = '\0';
  747.       set_var (LEVEL_SET, vname, scr);
  748.       if (CHECKBREAK())
  749.          break;
  750.       exec_command (cstr);
  751.       *ptr = old;
  752.    }
  753.    --H_stack;
  754.    free (args);
  755.    free (cstr);
  756.    unset_var (LEVEL_SET, vname);
  757.    free (vname);
  758.    return (0);
  759. }
  760.  
  761.  
  762. do_forever(str)
  763. char *str;
  764. {
  765.    int rcode = 0;
  766.    char *ptr = next_word(str);
  767.  
  768.    ++H_stack;
  769.    for (;;) {
  770.       if (CHECKBREAK()) {
  771.          rcode = 20;
  772.          break;
  773.       }
  774.       if (exec_command (ptr) < 0) {
  775.          str = get_var(LEVEL_SET, V_LASTERR);
  776.          rcode = (str) ? atoi(str) : 20;
  777.          break;
  778.       }
  779.    }
  780.    --H_stack;
  781.    return (rcode);
  782. }
  783.  
  784.  
  785. /*
  786.  * CP file file
  787.  * CP file file file... destdir
  788.  * CP [-r] dir dir dir... destdir
  789.  */
  790.  
  791. char *errstr;          /* let's be alittle more informative */
  792.  
  793. do_copy()
  794. {
  795.    register short recur, i, ierr;
  796.    register char *destname;
  797.    register char destisdir;
  798.    register FIB *fib;
  799.    
  800.    errstr = "";
  801.    ierr = 0;
  802.    fib = (FIB *)AllocMem((long)sizeof(FIB), 0);
  803.    recur = (strncmp(av[1], "-r", 2)) ? 0 : 1;
  804.    destname = av[ac - 1];
  805.  
  806.    if (ac < recur + 3) {
  807.       ierr = 500;
  808.       goto done;
  809.    }
  810.  
  811.    destisdir = isdir(destname);
  812.    if (ac > recur + 3 && !destisdir) {
  813.       ierr = 507;
  814.       goto done;
  815.    }
  816.  
  817.    /*
  818.     * copy set:                        reduce to:
  819.     *    file to file                     file to file
  820.     *    dir  to file (NOT ALLOWED)
  821.     *    file to dir                      dir to dir
  822.     *    dir  to dir                      dir to dir
  823.     *
  824.     */
  825.  
  826.    fflush(stdout);
  827.    stdout->_buflen = 1;
  828.    for (i = recur + 1; i < ac - 1; ++i) {
  829.       short srcisdir = isdir(av[i]);
  830.       if (srcisdir && has_wild && (ac >2)) /* hack to stop dir's from */
  831.           continue;               /* getting copied if specified */
  832.                                  /* from wild expansion */
  833.       if (CHECKBREAK())
  834.          break;
  835.       if (srcisdir) {
  836.          struct FileLock *srcdir, *destdir;
  837.          if (!destisdir) {        /* disallow dir to file */
  838.             ierr = 507;
  839.             goto done;
  840.          }
  841.          if (!(destdir = (struct FileLock *)Lock(destname, ACCESS_READ))) {
  842.             ierr = 205;
  843.             errstr = destname;
  844.             goto done;
  845.          }
  846.          if (!(srcdir = (struct FileLock *)Lock(av[i], ACCESS_READ))) {
  847.             ierr = 205;
  848.             errstr = av[i];
  849.             UnLock(destdir);
  850.             goto done;
  851.          }
  852.          ierr = copydir(srcdir, destdir, recur);
  853.          UnLock(srcdir);
  854.          UnLock(destdir);
  855.          if (ierr)
  856.             break;
  857.       } else {                      /* FILE to DIR,   FILE to FILE   */
  858.          struct FileLock *destdir, *srcdir, *tmp;
  859.          char *destfilename;
  860.  
  861.          srcdir = (struct FileLock *)((struct Process *)FindTask(0))->pr_CurrentDir;
  862.          if (destisdir) {
  863.             if ((tmp = (struct FileLock *)Lock(av[i], ACCESS_READ)) == NULL || !Examine(tmp,fib)){
  864.                if (tmp) UnLock(tmp);
  865.                ierr = 205;
  866.                errstr = av[i];
  867.                goto done;
  868.             }
  869.             UnLock(tmp);
  870.             destdir = (struct FileLock *)Lock(destname, ACCESS_READ);
  871.             destfilename = fib->fib_FileName;
  872.          } else {
  873.             destdir = srcdir;
  874.             destfilename = destname;
  875.          }
  876.          printf(" %s..",av[i]);
  877.          ierr = copyfile(av[i], srcdir, destfilename, destdir);
  878.          if (destisdir)
  879.             UnLock(destdir);
  880.          if (ierr)
  881.             break;
  882.       }
  883.    }
  884. done:
  885.    stdout->_buflen = STDBUF;            /* set back to buffr'd */
  886.    FreeMem(fib, (long)sizeof(*fib));
  887.    if (ierr) {
  888.       ierror(errstr, ierr);
  889.       return(20);
  890.    }
  891.    return(0);
  892. }
  893.  
  894.  
  895. copydir(srcdir, destdir, recur)
  896. register struct FileLock *srcdir, *destdir;
  897. {
  898.    struct FileLock *cwd;
  899.    register FIB *srcfib;
  900.    register struct FileLock *destlock, *srclock;
  901.    int ierr;
  902.    static int level; 
  903.  
  904.    level++;
  905.    ierr = 0;
  906.    srcfib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
  907.    if (Examine(srcdir, srcfib)) {
  908.       while (ExNext(srcdir, srcfib)) {
  909.          if (CHECKBREAK())
  910.         break;
  911.          if (srcfib->fib_DirEntryType < 0) {
  912.         printf("%*s%s..",(level-1) * 6," ",srcfib->fib_FileName);
  913.             ierr = copyfile(srcfib->fib_FileName,srcdir,srcfib->fib_FileName,destdir);
  914.             if (ierr)
  915.                break;
  916.          } else {
  917.             if (recur) {
  918.                cwd = (struct FileLock *)CurrentDir(srcdir);
  919.                if (srclock = (struct FileLock *)Lock(srcfib->fib_FileName, ACCESS_READ)) {
  920.                   CurrentDir(destdir);
  921.                   if (!(destlock = (struct FileLock *)
  922.                 Lock(srcfib->fib_FileName))) {
  923.                      destlock = (struct FileLock *)CreateDir(srcfib->fib_FileName);
  924.                printf("%*s%s (Dir)....[Created]\n",(level-1) * 6,
  925.                   " ",srcfib->fib_FileName); 
  926.           }
  927.             else 
  928.              printf("%*s%s (Dir)\n",(level-1) * 6," ",srcfib->fib_FileName); 
  929.                   if (destlock) {
  930.                      ierr = copydir(srclock, destlock, recur);
  931.                      UnLock(destlock);
  932.                   } else {
  933.                      ierr = (int)((long)IoErr());
  934.                   }
  935.                   UnLock(srclock);
  936.                } else {
  937.                   ierr = (int)((long)IoErr());
  938.                }
  939.                CurrentDir(cwd);
  940.                if (ierr)
  941.                   break;
  942.             }
  943.          }
  944.       }
  945.    } else {
  946.       ierr = (int)((long)IoErr());
  947.    }      
  948.    --level;
  949.    FreeMem(srcfib, (long)sizeof(FIB));
  950.    return(ierr);
  951. }
  952.  
  953.  
  954. copyfile(srcname, srcdir, destname, destdir)
  955. char *srcname, *destname;
  956. struct FileLock *srcdir, *destdir;
  957. {
  958.    struct FileLock *cwd;
  959.    struct FileHandle *f1, *f2;
  960.    long i; 
  961.    int ierr;
  962.    char *buf;
  963.  
  964.    buf = (char *)AllocMem(8192L, MEMF_PUBLIC|MEMF_CLEAR);   
  965.    if (buf == NULL) {
  966.       ierr = 103;
  967.       goto fail;
  968.    }
  969.  
  970.    ierr = 0;
  971.    cwd = (struct FileLock *)CurrentDir(srcdir);
  972.    f1 = Open(srcname, MODE_OLDFILE);
  973.    if (f1 == NULL) {
  974.       errstr = srcname;
  975.       ierr = 205;
  976.       goto fail;
  977.    }
  978.    CurrentDir(destdir);
  979.    f2 = Open(destname, MODE_NEWFILE);
  980.    if (f2 == NULL) {
  981.       Close(f1);
  982.       ierr = (int)((long)IoErr());
  983.       errstr = destname;
  984.       goto fail;
  985.    }
  986.    while (i = Read(f1, buf, 8192L))
  987.       if (Write(f2, buf, i) != i) {
  988.          ierr = (int)((long)IoErr());
  989.      break;
  990.       }
  991.    Close(f2);
  992.    Close(f1);
  993.    if (!ierr)  {
  994.       printf("..copied\n"); 
  995.    }
  996.    else {
  997.       DeleteFile(destname);
  998.       printf("..Not copied..");
  999.    }
  1000. fail:
  1001.    if (buf) 
  1002.       FreeMem(buf, 8192L);
  1003.    CurrentDir(cwd);
  1004.    return(ierr);
  1005. }
  1006.