# 2.11BSD#431 - /usr/src/new/kermit5.188/ckcfn3.c

##### Functions

    adebu             X
    canned            X
    chkwin            X
    clsif             X
    clsof             X
    dumprbuf          X
    dumpsbuf          X
    freerbuf          X
    freerpkt          X
    freesbuf          X
    gattr             X
    getrbuf           X
    getreason         X
    getsbuf           X
    inibufs           X
    initattr          X
    makebuf           X
    mkrbuf            X
    mksbuf            X
    opena             X
    openi             X
    openo             X
    opent             X
    rsattr            X
    sattr             X
    tolower           X
    toupper           X
    window            X

##### Variables

    bigbufp           X
    bigrbsiz          X
    bigrbt            X
    bigrbuf           X
    bigsbsiz          X
    bigsbt            X
    bigsbuf           X
    dum001            X
    dum002            X
    dum003            X
    r_pkt             X
    rbufnum           X
    rbufuse           X
    rseqtbl           X
    s_pkt             X
    sacktbl           X
    sbufnum           X
    sbufuse           X
    sseqtbl           X
    winlo             X
    xbuf              X

##### Macros

    ABUFL             X
    DSBUFL            X
    DTBUFL            X
    FACTOR            X
    FTBUFL            X
    IDBUFL            X
    RPBUFL            X
    SPBUFL            X
    TSBUFL            X

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

#### Defined functions

adebu defined in line 1105; used 1 times

- in line 1150

canned defined in line 1248; never used
chkwin defined in line 475; used 4 times

- in /usr/src/new/kermit5.188/ckcfn2.c line 358, 466, 898, 1097

clsif defined in line 1362; used 1 times

- in /usr/src/new/kermit5.188/ckcfn2.c line 1204

clsof defined in line 1392; used 2 times

- in /usr/src/new/kermit5.188/ckcfn2.c line 1204
- in /usr/src/new/kermit5.188/ckcfns.c line 1243

dumprbuf defined in line 582; used 6 times

- in line 303
- in /usr/src/new/kermit5.188/ckcfn2.c line 254, 275, 281, 418-423(2)

dumpsbuf defined in line 528; used 4 times

- in line 302
- in /usr/src/new/kermit5.188/ckcfn2.c line 841, 1168
- in /usr/src/new/kermit5.188/ckcfns.c line 881

freerbuf defined in line 412; used 18 times

- in line 458
- in /usr/src/new/kermit5.188/ckcfn2.c line 949, 1290, 1315, 1329, 1338, 1349, 1362, 1384, 1404, 1423, 1444, 1462, 1468, 1484
- in /usr/src/new/kermit5.188/ckcfns.c line 1018, 1026, 1068

freerpkt defined in line 451; used 5 times

- in /usr/src/new/kermit5.188/ckcfn2.c line 366-370(2), 483, 496, 503

freesbuf defined in line 382; used 3 times

- in /usr/src/new/kermit5.188/ckcfn2.c line 484, 938, 951

gattr defined in line 788; never used
getrbuf defined in line 350; used 1 times

- in /usr/src/new/kermit5.188/ckcfn2.c line 1253

getreason defined in line 764; used 1 times

- in line 780

getsbuf defined in line 318; used 6 times

- in /usr/src/new/kermit5.188/ckcfn2.c line 903, 939, 985
- in /usr/src/new/kermit5.188/ckcfns.c line 878, 1046, 1478

inibufs defined in line 130; used 2 times

- in /usr/src/new/kermit5.188/ckcmai.c line 788
- in /usr/src/new/kermit5.188/ckuus3.c line 739

initattr defined in line 1066; never used
makebuf defined in line 219; used 2 times

- in line 257, 278

mkrbuf defined in line 274; used 2 times

- in line 299
- in /usr/src/new/kermit5.188/ckcfns.c line 882

mksbuf defined in line 253; used 2 times

- in line 298
- in /usr/src/new/kermit5.188/ckcfns.c line 876

opena defined in line 1143; never used
openi defined in line 1260; used 1 times

- in /usr/src/new/kermit5.188/ckcfns.c line 1314

openo defined in line 1312; used 1 times

- in line 1204

opent defined in line 1346; never used
rsattr defined in line 776; never used
sattr defined in line 638; never used
tolower defined in line 1433; never used
toupper defined in line 1434; never used
window defined in line 294; never used

#### Defined variables

bigbufp defined in line 128; used 6 times

- in line 156-158(3), 165, 187-191(2)

bigrbsiz defined in line 108; used 10 times

- in line 190-197(3), 278
- in /usr/src/new/kermit5.188/ckcfns.c line 2045, 2086
- in /usr/src/new/kermit5.188/ckuus3.c line 740, 1264
- in /usr/src/new/kermit5.188/ckuus4.c line 1399
- in /usr/src/new/kermit5.188/ckuus7.c line 1077

bigrbt defined in line 104; never used
bigrbuf defined in line 105; used 3 times

- in line 99, 191, 278

bigsbsiz defined in line 107; used 8 times

- in line 186-188(2), 196, 257
- in /usr/src/new/kermit5.188/ckcfns.c line 1720
- in /usr/src/new/kermit5.188/ckuus3.c line 742
- in /usr/src/new/kermit5.188/ckuus4.c line 1399
- in /usr/src/new/kermit5.188/ckuus7.c line 1103

bigsbt defined in line 101; never used
bigsbuf defined in line 103; used 2 times

- in line 187, 257

dum001 defined in line 76; never used
dum002 defined in line 80; used 1 times

- in line 355

dum003 defined in line 78; used 1 times

- in line 356

nreason defined in line 762; used 1 times

- in line 771

r_pkt defined in line 91; used 34 times

- in line 145-150(3), 278, 362, 425, 439-443(5), 600-606(7), 612-613(2)
- in /usr/src/new/kermit5.188/ckcfn2.c line 251-257(3), 1256, 1271-1279(4), 1286, 1382, 1485, 1491-1493(3)

rbufnum defined in line 79; used 12 times

- in line 277, 288, 353-366(6), 372, 431-432(2), 619

rbufuse defined in line 81; used 6 times

- in line 287, 360-361(2), 429-430(2), 599

reason defined in line 758; used 2 times

- in line 762, 771

refused defined in line 756; used 5 times

- in line 780-784(4), 1376

rseqtbl defined in line 83; used 13 times

- in line 284, 428, 455
- in /usr/src/new/kermit5.188/ckcfn2.c line 247-249(2), 316, 349, 929, 1480, 1490
- in /usr/src/new/kermit5.188/ckcfns.c line 1018, 1026, 1065

s_pkt defined in line 90; used 45 times

- in line 138-143(3), 257, 333-341(7), 402-407(6), 548-554(7), 560-563(3)
- in /usr/src/new/kermit5.188/ckcfn2.c line 383, 473, 508, 537, 746-748(3), 835, 934, 990, 1163-1174(4), 1191-1195(4)

sacktbl defined in line 84; used 7 times

- in line 264, 336
- in /usr/src/new/kermit5.188/ckcfn2.c line 396-397(2), 474, 486, 536

sbufnum defined in line 75; used 12 times

- in line 256, 268, 326-332(4), 342-346(2), 392, 574
- in /usr/src/new/kermit5.188/ckcfns.c line 1400-1401(2)

sbufuse defined in line 77; used 5 times

- in line 267, 330-331(2), 393, 547

sseqtbl defined in line 82; used 13 times

- in line 263, 335, 389-395(3)
- in /usr/src/new/kermit5.188/ckcfn2.c line 472, 506, 535, 741, 984-988(2), 1099
- in /usr/src/new/kermit5.188/ckcfns.c line 1043

winlo defined in line 73; used 57 times

- in line 574, 619
- in /usr/src/new/kermit5.188/ckcfn2.c line 247-252(5), 296-297(2), 309-318(5), 327-329(3), 341, 358, 384, 396-402(5), 416, 440, 451-456(3), 466-468(2), 485-488(5), 509, 521, 550, 890, 898, 921, 945-952(4), 965, 1097, 1298
- in /usr/src/new/kermit5.188/ckcfns.c line 875, 892, 1046, 1394-1395(2), 1425
- in /usr/src/new/kermit5.188/ckuusx.c line 758

xbuf defined in line 95; used 14 times

- in line 545, 556, 563-575(6), 597, 608-620(5)

#### Defined macros

ABUFL defined in line 792; used 4 times

- in line 793, 829, 904, 1014

DSBUFL defined in line 808; used 3 times

- in line 804, 958-961(2)

DTBUFL defined in line 796; used 2 times

- in line 797, 886

FACTOR defined in line 181; used 2 times

- in line 182-183(2)

FTBUFL defined in line 794; used 2 times

- in line 795, 837

IDBUFL defined in line 800; used 2 times

- in line 801, 988

RPBUFL defined in line 813; used 1 times

- in line 814

SPBUFL defined in line 810; used 3 times

- in line 806, 1000-1003(2)

TSBUFL defined in line 798; used 2 times

- in line 799, 913

Last modified: 1996-03-23 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3420 |