1 #define VERSION "sz 2.12 05-29-88" 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 Following is used for testing, might not be reasonable for production 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 BADSYNC 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 * 2.1x hacks to avoid VMS fseek() bogosity, allow input from pipe 52 * -DBADSEEK -DTXBSIZE=32768 53 * 2.x has mods for VMS flavor 54 * 55 * 1.34 implements tx backchannel garbage count and ZCRCW after ZRPOS 56 * in accordance with the 7-31-87 ZMODEM Protocol Description 57 */ 58 59 60 #include <sys/types.h> 61 62 #ifdef vax11c 63 #define BADSEEK 64 #define TXBSIZE 32768 /* Must be power of two, < MAXINT */ 65 #include <types.h> 66 #include <stat.h> 67 #define LOGFILE "szlog.tmp" 68 #define OS "VMS" 69 #define READCHECK 70 #define BUFWRITE 71 #define iofd 72 extern int errno; 73 #define SS_NORMAL SS$_NORMAL 74 #define xsendline(c) sendline(c) 75 76 77 #else /* vax11c */ 78 79 80 #define SS_NORMAL 0 81 #define LOGFILE "/tmp/szlog" 82 83 #define sendline(c) putchar((c) & 0377) 84 #define xsendline(c) putchar(c) 85 86 #endif 87 88 #include <signal.h> 89 #include <setjmp.h> 90 #include <ctype.h> 91 #include <errno.h> 92 #include <stdlib.h> 93 #include <string.h> 94 #include <stdlib.h> 95 #include <unistd.h> 96 #include <utime.h> 97 #include <stdio.h> 98 #include <stdarg.h> 99 100 #define PATHLEN 256 101 #define OK 0 102 #define FALSE 0 103 #define TRUE 1 104 #undef ERROR 105 #define ERROR (-1) 106 /* Ward Christensen / CP/M parameters - Don't change these! */ 107 #define ENQ 005 108 #define CAN ('X'&037) 109 #define XOFF ('s'&037) 110 #define XON ('q'&037) 111 #define SOH 1 112 #define STX 2 113 #define EOT 4 114 #define ACK 6 115 #define NAK 025 116 #define CPMEOF 032 117 #define WANTCRC 0103 /* send C not NAK to get crc not checksum */ 118 #define WANTG 0107 /* Send G not NAK to get nonstop batch xmsn */ 119 #define TIMEOUT (-2) 120 #define RCDO (-3) 121 #define RETRYMAX 10 122 123 124 #define HOWMANY 2 125 int Zmodem=0; /* ZMODEM protocol requested by receiver */ 126 unsigned Baudrate=2400; /* Default, should be set by first mode() call */ 127 unsigned Txwindow; /* Control the size of the transmitted window */ 128 unsigned Txwspac; /* Spacing between zcrcq requests */ 129 unsigned Txwcnt; /* Counter used to space ack requests */ 130 long Lrxpos; /* Receiver's last reported offset */ 131 int errors; 132 133 #ifdef vax11c 134 #include "vrzsz.c" /* most of the system dependent stuff here */ 135 #else 136 #include "rbsb.c" /* most of the system dependent stuff here */ 137 #endif 138 #include "crctab.c" 139 140 int Filesleft; 141 long Totalleft; 142 143 /* 144 * Attention string to be executed by receiver to interrupt streaming data 145 * when an error is detected. A pause (0336) may be needed before the 146 * ^C (03) or after it. 147 */ 148 #ifdef READCHECK 149 char Myattn[] = { 0 }; 150 #else 151 #ifdef USG 152 char Myattn[] = { 03, 0336, 0 }; 153 #else 154 char Myattn[] = { 0 }; 155 #endif 156 #endif 157 158 FILE *in; 159 160 #ifdef BADSEEK 161 int Canseek = 0; /* 1: Can seek 0: only rewind -1: neither (pipe) */ 162 #ifndef TXBSIZE 163 #define TXBSIZE 16384 /* Must be power of two, < MAXINT */ 164 #endif 165 #else 166 int Canseek = 1; /* 1: Can seek 0: only rewind -1: neither (pipe) */ 167 #endif 168 169 #ifdef TXBSIZE 170 #define TXBMASK (TXBSIZE-1) 171 char Txb[TXBSIZE]; /* Circular buffer for file reads */ 172 char *txbuf = Txb; /* Pointer to current file segment */ 173 #else 174 char txbuf[1024]; 175 #endif 176 long vpos = 0; /* Number of bytes read from file */ 177 178 char Lastrx; 179 char Crcflg; 180 int Verbose=0; 181 int Modem2=0; /* XMODEM Protocol - don't send pathnames */ 182 int Restricted=0; /* restricted; no /.. or ../ in filenames */ 183 int Quiet=0; /* overrides logic that would otherwise set verbose */ 184 int Ascii=0; /* Add CR's for brain damaged programs */ 185 int Fullname=0; /* transmit full pathname */ 186 int Unlinkafter=0; /* Unlink file after it is sent */ 187 int Dottoslash=0; /* Change foo.bar.baz to foo/bar/baz */ 188 int firstsec; 189 int errcnt=0; /* number of files unreadable */ 190 int blklen=128; /* length of transmitted records */ 191 int Optiong; /* Let it rip no wait for sector ACK's */ 192 int Eofseen; /* EOF seen on input set by zfilbuf */ 193 int BEofseen; /* EOF seen on input set by fooseek */ 194 int Totsecs; /* total number of sectors this file */ 195 int Filcnt=0; /* count of number of files opened */ 196 int Lfseen=0; 197 unsigned Rxbuflen = 16384; /* Receiver's max buffer length */ 198 int Tframlen = 0; /* Override for tx frame length */ 199 int blkopt=0; /* Override value for zmodem blklen */ 200 int Rxflags = 0; 201 long bytcnt; 202 int Wantfcs32 = TRUE; /* want to send 32 bit FCS */ 203 char Lzconv; /* Local ZMODEM file conversion request */ 204 char Lzmanag; /* Local ZMODEM file management request */ 205 int Lskipnocor; 206 char Lztrans; 207 char zconv; /* ZMODEM file conversion request */ 208 char zmanag; /* ZMODEM file management request */ 209 char ztrans; /* ZMODEM file transport request */ 210 int Command; /* Send a command, then exit. */ 211 char *Cmdstr; /* Pointer to the command string */ 212 int Cmdtries = 11; 213 int Cmdack1; /* Rx ACKs command, then do it */ 214 int Exitcode = 0; 215 int Test; /* 1= Force receiver to send Attn, etc with qbf. */ 216 /* 2= Character transparency test */ 217 char *qbf="The quick brown fox jumped over the lazy dog's back 1234567890\r\n"; 218 long Lastsync; /* Last offset to which we got a ZRPOS */ 219 int Beenhereb4; /* How many times we've been ZRPOS'd same place */ 220 221 jmp_buf tohere; /* For the interrupt on RX timeout */ 222 jmp_buf intrjmp; /* For the interrupt on RX CAN */ 223 224 void onintr(int sig ); 225 int main(int argc , char *argv []); 226 int wcsend(int argc , char *argp []); 227 int wcs(char *oname ); 228 int wctxpn(char *name ); 229 int getnak(void); 230 int wctx(long flen ); 231 int wcputsec(char *buf , int sectnum , int cseclen ); 232 int filbuf(char *buf , int count ); 233 int zfilbuf(void); 234 int fooseek(FILE *fptr , long pos , int whence ); 235 void alrm(int sig ); 236 int readline(int timeout ); 237 void flushmo(void); 238 void purgeline(void); 239 void canit(void); 240 void zperr(); 241 char *substr(char *s , char *t ); 242 int usage(void); 243 int getzrxinit(void); 244 int sendzsinit(void); 245 int zsendfile(char *buf , int blen ); 246 int zsendfdata(void); 247 int getinsync(int flag ); 248 void saybibi(void); 249 void bttyout(int c ); 250 int zsendcmd(char *buf , int blen ); 251 void chkinvok(char *s ); 252 void countem(int argc , char **argv ); 253 void chartest(int m ); 254 255 /* called by signal interrupt or terminate to clean things up */ 256 void bibi(int n) 257 { 258 canit(); fflush(stdout); mode(0); 259 fprintf(stderr, "sz: caught signal %d; exiting\n", n); 260 if (n == SIGQUIT) 261 abort(); 262 if (n == 99) 263 fprintf(stderr, "mode(2) in rbsb.c not implemented!!\n"); 264 cucheck(); 265 exit(128+n); 266 } 267 /* Called when ZMODEM gets an interrupt (^X) */ 268 void onintr(int sig) 269 { 270 signal(SIGINT, SIG_IGN); 271 longjmp(intrjmp, -1); 272 } 273 274 int Zctlesc; /* Encode control characters */ 275 int Nozmodem = 0; /* If invoked as "sb" */ 276 char *Progname = "sz"; 277 int Zrwindow = 1400; /* RX window size (controls garbage count) */ 278 #include "zm.c" 279 280 281 int main(int argc, char *argv[]) 282 { 283 register char *cp; 284 register int npats; 285 int dm; 286 char **patts; 287 static char xXbuf[BUFSIZ]; 288 289 if ((cp = getenv("ZNULLS")) && *cp) 290 Znulls = atoi(cp); 291 if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh"))) 292 Restricted=TRUE; 293 from_cu(); 294 chkinvok(argv[0]); 295 296 Rxtimeout = 600; 297 npats=0; 298 if (argc<2) 299 usage(); 300 setbuf(stdout, xXbuf); 301 while (--argc) { 302 cp = *++argv; 303 if (*cp++ == '-' && *cp) { 304 while ( *cp) { 305 switch(*cp++) { 306 case '\\': 307 *cp = toupper(*cp); continue; 308 case '+': 309 Lzmanag = ZMAPND; break; 310 #ifdef CSTOPB 311 case '2': 312 Twostop = TRUE; break; 313 #endif 314 case 'a': 315 Lzconv = ZCNL; 316 Ascii = TRUE; break; 317 case 'b': 318 Lzconv = ZCBIN; break; 319 case 'C': 320 if (--argc < 1) { 321 usage(); 322 } 323 Cmdtries = atoi(*++argv); 324 break; 325 case 'i': 326 Cmdack1 = ZCACK1; 327 /* **** FALL THROUGH TO **** */ 328 case 'c': 329 if (--argc != 1) { 330 usage(); 331 } 332 Command = TRUE; 333 Cmdstr = *++argv; 334 break; 335 case 'd': 336 ++Dottoslash; 337 /* **** FALL THROUGH TO **** */ 338 case 'f': 339 Fullname=TRUE; break; 340 case 'e': 341 Zctlesc = 1; break; 342 case 'k': 343 blklen=1024; break; 344 case 'L': 345 if (--argc < 1) { 346 usage(); 347 } 348 blkopt = atoi(*++argv); 349 if (blkopt<24 || blkopt>1024) 350 usage(); 351 break; 352 case 'l': 353 if (--argc < 1) { 354 usage(); 355 } 356 Tframlen = atoi(*++argv); 357 if (Tframlen<32 || Tframlen>1024) 358 usage(); 359 break; 360 case 'N': 361 Lzmanag = ZMNEWL; break; 362 case 'n': 363 Lzmanag = ZMNEW; break; 364 case 'o': 365 Wantfcs32 = FALSE; break; 366 case 'p': 367 Lzmanag = ZMPROT; break; 368 case 'r': 369 Lzconv = ZCRESUM; 370 case 'q': 371 Quiet=TRUE; Verbose=0; break; 372 case 't': 373 if (--argc < 1) { 374 usage(); 375 } 376 Rxtimeout = atoi(*++argv); 377 if (Rxtimeout<10 || Rxtimeout>1000) 378 usage(); 379 break; 380 case 'T': 381 if (++Test > 1) { 382 chartest(1); chartest(2); 383 mode(0); exit(0); 384 } 385 break; 386 #ifndef vax11c 387 case 'u': 388 ++Unlinkafter; break; 389 #endif 390 case 'v': 391 ++Verbose; break; 392 case 'w': 393 if (--argc < 1) { 394 usage(); 395 } 396 Txwindow = atoi(*++argv); 397 if (Txwindow < 256) 398 Txwindow = 256; 399 Txwindow = (Txwindow/64) * 64; 400 Txwspac = Txwindow/4; 401 if (blkopt > Txwspac 402 || (!blkopt && Txwspac < 1024)) 403 blkopt = Txwspac; 404 break; 405 case 'X': 406 ++Modem2; break; 407 case 'Y': 408 Lskipnocor = TRUE; 409 /* **** FALLL THROUGH TO **** */ 410 case 'y': 411 Lzmanag = ZMCLOB; break; 412 default: 413 usage(); 414 } 415 } 416 } 417 else if ( !npats && argc>0) { 418 if (argv[0][0]) { 419 npats=argc; 420 patts=argv; 421 #ifndef vax11c 422 if ( !strcmp(*patts, "-")) 423 iofd = 1; 424 #endif 425 } 426 } 427 } 428 if (npats < 1 && !Command && !Test) 429 usage(); 430 if (Verbose) { 431 if (freopen(LOGFILE, "a", stderr)==NULL) { 432 printf("Can't open log file %s\n",LOGFILE); 433 exit(0200); 434 } 435 setbuf(stderr, (char *)NULL); 436 } 437 if (Fromcu && !Quiet) { 438 if (Verbose == 0) 439 Verbose = 2; 440 } 441 vfile("%s %s for %s\n", Progname, VERSION, OS); 442 443 mode(1); 444 445 if (signal(SIGINT, bibi) == SIG_IGN) { 446 signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN); 447 } else { 448 signal(SIGINT, bibi); signal(SIGKILL, bibi); 449 } 450 if ( !Fromcu) 451 signal(SIGQUIT, SIG_IGN); 452 signal(SIGTERM, bibi); 453 454 if ( !Modem2) { 455 if (!Nozmodem) { 456 printf("rz\r"); fflush(stdout); 457 } 458 countem(npats, patts); 459 if (!Nozmodem) { 460 stohdr(0L); 461 if (Command) 462 Txhdr[ZF0] = ZCOMMAND; 463 zshhdr(ZRQINIT, Txhdr); 464 } 465 } 466 fflush(stdout); 467 468 if (Command) { 469 if (getzrxinit()) { 470 Exitcode=0200; canit(); 471 } 472 else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) { 473 Exitcode=0200; canit(); 474 } 475 } else if (wcsend(npats, patts)==ERROR) { 476 Exitcode=0200; 477 canit(); 478 } 479 fflush(stdout); 480 mode(0); 481 dm = ((errcnt != 0) | Exitcode); 482 if (dm) { 483 cucheck(); exit(dm); 484 } 485 putc('\n',stderr); 486 exit(SS_NORMAL); 487 /*NOTREACHED*/ 488 } 489 490 int wcsend(int argc, char *argp[]) 491 { 492 register int n; 493 494 Crcflg=FALSE; 495 firstsec=TRUE; 496 bytcnt = -1; 497 for (n=0; n<argc; ++n) { 498 Totsecs = 0; 499 if (wcs(argp[n])==ERROR) 500 return ERROR; 501 } 502 Totsecs = 0; 503 if (Filcnt==0) { /* bitch if we couldn't open ANY files */ 504 if ( !Modem2) { 505 Command = TRUE; 506 Cmdstr = "echo \"sz: Can't open any requested files\""; 507 if (getnak()) { 508 Exitcode=0200; canit(); 509 } 510 if (!Zmodem) 511 canit(); 512 else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) { 513 Exitcode=0200; canit(); 514 } 515 Exitcode = 1; return OK; 516 } 517 canit(); 518 fprintf(stderr,"\r\nCan't open any requested files.\r\n"); 519 return ERROR; 520 } 521 if (Zmodem) 522 saybibi(); 523 else if ( !Modem2) 524 wctxpn(""); 525 return OK; 526 } 527 528 int wcs(char *oname) 529 { 530 register int c; 531 register char *p; 532 struct stat f; 533 char name[PATHLEN]; 534 535 strcpy(name, oname); 536 537 if (Restricted) { 538 /* restrict pathnames to current tree or uucppublic */ 539 if ( substr(name, "../") 540 || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) { 541 canit(); 542 fprintf(stderr,"\r\nsz:\tSecurity Violation\r\n"); 543 return ERROR; 544 } 545 } 546 547 if ( !strcmp(oname, "-")) { 548 if ((p = getenv("ONAME")) && *p) 549 strcpy(name, p); 550 else 551 sprintf(name, "s%d.sz", getpid()); 552 in = stdin; 553 } 554 else if ((in=fopen(oname, "r"))==NULL) { 555 ++errcnt; 556 return OK; /* pass over it, there may be others */ 557 } 558 BEofseen = Eofseen = 0; vpos = 0; 559 /* Check for directory or block special files */ 560 fstat(fileno(in), &f); 561 c = f.st_mode & S_IFMT; 562 if (c == S_IFDIR || c == S_IFBLK) { 563 fclose(in); 564 return OK; 565 } 566 567 ++Filcnt; 568 switch (wctxpn(name)) { 569 case ERROR: 570 return ERROR; 571 case ZSKIP: 572 return OK; 573 } 574 if (!Zmodem && wctx(f.st_size)==ERROR) 575 return ERROR; 576 #ifndef vax11c 577 if (Unlinkafter) 578 unlink(oname); 579 #endif 580 return 0; 581 } 582 583 /* 584 * generate and transmit pathname block consisting of 585 * pathname (null terminated), 586 * file length, mode time and file mode in octal 587 * as provided by the Unix fstat call. 588 * N.B.: modifies the passed name, may extend it! 589 */ 590 int wctxpn(char *name) 591 { 592 register char *p, *q; 593 char name2[PATHLEN]; 594 struct stat f; 595 596 if (Modem2) { 597 if ((in!=stdin) && *name && fstat(fileno(in), &f)!= -1) { 598 fprintf(stderr, "Sending %s, %lld blocks: ", 599 name, f.st_size>>7); 600 } 601 fprintf(stderr, "Give your local XMODEM receive command now.\r\n"); 602 return OK; 603 } 604 zperr("Awaiting pathname nak for %s", *name?name:"<END>"); 605 if ( !Zmodem) 606 if (getnak()) 607 return ERROR; 608 609 q = (char *) 0; 610 if (Dottoslash) { /* change . to . */ 611 for (p=name; *p; ++p) { 612 if (*p == '/') 613 q = p; 614 else if (*p == '.') 615 *(q=p) = '/'; 616 } 617 if (q && strlen(++q) > 8) { /* If name>8 chars */ 618 q += 8; /* make it .ext */ 619 strcpy(name2, q); /* save excess of name */ 620 *q = '.'; 621 strcpy(++q, name2); /* add it back */ 622 } 623 } 624 625 for (p=name, q=txbuf ; *p; ) 626 if ((*q++ = *p++) == '/' && !Fullname) 627 q = txbuf; 628 *q++ = 0; 629 p=q; 630 while (q < (txbuf + 1024)) 631 *q++ = 0; 632 if (!Ascii && (in!=stdin) && *name && fstat(fileno(in), &f)!= -1) 633 sprintf(p, "%llu %llo %o 0 %d %ld", f.st_size, f.st_mtime, 634 f.st_mode, Filesleft, Totalleft); 635 Totalleft -= f.st_size; 636 if (--Filesleft <= 0) 637 Totalleft = 0; 638 if (Totalleft < 0) 639 Totalleft = 0; 640 641 /* force 1k blocks if name won't fit in 128 byte block */ 642 if (txbuf[125]) 643 blklen=1024; 644 else { /* A little goodie for IMP/KMD */ 645 txbuf[127] = (f.st_size + 127) >>7; 646 txbuf[126] = (f.st_size + 127) >>15; 647 } 648 if (Zmodem) 649 return zsendfile(txbuf, 1+strlen(p)+(p-txbuf)); 650 if (wcputsec(txbuf, 0, 128)==ERROR) 651 return ERROR; 652 return OK; 653 } 654 655 int getnak() 656 { 657 register int firstch; 658 659 Lastrx = 0; 660 for (;;) { 661 switch (firstch = readline(800)) { 662 case ZPAD: 663 if (getzrxinit()) 664 return ERROR; 665 Ascii = 0; /* Receiver does the conversion */ 666 return FALSE; 667 case TIMEOUT: 668 zperr("Timeout on pathname"); 669 return TRUE; 670 case WANTG: 671 #ifdef MODE2OK 672 mode(2); /* Set cbreak, XON/XOFF, etc. */ 673 #endif 674 Optiong = TRUE; 675 blklen=1024; 676 case WANTCRC: 677 Crcflg = TRUE; 678 case NAK: 679 return FALSE; 680 case CAN: 681 if ((firstch = readline(20)) == CAN && Lastrx == CAN) 682 return TRUE; 683 default: 684 break; 685 } 686 Lastrx = firstch; 687 } 688 } 689 690 691 int wctx(long flen) 692 { 693 register int thisblklen; 694 register int sectnum, attempts, firstch; 695 long charssent; 696 697 charssent = 0; firstsec=TRUE; thisblklen = blklen; 698 vfile("wctx:file length=%ld", flen); 699 700 while ((firstch=readline(Rxtimeout))!=NAK && firstch != WANTCRC 701 && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN) 702 ; 703 if (firstch==CAN) { 704 zperr("Receiver CANcelled"); 705 return ERROR; 706 } 707 if (firstch==WANTCRC) 708 Crcflg=TRUE; 709 if (firstch==WANTG) 710 Crcflg=TRUE; 711 sectnum=0; 712 for (;;) { 713 if (flen <= (charssent + 896L)) 714 thisblklen = 128; 715 if ( !filbuf(txbuf, thisblklen)) 716 break; 717 if (wcputsec(txbuf, ++sectnum, thisblklen)==ERROR) 718 return ERROR; 719 charssent += thisblklen; 720 } 721 fclose(in); 722 attempts=0; 723 do { 724 purgeline(); 725 sendline(EOT); 726 fflush(stdout); 727 ++attempts; 728 } 729 while ((firstch = readline(Rxtimeout)) != ACK && 730 attempts < RETRYMAX); 731 if (attempts == RETRYMAX) { 732 zperr("No ACK on EOT"); 733 return ERROR; 734 } 735 else 736 return OK; 737 } 738 /** 739 * @param cseclen :data length of this sector to send 740 */ 741 int wcputsec(char *buf, int sectnum, int cseclen) 742 { 743 register int checksum, wcj; 744 register char *cp; 745 unsigned oldcrc; 746 int firstch; 747 int attempts; 748 749 firstch=0; /* part of logic to detect CAN CAN */ 750 751 if (Verbose>2) 752 fprintf(stderr, "Sector %3d %2dk\n", Totsecs, Totsecs/8 ); 753 else if (Verbose>1) 754 fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs/8 ); 755 for (attempts=0; attempts <= RETRYMAX; attempts++) { 756 Lastrx= firstch; 757 sendline(cseclen==1024?STX:SOH); 758 sendline(sectnum); 759 sendline(-sectnum -1); 760 oldcrc=checksum=0; 761 for (wcj=cseclen,cp=buf; --wcj>=0; ) { 762 sendline(*cp); 763 oldcrc=updcrc((0377& *cp), oldcrc); 764 checksum += *cp++; 765 } 766 if (Crcflg) { 767 oldcrc=updcrc(0,updcrc(0,oldcrc)); 768 sendline((int)oldcrc>>8); 769 sendline((int)oldcrc); 770 } 771 else 772 sendline(checksum); 773 774 if (Optiong) { 775 firstsec = FALSE; return OK; 776 } 777 firstch = readline(Rxtimeout); 778 gotnak: 779 switch (firstch) { 780 case CAN: 781 if(Lastrx == CAN) { 782 cancan: 783 zperr("Cancelled"); return ERROR; 784 } 785 break; 786 case TIMEOUT: 787 zperr("Timeout on sector ACK"); continue; 788 case WANTCRC: 789 if (firstsec) 790 Crcflg = TRUE; 791 case NAK: 792 zperr("NAK on sector"); continue; 793 case ACK: 794 firstsec=FALSE; 795 Totsecs += (cseclen>>7); 796 return OK; 797 case ERROR: 798 zperr("Got burst for sector ACK"); break; 799 default: 800 zperr("Got %02x for sector ACK", firstch); break; 801 } 802 for (;;) { 803 Lastrx = firstch; 804 if ((firstch = readline(Rxtimeout)) == TIMEOUT) 805 break; 806 if (firstch == NAK || firstch == WANTCRC) 807 goto gotnak; 808 if (firstch == CAN && Lastrx == CAN) 809 goto cancan; 810 } 811 } 812 zperr("Retry Count Exceeded"); 813 return ERROR; 814 } 815 816 /* fill buf with count chars padding with ^Z for CPM */ 817 int filbuf(char *buf, int count) 818 { 819 register int c, m; 820 821 if ( !Ascii) { 822 m = read(fileno(in), buf, count); 823 if (m <= 0) 824 return 0; 825 while (m < count) 826 buf[m++] = 032; 827 return count; 828 } 829 m=count; 830 if (Lfseen) { 831 *buf++ = 012; --m; Lfseen = 0; 832 } 833 while ((c=getc(in))!=EOF) { 834 if (c == 012) { 835 *buf++ = 015; 836 if (--m == 0) { 837 Lfseen = TRUE; break; 838 } 839 } 840 *buf++ =c; 841 if (--m == 0) 842 break; 843 } 844 if (m==count) 845 return 0; 846 else 847 while (--m>=0) 848 *buf++ = CPMEOF; 849 return count; 850 } 851 852 /* Fill buffer with blklen chars */ 853 int zfilbuf() 854 { 855 int n; 856 857 #ifdef TXBSIZE 858 /* We assume request is within buffer, or just beyond */ 859 txbuf = Txb + (bytcnt & TXBMASK); 860 if (vpos <= bytcnt) { 861 n = fread(txbuf, 1, blklen, in); 862 vpos += n; 863 if (n < blklen) 864 Eofseen = 1; 865 return n; 866 } 867 if (vpos >= (bytcnt+blklen)) 868 return blklen; 869 /* May be a short block if crash recovery etc. */ 870 Eofseen = BEofseen; 871 return (vpos - bytcnt); 872 #else 873 n = fread(txbuf, 1, blklen, in); 874 if (n < blklen) 875 Eofseen = 1; 876 return n; 877 #endif 878 } 879 880 #ifdef TXBSIZE 881 int fooseek(FILE *fptr, long pos, int whence) 882 { 883 int m, n; 884 885 vfile("fooseek: pos =%lu vpos=%lu Canseek=%d", pos, vpos, Canseek); 886 /* Seek offset < current buffer */ 887 if (pos < (vpos -TXBSIZE +1024)) { 888 BEofseen = 0; 889 if (Canseek > 0) { 890 vpos = pos & ~TXBMASK; 891 if (vpos >= pos) 892 vpos -= TXBSIZE; 893 if (fseek(fptr, vpos, 0)) 894 return 1; 895 } 896 else if (Canseek == 0) 897 if (fseek(fptr, vpos = 0L, 0)) 898 return 1; 899 else 900 return 1; 901 while (vpos <= pos) { 902 n = fread(Txb, 1, TXBSIZE, fptr); 903 vpos += n; 904 vfile("n=%d vpos=%ld", n, vpos); 905 if (n < TXBSIZE) { 906 BEofseen = 1; 907 break; 908 } 909 } 910 vfile("vpos=%ld", vpos); 911 return 0; 912 } 913 /* Seek offset > current buffer (crash recovery, etc.) */ 914 if (pos > vpos) { 915 if (Canseek) 916 if (fseek(fptr, vpos = (pos & ~TXBMASK), 0)) 917 return 1; 918 while (vpos <= pos) { 919 txbuf = Txb + (vpos & TXBMASK); 920 m = TXBSIZE - (vpos & TXBMASK); 921 n = fread(txbuf, 1, m, fptr); 922 vpos += n; 923 vfile("bo=%d n=%d vpos=%ld", txbuf-Txb, n, vpos); 924 if (m < n) { 925 BEofseen = 1; 926 break; 927 } 928 } 929 return 0; 930 } 931 /* Seek offset is within current buffer */ 932 vfile("vpos=%ld", vpos); 933 return 0; 934 } 935 #define fseek fooseek 936 #endif 937 938 void vfile(const char *string, ...) 939 { 940 if (Verbose > 2) { 941 va_list args; 942 va_start(args, string); 943 vfprintf(stderr, string, args); 944 va_end(args); 945 fprintf(stderr, "\n"); 946 } 947 } 948 949 950 void alrm(int sig) 951 { 952 longjmp(tohere, -1); 953 } 954 955 956 #ifndef vax11c 957 /* 958 * readline(timeout) reads character(s) from file descriptor 0 959 * timeout is in tenths of seconds 960 */ 961 int readline(int timeout) 962 { 963 register int c; 964 static char byt[1]; 965 966 fflush(stdout); 967 if (setjmp(tohere)) { 968 zperr("TIMEOUT"); 969 return TIMEOUT; 970 } 971 c = timeout/10; 972 if (c<2) 973 c=2; 974 if (Verbose>5) { 975 fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, c); 976 } 977 signal(SIGALRM, alrm); alarm(c); 978 c=read(iofd, byt, 1); 979 alarm(0); 980 if (Verbose>5) 981 fprintf(stderr, "ret %x\n", byt[0]); 982 if (c<1) 983 return TIMEOUT; 984 return (byt[0]&0377); 985 } 986 987 void flushmo() 988 { 989 fflush(stdout); 990 } 991 992 993 void purgeline() 994 { 995 #ifdef USG 996 ioctl(iofd, TCFLSH, 0); 997 #else 998 lseek(iofd, 0L, 2); 999 #endif 1000 } 1001 #endif 1002 1003 /* send cancel string to get the other end to shut up */ 1004 void canit() 1005 { 1006 static char canistr[] = { 1007 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 1008 }; 1009 1010 #ifdef vax11c 1011 raw_wbuf(strlen(canistr), canistr); 1012 purgeline(); 1013 #else 1014 printf("%s", canistr); 1015 fflush(stdout); 1016 #endif 1017 } 1018 1019 1020 /* 1021 * Log an error 1022 */ 1023 /*VARARGS1*/ 1024 void zperr(char *s, char *p, char *u) 1025 { 1026 if (Verbose <= 0) 1027 return; 1028 fprintf(stderr, "\nRetry %d: ", errors); 1029 fprintf(stderr, s, p, u); 1030 fprintf(stderr, "\n"); 1031 } 1032 1033 /* 1034 * substr(string, token) searches for token in string s 1035 * returns pointer to token within string if found, NULL otherwise 1036 */ 1037 char * 1038 substr(char *s, char *t) 1039 { 1040 register char *ss,*tt; 1041 /* search for first char of token */ 1042 for (ss=s; *s; s++) 1043 if (*s == *t) 1044 /* compare token with substring */ 1045 for (ss=s,tt=t; ;) { 1046 if (*tt == 0) 1047 return s; 1048 if (*ss++ != *tt++) 1049 break; 1050 } 1051 return (char *)NULL; 1052 } 1053 1054 char *babble[] = { 1055 #ifdef vax11c 1056 " Send file(s) with ZMODEM Protocol", 1057 "Usage: sz [-2+abdefkLlNnquvwYy] [-] file ...", 1058 " sz [-2Ceqv] -c COMMAND", 1059 " \\ Force next option letter to upper case", 1060 #else 1061 "Send file(s) with ZMODEM/YMODEM/XMODEM Protocol", 1062 " (Y) = Option applies to YMODEM only", 1063 " (Z) = Option applies to ZMODEM only", 1064 "Usage: sz [-2+abdefkLlNnquvwYy] [-] file ...", 1065 " sz [-2Ceqv] -c COMMAND", 1066 " sb [-2adfkquv] [-] file ...", 1067 " sx [-2akquv] [-] file", 1068 #endif 1069 #ifdef CSTOPB 1070 " 2 Use 2 stop bits", 1071 #endif 1072 " + Append to existing destination file (Z)", 1073 " a (ASCII) change NL to CR/LF", 1074 " b Binary file transfer override", 1075 " c send COMMAND (Z)", 1076 #ifndef vax11c 1077 " d Change '.' to '/' in pathnames (Y/Z)", 1078 #endif 1079 " e Escape all control characters (Z)", 1080 " f send Full pathname (Y/Z)", 1081 " i send COMMAND, ack Immediately (Z)", 1082 " k Send 1024 byte packets (Y)", 1083 " L N Limit subpacket length to N bytes (Z)", 1084 " l N Limit frame length to N bytes (l>=L) (Z)", 1085 " n send file if source newer (Z)", 1086 " N send file if source newer or longer (Z)", 1087 " o Use 16 bit CRC instead of 32 bit CRC (Z)", 1088 " p Protect existing destination file (Z)", 1089 " r Resume/Recover interrupted file transfer (Z)", 1090 " q Quiet (no progress reports)", 1091 #ifndef vax11c 1092 " u Unlink file after transmission", 1093 #endif 1094 " v Verbose - provide debugging information", 1095 " w N Window is N bytes (Z)", 1096 " Y Yes, overwrite existing file, skip if not present at rx (Z)", 1097 " y Yes, overwrite existing file (Z)", 1098 "- as pathname sends standard input as sPID.sz or environment ONAME", 1099 "" 1100 }; 1101 1102 int usage() 1103 { 1104 char **pp; 1105 1106 for (pp=babble; **pp; ++pp) 1107 fprintf(stderr, "%s\n", *pp); 1108 fprintf(stderr, "%s for %s by Chuck Forsberg, Omen Technology INC\n", 1109 VERSION, OS); 1110 fprintf(stderr, "\t\t\042The High Reliability Software\042\n"); 1111 cucheck(); 1112 exit(SS_NORMAL); 1113 } 1114 1115 /* 1116 * Get the receiver's init parameters 1117 */ 1118 int getzrxinit() 1119 { 1120 register int n; 1121 struct stat f; 1122 1123 for (n=10; --n>=0; ) { 1124 1125 switch (zgethdr(Rxhdr, 1)) { 1126 case ZCHALLENGE: /* Echo receiver's challenge numbr */ 1127 stohdr(Rxpos); 1128 zshhdr(ZACK, Txhdr); 1129 continue; 1130 case ZCOMMAND: /* They didn't see out ZRQINIT */ 1131 stohdr(0L); 1132 zshhdr(ZRQINIT, Txhdr); 1133 continue; 1134 case ZRINIT: 1135 Rxflags = 0377 & Rxhdr[ZF0]; 1136 Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32)); 1137 Zctlesc |= Rxflags & TESCCTL; 1138 Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8); 1139 if ( !(Rxflags & CANFDX)) 1140 Txwindow = 0; 1141 vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen); 1142 if ( !Fromcu) 1143 signal(SIGINT, SIG_IGN); 1144 #ifdef MODE2OK 1145 mode(2); /* Set cbreak, XON/XOFF, etc. */ 1146 #endif 1147 #ifndef READCHECK 1148 #ifndef USG 1149 /* Use 1024 byte frames if no sample/interrupt */ 1150 if (Rxbuflen < 32 || Rxbuflen > 1024) { 1151 Rxbuflen = 1024; 1152 vfile("Rxbuflen=%d", Rxbuflen); 1153 } 1154 #endif 1155 #endif 1156 /* Override to force shorter frame length */ 1157 if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32)) 1158 Rxbuflen = Tframlen; 1159 if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024)) 1160 Rxbuflen = Tframlen; 1161 vfile("Rxbuflen=%d", Rxbuflen); 1162 1163 #ifndef vax11c 1164 /* If using a pipe for testing set lower buf len */ 1165 fstat(iofd, &f); 1166 if ((f.st_mode & S_IFMT) != S_IFCHR) { 1167 Rxbuflen = 1024; 1168 } 1169 #endif 1170 #ifdef BADSEEK 1171 Canseek = 0; 1172 Txwindow = TXBSIZE - 1024; 1173 Txwspac = TXBSIZE/4; 1174 #endif 1175 /* 1176 * If input is not a regular file, force ACK's to 1177 * prevent running beyond the buffer limits 1178 */ 1179 if ( !Command) { 1180 fstat(fileno(in), &f); 1181 if ((f.st_mode & S_IFMT) != S_IFREG) { 1182 Canseek = -1; 1183 #ifdef TXBSIZE 1184 Txwindow = TXBSIZE - 1024; 1185 Txwspac = TXBSIZE/4; 1186 #else 1187 return ERROR; 1188 #endif 1189 } 1190 } 1191 /* Set initial subpacket length */ 1192 if (blklen < 1024) { /* Command line override? */ 1193 if (Baudrate > 300) 1194 blklen = 256; 1195 if (Baudrate > 1200) 1196 blklen = 512; 1197 if (Baudrate > 2400) 1198 blklen = 1024; 1199 } 1200 if (Rxbuflen && blklen>Rxbuflen) 1201 blklen = Rxbuflen; 1202 if (blkopt && blklen > blkopt) 1203 blklen = blkopt; 1204 vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen); 1205 vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac); 1206 1207 return (sendzsinit()); 1208 case ZCAN: 1209 case TIMEOUT: 1210 return ERROR; 1211 case ZRQINIT: 1212 if (Rxhdr[ZF0] == ZCOMMAND) 1213 continue; 1214 default: 1215 zshhdr(ZNAK, Txhdr); 1216 continue; 1217 } 1218 } 1219 return ERROR; 1220 } 1221 1222 /* Send send-init information */ 1223 int sendzsinit() 1224 { 1225 register int c; 1226 1227 if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL))) 1228 return OK; 1229 errors = 0; 1230 for (;;) { 1231 stohdr(0L); 1232 if (Zctlesc) { 1233 Txhdr[ZF0] |= TESCCTL; zshhdr(ZSINIT, Txhdr); 1234 } 1235 else 1236 zsbhdr(ZSINIT, Txhdr); 1237 zsdata(Myattn, 1+strlen(Myattn), ZCRCW); 1238 c = zgethdr(Rxhdr, 1); 1239 switch (c) { 1240 case ZCAN: 1241 return ERROR; 1242 case ZACK: 1243 return OK; 1244 default: 1245 if (++errors > 19) 1246 return ERROR; 1247 continue; 1248 } 1249 } 1250 } 1251 1252 /* Send file name and related info */ 1253 int zsendfile(char *buf, int blen) 1254 { 1255 register int c; 1256 register UNSL long crc; 1257 1258 for (;;) { 1259 Txhdr[ZF0] = Lzconv; /* file conversion request */ 1260 Txhdr[ZF1] = Lzmanag; /* file management request */ 1261 if (Lskipnocor) 1262 Txhdr[ZF1] |= ZMSKNOLOC; 1263 Txhdr[ZF2] = Lztrans; /* file transport request */ 1264 Txhdr[ZF3] = 0; 1265 zsbhdr(ZFILE, Txhdr); 1266 zsdata(buf, blen, ZCRCW); 1267 again: 1268 c = zgethdr(Rxhdr, 1); 1269 switch (c) { 1270 case ZRINIT: 1271 while ((c = readline(50)) > 0) 1272 if (c == ZPAD) { 1273 goto again; 1274 } 1275 /* **** FALL THRU TO **** */ 1276 default: 1277 continue; 1278 case ZCAN: 1279 case TIMEOUT: 1280 case ZABORT: 1281 case ZFIN: 1282 return ERROR; 1283 case ZCRC: 1284 crc = 0xFFFFFFFFL; 1285 if (Canseek >= 0) { 1286 while (((c = getc(in)) != EOF) && --Rxpos) 1287 crc = UPDC32(c, crc); 1288 crc = ~crc; 1289 clearerr(in); /* Clear EOF */ 1290 fseek(in, 0L, 0); 1291 } 1292 stohdr(crc); 1293 zsbhdr(ZCRC, Txhdr); 1294 goto again; 1295 case ZSKIP: 1296 fclose(in); return c; 1297 case ZRPOS: 1298 /* 1299 * Suppress zcrcw request otherwise triggered by 1300 * lastyunc==bytcnt 1301 */ 1302 if (Rxpos && fseek(in, Rxpos, 0)) 1303 return ERROR; 1304 Lastsync = (bytcnt = Txpos = Rxpos) -1; 1305 return zsendfdata(); 1306 } 1307 } 1308 } 1309 1310 /* Send the data in the file */ 1311 int zsendfdata() 1312 { 1313 register int c, e, n; 1314 register int newcnt; 1315 register long tcount = 0; 1316 int junkcount; /* Counts garbage chars received by TX */ 1317 static int tleft = 6; /* Counter for test mode */ 1318 1319 Lrxpos = 0; 1320 junkcount = 0; 1321 Beenhereb4 = FALSE; 1322 somemore: 1323 if (setjmp(intrjmp)) { 1324 waitack: 1325 junkcount = 0; 1326 c = getinsync(0); 1327 gotack: 1328 switch (c) { 1329 default: 1330 case ZCAN: 1331 fclose(in); 1332 return ERROR; 1333 case ZSKIP: 1334 fclose(in); 1335 return c; 1336 case ZACK: 1337 case ZRPOS: 1338 break; 1339 case ZRINIT: 1340 return OK; 1341 } 1342 #ifdef READCHECK 1343 /* 1344 * If the reverse channel can be tested for data, 1345 * this logic may be used to detect error packets 1346 * sent by the receiver, in place of setjmp/longjmp 1347 * rdchk(fdes) returns non 0 if a character is available 1348 */ 1349 while (rdchk(iofd)) { 1350 #ifdef SV 1351 switch (checked) 1352 #else 1353 switch (readline(1)) 1354 #endif 1355 { 1356 case CAN: 1357 case ZPAD: 1358 c = getinsync(1); 1359 goto gotack; 1360 case XOFF: /* Wait a while for an XON */ 1361 case XOFF|0200: 1362 readline(100); 1363 } 1364 } 1365 #endif 1366 } 1367 1368 if ( !Fromcu) 1369 signal(SIGINT, onintr); 1370 newcnt = Rxbuflen; 1371 Txwcnt = 0; 1372 stohdr(Txpos); 1373 zsbhdr(ZDATA, Txhdr); 1374 1375 /* 1376 * Special testing mode. This should force receiver to Attn,ZRPOS 1377 * many times. Each time the signal should be caught, causing the 1378 * file to be started over from the beginning. 1379 */ 1380 if (Test) { 1381 if ( --tleft) 1382 while (tcount < 20000) { 1383 printf("%s", qbf); fflush(stdout); 1384 tcount += strlen(qbf); 1385 #ifdef READCHECK 1386 while (rdchk(iofd)) { 1387 #ifdef SV 1388 switch (checked) 1389 #else 1390 switch (readline(1)) 1391 #endif 1392 { 1393 case CAN: 1394 case ZPAD: 1395 #ifdef TCFLSH 1396 ioctl(iofd, TCFLSH, 1); 1397 #endif 1398 goto waitack; 1399 case XOFF: /* Wait for XON */ 1400 case XOFF|0200: 1401 readline(100); 1402 } 1403 } 1404 #endif 1405 } 1406 signal(SIGINT, SIG_IGN); canit(); 1407 sleep(3); purgeline(); mode(0); 1408 printf("\nsz: Tcount = %ld\n", tcount); 1409 if (tleft) { 1410 printf("ERROR: Interrupts Not Caught\n"); 1411 exit(1); 1412 } 1413 exit(SS_NORMAL); 1414 } 1415 1416 do { 1417 n = zfilbuf(); 1418 if (Eofseen) 1419 e = ZCRCE; 1420 else if (junkcount > 3) 1421 e = ZCRCW; 1422 else if (bytcnt == Lastsync) 1423 e = ZCRCW; 1424 else if (Rxbuflen && (newcnt -= n) <= 0) 1425 e = ZCRCW; 1426 else if (Txwindow && (Txwcnt += n) >= Txwspac) { 1427 Txwcnt = 0; e = ZCRCQ; 1428 } 1429 else 1430 e = ZCRCG; 1431 if (Verbose>1) 1432 fprintf(stderr, "\r%7ld ZMODEM%s ", 1433 Txpos, Crc32t?" CRC-32":""); 1434 zsdata(txbuf, n, e); 1435 bytcnt = Txpos += n; 1436 if (e == ZCRCW) 1437 goto waitack; 1438 #ifdef READCHECK 1439 /* 1440 * If the reverse channel can be tested for data, 1441 * this logic may be used to detect error packets 1442 * sent by the receiver, in place of setjmp/longjmp 1443 * rdchk(fdes) returns non 0 if a character is available 1444 */ 1445 fflush(stdout); 1446 while (rdchk(iofd)) { 1447 #ifdef SV 1448 switch (checked) 1449 #else 1450 switch (readline(1)) 1451 #endif 1452 { 1453 case CAN: 1454 case ZPAD: 1455 c = getinsync(1); 1456 if (c == ZACK) 1457 break; 1458 #ifdef TCFLSH 1459 ioctl(iofd, TCFLSH, 1); 1460 #endif 1461 /* zcrce - dinna wanna starta ping-pong game */ 1462 zsdata(txbuf, 0, ZCRCE); 1463 goto gotack; 1464 case XOFF: /* Wait a while for an XON */ 1465 case XOFF|0200: 1466 readline(100); 1467 default: 1468 ++junkcount; 1469 } 1470 } 1471 #endif /* READCHECK */ 1472 if (Txwindow) { 1473 while ((tcount = Txpos - Lrxpos) >= Txwindow) { 1474 vfile("%ld window >= %u", tcount, Txwindow); 1475 if (e != ZCRCQ) 1476 zsdata(txbuf, 0, e = ZCRCQ); 1477 c = getinsync(1); 1478 if (c != ZACK) { 1479 #ifdef TCFLSH 1480 ioctl(iofd, TCFLSH, 1); 1481 #endif 1482 zsdata(txbuf, 0, ZCRCE); 1483 goto gotack; 1484 } 1485 } 1486 vfile("window = %ld", tcount); 1487 } 1488 } while (!Eofseen); 1489 if ( !Fromcu) 1490 signal(SIGINT, SIG_IGN); 1491 1492 for (;;) { 1493 stohdr(Txpos); 1494 zsbhdr(ZEOF, Txhdr); 1495 switch (getinsync(0)) { 1496 case ZACK: 1497 continue; 1498 case ZRPOS: 1499 goto somemore; 1500 case ZRINIT: 1501 return OK; 1502 case ZSKIP: 1503 fclose(in); 1504 return c; 1505 default: 1506 fclose(in); 1507 return ERROR; 1508 } 1509 } 1510 } 1511 1512 /* 1513 * Respond to receiver's complaint, get back in sync with receiver 1514 */ 1515 int getinsync(int flag) 1516 { 1517 register int c; 1518 1519 for (;;) { 1520 if (Test) { 1521 printf("\r\n\n\n***** Signal Caught *****\r\n"); 1522 Rxpos = 0; c = ZRPOS; 1523 } else 1524 c = zgethdr(Rxhdr, 0); 1525 switch (c) { 1526 case ZCAN: 1527 case ZABORT: 1528 case ZFIN: 1529 case TIMEOUT: 1530 return ERROR; 1531 case ZRPOS: 1532 /* ************************************* */ 1533 /* If sending to a buffered modem, you */ 1534 /* might send a break at this point to */ 1535 /* dump the modem's buffer. */ 1536 clearerr(in); /* In case file EOF seen */ 1537 if (fseek(in, Rxpos, 0)) 1538 return ERROR; 1539 Eofseen = 0; 1540 bytcnt = Lrxpos = Txpos = Rxpos; 1541 if (Lastsync == Rxpos) { 1542 if (++Beenhereb4 > 4) 1543 if (blklen > 32) 1544 blklen /= 2; 1545 } 1546 Lastsync = Rxpos; 1547 return c; 1548 case ZACK: 1549 Lrxpos = Rxpos; 1550 if (flag || Txpos == Rxpos) 1551 return ZACK; 1552 continue; 1553 case ZRINIT: 1554 case ZSKIP: 1555 fclose(in); 1556 return c; 1557 case ERROR: 1558 default: 1559 zsbhdr(ZNAK, Txhdr); 1560 continue; 1561 } 1562 } 1563 } 1564 1565 1566 /* Say "bibi" to the receiver, try to do it cleanly */ 1567 void saybibi() 1568 { 1569 for (;;) { 1570 stohdr(0L); /* CAF Was zsbhdr - minor change */ 1571 zshhdr(ZFIN, Txhdr); /* to make debugging easier */ 1572 switch (zgethdr(Rxhdr, 0)) { 1573 case ZFIN: 1574 sendline('O'); sendline('O'); flushmo(); 1575 case ZCAN: 1576 case TIMEOUT: 1577 return; 1578 } 1579 } 1580 } 1581 1582 /* Local screen character display function */ 1583 void bttyout(int c) 1584 { 1585 if (Verbose) 1586 putc(c, stderr); 1587 } 1588 1589 /* Send command and related info */ 1590 int zsendcmd(char *buf, int blen) 1591 { 1592 register int c; 1593 long cmdnum; 1594 1595 cmdnum = getpid(); 1596 errors = 0; 1597 for (;;) { 1598 stohdr(cmdnum); 1599 Txhdr[ZF0] = Cmdack1; 1600 zsbhdr(ZCOMMAND, Txhdr); 1601 zsdata(buf, blen, ZCRCW); 1602 listen: 1603 Rxtimeout = 100; /* Ten second wait for resp. */ 1604 c = zgethdr(Rxhdr, 1); 1605 1606 switch (c) { 1607 case ZRINIT: 1608 goto listen; /* CAF 8-21-87 */ 1609 case ERROR: 1610 case TIMEOUT: 1611 if (++errors > Cmdtries) 1612 return ERROR; 1613 continue; 1614 case ZCAN: 1615 case ZABORT: 1616 case ZFIN: 1617 case ZSKIP: 1618 case ZRPOS: 1619 return ERROR; 1620 default: 1621 if (++errors > 20) 1622 return ERROR; 1623 continue; 1624 case ZCOMPL: 1625 Exitcode = Rxpos; 1626 saybibi(); 1627 return OK; 1628 case ZRQINIT: 1629 #ifdef vax11c /* YAMP :== Yet Another Missing Primitive */ 1630 return ERROR; 1631 #else 1632 vfile("******** RZ *******"); 1633 system("rz"); 1634 vfile("******** SZ *******"); 1635 goto listen; 1636 #endif 1637 } 1638 } 1639 } 1640 1641 /* 1642 * If called as sb use YMODEM protocol 1643 */ 1644 void chkinvok(char *s) 1645 { 1646 #ifdef vax11c 1647 Progname = "sz"; 1648 #else 1649 register char *p; 1650 1651 p = s; 1652 while (*p == '-') 1653 s = ++p; 1654 while (*p) 1655 if (*p++ == '/') 1656 s = p; 1657 if (*s == 'v') { 1658 Verbose=1; ++s; 1659 } 1660 Progname = s; 1661 if (s[0]=='s' && s[1]=='b') { 1662 Nozmodem = TRUE; blklen=1024; 1663 } 1664 if (s[0]=='s' && s[1]=='x') { 1665 Modem2 = TRUE; 1666 } 1667 #endif 1668 } 1669 1670 void countem(int argc, char **argv) 1671 { 1672 register int c; 1673 struct stat f; 1674 1675 for (Totalleft = 0, Filesleft = 0; --argc >=0; ++argv) { 1676 f.st_size = -1; 1677 if (Verbose>2) { 1678 fprintf(stderr, "\nCountem: %03d %s ", argc, *argv); 1679 fflush(stderr); 1680 } 1681 if (access(*argv, 04) >= 0 && stat(*argv, &f) >= 0) { 1682 c = f.st_mode & S_IFMT; 1683 if (c != S_IFDIR && c != S_IFBLK) { 1684 ++Filesleft; Totalleft += f.st_size; 1685 } 1686 } 1687 if (Verbose>2) 1688 fprintf(stderr, " %lld", f.st_size); 1689 } 1690 if (Verbose>2) 1691 fprintf(stderr, "\ncountem: Total %d %ld\n", 1692 Filesleft, Totalleft); 1693 } 1694 1695 void chartest(int m) 1696 { 1697 register int n; 1698 1699 mode(m); 1700 printf("\r\n\nCharacter Transparency Test Mode %d\r\n", m); 1701 printf("If Pro-YAM/ZCOMM is not displaying ^M hit ALT-V NOW.\r\n"); 1702 printf("Hit Enter.\021"); fflush(stdout); 1703 readline(500); 1704 1705 for (n = 0; n < 256; ++n) { 1706 if (!(n%8)) 1707 printf("\r\n"); 1708 printf("%02x ", n); fflush(stdout); 1709 sendline(n); flushmo(); 1710 printf(" "); fflush(stdout); 1711 if (n == 127) { 1712 printf("Hit Enter.\021"); fflush(stdout); 1713 readline(500); 1714 printf("\r\n"); fflush(stdout); 1715 } 1716 } 1717 printf("\021\r\nEnter Characters, echo is in hex.\r\n"); 1718 printf("Hit SPACE or pause 40 seconds for exit.\r\n"); 1719 1720 while (n != TIMEOUT && n != ' ') { 1721 n = readline(400); 1722 printf("%02x\r\n", n); 1723 fflush(stdout); 1724 } 1725 printf("\r\nMode %d character transparency test ends.\r\n", m); 1726 fflush(stdout); 1727 } 1728 1729 /* End of sz.c */ 1730