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