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

Defined functions

canned defined in line 318; never used
clsif defined in line 845; never used
clsof defined in line 864; used 1 times
cwd defined in line 906; never used
decode defined in line 134; used 1 times
encode defined in line 79; used 3 times
encstr defined in line 63; used 5 times
fstats defined in line 571; used 2 times
getchx defined in line 280; used 2 times
getpkt defined in line 217; used 2 times
gnfile defined in line 709; used 2 times
openi defined in line 763; used 1 times
openo defined in line 798; used 1 times
opent defined in line 838; never used
putfil defined in line 189; never used
putsrv defined in line 178; used 1 times
puttrm defined in line 184; never used
rcvfil defined in line 424; never used
reof defined in line 453; never used
reot defined in line 466; never used
rinit defined in line 353; never used
rpar defined in line 614; used 2 times
sdata defined in line 532; never used
sdebu defined in line 690; used 1 times
seof defined in line 548; never used
seot defined in line 562; never used
sfile defined in line 476; never used
sinit defined in line 365; used 2 times
sipkt defined in line 415; used 1 times
sndhlp defined in line 884; never used
spar defined in line 637; used 1 times
syscmd defined in line 924; never used
tinit defined in line 328; never used
tstats defined in line 581; used 2 times

Defined variables

cmdstr defined in line 47; used 11 times
first defined in line 55; used 11 times
fnsv defined in line 1; used 1 times
memptr defined in line 45; used 6 times
memstr defined in line 54; used 9 times
next defined in line 57; used 3 times
sndsrc defined in line 49; used 11 times
t defined in line 56; used 3 times

Defined macros

NULL defined in line 24; used 6 times
Last modified: 1985-08-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2727
Valid CSS Valid XHTML 1.0 Strict