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