1: #define VERSION "sz 3.07 2-02-90" 2: #define PUBDIR "/usr/spool/uucppublic" 3: 4: /*% cc -compat -M2 -Ox -K -i -DTXBSIZE=16384 -DNFGVMIN -DREADCHECK sz.c -lx -o sz; size sz 5: 6: /*% cc -Zi -DXX -DNFGVMIN -DREADCHECK sz.c -lx -o xsz; size xsz 7: <-xtx-*> cc -Osal -DTXBSIZE=32768 -DSV sz.c -lx -o $B/sz; size $B/sz 8: 9: **************************************************************************** 10: * 11: * sz.c By Chuck Forsberg, Omen Technology INC 12: * 13: **************************************************************************** 14: * 15: * Typical Unix/Xenix/Clone compiles: 16: * 17: * cc -O sz.c -o sz USG (SYS III/V) Unix 18: * cc -O -DSV sz.c -o sz Sys V Release 2 with non-blocking input 19: * Define to allow reverse channel checking 20: * cc -O -DV7 sz.c -o sz Unix Version 7, 2.8 - 4.3 BSD 21: * 22: * cc -O -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz Classic Xenix 23: * 24: * ln sz sb **** All versions **** 25: * ln sz sx **** All versions **** 26: * 27: **************************************************************************** 28: * 29: * Typical VMS compile and install sequence: 30: * 31: * define LNK$LIBRARY SYS$LIBRARY:VAXCRTL.OLB 32: * cc sz.c 33: * cc vvmodem.c 34: * link sz,vvmodem 35: * sz :== $disk$user2:[username.subdir]sz.exe 36: * 37: * If you feel adventureous, remove the #define BADSEEK line 38: * immediately following the #ifdef vax11c line! Some VMS 39: * systems know how to fseek, some don't. 40: * 41: **************************************************************************** 42: * 43: * 44: * A program for Unix to send files and commands to computers running 45: * Professional-YAM, PowerCom, YAM, IMP, or programs supporting Y/XMODEM. 46: * 47: * Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM. 48: * 49: * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin 50: * 51: * 52: * This version implements numerous enhancements including ZMODEM 53: * Run Length Encoding and variable length headers. These 54: * features were not funded by the original Telenet development 55: * contract. 56: * 57: * This software may be freely used for non commercial and 58: * educational (didactic only) purposes. This software may also 59: * be freely used to support file transfer operations to or from 60: * licensed Omen Technology products. Any programs which use 61: * part or all of this software must be provided in source form 62: * with this notice intact except by written permission from Omen 63: * Technology Incorporated. 64: * 65: * Use of this software for commercial or administrative purposes 66: * except when exclusively limited to interfacing Omen Technology 67: * products requires a per port license payment of $20.00 US per 68: * port (less in quantity). Use of this code by inclusion, 69: * decompilation, reverse engineering or any other means 70: * constitutes agreement to these conditions and acceptance of 71: * liability to license the materials and payment of reasonable 72: * legal costs necessary to enforce this license agreement. 73: * 74: * 75: * Omen Technology Inc FAX: 503-621-3745 76: * Post Office Box 4681 77: * Portland OR 97208 78: * 79: * This code is made available in the hope it will be useful, 80: * BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY 81: * DAMAGES OF ANY KIND. 82: * 83: * 84: * 2.1x hacks to avoid VMS fseek() bogosity, allow input from pipe 85: * -DBADSEEK -DTXBSIZE=32768 86: * 2.x has mods for VMS flavor 87: * 88: * 1.34 implements tx backchannel garbage count and ZCRCW after ZRPOS 89: * in accordance with the 7-31-87 ZMODEM Protocol Description 90: */ 91: 92: #ifdef XX 93: #define XARGSFILE "args" 94: long Thisflen; 95: #endif 96: 97: char *substr(), *getenv(); 98: 99: #ifdef vax11c 100: #define STATIC 101: #define BADSEEK 102: #define TXBSIZE 32768 /* Must be power of two, < MAXINT */ 103: #include <types.h> 104: #include <stat.h> 105: #define STAT 106: #define LOGFILE "szlog.tmp" 107: #include <stdio.h> 108: #include <signal.h> 109: #include <setjmp.h> 110: #include <ctype.h> 111: #include <errno.h> 112: #define OS "VMS" 113: #define ROPMODE "r" 114: #define READCHECK 115: #define BUFWRITE 116: extern int errno; 117: #define SS_NORMAL SS$_NORMAL 118: #define xsendline(c) sendline(c) 119: 120: #ifndef PROGNAME 121: #define PROGNAME "sz" 122: #endif 123: 124: 125: #else /* vax11c */ 126: 127: #ifdef GENIE 128: #define STATIC static 129: #define LOGFILE "szlog" 130: #define BADSEEK 131: #define TXBSIZE 32768 /* Must be power of two, < MAXINT */ 132: #define OS "GEnie" 133: #define SS_NORMAL 0 134: #include <stdio.h> 135: #include <signal.h> 136: #include <setjmp.h> 137: #include <ctype.h> 138: #include <errno.h> 139: #include <stdlib.h> 140: #include <fildes.h> 141: FILDES fdes; 142: extern int errno; 143: int Binfile; 144: long Thisflen; 145: 146: #define sendline(c) putchar(c & 0377) 147: #define xsendline(c) putchar(c) 148: 149: #else /* GENIE */ 150: 151: #define LOGFILE "/tmp/szlog" 152: #define SS_NORMAL 0 153: #include <stdio.h> 154: #include <signal.h> 155: #include <setjmp.h> 156: #include <ctype.h> 157: #include <errno.h> 158: extern int errno; 159: #define STATIC 160: 161: #define sendline(c) putchar(c & 0377) 162: #define xsendline(c) putchar(c) 163: 164: #endif 165: #endif 166: 167: #define PATHLEN 256 168: #define OK 0 169: #define FALSE 0 170: #ifdef TRUE 171: #undef TRUE 172: #endif 173: #define TRUE 1 174: #define ERROR (-1) 175: /* Ward Christensen / CP/M parameters - Don't change these! */ 176: #define ENQ 005 177: #define CAN ('X'&037) 178: #define XOFF ('s'&037) 179: #define XON ('q'&037) 180: #define SOH 1 181: #define STX 2 182: #define EOT 4 183: #define ACK 6 184: #define NAK 025 185: #define CPMEOF 032 186: #define WANTCRC 0103 /* send C not NAK to get crc not checksum */ 187: #define WANTG 0107 /* Send G not NAK to get nonstop batch xmsn */ 188: #define TIMEOUT (-2) 189: #define RCDO (-3) 190: #define GCOUNT (-4) 191: #define RETRYMAX 10 192: 193: 194: #define HOWMANY 2 195: STATIC int Zmodem=0; /* ZMODEM protocol requested by receiver */ 196: unsigned Baudrate=4800; /* Default, set by first mode() call */ 197: STATIC unsigned Effbaud = 4800; 198: STATIC unsigned Txwindow; /* Control the size of the transmitted window */ 199: STATIC unsigned Txwspac; /* Spacing between zcrcq requests */ 200: STATIC unsigned Txwcnt; /* Counter used to space ack requests */ 201: STATIC long Lrxpos; /* Receiver's last reported offset */ 202: STATIC int errors; 203: 204: #ifdef vax11c 205: #include "vrzsz.c" /* most of the system dependent stuff here */ 206: #else 207: #ifdef GENIE 208: #include "genie.c" /* most of the system dependent stuff here */ 209: #else 210: #include "rbsb.c" /* most of the system dependent stuff here */ 211: #ifdef XX 212: #undef STAT 213: #endif 214: #endif 215: #endif 216: 217: #include "crctab.c" 218: 219: STATIC int Filesleft; 220: STATIC long Totalleft; 221: 222: /* 223: * Attention string to be executed by receiver to interrupt streaming data 224: * when an error is detected. A pause (0336) may be needed before the 225: * ^C (03) or after it. 226: */ 227: #ifdef READCHECK 228: STATIC char Myattn[] = { 0 }; 229: #else 230: #ifdef USG 231: STATIC char Myattn[] = { 03, 0336, 0 }; 232: #else 233: #ifndef GENIE 234: STATIC char Myattn[] = { 0 }; 235: #endif 236: #endif 237: #endif 238: 239: FILE *in; 240: 241: #ifdef BADSEEK 242: STATIC int Canseek = 0; /* 1: Can seek 0: only rewind -1: neither (pipe) */ 243: #ifndef TXBSIZE 244: #define TXBSIZE 16384 /* Must be power of two, < MAXINT */ 245: #endif 246: #else 247: STATIC int Canseek = 1; /* 1: Can seek 0: only rewind -1: neither (pipe) */ 248: #endif 249: 250: #ifdef TXBSIZE 251: #define TXBMASK (TXBSIZE-1) 252: STATIC char Txb[TXBSIZE]; /* Circular buffer for file reads */ 253: STATIC char *txbuf = Txb; /* Pointer to current file segment */ 254: #else 255: STATIC char txbuf[1024]; 256: #endif 257: STATIC long vpos = 0; /* Number of bytes read from file */ 258: 259: STATIC char Lastrx; 260: STATIC char Crcflg; 261: STATIC int Verbose=0; 262: STATIC int Modem2=0; /* XMODEM Protocol - don't send pathnames */ 263: STATIC int Restricted=0; /* restricted; no /.. or ../ in filenames */ 264: STATIC int Quiet=0; /* overrides logic that would otherwise set verbose */ 265: STATIC int Ascii=0; /* Add CR's for brain damaged programs */ 266: STATIC int Fullname=0; /* transmit full pathname */ 267: STATIC int Unlinkafter=0; /* Unlink file after it is sent */ 268: STATIC int Dottoslash=0; /* Change foo.bar.baz to foo/bar/baz */ 269: STATIC int firstsec; 270: STATIC int errcnt=0; /* number of files unreadable */ 271: STATIC int blklen=128; /* length of transmitted records */ 272: STATIC int Optiong; /* Let it rip no wait for sector ACK's */ 273: STATIC int Eofseen; /* EOF seen on input set by zfilbuf */ 274: STATIC int BEofseen; /* EOF seen on input set by fooseek */ 275: STATIC int Totsecs; /* total number of sectors this file */ 276: STATIC int Filcnt=0; /* count of number of files opened */ 277: STATIC int Lfseen=0; 278: STATIC unsigned Rxbuflen = 16384; /* Receiver's max buffer length */ 279: STATIC int Tframlen = 0; /* Override for tx frame length */ 280: STATIC int blkopt=0; /* Override value for zmodem blklen */ 281: STATIC int Rxflags = 0; 282: STATIC long bytcnt; 283: STATIC int Wantfcs32 = TRUE; /* want to send 32 bit FCS */ 284: STATIC char Lzconv; /* Local ZMODEM file conversion request */ 285: STATIC char Lzmanag; /* Local ZMODEM file management request */ 286: STATIC int Lskipnocor; 287: STATIC char Lztrans; 288: STATIC int Command; /* Send a command, then exit. */ 289: STATIC char *Cmdstr; /* Pointer to the command string */ 290: STATIC int Cmdtries = 11; 291: STATIC int Cmdack1; /* Rx ACKs command, then do it */ 292: STATIC int Exitcode; 293: STATIC int Test; /* 1= Force receiver to send Attn, etc with qbf. */ 294: /* 2= Character transparency test */ 295: STATIC char *qbf= 296: "The quick brown fox jumped over the lazy dog's back 1234567890\r\n"; 297: STATIC long Lastsync; /* Last offset to which we got a ZRPOS */ 298: STATIC int Beenhereb4; /* How many times we've been ZRPOS'd same place */ 299: 300: STATIC jmp_buf tohere; /* For the interrupt on RX timeout */ 301: STATIC jmp_buf intrjmp; /* For the interrupt on RX CAN */ 302: 303: #ifdef XARGSFILE 304: char * 305: mystrsave(s) 306: char *s; 307: { 308: register char *p; 309: char *malloc(); 310: 311: if (p = malloc(strlen(s)+1) ) { 312: strcpy(p, s); return p; 313: } 314: fprintf(stderr, "No memory for mystrsave!\n"); 315: exit(1); 316: } 317: 318: /* Remove (presumably) terminating CR and/or LF from string */ 319: uncrlf(s) 320: register char *s; 321: { 322: for ( ; *s; ++s) 323: switch (*s) { 324: case '\r': 325: case '\n': 326: *s = 0; return; 327: } 328: } 329: #endif 330: 331: 332: /* called by signal interrupt or terminate to clean things up */ 333: bibi(n) 334: { 335: canit(); fflush(stdout); mode(0); 336: fprintf(stderr, "sz: caught signal %d; exiting\n", n); 337: #ifndef GENIE 338: if (n == SIGQUIT) 339: abort(); 340: #endif 341: if (n == 99) 342: fprintf(stderr, "mode(2) in rbsb.c not implemented!!\n"); 343: cucheck(); 344: exit(128+n); 345: } 346: /* Called when ZMODEM gets an interrupt (^X) */ 347: onintr() 348: { 349: signal(SIGINT, SIG_IGN); 350: longjmp(intrjmp, -1); 351: } 352: 353: STATIC int Zctlesc; /* Encode control characters */ 354: STATIC int Nozmodem = 0; /* If invoked as "sb" */ 355: STATIC char *Progname = "sz"; 356: STATIC int Zrwindow = 1400; /* RX window size (controls garbage count) */ 357: #include "zm.c" 358: 359: #include "zmr.c" 360: 361: #ifdef XARGSFILE 362: #define XARGSMAX 256 363: char *xargv[XARGSMAX+1]; 364: #endif 365: 366: main(argc, argv) 367: char *argv[]; 368: { 369: register char *cp; 370: register npats; 371: int dm; 372: char **patts; 373: static char xXbuf[BUFSIZ]; 374: 375: if ((cp = getenv("ZNULLS")) && *cp) 376: Znulls = atoi(cp); 377: if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh"))) 378: Restricted=TRUE; 379: from_cu(); 380: #ifdef vax11c 381: chkinvok(PROGNAME); 382: #else 383: chkinvok(argv[0]); 384: #endif 385: 386: Rxtimeout = 600; 387: npats=0; 388: if (argc<2) 389: usage(); 390: setbuf(stdout, xXbuf); 391: while (--argc) { 392: cp = *++argv; 393: if (*cp++ == '-' && *cp) { 394: while ( *cp) { 395: switch(*cp++) { 396: case '\\': 397: *cp = toupper(*cp); continue; 398: case '+': 399: Lzmanag = ZMAPND; break; 400: #ifdef CSTOPB 401: case '2': 402: Twostop = TRUE; break; 403: #endif 404: case 'a': 405: Lzconv = ZCNL; 406: Ascii = TRUE; break; 407: case 'b': 408: Lzconv = ZCBIN; break; 409: case 'C': 410: if (--argc < 1) { 411: usage(); 412: } 413: Cmdtries = atoi(*++argv); 414: break; 415: case 'i': 416: Cmdack1 = ZCACK1; 417: /* **** FALL THROUGH TO **** */ 418: case 'c': 419: if (--argc != 1) { 420: usage(); 421: } 422: Command = TRUE; 423: Cmdstr = *++argv; 424: break; 425: case 'd': 426: ++Dottoslash; 427: /* **** FALL THROUGH TO **** */ 428: case 'f': 429: Fullname=TRUE; break; 430: case 'e': 431: Zctlesc = 1; break; 432: case 'k': 433: blklen=1024; break; 434: case 'L': 435: if (--argc < 1) { 436: usage(); 437: } 438: blkopt = atoi(*++argv); 439: if (blkopt<24 || blkopt>1024) 440: usage(); 441: break; 442: case 'l': 443: if (--argc < 1) { 444: usage(); 445: } 446: Tframlen = atoi(*++argv); 447: if (Tframlen<32 || Tframlen>1024) 448: usage(); 449: break; 450: case 'N': 451: Lzmanag = ZMNEWL; break; 452: case 'n': 453: Lzmanag = ZMNEW; break; 454: case 'o': 455: Wantfcs32 = FALSE; break; 456: case 'p': 457: Lzmanag = ZMPROT; break; 458: case 'r': 459: if (Lzconv == ZCRESUM) 460: Lzmanag = (Lzmanag & ZMMASK) | ZMCRC; 461: Lzconv = ZCRESUM; break; 462: case 'q': 463: Quiet=TRUE; Verbose=0; break; 464: case 't': 465: if (--argc < 1) { 466: usage(); 467: } 468: Rxtimeout = atoi(*++argv); 469: if (Rxtimeout<10 || Rxtimeout>1000) 470: usage(); 471: break; 472: case 'T': 473: if (++Test > 1) { 474: chartest(1); chartest(2); 475: mode(0); exit(SS_NORMAL); 476: } 477: break; 478: #ifndef vax11c 479: case 'u': 480: ++Unlinkafter; break; 481: #endif 482: case 'v': 483: ++Verbose; break; 484: case 'w': 485: if (--argc < 1) { 486: usage(); 487: } 488: Txwindow = atoi(*++argv); 489: if (Txwindow < 256) 490: Txwindow = 256; 491: Txwindow = (Txwindow/64) * 64; 492: Txwspac = Txwindow/4; 493: if (blkopt > Txwspac 494: || (!blkopt && Txwspac < 1024)) 495: blkopt = Txwspac; 496: break; 497: case 'X': 498: ++Modem2; break; 499: case 'Y': 500: Lskipnocor = TRUE; 501: /* **** FALLL THROUGH TO **** */ 502: case 'y': 503: Lzmanag = ZMCLOB; break; 504: case 'Z': 505: case 'z': 506: Lztrans = ZTRLE; break; 507: default: 508: usage(); 509: } 510: } 511: } 512: else if ( !npats && argc>0) { 513: if (argv[0][0]) { 514: npats=argc; 515: patts=argv; 516: } 517: } 518: } 519: if (npats < 1 && !Command && !Test) 520: usage(); 521: if (Verbose) { 522: if (freopen(LOGFILE, "a", stderr)==NULL) { 523: printf("Can't open log file %s\n",LOGFILE); 524: exit(0200); 525: } 526: setbuf(stderr, NULL); 527: } 528: if (Fromcu && !Quiet) { 529: if (Verbose == 0) 530: Verbose = 2; 531: } 532: vfile("%s %s for %s\n", Progname, VERSION, OS); 533: 534: #ifdef XARGSFILE 535: vfile("npats=%d *patts=%s", npats, *patts); 536: if (npats == 1 && !strcmp(XARGSFILE, *patts)) { 537: in = fopen(XARGSFILE, "r"); 538: if (!in) { 539: printf(stderr, "Can't open / control file!\n"); 540: exit(2); 541: } 542: for (npats=0,argv=patts=xargv; npats<XARGSMAX; ++npats,++argv) { 543: if (fgets(txbuf, 1024, in) <= 0) 544: break; 545: uncrlf(txbuf); 546: *argv = mystrsave(txbuf); 547: } 548: fclose(in); 549: } 550: #endif 551: 552: mode(1); 553: 554: #ifdef GENIE 555: signal(SIGINT, SIG_IGN); 556: #else 557: if (signal(SIGINT, bibi) == SIG_IGN) { 558: signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN); 559: } else { 560: signal(SIGINT, bibi); signal(SIGKILL, bibi); 561: } 562: #endif 563: #ifdef SIGQUIT 564: if ( !Fromcu) 565: signal(SIGQUIT, SIG_IGN); 566: #endif 567: #ifdef SIGTERM 568: signal(SIGTERM, bibi); 569: #endif 570: 571: if ( !Modem2) { 572: if (!Nozmodem) { 573: printf("rz\r"); fflush(stdout); 574: } 575: countem(npats, patts); 576: if (!Nozmodem) { 577: stohdr(0L); 578: if (Command) 579: Txhdr[ZF0] = ZCOMMAND; 580: zshhdr(4, ZRQINIT, Txhdr); 581: } 582: } 583: fflush(stdout); 584: 585: if (Command) { 586: if (getzrxinit()) { 587: Exitcode=0200; canit(); 588: } 589: else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) { 590: Exitcode=0200; canit(); 591: } 592: } else if (wcsend(npats, patts)==ERROR) { 593: Exitcode=0200; 594: canit(); 595: } 596: fflush(stdout); 597: mode(0); 598: dm = ((errcnt != 0) | Exitcode); 599: if (dm) { 600: cucheck(); 601: exit(dm); 602: } 603: exit(SS_NORMAL); 604: /*NOTREACHED*/ 605: } 606: 607: wcsend(argc, argp) 608: char *argp[]; 609: { 610: register n; 611: 612: Crcflg=FALSE; 613: firstsec=TRUE; 614: bytcnt = -1; 615: if (Nozmodem) { 616: printf("Start your YMODEM receive. "); fflush(stdout); 617: } 618: for (n=0; n<argc; ++n) { 619: Totsecs = 0; 620: if (wcs(argp[n])==ERROR) 621: return ERROR; 622: } 623: Totsecs = 0; 624: if (Filcnt==0) { /* bitch if we couldn't open ANY files */ 625: if (!Nozmodem && !Modem2) { 626: Command = TRUE; 627: Cmdstr = "echo \"sz: Can't open any requested files\""; 628: if (getnak()) { 629: Exitcode=0200; canit(); 630: } 631: if (!Zmodem) 632: canit(); 633: else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) { 634: Exitcode=0200; canit(); 635: } 636: Exitcode = 1; return OK; 637: } 638: canit(); 639: fprintf(stderr,"\r\nCan't open any requested files.\r\n"); 640: return ERROR; 641: } 642: if (Zmodem) 643: saybibi(); 644: else if ( !Modem2) 645: wctxpn(""); 646: return OK; 647: } 648: 649: wcs(oname) 650: char *oname; 651: { 652: register c; 653: register char *p, *q; 654: #ifdef STAT 655: struct stat f; 656: #endif 657: char name[PATHLEN]; 658: 659: strcpy(name, oname); 660: 661: #ifdef XARGSFILE 662: /* Parse GEniename:REALname:length pathname syntax */ 663: Thisflen = -1; 664: for (p = oname; *p; ++p) { 665: if (*p == ':') { 666: *p++ = 0; 667: q = p; 668: for (++p; *p; ++p) { 669: if (*p == ':') { 670: *p++ = 0; 671: Thisflen = atol(p); 672: break; 673: } 674: } 675: strcpy(name, q); 676: break; 677: } 678: } 679: #endif 680: 681: #ifdef GENIE 682: _describe(oname,&fdes); /* An undocumented goodie */ 683: if (fdes.type_file == 1) { /* Fortran Sequential Binary */ 684: Binfile = 1; 685: in = fopen(oname,"rB"); 686: } 687: else if (fdes.type_file == 0) { /* Ascii */ 688: Binfile = 0; 689: in = fopen(oname,"r"); 690: } 691: else { /* not a SL filetype */ 692: fprintf(stderr, "\nUnknown file type %d\n",fdes.type_file); 693: ++errcnt; 694: return OK; /* pass over it, there may be others */ 695: } 696: #else 697: if (Restricted) { 698: /* restrict pathnames to current tree or uucppublic */ 699: if ( substr(name, "../") 700: || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) { 701: canit(); 702: fprintf(stderr,"\r\nsz:\tSecurity Violation\r\n"); 703: return ERROR; 704: } 705: } 706: 707: in=fopen(oname, ROPMODE); 708: #endif 709: 710: if (in==NULL) { 711: ++errcnt; 712: return OK; /* pass over it, there may be others */ 713: } 714: BEofseen = Eofseen = 0; vpos = 0; 715: 716: #ifdef STAT 717: /* Check for directory or block special files */ 718: fstat(fileno(in), &f); 719: c = f.st_mode & S_IFMT; 720: if (c == S_IFDIR || c == S_IFBLK) { 721: fclose(in); 722: return OK; 723: } 724: #endif 725: 726: ++Filcnt; 727: switch (wctxpn(name)) { 728: case ERROR: 729: return ERROR; 730: case ZSKIP: 731: return OK; 732: } 733: #ifdef STAT 734: if (!Zmodem && wctx(f.st_size)==ERROR) 735: return ERROR; 736: #else 737: if (!Zmodem && wctx(1000000000L)==ERROR) 738: return ERROR; 739: #endif 740: 741: #ifndef vax11c 742: #ifndef GENIE 743: if (Unlinkafter) 744: unlink(oname); 745: #endif 746: #endif 747: 748: return 0; 749: } 750: 751: /* 752: * generate and transmit pathname block consisting of 753: * pathname (null terminated), 754: * file length, mode time and file mode in octal 755: * as provided by the Unix fstat call. 756: * N.B.: modifies the passed name, may extend it! 757: */ 758: wctxpn(name) 759: char *name; 760: { 761: register char *p, *q; 762: char name2[PATHLEN]; 763: #ifdef STAT 764: struct stat f; 765: #endif 766: 767: if (Modem2) { 768: #ifdef STAT 769: if (*name && fstat(fileno(in), &f)!= -1) { 770: fprintf(stderr, "Sending %s, %ld XMODEM blocks. ", 771: name, (127+f.st_size)>>7); 772: } 773: #endif 774: fprintf(stderr, "Give your local XMODEM receive command now.\r\n"); 775: fflush(stderr); 776: return OK; 777: } 778: zperr("Awaiting pathname nak for %s", *name?name:"<END>"); 779: if ( !Zmodem) 780: if (getnak()) 781: return ERROR; 782: 783: q = (char *) 0; 784: if (Dottoslash) { /* change . to . */ 785: for (p=name; *p; ++p) { 786: if (*p == '/') 787: q = p; 788: else if (*p == '.') 789: *(q=p) = '/'; 790: } 791: if (q && strlen(++q) > 8) { /* If name>8 chars */ 792: q += 8; /* make it .ext */ 793: strcpy(name2, q); /* save excess of name */ 794: *q = '.'; 795: strcpy(++q, name2); /* add it back */ 796: } 797: } 798: 799: for (p=name, q=txbuf ; *p; ) 800: if ((*q++ = *p++) == '/' && !Fullname) 801: q = txbuf; 802: *q++ = 0; 803: p=q; 804: while (q < (txbuf + 1024)) 805: *q++ = 0; 806: if (*name) { 807: #ifdef XX 808: if (Thisflen >= 0) { 809: sprintf(p, "%u 0 0 0 %d %ld", 810: Thisflen, Filesleft, Totalleft); 811: Totalleft -= Thisflen; 812: } 813: #endif 814: #ifdef GENIE 815: else 816: sprintf(p, "%d", fdes.current_file_size * 1260); 817: vfile("%s open Binfile=%d size=%ld", name, Binfile, 818: fdes.current_file_size * 1260); 819: #endif 820: 821: #ifdef STAT 822: #ifndef XX 823: if (fstat(fileno(in), &f)!= -1) 824: sprintf(p, "%lu %lo %o 0 %d %ld", f.st_size, f.st_mtime, 825: f.st_mode, Filesleft, Totalleft); 826: Totalleft -= f.st_size; 827: #endif 828: #endif 829: 830: } 831: if (--Filesleft <= 0) 832: Totalleft = 0; 833: if (Totalleft < 0) 834: Totalleft = 0; 835: 836: #ifdef STAT 837: /* force 1k blocks if name won't fit in 128 byte block */ 838: if (txbuf[125]) 839: blklen=1024; 840: else { /* A little goodie for IMP/KMD */ 841: txbuf[127] = (f.st_size + 127) >>7; 842: txbuf[126] = (f.st_size + 127) >>15; 843: } 844: #endif 845: if (Zmodem) 846: return zsendfile(txbuf, 1+strlen(p)+(p-txbuf)); 847: if (wcputsec(txbuf, 0, 128)==ERROR) 848: return ERROR; 849: return OK; 850: } 851: 852: getnak() 853: { 854: register firstch; 855: 856: Lastrx = 0; 857: for (;;) { 858: switch (firstch = readline(800)) { 859: case ZPAD: 860: if (getzrxinit()) 861: return ERROR; 862: Ascii = 0; /* Receiver does the conversion */ 863: return FALSE; 864: case TIMEOUT: 865: zperr("Timeout on pathname"); 866: return TRUE; 867: case WANTG: 868: #ifdef MODE2OK 869: mode(2); /* Set cbreak, XON/XOFF, etc. */ 870: #endif 871: Optiong = TRUE; 872: blklen=1024; 873: case WANTCRC: 874: Crcflg = TRUE; 875: case NAK: 876: return FALSE; 877: case CAN: 878: if ((firstch = readline(20)) == CAN && Lastrx == CAN) 879: return TRUE; 880: default: 881: break; 882: } 883: Lastrx = firstch; 884: } 885: } 886: 887: 888: wctx(flen) 889: long flen; 890: { 891: register int thisblklen; 892: register int sectnum, attempts, firstch; 893: long charssent; 894: 895: charssent = 0; firstsec=TRUE; thisblklen = blklen; 896: vfile("wctx:file length=%ld", flen); 897: 898: while ((firstch=readline(Rxtimeout))!=NAK && firstch != WANTCRC 899: && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN) 900: ; 901: if (firstch==CAN) { 902: zperr("Receiver CANcelled"); 903: return ERROR; 904: } 905: if (firstch==WANTCRC) 906: Crcflg=TRUE; 907: if (firstch==WANTG) 908: Crcflg=TRUE; 909: sectnum=0; 910: for (;;) { 911: if (flen <= (charssent + 896L)) 912: thisblklen = 128; 913: if ( !filbuf(txbuf, thisblklen)) 914: break; 915: if (wcputsec(txbuf, ++sectnum, thisblklen)==ERROR) 916: return ERROR; 917: charssent += thisblklen; 918: } 919: fclose(in); 920: attempts=0; 921: do { 922: purgeline(); 923: sendline(EOT); 924: flushmo(); 925: ++attempts; 926: } 927: while ((firstch=(readline(Rxtimeout)) != ACK) && attempts < RETRYMAX); 928: if (attempts == RETRYMAX) { 929: zperr("No ACK on EOT"); 930: return ERROR; 931: } 932: else 933: return OK; 934: } 935: 936: wcputsec(buf, sectnum, cseclen) 937: char *buf; 938: int sectnum; 939: int cseclen; /* data length of this sector to send */ 940: { 941: register checksum, wcj; 942: register char *cp; 943: unsigned oldcrc; 944: int firstch; 945: int attempts; 946: 947: firstch=0; /* part of logic to detect CAN CAN */ 948: 949: if (Verbose>2) 950: fprintf(stderr, "Sector %3d %2dk\n", Totsecs, Totsecs/8 ); 951: else if (Verbose>1) 952: fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs/8 ); 953: for (attempts=0; attempts <= RETRYMAX; attempts++) { 954: Lastrx= firstch; 955: sendline(cseclen==1024?STX:SOH); 956: sendline(sectnum); 957: sendline(-sectnum -1); 958: oldcrc=checksum=0; 959: for (wcj=cseclen,cp=buf; --wcj>=0; ) { 960: sendline(*cp); 961: oldcrc=updcrc((0377& *cp), oldcrc); 962: checksum += *cp++; 963: } 964: if (Crcflg) { 965: oldcrc=updcrc(0,updcrc(0,oldcrc)); 966: sendline((int)oldcrc>>8); 967: sendline((int)oldcrc); 968: } 969: else 970: sendline(checksum); 971: flushmo(); 972: 973: if (Optiong) { 974: firstsec = FALSE; return OK; 975: } 976: firstch = readline(Rxtimeout); 977: gotnak: 978: switch (firstch) { 979: case CAN: 980: if(Lastrx == CAN) { 981: cancan: 982: zperr("Cancelled"); return ERROR; 983: } 984: break; 985: case TIMEOUT: 986: zperr("Timeout on sector ACK"); continue; 987: case WANTCRC: 988: if (firstsec) 989: Crcflg = TRUE; 990: case NAK: 991: zperr("NAK on sector"); continue; 992: case ACK: 993: firstsec=FALSE; 994: Totsecs += (cseclen>>7); 995: return OK; 996: case ERROR: 997: zperr("Got burst for sector ACK"); break; 998: default: 999: zperr("Got %02x for sector ACK", firstch); break; 1000: } 1001: for (;;) { 1002: Lastrx = firstch; 1003: if ((firstch = readline(Rxtimeout)) == TIMEOUT) 1004: break; 1005: if (firstch == NAK || firstch == WANTCRC) 1006: goto gotnak; 1007: if (firstch == CAN && Lastrx == CAN) 1008: goto cancan; 1009: } 1010: } 1011: zperr("Retry Count Exceeded"); 1012: return ERROR; 1013: } 1014: 1015: /* fill buf with count chars padding with ^Z for CPM */ 1016: filbuf(buf, count) 1017: register char *buf; 1018: { 1019: register c, m; 1020: 1021: if ( !Ascii) { 1022: m = read(fileno(in), buf, count); 1023: if (m <= 0) 1024: return 0; 1025: while (m < count) 1026: buf[m++] = 032; 1027: return count; 1028: } 1029: m=count; 1030: if (Lfseen) { 1031: *buf++ = 012; --m; Lfseen = 0; 1032: } 1033: while ((c=getc(in))!=EOF) { 1034: if (c == 012) { 1035: *buf++ = 015; 1036: if (--m == 0) { 1037: Lfseen = TRUE; break; 1038: } 1039: } 1040: *buf++ =c; 1041: if (--m == 0) 1042: break; 1043: } 1044: if (m==count) 1045: return 0; 1046: else 1047: while (--m>=0) 1048: *buf++ = CPMEOF; 1049: return count; 1050: } 1051: 1052: /* Fill buffer with blklen chars */ 1053: zfilbuf() 1054: { 1055: int n; 1056: 1057: #ifdef TXBSIZE 1058: vfile("zfilbuf: bytcnt =%lu vpos=%lu blklen=%d", bytcnt, vpos, blklen); 1059: /* We assume request is within buffer, or just beyond */ 1060: txbuf = Txb + (bytcnt & TXBMASK); 1061: if (vpos <= bytcnt) { 1062: #ifdef GENIE 1063: if (Binfile) { 1064: long l, m; char *p; 1065: 1066: for (p=txbuf, n=0, l=blklen; l; l -= 128, p+= 128) { 1067: n += m = fgetb(p, 128, in); 1068: if (m == 0) 1069: break; 1070: } 1071: } else 1072: #endif 1073: n = fread(txbuf, 1, blklen, in); 1074: 1075: vpos += n; 1076: if (n < blklen) 1077: Eofseen = 1; 1078: vfile("zfilbuf: n=%d vpos=%lu Eofseen=%d", n, vpos, Eofseen); 1079: return n; 1080: } 1081: if (vpos >= (bytcnt+blklen)) 1082: return blklen; 1083: /* May be a short block if crash recovery etc. */ 1084: Eofseen = BEofseen; 1085: return (vpos - bytcnt); 1086: #else 1087: n = fread(txbuf, 1, blklen, in); 1088: if (n < blklen) 1089: Eofseen = 1; 1090: return n; 1091: #endif 1092: } 1093: 1094: #ifdef TXBSIZE 1095: /* Replacement for brain damaged fseek function. Returns 0==success */ 1096: fooseek(fptr, pos, whence) 1097: FILE *fptr; 1098: long pos; 1099: { 1100: long m, n; 1101: #ifdef GENIE 1102: long l, k; char *p; 1103: #endif 1104: 1105: vfile("fooseek: pos =%lu vpos=%lu Canseek=%d", pos, vpos, Canseek); 1106: /* Seek offset < current buffer */ 1107: if (pos < (vpos -TXBSIZE +1024)) { 1108: BEofseen = 0; 1109: if (Canseek > 0) { 1110: vpos = pos & ~TXBMASK; 1111: if (vpos >= pos) 1112: vpos -= TXBSIZE; 1113: if (fseek(fptr, vpos, 0)) 1114: return 1; 1115: } 1116: else if (Canseek == 0) { 1117: #ifdef GENIE 1118: if (Binfile) { 1119: if (fseekb(fptr, vpos = 0L, 0)) 1120: return 1; 1121: } else 1122: #endif 1123: if (fseek(fptr, vpos = 0L, 0)) 1124: return 1; 1125: } else 1126: return 1; 1127: while (vpos < pos) { 1128: #ifdef GENIE 1129: if (Binfile) { 1130: for (p=Txb,n=0,l=TXBSIZE; l; l -= 128,p+= 128) { 1131: n += (k = fgetb(p, 128, fptr)); 1132: vfile("bsk1: l=%d k=%d", l, k); 1133: if (k == 0) 1134: break; 1135: } 1136: } else 1137: #endif 1138: n = fread(Txb, 1, TXBSIZE, fptr); 1139: vpos += n; 1140: vfile("n=%d vpos=%ld", n, vpos); 1141: if (n < TXBSIZE) { 1142: BEofseen = 1; 1143: break; 1144: } 1145: } 1146: vfile("vpos=%ld", vpos); 1147: return 0; 1148: } 1149: /* Seek offset > current buffer (Crash Recovery, etc.) */ 1150: if (pos > vpos) { 1151: if (Canseek) 1152: if (fseek(fptr, vpos = (pos & ~TXBMASK), 0)) 1153: return 1; 1154: while (vpos <= pos) { 1155: txbuf = Txb + (vpos & TXBMASK); 1156: m = TXBSIZE - (vpos & TXBMASK); 1157: vfile("m=%ld vpos=%ld", m,vpos); 1158: #ifdef GENIE 1159: if (Binfile) { 1160: for (p=txbuf,n=0,l=m; l; l -= 128,p+= 128) { 1161: n += (k = fgetb(p, 128, fptr)); 1162: vfile("bsk2: l=%d k=%d n=%d", l, k, n); 1163: if (k == 0) 1164: break; 1165: } 1166: } else 1167: #endif 1168: n = fread(txbuf, 1, m, fptr); 1169: vfile("n=%ld vpos=%ld", n,vpos); 1170: vpos += n; 1171: vfile("bo=%d m=%ld vpos=%ld", txbuf-Txb,m,vpos); 1172: if (n < m) { 1173: BEofseen = 1; 1174: break; 1175: } 1176: } 1177: return 0; 1178: } 1179: /* Seek offset is within current buffer */ 1180: vfile("within buffer: vpos=%ld", vpos); 1181: return 0; 1182: } 1183: #define fseek fooseek 1184: #endif 1185: 1186: 1187: /* VARARGS1 */ 1188: vfile(f, a, b, c, d) 1189: long a, b, c, d; 1190: { 1191: if (Verbose > 2) { 1192: fprintf(stderr, f, a, b, c, d); 1193: fprintf(stderr, "\n"); 1194: } 1195: } 1196: 1197: 1198: alrm() 1199: { 1200: longjmp(tohere, -1); 1201: } 1202: 1203: 1204: #ifndef GENIE 1205: #ifndef vax11c 1206: /* 1207: * readline(timeout) reads character(s) from file descriptor 0 1208: * timeout is in tenths of seconds 1209: */ 1210: readline(timeout) 1211: { 1212: register int c; 1213: static char byt[1]; 1214: 1215: fflush(stdout); 1216: if (setjmp(tohere)) { 1217: zperr("TIMEOUT"); 1218: return TIMEOUT; 1219: } 1220: c = timeout/10; 1221: if (c<2) 1222: c=2; 1223: if (Verbose>5) { 1224: fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, c); 1225: } 1226: signal(SIGALRM, alrm); alarm(c); 1227: c=read(0, byt, 1); 1228: alarm(0); 1229: if (Verbose>5) 1230: fprintf(stderr, "ret %x\n", byt[0]); 1231: if (c<1) 1232: return TIMEOUT; 1233: return (byt[0]&0377); 1234: } 1235: 1236: flushmo() 1237: { 1238: fflush(stdout); 1239: } 1240: 1241: 1242: purgeline() 1243: { 1244: #ifdef USG 1245: ioctl(0, TCFLSH, 0); 1246: #else 1247: lseek(0, 0L, 2); 1248: #endif 1249: } 1250: #endif 1251: #endif 1252: 1253: /* send cancel string to get the other end to shut up */ 1254: canit() 1255: { 1256: static char canistr[] = { 1257: 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 1258: }; 1259: 1260: #ifdef vax11c 1261: raw_wbuf(strlen(canistr), canistr); 1262: purgeline(); 1263: #else 1264: printf(canistr); 1265: fflush(stdout); 1266: #endif 1267: } 1268: 1269: 1270: /* 1271: * Log an error 1272: */ 1273: /*VARARGS1*/ 1274: zperr(s,p,u) 1275: char *s, *p, *u; 1276: { 1277: if (Verbose <= 0) 1278: return; 1279: fprintf(stderr, "Retry %d: ", errors); 1280: fprintf(stderr, s, p, u); 1281: fprintf(stderr, "\n"); 1282: } 1283: 1284: /* 1285: * substr(string, token) searches for token in string s 1286: * returns pointer to token within string if found, NULL otherwise 1287: */ 1288: char * 1289: substr(s, t) 1290: register char *s,*t; 1291: { 1292: register char *ss,*tt; 1293: /* search for first char of token */ 1294: for (ss=s; *s; s++) 1295: if (*s == *t) 1296: /* compare token with substring */ 1297: for (ss=s,tt=t; ;) { 1298: if (*tt == 0) 1299: return s; 1300: if (*ss++ != *tt++) 1301: break; 1302: } 1303: return NULL; 1304: } 1305: 1306: char *babble[] = { 1307: #ifdef vax11c 1308: "Send file(s) with ZMODEM/YMODEM/XMODEM Protocol", 1309: " (Y) = Option applies to YMODEM only", 1310: " (Z) = Option applies to ZMODEM only", 1311: "Usage: sz [-2+abdefkLlNnquvwYy] [-] file ...", 1312: " sz [-2Ceqv] -c COMMAND", 1313: " \\ Force next option letter to upper case", 1314: " sb [-2adfkquv] [-] file ...", 1315: " sx [-2akquv] [-] file", 1316: #endif 1317: #ifndef vax11c 1318: "Send file(s) with ZMODEM/YMODEM/XMODEM Protocol", 1319: " (Y) = Option applies to YMODEM only", 1320: " (Z) = Option applies to ZMODEM only", 1321: "Usage: sz [-2+abdefkLlNnquvwYy] [-] file ...", 1322: " sz [-2Ceqv] -c COMMAND", 1323: " sb [-2adfkquv] [-] file ...", 1324: " sx [-2akquv] [-] file", 1325: #endif 1326: #ifdef CSTOPB 1327: " 2 Use 2 stop bits", 1328: #endif 1329: " + Append to existing destination file (Z)", 1330: " a (ASCII) change NL to CR/LF", 1331: " b Binary file transfer override", 1332: " c send COMMAND (Z)", 1333: #ifndef vax11c 1334: " d Change '.' to '/' in pathnames (Y/Z)", 1335: #endif 1336: " e Escape all control characters (Z)", 1337: " f send Full pathname (Y/Z)", 1338: " i send COMMAND, ack Immediately (Z)", 1339: " k Send 1024 byte packets (Y)", 1340: " L N Limit subpacket length to N bytes (Z)", 1341: " l N Limit frame length to N bytes (l>=L) (Z)", 1342: " n send file only if source newer (Z)", 1343: " N send file only if source newer or longer (Z)", 1344: " o Use 16 bit CRC instead of 32 bit CRC (Z)", 1345: " p Protect existing destination file (Z)", 1346: " r Resume/Recover interrupted file transfer (Z)", 1347: " q Quiet (no progress reports)", 1348: #ifndef vax11c 1349: " u Unlink (remove) file after transmission", 1350: #endif 1351: " v Verbose - provide debugging information", 1352: " w N restrict Window to N bytes (Z)", 1353: " Y Yes, overwrite existing file, skip if not present at rx (Z)", 1354: " y Yes, overwrite existing file (Z)", 1355: " Z Activate ZMODEM compression(Z)", 1356: "" 1357: }; 1358: 1359: usage() 1360: { 1361: char **pp; 1362: 1363: for (pp=babble; **pp; ++pp) 1364: fprintf(stderr, "%s\n", *pp); 1365: fprintf(stderr, "%s for %s by Chuck Forsberg, Omen Technology INC\n", 1366: VERSION, OS); 1367: fprintf(stderr, "\t\t\042The High Reliability Software\042\n"); 1368: cucheck(); 1369: exit(SS_NORMAL); 1370: } 1371: 1372: /* 1373: * Get the receiver's init parameters 1374: */ 1375: getzrxinit() 1376: { 1377: register n; 1378: #ifdef STAT 1379: struct stat f; 1380: #endif 1381: 1382: for (n=10; --n>=0; ) { 1383: 1384: switch (zgethdr(Rxhdr, 1)) { 1385: case ZCHALLENGE: /* Echo receiver's challenge numbr */ 1386: stohdr(Rxpos); 1387: zshhdr(4, ZACK, Txhdr); 1388: continue; 1389: case ZCOMMAND: /* They didn't see out ZRQINIT */ 1390: stohdr(0L); 1391: zshhdr(4, ZRQINIT, Txhdr); 1392: continue; 1393: case ZRINIT: 1394: Rxflags = 0377 & Rxhdr[ZF0]; 1395: Usevhdrs = Rxhdr[ZF1] & CANVHDR; 1396: Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32)); 1397: Zctlesc |= Rxflags & TESCCTL; 1398: Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8); 1399: if ( !(Rxflags & CANFDX)) 1400: Txwindow = 0; 1401: vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen); 1402: if ( !Fromcu) 1403: signal(SIGINT, SIG_IGN); 1404: #ifdef MODE2OK 1405: mode(2); /* Set cbreak, XON/XOFF, etc. */ 1406: #endif 1407: 1408: #ifndef READCHECK 1409: #ifndef USG 1410: #ifndef GENIE 1411: /* Use 1024 byte frames if no sample/interrupt */ 1412: if (Rxbuflen < 32 || Rxbuflen > 1024) { 1413: Rxbuflen = 1024; 1414: vfile("Rxbuflen=%d", Rxbuflen); 1415: } 1416: #endif 1417: #endif 1418: #endif 1419: 1420: /* Override to force shorter frame length */ 1421: if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32)) 1422: Rxbuflen = Tframlen; 1423: if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024)) 1424: Rxbuflen = Tframlen; 1425: vfile("Rxbuflen=%d", Rxbuflen); 1426: 1427: #ifndef GENIE 1428: #ifndef vax11c 1429: #ifdef STAT 1430: /* If using a pipe for testing set lower buf len */ 1431: fstat(0, &f); 1432: if ((f.st_mode & S_IFMT) != S_IFCHR) { 1433: Rxbuflen = 1024; 1434: } 1435: #endif 1436: #endif 1437: #endif 1438: 1439: #ifdef BADSEEK 1440: #ifdef GENIE 1441: if (Txwindow == 0) { 1442: Txwspac = (Txwindow = 4096)/4; 1443: } 1444: #else 1445: if (Txwindow == 0) 1446: Txwindow = TXBSIZE - 1024; 1447: Txwspac = TXBSIZE/4; 1448: #endif 1449: Canseek = 0; 1450: #endif 1451: 1452: /* 1453: * If input is not a regular file, force ACK's to 1454: * prevent running beyond the buffer limits 1455: */ 1456: #ifdef STAT 1457: if ( !Command) { 1458: fstat(fileno(in), &f); 1459: if ((f.st_mode & S_IFMT) != S_IFREG) { 1460: Canseek = -1; 1461: #ifdef TXBSIZE 1462: Txwindow = TXBSIZE - 1024; 1463: Txwspac = TXBSIZE/4; 1464: #else 1465: return ERROR; 1466: #endif 1467: } 1468: } 1469: #endif 1470: 1471: /* Set initial subpacket length */ 1472: if (blklen < 1024) { /* Command line override? */ 1473: if (Effbaud > 300) 1474: blklen = 256; 1475: if (Effbaud > 1200) 1476: blklen = 512; 1477: if (Effbaud > 2400) 1478: blklen = 1024; 1479: } 1480: if (Rxbuflen && blklen>Rxbuflen) 1481: blklen = Rxbuflen; 1482: if (blkopt && blklen > blkopt) 1483: blklen = blkopt; 1484: #ifdef GENIE 1485: blklen /= 128; blklen *= 128; 1486: if (blklen < 128) 1487: blklen = 128; 1488: #endif 1489: vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen); 1490: vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac); 1491: 1492: 1493: if (Lztrans == ZTRLE && (Rxflags & CANRLE)) 1494: Txfcs32 = 2; 1495: else 1496: Lztrans = 0; 1497: 1498: return (sendzsinit()); 1499: case ZCAN: 1500: case TIMEOUT: 1501: return ERROR; 1502: case ZRQINIT: 1503: if (Rxhdr[ZF0] == ZCOMMAND) 1504: continue; 1505: default: 1506: zshhdr(4, ZNAK, Txhdr); 1507: continue; 1508: } 1509: } 1510: return ERROR; 1511: } 1512: 1513: /* Send send-init information */ 1514: sendzsinit() 1515: { 1516: register c; 1517: 1518: if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL))) 1519: return OK; 1520: errors = 0; 1521: for (;;) { 1522: stohdr(0L); 1523: #ifdef ALTCANOFF 1524: Txhdr[ALTCOFF] = ALTCANOFF; 1525: #endif 1526: if (Zctlesc) { 1527: Txhdr[ZF0] |= TESCCTL; zshhdr(4, ZSINIT, Txhdr); 1528: } 1529: else 1530: zsbhdr(4, ZSINIT, Txhdr); 1531: zsdata(Myattn, ZATTNLEN, ZCRCW); 1532: c = zgethdr(Rxhdr, 1); 1533: switch (c) { 1534: case ZCAN: 1535: return ERROR; 1536: case ZACK: 1537: return OK; 1538: default: 1539: if (++errors > 19) 1540: return ERROR; 1541: continue; 1542: } 1543: } 1544: } 1545: 1546: /* Send file name and related info */ 1547: zsendfile(buf, blen) 1548: char *buf; 1549: { 1550: register c; 1551: register UNSL long crc; 1552: long lastcrcrq = -1; 1553: char *p; 1554: 1555: for (;;) { 1556: Txhdr[ZF0] = Lzconv; /* file conversion request */ 1557: Txhdr[ZF1] = Lzmanag; /* file management request */ 1558: if (Lskipnocor) 1559: Txhdr[ZF1] |= ZMSKNOLOC; 1560: Txhdr[ZF2] = Lztrans; /* file transport request */ 1561: Txhdr[ZF3] = 0; 1562: zsbhdr(4, ZFILE, Txhdr); 1563: zsdata(buf, blen, ZCRCW); 1564: again: 1565: c = zgethdr(Rxhdr, 1); 1566: switch (c) { 1567: case ZRINIT: 1568: while ((c = readline(50)) > 0) 1569: if (c == ZPAD) { 1570: goto again; 1571: } 1572: continue; 1573: case ZCAN: 1574: case TIMEOUT: 1575: case ZABORT: 1576: case ZFIN: 1577: default: 1578: return ERROR; 1579: case ZCRC: 1580: if (Rxpos != lastcrcrq) { 1581: lastcrcrq = Rxpos; 1582: crc = 0xFFFFFFFFL; 1583: if (Canseek >= 0) { 1584: fseek(in, 0L, 0); 1585: while (((c = getc(in)) != EOF) && --lastcrcrq) 1586: crc = UPDC32(c, crc); 1587: crc = ~crc; 1588: clearerr(in); /* Clear possible EOF */ 1589: lastcrcrq = Rxpos; 1590: } 1591: } 1592: stohdr(crc); 1593: zsbhdr(4, ZCRC, Txhdr); 1594: goto again; 1595: case ZFERR: 1596: case ZSKIP: 1597: fclose(in); return c; 1598: case ZRPOS: 1599: /* 1600: * Suppress zcrcw request otherwise triggered by 1601: * lastyunc==bytcnt 1602: */ 1603: #ifdef GENIE 1604: /* 1605: * Special case - turn on RLE if not archive, etc. 1606: * otherwise turn off RLE unless cmd line specified 1607: */ 1608: if (Rxflags & CANRLE) { /* RX can do it */ 1609: bytcnt = 0; 1610: zfilbuf(); 1611: vfile("txbuf012: %x %x %x", txbuf[0], txbuf[1], 1612: txbuf[2]); 1613: if ((txbuf[0] != 032) /* .ARC file */ 1614: && (txbuf[0] != 0x1f) /* .Z file */ 1615: && (txbuf[0] != 0x1c) /* .LHZ file */ 1616: && strncmp(txbuf, "ZOO", 3) 1617: && strncmp(txbuf, "GIF", 3) 1618: && (txbuf[2] != 3)) /* .ZIP file */ 1619: Txfcs32 = 2; 1620: else if ( !(Lztrans & ZTRLE)) 1621: Txfcs32 = 1; 1622: } 1623: /* GEnie binary can't seek to byte */ 1624: if (Binfile) { 1625: Rxpos &= ~127L; 1626: } 1627: #endif 1628: if (fseek(in, Rxpos, 0)) 1629: return ERROR; 1630: Lastsync = (bytcnt = Txpos = Lrxpos = Rxpos) -1; 1631: return zsendfdata(); 1632: } 1633: } 1634: } 1635: 1636: /* Send the data in the file */ 1637: zsendfdata() 1638: { 1639: register c, e, n; 1640: register newcnt; 1641: register long tcount = 0; 1642: int junkcount; /* Counts garbage chars received by TX */ 1643: static int tleft = 6; /* Counter for test mode */ 1644: 1645: junkcount = 0; 1646: Beenhereb4 = FALSE; 1647: somemore: 1648: if (setjmp(intrjmp)) { 1649: waitack: 1650: junkcount = 0; 1651: c = getinsync(0); 1652: gotack: 1653: switch (c) { 1654: default: 1655: case ZCAN: 1656: fclose(in); 1657: return ERROR; 1658: case ZSKIP: 1659: fclose(in); 1660: return c; 1661: case ZACK: 1662: case ZRPOS: 1663: break; 1664: case ZRINIT: 1665: return OK; 1666: } 1667: #ifdef READCHECK 1668: /* 1669: * If the reverse channel can be tested for data, 1670: * this logic may be used to detect error packets 1671: * sent by the receiver, in place of setjmp/longjmp 1672: * rdchk(fd) returns non 0 if a character is available 1673: */ 1674: while (rdchk(0)) { 1675: #ifdef EATSIT 1676: switch (checked) 1677: #else 1678: switch (readline(1)) 1679: #endif 1680: { 1681: case CAN: 1682: case ZPAD: 1683: c = getinsync(1); 1684: goto gotack; 1685: case XOFF: /* Wait a while for an XON */ 1686: case XOFF|0200: 1687: readline(100); 1688: } 1689: } 1690: #endif 1691: } 1692: 1693: if ( !Fromcu) 1694: signal(SIGINT, onintr); 1695: newcnt = Rxbuflen; 1696: Txwcnt = 0; 1697: stohdr(Txpos); 1698: zsbhdr(4, ZDATA, Txhdr); 1699: 1700: /* 1701: * Special testing mode. This should force receiver to Attn,ZRPOS 1702: * many times. Each time the signal should be caught, causing the 1703: * file to be started over from the beginning. 1704: */ 1705: if (Test) { 1706: if ( --tleft) 1707: while (tcount < 20000) { 1708: printf(qbf); fflush(stdout); 1709: tcount += strlen(qbf); 1710: #ifdef READCHECK 1711: while (rdchk(0)) { 1712: #ifdef EATSIT 1713: switch (checked) 1714: #else 1715: switch (readline(1)) 1716: #endif 1717: { 1718: case CAN: 1719: case ZPAD: 1720: #ifdef TCFLSH 1721: ioctl(0, TCFLSH, 1); 1722: #endif 1723: goto waitack; 1724: case XOFF: /* Wait for XON */ 1725: case XOFF|0200: 1726: readline(100); 1727: } 1728: } 1729: #endif 1730: } 1731: signal(SIGINT, SIG_IGN); canit(); 1732: sleep(3); purgeline(); mode(0); 1733: printf("\nsz: Tcount = %ld\n", tcount); 1734: if (tleft) { 1735: printf("ERROR: Interrupts Not Caught\n"); 1736: exit(1); 1737: } 1738: exit(SS_NORMAL); 1739: } 1740: 1741: do { 1742: n = zfilbuf(); 1743: if (Eofseen) 1744: e = ZCRCE; 1745: else if (junkcount > 3) 1746: e = ZCRCW; 1747: else if (bytcnt == Lastsync) 1748: e = ZCRCW; 1749: else if (Rxbuflen && (newcnt -= n) <= 0) 1750: e = ZCRCW; 1751: else if (Txwindow && (Txwcnt += n) >= Txwspac) { 1752: Txwcnt = 0; e = ZCRCQ; 1753: } else 1754: e = ZCRCG; 1755: if (Verbose>1) 1756: fprintf(stderr, "\r%7ld ZMODEM%s ", 1757: Txpos, Crc32t?" CRC-32":""); 1758: zsdata(txbuf, n, e); 1759: bytcnt = Txpos += n; 1760: if (e == ZCRCW) 1761: goto waitack; 1762: #ifdef READCHECK 1763: /* 1764: * If the reverse channel can be tested for data, 1765: * this logic may be used to detect error packets 1766: * sent by the receiver, in place of setjmp/longjmp 1767: * rdchk(fd) returns non 0 if a character is available 1768: */ 1769: fflush(stdout); 1770: while (rdchk(0)) { 1771: #ifdef EATSIT 1772: switch (checked) 1773: #else 1774: switch (readline(1)) 1775: #endif 1776: { 1777: case CAN: 1778: case ZPAD: 1779: c = getinsync(1); 1780: if (c == ZACK) 1781: break; 1782: #ifdef TCFLSH 1783: ioctl(0, TCFLSH, 1); 1784: #endif 1785: /* zcrce - dinna wanna starta ping-pong game */ 1786: zsdata(txbuf, 0, ZCRCE); 1787: goto gotack; 1788: case XOFF: /* Wait a while for an XON */ 1789: case XOFF|0200: 1790: readline(100); 1791: default: 1792: ++junkcount; 1793: } 1794: } 1795: #endif /* READCHECK */ 1796: if (Txwindow) { 1797: while ((tcount = (Txpos - Lrxpos)) >= Txwindow) { 1798: vfile("%ld window >= %u", tcount, Txwindow); 1799: if (e != ZCRCQ) 1800: zsdata(txbuf, 0, e = ZCRCQ); 1801: c = getinsync(1); 1802: if (c != ZACK) { 1803: #ifdef TCFLSH 1804: ioctl(0, TCFLSH, 1); 1805: #endif 1806: zsdata(txbuf, 0, ZCRCE); 1807: goto gotack; 1808: } 1809: } 1810: vfile("window = %ld", tcount); 1811: } 1812: } while (!Eofseen); 1813: if ( !Fromcu) 1814: signal(SIGINT, SIG_IGN); 1815: 1816: for (;;) { 1817: stohdr(Txpos); 1818: zsbhdr(4, ZEOF, Txhdr); 1819: switch (getinsync(0)) { 1820: case ZACK: 1821: continue; 1822: case ZRPOS: 1823: goto somemore; 1824: case ZRINIT: 1825: return OK; 1826: case ZSKIP: 1827: fclose(in); 1828: return c; 1829: default: 1830: fclose(in); 1831: return ERROR; 1832: } 1833: } 1834: } 1835: 1836: /* 1837: * Respond to receiver's complaint, get back in sync with receiver 1838: */ 1839: getinsync(flag) 1840: { 1841: register c; 1842: 1843: for (;;) { 1844: if (Test) { 1845: printf("\r\n\n\n***** Signal Caught *****\r\n"); 1846: Rxpos = 0; c = ZRPOS; 1847: } else 1848: c = zgethdr(Rxhdr, 0); 1849: switch (c) { 1850: case ZCAN: 1851: case ZABORT: 1852: case ZFIN: 1853: case TIMEOUT: 1854: return ERROR; 1855: case ZRPOS: 1856: /* ************************************* */ 1857: /* If sending to a buffered modem, you */ 1858: /* might send a break at this point to */ 1859: /* dump the modem's buffer. */ 1860: clearerr(in); /* In case file EOF seen */ 1861: if (fseek(in, Rxpos, 0)) 1862: return ERROR; 1863: Eofseen = 0; 1864: bytcnt = Lrxpos = Txpos = Rxpos; 1865: #ifndef GENIE 1866: if (Lastsync == Rxpos) { 1867: if (++Beenhereb4 > 4) 1868: if (blklen > 32) 1869: blklen /= 2; 1870: } 1871: #endif 1872: Lastsync = Rxpos; 1873: return c; 1874: case ZACK: 1875: Lrxpos = Rxpos; 1876: if (flag || Txpos == Rxpos) 1877: return ZACK; 1878: continue; 1879: case ZRINIT: 1880: case ZSKIP: 1881: fclose(in); 1882: return c; 1883: case ERROR: 1884: default: 1885: zsbhdr(4, ZNAK, Txhdr); 1886: continue; 1887: } 1888: } 1889: } 1890: 1891: 1892: /* Say "bibi" to the receiver, try to do it cleanly */ 1893: saybibi() 1894: { 1895: for (;;) { 1896: stohdr(0L); /* CAF Was zsbhdr - minor change */ 1897: zshhdr(4, ZFIN, Txhdr); /* to make debugging easier */ 1898: switch (zgethdr(Rxhdr, 0)) { 1899: case ZFIN: 1900: sendline('O'); sendline('O'); flushmo(); 1901: case ZCAN: 1902: case TIMEOUT: 1903: return; 1904: } 1905: } 1906: } 1907: 1908: /* Local screen character display function */ 1909: bttyout(c) 1910: { 1911: if (Verbose) 1912: putc(c, stderr); 1913: } 1914: 1915: /* Send command and related info */ 1916: zsendcmd(buf, blen) 1917: char *buf; 1918: { 1919: register c; 1920: long cmdnum; 1921: 1922: #ifdef GENIE 1923: cmdnum = 69; 1924: #else 1925: cmdnum = getpid(); 1926: #endif 1927: errors = 0; 1928: for (;;) { 1929: stohdr(cmdnum); 1930: Txhdr[ZF0] = Cmdack1; 1931: zsbhdr(4, ZCOMMAND, Txhdr); 1932: zsdata(buf, blen, ZCRCW); 1933: listen: 1934: Rxtimeout = 100; /* Ten second wait for resp. */ 1935: Usevhdrs = 0; /* Allow rx to send fixed len headers */ 1936: c = zgethdr(Rxhdr, 1); 1937: 1938: switch (c) { 1939: case ZRINIT: 1940: goto listen; /* CAF 8-21-87 */ 1941: case ERROR: 1942: case GCOUNT: 1943: case TIMEOUT: 1944: if (++errors > Cmdtries) 1945: return ERROR; 1946: continue; 1947: case ZCAN: 1948: case ZABORT: 1949: case ZFIN: 1950: case ZSKIP: 1951: case ZRPOS: 1952: return ERROR; 1953: default: 1954: if (++errors > 20) 1955: return ERROR; 1956: continue; 1957: case ZCOMPL: 1958: Exitcode = Rxpos; 1959: saybibi(); 1960: return OK; 1961: case ZRQINIT: 1962: #ifdef vax11c /* YAMP :== Yet Another Missing Primitive */ 1963: return ERROR; 1964: #else 1965: vfile("******** RZ *******"); 1966: system("rz"); 1967: vfile("******** SZ *******"); 1968: goto listen; 1969: #endif 1970: } 1971: } 1972: } 1973: 1974: /* 1975: * If called as sb use YMODEM protocol 1976: */ 1977: chkinvok(s) 1978: char *s; 1979: { 1980: register char *p; 1981: 1982: p = s; 1983: while (*p == '-') 1984: s = ++p; 1985: while (*p) 1986: if (*p++ == '/') 1987: s = p; 1988: if (*s == 'v') { 1989: Verbose=1; ++s; 1990: } 1991: Progname = s; 1992: if (s[0]=='s' && s[1]=='b') { 1993: Nozmodem = TRUE; blklen=1024; 1994: } 1995: if (s[0]=='s' && s[1]=='x') { 1996: Modem2 = TRUE; 1997: } 1998: } 1999: 2000: #ifdef STAT 2001: countem(argc, argv) 2002: register char **argv; 2003: { 2004: register c; 2005: struct stat f; 2006: 2007: for (Totalleft = 0, Filesleft = 0; --argc >=0; ++argv) { 2008: f.st_size = -1; 2009: if (Verbose>2) { 2010: fprintf(stderr, "\nCountem: %03d %s ", argc, *argv); 2011: fflush(stderr); 2012: } 2013: if (access(*argv, 04) >= 0 && stat(*argv, &f) >= 0) { 2014: c = f.st_mode & S_IFMT; 2015: if (c != S_IFDIR && c != S_IFBLK) { 2016: ++Filesleft; Totalleft += f.st_size; 2017: } 2018: } 2019: if (Verbose>2) 2020: fprintf(stderr, " %ld", f.st_size); 2021: } 2022: if (Verbose>2) 2023: fprintf(stderr, "\ncountem: Total %d %ld\n", 2024: Filesleft, Totalleft); 2025: } 2026: #else 2027: countem(argc, argv) 2028: register char **argv; 2029: { 2030: register c; 2031: register char *p; 2032: long size; 2033: 2034: for (Totalleft = 0, Filesleft = 0; --argc >=0; ++argv) { 2035: size = -1; 2036: if (Verbose>2) { 2037: fprintf(stderr, "\nCountem: %03d %s ", argc, *argv); 2038: fflush(stderr); 2039: } 2040: ++Filesleft; 2041: #ifdef XARGSFILE 2042: /* Look for file length in third colon sep field */ 2043: for (p = *argv; *p; ++p) { 2044: if (*p == ':') { 2045: for (++p; *p; ++p) { 2046: if (*p == ':') { 2047: ++p; 2048: size = atol(p); 2049: Totalleft += size; 2050: break; 2051: } 2052: } 2053: break; 2054: } 2055: } 2056: #endif 2057: 2058: if (Verbose>2) 2059: fprintf(stderr, " %ld", size); 2060: } 2061: if (Verbose>2) 2062: fprintf(stderr, "\ncountem: Total %d %ld\n", 2063: Filesleft, Totalleft); 2064: } 2065: #endif 2066: 2067: chartest(m) 2068: { 2069: register n; 2070: 2071: mode(m); 2072: printf("\r\n\nCharacter Transparency Test Mode %d\r\n", m); 2073: printf("If Pro-YAM/ZCOMM is not displaying ^M hit ALT-V NOW.\r\n"); 2074: printf("Hit Enter.\021"); fflush(stdout); 2075: readline(500); 2076: 2077: for (n = 0; n < 256; ++n) { 2078: if (!(n%8)) 2079: printf("\r\n"); 2080: printf("%02x ", n); fflush(stdout); 2081: sendline(n); flushmo(); 2082: printf(" "); fflush(stdout); 2083: if (n == 127) { 2084: printf("Hit Enter.\021"); fflush(stdout); 2085: readline(500); 2086: printf("\r\n"); fflush(stdout); 2087: } 2088: } 2089: printf("\021\r\nEnter Characters, echo is in hex.\r\n"); 2090: printf("Hit SPACE or pause 40 seconds for exit.\r\n"); 2091: 2092: while (n != TIMEOUT && n != ' ') { 2093: n = readline(400); 2094: printf("%02x\r\n", n); 2095: fflush(stdout); 2096: } 2097: printf("\r\nMode %d character transparency test ends.\r\n", m); 2098: fflush(stdout); 2099: } 2100: 2101: /* End of sz.c */