Annotation of researchv10dc/lbin/kermit/ckcfns.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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