home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / ncr9800 / ckvfns.c < prev    next >
C/C++ Source or Header  |  1990-07-12  |  32KB  |  1,021 lines

  1. char *fnsv = "V-Kermit functions, 4E(054) 29 May 90";
  2.  
  3. /*  C K V F N S  --  System-independent Kermit protocol support functions.  */
  4.  
  5. /**********************************************************************
  6. *                                                                     *
  7. * IVS / MCS-Kermit REL 2                                              *
  8. * source code                                                         *
  9. *                                                                     *
  10. * Change History:                                                     *
  11. *                                                                     *
  12. *                1. Modify C-Kermit(4E) source code to                *
  13. *                   produce new module for MCS/IVS-Kermit             *
  14. *                   ORIGINAL RELEASE                                  *
  15. *                   June 22, 1990                                     *
  16. *                                                                     *
  17. *                                                                     *
  18. ***********************************************************************/
  19.  
  20.  
  21. /*  ...Part 1 (others moved to ckcfn2 to make this module small enough) */
  22.  
  23. /*
  24.  Author: Frank da Cruz (fdc@cunixc.cc.columbia.edu, FDCCU@CUVMA.BITNET),
  25.  Columbia University Center for Computing Activities.
  26.  First released January 1985.
  27.  Copyright (C) 1985, 1989, Trustees of Columbia University in the City of New
  28.  York.  Permission is granted to any individual or institution to use, copy, or
  29.  redistribute this software so long as it is not sold for profit, provided this
  30.  copyright notice is retained.
  31. */
  32. /*
  33.  System-dependent primitives defined in:
  34.  
  35.    ck?tio.c -- terminal i/o
  36.    ck?fio.c -- file i/o, directory structure
  37. */
  38. #include "ckcsym.h"            /* Need this for Mac */
  39. #include "ckcker.h"            /* Symbol definitions for Kermit */
  40. #include "ckcdeb.h"            /* Debug formats, typedefs, etc. */
  41.  
  42. #ifndef NULL
  43. #define NULL 0
  44. #endif
  45.  
  46. /* Externals from ckcmai.c */
  47. extern int spsiz, rpsiz, timint, rtimo, npad, ebq, ebqflg, rpt, rptq,
  48.  rptflg, capas, keep;
  49. extern int pktnum, prvpkt, sndtyp, bctr, bctu, fmask,
  50.  size, osize, maxsize, spktl, nfils, stdouf, /* warn, */ timef, spsizf;
  51. extern int parity, speed, turn, turnch,
  52.  delay, displa, pktlog, tralog, seslog, xflg, mypadn;
  53. extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, fsize;
  54. extern int tsecs;
  55. extern int deblog, hcflg, binary, savmod, fncnv, local, server, cxseen, czseen;
  56. extern int rq, rqf, sq, wsize, urpsiz, rln;
  57. extern int atcapr, atcapb, atcapu;
  58. extern int lpcapr, lpcapb, lpcapu;
  59. extern int swcapr, swcapb, swcapu;
  60. extern CHAR padch, mypadc, eol, seol, ctlq, myctlq, sstate;
  61. extern CHAR filnam[], sndpkt[], recpkt[], data[], srvcmd[], stchr, mystch;
  62. extern char *cmarg, *cmarg2, *hlptxt, **cmlist;
  63. extern CHAR *srvptr;
  64. extern char *rdatap;
  65. long zchki();
  66. char *strcpy();
  67. CHAR *rpar();
  68.  
  69. /* Variables local to this module */
  70.  
  71. static char *memptr;            /* Pointer for memory strings */
  72.  
  73. static char cmdstr[100];        /* NCR-VRX system command string */
  74.  
  75. static int  sndsrc;            /* Flag for where to send from: */
  76.                     /* -1: name in cmdata */
  77.                     /*  0: stdin          */
  78.                     /* >0: list in cmlist */
  79.  
  80. static int  memstr,            /* Flag for input from memory string */
  81.     first;                /* Flag for first char from input */
  82. static CHAR t,                /* Current character */
  83.     next;                /* Next character */
  84.  
  85. /*  E N C S T R  --  Encode a string from memory. */
  86.  
  87. /*  Call this instead of getpkt() if source is a string, rather than a file. */
  88.  
  89. encstr(s) char* s; {
  90.     int m; char *p;
  91.  
  92.     m = memstr; p = memptr;        /* Save these. */
  93.  
  94.     memptr = s;                /* Point to the string. */
  95.     memstr = 1;                /* Flag memory string as source. */
  96.     first = 1;                /* Initialize character lookahead. */
  97.     getpkt(spsiz-bctu-3);        /* Fill a packet from the string. */
  98.     memstr = m;                /* Restore memory string flag */
  99.     memptr = p;                /* and pointer */
  100.     first = 1;                /* Put this back as we found it. */
  101. }
  102.  
  103. /* E N C O D E - Kermit packet encoding procedure */
  104.  
  105. encode(a) CHAR a; {            /* The current character */
  106.     int a7;                /* Low order 7 bits of character */
  107.     int b8;                /* 8th bit of character */
  108.  
  109.     if (rptflg)    {                   /* Repeat processing? */
  110.         if (a == next && (first == 0)) { /* Got a run... */
  111.         if (++rpt < 94)        /* Below max, just count */
  112.                 return;
  113.         else if (rpt == 94) {    /* Reached max, must dump */
  114.                 data[size++] = rptq;
  115.                 data[size++] = tochar(rpt);
  116.                 rpt = 0;
  117.         }
  118.         } else if (rpt == 1) {        /* Run broken, only 2? */
  119.             rpt = 0;            /* Yes, reset repeat flag & count. */
  120.         encode(a);            /* Do the character twice. */
  121.         if (size <= maxsize) osize = size;
  122.         rpt = 0;
  123.         encode(a);
  124.         return;
  125.     } else if (rpt > 1) {        /* More than two */
  126.             data[size++] = rptq;    /* Insert the repeat prefix */
  127.             data[size++] = tochar(++rpt); /* and count. */
  128.             rpt = 0;            /* Reset repeat counter. */
  129.         }
  130.     }
  131.     a7 = a & 0177;            /* Isolate ASCII part */
  132.     b8 = a & 0200;            /* and 8th (parity) bit. */
  133.  
  134.     if (ebqflg && b8) {            /* Do 8th bit prefix if necessary. */
  135.         data[size++] = ebq;
  136.         a = a7;
  137.     }
  138.     if ((a7 < SP) || (a7==DEL))    {    /* Do control prefix if necessary */
  139.         data[size++] = myctlq;
  140.     a = ctl(a);
  141.     }
  142.     if (a7 == myctlq)            /* Prefix the control prefix */
  143.         data[size++] = myctlq;
  144.  
  145.     if ((rptflg) && (a7 == rptq))    /* If it's the repeat prefix, */
  146.         data[size++] = myctlq;        /* quote it if doing repeat counts. */
  147.  
  148.     if ((ebqflg) && (a7 == ebq))    /* Prefix the 8th bit prefix */
  149.         data[size++] = myctlq;        /* if doing 8th-bit prefixes */
  150.  
  151.     data[size++] = a;            /* Finally, insert the character */
  152.     data[size] = '\0';            /* itself, and mark the end. */
  153. }
  154.  
  155. /* D E C O D E  --  Kermit packet decoding procedure */
  156.  
  157. /* Call with string to be decoded and an output function. */
  158. /* Returns 0 on success, -1 on failure (e.g. disk full).  */
  159.  
  160. decode(buf,fn) CHAR *buf; int (*fn)(); {
  161.     unsigned int a, a7, b8;        /* Low order 7 bits, and the 8th bit */
  162.  
  163.     rpt = 0;                /* Initialize repeat count. */
  164.  
  165.     while ((a = *buf++) != '\0') {
  166.     if (rptflg) {            /* Repeat processing? */
  167.         if (a == rptq) {        /* Yes, got a repeat prefix? */
  168.         rpt = xunchar(*buf++);    /* Yes, get the repeat count, */
  169.         a = *buf++;        /* and get the prefixed character. */
  170.         }
  171.     }
  172.     b8 = 0;                /* Check high order "8th" bit */
  173.     if (ebqflg) {            /* 8th-bit prefixing? */
  174.         if (a == ebq) {        /* Yes, got an 8th-bit prefix? */
  175.         b8 = 0200;        /* Yes, remember this, */
  176.         a = *buf++;        /* and get the prefixed character. */
  177.         }
  178.     }
  179.     if (a == ctlq) {        /* If control prefix, */
  180.         a  = *buf++;        /* get its operand. */
  181.         a7 = a & 0177;        /* Only look at low 7 bits. */
  182.         if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') /* Uncontrollify */
  183.         a = ctl(a);            /* if in control range. */
  184.     }
  185.     a |= b8;            /* OR in the 8th bit */
  186.     if (rpt == 0) rpt = 1;        /* If no repeats, then one */
  187. #ifdef NLCHAR
  188.     if (!binary) {            /* If in text mode, */
  189.         if (a == CR) continue;    /* discard carriage returns, */
  190.             if (a == LF) a = NLCHAR;     /* convert LF to system's newline. */
  191.         }
  192. #endif
  193.     for (; rpt > 0; rpt--) {    /* Output the char RPT times */
  194.         if ((*fn)(a) < 0) return(-1); /* Send it to the output function. */
  195.         ffc++, tfc++;        /* Count the character */
  196.     }
  197.     }
  198.     return(0);
  199. }
  200.  
  201.  
  202. /*  Output functions passed to 'decode':  */
  203.  
  204. putsrv(c) char c; {     /*  Put character in server command buffer  */
  205.     *srvptr++ = c;
  206.     *srvptr = '\0';    /* Make sure buffer is null-terminated */
  207.     return(0);
  208. }
  209.  
  210. puttrm(c) char c; {     /*  Output character to console.  */
  211.     conoc(c);
  212.     return(0);
  213. }
  214.  
  215. putfil(c) char c; {            /*  Output char to file. */
  216.     if (zchout(ZOFILE, c & fmask) < 0) {
  217.     czseen = 1;               /* If write error... */
  218.     if (deblog) debug(F101,"putfil zchout write error, setting czseen","",1);
  219.     return(-1);
  220.     }
  221.     return(0);
  222. }
  223.  
  224. /*  G E T P K T -- Fill a packet data field  */
  225.  
  226. /*
  227.  Gets characters from the current source -- file or memory string.
  228.  Encodes the data into the packet, filling the packet optimally.
  229.  Set first = 1 when calling for the first time on a given input stream
  230.  (string or file).
  231.  
  232.  Uses global variables:
  233.  t     -- current character.
  234.  first -- flag: 1 to start up, 0 for input in progress, -1 for EOF.
  235.  next  -- next character.
  236.  data  -- the packet data buffer.
  237.  size  -- number of characters in the data buffer.
  238.  
  239. Returns the size as value of the function, and also sets global size,
  240. and fills (and null-terminates) the global data array.  Returns 0 upon eof.
  241. */
  242.  
  243. getpkt(bufmax) int bufmax; {        /* Fill one packet buffer */
  244.   int i, x;                /* Loop index. */
  245.  
  246.   static char leftover[6] = { '\0', '\0', '\0', '\0', '\0', '\0' };
  247.  
  248.   if (deblog) debug(F111,"getpkt","bufmax",bufmax);
  249.  
  250.   if (first == 1) {        /* If first time thru...  */
  251.        first = 0;        /* remember, */
  252.        *leftover = '\0';       /* discard any interrupted leftovers, */
  253.        x = getchx(&t);        /* get first character of file into t, */
  254.        if (x == 0) {            /* watching out for null file, */
  255.          first = -1;
  256.          return(size = 0);
  257.        }
  258.   } else if ((first == -1) && (*leftover == '\0')) /* EOF from last time? */
  259.       return(size = 0);
  260.  
  261.   /* Do any leftovers */
  262.  
  263.   for (size = 0; (data[size] = leftover[size]) != '\0'; size++)
  264.        ;
  265.   *leftover = '\0';
  266.   if (first == -1) return(size);    /* Handle final leftovers leftovers */
  267.  
  268.     /* Now fill up the rest of the packet. */
  269.  
  270.     rpt = 0;                /* Clear out any old repeat count. */
  271.     while (first > -1) {        /* Until EOF... */
  272.          x = getchx(&next);        /* Get next character for lookahead. */
  273.          if (x == 0) first = -1;        /* Flag eof for next time. */
  274.          osize = size;            /* Remember current position. */
  275.       encode(t);            /* Encode the current character. */
  276.          t = next;            /* Next is now current. */
  277.  
  278.          if (size == bufmax) {         /* If the packet is exactly full, */
  279.         if (deblog) debug(F101,"getpkt exact fit","",size);
  280.         return(size);        /* ... return. */
  281.          }
  282.          if (size > bufmax) {        /* If too big, save some for next. */
  283.            for (i = 0; (leftover[i] = data[osize+i]) != '\0'; i++)
  284.                 ;
  285.            if (deblog) debug(F111,"getpkt leftover",leftover,size);
  286.            if (deblog) debug(F101," osize","",osize);
  287.            size = osize;        /* Return truncated packet. */
  288.            data[size] = '\0';
  289.            return(size);
  290.          }
  291.     }                       /* Otherwise, keep filling. */
  292.     if (deblog) debug(F111,"getpkt eof/eot",data,size);
  293.                            /* Fell thru before packet full, */
  294.     return(size);           /* return partially filled last packet. */
  295. }
  296.  
  297. /*  G E T C H X  --  Get the next character from file (or pipe). */
  298.  
  299. /*
  300.  On systems like NCR-VRX, the Macintosh, etc, that use a single character
  301.  (NLCHAR, defined in ckcdeb.h) to separate lines in text files, and
  302.  when in text/ascii mode (binary == 0), this function maps the newline
  303.  character to CRLF.  If NLCHAR is not defined, then this mapping is
  304.  not done, even in text mode.
  305.  
  306.  Returns 1 on success with ch set to the character, or 0 on failure (EOF)
  307. */
  308. getchx(ch) char *ch; {            /* Get next character */
  309.     int x; CHAR a;            /* The character to return. */
  310.     static int b = 0;            /* A character to remember. */
  311.  
  312.     if (b > 0) {            /* Do we have a LF saved? */
  313.     b = 0;                /* Yes, return that. */
  314.     *ch = LF;
  315.     return(1);
  316.     }
  317.  
  318.     if (memstr)                /* Try to get the next character */
  319.         x = ((a = *memptr++) == '\0');    /* from the appropriate source, */
  320.     else                /* memory or the current file. */
  321.         x = (zchin(ZIFILE,&a) == -1);
  322.  
  323.     if (x)
  324.         return(0);            /* No more, return 0 for EOF. */
  325.     else {                /* Otherwise, read the next char. */
  326.     ffc++, tfc++;            /* Count it. */
  327.     a &= fmask;            /* Bytesize mask. */
  328. #ifdef NLCHAR
  329.     if (!binary && (a == NLCHAR)) {    /* If nl and we must do nl-CRLF */
  330.         b = 1;            /* mapping, remember a linefeed, */
  331.         *ch = CR;            /* and return a carriage return. */
  332.         return(1);
  333.     } else {
  334.         *ch = a;            /*  General case, return the char. */
  335.         return(1);
  336.         }
  337. #else
  338.         *ch = a;
  339.         return(1);
  340. #endif
  341.     }
  342. }
  343.  
  344.  
  345. /*  C A N N E D  --  Check if current file transfer cancelled */
  346.  
  347. canned(buf) char *buf; {
  348.     if (*buf == 'X') cxseen = 1;
  349.     if (*buf == 'Z') czseen = 1;
  350.     if (deblog) debug(F101,"canned: cxseen","",cxseen);
  351.     if (deblog) debug(F101," czseen","",czseen);
  352.     return((czseen || cxseen) ? 1 : 0);
  353. }
  354.  
  355. /*  R E S E T C  --  Reset per-transaction character counters */
  356. resetc() {
  357.     tfc = tlci = tlco = 0;    /* Total file chars, line chars in & out */
  358. }
  359.  
  360.  
  361. /*  T I N I T  --  Initialize a transaction  */
  362.  
  363. tinit() {
  364.     xflg = 0;                /* Reset x-packet flag */
  365.     rqf = -1;                /* Reset 8th-bit-quote request flag */
  366.     memstr = 0;                /* Reset memory-string flag */
  367.     memptr = NULL;            /*  and pointer */
  368.     bctu = 1;                /* Reset block check type to 1 */
  369.     ebq = ebqflg = 0;            /* Reset 8th-bit quoting stuff */
  370.     if (savmod) {            /* If binary file mode was saved, */
  371.         binary = 1;            /*  restore it, */
  372.     savmod = 0;            /*  unsave it. */
  373.     }
  374.     prvpkt = -1;            /* Reset packet number */
  375.     pktnum = 0;
  376.     cxseen = czseen = 0;        /* Reset interrupt flags */
  377.     *filnam = '\0';            /* Clear file name */
  378.     *sndpkt = '\0';            /* Clear retransmission buffer */
  379.     if (server)             /* If acting as server, */
  380.     timint = 30;            /* Use 30 second timeout, */
  381. }
  382.  
  383.  
  384. /*  R I N I T  --  Respond to S packet  */
  385.  
  386. rinit(d) char *d; {
  387.     char *tp;
  388.     ztime(&tp);
  389.     tlog(F110,"Transaction begins",tp,0l); /* Make transaction log entry */
  390.     filcnt = 0;                /* Init file counter */
  391.     spar(d);
  392.     ack1(rpar());
  393. }
  394.  
  395. /*  S I N I T  --  Make sure file exists, then send Send-Init packet */
  396.  
  397. sinit() {
  398.     int x; char *tp;
  399.     int type;
  400.     filcnt = 0;
  401.     sndsrc = nfils;            /* Where to look for files to send */
  402.     ztime(&tp);
  403.     tlog(F110,"Transaction begins",tp,0l); /* Make transaction log entry */
  404.     if (deblog) debug(F101,"sinit: sndsrc","",sndsrc);
  405.     if (sndsrc < 0) {            /* Must expand from 'send' command */
  406.     nfils = zxpand(cmarg);        /* Look up literal name. */
  407.     if (nfils < 0) {
  408.         screen(SCR_EM,0,0l,"Too many files");
  409.         return(0);
  410.         } else if (nfils == 0) {    /* If none found, */
  411.         char xname[100];        /* convert the name. */
  412.         zrtol(cmarg,xname, &type);
  413.         nfils = zxpand(xname);     /* Look it up again. */
  414.     }
  415.     if (nfils < 1) {        /* If no match, report error. */
  416.         if (server)
  417.             errpkt("File not found");
  418.         else
  419.         screen(SCR_EM,0,0l,"File not found");
  420.         return(0);
  421.     }
  422.     x = gnfile();            /* Position to first file. */
  423.     if (x < 1) {
  424.         if (!server)
  425.             screen(SCR_EM,0,0l,"No readable file to send");
  426.             else
  427.             errpkt("No readable file to send");
  428.         return(0);
  429.         }
  430.     } else if (sndsrc > 0) {        /* Command line arglist -- */
  431.     x = gnfile();            /* Get the first file from it. */
  432.     if (x < 1) return(0);        /* (if any) */
  433.     } else if (sndsrc == 0) {        /* stdin or memory always exist... */
  434.     if ((cmarg2 != NULL) && (*cmarg2)) {
  435.         strcpy(filnam,cmarg2);    /* If F packet, "as" name is used */
  436.         cmarg2 = "";        /* if provided, */
  437.         } else                /* otherwise */
  438.         strcpy(filnam,"stdin");    /* just use this. */
  439.     }
  440.     if (deblog) debug(F101,"sinit: nfils","",nfils);
  441.     if (deblog) debug(F110," filnam",filnam,0);
  442.     if (deblog) debug(F110," cmdstr",cmdstr,0);
  443.     ttflui();                /* Flush input buffer. */
  444.     if (!local && !server) sleep(delay);
  445.     sipkt('S');                /* Send the Send-Init packet. */
  446.     return(1);
  447. }
  448.  
  449. sipkt(c) char c; {            /* Send S or I packet. */
  450.     CHAR *rp;
  451.     ttflui();                /* Flush pending input. */
  452.     rp = rpar();            /* Get parameters. */
  453.     spack(c,pktnum,strlen(rp),rp);
  454. }
  455.  
  456. /*  R C V F I L -- Receive a file  */
  457.  
  458. rcvfil() {
  459.     int x;
  460.     ffc = flci = flco = 0;        /* Init per-file counters */
  461.     srvptr = srvcmd;            /* Decode file name from packet. */
  462.     decode(rdatap,putsrv);
  463.     if (*srvcmd == '\0')        /* Watch out for null F packet. */
  464.         strcpy(srvcmd,"NONAME");
  465.     screen(SCR_FN,0,0l,srvcmd);        /* Put it on screen */
  466.     tlog(F110,"Receiving",srvcmd,0l);    /* Transaction log entry */
  467.     if (cmarg2 != NULL) {               /* Check for alternate name */
  468.         if (*cmarg2 != '\0') {
  469.             strcpy(srvcmd,cmarg2);    /* Got one, use it. */
  470.         *cmarg2 = '\0';
  471.         }
  472.     }
  473.     x = openo(srvcmd,filnam);        /* Try to open it */
  474.     if (x) {
  475.     tlog(F110," as",filnam,0l);
  476.     screen(SCR_AN,0,0l,filnam);
  477.     intmsg(++filcnt);
  478.     } else {
  479.         tlog(F110,"Failure to open",filnam,0l);
  480.     screen(SCR_EM,0,0l,"Can't open file");
  481.     }
  482.     return(x);                /* Pass on return code from openo */
  483. }
  484.  
  485. /*  R E O F  --  Receive End Of File  */
  486.  
  487. reof() {
  488.     int x;
  489.     if (cxseen == 0) cxseen = (*rdatap == 'D');    /* Got discard directive? */
  490.     x = clsof(cxseen | czseen);
  491.     if (cxseen || czseen) {
  492.     tlog(F100," *** Discarding","",0l);
  493.     cxseen = 0;
  494.     } else
  495.     fstats();
  496.     return(x);
  497. }
  498.  
  499.  
  500. /*  R E O T  --  Receive End Of Transaction  */
  501.  
  502. reot() {
  503.     cxseen = czseen = 0;        /* Reset interruption flags */
  504.     tstats();
  505. }
  506.  
  507. /*  S F I L E -- Send File header or teXt header packet  */
  508.  
  509. /*  Call with x nonzero for X packet, zero for F packet  */
  510. /*  Returns 1 on success, 0 on failure                   */
  511.  
  512. sfile(x) int x; {
  513.     char pktnam[100];            /* Local copy of name */
  514.     char *s;
  515.  
  516.     if (x == 0) {            /* F-Packet setup */
  517.  
  518.         if (*cmarg2 != '\0') {        /* If we have a send-as name, */
  519.         strcpy(pktnam,cmarg2);    /* copy it literally, */
  520.         cmarg2 = "";        /* and blank it out for next time. */
  521.         } else {            /* Otherwise use actual file name: */
  522.         if (fncnv) {        /* If converting names, */
  523.             zltor(filnam,pktnam);    /* convert it to common form, */
  524.         } else {            /* otherwise, */
  525.             strcpy(pktnam,filnam);    /* copy it literally. */
  526.             }
  527.         }
  528.         if (deblog) debug(F110,"sfile",filnam,0);    /* Log debugging info */
  529.         if (deblog) debug(F110," pktnam",pktnam,0);
  530.         if (openi(filnam) == 0)     /* Try to open the file */
  531.         return(0);
  532.         s = pktnam;            /* Name for packet data field */
  533.  
  534.     } else {                /* X-packet setup */
  535.  
  536.         if (deblog) debug(F110,"sxpack",cmdstr,0);    /* Log debugging info */
  537.         s = cmdstr;            /* Name for data field */
  538.     }
  539.  
  540.     flci = flco = ffc = 0;        /* Init counters, etc. */
  541.     encstr(s);                /* Encode the name into data[]. */
  542.     nxtpkt(&pktnum);            /* Increment the packet number */
  543.     spack(x ? 'X' : 'F', pktnum, size, data); /* Send the F or X packet */
  544.  
  545.     if (x == 0) {            /* Display for F packet */
  546.         if (displa) {            /* Screen */
  547.         screen(SCR_FN,'F',(long)pktnum,filnam);
  548.         screen(SCR_AN,0,0l,pktnam);
  549.         screen(SCR_FS,0,(long)fsize,"");
  550.         }
  551.         tlog(F110,"Sending",filnam,0l);    /* Transaction log entry */
  552.         tlog(F110," as",pktnam,0l);
  553.  
  554.     } else {                /* Display for X-packet */
  555.  
  556.         screen(SCR_XD,'X',(long)pktnum,cmdstr);    /* Screen */
  557.         tlog(F110,"Sending from:",cmdstr,0l);    /* Transaction log */
  558.     }
  559.     intmsg(++filcnt);            /* Count file, give interrupt msg */
  560.     first = 1;                /* Init file character lookahead. */
  561.     return(1);
  562. }
  563.  
  564. /*  S D A T A -- Send a data packet */
  565.  
  566. /*  Return -1 if no data to send, else send packet and return length  */
  567.  
  568. sdata() {
  569.     int len;
  570.     if (deblog) debug(F111,"sdata","spsiz",spsiz);
  571.     if (cxseen || czseen) return(-1);    /* If interrupted, done. */
  572.     if ((len = getpkt(spsiz-bctu-3)) == 0) /* Done if no data. */
  573.         return(-1);
  574.     nxtpkt(&pktnum);            /* Increment the packet number */
  575.     spack('D',pktnum,len,data);        /* Send the packet */
  576.     return(len);
  577. }
  578.  
  579.  
  580. /*  S E O F -- Send an End-Of-File packet */
  581.  
  582. /*  Call with a string pointer to character to put in the data field, */
  583. /*  or else a null pointer or "" for no data.  */
  584.  
  585. seof(s) char *s; {
  586.     nxtpkt(&pktnum);            /* Increment the packet number */
  587.     if ((s != NULL) && (*s != '\0')) {
  588.     spack('Z',pktnum,1,s);
  589.     tlog(F100," *** interrupted, sending discard request","",0l);
  590.     } else {
  591.     spack('Z',pktnum,0,"");
  592.     fstats();
  593.     }
  594. }
  595.  
  596.  
  597. /*  S E O T -- Send an End-Of-Transaction packet */
  598.  
  599. seot() {
  600.     nxtpkt(&pktnum);            /* Increment the packet number */
  601.     spack('B',pktnum,0,"");        /* Send the EOT packet */
  602.     cxseen = czseen = 0;        /* Reset interruption flags */
  603.     tstats();                /* Log timing info */
  604. }
  605.  
  606. /*   R P A R -- Fill the data array with my send-init parameters  */
  607.  
  608. CHAR *
  609. rpar() {
  610.     if (rpsiz > MAXPACK)        /* Biggest normal packet I want. */
  611.       data[1] = tochar(MAXPACK);    /* If > 94, use 94, but specify */
  612.     else                /* extended packet length below... */
  613.       data[1] = tochar(rpsiz);        /* else use what the user said. */
  614.     data[2] = tochar(rtimo);        /* When I want to be timed out */
  615.     data[3] = tochar(mypadn);        /* How much padding I need (none) */
  616.     data[4] = ctl(mypadc);        /* Padding character I want */
  617.  
  618.     if (eol == LF)
  619.            data [5] = tochar (CR);      /* for vrx ivs use only */
  620.        else
  621.            data[5] = tochar(eol);        /* End-Of-Line character I want */
  622.  
  623.     data[6] = '#';            /* Control-Quote character I send */
  624.     switch (rqf) {            /* 8th-bit prefix */
  625.     case -1:
  626.     case  1: if (parity) ebq = sq = '&'; break;
  627.     case  0:
  628.     case  2: break;
  629.     }
  630.     data[7] = sq;
  631.     data[8] = bctr + '0';        /* Block check type */
  632.     if (rptflg)                /* Run length encoding */
  633.         data[9] = rptq;            /* If receiving, agree. */
  634.     else
  635.         data[9] = '~';
  636.  
  637.     data[10] = tochar((atcapr?atcapb:0)|(lpcapr?lpcapb:0)|(swcapr?swcapb:0));
  638.     data[capas+1] = tochar(swcapr ? wsize : 0);    /* Window size */
  639.  
  640.     rpsiz = urpsiz;            /* Long packets ... */
  641.     data[capas+2] = tochar(rpsiz / 95);    /* Long packet size, big part */
  642.     data[capas+3] = tochar(rpsiz % 95);    /* Long packet size, little part */
  643.     data[capas+4] = '\0';        /* Terminate the init string */
  644.     if (deblog) {
  645.     if (deblog) debug(F110,"rpar",data+1,0);
  646.     rdebu(capas+2);
  647.     }
  648.     return(data+1);            /* Return pointer to string. */
  649. }
  650.  
  651. /* S P A R --Get the other system's Send-Init parameters */
  652.  
  653.  
  654. spar(s) char *s; {            /* Set parameters */
  655.     int x, lpsiz;
  656.  
  657.     s--;                /* Line up with field numbers. */
  658.  
  659. if (deblog) debug(F101,"spar rln","",rln);
  660.  
  661. /* Limit on size of outbound packets */
  662.     x = (rln >= 1) ? xunchar(s[1]) : 80;
  663.     lpsiz = spsiz;            /* Remember what they SET. */
  664.     if (spsizf) {            /* SET-command override? */
  665.     if (x < spsiz) spsiz = x;    /* Ignore LEN unless smaller */
  666.     } else {                /* otherwise */
  667.     spsiz = (x < 10) ? 80 : x;    /* believe them if reasonable */
  668.     }
  669.  
  670. /* Timeout on inbound packets */
  671.     if (!timef) {            /* Only if not SET-cmd override */
  672.     x = (rln >= 2) ? xunchar(s[2]) : 5;
  673.     timint = (x < 0) ? 5 : x;
  674.     }
  675.  
  676. /* Outbound Padding */
  677.     npad = 0; padch = SNDPADC;
  678.     if (rln >= 3) {
  679.     npad = xunchar(s[3]);
  680.     if (rln >= 4) padch = ctl(s[4]); else padch = SNDPADC;
  681.     }
  682.  
  683. /* Outbound Packet Terminator */
  684.     seol = (rln >= 5) ? xunchar(s[5]) : '\r';
  685.     if ((seol < 2) || (seol > 31)) seol = '\r';
  686.     if (seol == '\r') seol = '\n';  /* VRX IVS ONLY */
  687.  
  688. /* Control prefix */
  689.     x = (rln >= 6) ? s[6] : '#';
  690.     myctlq = ((x > 32 && x < 63) || (x > 95 && x < 127)) ? x : '#';
  691.  
  692. /* 8th-bit prefix */
  693.     rq = (rln >= 7) ? s[7] : 0;
  694.     if (rq == 'Y') rqf = 1;
  695.       else if ((rq > 32 && rq < 63) || (rq > 95 && rq < 127)) rqf = 2;
  696.         else rqf = 0;
  697.     switch (rqf) {
  698.     case 0: ebqflg = 0; break;
  699.     case 1: if (parity) { ebqflg = 1; ebq = '&'; } break;
  700.     case 2: if (ebqflg = (ebq == sq || sq == 'Y')) ebq = rq;
  701.     }
  702.  
  703. /* Block check */
  704.     x = 1;
  705.     if (rln >= 8) {
  706.     x = s[8] - '0';
  707.     if ((x < 1) || (x > 3)) x = 1;
  708.     }
  709.     bctr = x;
  710.  
  711. /* Repeat prefix */
  712.     if (rln >= 9) {
  713.     rptq = s[9];
  714.     rptflg = ((rptq > 32 && rptq < 63) || (rptq > 95 && rptq < 127));
  715.     } else rptflg = 0;
  716.  
  717. /* Capabilities */
  718.     atcapu = lpcapu = swcapu = 0;
  719.     if (rln >= 10) {
  720.         x = xunchar(s[10]);
  721.         atcapu = (x & atcapb) && atcapr;
  722.     lpcapu = (x & lpcapb) && lpcapr;
  723.     swcapu = (x & swcapb) && swcapb;
  724.     for (capas = 10; (xunchar(s[capas]) & 1) && (rln >= capas); capas++) ;
  725.     }
  726.  
  727. /* Long Packets */
  728.     if (lpcapu) {
  729.         if (rln > capas+2) {
  730.         x = xunchar(s[capas+2]) * 95 + xunchar(s[capas+3]);
  731.         if (spsizf) {        /* If overriding negotiations */
  732.         spsiz = (x < lpsiz) ? x : lpsiz; /* do this, */
  733.         } else {                     /* otherwise */
  734.         spsiz = (x > MAXSP) ? MAXSP : x; /* do this. */
  735.         }
  736.         if (spsiz < 10) spsiz = 80;    /* Be defensive... */
  737.     }
  738.     }
  739.  
  740. /* Sliding Windows */
  741.     if (swcapu) {
  742.         if (rln > capas+1) {
  743.         x = xunchar(s[capas+1]);
  744.         wsize = x > MAXWS ? MAXWS : x;
  745.     }
  746.     else wsize = 1;
  747.     }
  748.     if (deblog) sdebu(rln);        /* Record parameters in debug log */
  749. }
  750.  
  751. /*  G N F I L E  --  Get the next file name from a file group.  */
  752.  
  753. /*  Returns 1 if there's a next file, 0 otherwise  */
  754.  
  755. gnfile() {
  756.     int x; long y;
  757.  
  758. /* If file group interruption (C-Z) occured, fail.  */
  759.  
  760.     if (deblog) debug(F101,"gnfile: czseen","",czseen);
  761.  
  762.     if (czseen) {
  763.     tlog(F100,"Transaction cancelled","",0l);
  764.     return(0);
  765.     }
  766.  
  767. /* If input was stdin or memory string, there is no next file.  */
  768.  
  769.     if (sndsrc == 0) return(0);
  770.  
  771. /* If file list comes from command line args, get the next list element. *
  772.  *
  773.  *  y = -1;
  774.  *  while (y < 0) {                     * Keep trying till we get one... *
  775.  *
  776.  *  if (sndsrc > 0) {
  777.  *   if (nfils-- > 0) {
  778.  *
  779.  *      strcpy(filnam,*cmlist++);
  780.  *        if (deblog) debug(F111,"gnfile: cmlist filnam",filnam,nfils);
  781.  *
  782.  *        } else {
  783.  *        *filnam = '\0';
  784.  *         if (deblog) debug(F101,"gnfile cmlist: nfils","",nfils);
  785.  *        return(0);
  786.  *        }
  787.  *    }
  788. */
  789.  
  790. /* Otherwise, step to next element of internal wildcard expansion list. */
  791.  
  792. /*    if (sndsrc < 0) {
  793.  *        x = znext(filnam);
  794.  *        if (deblog) debug(F111,"gnfile znext: filnam",filnam,x);
  795.  *        if (x == 0) return(0);
  796.  *    }
  797. */
  798.  
  799. /* Get here with a filename. */
  800.  
  801. /*
  802.  *      y = zchki(filnam);              * Check if file readable *
  803.  *    if (y < 0) {
  804.  *        if (deblog) debug(F110,"gnfile skipping:",filnam,0);
  805.  *        tlog(F111,filnam,"not sent, reason",(long)y);
  806.  *        screen(SCR_ST,ST_SKIP,0l,filnam);
  807.  *    } else fsize = y;
  808.  *   }
  809.  */
  810.  
  811.  /* **********************************************************
  812.  
  813.            the two lines added above the return statement
  814.            were not ported correctly during the 4E code
  815.            port to VRX. I confess I did it with diff
  816.            output. If maybe appropriate to mention, when
  817.            using diff (unix) care must be exercised to
  818.            prevent missed code lines as these.
  819.  
  820.     PEG 01/26/90
  821.  
  822.     ********************************************************** */
  823.  
  824.  
  825.  
  826.       y = -1;            /* this line probably useless but MCDAID
  827.                             ported it, so why change              */
  828.  
  829.       x = znext(filnam);
  830.       return(x);
  831.  
  832. }
  833.  
  834. /*  O P E N I  --  Open an existing file for input  */
  835.  
  836. openi(name) char *name; {
  837.     int x, filno;
  838.     int type;
  839.     char xname [100];
  840.  
  841.     if (memstr) return(1);        /* Just return if file is memory. */
  842.  
  843.     if (deblog) debug(F110,"openi",name,0);
  844.     if (deblog) debug(F101," sndsrc","",sndsrc);
  845.  
  846.     filno = (sndsrc == 0) ? ZSTDIO : ZIFILE;    /* ... */
  847.  
  848.     if (deblog) debug(F101," file number","",filno);
  849.  
  850.     zrtol(name,xname,&type);        /* to local form and then */
  851.     x = zopeni(filno,xname,type);    /* try opening it again. */
  852.     if (deblog) debug(F101," zopeni","",x);
  853.     if (x) {
  854.         if (deblog) debug(F110," ok",xname,0);
  855.         return(1);            /* It worked. */
  856.         } else {
  857.         screen(SCR_EM,0,0l,"Can't open file");  /* It didn't work. */
  858.         tlog(F110,xname,"could not be opened",0l);
  859.         if (deblog) debug(F110," openi failed",xname,0);
  860.         return(0);
  861.         }
  862. }
  863.  
  864. /*  O P E N O  --  Open a new file for output.  */
  865.  
  866. /*  Returns actual name under which the file was opened in string 'name2'. */
  867.  
  868. openo(name,name2)
  869.     char *name, *name2;
  870.     {
  871.     char xname[100], *xp;
  872.     int  type;
  873.  
  874.     if (stdouf)                /* Receiving to stdout? */
  875.     return(zopeno(ZSTDIO,"",0));
  876.  
  877.     if (deblog) debug(F110,"openo: name",name,0);
  878.  
  879.     if (cxseen || czseen) {        /* If interrupted, get out before */
  880.     if (deblog) debug(F100," open cancelled","",0);
  881.                                 /* destroying existing file. */
  882.     return(1);            /* Pretend to succeed. */
  883.     }
  884.     xp = xname;                /* OK to proceed. */
  885.     zrtol (name,xp,&type);               /* convert name to local form */
  886.     if (deblog) debug(F110,"openo: xname",xname,0);
  887.  
  888. /*  if (warn) {                 * File collision avoidance? *
  889.  *  if (zchki(xname) != -1) {     * Yes, file exists? *
  890.  *        znewn(xname,&xp);         * Yes, make new name. *
  891.  *        strcpy(xname,xp);
  892.  *        if (deblog) debug(F110," exists, new name ",xname,0);
  893.  *       }
  894.  *   }
  895.  */
  896.  
  897.     if (zopeno(ZOFILE,xname,type) == 0) {    /* Try to open the file */
  898.     if (deblog) debug(F110,"openo failed",xname,0);
  899.     tlog(F110,"Failure to open",xname,0l);
  900.     return(0);
  901.     } else {
  902.     strcpy(name2,xname);
  903.     if (deblog) debug(F110,"openo ok, name2",name2,0);
  904.     return(1);
  905.     }
  906. }
  907.  
  908. /*  O P E N T  --  Open the terminal for output, in place of a file  */
  909.  
  910. opent() {
  911.     ffc = tfc = 0;
  912.     return(zopeno(ZCTERM,"",0));
  913. }
  914.  
  915. /*  C L S I F  --  Close the current input file. */
  916.  
  917. clsif() {
  918.     if (memstr) {            /* If input was memory string, */
  919.     memstr = 0;            /* indicate no more. */
  920.     } else zclose(ZIFILE);        /* else close input file. */
  921.  
  922.     if (czseen || cxseen)
  923.         screen(SCR_ST,ST_DISC,0l,"");
  924.     else
  925.         screen(SCR_ST,ST_OK,0l,"");
  926.     cxseen = hcflg = 0;            /* Reset flags, */
  927.     *filnam = '\0';            /* and current file name */
  928. }
  929.  
  930.  
  931. /*  C L S O F  --  Close an output file.  */
  932.  
  933. /*  Call with disp != 0 if file is to be discarded.  */
  934. /*  Returns -1 upon failure to close, 0 or greater on success. */
  935.  
  936. clsof(disp) int disp; {
  937.     int x;
  938.     if ((x = zclose(ZOFILE)) < 0) {    /* Try to close the file */
  939.     tlog(F100,"Failure to close",filnam,0l);
  940.     screen(SCR_ST,ST_ERR,0l,"");
  941.     } else if (disp && (keep == 0)) {    /* Delete it if interrupted, */
  942.     if (*filnam) zdelet(filnam);    /* and not keeping incomplete files */
  943.     if (deblog) debug(F100,"Discarded","",0);
  944.     tlog(F100,"Discarded","",0l);
  945.     screen(SCR_ST,ST_DISC,0l,"");
  946.     } else {                /* Nothing wrong, just keep it */
  947.     if (deblog) debug(F100,"Closed","",0);    /* and give comforting messages. */
  948.     screen(SCR_ST,ST_OK,0l,"");
  949.     }
  950.     *filnam = '\0';            /* Zero the current file name. */
  951.     return(x);                /* Send back zclose() return code. */
  952. }
  953.  
  954. /*  S N D H L P  --  Routine to send builtin help  */
  955.  
  956. sndhlp() {
  957.     nfils = 0;                /* No files, no lists. */
  958.     xflg = 1;                /* Flag we must send X packet. */
  959.     strcpy(cmdstr,"help text");        /* Data for X packet. */
  960.     first = 1;                /* Init getchx lookahead */
  961.     memstr = 1;                /* Just set the flag. */
  962.     memptr = hlptxt;            /* And the pointer. */
  963.     if (binary) {            /* If file mode is binary, */
  964.     binary = 0;            /*  turn it back to text for this, */
  965.     savmod = 1;            /*  remember to restore it later. */
  966.     }
  967.     return(sinit());
  968. }
  969.  
  970.  
  971. /*  C W D  --  Change current working directory  */
  972.  
  973. /*
  974.  String passed has first byte as length of directory name, rest of string
  975.  is name.  Fails if can't connect, else ACKs (with name) and succeeds.
  976. */
  977.  
  978. cwd(vdir) char *vdir; {
  979.     char *cdd, *zgtdir();
  980.     vdir[xunchar(*vdir) + 1] = '\0';    /* End with a null */
  981.     if (zchdir(vdir+1)) {
  982.     cdd = zgtdir();            /* Get new working directory. */
  983.     encstr(cdd);
  984.     ack1(data);
  985.     tlog(F110,"Changed directory to",cdd,0l);
  986.     return(1);
  987.     } else {
  988.     tlog(F110,"Failed to change directory to",vdir+1,0l);
  989.     return(0);
  990.     }
  991. }
  992.  
  993.  
  994. /*  S Y S C M D  --  Do a system command  */
  995.  
  996. /*  Command string is formed by concatenating the two arguments.  */
  997.  
  998. syscmd(prefix,suffix) char *prefix, *suffix; {
  999.     char *cp;
  1000.  
  1001.     if (prefix == NULL || *prefix == '\0') return(0);
  1002.  
  1003.     for (cp = cmdstr; *prefix != '\0'; *cp++ = *prefix++) ;
  1004.     while (*cp++ = *suffix++) ;
  1005.  
  1006.     if (deblog) debug(F110,"syscmd",cmdstr,0);
  1007.     if (zopeni(ZSYSFN,cmdstr,0) > 0) {
  1008.     if (deblog) debug(F100,"syscmd zopeni ok",cmdstr,0);
  1009.     nfils = sndsrc = 0;        /* Flag that input from stdin */
  1010.     xflg = hcflg = 1;        /* And special flags for pipe */
  1011.     if (binary) {            /* If file mode is binary, */
  1012.         binary = 0;            /*  turn it back to text for this, */
  1013.         savmod = 1;            /*  remember to restore it later. */
  1014.     }
  1015.     return (sinit());        /* Send S packet */
  1016.     } else {
  1017.     if (deblog) debug(F100,"syscmd zopeni failed",cmdstr,0);
  1018.     return(0);
  1019.     }
  1020. }
  1021.