home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 185_01 / hsh.c < prev    next >
Text File  |  1985-08-21  |  25KB  |  863 lines

  1. /* hsh -- ZCPR3 history shell                                               */
  2. /* copyright 1985  Michael M Rubenstein                                     */
  3.  
  4. /* version 1.1  6 Oct 85                                                    */
  5.  
  6. /* Modifications                                                            */
  7.  
  8. /* 1.1      (MMR) Fixed handling of firsthist on wrap around.  Previous     */
  9. /*          did not reset to 0, which could result in the program hanging   */
  10. /*          if a search was done for a leading string which was not in the  */
  11. /*          history.                                                        */
  12.  
  13. #include <sysio.h>
  14. #include <fcb.h>
  15.  
  16. #define SHNAME          "HSH.COM"       /* default name */
  17. #define VARFILE         "HSH.VAR"       /* history file */
  18. #define DEFNHIST        10              /* default number of history lines */
  19.  
  20. /* some interesting characters                                              */
  21. #define CTL             0x1f
  22. #define NUL             0
  23. #define CTLA            (CTL & 'A')
  24. #define CTLC            (CTL & 'C')
  25. #define CTLD            (CTL & 'D')
  26. #define CTLE            (CTL & 'E')
  27. #define CTLF            (CTL & 'F')
  28. #define CTLG            (CTL & 'G')
  29. #define BEL             CTLG
  30. #define BS              (CTL & 'H')
  31. #define CTLJ            (CTL & 'J')
  32. #define LF              CTLJ
  33. #define CR              (CTL & 'M')
  34. #define CTLL            (CTL & 'L')
  35. #define CTLP            (CTL & 'P')
  36. #define CTLQ            (CTL & 'Q')
  37. #define CTLR            (CTL & 'R')
  38. #define CTLS            (CTL & 'S')
  39. #define CTLT            (CTL & 'T')
  40. #define CTLU            (CTL & 'U')
  41. #define CTLV            (CTL & 'V')
  42. #define CTLW            (CTL & 'W')
  43. #define CTLX            (CTL & 'X')
  44. #define CTLY            (CTL & 'Y')
  45. #define CTLZ            (CTL & 'Z')
  46. #define ESC             (CTL & '[')
  47. #define DEL             0x7f
  48.  
  49. extern unsigned         z3env;          /* pointer to ZCPR3 environment */
  50. extern FCB              dfcb_;          /* default CP/M FCB */
  51.  
  52. int                     curdir = FALSE;     /* if TRUE, search current dir */
  53. int                     nhist = DEFNHIST;   /* number of history lines */
  54. int                     firsthist = 0;      /* index of first history line */
  55. int                     lasthist = 0;       /* index of one past last line */
  56. int                     drive, user;        /* current drive/user */
  57. int                     rdrive, ruser;      /* root drive/user */
  58. int                     linepos;            /* position on CRT line */
  59. int                     maxpos;             /* max pos on CRT line used */
  60. int                     maxcols;            /* columns on CRT display */
  61. char                    *cur;               /* pointer to current char in */
  62.                                             /* line being edited */
  63. char                    *line;              /* pointer to start of line */
  64.                                             /* being edited */
  65. char                    *maxcur;            /* end of line */
  66.  
  67. char                    *gethline();        /* get a line from the history */
  68. char                    *puthline();        /* put a line to the history */
  69.  
  70. FCB                     *gefcb();       /* get ZCPR3 external FCB */
  71. char                    *getcrt();      /* get ZCPR3 terminal data */
  72.  
  73. main()
  74. {
  75.   static FCB            *efcb;          /* FCB for shell name */
  76.   static char           shname[13];     /* shell name */
  77.   static char           *s;
  78.   int                   du;
  79.   static int            c;
  80.   static int            i;
  81.   static int            n = -1;         /* value of command line arg */
  82.   char                  aline[256];
  83.  
  84.   line = aline;                         /* cheap way to allocate mem */
  85.   maxcur = line + 255;                  /* end of line */
  86.  
  87.   /* if there is a command line argument, evaluate and save it */
  88.   if (isdigit(dfcb_.name1.fname[0]))
  89.   {
  90.     n = atoi(dfcb_.name1.fname);
  91.     if (n < 0)
  92.       error("hsh: number of history lines too large.");
  93.   }
  94.   else
  95.   if (dfcb_.name1.fname[0] != ' ')
  96.     error("syntax:  hsh [<number of history lines to keep>]");
  97.  
  98.  
  99.   if (z3env == 0)
  100.     error("hsh: ZCPR3 required.");
  101.  
  102.   /* clear external command line.  abort if none */
  103.   if (!clcl())
  104.     error("hsh: ZCPR3 external command line required.");
  105.  
  106.   /* find where we are and where root dir is for later use */
  107.   drive = curdsk();
  108.   user = getusr();
  109.   du = groot();
  110.   rdrive = du >> 8;
  111.   ruser = du & 8;
  112.  
  113.   /* if not invoked as a shell, install as shell */
  114.   if (!qsh())
  115.   {
  116.     /* if no external FCB, use default name */
  117.     if ((efcb = gefcb()) == NULL)
  118.     {
  119.       setfcb(SHNAME, &dfcb_);
  120.       efcb = &dfcb_;
  121.     }
  122.  
  123.     /* find where program is and set up name with drive/user */
  124.     if ((du = pfnd(efcb, curdir)) == -1)
  125.       error("hsh: Cannot find shell program.");
  126.     shname[0] = (du >> 8) + 'A';
  127.     du &= 0xff;
  128.     shname[1] = du / 10 + '0';
  129.     shname[2] = du % 10 + '0';
  130.     shname[3] = ':';
  131.     for (i = 0; i < 8; ++i)
  132.     {
  133.       if ((c = (efcb->name1.fname[i] & 0x7f)) == ' ')
  134.         break;
  135.       shname[4 + i] = c;
  136.     }
  137.     shname[4 + i] = '\0';
  138.     if (shpsh(shname))
  139.       error("hsh: Cannot install shell.");
  140.  
  141.     ps("HSH Version 1.0 (1 Oct 85) installed\r\n");
  142.  
  143.     /* if a command line arg was entered, set up history file with number */
  144.     /* of lines to keep */
  145.     if (n >= 0)
  146.     {
  147.       nhist = n;
  148.     /* go to the right place */
  149.       select(rdrive);
  150.       setusr(ruser);
  151.       setfcb(VARFILE, &dfcb_);
  152.       delete(&dfcb_);
  153.       if (make(&dfcb_) == 0xff)
  154.         sherror("hsh: Cannot create HSH.VAR.");
  155.       puthist();
  156.     }
  157.  
  158.     /* exit after installing shell, so will work from submit file */
  159.     return;
  160.   }
  161.  
  162.   /* set ZCPR3 command status message so next program won't think it's */
  163.   /* a shell (needed since we don't warm boot on exit) */
  164.   pcst(0);
  165.  
  166.   maxcols = *getcrt() & 0xff;
  167.  
  168.   gethist();                            /* get history */
  169.   getcmd();                             /* handle a command */
  170.   puthist();                            /* save history */
  171. }
  172.  
  173. /* get the history                                                          */
  174. gethist()
  175. {
  176.   /* first record in history file keeps parameters */
  177.   struct {              int     f_nhist, f_fhist, f_lhist;
  178.                         char    f_fill[126];
  179.          }              fnhist;
  180.  
  181.   /* go to the right place */
  182.   select(rdrive);
  183.   setusr(ruser);
  184.   setfcb(VARFILE, &dfcb_);
  185.  
  186.   /* if there's a history file, read it in and set firsthist and lasthist */
  187.   if (open(&dfcb_) != 0xff)
  188.   {
  189.     setdma(&fnhist);
  190.     if (!rdseq(&dfcb_))
  191.     {
  192.       nhist = fnhist.f_nhist;
  193.       firsthist = fnhist.f_fhist;
  194.       lasthist = fnhist.f_lhist;
  195.     }
  196.   }
  197.   else
  198.     /* if no history file, create it */
  199.     if (make(&dfcb_) == 0xff)
  200.       sherror("hsh: Cannot create HSH.VAR.");
  201. }
  202.  
  203. /* put the history paramters to file                                        */
  204. puthist()
  205. {
  206.   /* first record in history file keeps parameters */
  207.   struct {              int     f_nhist, f_fhist, f_lhist;
  208.                         char    f_fill[126];
  209.          }              fnhist;
  210.  
  211.   fnhist.f_nhist = nhist;
  212.   fnhist.f_fhist = firsthist;
  213.   fnhist.f_lhist = lasthist;
  214.  
  215.   setdma(&fnhist);
  216.   dfcb_.rrec = 0;
  217.   if (wrran(&dfcb_))
  218.     sherror("hsh: Error writing HSH.VAR.");
  219.  
  220.   if (close(&dfcb_) == 0xff)
  221.     sherror("hsh: Error closing HSH.VAR");
  222.  
  223.   /* return to where we were */
  224.   select(drive);
  225.   setusr(user);
  226. }
  227.  
  228. /* get a history line.  returns pointer to line for convenience.            */
  229. char *gethline(line, n)
  230.   char                  *line;
  231.   int                   n;
  232. {
  233.   dfcb_.rrec = 2 * n + 1;
  234.   setdma(line);
  235.   if (rdran(&dfcb_))
  236.     sherror("hsh: Cannot read HSH.VAR.");
  237.  
  238.   ++dfcb_.rrec;
  239.   setdma(line + 128);
  240.   if (rdran(&dfcb_))
  241.     sherror("hsh: Cannot read HSH.VAR.");
  242.   return line;
  243. }
  244.  
  245. /* put a history line.  returns pointer to line for convenience.            */
  246. char *puthline(line, n)
  247.   char                  *line;
  248.   int                   n;
  249. {
  250.   dfcb_.rrec = 2 * n + 1;
  251.   setdma(line);
  252.   if (wrran(&dfcb_))
  253.     sherror("hsh: Cannot write HSH.VAR.");
  254.  
  255.   ++dfcb_.rrec;
  256.   setdma(line + 128);
  257.   if (wrran(&dfcb_))
  258.     sherror("hsh: Cannot write HSH.VAR.");
  259.   return line;
  260. }
  261.  
  262. /* get a command and pass to CCP                                            */
  263. getcmd()
  264. {
  265.   static char           *cmd;
  266.   static char           *dirname;
  267.   static int            i;
  268.   static char           prompt[14];
  269.   static char           *s;
  270.  
  271.   /* set up prompt */
  272.   s = prompt;
  273.   *(s++) = drive + 'A';
  274.   if (user > 10)
  275.     *(s++) = user / 10 + '0';
  276.   *(s++) = user % 10 + '0';
  277.   if ((dirname = dutd((drive << 8) + user)) != NULL)
  278.   {
  279.     *(s++) = ':';
  280.     for (i = 0; i < 8 && dirname[i] != ' '; ++i)
  281.       *(s++) = dirname[i];
  282.   }
  283.   *(s++) = '>';
  284.   *s = '\0';
  285.  
  286.   for (;;)
  287.   {
  288.     pzex(1);                            /* mark prompt for ZEX */
  289.     getline(prompt);                    /* get a line */
  290.     pzex(0);
  291.     for (cmd = line; isspace(*cmd); ++cmd)      /* skip spaces at start */
  292.       ;
  293.     if (*cmd == '\0')
  294.       continue;
  295.     puthline(line, lasthist);
  296.     if (++lasthist > nhist)          /* advance history */
  297.       lasthist = 0;
  298.     if (lasthist == firsthist)
  299.       ++firsthist;
  300.     if (firsthist > nhist)
  301.       firsthist = 0;
  302.  
  303.     if (pcl(cmd))                     /* pass to CCP */
  304.       return;
  305.  
  306.     ps("\r\nhsh: Command too long.");
  307.   }
  308. }
  309.  
  310. /* get a line with editing                                                  */
  311. getline(prompt)
  312.   char                  *prompt;
  313. {
  314.   static char           *maxcur;        /* last char possible on line */
  315.   static char           *p, *q;
  316.   static int            n;
  317.   static int            i;
  318.   static int            c;
  319.   static int            hindex;         /* index into history for recall */
  320.   char                  wkline[256];    /* work line for history search */
  321.  
  322.   maxpos = 0;
  323.   setmem(line, 256, 0);                 /* clear the line */
  324.   hindex = lasthist;                    /* point to next line for history */
  325.  
  326.   ps("\r\n");
  327.   ps(prompt);
  328.   cur = line;
  329.  
  330.   for (;;)
  331.     switch (c = bconin() & 0x7f)
  332.     {
  333.       case CR:      /* done with line */
  334.                     bcnout('\r');
  335.                     i = (maxpos + maxcols - 1) / maxcols
  336.                       - (linepos + maxcols - 1) / maxcols;
  337.                     while (i-- > 0)
  338.                       bcnout('\n');
  339.                     return line;
  340.  
  341.       case CTLS:    /* back one character */
  342.                     if (cur != line)
  343.                       backup();
  344.                     break;
  345.  
  346.       case CTLA:    /* back one word */
  347.                     if (cur == line)
  348.                       break;
  349.                     backup();
  350.                     while (cur != line && !isalnum(*cur))
  351.                       backup();
  352.                     while (cur != line && isalnum(*(cur - 1)))
  353.                       backup();
  354.                     break;
  355.  
  356.       case CTLQ:    /* back on command */
  357.                     if (cur != line)
  358.                       backup();
  359.                     while (cur != line && *(cur - 1) != ';')
  360.                       backup();
  361.                     break;
  362.  
  363.       case CTLD:    /* forward one character */
  364.                     if (*cur != '\0')
  365.                       forward();
  366.                     break;
  367.  
  368.       case CTLF:    /* forward one word */
  369.                     while (isalnum(*cur))
  370.                       forward();
  371.                     while (*cur != '\0' && !isalnum(*cur))
  372.                       forward();
  373.                     break;
  374.  
  375.       case CTLR:    /* forward command */
  376.                     while (*cur != '\0' && *cur != ';')
  377.                       forward();
  378.                     if (*cur == ';')
  379.                       forward();
  380.                     break;
  381.  
  382.       case BS:
  383.       case DEL:     /* backspace and delete */
  384.                     if (cur == line)
  385.                       break;
  386.                     backup();           /* NOTE fall through */
  387.       case CTLG:    /* delete current char */
  388.                     if (*cur != '\0')
  389.                       delchr();
  390.                     break;
  391.  
  392.       case CTLW:    /* delete word left */
  393.                     if (cur == line)
  394.                       break;
  395.                     backup();
  396.                     while (cur != line && !isalnum(*cur))
  397.                       backup();
  398.                     while (cur != line && isalnum(*(cur - 1)))
  399.                       backup();
  400.                     /* NOTE fall through */
  401.       case CTLT:    /* delete word right */
  402.                     while (isalnum(*cur))
  403.                       delchr();
  404.                     while (*cur != '\0' && !isalnum(*cur))
  405.                       delchr();
  406.                     break;
  407.  
  408.       case CTLZ:    /* delete command */
  409.                     if (*cur == ';')
  410.                       forward();
  411.                     while (cur != line && *(cur - 1) != ';')
  412.                       backup();
  413.                     while (*cur != '\0' && *cur != ';')
  414.                       delchr();
  415.                     if (*cur == ';')
  416.                       delchr();
  417.                     if (*cur == '\0' && *(cur - 1) == ';')
  418.                     {
  419.                       backup();
  420.                       delchr();
  421.                     }
  422.                     break;
  423.  
  424.       case CTLD:    /* forward one character */
  425.                     if (*cur != '\0')
  426.                       forward();
  427.                     break;
  428.  
  429.       case CTLV:    /* insert char */
  430.                     p = cur + strlen(cur);
  431.                     if (p == maxcur)
  432.                       *(p - 1) = '\0';
  433.                     while (p > cur)
  434.                     {
  435.                       *p = *(p - 1);
  436.                       --p;
  437.                     }
  438.                     *cur = ' ';
  439.                     while (*cur != '\0')
  440.                       forward();
  441.                     while (cur > p)
  442.                       backup();
  443.                     break;
  444.  
  445.       case CTLX:    /* recall next line */
  446.                     if (hindex != lasthist)
  447.                     {
  448.                       ++hindex;
  449.                       if (hindex > nhist)
  450.                         hindex = 0;
  451.                     }
  452.                     if (hindex != lasthist)
  453.                     {
  454.                       delln();
  455.                       gethline(line, hindex);
  456.                       showln();
  457.                       break;
  458.                     }                   /* NOTE fall through */
  459.       case CTLU:    /* delete line */
  460.                     hindex = lasthist;
  461.                     delln();
  462.                     break;
  463.  
  464.       case CTLY:    /* delete to end of line */
  465.                     i = linepos;
  466.                     p = cur;
  467.                     while (*cur != '\0')
  468.                       forward();
  469.                     n = linepos - i;
  470.                     while (cur > p)
  471.                       *(--cur) = '\0';
  472.                     for (i = 0; i < n; ++i)
  473.                       pc('\b');
  474.                     for (i = 0; i < n; ++i)
  475.                       pc(' ');
  476.                     for (i = 0; i < n; ++i)
  477.                       pc('\b');
  478.                     break;
  479.  
  480.       case CTLE:    /* recall previous line */
  481.                     if (hindex == firsthist)
  482.                     {
  483.                       bell();
  484.                       break;
  485.                     }
  486.                     delln();
  487.                     if (--hindex < 0)
  488.                       hindex = nhist;
  489.                     gethline(line, hindex);
  490.                     showln();
  491.                     break;
  492.  
  493.       case CTLL:    /* search for previous */
  494.                     n = FALSE;
  495.                     for (i = hindex; i != firsthist;)
  496.                     {
  497.                       if (--i < 0)
  498.                         i = nhist;
  499.  
  500.                       if (n = prefix(line, cur, gethline(wkline, i)))
  501.                         break;
  502.                     }
  503.                     if (n)
  504.                     {
  505.                       p = cur;
  506.                       delln();
  507.                       gethline(line, hindex = i);
  508.                       showln();
  509.                       while (cur < p)
  510.                         forward();
  511.                     }
  512.                     else
  513.                       bell();
  514.                     break;
  515.  
  516.       case CTLJ:    /* help */
  517.                     p = cur;
  518.                     help();
  519.                     maxpos = 0;
  520.                     ps(prompt);
  521.                     cur = line;
  522.                     while (cur < p)
  523.                       forward();
  524.                     showln();
  525.                     break;
  526.  
  527.       case NUL:     /* ignore nulls */
  528.                      break;
  529.  
  530.       case CTLP:    /* take next char as literal */
  531.                     if ((c = bconin() & 0x7f) == NUL)
  532.                       break;            /* NUL can't be handled */
  533.                                         /* NOTE fall through */
  534.       default:      if (cur == line)
  535.                       switch (c)        /* handle special commands */
  536.                       {
  537.                         case ESC:   delln();
  538.                                     ps("<exit hsh>\r\n");
  539.                                     shpop();
  540.                                     puthist();
  541.                                     exit(0);
  542.  
  543.                         case CTLC:  delln();
  544.                                     ps("^C");
  545.                                     puthist();
  546.                                     boot_();
  547.                       }
  548.  
  549.                     if (cur == maxcur)
  550.                       bell();
  551.                     else
  552.                     {
  553.                       *cur = c;
  554.                       forward();
  555.                       showln();
  556.                     }
  557.     }
  558. }
  559.  
  560. /* delete character                                                         */
  561. delchr()
  562. {
  563.   static char           *p;
  564.  
  565.   for (p = cur; (*p = *(p + 1)) != '\0'; ++p)
  566.     ;
  567.   p = cur;
  568.   while (*cur != '\0')
  569.     forward();
  570.   ps("  \b\b");
  571.   while (cur > p)
  572.     backup();
  573. }
  574.  
  575. /* delete entire line                                                       */
  576. delln()
  577. {
  578.   while (*cur != '\0')
  579.     forward();
  580.   while (cur > line)
  581.   {
  582.     if (*--cur < ' ' || *cur == DEL)
  583.       ps("\b \b");
  584.     ps("\b \b");
  585.     *cur = '\0';
  586.   }
  587.   maxpos = linepos;
  588. }
  589.  
  590. /* show line from current position                                          */
  591. showln()
  592. {
  593.   static char           *p;
  594.  
  595.   if (*cur != '\0')
  596.   {
  597.     p = cur;
  598.     while (*cur != '\0')
  599.       forward();
  600.     ps(" \b");
  601.     while (cur != p)
  602.       backup();
  603.   }
  604. }
  605.  
  606. /* back up one character                                                    */
  607. backup()
  608. {
  609.   --cur;
  610.   if (*cur < ' ' || *cur == DEL)
  611.     pc('\b');
  612.   pc('\b');
  613. }
  614.  
  615. /* forward one character                                                    */
  616. forward()
  617. {
  618.   pctl(*(cur++));
  619. }
  620.  
  621. /* is s - t a prefix of u.  ignore case                                     */
  622. prefix(s, t, u)
  623.   register char         *s, *t, *u;
  624. {
  625.   while (s < t)
  626.     if (toupper(*(s++)) != toupper(*(u++)))
  627.       return FALSE;
  628.  
  629.   return  TRUE;
  630. }
  631.  
  632. /* put string to console                                                    */
  633. ps(s)
  634.   register char         *s;
  635. {
  636.   while (*s != '\0')
  637.     pc(*(s++));
  638. }
  639.  
  640. /* output a number to console                                               */
  641. pn(n)
  642.   unsigned              n;
  643. {
  644.   if (n > 9)
  645.     pn(n / 10);
  646.   pc(n % 10 + '0');
  647. }
  648.  
  649. /* put char to console                                                      */
  650. pc(c)
  651.   int                   c;
  652. {
  653.   bcnout(c);
  654.   switch (c)
  655.   {
  656.     case BS:            --linepos;
  657.                         break;
  658.  
  659.     case CR:            linepos = 0;
  660.                         break;
  661.  
  662.     default:            if (c >= ' ' && c < DEL)
  663.                           if (++linepos > maxpos)
  664.                             maxpos = linepos;
  665.   }
  666. }
  667.  
  668. /* put character to console, converting controls to printables              */
  669. pctl(c)
  670.   int                   c;
  671. {
  672.   if (c == DEL)
  673.   {
  674.     ps("^?");
  675.     return;
  676.   }
  677.  
  678.   if (c < ' ')
  679.   {
  680.     pc('^');
  681.     pc (c += '@');
  682.     return;
  683.   }
  684.  
  685.   pc(c);
  686. }
  687.  
  688. /* audible alarm                                                            */
  689. bell()
  690. {
  691.   bcnout(BEL);
  692. }
  693.  
  694. /* critical error.  remove shell and exit with message                      */
  695. sherror(s)
  696.   char                  *s;
  697. {
  698.   shpop();
  699.   error(s);
  700. }
  701.  
  702. /* display help                                                             */
  703. help()
  704. {
  705.   static char           *msg[] =
  706.   {
  707.     "\r\n\n\n\n          +-------+-------+-------+--------+--------+\r\n",
  708.     "          | Back  | Fwd   | Del L | Del R  | Del All|\r\n",
  709.     "    +-----+-------+-------+-------+--------+--------+\r\n",
  710.     "    |Char |  ^S   |  ^D   |  BS   |  ^G    |        |\r\n",
  711.     "    +-----+-------+-------+-------+--------+--------+\r\n",
  712.     "    |Word |  ^A   |  ^F   |  ^W   |  ^T    |        |\r\n",
  713.     "    +-----+-------+-------+-------+--------+--------+\r\n",
  714.     "    |Cmd  |  ^Q   |  ^R   |       |        |  ^Z    |\r\n",
  715.     "    +-----+-------+-------+-------+--------+--------+\r\n",
  716.     "    |Line |       |       |       |  ^Y    |  ^U    |\r\n",
  717.     "    +-----+-------+-------+-------+--------+--------+\r\n\n",
  718.     "    ^E - Recall prev cmd line.\r\n",
  719.     "    ^L - Search for match left of the cursor.\r\n",
  720.     "    ^P - Quote next char.\r\n",
  721.     "    ^V - Insert char.\r\n",
  722.     "    ^X - Recall next cmd line.\r\n\n",
  723.     NULL
  724.   };
  725.  
  726.   static char           **p;
  727.  
  728.   for (p = msg; *p != NULL; ++p)
  729.     ps(*p);
  730. }
  731.  
  732. /* ZCPR3 transfer routines                                                  */
  733. /* These routines simply convert calling sequences and return values        */
  734. /* between C/80 and Z3LIB.                                                  */
  735.  
  736. /* clear command line                                                       */
  737. clcl()
  738. {
  739. #asm
  740.         call    clrcl##
  741.         mov     h,a
  742.         mov     l,a
  743. #endasm
  744. }
  745.  
  746. /* is this a shell?                                                         */
  747. qsh()
  748. {
  749. #asm
  750.         call    qshell##
  751.         lxi     h,0
  752.         rnz
  753.         inx     h
  754. #endasm
  755. }
  756.  
  757. /* point to external FCB                                                    */
  758. FCB *gefcb()
  759. {
  760. #asm
  761.         call    getefcb##
  762.         rnz
  763.         lxi     h,0
  764. #endasm
  765. }
  766.  
  767. /* install shell                                                            */
  768. shpsh()
  769. {
  770. #asm
  771.         pop     d
  772.         pop     h
  773.         push    h
  774.         push    d
  775.         call    shpush##
  776.         mvi     h,0
  777.         mov     l,a
  778. #endasm
  779. }
  780.  
  781. /* get root drive/user                                                      */
  782. groot()
  783. {
  784. #asm
  785.         call    root##
  786.         mov     h,b
  787.         mov     l,c
  788. #endasm
  789. }
  790.  
  791. /* put command line                                                         */
  792. pcl()
  793. {
  794. #asm
  795.         pop     d
  796.         pop     h
  797.         push    h
  798.         push    d
  799.         call    putcl##
  800.         mov     h,a
  801.         mov     l,a
  802. #endasm
  803. }
  804.  
  805. /* convert drive/user to directory name                                     */
  806. dutd()
  807. {
  808. #asm
  809.         pop     h
  810.         pop     b
  811.         push    b
  812.         push    h
  813.         call    dutdir##
  814.         rnz
  815.         lxi     h,0
  816. #endasm
  817. }
  818.  
  819. /* find file along path                                                     */
  820. pfnd()
  821. {
  822. #asm
  823.         pop     h
  824.         pop     b
  825.         pop     d
  826.         push    d
  827.         push    b
  828.         push    h
  829.         mov     a,c
  830.         call    pfind##
  831.         mov     h,b
  832.         mov     l,c
  833.         rnz
  834.         lxi     h,0
  835. #endasm
  836. }
  837.  
  838. /* set command status message                                               */
  839. pcst()
  840. {
  841. #asm
  842.         pop     h
  843.         pop     b
  844.         push    b
  845.         push    h
  846.         mov     a,c
  847.         call    putcst##
  848. #endasm
  849. }
  850.  
  851. /* set ZEX control message                                                  */
  852. pzex()
  853. {
  854. #asm
  855.         pop     h
  856.         pop     b
  857.         push    b
  858.         push    h
  859.         mov     a,c
  860.         call    putzex##
  861. #endasm
  862. }
  863.