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) && attempts < RETRYMAX); 730 if (attempts == RETRYMAX) { 731 zperr("No ACK on EOT"); 732 return ERROR; 733 } 734 else 735 return OK; 736 } 737 /** 738 * @param cseclen :data length of this sector to send 739 */ 740 int wcputsec(char *buf, int sectnum, int cseclen) 741 { 742 register int checksum, wcj; 743 register char *cp; 744 unsigned oldcrc; 745 int firstch; 746 int attempts; 747 748 firstch=0; /* part of logic to detect CAN CAN */ 749 750 if (Verbose>2) 751 fprintf(stderr, "Sector %3d %2dk\n", Totsecs, Totsecs/8 ); 752 else if (Verbose>1) 753 fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs/8 ); 754 for (attempts=0; attempts <= RETRYMAX; attempts++) { 755 Lastrx= firstch; 756 sendline(cseclen==1024?STX:SOH); 757 sendline(sectnum); 758 sendline(-sectnum -1); 759 oldcrc=checksum=0; 760 for (wcj=cseclen,cp=buf; --wcj>=0; ) { 761 sendline(*cp); 762 oldcrc=updcrc((0377& *cp), oldcrc); 763 checksum += *cp++; 764 } 765 if (Crcflg) { 766 oldcrc=updcrc(0,updcrc(0,oldcrc)); 767 sendline((int)oldcrc>>8); 768 sendline((int)oldcrc); 769 } 770 else 771 sendline(checksum); 772 773 if (Optiong) { 774 firstsec = FALSE; return OK; 775 } 776 firstch = readline(Rxtimeout); 777 gotnak: 778 switch (firstch) { 779 case CAN: 780 if(Lastrx == CAN) { 781 cancan: 782 zperr("Cancelled"); return ERROR; 783 } 784 break; 785 case TIMEOUT: 786 zperr("Timeout on sector ACK"); continue; 787 case WANTCRC: 788 if (firstsec) 789 Crcflg = TRUE; 790 case NAK: 791 zperr("NAK on sector"); continue; 792 case ACK: 793 firstsec=FALSE; 794 Totsecs += (cseclen>>7); 795 return OK; 796 case ERROR: 797 zperr("Got burst for sector ACK"); break; 798 default: 799 zperr("Got %02x for sector ACK", firstch); break; 800 } 801 for (;;) { 802 Lastrx = firstch; 803 if ((firstch = readline(Rxtimeout)) == TIMEOUT) 804 break; 805 if (firstch == NAK || firstch == WANTCRC) 806 goto gotnak; 807 if (firstch == CAN && Lastrx == CAN) 808 goto cancan; 809 } 810 } 811 zperr("Retry Count Exceeded"); 812 return ERROR; 813 } 814 815 /* fill buf with count chars padding with ^Z for CPM */ 816 int filbuf(char *buf, int count) 817 { 818 register int c, m; 819 820 if ( !Ascii) { 821 m = read(fileno(in), buf, count); 822 if (m <= 0) 823 return 0; 824 while (m < count) 825 buf[m++] = 032; 826 return count; 827 } 828 m=count; 829 if (Lfseen) { 830 *buf++ = 012; --m; Lfseen = 0; 831 } 832 while ((c=getc(in))!=EOF) { 833 if (c == 012) { 834 *buf++ = 015; 835 if (--m == 0) { 836 Lfseen = TRUE; break; 837 } 838 } 839 *buf++ =c; 840 if (--m == 0) 841 break; 842 } 843 if (m==count) 844 return 0; 845 else 846 while (--m>=0) 847 *buf++ = CPMEOF; 848 return count; 849 } 850 851 /* Fill buffer with blklen chars */ 852 int zfilbuf() 853 { 854 int n; 855 856 #ifdef TXBSIZE 857 /* We assume request is within buffer, or just beyond */ 858 txbuf = Txb + (bytcnt & TXBMASK); 859 if (vpos <= bytcnt) { 860 n = fread(txbuf, 1, blklen, in); 861 vpos += n; 862 if (n < blklen) 863 Eofseen = 1; 864 return n; 865 } 866 if (vpos >= (bytcnt+blklen)) 867 return blklen; 868 /* May be a short block if crash recovery etc. */ 869 Eofseen = BEofseen; 870 return (vpos - bytcnt); 871 #else 872 n = fread(txbuf, 1, blklen, in); 873 if (n < blklen) 874 Eofseen = 1; 875 return n; 876 #endif 877 } 878 879 #ifdef TXBSIZE 880 int fooseek(FILE *fptr, long pos, int whence) 881 { 882 int m, n; 883 884 vfile("fooseek: pos =%lu vpos=%lu Canseek=%d", pos, vpos, Canseek); 885 /* Seek offset < current buffer */ 886 if (pos < (vpos -TXBSIZE +1024)) { 887 BEofseen = 0; 888 if (Canseek > 0) { 889 vpos = pos & ~TXBMASK; 890 if (vpos >= pos) 891 vpos -= TXBSIZE; 892 if (fseek(fptr, vpos, 0)) 893 return 1; 894 } 895 else if (Canseek == 0) 896 if (fseek(fptr, vpos = 0L, 0)) 897 return 1; 898 else 899 return 1; 900 while (vpos <= pos) { 901 n = fread(Txb, 1, TXBSIZE, fptr); 902 vpos += n; 903 vfile("n=%d vpos=%ld", n, vpos); 904 if (n < TXBSIZE) { 905 BEofseen = 1; 906 break; 907 } 908 } 909 vfile("vpos=%ld", vpos); 910 return 0; 911 } 912 /* Seek offset > current buffer (crash recovery, etc.) */ 913 if (pos > vpos) { 914 if (Canseek) 915 if (fseek(fptr, vpos = (pos & ~TXBMASK), 0)) 916 return 1; 917 while (vpos <= pos) { 918 txbuf = Txb + (vpos & TXBMASK); 919 m = TXBSIZE - (vpos & TXBMASK); 920 n = fread(txbuf, 1, m, fptr); 921 vpos += n; 922 vfile("bo=%d n=%d vpos=%ld", txbuf-Txb, n, vpos); 923 if (m < n) { 924 BEofseen = 1; 925 break; 926 } 927 } 928 return 0; 929 } 930 /* Seek offset is within current buffer */ 931 vfile("vpos=%ld", vpos); 932 return 0; 933 } 934 #define fseek fooseek 935 #endif 936 937 void vfile(const char *string, ...) 938 { 939 if (Verbose > 2) { 940 va_list args; 941 va_start(args, string); 942 vfprintf(stderr, string, args); 943 va_end(args); 944 fprintf(stderr, "\n"); 945 } 946 } 947 948 949 void alrm(int sig) 950 { 951 longjmp(tohere, -1); 952 } 953 954 955 #ifndef vax11c 956 /* 957 * readline(timeout) reads character(s) from file descriptor 0 958 * timeout is in tenths of seconds 959 */ 960 int readline(int timeout) 961 { 962 register int c; 963 static char byt[1]; 964 965 fflush(stdout); 966 if (setjmp(tohere)) { 967 zperr("TIMEOUT"); 968 return TIMEOUT; 969 } 970 c = timeout/10; 971 if (c<2) 972 c=2; 973 if (Verbose>5) { 974 fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, c); 975 } 976 signal(SIGALRM, alrm); alarm(c); 977 c=read(iofd, byt, 1); 978 alarm(0); 979 if (Verbose>5) 980 fprintf(stderr, "ret %x\n", byt[0]); 981 if (c<1) 982 return TIMEOUT; 983 return (byt[0]&0377); 984 } 985 986 void flushmo() 987 { 988 fflush(stdout); 989 } 990 991 992 void purgeline() 993 { 994 #ifdef USG 995 ioctl(iofd, TCFLSH, 0); 996 #else 997 lseek(iofd, 0L, 2); 998 #endif 999 } 1000 #endif 1001 1002 /* send cancel string to get the other end to shut up */ 1003 void canit() 1004 { 1005 static char canistr[] = { 1006 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 1007 }; 1008 1009 #ifdef vax11c 1010 raw_wbuf(strlen(canistr), canistr); 1011 purgeline(); 1012 #else 1013 printf("%s", canistr); 1014 fflush(stdout); 1015 #endif 1016 } 1017 1018 1019 /* 1020 * Log an error 1021 */ 1022 /*VARARGS1*/ 1023 void zperr(char *s, char *p, char *u) 1024 { 1025 if (Verbose <= 0) 1026 return; 1027 fprintf(stderr, "\nRetry %d: ", errors); 1028 fprintf(stderr, s, p, u); 1029 fprintf(stderr, "\n"); 1030 } 1031 1032 /* 1033 * substr(string, token) searches for token in string s 1034 * returns pointer to token within string if found, NULL otherwise 1035 */ 1036 char * 1037 substr(char *s, char *t) 1038 { 1039 register char *ss,*tt; 1040 /* search for first char of token */ 1041 for (ss=s; *s; s++) 1042 if (*s == *t) 1043 /* compare token with substring */ 1044 for (ss=s,tt=t; ;) { 1045 if (*tt == 0) 1046 return s; 1047 if (*ss++ != *tt++) 1048 break; 1049 } 1050 return (char *)NULL; 1051 } 1052 1053 char *babble[] = { 1054 #ifdef vax11c 1055 " Send file(s) with ZMODEM Protocol", 1056 "Usage: sz [-2+abdefkLlNnquvwYy] [-] file ...", 1057 " sz [-2Ceqv] -c COMMAND", 1058 " \\ Force next option letter to upper case", 1059 #else 1060 "Send file(s) with ZMODEM/YMODEM/XMODEM Protocol", 1061 " (Y) = Option applies to YMODEM only", 1062 " (Z) = Option applies to ZMODEM only", 1063 "Usage: sz [-2+abdefkLlNnquvwYy] [-] file ...", 1064 " sz [-2Ceqv] -c COMMAND", 1065 " sb [-2adfkquv] [-] file ...", 1066 " sx [-2akquv] [-] file", 1067 #endif 1068 #ifdef CSTOPB 1069 " 2 Use 2 stop bits", 1070 #endif 1071 " + Append to existing destination file (Z)", 1072 " a (ASCII) change NL to CR/LF", 1073 " b Binary file transfer override", 1074 " c send COMMAND (Z)", 1075 #ifndef vax11c 1076 " d Change '.' to '/' in pathnames (Y/Z)", 1077 #endif 1078 " e Escape all control characters (Z)", 1079 " f send Full pathname (Y/Z)", 1080 " i send COMMAND, ack Immediately (Z)", 1081 " k Send 1024 byte packets (Y)", 1082 " L N Limit subpacket length to N bytes (Z)", 1083 " l N Limit frame length to N bytes (l>=L) (Z)", 1084 " n send file if source newer (Z)", 1085 " N send file if source newer or longer (Z)", 1086 " o Use 16 bit CRC instead of 32 bit CRC (Z)", 1087 " p Protect existing destination file (Z)", 1088 " r Resume/Recover interrupted file transfer (Z)", 1089 " q Quiet (no progress reports)", 1090 #ifndef vax11c 1091 " u Unlink file after transmission", 1092 #endif 1093 " v Verbose - provide debugging information", 1094 " w N Window is N bytes (Z)", 1095 " Y Yes, overwrite existing file, skip if not present at rx (Z)", 1096 " y Yes, overwrite existing file (Z)", 1097 "- as pathname sends standard input as sPID.sz or environment ONAME", 1098 "" 1099 }; 1100 1101 int usage() 1102 { 1103 char **pp; 1104 1105 for (pp=babble; **pp; ++pp) 1106 fprintf(stderr, "%s\n", *pp); 1107 fprintf(stderr, "%s for %s by Chuck Forsberg, Omen Technology INC\n", 1108 VERSION, OS); 1109 fprintf(stderr, "\t\t\042The High Reliability Software\042\n"); 1110 cucheck(); 1111 exit(SS_NORMAL); 1112 } 1113 1114 /* 1115 * Get the receiver's init parameters 1116 */ 1117 int getzrxinit() 1118 { 1119 register int n; 1120 struct stat f; 1121 1122 for (n=10; --n>=0; ) { 1123 1124 switch (zgethdr(Rxhdr, 1)) { 1125 case ZCHALLENGE: /* Echo receiver's challenge numbr */ 1126 stohdr(Rxpos); 1127 zshhdr(ZACK, Txhdr); 1128 continue; 1129 case ZCOMMAND: /* They didn't see out ZRQINIT */ 1130 stohdr(0L); 1131 zshhdr(ZRQINIT, Txhdr); 1132 continue; 1133 case ZRINIT: 1134 Rxflags = 0377 & Rxhdr[ZF0]; 1135 Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32)); 1136 Zctlesc |= Rxflags & TESCCTL; 1137 Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8); 1138 if ( !(Rxflags & CANFDX)) 1139 Txwindow = 0; 1140 vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen); 1141 if ( !Fromcu) 1142 signal(SIGINT, SIG_IGN); 1143 #ifdef MODE2OK 1144 mode(2); /* Set cbreak, XON/XOFF, etc. */ 1145 #endif 1146 #ifndef READCHECK 1147 #ifndef USG 1148 /* Use 1024 byte frames if no sample/interrupt */ 1149 if (Rxbuflen < 32 || Rxbuflen > 1024) { 1150 Rxbuflen = 1024; 1151 vfile("Rxbuflen=%d", Rxbuflen); 1152 } 1153 #endif 1154 #endif 1155 /* Override to force shorter frame length */ 1156 if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32)) 1157 Rxbuflen = Tframlen; 1158 if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024)) 1159 Rxbuflen = Tframlen; 1160 vfile("Rxbuflen=%d", Rxbuflen); 1161 1162 #ifndef vax11c 1163 /* If using a pipe for testing set lower buf len */ 1164 fstat(iofd, &f); 1165 if ((f.st_mode & S_IFMT) != S_IFCHR) { 1166 Rxbuflen = 1024; 1167 } 1168 #endif 1169 #ifdef BADSEEK 1170 Canseek = 0; 1171 Txwindow = TXBSIZE - 1024; 1172 Txwspac = TXBSIZE/4; 1173 #endif 1174 /* 1175 * If input is not a regular file, force ACK's to 1176 * prevent running beyond the buffer limits 1177 */ 1178 if ( !Command) { 1179 fstat(fileno(in), &f); 1180 if ((f.st_mode & S_IFMT) != S_IFREG) { 1181 Canseek = -1; 1182 #ifdef TXBSIZE 1183 Txwindow = TXBSIZE - 1024; 1184 Txwspac = TXBSIZE/4; 1185 #else 1186 return ERROR; 1187 #endif 1188 } 1189 } 1190 /* Set initial subpacket length */ 1191 if (blklen < 1024) { /* Command line override? */ 1192 if (Baudrate > 300) 1193 blklen = 256; 1194 if (Baudrate > 1200) 1195 blklen = 512; 1196 if (Baudrate > 2400) 1197 blklen = 1024; 1198 } 1199 if (Rxbuflen && blklen>Rxbuflen) 1200 blklen = Rxbuflen; 1201 if (blkopt && blklen > blkopt) 1202 blklen = blkopt; 1203 vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen); 1204 vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac); 1205 1206 return (sendzsinit()); 1207 case ZCAN: 1208 case TIMEOUT: 1209 return ERROR; 1210 case ZRQINIT: 1211 if (Rxhdr[ZF0] == ZCOMMAND) 1212 continue; 1213 default: 1214 zshhdr(ZNAK, Txhdr); 1215 continue; 1216 } 1217 } 1218 return ERROR; 1219 } 1220 1221 /* Send send-init information */ 1222 int sendzsinit() 1223 { 1224 register int c; 1225 1226 if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL))) 1227 return OK; 1228 errors = 0; 1229 for (;;) { 1230 stohdr(0L); 1231 if (Zctlesc) { 1232 Txhdr[ZF0] |= TESCCTL; zshhdr(ZSINIT, Txhdr); 1233 } 1234 else 1235 zsbhdr(ZSINIT, Txhdr); 1236 zsdata(Myattn, 1+strlen(Myattn), ZCRCW); 1237 c = zgethdr(Rxhdr, 1); 1238 switch (c) { 1239 case ZCAN: 1240 return ERROR; 1241 case ZACK: 1242 return OK; 1243 default: 1244 if (++errors > 19) 1245 return ERROR; 1246 continue; 1247 } 1248 } 1249 } 1250 1251 /* Send file name and related info */ 1252 int zsendfile(char *buf, int blen) 1253 { 1254 register int c; 1255 register UNSL long crc; 1256 1257 for (;;) { 1258 Txhdr[ZF0] = Lzconv; /* file conversion request */ 1259 Txhdr[ZF1] = Lzmanag; /* file management request */ 1260 if (Lskipnocor) 1261 Txhdr[ZF1] |= ZMSKNOLOC; 1262 Txhdr[ZF2] = Lztrans; /* file transport request */ 1263 Txhdr[ZF3] = 0; 1264 zsbhdr(ZFILE, Txhdr); 1265 zsdata(buf, blen, ZCRCW); 1266 again: 1267 c = zgethdr(Rxhdr, 1); 1268 switch (c) { 1269 case ZRINIT: 1270 while ((c = readline(50)) > 0) 1271 if (c == ZPAD) { 1272 goto again; 1273 } 1274 /* **** FALL THRU TO **** */ 1275 default: 1276 continue; 1277 case ZCAN: 1278 case TIMEOUT: 1279 case ZABORT: 1280 case ZFIN: 1281 return ERROR; 1282 case ZCRC: 1283 crc = 0xFFFFFFFFL; 1284 if (Canseek >= 0) { 1285 while (((c = getc(in)) != EOF) && --Rxpos) 1286 crc = UPDC32(c, crc); 1287 crc = ~crc; 1288 clearerr(in); /* Clear EOF */ 1289 fseek(in, 0L, 0); 1290 } 1291 stohdr(crc); 1292 zsbhdr(ZCRC, Txhdr); 1293 goto again; 1294 case ZSKIP: 1295 fclose(in); return c; 1296 case ZRPOS: 1297 /* 1298 * Suppress zcrcw request otherwise triggered by 1299 * lastyunc==bytcnt 1300 */ 1301 if (Rxpos && fseek(in, Rxpos, 0)) 1302 return ERROR; 1303 Lastsync = (bytcnt = Txpos = Rxpos) -1; 1304 return zsendfdata(); 1305 } 1306 } 1307 } 1308 1309 /* Send the data in the file */ 1310 int zsendfdata() 1311 { 1312 register int c, e, n; 1313 register int newcnt; 1314 register long tcount = 0; 1315 int junkcount; /* Counts garbage chars received by TX */ 1316 static int tleft = 6; /* Counter for test mode */ 1317 1318 Lrxpos = 0; 1319 junkcount = 0; 1320 Beenhereb4 = FALSE; 1321 somemore: 1322 if (setjmp(intrjmp)) { 1323 waitack: 1324 junkcount = 0; 1325 c = getinsync(0); 1326 gotack: 1327 switch (c) { 1328 default: 1329 case ZCAN: 1330 fclose(in); 1331 return ERROR; 1332 case ZSKIP: 1333 fclose(in); 1334 return c; 1335 case ZACK: 1336 case ZRPOS: 1337 break; 1338 case ZRINIT: 1339 return OK; 1340 } 1341 #ifdef READCHECK 1342 /* 1343 * If the reverse channel can be tested for data, 1344 * this logic may be used to detect error packets 1345 * sent by the receiver, in place of setjmp/longjmp 1346 * rdchk(fdes) returns non 0 if a character is available 1347 */ 1348 while (rdchk(iofd)) { 1349 #ifdef SV 1350 switch (checked) 1351 #else 1352 switch (readline(1)) 1353 #endif 1354 { 1355 case CAN: 1356 case ZPAD: 1357 c = getinsync(1); 1358 goto gotack; 1359 case XOFF: /* Wait a while for an XON */ 1360 case XOFF|0200: 1361 readline(100); 1362 } 1363 } 1364 #endif 1365 } 1366 1367 if ( !Fromcu) 1368 signal(SIGINT, onintr); 1369 newcnt = Rxbuflen; 1370 Txwcnt = 0; 1371 stohdr(Txpos); 1372 zsbhdr(ZDATA, Txhdr); 1373 1374 /* 1375 * Special testing mode. This should force receiver to Attn,ZRPOS 1376 * many times. Each time the signal should be caught, causing the 1377 * file to be started over from the beginning. 1378 */ 1379 if (Test) { 1380 if ( --tleft) 1381 while (tcount < 20000) { 1382 printf("%s", qbf); fflush(stdout); 1383 tcount += strlen(qbf); 1384 #ifdef READCHECK 1385 while (rdchk(iofd)) { 1386 #ifdef SV 1387 switch (checked) 1388 #else 1389 switch (readline(1)) 1390 #endif 1391 { 1392 case CAN: 1393 case ZPAD: 1394 #ifdef TCFLSH 1395 ioctl(iofd, TCFLSH, 1); 1396 #endif 1397 goto waitack; 1398 case XOFF: /* Wait for XON */ 1399 case XOFF|0200: 1400 readline(100); 1401 } 1402 } 1403 #endif 1404 } 1405 signal(SIGINT, SIG_IGN); canit(); 1406 sleep(3); purgeline(); mode(0); 1407 printf("\nsz: Tcount = %ld\n", tcount); 1408 if (tleft) { 1409 printf("ERROR: Interrupts Not Caught\n"); 1410 exit(1); 1411 } 1412 exit(SS_NORMAL); 1413 } 1414 1415 do { 1416 n = zfilbuf(); 1417 if (Eofseen) 1418 e = ZCRCE; 1419 else if (junkcount > 3) 1420 e = ZCRCW; 1421 else if (bytcnt == Lastsync) 1422 e = ZCRCW; 1423 else if (Rxbuflen && (newcnt -= n) <= 0) 1424 e = ZCRCW; 1425 else if (Txwindow && (Txwcnt += n) >= Txwspac) { 1426 Txwcnt = 0; e = ZCRCQ; 1427 } 1428 else 1429 e = ZCRCG; 1430 if (Verbose>1) 1431 fprintf(stderr, "\r%7ld ZMODEM%s ", 1432 Txpos, Crc32t?" CRC-32":""); 1433 zsdata(txbuf, n, e); 1434 bytcnt = Txpos += n; 1435 if (e == ZCRCW) 1436 goto waitack; 1437 #ifdef READCHECK 1438 /* 1439 * If the reverse channel can be tested for data, 1440 * this logic may be used to detect error packets 1441 * sent by the receiver, in place of setjmp/longjmp 1442 * rdchk(fdes) returns non 0 if a character is available 1443 */ 1444 fflush(stdout); 1445 while (rdchk(iofd)) { 1446 #ifdef SV 1447 switch (checked) 1448 #else 1449 switch (readline(1)) 1450 #endif 1451 { 1452 case CAN: 1453 case ZPAD: 1454 c = getinsync(1); 1455 if (c == ZACK) 1456 break; 1457 #ifdef TCFLSH 1458 ioctl(iofd, TCFLSH, 1); 1459 #endif 1460 /* zcrce - dinna wanna starta ping-pong game */ 1461 zsdata(txbuf, 0, ZCRCE); 1462 goto gotack; 1463 case XOFF: /* Wait a while for an XON */ 1464 case XOFF|0200: 1465 readline(100); 1466 default: 1467 ++junkcount; 1468 } 1469 } 1470 #endif /* READCHECK */ 1471 if (Txwindow) { 1472 while ((tcount = Txpos - Lrxpos) >= Txwindow) { 1473 vfile("%ld window >= %u", tcount, Txwindow); 1474 if (e != ZCRCQ) 1475 zsdata(txbuf, 0, e = ZCRCQ); 1476 c = getinsync(1); 1477 if (c != ZACK) { 1478 #ifdef TCFLSH 1479 ioctl(iofd, TCFLSH, 1); 1480 #endif 1481 zsdata(txbuf, 0, ZCRCE); 1482 goto gotack; 1483 } 1484 } 1485 vfile("window = %ld", tcount); 1486 } 1487 } while (!Eofseen); 1488 if ( !Fromcu) 1489 signal(SIGINT, SIG_IGN); 1490 1491 for (;;) { 1492 stohdr(Txpos); 1493 zsbhdr(ZEOF, Txhdr); 1494 switch (getinsync(0)) { 1495 case ZACK: 1496 continue; 1497 case ZRPOS: 1498 goto somemore; 1499 case ZRINIT: 1500 return OK; 1501 case ZSKIP: 1502 fclose(in); 1503 return c; 1504 default: 1505 fclose(in); 1506 return ERROR; 1507 } 1508 } 1509 } 1510 1511 /* 1512 * Respond to receiver's complaint, get back in sync with receiver 1513 */ 1514 int getinsync(int flag) 1515 { 1516 register int c; 1517 1518 for (;;) { 1519 if (Test) { 1520 printf("\r\n\n\n***** Signal Caught *****\r\n"); 1521 Rxpos = 0; c = ZRPOS; 1522 } else 1523 c = zgethdr(Rxhdr, 0); 1524 switch (c) { 1525 case ZCAN: 1526 case ZABORT: 1527 case ZFIN: 1528 case TIMEOUT: 1529 return ERROR; 1530 case ZRPOS: 1531 /* ************************************* */ 1532 /* If sending to a buffered modem, you */ 1533 /* might send a break at this point to */ 1534 /* dump the modem's buffer. */ 1535 clearerr(in); /* In case file EOF seen */ 1536 if (fseek(in, Rxpos, 0)) 1537 return ERROR; 1538 Eofseen = 0; 1539 bytcnt = Lrxpos = Txpos = Rxpos; 1540 if (Lastsync == Rxpos) { 1541 if (++Beenhereb4 > 4) 1542 if (blklen > 32) 1543 blklen /= 2; 1544 } 1545 Lastsync = Rxpos; 1546 return c; 1547 case ZACK: 1548 Lrxpos = Rxpos; 1549 if (flag || Txpos == Rxpos) 1550 return ZACK; 1551 continue; 1552 case ZRINIT: 1553 case ZSKIP: 1554 fclose(in); 1555 return c; 1556 case ERROR: 1557 default: 1558 zsbhdr(ZNAK, Txhdr); 1559 continue; 1560 } 1561 } 1562 } 1563 1564 1565 /* Say "bibi" to the receiver, try to do it cleanly */ 1566 void saybibi() 1567 { 1568 for (;;) { 1569 stohdr(0L); /* CAF Was zsbhdr - minor change */ 1570 zshhdr(ZFIN, Txhdr); /* to make debugging easier */ 1571 switch (zgethdr(Rxhdr, 0)) { 1572 case ZFIN: 1573 sendline('O'); sendline('O'); flushmo(); 1574 case ZCAN: 1575 case TIMEOUT: 1576 return; 1577 } 1578 } 1579 } 1580 1581 /* Local screen character display function */ 1582 void bttyout(int c) 1583 { 1584 if (Verbose) 1585 putc(c, stderr); 1586 } 1587 1588 /* Send command and related info */ 1589 int zsendcmd(char *buf, int blen) 1590 { 1591 register int c; 1592 long cmdnum; 1593 1594 cmdnum = getpid(); 1595 errors = 0; 1596 for (;;) { 1597 stohdr(cmdnum); 1598 Txhdr[ZF0] = Cmdack1; 1599 zsbhdr(ZCOMMAND, Txhdr); 1600 zsdata(buf, blen, ZCRCW); 1601 listen: 1602 Rxtimeout = 100; /* Ten second wait for resp. */ 1603 c = zgethdr(Rxhdr, 1); 1604 1605 switch (c) { 1606 case ZRINIT: 1607 goto listen; /* CAF 8-21-87 */ 1608 case ERROR: 1609 case TIMEOUT: 1610 if (++errors > Cmdtries) 1611 return ERROR; 1612 continue; 1613 case ZCAN: 1614 case ZABORT: 1615 case ZFIN: 1616 case ZSKIP: 1617 case ZRPOS: 1618 return ERROR; 1619 default: 1620 if (++errors > 20) 1621 return ERROR; 1622 continue; 1623 case ZCOMPL: 1624 Exitcode = Rxpos; 1625 saybibi(); 1626 return OK; 1627 case ZRQINIT: 1628 #ifdef vax11c /* YAMP :== Yet Another Missing Primitive */ 1629 return ERROR; 1630 #else 1631 vfile("******** RZ *******"); 1632 system("rz"); 1633 vfile("******** SZ *******"); 1634 goto listen; 1635 #endif 1636 } 1637 } 1638 } 1639 1640 /* 1641 * If called as sb use YMODEM protocol 1642 */ 1643 void chkinvok(char *s) 1644 { 1645 #ifdef vax11c 1646 Progname = "sz"; 1647 #else 1648 register char *p; 1649 1650 p = s; 1651 while (*p == '-') 1652 s = ++p; 1653 while (*p) 1654 if (*p++ == '/') 1655 s = p; 1656 if (*s == 'v') { 1657 Verbose=1; ++s; 1658 } 1659 Progname = s; 1660 if (s[0]=='s' && s[1]=='b') { 1661 Nozmodem = TRUE; blklen=1024; 1662 } 1663 if (s[0]=='s' && s[1]=='x') { 1664 Modem2 = TRUE; 1665 } 1666 #endif 1667 } 1668 1669 void countem(int argc, char **argv) 1670 { 1671 register int c; 1672 struct stat f; 1673 1674 for (Totalleft = 0, Filesleft = 0; --argc >=0; ++argv) { 1675 f.st_size = -1; 1676 if (Verbose>2) { 1677 fprintf(stderr, "\nCountem: %03d %s ", argc, *argv); 1678 fflush(stderr); 1679 } 1680 if (access(*argv, 04) >= 0 && stat(*argv, &f) >= 0) { 1681 c = f.st_mode & S_IFMT; 1682 if (c != S_IFDIR && c != S_IFBLK) { 1683 ++Filesleft; Totalleft += f.st_size; 1684 } 1685 } 1686 if (Verbose>2) 1687 fprintf(stderr, " %lld", f.st_size); 1688 } 1689 if (Verbose>2) 1690 fprintf(stderr, "\ncountem: Total %d %ld\n", 1691 Filesleft, Totalleft); 1692 } 1693 1694 void chartest(int m) 1695 { 1696 register int n; 1697 1698 mode(m); 1699 printf("\r\n\nCharacter Transparency Test Mode %d\r\n", m); 1700 printf("If Pro-YAM/ZCOMM is not displaying ^M hit ALT-V NOW.\r\n"); 1701 printf("Hit Enter.\021"); fflush(stdout); 1702 readline(500); 1703 1704 for (n = 0; n < 256; ++n) { 1705 if (!(n%8)) 1706 printf("\r\n"); 1707 printf("%02x ", n); fflush(stdout); 1708 sendline(n); flushmo(); 1709 printf(" "); fflush(stdout); 1710 if (n == 127) { 1711 printf("Hit Enter.\021"); fflush(stdout); 1712 readline(500); 1713 printf("\r\n"); fflush(stdout); 1714 } 1715 } 1716 printf("\021\r\nEnter Characters, echo is in hex.\r\n"); 1717 printf("Hit SPACE or pause 40 seconds for exit.\r\n"); 1718 1719 while (n != TIMEOUT && n != ' ') { 1720 n = readline(400); 1721 printf("%02x\r\n", n); 1722 fflush(stdout); 1723 } 1724 printf("\r\nMode %d character transparency test ends.\r\n", m); 1725 fflush(stdout); 1726 } 1727 1728 /* End of sz.c */ 1729