home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / beehive / program / cshell.arc / SH.C < prev    next >
Text File  |  1990-11-03  |  14KB  |  686 lines

  1. /*
  2.  *    Little Shell Version 2.1
  3.  *    Copyright (c) 1982 Steve Blasingame
  4.  *    edit of 3-7-82
  5.  */
  6. #include    <bdscio.h>
  7. #include    <fcb.h>
  8. #include    <doglob.h>
  9. #define    EOT    4    /* ascii eot */
  10. #define    PROMPT    "$ "    /* prompt string */
  11. #define TABSIZE    7    /* spaces in a tab */
  12. #define    CNTLH    8    /* backspace */
  13. #define DEL    0x7f    /* ascii del */
  14. #define QUIT    0x1c    /* cntl-backslash */
  15. #define LINEKILL 24    /* cntl-x */
  16. #define    SLEEPNO    16    /* sleep constant for 4 Mz Z80a */
  17. #define COMMENT    '#'    /* comment line */
  18. #define    stdin    0    /* for console io */
  19. #define    stdout    1    /* for console io */
  20. #define    FILE    struct _buf
  21. #define SHBUF    0xf54b    /* Buffer in current bios */
  22. char    combuf[MAXLINE]; /* command line buffer */
  23. char    globs[GLOBMAX*FILENAMESIZE]; /* expansion buffer */
  24. int    argvp[20];    /* array of argument pointers */
  25. int    argcp;        /* argument count for execv */
  26. int    testmode;    /* verbose flag */
  27. int    flag;        /* for lst function */
  28.  
  29. /* Structure of Shell's Storage Area in the CBIOS */
  30. struct    exbuf    {
  31.     char    _shdsk;        /* current directory */
  32.     int    _shsav;        /* buffer save flag  */
  33.     char    _nocli;        /* no shell option */
  34.     char    _shbuf[BUFSIZ]; /* buffer */
  35. };
  36.  
  37. struct exbuf *iop;        /* pointer to bios buffer */
  38. int    parse();        /* parse command line */
  39. int    dolocal();        /* do built-in shell commands */
  40. int    lexecv();        /* local execv until C1.45a */
  41. char    *b_gets();        /* local crt driver */
  42. char    pwd();            /* return current logical disk */
  43. char    chdir();        /* select disk */
  44. int    filprt();        /* list selected file on screen */
  45. int    lst();            /* format directory listing */
  46. int    dofile();        /* process shell script */
  47. int    flock();        /* lock or unlock file */
  48. int    doshell();        /* exec the shell */
  49. int    expand();        /* expand global filenames */
  50. int    dozap();        /* interactively delete files */
  51. int    doglob();        /* parse global file expressions */
  52. int    more();            /* list multiple files on screen */
  53. int    crfil();        /* fill memory */
  54. int    strcmp();
  55.  
  56. main(argc,argv)
  57. int argc;
  58. char *argv[];
  59. {
  60. char *cp;
  61.  
  62. _allocp = 0;    /* initializer */
  63. iop = SHBUF;    /* initializer */
  64. testmode = 0;    /* initializer */
  65. iop->_nocli = 0;    /* default shell on reboot */
  66. if (argc == 2 && (strcmp(argv[1],"-T") == 0)) testmode =1;
  67. if (argc == 3 && (strcmp(argv[1],"-F") == 0)) parse(strlower(argv[2]));
  68.  
  69.  
  70.     bdos(0x0e, iop->_shdsk);    /* restore cwd */
  71.  
  72.     while (1) {
  73.         crfil(combuf,MAXLINE,0);
  74.         if (!iop->_shsav) {
  75.             puts(PROMPT);
  76.             if (!b_gets(combuf))
  77.                 break;
  78.             else {
  79.                 cp = combuf;
  80.                 if (parse(cp) == -1)
  81.                     puts("what?\n");
  82.             }
  83.         }
  84.         else {
  85.             strcpy(combuf,&iop->_shbuf);
  86.             iop->_shsav = 0;
  87.             cp = combuf;
  88.             if (parse(cp) == -1)
  89.                 puts("syntax error\n");
  90.         }
  91.     }
  92. chdir('a');            /* home directory */
  93. if (execl("a:login",0) == -1)    /* admittedly a kluge */
  94.     ;
  95. doshell();
  96. }
  97. parse(cp)
  98. char *cp;
  99. {
  100. int i;
  101. char    *pointer;
  102. i=0;
  103. argvp[i]=cp;
  104.  
  105.     if (testmode) puts(cp);
  106.     if (*cp == '\n')
  107.         return 0;
  108.     else {
  109.         while(*cp == ' ')    /* skip blanks */
  110.             cp++;
  111.         argvp[i]=cp;
  112.         while(*++cp != NULL) {
  113.             if (*cp == ' ') {
  114.                 i++;
  115.                 *cp = NULL;
  116.                 argvp[i]=cp+1;
  117.             }
  118.             else if (*cp == ';') {
  119.                 if (cp == combuf || *(cp+1) != ' ')
  120.                     return -1;
  121.                 else {
  122.                     i++;
  123.                     *cp = NULL;
  124.                     argvp[i]=NULL;
  125.                     cp += 2;
  126.                     strcpy(iop->_shbuf,cp);
  127.                     iop->_shsav = 1;
  128.                     break;
  129.                 }
  130.             }
  131.             else if (*cp == '\n') {
  132.                 i++;
  133.                 *cp = NULL;
  134.                 argvp[i]=NULL;
  135.                 break;
  136.             }
  137.         }
  138.     argcp = 0;
  139.     while(1) {
  140.         if (!argvp[argcp]) break;
  141.         argcp++;
  142.     }
  143.     if (dolocal(&argvp)) {
  144.         return 0;
  145.     }
  146.     else {
  147.         pointer = &argvp + 1;
  148.         if (lexecv(argvp[0], pointer) == -1) {
  149.             if (dofile(argcp,&argvp) == -1) {
  150.                 puts(argvp[0]);
  151.                 puts(": not found\n");
  152.             }
  153.         return 0;
  154.         }
  155.     }
  156.     }
  157. return(-1);
  158. }
  159. dolocal(ptr)
  160. char *ptr[];
  161. {
  162. int value;
  163. char *tpoint;
  164.     if (strcmp(*ptr,"clr") == 0) {
  165.         puts(CLEARS);
  166.         return 1;
  167.     }
  168.     else if (strcmp(*ptr,"ccp") == 0) {
  169.         iop->_nocli = 1;    /* set no shell mode */
  170.         bios(1,0);        /* warm boot cpm */
  171.     }
  172.     else if (strcmp(*ptr,"exit") == 0) {
  173.         iop->_shsav = 0;    /* flush shell buffer */
  174.         bios(1,0);        /* warm boot cpm */
  175.     }
  176.     else if (**ptr == COMMENT) return 1;
  177.     else if (strcmp(*ptr,"logout") == 0) {
  178.         chdir('a');    /* set default directory */
  179.         execl("a:login",0);
  180.         ;
  181.         return 1;
  182.     }
  183.     else if (strcmp(*ptr,"echo") == 0) {
  184.         ++ptr;
  185.         while (*ptr != 0) {
  186.             puts(*ptr);
  187.             putchar(' ');
  188.             ptr++;
  189.         }
  190.         putchar('\n');
  191.         return 1;
  192.     }
  193.     else if (strcmp(*ptr,"pwd") == 0) {
  194.             putchar(pwd());    /* print current disk */
  195.             puts(":\n");
  196.             return 1;
  197.     }
  198.     else if (strcmp(*ptr,"cd") == 0) {
  199.             chdir(**++ptr);    /* set default disk */
  200.         return 1;
  201.     }
  202.     else if (strcmp(*ptr,"sleep") == 0) {
  203.         value = (SLEEPNO * atoi(*++ptr));
  204.         sleep(value);
  205.         return 1;
  206.     }
  207.     else if (strcmp(*ptr,"rm") == 0) {
  208.         ++ptr;    /* remove files */
  209.         if (*ptr == 0 || **ptr == '\n' || **ptr == 0) {
  210.             puts("usage: rm [file] [file...]\n");
  211.             return 1;
  212.         }
  213.         while (*ptr != NULL && **ptr != NULL) {
  214.             expand(dozap,*ptr,0);
  215.             ptr++;
  216.         }
  217.     return 1;
  218.     }
  219.     else if (strcmp(*ptr,"lock") == 0) {
  220.         ++ptr;
  221.         if (*ptr == 0 || **ptr == '\n' || **ptr == 0) {
  222.             puts("usage: lock [file] [file...]\n");
  223.             return 1;
  224.         }
  225.         while (*ptr != NULL && **ptr != NULL) {
  226.             expand(flock,*ptr,1);
  227.             ptr++;
  228.         }
  229.     return 1;
  230.     }
  231.     else if (strcmp(*ptr,"unlock") == 0) {
  232.         ++ptr;
  233.         if (*ptr == 0 || **ptr == '\n' || **ptr == 0) {
  234.             puts("usage: unlock [file] [file...]\n");
  235.             return 1;
  236.         }
  237.         while (*ptr != NULL && **ptr != NULL) {
  238.             expand(flock,*ptr,0);
  239.             ptr++;
  240.         }
  241.     return 1;
  242.     }
  243.     else if (strcmp(*ptr,"mv") == 0) {
  244.         tpoint = *++ptr;
  245.         ++ptr;
  246.         value = *ptr;
  247.         if (tpoint == 0 || *tpoint == '\n' || **ptr == '\n' || *ptr == 0) {
  248.             puts("usage: mv [source] [dest]\n");
  249.             return 1;
  250.         }
  251.             if (index(tpoint,"*") != -1 || index(tpoint,"?") != -1) {
  252.                 puts(tpoint);
  253.                 puts(": ambiguous\n");
  254.                 return 1;
  255.             }
  256.             else if (index(value,"*") != -1 || index(value,"?") != -1) {
  257.                 puts(value);
  258.                 puts(": ambiguous\n");
  259.                 return 1;
  260.             }
  261.             else if (fstat(*ptr) == -1) {
  262.                 if ((value=fstat(tpoint)) == 1) {
  263.                     puts(tpoint);
  264.                     puts(": readonly\n");
  265.                     return 1;
  266.                 }
  267.                 else if (value == 0) {
  268.                     if (rename(tpoint,*ptr) == -1) {
  269.                         puts(*ptr);
  270.                         puts(": file not found\n");
  271.                         return 1;
  272.                     }
  273.                 }
  274.                 else if (value == -1) {
  275.                     puts(tpoint);
  276.                     puts(": file not found\n");
  277.                     return 1;
  278.                 }
  279.             }
  280.             else {
  281.                 puts(*ptr);
  282.                 puts(": file already exists\n");
  283.                 return 1;
  284.             }
  285.         return 1;
  286.     }
  287.     else if (strcmp(*ptr,"ls") == 0) {
  288.         ++ptr;
  289.         flag = 0; /* a kluge */
  290.         if (!(*ptr == 0 || **ptr == '\n' || **ptr == 0)) {
  291.             while (*ptr != NULL && **ptr != NULL) {
  292.                 expand(lst,*ptr,0);
  293.                 ptr++;
  294.             }
  295.             putchar('\n');
  296.         }
  297.         else {
  298.             expand(lst,"*.*",0);
  299.             putchar('\n');
  300.         }
  301.         return 1;
  302.     }
  303.     else if (strcmp(*ptr,"cat") == 0) {
  304.         ++ptr;
  305.         if (*ptr == 0 || **ptr == '\n' || **ptr == 0) {
  306.             puts("usage: cat [file] [file...]\n");
  307.             return 1;
  308.         }
  309.         while (*ptr != 0) {
  310.             expand(filprt,*ptr,0);
  311.             ptr++;
  312.         }
  313.         return 1;
  314.     }
  315.     else return 0;
  316. }
  317. lexecv(pgm,argv)
  318. char *pgm;
  319. char **argv;
  320. {
  321. int p[10];    /* only 10 for now */
  322. int argcp, val;
  323.     argcp=10;
  324.     val=0;
  325.  
  326.     while (*argv != NULL) {
  327.         p[11-argcp] = *argv++;
  328.         if (--argcp < 0) {
  329.             argcp = 0;
  330.             break;
  331.         }
  332.     }
  333.     p[11-argcp] = NULL;
  334.  
  335.     /* replace this grossness with something reasonable */
  336.     val=execl(pgm,p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9],p[10]);
  337.     return val;
  338. }
  339. dofile(largc,largv)
  340. int largc;
  341. char *largv[];
  342. {
  343. char local[BUFSIZ], tmpbuf[BUFSIZ], *bp, scratch[BUFSIZ];
  344. int x;
  345. FILE file;
  346. scratch[0]=0;    /* initializer */
  347.  
  348.     strcpy(local,largv[0]);
  349.     strcat(local,".sh");
  350.     if (fopen(local,file) == -1) return -1;
  351.  
  352.     while (fgets(local,file)) {
  353.         bp = local;
  354.         while (1) {
  355.             if (*bp) {
  356.                 if (*bp == '$') {
  357.                     *bp = NULL;
  358.                     strcpy(tmpbuf,local);
  359.                     if ((x=atoi(++bp)) <= largc) {
  360.                         strcat(tmpbuf,largv[x]);
  361.                     }
  362.                     else {
  363.                         puts("invalid argument\n");
  364.                         return 0;
  365.                     }
  366.                     strcat(tmpbuf,++bp);
  367.                     strcpy(local,tmpbuf);
  368.                     bp -= 2; /* klugy */
  369.                 }
  370.                 else if (*bp == '\n') {
  371.                     *bp = NULL;
  372.                 }
  373.                 bp++;
  374.             }
  375.             else break;
  376.         }
  377.         strcat(scratch,local);
  378.         strcat(scratch," ; ");
  379.         if (iop->_shsav) {
  380.             if ((strlen(iop->_shbuf)+strlen(scratch)) >= BUFSIZ) {
  381.                 puts("sh: buffer overflow\n");
  382.                 return 0;
  383.             }
  384.         }
  385.     }
  386.     if (iop->_shsav) {
  387.         strcat(scratch,iop->_shbuf);
  388.         strcpy(iop->_shbuf,scratch);
  389.     }
  390.     else {
  391.         *(scratch+strlen(scratch)-1) = NULL; /* kluge */
  392.         *(scratch+strlen(scratch)-2) = '\n'; /* more */
  393.         strcpy(iop->_shbuf,scratch);
  394.         iop->_shsav=1;
  395.     }
  396. return 0;
  397. }
  398. char *
  399. b_gets(buf)
  400. char *buf;
  401. {
  402. char c;
  403. int tab;
  404. tab = TABSIZE;
  405.  
  406.     while((c=bios(3,0)) != '\r') {
  407.         if (c == QUIT) {
  408.             puts("\nQuit\n");
  409.             bios(1,0);    /* warm boot cpm */
  410.         }
  411.         if ((c == CNTLH || c == DEL) && buf !=combuf) {
  412.             putchar(CNTLH);
  413.             putchar(' ');
  414.             putchar(CNTLH);
  415.             buf -= 2;
  416.         }
  417.         else if (c == '\t') {
  418.             putchar(' ');
  419.             while (--tab) {
  420.                 *buf = ' ';
  421.                 buf++;
  422.                 putchar(' ');
  423.             }
  424.         tab = TABSIZE;
  425.         }
  426.         else if (c == LINEKILL) {
  427.             while (1) {
  428.                 putchar(CNTLH);
  429.                 putchar(' ');
  430.                 putchar(CNTLH);
  431.                 if (buf == (combuf-1))
  432.                     break;
  433.                 else
  434.                     --buf;
  435.             }
  436.             puts(PROMPT);
  437.         }
  438.         else if (c == EOT) {
  439.             puts("logout\n");
  440.             return 0;
  441.         }
  442.         else {
  443.             *buf = c;
  444.             putchar(c);
  445.         }
  446.         if (buf != (combuf+MAXLINE))
  447.             buf++;
  448.     }
  449. putchar('\n');
  450. *buf = '\n';
  451. *++buf = '\0';
  452. return combuf;
  453. }
  454. pwd()        /* return current directory */
  455. {
  456.     return(iop->_shdsk+97);
  457. }
  458. chdir(c)    /* cp/m function 14 */
  459. char c;
  460. {
  461.     if (c < 65 || c > 122)
  462.         return 0;
  463.     c -= 97;
  464.     bdos(0x0e,c);
  465.     iop->_shdsk = c;
  466.     return c;
  467. }
  468. flock(filnam,mode) char *filnam; int mode; {
  469. fcb address;
  470. char *offset;
  471. offset = &address.f_name[8];
  472.  
  473.     setfcb(address,filnam);
  474.     if (mode == TRUE) *offset |= '\200';
  475.     else *offset &= 0x7f;
  476.     if (bdos(30,&address) == 0xff) {
  477.         puts(filnam);
  478.         puts(": not found.\n");
  479.     }
  480. return(0);
  481. }
  482. filprt(filnam)
  483. char *filnam;
  484. {
  485. FILE fbuf;
  486. char c, str[BUFSIZ];
  487. int count;
  488.  
  489.     count = 0;
  490.     if (fopen(filnam,fbuf) == -1)
  491.         return -1;
  492.     else {
  493.         puts(CLEARS);
  494.         putchar('-'); puts(filnam); puts("-\n");
  495.         for (;;) {
  496.             if (!fgets(str,fbuf)) {
  497.                 fclose(fbuf);
  498.                 fflush(fbuf);
  499.                 puts("-eof-");
  500.                 if (bios(3,0) == 'q') {
  501.                     puts("\010 \010\010 \010\010 \010\010 \010\010 \010\010 ");
  502.                     return -1;
  503.                 }
  504.                 putchar('\n');
  505.                 return 0;
  506.             }
  507.             if ((count += 1) == 22) {
  508.                 count = 0;
  509.                 puts("-more-");
  510.                 if ((c=bios(3,0)) == 'n') {
  511.                 puts("\010 \010\010 \010\010 \010\010 \010\010 \010\010 \010\010 ");
  512.                     fclose(fbuf);
  513.                     return 1;
  514.                 }
  515.                 else if (c == 'q') {
  516.                     fclose(fbuf);
  517.                     puts("\010 \010\010 \010\010 \010\010 \010\010 \010\010 \010\010 ");
  518.                     return -1;
  519.                 }
  520.                 puts(CLEARS);
  521.                 putchar('-'); puts(filnam); puts("-\n");
  522.             }
  523.             fputs(str,stdout);
  524.         }
  525.     }
  526. puts("-eof-");
  527. if (bios(3,0) == 'q') {
  528.     puts("\010 \010\010 \010\010 \010\010 \010\010 \010\010 ");
  529.     return -1;
  530. }
  531. else putchar('\n');
  532. return 0;
  533. }
  534.  
  535. lst(vector)
  536. char *vector;
  537. {
  538. int q;    /* flag must be an external */
  539.  
  540.         if (flag == 3) {
  541.             puts(vector);
  542.             putchar('\n');
  543.             flag = 0;
  544.         }
  545.         else {
  546.             puts(vector);
  547.             for (q = 0; q != (20-strlen(vector)); q++)
  548.                 putchar(' ');
  549.             flag++;
  550.         }
  551. return 0;
  552. }
  553. pickout(fcon,name) fcb *fcon; char *name; {
  554.     char i;
  555.  
  556.     if (fcon->f_entry) {
  557.         *name++ = " abcd"[fcon->f_entry & 0x7f] ;
  558.         *name++ = ':' ;
  559.     }
  560.  
  561.     for (i=0; fcon->f_name[i] != ' ' && i < 8; i++)
  562.         *name++ = tolower(fcon->f_name[i]) ;
  563.     *name++ = '.';
  564.     for (i=8; fcon->f_name[i] != ' ' && i < 11; i++)
  565.         *name++ = tolower(fcon->f_name[i]) ;
  566.     *name = 0;
  567. }
  568. remove(filnam) char *filnam; {
  569. fcb address;
  570.  
  571.     if (fstat(filnam) == 1) return 1; /* readonly file */
  572.     setfcb(address,filnam);
  573.     if (bdos(19,&address) == 0xff)    /* cpm delete call */
  574.         return -1;    /* file not found */
  575.     else return 0;
  576. }
  577. doshell()
  578. {
  579. execl("a:sh",0);
  580. }
  581. fstat(filnam) char *filnam; {
  582. char *byte, c;
  583. fcb address;
  584.  
  585.     setfcb(address,filnam);
  586.     if ((c=bdos(17,&address)) == 255)
  587.         return -1;    /* file not found */
  588.     byte =(0x80 + (c * 32) + _MBYTE); /* permission byte */
  589.  
  590.     if ((*byte & '\200') == 0) return 0; /* readwrite */
  591.     else return 1;                /* readonly */
  592. }
  593. expand(func,parm1,parm2) /* perform global file expansions */
  594. int (*func)();
  595. char *parm1;
  596. int parm2;
  597. {
  598.     int count, ret;
  599.     count = GLOBMAX;
  600.  
  601.         crfil(globs,count*FILENAMESIZE,0xff);
  602.         while (count--)
  603.             globv[count] = &globs[count*FILENAMESIZE];
  604.         globv[GLOBMAX]=0;
  605.         if ((ret = doglob(parm1)) >= 1) {
  606.             qsort(globs,ret,FILENAMESIZE,strcmp);
  607.             count = 0;
  608.             while (count < ret) {
  609.                 if ((*func)(globv[count],parm2) == -1)
  610.                     break;
  611.                 count++;
  612.             }
  613.         }
  614.         else {
  615.             puts(parm1);
  616.             puts(": no match\n");
  617.         }
  618. return 0;
  619. }
  620. dozap(file) char *file; {
  621. int ret;
  622.  
  623.     if ((ret = remove(file)) == -1) {
  624.         puts(file);
  625.         puts(": not found\n");
  626.     }
  627.     else if (ret == 1) {
  628.         puts(file);
  629.         puts(" readonly -- zap?");
  630.         if (bios(3,0) == 'y') { 
  631.             flock(file,0);
  632.             remove(file);
  633.         }
  634.         putchar('\n');
  635.     }
  636. return 0;
  637. }
  638. doglob(string) /* glob - expand filename expressions */
  639. char *string;
  640. {
  641. char f, c, buf[20];
  642. fcb address;
  643. fcb *dirbuf;
  644. int flag, q, i;
  645. flag=0;
  646. i=0;
  647.  
  648.     if (strlen(string) == 2 && *(string+1) == ':') {
  649.         setfcb(address,"????????.???");
  650.         address.f_entry = tolower(*string)-96;
  651.     }
  652.     else
  653.         setfcb(address,string);
  654.  
  655.     for (f=17; (c=bdos(f,&address)) != 255; f=18) {
  656.         dirbuf = (0x80 + (c * 32));
  657.         dirbuf->f_entry = address.f_entry; 
  658.         pickout(dirbuf, buf);
  659.             strcpy(globv[i],buf);
  660.             if (++i == GLOBMAX) break;
  661.     }
  662. globv[i] = 0;        /* null terminate vector */
  663. return i;
  664. }
  665. index(string,ch) /* return pointer to ch in string */
  666. char *string, *ch;
  667. {
  668.  
  669.     while (*string) {
  670.         if (*string==*ch)
  671.             return string;
  672.         string++;
  673.     }
  674. return -1;
  675. }
  676. crfil(address,length,byte) /* zero fill at address for length bytes */
  677. char *address, byte;
  678. unsigned length;
  679. {
  680.  
  681.     while (--length) {
  682.         *++address = byte;
  683.     }
  684. return 0;
  685. }
  686.