Annotation of 43BSDReno/contrib/kermit/ckcfns.c, revision 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.