home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / researchmachines / rmluti.c < prev   
Text File  |  1985-07-10  |  14KB  |  623 lines

  1.  
  2. /************************************************************************/
  3.  
  4. /*  File  KUTIL2.C  -  Extended buffer filling/emptying procedures etc.
  5.         Chris Kennington    RML.    9th July 1985    */
  6.  
  7. #define     DEFS1        1
  8. #define  DEFS3        1
  9. #define     DEFS4        1
  10.  
  11. #include  "stdio.h"
  12. #include  "ctype.h"
  13. #include  "b:kext.h"
  14.  
  15. /* Variables global to this file:-                */
  16.  
  17. static    int    oldsz, oldt, qu8=0, rpt, sz;
  18. static    char    *dt;
  19. static  char    del1[]  = {BKSP,SP,0};
  20. static    char    del7[]    = {BKSP,BKSP,BKSP,BKSP,BKSP,BKSP,BKSP,SP,SP,SP,SP,SP,SP,SP,0};
  21. #ifndef MPUZ80
  22. static  char    *images[] = {"7-bit stripped","8-bit binary","8th-bit prefixed",0};
  23. #endif
  24.  
  25. extern  int  outfc(), outfile();
  26.  
  27.  
  28.  
  29. char  ascch(c)        /* edit out multiple CR/LFs        */
  30. /* Returns c unless redundant, when returns 0            */
  31. char    c;
  32. {
  33.     static char oldc = 0;
  34.  
  35.     c &= 0x7f;            /* strip to 7 bits        */
  36.     if ( ( (c == CR) && (oldc == LF) ) || ( (c == LF) && (oldc == CR) ) )
  37.     c = oldc = 0;
  38.     else {
  39.     oldc = c;
  40.     if (c == LF)
  41.         c = CR;
  42.     }
  43.     return(c);
  44. }        /* end of ascch()                */
  45.  
  46.  
  47.  
  48. bufemp(buffer,len)
  49. /*  Puts data from an incoming packet into a file,
  50.     sleeping & waking comms & network.
  51.     If no file open (fp = 0), displays on screen
  52.     Returns 0 if OK, else contents of "errno".            */
  53. char  buffer[];                /* Buffer */
  54. int   len;
  55. {
  56.     int  ret;
  57.  
  58.     if (fp == 0)
  59.     ret = decode(buffer,len,outfc);
  60.     else {
  61.     s4sleep();            /* Inhibit communications */
  62.     if (list == 1)
  63.         outc('.');
  64.     ret = decode(buffer,len,outfile);
  65.     }
  66.     netcool();
  67.     return(ret);
  68. }                /* end of bufemp()        */
  69.  
  70.  
  71.  
  72. bufill(buffer)
  73. /*  Get a bufferful of data from the file that's being sent, sleeping
  74.  *    & waking comms & network.
  75.  *  Traps CP/M soft EoF (ctl-Z).                 */
  76. char *buffer;
  77. {
  78.     int t;
  79.  
  80.     s4sleep();                /* Inhibit communications */
  81.     errno = 0;
  82.     dt = buffer;
  83.     if (softeof) {            /* Trap CP/M text-file    */
  84.     sz = EOF;
  85.     goto Exit;
  86.     }
  87.     if (list == 1)
  88.     outc('.');            /* dot-printing    */
  89.     rpt = sz = 0;            /* Init data buffer pointer */
  90.     oldt = -2;                /* impossible value    */
  91.     while((t = getc(fp)) != EOF) {    /* Get the next character */
  92.   /* if there is an error, getc() will also return EOF and there is an
  93.      error-code in "errno".  This is picked up in sdata().        */
  94. #ifdef MPUZ80
  95.     if (list == 2) 
  96. #else
  97.     if ( (list == 2) && (t != LF) )
  98. #endif
  99.         outc(t);
  100.     encode(t);
  101.     if ( (image == 0) && (t == CTLZ) ) {
  102.         softeof = TRUE;
  103.         goto Exit;            /* CP/M text EOF    */
  104.     }
  105.     if (sz > spsiz-7)        /* Check length        */
  106.          goto Exit;
  107.     }
  108.   /* reach here on (hard) EOF or error                */
  109.     softeof = TRUE;            /* so dont reread    */
  110.     if (sz==0)
  111.     sz = EOF;
  112. Exit:
  113.     netcool();
  114.     return(sz);                /* Handle partial buffer */
  115. }            /* end of bufill()        */
  116.  
  117.  
  118.  
  119. clear5()        /* clear bottom lines of screen        */
  120. {
  121.     int    lin;
  122.  
  123.     lin = (SCRBOT+3)*256;
  124.     while (lin < (SCRLEN*256)) {
  125.     vtline(lin,blanx);
  126.     lin += 256;
  127.     }
  128. }            /* end of clear5()            */
  129.  
  130.  
  131.  
  132. compmode()        /* display transfer modes        */
  133. {
  134.     if (image == 2)
  135.     txtout(" 8-bit data, ");
  136.     else if (oldimage == 2) {
  137.     printmsg("Warning: 8-bit transfer not agreed by remote Kermit.\r");
  138.     oldimage = image;
  139.     }
  140.     if (rptflg == TRUE)
  141.     txtout(" Compressing, ");
  142.     return;
  143. }            /* end of compmode()            */
  144.  
  145.  
  146.  
  147. decode(buf,len,fn)        /* packet decoding procedure    */
  148. /* Called with string to be decoded and an output function.
  149.     Returns 0 or error-code.                */
  150. char *buf;
  151. int  len, (*fn)();
  152. {
  153.     char  a, a7, b8, *end, rep;
  154.     int   flg8=0, r, rr=0;
  155.  
  156.     if (image == 2)
  157.     flg8 = -1;
  158.  
  159.     end = buf + len;
  160.     while (buf < end) {
  161.     a = *buf++;
  162.     if ( rptflg && (a == '~') ) {    /* got a repeat prefix? */
  163.         rep = unchar(*buf++);    /* Yes, get the repeat count, */
  164.         a = *buf++;        /* and get the prefixed character. */
  165.     }
  166.     else
  167.         rep = 1;
  168.     b8 = 0;                /* Check high order "8th" bit */
  169.     if ( flg8 && (a == qu8) ) {
  170.         b8 = 0200;
  171.         a = *buf++;        /* and get the prefixed character. */
  172.         }
  173.     if (a == quote) {        /* If control prefix, */
  174.         a  = *buf++;        /* get its operand. */
  175.         a7 = a & 0177;        /* Only look at low 7 bits. */
  176.         if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') /* Uncontrollify */
  177.         a = ctl(a);            /* if in control range. */
  178.     }
  179.     a |= b8;            /* OR in the 8th bit */
  180.     while (rep-- > 0) {
  181.         r = (*fn)(a);        /* Send them to the output function. */
  182.         rr |= r;
  183.     }    }
  184.     return(rr);
  185. }            /* end of decode()            */
  186.  
  187.  
  188.  
  189. encode(a)                
  190. /* encode single character into packet for transmission    */
  191. int a;                /* char to be encoded        */
  192. {
  193.     int a7;                /* Low order 7 bits    */
  194.     int b8;                /* 8th bit of character */
  195.     int flg8 = 0;
  196.  
  197.     if (image == 2)
  198.     flg8 = -1;
  199.  
  200.     if (rptflg)    {        /* repeat-count processing    */
  201.         if (a == oldt) {        /* char is same        */
  202. /* This algorithm is simple but relatively inefficient; it stores
  203.     the repeat flag, count and character each time around so
  204.     that when the run is broken the buffer is valid; also it
  205.     treats a pair as a run, which requires 3 bytes not 2 unless
  206.     the pair is control- or 8bit-prefixed; but it does not
  207.     require lookahead logic from the data-read.        */
  208.         sz = oldsz;            /* wind back pointer    */
  209.         dt[sz++] = '~';        /*  store prefix    */
  210.         dt[sz++] = tochar(++rpt);    /*   & count        */
  211.         if (rpt > 93)        /* force new start    */
  212.         oldt = -2;        /* impossible value    */
  213.     }
  214.     else {                /* not run, or end    */
  215.         rpt = 1;
  216.         oldt = a;            /* save char        */
  217.         oldsz = sz;
  218.     }    }
  219.  
  220.     a7 = a & 0177;            /* Isolate ASCII part */
  221.     b8 = a & 0200;            /* and 8th (parity) bit. */
  222.  
  223.     if (flg8 && b8) {            /* Do 8th bit prefix if necessary. */
  224.         dt[sz++] = qu8;
  225.         a = a7;
  226.     }
  227.     if ((a7 < SP) || (a7==DELT)) {    /* Do control prefix if necessary */
  228.         dt[sz++] = MYQUOTE;
  229.     a = ctl(a);
  230.     }
  231.     if (a7 == MYQUOTE)            /* Prefix the control prefix */
  232.         dt[sz++] = MYQUOTE;
  233.     else if (rptflg && (a7 == '~'))    /* If it's the repeat prefix, */
  234.         dt[sz++] = MYQUOTE;        /* quote it if doing repeat counts. */
  235.     else if (flg8 && (a7 == qu8))        /* Prefix the 8th bit prefix */
  236.         dt[sz++] = MYQUOTE;        /* if doing 8th-bit prefixes */
  237.  
  238.     dt[sz++] = a;            /* Finally, insert the character */
  239.     dt[sz] = '\0';            /* itself, and mark the end. */
  240.     return;
  241. }            /* end of encode()        */
  242.  
  243.  
  244.  
  245.  
  246. error(fmt, a1, a2, a3, a4, a5)
  247. /*  Generate both error-message to user and if suitable
  248.     error-packet to remote.                */
  249. char *fmt;
  250. {
  251.     int len;
  252.  
  253.     sprintf(packet,fmt,a1,a2,a3,a4,a5);
  254.     printmsg(packet);
  255.     if ( (kmode == RECV) || (kmode == SEND) ) {
  256.     len = strlen(packet) + 1;
  257.     spack('E',n,len,packet);
  258.     }
  259.     return;
  260. }            /* end of error()    */
  261.  
  262.  
  263.  
  264.  
  265. /*  kropen(), kwopen(), kclose():
  266.   Open and close CP/M files making necessary calls to sleep
  267.     and wake disk system & network.                */
  268.  
  269. kclose(fptr)        /* close file                */
  270. FILE  *fptr;
  271. {
  272.     int      ret;
  273.  
  274.     if (fptr == 0)
  275.     return;
  276.     bell();
  277.     ++files;
  278.     s4sleep();
  279.     if ( (ret = fclose(fptr)) < 0)
  280.     printmsg(diskfail,errno);    /* Aztec's  error-code    */
  281.     else
  282.     ret = 0;
  283.     netcool();
  284.     return(ret);
  285. }            /* end of kclose()            */
  286.  
  287.  
  288. FILE  *kropen(name)    /* open file for reading        */
  289. char  name[];
  290. {
  291.     FILE  *frp;
  292.  
  293.     s4sleep();
  294.     softeof = FALSE;
  295.     frp = fopen(name,"r");
  296.     netcool();
  297.     return(frp);
  298. }            /* end of fropen()            */
  299.  
  300.  
  301. FILE  *kwopen(name)    /* open file for writing        */
  302. char  *name;
  303. {
  304.     FILE  *frp;
  305.  
  306.     s4sleep();
  307.     frp = fopen(name,"w");
  308.     netcool();
  309.     return(frp);
  310. }            /* end of kwopen()            */
  311.  
  312. /* end of open-&-close routines                    */
  313.  
  314.  
  315.  
  316. no_op()            /* null routine                */
  317. {
  318.     return;
  319. }            /* End of no_op()            */
  320.  
  321.  
  322.  
  323. outfc(ch)        /* output char with control        */
  324. char    ch;
  325. /* expands tabs (every 8) and handles paging;
  326.    returns 1 if CTLC input at CR or LF, else 0.            */
  327. {
  328.     static char col=0;
  329.     char    c, *more, *dlt;
  330.  
  331.     if (ch < SP) switch(ch) {
  332.   /* deal with selected control-characters            */
  333.       case CR:
  334.     if (kbdin() == CTLC)
  335.         return(1);
  336.     if (pager != 0)
  337.         if ( ++scrline > (pager << 2) ) {
  338.         if (col < 73) {        /* room for "[more]"    */
  339.             while (col++ < 73)
  340.             outc(SP);
  341.             more = "[more]";
  342.             while ( (c = *more++) != 0)
  343.             outc(c);
  344.             dlt = del7;
  345.         }
  346.         else if (col < 79)  {            /* no room        */
  347.             while (col++ < 78)
  348.             outc(SP);
  349.             outc('*');
  350.             dlt = del1;
  351.         }
  352.         else
  353.             dlt = null;
  354.         if ( (commode & 0x02) != 0 )
  355.             nextout(XOFF);        /* hold up    */
  356.         while ( (c = kbdin()) == 0)
  357.             ;
  358.         if ( (commode & 0x02) != 0 )
  359.             nextout(XON);        /* restart    */
  360.         scrline = 0;
  361.         if (c == CTLC)
  362.             return(1);
  363.         while ( (c = *dlt++) != 0)
  364.             outc(c);
  365.         }
  366.     outc(ch);
  367.     col = 0;
  368.     break;
  369.  
  370.       case LF:
  371.   /* ignored - CR is expected to be treated as "newline"    */
  372.     break;
  373.  
  374.       case TAB:
  375.     c = 8 - (col & (char)0x07);
  376.     col &= (char)0xf8;
  377.     col += 0x08;
  378.     while (c-- > 0)
  379.         outc(SP);
  380.     break;
  381.  
  382.       case BKSP:
  383.     if (col-- < 0)
  384.         col = 0;
  385.     else
  386.         outc(BKSP);
  387.     break;
  388.  
  389.       default:            /* pass all other controls    */
  390.     outc(ch);
  391.     break;
  392.     }                /* end if-switch        */
  393.     else {            /* normal chars            */
  394.     outc(ch);
  395.     ++col;
  396.     }
  397.     return(0);
  398. }                /* end of outfc()        */
  399.  
  400.  
  401.  
  402.  
  403. static int outfile(ch)   /* char to file            */
  404. /* Returns 0 or error-code                    */
  405. char    ch;
  406. {
  407.     int    r;
  408.  
  409.     r = errno = 0;
  410.     if (image == 0)        /* for 7-bit transfers    */
  411.     if ( (ch = ascch(ch)) == 0 ) /* CR/LF trapping    */
  412.         return(0);        /* ignore nulls        */
  413.     else if (ch == CR) {    /*  CR => CR/LF    */
  414.         putc(CR,fp);
  415.         if (list == 2)
  416.         outc(CR);
  417.         ch = LF;
  418.     }                /* end elseif    */
  419. #ifndef MPUZ80
  420.     if ( (list == 2) && (ch != LF) )
  421. #else
  422.     if (list == 2)
  423. #endif
  424.     outc(ch);
  425.     if (putc(ch,fp) < 0)
  426.     r = errno;        /* accumulate errors    */
  427.     return(r);
  428. }        /* end of outfile()                */
  429.  
  430.  
  431.  
  432. parex()        /* exchange parameters            */
  433. /* returns 1 if successful, -1 if refused, 0 if no answer;
  434.     only allows 3 timeouts/NAKs            */
  435. {
  436.     int      ln1, ln2, num, r=0, t;
  437.  
  438.     ln1 = spar(packet);        /* fill with ours    */
  439.     forever {
  440.     spack('I',0,ln1,packet);
  441.     switch( (t = rpack(&ln2,&num,recpkt)) ) {
  442.       case 'Y':        /* ACK            */
  443.         rpar(recpkt,ln2);    /* take theirs        */
  444.         txtout(" OK ");
  445.         compmode();
  446.         n = num + 1;    /* initial number    */
  447.         return(1);
  448.       case 'N':        /* NAK            */
  449.       case FALSE:        /* timeout        */
  450.         if (r++ > 3)
  451.         return(0);
  452.         else
  453.         break;
  454.       default:        /* protocl error    */
  455.         printmsg(badmsg,'Y',t);
  456.       case 'E':        /* cant cope        */
  457.         return(-1);
  458.     }        /* end switch            */
  459.     txtout(trying);
  460.     }            /* end forever            */
  461. }        /* end of parex()            */
  462.  
  463.  
  464.  
  465. rpar(data,len)    /* instal received parameters safely        */
  466. char    *data, len;
  467. /* Set up incoming parameters to either what has been received
  468.     or, if nil, to defaults.
  469.   RML Kermit does not handle variable timeouts.
  470.   No return-code.                        */
  471. {
  472.     char    i, p;
  473.  
  474.   /* initialize to defaults in case incoming block is short    */
  475.     spsiz = 80;            /* packet-length 80 chars    */
  476.     eol = CR;            /* terminator normally CR    */
  477.     quote = '#';        /* standard control-quote char    */
  478.     qu8 = 0;            /* no 8th-bit quoting        */
  479.     rptflg = 0;            /*  nor repeat-quoting        */
  480.   /* image is not changed                    */
  481.  
  482.     i = 0;
  483.     while (len-- > 0) {
  484.     p = data[len];
  485.     
  486.     switch (len) {        /* for each parameter        */
  487.  
  488.       case 0:            /* MAXL            */
  489.         spsiz = unchar(p);
  490.         break;
  491.  
  492.       case 2:            /* NPAD            */
  493.         pad = unchar(p);
  494.         break;
  495.  
  496.       case 3:            /* PADC            */
  497.         padchar = ctl(p);
  498.         break;
  499.  
  500.       case 4:            /* EOL            */
  501.         eol = unchar(p);
  502.         break;
  503.  
  504.       case 5:            /* QCTL            */
  505.         quote = p;
  506.         break;
  507.  
  508.       case 6:            /* QBIN            */
  509.   /* 8th-bit quoting only negotiable if set by user        */
  510.         i = 1;
  511.         if (image == 2) switch (p) {
  512.           case 'Y':
  513.         qu8 = '&';
  514.         break;
  515.           case 'N':
  516.         qu8 = image = 0;
  517.         break;
  518.           default:
  519.         if (isalnum(p) == 0)    /* provided punctuation */
  520.             qu8 = p;
  521.         else
  522.             qu8 = image = 0;
  523.         break;
  524.         }            /* end inner switch        */
  525.         break;
  526.  
  527.       case 8:            /* REPT            */
  528.         if (p == '~')
  529.         rptflg = TRUE;
  530.         break;
  531.  
  532.       default:            /* CHKT, CAPAS etc.    */
  533.         break;
  534.  
  535.     }    }            /* end while & outer switch    */
  536.  
  537.     if (i == 0)                /* no data[6]        */
  538.     qu8 = 0;
  539.     if ( (qu8 == 0) && (image == 2) )    /* invlaid setting    */
  540.     image = 0;
  541.     if (list > 2) {            /* debug only        */
  542.     printf("\rDbg: Parameters in, 8th-bit setting now %d ",image);
  543. #ifndef MPUZ80
  544.     printf("(%s)",images[image]);
  545.     if (image == 2)
  546.         printf(", prefix %c. ",qu8);
  547.     else
  548.         printf(". ");
  549. #endif
  550.     }
  551.     return;
  552. }            /* end of rpar()            */
  553.  
  554.  
  555.  
  556.  
  557. show5(text)
  558. /* display up to 5 lines of text at bottom of screen    */
  559. char **text;
  560. {
  561.     char    c,  *hp;
  562.     int        lin;
  563.  
  564.     clear5();            /* clear it first    */
  565.     lin = (SCRBOT+3)*256;
  566.     for (c=0; c<5; ++c) {
  567.     if ( (hp = text[c]) == 0 )
  568.         break;
  569.     vtline(lin,hp);
  570.     if ( (lin += 256) > 24*256)
  571.         break;
  572.     }
  573.     return;
  574. }            /* end of show5()            */
  575.  
  576.  
  577.  
  578. spar(data)        /* fill up packet with own parameters    */
  579. char    *data;
  580. /* returns length of parameter block (6, 7 or 9)        */
  581. {
  582.     char    len;
  583.  
  584.     data[0] = tochar(spsiz);
  585.     data[1] = tochar(MYTIME);
  586.     data[2] = tochar(MYPAD);
  587.     data[3] = ctl(0);
  588.     data[4] = tochar(MYEOL);
  589.     data[5] = MYQUOTE;
  590.     len = 6;                /* min length        */
  591.     if (image == 2) {
  592.     data[6] = 'Y';            /*  feed back 8-quote    */
  593.     if (qu8 == 0)
  594.         qu8 = '&';
  595.     len = 7;
  596.     }
  597.     else {
  598.     data[6] = 'N';            /*  otherwise reject    */
  599.     qu8 = 0;
  600.     }
  601.     if (rptflg) {            /* if repeat-quoting    */
  602.     data[7] = '1';            /*  1-byte checksum    */
  603.     data[8] = '~';            /*  only ~ for repeating*/
  604.     len = 9;
  605.     }
  606.     if (list > 2) {            /* debug only        */
  607.     printf("\rDbg: Parameters out, 8th-bit setting now %d ",image);
  608. #ifndef MPUZ80
  609.     printf("(%s)",images[image]);
  610.     if (image == 2)
  611.         printf(", prefix %c. ",qu8);
  612.     else
  613.         printf(". ");
  614. #endif
  615.     }
  616.     return(len);
  617. }            /* end of spar()            */
  618.  
  619.  
  620.  
  621. /**********************  End of KUTIL2.C  **************************/
  622.  
  623.