home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / se / part3 / docmd2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-30  |  17.8 KB  |  946 lines

  1. /*
  2. ** docmd2.c
  3. **
  4. ** routines to actually execute commands
  5. */
  6.  
  7. #include "se.h"
  8. #include "extern.h"
  9.  
  10.  
  11. /* append --- append lines after "line" */
  12.  
  13. append (line, str)
  14. int line;
  15. char str[];
  16. {
  17.     char lin[MAXLINE];
  18.     char term;
  19.     int ret;
  20.     int len, i, dpos, dotseen;
  21.     int inject ();
  22.  
  23.     Curln = line;
  24.  
  25.     if (str[0] == ':')    /* text to be added is in the command line */
  26.         ret = inject (&str[1]);
  27.     else
  28.     {
  29.         Cmdrow = Toprow + (Curln - Topln) + 1;  /* 1 below Curln */
  30.         lin[0] = EOS;
  31.         if (Indent > 0 || line <= 0)
  32.             len = max (0, Indent - 1);
  33.         else /* do auto indent */
  34.         {
  35.             LINEDESC *k, *gettxt ();
  36.             k = gettxt (line);
  37.             for (len = 0; Txt[len] == ' '; len++)
  38.                 ;
  39.         }
  40.         dpos = len;     /* position for terminating '.' */
  41.  
  42.         for (ret = NOSTATUS; ret == NOSTATUS; )
  43.         {
  44.             if (! hwinsdel())   /* do it the old, slow way */
  45.             {
  46.                 if (Cmdrow > Botrow)
  47.                 {
  48.                     Cmdrow = Toprow + 1;
  49.                     cprow (Botrow, Toprow);
  50.                     adjust_window (Curln, Curln);
  51.                     if (First_affected > Topln)
  52.                         First_affected = Topln;
  53.                 }
  54.                 clrrow (Cmdrow);
  55.                 if (Cmdrow < Botrow)
  56.                     clrrow (Cmdrow + 1);
  57.             }
  58.             else    /* try to be smart about it */
  59.             {
  60.                 if (Cmdrow > Botrow)
  61.                 {
  62.                     Cmdrow--;
  63.                     dellines (Toprow, 1);
  64.                     inslines (Cmdrow, 1);
  65.                     Topln++;
  66.                 }
  67.                 else
  68.                 {
  69.                     dellines (Botrow, 1);
  70.                     inslines (Cmdrow, 1);
  71.                 }
  72.             }
  73.             prompt ("apd>");
  74.             do
  75.                 getcmd (lin, Firstcol, &len, &term);
  76.             while (term == CURSOR_UP || term == CURSOR_DOWN
  77.                 || term == CURSOR_SAME);
  78.  
  79.             dotseen = 0;
  80.             if (lin[0] == '.' && lin[1] == '\n' && lin[2] == EOS)
  81.                 dotseen = 1;
  82.             for (i = 0; i < dpos && lin[i] == ' '; i++)
  83.                 ;
  84.             if (i == dpos && lin[dpos] == '.' && lin[dpos + 1] == '\n'
  85.                 && lin[dpos+2] == EOS)
  86.                 dotseen = 1;
  87.  
  88.             if (dotseen)
  89.             {
  90.                 if (hwinsdel())
  91.                 {
  92.                     dellines (Cmdrow, 1);
  93.                     inslines (Botrow, 1);
  94.                 }
  95.                 ret = OK;
  96.             }
  97.             else if (inject (lin) == ERR)
  98.                 ret = ERR;
  99.             else            /* inject occured */
  100.                 prompt ("");    /* erase prompt */
  101.             Cmdrow++;
  102.             if (term != FUNNY)
  103.             {
  104.                 if (Indent > 0)
  105.                     len = Indent - 1;
  106.                 else /* do auto indent */
  107.                     for (len = 0; lin[len] == ' '; len++)
  108.                         ;
  109.                 dpos = len;
  110.                 lin[0] = EOS;
  111.             }
  112.         }
  113.         Cmdrow = Botrow + 1;
  114.         if (hwinsdel())            /* since we take control */
  115.         {                /* of the screen, we're sure */
  116.             Sctop = Topln;        /* it's still OK */
  117.  
  118.             for (i = 0; i < Sclen; i++)
  119.                 Scline[i] = Sctop + i <= Lastln ? i : -1;
  120.         }
  121.     }
  122.     if (Curln == 0 && Lastln > 0)   /* for 0a or 1i followed by "." */
  123.         Curln = 1;
  124.     if (First_affected > line)
  125.         First_affected = line;
  126.  
  127.     tflush ();
  128.     return (ret);
  129. }
  130.  
  131. /* copy --- copy line1 through line2 after line3 */
  132.  
  133. int copy (line3)
  134. int line3;
  135. {
  136.     register int i;
  137.     int ret;
  138.     register LINEDESC *ptr3, *after3, *k;
  139.     LINEDESC *getind ();
  140.  
  141.     ret = ERR;
  142.  
  143. #ifdef OLD_SCRATCH
  144.     ptr3 = getind (line3);
  145.     after3 = ptr3 -> Nextline;
  146. #endif
  147.  
  148.     if (Line1 <= 0)
  149.         Errcode = EORANGE;
  150.     else
  151.     {
  152.         ret = OK;
  153.         Curln = line3;
  154.         k = getind (Line1);
  155.         for (i = Line1; i <= Line2; i++)
  156.         {
  157.             gtxt (k);
  158.             if (inject (Txt) == ERR || intrpt ())
  159.             {
  160.                 ret = ERR;
  161.                 break;
  162.             }
  163. #ifdef OLD_SCRATCH
  164.             if (k == ptr3)        /* make sure we don't copy stuff */
  165.                 k = after3;    /* that's already been copied */
  166.             else
  167.                 k = k -> Nextline;
  168. #else
  169.             if (Line1 < line3)
  170.                 k++;
  171.             else
  172.                 k += 2;
  173.             /*
  174.              * inject calls blkmove, which will shift the
  175.              * lines down one in the array, so we add two
  176.              * instead of one to get to the next line.
  177.              */
  178. #endif
  179.         }
  180.         First_affected = min (First_affected, line3 + 1);
  181.     }
  182.     return (ret);
  183. }
  184.  
  185.  
  186. /* delete --- delete lines from through to */
  187.  
  188. int delete (from, to, status)
  189. int from, to, *status;
  190. {
  191.     int nextln (), prevln ();
  192.     LINEDESC *k1, *k2, *j1, *j2, *l1;
  193.     LINEDESC *getind ();
  194.  
  195.     if (from <= 0)          /* can't delete line 0 */
  196.     {
  197.         *status = ERR;
  198.         Errcode = EORANGE;
  199.     }
  200.     else
  201.     {
  202.         if (First_affected > from)
  203.             First_affected = from;
  204. #ifdef OLD_SCRATCH
  205.         k1 = getind (prevln (from));
  206.         j1 = k1 -> Nextline;
  207.         j2 = getind (to);
  208.         k2 = j2 -> Nextline;
  209.         relink (k1, k2, k1, k2);        /* close chain around deletion */
  210. #else
  211.         blkmove (from, to, MAXBUF - 1);    /* stick at end of buffer */
  212. #endif
  213.  
  214.         Lastln -= to - from + 1;        /* adjust number of last line */
  215.         Curln = prevln (from);
  216.  
  217. #ifdef OLD_SCRATCH
  218.         if (Limbo != NOMORE)            /* discard lines in limbo */
  219.         {
  220.             l1 = Limbo -> Prevline;
  221.             Limbo -> Prevline = Free;
  222.             Free = l1;
  223.         }
  224. #endif
  225.  
  226.         Lost_lines += Limcnt;
  227.         Limcnt = to - from + 1;        /* number of lines "deleted" */
  228.  
  229. #ifdef OLD_SCRATCH
  230.         Limbo = j1;     /* put what we just deleted in limbo */
  231.         relink (j2, j1, j2, j1);        /* close the ring */
  232. #else
  233.         /* point at first deleted */
  234.         Limbo = &Buf[MAXBUF - (to - from + 1)];
  235. #endif
  236.         *status = OK;
  237.         svdel (from, to - from + 1);
  238.         Buffer_changed = YES;
  239.     }
  240.  
  241.     return (*status);
  242. }
  243.  
  244.  
  245. /* join --- join a group of lines into a single line */
  246.  
  247. int join (sub)
  248. char sub[];
  249. {
  250.     char new[MAXLINE];
  251.     register int l, line, sublen;
  252.     int ret;
  253.     int inject (), delete (), prevln (), strlen ();
  254.     register LINEDESC *k;
  255.     LINEDESC *getind ();
  256.  
  257.     ret = OK;
  258.     if (Line1 <= 0)
  259.     {
  260.         Errcode = EORANGE;
  261.         return (ERR);
  262.     }
  263.  
  264.     sublen = strlen (sub) + 1;      /* length of separator & EOS */
  265.     line = Line1;
  266.     k = getind (line);
  267.     gtxt (k);
  268.     move_ (Txt, new, (int) k -> Lineleng);    /* move in first chunk */
  269.     l = k -> Lineleng;
  270.  
  271.     for (line++; line <= Line2; line++)
  272.     {
  273.         if (intrpt ())
  274.             return (ERR);
  275.         if (new[l - 2] == '\n') /* zap the NEWLINE */
  276.             l--;
  277.         k = NEXTLINE(k);    /* get the next line */
  278.         gtxt (k);
  279.         if (l + sublen - 1 + k -> Lineleng - 1 > MAXLINE)    /* won't fit */
  280.         {
  281.             Errcode = E2LONG;
  282.             return (ERR);
  283.         }
  284.         move_ (sub, &new[l - 1], sublen);    /* insert separator string */
  285.         l += sublen - 1;
  286.         move_ (Txt, &new[l - 1], (int) k -> Lineleng);    /* move next line */
  287.         l += k -> Lineleng - 1;
  288.     }
  289.     Curln = Line2;          /* all this will replace line1 through line2 */
  290.     ret = inject (new);    /* inject the new line */
  291.     if (ret == OK)
  292.         ret = delete (Line1, Line2, &ret);    /* delete old lines */
  293.     Curln++;
  294.  
  295.     if (First_affected > Curln)
  296.         First_affected = Curln;
  297.  
  298.     return (ret);
  299. }
  300.  
  301.  
  302. /* move --- move line1 through line2 after line3 */
  303.  
  304. int move (line3)
  305. int line3;
  306. {
  307.     int nextln (), prevln ();
  308.     LINEDESC *k0, *k1, *k2, *k3, *k4, *k5;
  309.     LINEDESC *getind ();
  310.  
  311.     if (Line1 <= 0)
  312.     {
  313.         Errcode = EORANGE;
  314.         return (ERR);
  315.     }
  316.  
  317.     if (Line1 <= line3 && line3 <= Line2)
  318.     {
  319.         Errcode = EINSIDEOUT;
  320.         return (ERR);
  321.     }
  322.  
  323. #ifdef OLD_SCRATCH
  324.     k0 = getind (prevln (Line1));
  325.     k1 = k0 -> Nextline;
  326.     k2 = getind (Line2);
  327.     k3 = k2 -> Nextline;
  328.     relink (k0, k3, k0, k3);
  329. #else
  330.     blkmove (Line1, Line2, line3);
  331. #endif
  332.  
  333.     if (line3 > Line1)
  334.     {
  335.         Curln = line3;
  336. #ifdef OLD_SCRATCH
  337.         line3 -= Line2 - Line1 + 1;
  338. #endif
  339.     }
  340.     else
  341.         Curln = line3 + (Line2 - Line1 + 1);
  342.  
  343. #ifdef OLD_SCRATCH
  344.     k4 = getind (line3);
  345.     k5 = k4 -> Nextline;
  346.     relink (k4, k1, k2, k5);
  347.     relink (k2, k5, k4, k1);
  348. #endif
  349.  
  350.     Buffer_changed = YES;
  351.     First_affected = min (First_affected, min (Line1, line3));
  352.  
  353.     return (OK);
  354. }
  355.  
  356. /* overlay --- let user edit lines directly */
  357.  
  358. overlay (status)
  359. int *status;
  360. {
  361.     char savtxt[MAXLINE], term, kname;
  362.     static char empty[] = "\n";
  363.     int lng, vcol, lcurln, scurln;
  364.     int inject (), nextln (), prevln (), strcmp ();
  365.     LINEDESC *indx;
  366.     LINEDESC *getind (), *gettxt ();
  367.  
  368.     *status = OK;
  369.     if (Line1 == 0)
  370.     {
  371.         Curln = 0;
  372.         *status = inject (empty);
  373.         if (*status == ERR)
  374.             return;
  375.         First_affected = 1;
  376.         Line1 = 1;
  377.         Line2++;
  378.     }
  379.  
  380.     for (lcurln = Line1; lcurln <= Line2; lcurln++)
  381.     {
  382.         Curln = lcurln;
  383.         vcol = Overlay_col - 1;
  384.         do {
  385.             adjust_window (Curln, Curln);
  386.             updscreen ();
  387.             Cmdrow = Curln - Topln + Toprow;
  388.             indx = gettxt (Curln);
  389.             lng = indx -> Lineleng;
  390.             if (Txt[lng - 2] == '\n')       /* clobber newline */
  391.                 lng--;
  392.             if (vcol < 0)
  393.                 vcol = lng - 1;
  394.             while (lng - 1 < vcol)
  395.             {
  396.                 Txt[lng - 1] = ' ';
  397.                 lng++;
  398.             }
  399.             Txt[lng - 1] = '\n';
  400.             Txt[lng] = EOS;
  401.             move_ (Txt, savtxt, lng + 1);    /* make a copy of the line */
  402.             getcmd (Txt, Firstcol, &vcol, &term);
  403.             if (term == FUNNY)
  404.             {
  405.                 if (First_affected > Curln)
  406.                     First_affected = Curln;
  407.                 Cmdrow = Botrow + 1;
  408.                 return;
  409.             }
  410.             if (strcmp (Txt, savtxt) != 0)  /* was line changed? */
  411.             {
  412.                 kname = indx -> Markname;
  413.                 delete (Curln, Curln, status);
  414.                 scurln = Curln;
  415.                 if (*status == OK)
  416.                     *status = inject (Txt);
  417.                 if (*status == ERR)
  418.                 {
  419.                     Cmdrow = Botrow + 1;
  420.                     return;
  421.                 }
  422.                 indx = getind (nextln (scurln));
  423.                 indx -> Markname = kname;
  424.             }
  425.             else
  426.             {           /* in case end-of-line is moved */
  427.                 if (First_affected > Curln)
  428.                     First_affected = Curln;
  429.             }
  430.             switch (term) {
  431.             case CURSOR_UP:
  432.                 if (Curln > 1)
  433.                     Curln--;
  434.                 else
  435.                     Curln = Lastln;
  436.                 break;
  437.             case CURSOR_DOWN:
  438.                 if (Curln < Lastln)
  439.                     Curln++;
  440.                 else
  441.                     Curln = min (1, Lastln);
  442.                 break;
  443.             case CURSOR_SAME:
  444.                 vcol = 0;
  445.                 break;
  446.             }
  447.         } while (term == CURSOR_UP || 
  448.             term == CURSOR_DOWN ||
  449.             term == CURSOR_SAME);
  450.     }
  451.     Cmdrow = Botrow + 1;
  452.     return;
  453. }
  454.  
  455.  
  456. /* subst --- substitute "sub" for occurrences of pattern */
  457.  
  458. int subst (sub, gflag, glob)
  459. char sub[];
  460. int gflag, glob;
  461. {
  462.     char new[MAXLINE], kname;
  463.     register int line, m, k, lastm;
  464.     int j, junk, status, subbed, ret;
  465.     int tagbeg[10], tagend[10];
  466.     int amatch (), addset (), inject ();
  467.     register LINEDESC *inx;
  468.     LINEDESC *gettxt (), *getind ();
  469.  
  470.     if (Globals && glob)
  471.         ret = OK;
  472.     else
  473.         ret = ERR;
  474.  
  475.     if (Line1 <= 0)
  476.     {
  477.         Errcode = EORANGE;
  478.         return (ERR);
  479.     }
  480.  
  481.     /* the following code has been removed for your protection
  482.        index() occasionally grabs newlines out of the character class
  483.        counter in a pattern.  for example [0-9] doesn't work due to this
  484.  
  485.         if (index (Pat, '\n') != -1)    # never delete NEWLINE
  486.         {
  487.             Errcode = EBADPAT;
  488.             return (ERR);
  489.         }
  490.     */
  491.  
  492.     for (line = Line1; line <= Line2; line++)
  493.     {
  494.         if (intrpt ())
  495.             break;
  496.         j = 0;
  497.         subbed = NO;
  498.         inx = gettxt (line);
  499.         lastm = -1;
  500.         for (k = 0; Txt[k] != EOS; )
  501.         {
  502.             for (m = 1; m <= 9; m++)
  503.             {
  504.                 tagbeg[m] = -1;
  505.                 tagend[m] = -1;
  506.             }
  507.             if (gflag == YES || subbed == NO)
  508.                 m = amatch (Txt, k, Pat, &tagbeg[1], &tagend[1]);
  509.             else
  510.                 m = -1;
  511.             if (m > -1 && lastm != m)       /* replace matched text */
  512.             {
  513.                 subbed = YES;
  514.                 tagbeg[0] = k;
  515.                 tagend[0] = m;
  516.                 catsub (Txt, tagbeg, tagend, sub, new, &j, MAXLINE);
  517.                 lastm = m;
  518.             }
  519.             if (m == -1 || m == k)  /* no match or null match */
  520.             {
  521.                 junk = addset (Txt[k], new, &j, MAXLINE);
  522.                 k++;
  523.             }
  524.             else
  525.                 k = m;    /* skip matched text */
  526.         }
  527.         if (subbed == YES)
  528.         {
  529.             if (addset (EOS, new, &j, MAXLINE) == NO)
  530.             {
  531.                 ret = ERR;
  532.                 Errcode = E2LONG;
  533.                 break;
  534.             }
  535.             kname = inx -> Markname;
  536.             delete (line, line, &status);    /* remembers dot */
  537.             ret = inject (new);
  538.             if (First_affected > Curln)
  539.                 First_affected = Curln;
  540.             if (ret == ERR)
  541.                 break;
  542.             inx = getind (Curln);
  543.             inx -> Markname = kname;
  544.             ret = OK;
  545.             Buffer_changed = YES;
  546.         }
  547.         else    /* subbed == NO */
  548.             Errcode = ENOMATCH;
  549.     }
  550.  
  551.     return (ret);
  552. }
  553.  
  554.  
  555. /* uniquely_name --- mark-name line; make sure no other line has same name */
  556.  
  557. uniquely_name (kname, status)
  558. char kname;
  559. int *status;
  560. {
  561.     register int line;
  562.     register LINEDESC *k;
  563.  
  564.     defalt (Curln, Curln);
  565.  
  566.     if (Line1 <= 0)
  567.     {
  568.         *status = ERR;
  569.         Errcode = EORANGE;
  570.         return;
  571.     }
  572.  
  573.     *status = OK;
  574.     line = 0;
  575.     k = Line0;
  576.  
  577.     do {
  578.         line++;
  579.         k = NEXTLINE(k);
  580.         if (line == Line2)
  581.             k -> Markname = kname;
  582.         else if (k -> Markname == kname)
  583.             k -> Markname = DEFAULTNAME;
  584.     } while (line < Lastln);
  585.  
  586.     return;
  587. }
  588.  
  589.  
  590. /* draw_box --- draw or erase a box at coordinates in command line */
  591.  
  592. int draw_box (lin, i)
  593. char lin[];
  594. int *i;
  595. {
  596.     register int left, right, col, len;
  597.     int junk;
  598.     int ctoi (), strcmp (), inject (), delete ();
  599.     register LINEDESC *k;
  600.     LINEDESC *getind (), *gettxt ();
  601.     char text[MAXLINE];
  602.     char kname, ch;
  603.  
  604.     left = ctoi (lin, i);
  605.     if (left <= 0 || left > MAXLINE)
  606.     {
  607.         Errcode = EBADCOL;
  608.         return (ERR);
  609.     }
  610.  
  611.     if (lin[*i] == ',')
  612.     {
  613.         (*i)++;
  614.         SKIPBL (lin, *i);
  615.         right = ctoi (lin, i);
  616.         if (right <= 0 || right >= MAXLINE || left > right)
  617.         {
  618.             Errcode = EBADCOL;
  619.             return (ERR);
  620.         }
  621.     }
  622.     else
  623.         right = left;
  624.  
  625.     SKIPBL (lin, *i);
  626.     if (lin[*i] == '\n')
  627.         ch = ' ';
  628.     else
  629.         ch = lin[(*i)++];
  630.  
  631.     if (lin[*i] != '\n')
  632.     {
  633.         Errcode = EEGARB;
  634.         return (ERR);
  635.     }
  636.  
  637.     if (Line1 <= 0)
  638.     {
  639.         Errcode = EORANGE;
  640.         return (ERR);
  641.     }
  642.  
  643.     for (Curln = Line1; Curln <= Line2; Curln++)
  644.     {
  645.         k = gettxt (Curln);
  646.         len = k -> Lineleng;
  647.         move_ (Txt, text, len);
  648.  
  649.         if (text[len - 2] == '\n')
  650.             col = len - 1;
  651.         else
  652.             col = len;
  653.         while (col <= right)
  654.         {
  655.             text[col - 1] = ' ';
  656.             col++;
  657.         }
  658.         text[col - 1] = '\n';
  659.         text[col] = EOS;
  660.  
  661.         if (Curln == Line1 || Curln == Line2)
  662.             for (col = left; col <= right; col++)
  663.                 text[col - 1] = ch;
  664.         else
  665.         {
  666.             text[left - 1] = ch;
  667.             text[right - 1] = ch;
  668.         }
  669.  
  670.         if (strcmp (text, Txt) != 0)
  671.         {
  672.             kname = k -> Markname;
  673.             if (delete (Curln, Curln, &junk) == ERR
  674.                 || inject (text) == ERR)
  675.                 return (ERR);
  676.             k = getind (Curln);
  677.             k -> Markname = kname;
  678.             Buffer_changed = YES;
  679.         }
  680.     }
  681.  
  682.     Curln = Line1;        /* move to top of box */
  683.     if (First_affected > Curln)
  684.         First_affected = Curln;
  685.     adjust_window (Curln, Curln);
  686.     updscreen ();
  687.  
  688.     return (OK);
  689. }
  690.  
  691.  
  692. /* dfltsopt --- set the 's' option to the extension on the file name */
  693.  
  694. dfltsopt (name)
  695. char name[];
  696. {
  697.     int i;
  698.     int strlen (), dosopt ();
  699.  
  700.     for (i = strlen (name) - 1; i >= 0; i--)
  701.         if (name[i] == '.')
  702.         {
  703.             dosopt (&name[i + 1]);
  704.             break;
  705.         }
  706.     if (i < 0)
  707.         dosopt ("");
  708. }
  709.  
  710.  
  711.  
  712. /* doshell --- escape to the Shell to run one or more Unix commands */
  713.  
  714. /*
  715. ** emulate vi: if running just a shell, redraw the screen as
  716. ** soon as the shell exits. if running a program, let the user
  717. ** redraw the screen when he/she is ready.
  718. **
  719. ** also emulate USG Unix 5.0 ed: a ! as the first character is
  720. ** replaced by the previous shell command; an unescaped % is replaced
  721. ** by the saved file name. The expanded command is echoed.
  722. **
  723. ** If running at ICS school at Tech, and RSE is in the environment, don't
  724. ** allow forking, since it's called by a mail-only user.
  725. */
  726.  
  727. #ifdef BSD
  728. #define DEFAULT_PATH    "/bin/csh"
  729. #define DEF_SHELL    "csh"
  730. #else
  731. #define DEFAULT_PATH    "/bin/sh"
  732. #define DEF_SHELL    "sh"
  733. #endif
  734.  
  735. int doshell (lin, pi)
  736. char lin[];
  737. int *pi;
  738. {
  739.     int forkstatus, childstatus;
  740.     int (*save_quit)(), (*save_int)();
  741.     int int_hdlr ();
  742.     int (*signal())();
  743.     int i, auto_redraw;
  744.     char *path, *name, *p, *getenv ();
  745.     char new_command[MAXLINE];
  746.     int j, k;
  747.     static char sav_com[MAXLINE] = "";
  748.     int expanded = NO;
  749.  
  750.     if (At_gtics && getenv ("RSE") != NULL)    /* yes in environment */
  751.     {
  752.         remark ("You may not run the shell");
  753.         return OK;    /* will wipe out command line */
  754.     }
  755.  
  756.     if (Nlines == 0)        /* use normal 'ed' behavior */
  757.     {
  758.         tflush ();    /* flush out the terminal output */
  759.         position_cursor (Nrows - 1, 0);    /* bottom left corner */
  760.  
  761.         if ((p = getenv ("SHELL")) == NULL || strcmp (p, DEFAULT_PATH) == 0)
  762.         {
  763.             path = DEFAULT_PATH;
  764.             name = DEF_SHELL;    /* default */
  765.         }
  766. #ifdef BSD
  767.         /* on Berkeley systems, check the other shell */
  768.         else if (strcmp (p, "/bin/sh") == 0)
  769.         {
  770.             path = "/bin/sh";
  771.             name = "sh";
  772.         }
  773. #endif
  774.         else
  775.         {
  776.             if (p[0] == '/')    /* full pathname there */
  777.             {
  778.                 /* work backwards to find just name */
  779.                 path = p;
  780.                 i = strlen (p);
  781.                 while (p[i] != '/')
  782.                     i--;
  783.                 i++;        /* skip '/' */
  784.                 name = &p[i];
  785.             }
  786.             else
  787.             {
  788.                 char buf[MAXLINE];
  789.  
  790.                 sprintf (buf, "unknown shell, using %s",
  791.                     DEF_SHELL);
  792.                 remark (buf);
  793.                 path = DEFAULT_PATH;
  794.                 name = DEF_SHELL;
  795.             }
  796.         }
  797.  
  798.         auto_redraw = (lin[*pi] == '\n') ? YES : NO;
  799.  
  800.         /* build command, checking for leading !, and % anywhere */
  801.         if (lin[*pi] == '!')
  802.         {
  803.             if (sav_com[0] != EOS)
  804.             {
  805.                 for (j = 0; sav_com[j] != EOS; j++)
  806.                     new_command[j] = sav_com[j];
  807.                 if (new_command[j-1] == '\n')
  808.                     j--;
  809.                 (*pi)++;
  810.                 expanded = YES;
  811.             }
  812.             else
  813.             {
  814.                 Errcode = ENOCMD;
  815.                 return (ERR);
  816.             }
  817.         }
  818.         else
  819.             j = 0;
  820.  
  821.         for (i = *pi; lin[i] != EOS; i++)
  822.         {
  823.             if (lin[i] == ESCAPE)
  824.             {
  825.                 if (lin[i+1] != '%')
  826.                 {
  827.                     new_command[j++] = ESCAPE;
  828.                     new_command[j++] = lin[++i];
  829.                 }
  830.                 else
  831.                     new_command[j++] = lin[++i];
  832.             }
  833.             else if (lin[i] == '%')
  834.             {
  835.                 for (k = 0; Savfil[k] != EOS; k++)
  836.                     new_command[j++] = Savfil[k];
  837.                 expanded = YES;
  838.             }
  839.             else
  840.                 new_command[j++] = lin[i];
  841.         }
  842.  
  843.         if (new_command[j-1] == '\n')
  844.             j--;
  845.         new_command[j] = EOS;
  846.  
  847.         strcpy (sav_com, new_command);    /* save it */
  848.  
  849.         ttynormal ();
  850. #ifndef HARD_TERMS
  851.         t_exit ();
  852. #endif
  853.         write (1, "\n\n", 2);            /* clear out a line */
  854.  
  855.         forkstatus = fork();
  856.         if (forkstatus == -1)   /* the fork failed */
  857.         {
  858.             ttyedit ();
  859. #ifndef HARD_TERMS
  860.             t_init ();
  861. #endif
  862.             Errcode = ECANTFORK;
  863.             return ERR;
  864.         }
  865.  
  866.         if (forkstatus == 0)    /* we're in the child process */
  867.         {
  868.             signal (SIGINT, SIG_DFL);
  869.             signal (SIGQUIT, SIG_DFL);
  870. #ifdef BSD
  871.             if (strcmp (name, "sh") != 0)    /* not /bin/sh */
  872.                 signal (SIGTSTP, SIG_DFL);
  873.             else
  874.                 signal (SIGTSTP, SIG_IGN);
  875. #endif
  876.             if (auto_redraw)    /* no params; run a shell */
  877.             {
  878.                 execl (path, name, 0);
  879.                 _exit (RETERR);   /* exec failed, notify parent */
  880.             }
  881.             else
  882.             {
  883.                 if (expanded)        /* echo it */
  884.                     printf ("%s\n", new_command);
  885.  
  886.                 execl (path, name, "-c", new_command, 0);
  887.                 _exit (RETERR);
  888.             }
  889.         }
  890.  
  891.         /* we're in the parent process here */
  892.         save_int = signal (SIGINT, SIG_IGN);        /* ignore interrupts */
  893.         save_quit = signal (SIGQUIT, SIG_IGN);
  894.         while (wait (&childstatus) != forkstatus)
  895.             ;
  896.         save_int = signal (SIGINT, save_int);       /* catch interupts */
  897.         save_quit = signal (SIGQUIT, save_quit);
  898.         write (1, "\n\n", 2);    /* clear out some message space */
  899.         Currow = Nrows - 1;
  900.         Curcol = 0;
  901.         if ((childstatus >> 8) != 0)
  902.         {
  903.             ttyedit ();
  904. #ifndef HARD_TERMS
  905.             t_init ();
  906. #endif
  907.             Errcode = ENOSHELL;
  908.             return ERR;
  909.         }
  910.  
  911. /* this was the old way, so you can compare to what we do now. */
  912. /*
  913. /*        if (auto_redraw)
  914. /*        {
  915. /*            ttyedit();
  916. /*            restore_screen ();
  917. /*        }
  918. /*        else
  919. /*            remark("Type control-q to rebuild screen");
  920. */
  921.  
  922.         /* a la vi: */
  923.         if (! auto_redraw)
  924.         {
  925.             int c;
  926.  
  927.             printf ("type return to continue: ");
  928.             while ((c = getchar()) != '\n' && c != EOF)
  929.                 ;
  930.         }
  931.  
  932.         ttyedit ();
  933. #ifndef HARD_TERMS
  934.         t_init ();
  935. #endif
  936.         restore_screen ();
  937.  
  938.         return OK;
  939.     }
  940.  
  941.     else
  942.         remark ("Not implemented yet");
  943.     
  944.     return OK;
  945. }
  946.