Annotation of 43BSD/contrib/kermit/ckcfns.c, revision 1.1.1.1

1.1       root        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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.