Annotation of coherent/e/bin/cku179/ckcfn3.c, revision 1.1.1.1

1.1       root        1: /*  C K C F N 3  --  Packet buffer management for C-Kermit  */
                      2: 
                      3: /* See copyright notice at top of ckcfns.c. */
                      4: 
                      5: /* (plus assorted functions tacked on at the end) */
                      6: 
                      7: #include "ckcdeb.h"
                      8: #include "ckcasc.h"
                      9: #include "ckcker.h"
                     10: #include "ckcxla.h"
                     11: 
                     12: extern int unkcs, wmax, discard, bctu, local;
                     13: extern CHAR *data;
                     14: extern char filnam[];
                     15: #ifndef NOFRILLS
                     16: extern int rprintf, rmailf;            /* REMOTE MAIL, PRINT */
                     17: extern char optbuf[];                  /* Options buffer for mail, print */
                     18: #endif /* NOFRILLS */
                     19: extern int wslots;
                     20: extern int fblksiz, frecl, forg, frecfm, fncact, fcctrl, lf_opts;
                     21: #ifdef DYNAMIC
                     22:   extern CHAR *srvcmd;
                     23: #else
                     24:   extern CHAR srvcmd[];
                     25: #endif
                     26: 
                     27: extern int binary, spsiz;
                     28: extern int pktnum, cxseen, czseen, bsave, bsavef, nfils, stdinf;
                     29: extern int memstr, stdouf, keep, sndsrc, hcflg;
                     30: extern int server, en_cwd;
                     31: 
                     32: extern int
                     33:   atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
                     34:   attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso; 
                     35: 
                     36: extern long fsize, filcnt, ffc, tfc;
                     37: 
                     38: #ifndef NOCSETS
                     39: extern int tcharset, fcharset;
                     40: extern int ntcsets;
                     41: extern struct csinfo tcsinfo[], fcsinfo[];
                     42: 
                     43: /* Pointers to translation functions */
                     44: extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])();        
                     45: extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])();        
                     46: extern CHAR (*rx)();   /* Pointer to input character translation function */
                     47: extern CHAR (*sx)();    /* Pointer to output character translation function */
                     48: #endif /* NOCSETS */
                     49: 
                     50: /* Variables global to Kermit that are defined in this module */
                     51: 
                     52: int winlo;                             /* packet number at low window edge  */
                     53: 
                     54: int sbufnum;                           /* number of free buffers */
                     55: int dum001 = 1234;                     /* protection... */
                     56: int sbufuse[MAXWS];                    /* buffer in-use flag */
                     57: int dum003 = 1111;
                     58: int rbufnum;                           /* number of free buffers */
                     59: int dum002 = 4321;                     /* more protection */
                     60: int rbufuse[MAXWS];                    /* buffer in-use flag */
                     61: int sseqtbl[64];                       /* sequence # to buffer # table */
                     62: int rseqtbl[64];                       /* sequence # to buffer # table */
                     63: int sacktbl[64];                       /* sequence # ack table */
                     64: 
                     65: #ifdef DYNAMIC
                     66: struct pktinfo *s_pkt = NULL;          /* array of pktinfo structures */
                     67: struct pktinfo *r_pkt = NULL;          /* array of pktinfo structures */
                     68: #else
                     69: struct pktinfo s_pkt[MAXWS];           /* array of pktinfo structures */
                     70: struct pktinfo r_pkt[MAXWS];           /* array of pktinfo structures */
                     71: #endif /* DYNAMIC */
                     72: 
                     73: char xbuf[200];                                /* For debug logging */
                     74: 
                     75: #ifdef DYNAMIC
                     76: CHAR *bigsbuf = NULL, *bigrbuf = NULL;
                     77: #else
                     78: char bigsbt[8];                                /* Protection (shouldn't need this). */
                     79:                                        /* BUT DON'T REMOVE IT! */
                     80: CHAR bigsbuf[SBSIZ + 5];               /* Send-packet buffer area */
                     81: char bigrbt[8];                                /* Safety padding */
                     82: CHAR bigrbuf[RBSIZ + 5];               /* Receive-packet area */
                     83: #endif
                     84: int bigsbsiz = SBSIZ;                  /* Sizes of big send & rcv buffers. */
                     85: int bigrbsiz = RBSIZ;
                     86: 
                     87: /* FUNCTIONS */
                     88: 
                     89: /* For sanity, use "i" for buffer slots, "n" for packet numbers. */
                     90: 
                     91: /* I N I B U F S */
                     92: 
                     93: /*
                     94:   Allocates the big send and receive buffers.
                     95:   Call with size for big send buffer (s) and receive buffer (r).
                     96:   These sizes can be different.
                     97:   Attempts to allocate buffers of the requested size, but if it can't,
                     98:   it will allocate smaller ones.
                     99:   Sets global variables bigsbsiz and bigrbsiz to the actual sizes,
                    100:   and bigsbuf and bigrbuf pointing to the actual buffers.
                    101:   Designed to be called more than once.
                    102:   Returns 0 on success, -1 on failure.
                    103: */
                    104: 
                    105: CHAR *bigbufp = NULL;
                    106: 
                    107: int
                    108: inibufs(s,r) int s, r; {
                    109: #ifdef DYNAMIC
                    110:     int size, x;
                    111:     long z;
                    112: 
                    113:     if (s < 80 || r < 80) return(-1);  /* Validate arguments. */
                    114: 
                    115:     if (!s_pkt) {                      /* Allocate packet info structures */
                    116:        if (!(s_pkt = (struct pktinfo *) malloc(sizeof(struct pktinfo)*MAXWS)))
                    117:          fatal("ini_pkts: no memory for s_pkt");
                    118:     }
                    119:     if (!r_pkt) {
                    120:        if (!(r_pkt = (struct pktinfo *) malloc(sizeof(struct pktinfo)*MAXWS)))
                    121:          fatal("ini_pkts: no memory for s_pkt");
                    122:     }
                    123:     if (!srvcmd) {                     /* Allocate srvcmd buffer */
                    124:        srvcmd = (CHAR *) malloc(r + 100);
                    125:        if (!srvcmd) return(-1);
                    126:     }
                    127:     if (bigbufp) {                     /* Free previous buffers, if any. */
                    128:        free(bigbufp);
                    129:        bigbufp = NULL;
                    130:     }
                    131:     size = s + r + 40;                 /* Combined requested size + padding */
                    132: 
                    133:     /* Try to get the space.  If malloc fails, try to get a little less. */
                    134:     /* (Obviously, this algorithm can be refined.) */
                    135: 
                    136:     while (!(bigbufp = (CHAR *) malloc(size))) {
                    137:        size = (size * 3) / 2;          /* Failed, cut size by 1/3. */
                    138:        if (size < 200)                 /* Try again until too small. */
                    139:          return(-1);
                    140:     }
                    141:     debug(F101,"inibufs size","",size);        /* OK, we got some space. */
                    142: 
                    143: /*
                    144:   Now divide the allocated space between the send and receive buffers in the
                    145:   requested proportion.  The natural formula would be (s / (s + r)) * size
                    146:   (for the send buffer), but that doesn't work with integer arithmetic and we
                    147:   can't use floating point because some machines don't have it.  This can be
                    148:   rearranged as (s * size) / (s + r).  But (s * size) can be VERY large, too
                    149:   large for 32 bits.  So let's do it this way.  This arithmetic works for
                    150:   buffer sizes up to about 5,000,000.
                    151: */
                    152: #define FACTOR 20L
                    153:     z = ( (long) s * FACTOR ) / ( (long) s + (long) r );
                    154:     x = ( z * ( (long) size / FACTOR ) );
                    155:     if (x < 0) return(-1);             /* Catch overflow */
                    156: 
                    157:     bigsbsiz = x - 5;                  /* Size of send buffer */
                    158:     bigsbuf = bigbufp;                 /* Address of send buffer */
                    159:     debug(F101,"inibufs bigsbsiz","",bigsbsiz);
                    160: 
                    161:     bigrbsiz = size - x - 5;           /* Size of receive buffer */
                    162:     bigrbuf = bigbufp + x;             /* Addresss of receive buffer */
                    163:     debug(F101,"inibufs bigrbsiz","",bigrbsiz);
                    164: 
                    165:     return(0);                         /* Success */
                    166: #else                                  /* No dynamic allocation */
                    167:     bigsbsiz = SBSIZ;                  /* Just use the symbols */
                    168:     bigrbsiz = RBSIZ;                  /* ... */
                    169:     return(0);                         /* Success. */
                    170: #endif /* DYNAMIC */
                    171: }
                    172: 
                    173: 
                    174: /* M A K E B U F  --  Makes and clears a new buffers.  */
                    175: 
                    176: /* Call with: */
                    177: /*  slots:  number of buffer slots to make, 1 to 31 */
                    178: /*  bufsiz: size of the big buffer */
                    179: /*  buf:    address of the big buffer */
                    180: /*  xx:     pointer to array of pktinfo structures for these buffers */
                    181: 
                    182: /* Subdivides the big buffer into "slots" buffers. */
                    183: 
                    184: /* Returns: */
                    185: /*  -1 if too many or too few slots requested,     */
                    186: /*  -2 if slots would be too small.      */
                    187: /*   n (positive) on success = size of one buffer. */
                    188: /*   with pktinfo structure initialized for this set of buffers. */
                    189: 
                    190: int
                    191: makebuf(slots,bufsiz,buf,xx)
                    192: /* makebuf */ int slots, bufsiz; CHAR buf[]; struct pktinfo *xx; {
                    193: 
                    194:     CHAR *a;
                    195:     int i, size;
                    196: 
                    197:     debug(F101,"makebuf","",slots);
                    198:     debug(F101,"makebuf bufsiz","",bufsiz);
                    199:     debug(F101,"makebuf MAXWS","",MAXWS);
                    200: 
                    201:     if (slots > MAXWS || slots < 1) return(-1);
                    202:     if (bufsiz < slots * 10 ) return(-2);
                    203: 
                    204:     size = bufsiz / slots;             /* Divide up the big buffer. */
                    205:     a = buf;                           /* Address of first piece. */
                    206: 
                    207:     for (i = 0; i < slots; i++) {
                    208:        struct pktinfo *x = &xx[i];
                    209:        x->bf_adr = a;                  /* Address of this buffer */
                    210:        x->bf_len = size;               /* Length of this buffer */
                    211:        x->pk_len = 0;                  /* Length of data field */
                    212:         x->pk_typ = ' ';               /* packet type */
                    213:        x->pk_seq = -1;                 /* packet sequence number */
                    214:         x->pk_flg = 0;                 /* ack'd bit */
                    215:         x->pk_rtr = 0;                 /* retransmissions */
                    216:        *a = '\0';                      /* Clear the buffer */
                    217:        a += size;                      /* Position to next buffer slot */
                    218:     }
                    219:     return(size);
                    220: }
                    221: 
                    222: /*  M A K S B U F  --  Makes the send-packet buffer  */
                    223: 
                    224: int
                    225: mksbuf(slots) int slots; {
                    226:     int i, x;
                    227:     sbufnum = 0;
                    228:     if ((x = makebuf(slots,bigsbsiz,bigsbuf,s_pkt)) < 0) {
                    229:        debug(F101,"mksbuf makebuf return","",x);
                    230:        return(x);
                    231:     }
                    232:     debug(F101,"mksbuf makebuf return","",x);
                    233:     for (i = 0; i < 64; i++) {         /* Initialize sequence-number- */
                    234:        sseqtbl[i] = -1;                /* to-buffer-number table. */
                    235:         sacktbl[i] = 0;
                    236:     }
                    237:     for (i = 0; i < MAXWS; i++)
                    238:       sbufuse[i] = 0;                  /* Mark each buffer as free */
                    239:     sbufnum = slots;
                    240:     return(x);
                    241: }
                    242: 
                    243: /*  M A K R B U F  --  Makes the receive-packet buffer  */
                    244: 
                    245: int
                    246: mkrbuf(slots) int slots; {
                    247:     int i, x;
                    248:     rbufnum = 0;
                    249:     if ((x = makebuf(slots,bigrbsiz,bigrbuf,r_pkt)) < 0) {
                    250:        debug(F101,"mkrbuf makebuf return","",x);
                    251:        return(x);
                    252:     }
                    253:     debug(F101,"mkrbuf makebuf return","",x);
                    254:     for (i = 0; i < 64; i++) {         /* Initialize sequence-number- */
                    255:        rseqtbl[i] = -1;                /* to-buffer-number table. */
                    256:     }
                    257:     for (i = 0; i < MAXWS; i++)
                    258:       rbufuse[i] = 0;                  /* Mark each buffer as free */
                    259:     rbufnum = slots;
                    260:     return(x);
                    261: }
                    262: 
                    263: /*  W I N D O W  --  Resize the window to n  */
                    264: 
                    265: int
                    266: window(n) int n; {
                    267:     debug(F101,"window","",n);
                    268:     if (n < 1 || n > 31) return(-1);
                    269:     if (mksbuf(n) < 0) return(-1);
                    270:     if (mkrbuf(n) < 0) return(-1);
                    271:     wslots = n;
                    272: #ifdef DEBUG
                    273:     if (deblog) dumpsbuf();
                    274:     if (deblog) dumprbuf();
                    275: #endif /* DEBUG */
                    276:     return(0);
                    277: }
                    278: 
                    279: /*  G E T S B U F  --  Allocate a send-buffer.  */
                    280: 
                    281: /*  Call with packet sequence number to allocate buffer for. */
                    282: /*  Returns: */
                    283: /*   -4 if argument is invalid (negative, or greater than 63) */
                    284: /*   -3 if buffers were thought to be available but really weren't (bug!) */
                    285: /*   -2 if the number of free buffers is negative (bug!) */
                    286: /*   -1 if no free buffers. */
                    287: /*   0 or positive, packet sequence number, with buffer allocated for it. */
                    288: 
                    289: int
                    290: getsbuf(n) int n; {                    /* Allocate a send-buffer */
                    291:     int i;
                    292:     if (n < 0 || n > 63) {
                    293:        debug(F101,"getsbuf bad arg","",n);
                    294:        return(-4);     /* Bad argument */
                    295:     }
                    296:     debug(F101,"getsbuf, packet","",n);
                    297:     debug(F101,"getsbuf, sbufnum","",sbufnum);
                    298:     if (sbufnum == 0) return(-1);      /* No free buffers. */
                    299:     if (sbufnum < 0) return(-2);       /* Shouldn't happen. */
                    300:     for (i = 0; i < wslots; i++)       /* Find the first one not in use. */
                    301:       if (sbufuse[i] == 0) {           /* Got one? */
                    302:          sbufuse[i] = 1;               /* Mark it as in use. */
                    303:          sbufnum--;                    /* One less free buffer. */
                    304:          *s_pkt[i].bf_adr = '\0';      /* Zero the buffer data field */
                    305:          s_pkt[i].pk_seq = n;          /* Put in the sequence number */
                    306:           sseqtbl[n] = i;              /* Back pointer from sequence number */
                    307:           sacktbl[n] = 0;              /* ACK flag */
                    308:          s_pkt[i].pk_len = 0;          /* Data field length now zero. */
                    309:          s_pkt[i].pk_typ = ' ';        /* Blank the packet type too. */
                    310:          s_pkt[i].pk_flg = 0;          /* Zero the flags */
                    311:          s_pkt[i].pk_rtr = 0;          /* Zero the retransmission count */
                    312:          data = s_pkt[i].bf_adr + 7;   /* Set global "data" address. */
                    313:          if (i+1 > wmax) wmax = i+1;   /* For statistics. */
                    314:          return(n);                    /* Return its index. */
                    315:       }
                    316:     sbufnum = 0;                       /* Didn't find one. */
                    317:     return(-3);                                /* Shouldn't happen! */
                    318: }
                    319: 
                    320: int
                    321: getrbuf() {                            /* Allocate a receive buffer */
                    322:     int i;
                    323:     debug(F101,"getrbuf rbufnum","",rbufnum);
                    324:     debug(F101,"getrbuf wslots","",wslots);
                    325:     debug(F101,"getrbuf dum002","",dum002);
                    326:     debug(F101,"getrbuf dum003","",dum003);
                    327:     if (rbufnum == 0) return(-1);      /* No free buffers. */
                    328:     if (rbufnum < 0) return(-2);       /* Shouldn't happen. */
                    329:     for (i = 0; i < wslots; i++)       /* Find the first one not in use. */
                    330:       if (rbufuse[i] == 0) {           /* Got one? */
                    331:          rbufuse[i] = 1;               /* Mark it as in use. */
                    332:          *r_pkt[i].bf_adr = '\0';      /* Zero the buffer data field */
                    333:          rbufnum--;                    /* One less free buffer. */
                    334:          debug(F101,"getrbuf new rbufnum","",rbufnum);
                    335:          if (i+1 > wmax) wmax = i+1;   /* For statistics. */
                    336:          return(i);                    /* Return its index. */
                    337:       }
                    338:     debug(F101,"getrbuf foulup","",i);
                    339:     rbufnum = 0;                       /* Didn't find one. */
                    340:     return(-3);                                /* Shouldn't happen! */
                    341: }
                    342: 
                    343: /*  F R E E S B U F  --  Free send-buffer for given packet sequence number */
                    344: 
                    345: /*  Returns:  */
                    346: /*   1 upon success  */
                    347: /*  -1 if specified buffer does not exist */
                    348: 
                    349: int
                    350: freesbuf(n) int n; {                   /* Release send-buffer for packet n. */
                    351:     int i;
                    352: 
                    353:     debug(F101,"freesbuf","",n);
                    354:     if (n < 0 || n > 63)               /* No such packet. */
                    355:       return(-1);
                    356:     i = sseqtbl[n];                    /* Get the window slot number. */
                    357:     if (i > -1 && i <= wslots) {
                    358:        sseqtbl[n] = -1;                /* If valid, remove from seqtbl */
                    359:        sbufnum++;                      /* and count one more free buffer */
                    360:        sbufuse[i] = 0;                 /* and mark it as free, */
                    361:     } else {
                    362:        debug(F101," sseqtbl[n]","",sseqtbl[n]);
                    363:        return(-1);
                    364:     }
                    365: 
                    366: /* The following is done only so dumped buffers will look right. */
                    367: 
                    368:     if (1) {
                    369:        *s_pkt[i].bf_adr = '\0';        /* Zero the buffer data field */
                    370:        s_pkt[i].pk_seq = -1;           /* Invalidate the sequence number */
                    371:        s_pkt[i].pk_len = 0;            /* Data field length now zero. */
                    372:        s_pkt[i].pk_typ = ' ';          /* Blank the packet type too. */
                    373:        s_pkt[i].pk_flg = 0;            /* And zero the flag */
                    374:        s_pkt[i].pk_rtr = 0;            /* And the retries field. */
                    375:     }
                    376:     return(1);
                    377: }
                    378: 
                    379: int
                    380: freerbuf(i) int i; {                   /* Release receive-buffer slot "i". */
                    381:     int n;
                    382: 
                    383: /* NOTE !! Currently, this function frees the indicated buffer, but */
                    384: /* does NOT erase the data.  The program counts on this.  Will find a */
                    385: /* better way later.... */
                    386: 
                    387:     debug(F101,"freerbuf, slot","",i);
                    388:     if (i < 0 || i >= wslots) {                /* No such slot. */
                    389:        debug(F101,"freerbuf no such slot","",i);
                    390:        return(-1);
                    391:     }
                    392:     n = r_pkt[i].pk_seq;               /* Get the packet sequence number */
                    393:     debug(F101,"freerbuf, packet","",n);
                    394:     if (n > -1 && n < 64)              /* If valid, remove from seqtbl */
                    395:       rseqtbl[n] = -1;
                    396:     if (rbufuse[i] != 0) {             /* If really allocated, */
                    397:        rbufuse[i] = 0;                 /* mark it as free, */
                    398:        rbufnum++;                      /* and count one more free buffer. */
                    399:        debug(F101,"freerbuf, new rbufnum","",rbufnum);
                    400:     }
                    401: 
                    402: /* The following is done only so dumped buffers will look right. */
                    403: 
                    404:     if (1) {
                    405:      /* *r_pkt[i].bf_adr = '\0'; */    /* Zero the buffer data field */
                    406:        r_pkt[i].pk_seq = -1;           /* And from packet list */
                    407:        r_pkt[i].pk_len = 0;            /* Data field length now zero. */
                    408:        r_pkt[i].pk_typ = ' ';          /* Blank the packet type too. */
                    409:        r_pkt[i].pk_flg = 0;            /* And zero the flag */
                    410:        r_pkt[i].pk_rtr = 0;            /* And the retries field. */
                    411:     }
                    412:     return(1);
                    413: }
                    414: 
                    415: /* This is like freerbuf, except it's called with a packet sequence number */
                    416: /* rather than a packet buffer index. */
                    417: 
                    418: VOID
                    419: freerpkt(seq) int seq; {
                    420:     int k;
                    421:     debug(F101,"freerpkt seq","",seq);
                    422:     k = rseqtbl[seq];
                    423:     debug(F101,"freerpkt k","",k);
                    424:     if (k > -1) {
                    425:        k = freerbuf(k);
                    426:        debug(F101,"freerpkt freerbuf","",k);
                    427:     }
                    428: }
                    429: 
                    430: 
                    431: /*  C H K W I N  --  Check if packet n is in window. */
                    432: 
                    433: /*  Returns: */
                    434: /*    0 if it is in the current window,  */
                    435: /*   +1 if it would have been in previous window (e.g. if ack was lost), */
                    436: /*   -1 if it is outside any window (protocol error),   */
                    437: /*   -2 if either of the argument packet numbers is out of range.  */
                    438: 
                    439: /* Call with packet number to check (n), lowest packet number in window */
                    440: /* (bottom), and number of slots in window (slots).  */
                    441: 
                    442: int
                    443: chkwin(n,bottom,slots) int n, bottom, slots; {
                    444:     int top, prev;
                    445: 
                    446:     debug(F101,"chkwin packet","",n);
                    447:     debug(F101,"chkwin winlo","",bottom);
                    448:     debug(F101,"chkwin slots","",slots);
                    449: 
                    450: /* First do the easy and common cases, where the windows are not split. */
                    451: 
                    452:     if (n < 0 || n > 63 || bottom < 0 || bottom > 63)
                    453:       return(-2);
                    454: 
                    455:     if (n == bottom) return(0);                /* In a perfect world... */
                    456: 
                    457:     top = bottom + slots;              /* Calculate window top. */
                    458:     if (top < 64 && n < top && n >= bottom)
                    459:       return(0);                       /* In current window. */
                    460: 
                    461:     prev = bottom - slots;             /* Bottom of previous window. */
                    462:     if (prev > -1 && n < bottom && n > prev)
                    463:       return(1);                       /* In previous. */
                    464: 
                    465: /* Now consider the case where the current window is split. */
                    466: 
                    467:     if (top > 63) {                    /* Wraparound... */
                    468:        top -= 64;                      /* Get modulo-64 sequence number */
                    469:        if (n < top || n >= bottom) {
                    470:            return(0);                  /* In current window. */
                    471:        } else {                        /* Not in current window. */
                    472:            if (n < bottom && n >= prev) /* Previous window can't be split. */
                    473:              return(1);                /* In previous window. */
                    474:            else
                    475:              return(-1);               /* Not in previous window. */
                    476:        }
                    477:     }
                    478: 
                    479: /* Now the case where current window not split, but previous window is. */ 
                    480: 
                    481:     if (prev < 0) {                    /* Is previous window split? */
                    482:        prev += 64;                     /* Yes. */
                    483:        if (n < bottom || n >= prev)
                    484:          return(1);                    /* In previous window. */
                    485:     } else {                           /* Previous window not split. */
                    486:        if (n < bottom && n >= prev)
                    487:          return(1);                    /* In previous window. */
                    488:     }
                    489:     
                    490: /* It's not in the current window, and not in the previous window... */
                    491: 
                    492:     return(-1);                                /* So it's not in any window. */
                    493: }
                    494: 
                    495: int
                    496: dumpsbuf() {                           /* Dump send-buffers */
                    497: #ifdef DEBUG
                    498:     int j, x;                          /* to debug log. */
                    499: 
                    500:     if (! deblog) return(0);
                    501:     x = zsoutl(ZDFILE,"SEND BUFFERS:");
                    502:     if (x < 0) {
                    503:        deblog = 0;
                    504:        return(0);
                    505:     }
                    506:     x=zsoutl(ZDFILE,"buffer inuse address length data type seq flag retries");
                    507:     if (x < 0) {
                    508:        deblog = 0;
                    509:        return(0);
                    510:     }
                    511:     for ( j = 0; j < wslots; j++ ) {
                    512:        sprintf(xbuf,"%4d%6d%10d%5d%6d%4c%5d%5d%6d\n",
                    513:               j,
                    514:               sbufuse[j],
                    515:               s_pkt[j].bf_adr, 
                    516:               s_pkt[j].bf_len,
                    517:               s_pkt[j].pk_len,
                    518:               s_pkt[j].pk_typ,
                    519:               s_pkt[j].pk_seq,
                    520:               s_pkt[j].pk_flg,
                    521:               s_pkt[j].pk_rtr
                    522:               );
                    523:        if (zsout(ZDFILE,xbuf) < 0)  {
                    524:            deblog = 0;
                    525:            return(0);
                    526:        }
                    527:        if (s_pkt[j].pk_adr) {
                    528:            x = (int)strlen((char *) s_pkt[j].pk_adr);
                    529:            if (x)
                    530:              sprintf(xbuf,"[%.72s%s]\n",s_pkt[j].pk_adr, x > 72 ? "..." : "");
                    531:            else
                    532:              sprintf(xbuf,"[(empty string)]\n");
                    533:        } else {
                    534:            sprintf(xbuf,"[(null pointer)]\n");
                    535:        }
                    536:        if (zsout(ZDFILE,xbuf) < 0) {
                    537:            deblog = 0;
                    538:            return(0);
                    539:        }
                    540:     }
                    541:     sprintf(xbuf,"free: %d, winlo: %d\n", sbufnum, winlo);
                    542:     if (zsout(ZDFILE,xbuf) < 0) {
                    543:        deblog = 0;
                    544:        return(0);
                    545:     }
                    546:     return(0);
                    547: #endif /* DEBUG */
                    548: }
                    549: int
                    550: dumprbuf() {                           /* Dump receive-buffers */
                    551: #ifdef DEBUG
                    552:     int j, x;
                    553:     if (! deblog) return(0);
                    554:     if (zsoutl(ZDFILE,"RECEIVE BUFFERS:") < 0) {
                    555:        deblog = 0;
                    556:        return(0);
                    557:     }
                    558:     x=zsoutl(ZDFILE,"buffer inuse address length data type seq flag retries");
                    559:     if (x < 0) {
                    560:        deblog = 0;
                    561:        return(0);
                    562:     }
                    563:     for ( j = 0; j < wslots; j++ ) {
                    564:        sprintf(xbuf,"%4d%6d%10d%5d%6d%4c%5d%5d%6d\n",
                    565:               j,
                    566:               rbufuse[j],
                    567:               r_pkt[j].bf_adr, 
                    568:               r_pkt[j].bf_len,
                    569:               r_pkt[j].pk_len,
                    570:               r_pkt[j].pk_typ,
                    571:               r_pkt[j].pk_seq,
                    572:               r_pkt[j].pk_flg,
                    573:               r_pkt[j].pk_rtr
                    574:               );
                    575:        if (zsout(ZDFILE,xbuf) < 0) {
                    576:            deblog = 0;
                    577:            return(0);
                    578:        }
                    579:        x = (int)strlen((char *)r_pkt[j].bf_adr);
                    580:        sprintf(xbuf,"[%.72s%s]\n",r_pkt[j].bf_adr, x > 72 ? "..." : "");
                    581:        if (zsout(ZDFILE,xbuf) < 0)  {
                    582:            deblog = 0;
                    583:            return(0);
                    584:        }
                    585:     }
                    586:     sprintf(xbuf,"free: %d, winlo: %d\n", rbufnum, winlo);
                    587:     if (zsout(ZDFILE,xbuf) < 0)  {
                    588:        deblog = 0;
                    589:        return(0);
                    590:     }
                    591:     return(0);
                    592: #endif /* DEBUG */
                    593: }
                    594: 
                    595: /*** Some misc functions also moved here from the other ckcfn*.c modules ***/
                    596: /*** to even out the module sizes. ***/
                    597: 
                    598: /* Attribute Packets. */
                    599: 
                    600: /*
                    601:   Call with xp == 0 if we're sending a real file (F packet),
                    602:   or xp != 0 for screen data (X packet).
                    603:   Returns 0 on success, -1 on failure.
                    604: */
                    605: int
                    606: sattr(xp) int xp; {                    /* Send Attributes */
                    607:     int i, j, aln;
                    608:     char *tp;
                    609:     struct zattr x;
                    610: 
                    611:     if (zsattr(&x) < 0) return(-1);    /* Get attributes or die trying */
                    612:     if (nxtpkt() < 0) return(-1);      /* Next packet number */
                    613:     i = 0;                             /* i = Data field character number */
                    614:     if (atsido) {                      /* System type */
                    615:        data[i++] = '.';
                    616:        data[i++] = tochar(x.systemid.len); /*  Copy from attr structure */
                    617:        for (j = 0; j < x.systemid.len; j++)
                    618:          data[i++] = x.systemid.val[j];
                    619:     }
                    620:     if (attypo) {                      /* File type */
                    621:        data[i++] = '"';
                    622:        if (binary) {                   /* Binary  */
                    623:            data[i++] = tochar(2);      /*  Two characters */
                    624:            data[i++] = 'B';            /*  B for Binary */
                    625:            data[i++] = '8';            /*  8-bit bytes (note assumption...) */
                    626:        } else {                        /* Text */
                    627:            data[i++] = tochar(3);      /*  Three characters */
                    628:            data[i++] = 'A';            /*  A = (extended) ASCII with CRLFs */
                    629:            data[i++] = 'M';            /*  M for carriage return */
                    630:            data[i++] = 'J';            /*  J for linefeed */
                    631: 
                    632: #ifdef NOCSETS
                    633:            data[i++] = '*';            /* Encoding */
                    634:            data[i++] = tochar(1);      /* Length of value is 1 */
                    635:            data[i++] = 'A';            /* A for ASCII */
                    636: #else
                    637:            if (tcharset == TC_TRANSP)  /* Transfer character set */
                    638:              tp = NULL;
                    639:            else
                    640:              tp = tcsinfo[tcharset].designator;
                    641:            if ((tp != NULL) && (aln = (int)strlen(tp)) > 0) {
                    642:                data[i++] = '*';        /* Encoding */
                    643:                data[i++] = tochar(aln+1); /*  Length of charset designator. */
                    644:                data[i++] = 'C';        /*  Text in specified character set. */
                    645:                for (j = 0; j < aln; j++) /*  Designator from tcsinfo struct */
                    646:                  data[i++] = *tp++;      /*  Example: *&I6/100 */
                    647:            }
                    648: #endif /* NOCSETS */
                    649:        }
                    650:     }
                    651:     if ((xp == 0) && (x.length > -1L)) { /* If it's a real file */
                    652: 
                    653:        if (atdato && (aln = x.date.len) > 0) { /* Creation date, if any */
                    654:            data[i++] = '#';
                    655:            data[i++] = tochar(aln);
                    656:            for (j = 0; j < aln; j++)
                    657:              data[i++] = x.date.val[j];
                    658:        }
                    659:        if (atleno) {
                    660:            data[i] = '!';                      /* File length in K */
                    661:            sprintf((char *) &data[i+2],"%ld",x.lengthk);
                    662:            aln = (int)strlen((char *)(data+i+2));
                    663:            data[i+1] = tochar(aln);
                    664:            i += aln + 2;
                    665: 
                    666:            data[i] = '1';                      /* File length in bytes */
                    667:            sprintf((char *) &data[i+2],"%ld",x.length);
                    668:            aln = (int)strlen((char *)(data+i+2));
                    669:            data[i+1] = tochar(aln);
                    670:            i += aln + 2;
                    671:        }
                    672:        if (atblko && fblksiz) {                /* Blocksize, if set */
                    673:            data[i] = '(';
                    674:            sprintf((char *) &data[i+2],"%d",fblksiz);
                    675:            aln = (int)strlen((char *)(data+i+2));
                    676:            data[i+1] = tochar(aln);
                    677:            i += aln + 2;
                    678:        }
                    679:     }
                    680: #ifndef NOFRILLS
                    681:     if ((rprintf || rmailf) && atdiso) { /* MAIL, or REMOTE PRINT?  */
                    682:        data[i++] = '+';                /* Disposition */
                    683:         data[i++] = tochar((int)strlen(optbuf) + 1); /* Options, if any */
                    684:        if (rprintf)
                    685:          data[i++] = 'P';              /* P for Print */
                    686:        else
                    687:          data[i++] = 'M';              /* M for Mail */
                    688:        for (j = 0; optbuf[j]; j++)     /* Copy any options */
                    689:          data[i++] = optbuf[j];
                    690:     }
                    691: #endif /* NOFRILLS */
                    692:     data[i] = '\0';                    /* Make sure it's null-terminated */
                    693:     aln = (int)strlen((char *)data);   /* Get overall length of attributes */
                    694: 
                    695: /* Change this code to break attribute data up into multiple packets! */
                    696: 
                    697:     j = (spsiz < 95) ? (92 - bctu) : (spsiz - 2 - bctu);
                    698:     if (aln > j) {                     /* Check length of result */
                    699:        spack('A',pktnum,0,(CHAR *)""); /* send an empty attribute packet */
                    700:        debug(F101,"sattr pkt too long","",aln); /* if too long */
                    701:        debug(F101,"sattr spsiz","",spsiz);
                    702:     } else {                           /* Otherwise */
                    703:        spack('A',pktnum,aln,data);     /* send the real thing. */
                    704:        debug(F111,"sattr",data,aln);
                    705:     }
                    706: 
                    707:     return(0);
                    708: }
                    709: 
                    710: static char *reason[] = {
                    711:     "size", "type", "date", "creator", "account", "area", "password",
                    712:     "blocksize", "access", "encoding", "disposition", "protection",
                    713:     "protection", "origin", "format", "sys-dependent", "size" };
                    714: int nreason = sizeof(reason) / sizeof(char *);
                    715: 
                    716: int
                    717: rsattr(s) CHAR *s; {                   /* Read response to attribute packet */
                    718:     char c, *p;
                    719:     debug(F111,"rsattr: ",s,*s);
                    720:     if (*s++ == 'N') {                 /* If it's 'N' followed by anything, */
                    721:        p = (char *)s;
                    722:        if (local && ((c = *p++) > SP)) { /* get reason, */
                    723:            c -= '!';                     /* get offset */
                    724:            p = ((unsigned int) c <= nreason) ? reason[c] : "reason unknown";
                    725:        }
                    726:        screen(SCR_ST,ST_REFU,0L,p);    /* Say other Kermit refused. */
                    727:        debug(F110,"refused",p,0);
                    728:        tlog(F110,"refused",p,0L);
                    729:        return(-1);     
                    730:     }
                    731:     return(0);
                    732: }
                    733: 
                    734: int
                    735: gattr(s, yy) CHAR *s; struct zattr *yy; { /* Read incoming attribute packet */
                    736:     char c;
                    737:     int aln, i;
                    738: #define ABUFL 100                      /* Temporary buffer for conversions */
                    739:     char abuf[ABUFL];
                    740: #define FTBUFL 10                      /* File type buffer */
                    741:     static char ftbuf[FTBUFL];
                    742: #define DTBUFL 40                      /* File creation date */
                    743:     static char dtbuf[DTBUFL];
                    744: #define TSBUFL 10                      /* Transfer syntax */
                    745:     static char tsbuf[TSBUFL];
                    746: #define IDBUFL 10                      /* System ID */
                    747:     static char idbuf[IDBUFL];
                    748: #ifndef MAC
                    749: #define DSBUFL 100                     /* Disposition */
                    750:     static char dsbuf[DSBUFL];
                    751: #define SPBUFL 512                     /* System-dependent parameters */
                    752:     static char spbuf[SPBUFL];
                    753: #else
                    754: #define DSBUFL 100                     /* Disposition */
                    755:     static char *dsbuf = NULL;
                    756: #define SPBUFL 512                     /* System-dependent parameters */
                    757:     static char *spbuf = 0;
                    758: #endif /* MAC */
                    759: #define RPBUFL 20                      /* Attribute reply */
                    760:     static char rpbuf[RPBUFL];
                    761: 
                    762:     char *rp;                          /* Pointer to reply buffer */
                    763:     int retcode;                       /* Return code */
                    764: 
                    765: /* fill in the attributes we have received */
                    766: 
                    767:     rp = rpbuf;                                /* Initialize reply buffer */
                    768:     *rp++ = 'N';                       /* for negative reply. */
                    769:     retcode = 0;                       /* Initialize return code. */
                    770: 
                    771:     while (c = *s++) {                 /* Get attribute tag */
                    772:        aln = xunchar(*s++);            /* Length of attribute string */
                    773:        switch (c) {
                    774:          case '!':                     /* file length in K */
                    775:            for (i = 0; (i < aln) && (i < ABUFL); i++) /* Copy it */
                    776:              abuf[i] = *s++;
                    777:            abuf[i] = '\0';             /* Terminate with null */
                    778:            if (i < aln) s += (aln - i); /* If field was too long for buffer */
                    779:            yy->lengthk = atol(abuf);   /* Convert to number */
                    780:            break;
                    781: 
                    782:          case '"':                     /* file type */
                    783:            for (i = 0; (i < aln) && (i < FTBUFL); i++)
                    784:              ftbuf[i] = *s++;          /* Copy it into a static string */
                    785:            ftbuf[i] = '\0';
                    786:            if (i < aln) s += (aln - i);
                    787:            if (attypi) {
                    788:                yy->type.val = ftbuf;   /* Pointer to string */
                    789:                yy->type.len = i;       /* Length of string */
                    790:                debug(F101,"gattr file type",tsbuf,i);
                    791:                if (*ftbuf != 'A' && *ftbuf != 'B') { /* Reject unknown type */
                    792:                    retcode = -1;
                    793:                    *rp++ = c;
                    794:                }               
                    795:            }
                    796:            break;
                    797: 
                    798:          case '#':                     /* file creation date */
                    799:            for (i = 0; (i < aln) && (i < DTBUFL); i++)
                    800:              dtbuf[i] = *s++;          /* Copy it into a static string */
                    801:            if (i < aln) s += (aln - i);
                    802:            dtbuf[i] = '\0';
                    803:            if (atdati) {
                    804:                yy->date.val = dtbuf;   /* Pointer to string */
                    805:                yy->date.len = i;       /* Length of string */
                    806:            }
                    807:            if (fncact == XYFX_U) {     /* Receiving in update mode? */
                    808:                if (zstime(filnam,yy,1) > 0) { /* Compare dates */
                    809:                    discard = 1;        /* If incoming file is older, */
                    810:                    *rp++ = c;          /* discard it, reason = date. */
                    811:                    retcode = -1;       /* Rejection notice. */
                    812:                }
                    813:            }                           
                    814:            break;
                    815: 
                    816:          case '(':                     /* File Block Size */
                    817:            for (i = 0; (i < aln) && (i < ABUFL); i++) /* Copy it */
                    818:              abuf[i] = *s++;
                    819:            abuf[i] = '\0';             /* Terminate with null */
                    820:            if (i < aln) s += (aln - i);
                    821:            if (atblki) {
                    822:                yy->blksize = atol(abuf); /* Convert to number */
                    823:            }
                    824:            break;
                    825: 
                    826:          case '*':                     /* encoding (transfer syntax) */
                    827:            for (i = 0; (i < aln) && (i < TSBUFL); i++)
                    828:              tsbuf[i] = *s++;          /* Copy it into a static string */
                    829:            if (i < aln) s += (aln - i);
                    830:            tsbuf[i] = '\0';
                    831:            if (atenci) {
                    832:                yy->encoding.val = tsbuf; /* Pointer to string */
                    833:                yy->encoding.len = i;   /* Length of string */
                    834:                debug(F101,"gattr encoding",tsbuf,i);
                    835:                switch (*tsbuf) {
                    836: #ifndef NOCSETS
                    837:                  case 'A':             /* Normal (maybe extended) ASCII */
                    838:                    tcharset = TC_USASCII; /* Transparent chars untranslated */
                    839:                    break;
                    840:                  case 'C':             /* Specified character set */
                    841:                    for (i = 0; i < ntcsets; i++) { 
                    842:                        if (!strcmp(tcsinfo[i].designator,tsbuf+1)) break;
                    843:                    }
                    844:                    debug(F101,"gattr xfer charset lookup","",i);
                    845:                    if (i == ntcsets) { /* If unknown character set, */
                    846:                        debug(F110,"gattr: xfer charset unknown",tsbuf+1,0);
                    847:                        if (!unkcs) {   /* and SET UNKNOWN DISCARD, */
                    848:                            retcode = -1; /* reject the file. */
                    849:                            *rp++ = c;
                    850:                        }
                    851:                    } else {
                    852:                        tcharset = tcsinfo[i].code; /* if known, use it */
                    853:                        rx = xlr[tcharset][fcharset]; /* xlation function */
                    854:                    }
                    855:                    debug(F101,"gattr tcharset","",tcharset);
                    856:                break;
                    857: #endif /* NOCSETS */
                    858:              default:                  /* Something else. */
                    859:                debug(F110,"gattr unk encoding attribute",tsbuf,0);
                    860:                if (!unkcs) {           /* If SET UNK DISC */
                    861:                    retcode = -1;       /* reject the file */
                    862:                    *rp++ = c;
                    863:                }
                    864:                break;
                    865:                }
                    866:            }
                    867:            break;
                    868: 
                    869:          case '+':                     /* disposition */
                    870: #ifdef MAC
                    871:            if (!dsbuf)
                    872:                if ((dsbuf = malloc(DSBUFL+1)) == NULL)
                    873:                    fatal("gtattr: no memory for dsbuf");
                    874: #endif /* MAC */
                    875:            for (i = 0; (i < aln) && (i < DSBUFL); i++)
                    876:              dsbuf[i] = *s++;          /* Copy it into a static string */
                    877:            dsbuf[i] = '\0';
                    878:            if (i < aln) s += (aln - i);
                    879:            if (atdisi) {
                    880:                yy->disp.val = dsbuf;   /* Pointer to string */
                    881:                yy->disp.len = i;       /* Length of string */
                    882:                if (*dsbuf != 'M' && *dsbuf != 'P') {
                    883:                    retcode = -1;
                    884:                    *rp++ = c;
                    885:                }
                    886:            }
                    887:            break;
                    888: 
                    889:          case '.':                     /* sender's system ID */
                    890:            for (i = 0; (i < aln) && (i < IDBUFL); i++)
                    891:              idbuf[i] = *s++;          /* Copy it into a static string */
                    892:            idbuf[i] = '\0';
                    893:            if (i < aln) s += (aln - i);
                    894:            if (atsidi) {
                    895:                yy->systemid.val = idbuf; /* Pointer to string */
                    896:                yy->systemid.len = i;   /* Length of string */
                    897:            }
                    898:            break;
                    899: 
                    900:          case '0':                     /* system-dependent parameters */
                    901: #ifdef MAC
                    902:            if (!spbuf && !(spbuf = malloc(SPBUFL)))
                    903:                fatal("gattr: no memory for spbuf");
                    904: #endif /* MAC */
                    905:            for (i = 0; (i < aln) && (i < SPBUFL); i++)
                    906:              spbuf[i] = *s++;          /* Copy it into a static string */
                    907:            spbuf[i] = '\0';
                    908:            if (i < aln) s += (aln - i);
                    909:            if (atsysi) {
                    910:                yy->sysparam.val = spbuf; /* Pointer to string */
                    911:                yy->sysparam.len = i;   /* Length of string */
                    912:            }
                    913:            break;
                    914: 
                    915:          case '1':                     /* file length in bytes */
                    916:            for (i = 0; (i < aln) && (i < ABUFL); i++) /* Copy it */
                    917:              abuf[i] = *s++;
                    918:            abuf[i] = '\0';             /* Terminate with null */
                    919:            if (i < aln) s += (aln - i);
                    920:            yy->length = atol(abuf);    /* Convert to number */
                    921:            debug(F111,"gattr length",abuf,(int) yy->length);
                    922:            break;
                    923: 
                    924:          default:                      /* Unknown attribute */
                    925:            s += aln;                   /* Just skip past it */
                    926:            break;
                    927:        }
                    928:     }
                    929: 
                    930:     /* Check file length now, because we also need to know the file type */
                    931:     /* in case zchkspa() differentiates text and binary (VMS version does) */
                    932: 
                    933:     if (atleni) {                      /* Length attribute enabled? */
                    934:        if (yy->length > -1L) {         /* Length-in-bytes attribute rec'd? */
                    935:            if (!zchkspa(filnam,(yy->length))) { /* Check space */
                    936:                retcode = -1;
                    937:                *rp++ = '1';
                    938:            }
                    939:        } else if (yy->lengthk > -1L) { /* Length in K attribute rec'd? */
                    940:            if (!zchkspa(filnam,(yy->lengthk * 1024))) {
                    941:                retcode = -1;           /* Check space */
                    942:                *rp++ = '!';
                    943:            }
                    944:        }
                    945:     }
                    946: 
                    947:     /* (PWP) show the info */
                    948:     if (yy->length > 0L) {             /* Let the user know the size */
                    949:        fsize = yy->length;             
                    950:        screen(SCR_QE,0,fsize," Size");
                    951:     } else if (yy->lengthk > 0) {
                    952:        fsize = yy->lengthk * 1024L;
                    953:        screen(SCR_QE,0,fsize," Size");
                    954:     }
                    955: #ifdef DEBUG
                    956:     if (deblog) {
                    957:        sprintf(abuf,"%ld",fsize);
                    958:        debug(F110,"gattr fsize",abuf,0);
                    959:     }
                    960: #endif /* DEBUG */
                    961:     if (retcode == 0) rp = rpbuf;      /* Null reply string if accepted */
                    962:     *rp = '\0';                                /* End of reply string */
                    963:     yy->reply.val = rpbuf;             /* Add it to attribute structure */
                    964:     yy->reply.len = (int)strlen(rpbuf);
                    965:     debug(F111,"gattr return",rpbuf,retcode);
                    966:     return(retcode);
                    967: }
                    968: 
                    969: /*  I N I T A T T R  --  Initialize file attribute structure  */
                    970: 
                    971: int
                    972: initattr(yy) struct zattr *yy; {
                    973:     yy->lengthk = yy->length = -1L;
                    974:     yy->type.val = "";
                    975:     yy->type.len = 0;
                    976:     yy->date.val = "";
                    977:     yy->date.len = 0;
                    978:     yy->encoding.val = "";
                    979:     yy->encoding.len = 0;
                    980:     yy->disp.val = "";
                    981:     yy->disp.len = 0;
                    982:     yy->systemid.val = "";
                    983:     yy->systemid.len = 0;
                    984:     yy->sysparam.val = "";
                    985:     yy->sysparam.len = 0;
                    986:     yy->creator.val = "";
                    987:     yy->creator.len = 0;
                    988:     yy->account.val = "";
                    989:     yy->account.len = 0;
                    990:     yy->area.val = "";
                    991:     yy->area.len = 0;
                    992:     yy->passwd.val = "";
                    993:     yy->passwd.len = 0;
                    994:     yy->blksize = -1L;
                    995:     yy->access.val = "";
                    996:     yy->access.len = 0;
                    997:     yy->lprotect.val = "";
                    998:     yy->lprotect.len = 0;
                    999:     yy->gprotect.val = "";
                   1000:     yy->gprotect.len = 0;
                   1001:     yy->recfm.val = "";
                   1002:     yy->recfm.len = 0;
                   1003:     yy->reply.val = "";
                   1004:     yy->reply.len = 0;
                   1005:     return(0);
                   1006: }
                   1007: 
                   1008: /*  A D E B U -- Write attribute packet info to debug log  */
                   1009: 
                   1010: int
                   1011: adebu(f,zz) char *f; struct zattr *zz; {
                   1012: #ifdef DEBUG
                   1013:     if (deblog == 0) return(0);
                   1014:     debug(F110,"Attributes for incoming file ",f,0);
                   1015:     debug(F101," length in K","",(int) zz->lengthk);
                   1016:     debug(F111," file type",zz->type.val,zz->type.len);
                   1017:     debug(F111," creation date",zz->date.val,zz->date.len);
                   1018:     debug(F111," creator",zz->creator.val,zz->creator.len);
                   1019:     debug(F111," account",zz->account.val,zz->account.len);
                   1020:     debug(F111," area",zz->area.val,zz->area.len);
                   1021:     debug(F111," password",zz->passwd.val,zz->passwd.len);
                   1022:     debug(F101," blksize","",(int) zz->blksize);
                   1023:     debug(F111," access",zz->access.val,zz->access.len);
                   1024:     debug(F111," encoding",zz->encoding.val,zz->encoding.len);
                   1025:     debug(F111," disposition",zz->disp.val,zz->disp.len);
                   1026:     debug(F111," lprotection",zz->lprotect.val,zz->lprotect.len);
                   1027:     debug(F111," gprotection",zz->gprotect.val,zz->gprotect.len);
                   1028:     debug(F111," systemid",zz->systemid.val,zz->systemid.len);
                   1029:     debug(F111," recfm",zz->recfm.val,zz->recfm.len);
                   1030:     debug(F111," sysparam",zz->sysparam.val,zz->sysparam.len);
                   1031:     debug(F101," length","",(int) zz->length);
                   1032:     debug(F110," reply",zz->reply.val,0);
                   1033: #endif /* DEBUG */
                   1034:     return(0);
                   1035: }
                   1036: 
                   1037: /*  O P E N A -- Open a file, with attributes.  */
                   1038: /*
                   1039:   This function tries to open a new file to put the arriving data in.  The
                   1040:   filename is the one in the srvcmd buffer.  File collision actions are:
                   1041:   OVERWRITE (the existing file is overwritten), RENAME (the new file is
                   1042:   renamed), BACKUP (the existing file is renamed), DISCARD (the new file is
                   1043:   refused), UPDATE (the incoming file replaces the existing file only if the
                   1044:   incoming file has a newer creation date).
                   1045: 
                   1046:   Returns 0 on failure, nonzero on success.
                   1047: */
                   1048: int
                   1049: opena(f,zz) char *f; struct zattr *zz; {
                   1050:     int x;
                   1051:     static struct filinfo fcb;         /* Must be static! */
                   1052: 
                   1053:     debug(F111,"opena discard",f,discard);
                   1054: 
                   1055:     adebu(f,zz);                       /* Write attributes to debug log */
                   1056: 
                   1057:     ffc = 0L;                          /* Init file character counter */
                   1058: 
                   1059:     if (bsavef) {                      /* If somehow file mode */
                   1060:        binary = bsave;                 /* was saved but not restored, */
                   1061:        bsavef = 0;                     /* restore it. */
                   1062:        debug(F101,"opena restoring binary","",binary);
                   1063:     }
                   1064:     if (zz->type.val[0] == 'A') {      /* Check received attributes */
                   1065: #ifdef VMS
                   1066:        if (binary == XYFT_L)           /* Refuse to receive a file in */
                   1067:          return(0);                    /* labeled mode if sent as text. */
                   1068: #endif /* VMS */
                   1069:        bsave = binary;                 /* ASCII.  Save global file type */
                   1070:        bsavef = 1;                     /* ( restore it in clsof() ) */
                   1071:        binary = XYFT_T;                /* Set current type to Text. */
                   1072:        debug(F100,"opena attribute A = text","",binary);
                   1073:     } else if (zz->type.val[0] == 'B') {
                   1074:        bsave = binary;                 /* Binary.  Save global file type */
                   1075:        bsavef = 1;
                   1076: #ifdef VMS
                   1077:        if (binary != XYFT_L && binary != XYFT_U) /* Special VMS cases */
                   1078: #endif /* VMS */
                   1079:          binary = XYFT_B;
                   1080:        debug(F101,"opena attribute B = binary","",binary);
                   1081:     }
                   1082: 
                   1083:     /* Set up file control structure */
                   1084: 
                   1085:     fcb.bs = fblksiz;                  /* Blocksize */
                   1086: #ifndef NOCSETS
                   1087:     fcb.cs = fcharset;                 /* Character set */
                   1088: #else
                   1089:     fcb.cs = 0;                                /* Character set */
                   1090: #endif /* NOCSETS */
                   1091:     fcb.rl = frecl;                    /* Record Length */
                   1092:     fcb.fmt = frecfm;                  /* Record Format */
                   1093:     fcb.org = forg;                    /* Organization */
                   1094:     fcb.cc = fcctrl;                   /* Carriage control */
                   1095:     fcb.typ = binary;                  /* Type */
                   1096:     fcb.dsp = (fncact == XYFX_A) ? XYFZ_A : XYFZ_N; /* Disposition */
                   1097:     fcb.os_specific = '\0';            /* OS specific info */
                   1098: #ifdef VMS
                   1099:     fcb.lblopts = lf_opts;             /* VMS Labeled file options */
                   1100: #else
                   1101:     fcb.lblopts = 0;
                   1102: #endif /* VMS */
                   1103: 
                   1104:     if (x = openo(f,zz,&fcb)) {                /* Try to open the file. */
                   1105:        tlog(F110," as",f,0L);          /* OK, open, record name. */
                   1106:        if (binary) {                   /* Log file mode in transaction log */
                   1107:            tlog(F101," mode: binary","",(long) binary);
                   1108:        } else {                        /* If text mode, check character set */
                   1109:            tlog(F100," mode: text","",0L);
                   1110: #ifndef NOCSETS
                   1111:            tlog(F110," file character set",fcsinfo[fcharset].name,0L);
                   1112:            if (tcharset == TC_TRANSP)
                   1113:              tlog(F110," xfer character set","transparent",0L);
                   1114:            else
                   1115:              tlog(F110," xfer character set",tcsinfo[tcharset].name,0L);
                   1116: #endif /* NOCSETS */
                   1117:            debug(F111," opena charset",zz->encoding.val,zz->encoding.len);
                   1118:        }
                   1119:        screen(SCR_AN,0,0l,f);
                   1120:        intmsg(filcnt);
                   1121: 
                   1122: #ifdef datageneral
                   1123: /* Need to turn on multi-tasking console interrupt task here, since multiple */
                   1124: /* files may be received. */
                   1125:         if ((local) && (!quiet))        /* Only do this if local & not quiet */
                   1126:             consta_mt();                /* Start the asynch read task */
                   1127: #endif
                   1128: 
                   1129:     } else {                           /* Did not open file OK. */
                   1130:         tlog(F110,"Failure to open",f,0L);
                   1131:        screen(SCR_EM,0,0l,"Can't open file");
                   1132:     }
                   1133:     return(x);                         /* Pass on return code from openo */
                   1134: }
                   1135: 
                   1136: /*  C A N N E D  --  Check if current file transfer cancelled */
                   1137: 
                   1138: int
                   1139: canned(buf) CHAR *buf; {
                   1140:     if (*buf == 'X') cxseen = 1;
                   1141:     if (*buf == 'Z') czseen = 1;
                   1142:     debug(F101,"canned: cxseen","",cxseen);
                   1143:     debug(F101," czseen","",czseen);
                   1144:     return((czseen || cxseen) ? 1 : 0);
                   1145: }
                   1146: 
                   1147: 
                   1148: /*  O P E N I  --  Open an existing file for input  */
                   1149: 
                   1150: int
                   1151: openi(name) char *name; {
                   1152:     int x, filno;
                   1153:     char *name2;
                   1154: 
                   1155:     if (memstr) return(1);             /* Just return if file is memory. */
                   1156: 
                   1157:     debug(F110,"openi",name,0);
                   1158:     debug(F101," sndsrc","",sndsrc);
                   1159: 
                   1160:     filno = (sndsrc == 0) ? ZSTDIO : ZIFILE;    /* ... */
                   1161: 
                   1162:     debug(F101," file number","",filno);
                   1163: 
                   1164:     if (server && !en_cwd) {           /* If running as server */
                   1165:        zstrip(name,&name2);            /* and CWD is disabled, */
                   1166:        if (strcmp(name,name2)) {       /* check if pathname was included. */
                   1167:            tlog(F110,name,"authorization failure",0L);
                   1168:            debug(F110," openi authorization failure",name,0);
                   1169:            return(0);
                   1170:        } else name = name2;
                   1171:     }
                   1172:     if (zopeni(filno,name)) {          /* Otherwise, try to open it. */
                   1173:        debug(F110," ok",name,0);
                   1174:        return(1);
                   1175:     } else {                           /* If not found, */
                   1176:        char xname[100];                /* convert the name */
                   1177:        zrtol(name,xname);              /* to local form and then */
                   1178:        x = zopeni(filno,xname);        /* try opening it again. */
                   1179:        debug(F101," zopeni","",x);
                   1180:        if (x) {
                   1181:            debug(F110," ok",xname,0);
                   1182:            return(1);                  /* It worked. */
                   1183:         } else {
                   1184:            screen(SCR_EM,0,0l,"Can't open file");  /* It didn't work. */
                   1185:            tlog(F110,xname,"could not be opened",0L);
                   1186:            debug(F110," openi failed",xname,0);
                   1187:            return(0);
                   1188:         }
                   1189:     }
                   1190: }
                   1191: 
                   1192: /*  O P E N O  --  Open a new file for output.  */
                   1193: 
                   1194: int
                   1195: openo(name,zz,fcb) char *name; struct zattr *zz; struct filinfo *fcb; {
                   1196:     char *name2;
                   1197: 
                   1198:     if (stdouf)                                /* Receiving to stdout? */
                   1199:       return(zopeno(ZSTDIO,"",zz,NULL));
                   1200: 
                   1201:     debug(F110,"openo: name",name,0);
                   1202: 
                   1203:     if (cxseen || czseen || discard) { /* If interrupted, get out before */
                   1204:        debug(F100," open cancelled","",0); /* destroying existing file. */
                   1205:        return(1);                      /* Pretend to succeed. */
                   1206:     }
                   1207:     if (server && !en_cwd) {           /* If running as server */
                   1208:        zstrip(name,&name2);            /* and CWD is disabled, */
                   1209:        if (strcmp(name,name2)) {       /* check if pathname was included. */
                   1210:            tlog(F110,name,"authorization failure",0L);
                   1211:            debug(F110," openo authorization failure",name,0);
                   1212:            return(0);
                   1213:        } else name = name2;
                   1214:     }
                   1215: 
                   1216:     if (zopeno(ZOFILE,name,zz,fcb) == 0) { /* Try to open the file */
                   1217:        debug(F110,"openo failed",name,0);
                   1218:        tlog(F110,"Failure to open",name,0L);
                   1219:        return(0);
                   1220:     } else {
                   1221:        debug(F110,"openo ok, name",name,0);
                   1222:        return(1);
                   1223:     }
                   1224: }
                   1225: 
                   1226: /*  O P E N T  --  Open the terminal for output, in place of a file  */
                   1227: 
                   1228: int
                   1229: opent(zz) struct zattr *zz; {
                   1230:     ffc = tfc = 0L;
                   1231:     return(zopeno(ZCTERM,"",zz,NULL));
                   1232: }
                   1233: 
                   1234: /*  C L S I F  --  Close the current input file. */
                   1235: 
                   1236: int
                   1237: clsif() {
                   1238:     int x = 0;
                   1239: #ifdef datageneral
                   1240:     if ((local) && (!quiet))    /* Only do this if local & not quiet */
                   1241:         if (nfils < 1)          /* More files to send ... leave it on! */
                   1242:             connoi_mt();
                   1243: #endif /* datageneral */
                   1244:     if (memstr) {                      /* If input was memory string, */
                   1245:        memstr = 0;                     /* indicate no more. */
                   1246:     } else x = zclose(ZIFILE);         /* else close input file. */
                   1247:     if (czseen || cxseen) 
                   1248:        screen(SCR_ST,ST_DISC,0l,"");
                   1249:     else
                   1250:        screen(SCR_ST,ST_OK,0l,"");
                   1251:     hcflg = 0;                         /* Reset flags, */
                   1252:     *filnam = '\0';                    /* and current file name */
                   1253:     return(x);
                   1254: }
                   1255: 
                   1256: 
                   1257: /*  C L S O F  --  Close an output file.  */
                   1258: 
                   1259: /*  Call with disp != 0 if file is to be discarded.  */
                   1260: /*  Returns -1 upon failure to close, 0 or greater on success. */
                   1261: 
                   1262: int
                   1263: clsof(disp) int disp; {
                   1264:     int x;
                   1265: 
                   1266:     debug(F101,"clsof disp","",disp);
                   1267:     if (bsavef) {                      /* If we saved global file type */
                   1268:        debug(F101,"clsof restoring binary","",binary);
                   1269:        binary = bsave;                 /* restore it */
                   1270:        bsavef = 0;                     /* only this once. */
                   1271:     }
                   1272: #ifdef datageneral
                   1273:     if ((local) && (!quiet))           /* Only do this if local & not quiet */
                   1274:         connoi_mt();
                   1275: #endif
                   1276:     if ((x = zclose(ZOFILE)) < 0) {    /* Try to close the file */
                   1277:        tlog(F100,"Failure to close",filnam,0L);
                   1278:        screen(SCR_ST,ST_ERR,0l,"");
                   1279:     } else if (disp && (keep == 0)) {  /* Delete it if interrupted, */
                   1280:        if (*filnam) zdelet(filnam);    /* and not keeping incomplete files */
                   1281:        debug(F100,"Discarded","",0);
                   1282:        tlog(F100,"Discarded","",0L);
                   1283:        screen(SCR_ST,ST_DISC,0l,"");
                   1284:     } else {                           /* Nothing wrong, just keep it */
                   1285:        debug(F100,"Closed","",0);      /* and give comforting messages. */
                   1286:        screen(SCR_ST,ST_OK,0l,"");
                   1287:     }
                   1288:     return(x);                         /* Send back zclose() return code. */
                   1289: }
                   1290: 
                   1291: #ifdef SUNOS4S5
                   1292: tolower(c) char c; { return((c)-'A'+'a'); }
                   1293: toupper(c) char c; { return((c)-'a'+'A'); }
                   1294: #endif /* SUNOS4S5 */
                   1295: 

unix.superglobalmegacorp.com

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