Annotation of coherent/e/bin/ckermit/ckcfn3.c, revision 1.1

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

unix.superglobalmegacorp.com

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